Jump to content

MAFman

Members
  • Posts

    220
  • Joined

  • Last visited

Everything posted by MAFman

  1. For using a PIDLOOP() to control the steering and throttle, what settings for kP, kI, and kD are recommended?
  2. I definitely could make a ton of use out of this, and perhaps I can edit this to actually work with my algorithm.
  3. Found it! Also found the log line where the error happened... Apparently, it tried to get a key from System.Collections.Generic.Dictionary`2 and it didn't find it. What is the difference between Dictionary and Dictionary`2? Also, shouldn't the code try to access just System.Collections.Generic.Dictionary? Why is it saying AddObjectParts(IEnumerable`1 parts)[0x00000] in <filename unknown>:0 ? Especially the <filename unknown>? I'm guessing it should be "in <autonav>:0" or something. [LOG 13:51:15.203] kOS: FunctionCopy: Volume: 1 Direction: to Filename: autonav.ks [LOG 13:51:15.728] kOS: At autonavinit.ks on 1, line 17 RUN autoNav(direct). ^ Called from startup.ks on 1, line 20 RUN autoNavInit(270). ^ Called from boot.ks on 1, line 139 RUN startup.ks. ^ Called from boot.ks on 1, line 153 RUN startup.ks. ^ Called from sys:boot, line 1 (Can't show source line) ^ [LOG 13:51:15.730] System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Collections.Generic.Dictionary`2[System.String,System.Int32].get_Item (System.String key) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.ProgramBuilder.ReplaceLabels (System.Collections.Generic.List`1 program) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.ProgramBuilder.BuildProgram () [0x00000] in <filename unknown>:0 at kOS.Safe.Execution.ProgramContext.AddObjectParts (IEnumerable`1 parts) [0x00000] in <filename unknown>:0 at kOS.Function.FunctionLoad.Execute (kOS.SharedObjects shared) [0x00000] in <filename unknown>:0 at kOS.Function.FunctionManager.CallFunction (System.String functionName) [0x00000] in <filename unknown>:0 at kOS.Safe.Execution.CPU.CallBuiltinFunction (System.String functionName) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.OpcodeCall.StaticExecute (ICpu cpu, Boolean direct, System.Object destination, Boolean calledFromKOSDelegateCall) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.OpcodeCall.Execute (ICpu cpu) [0x00000] in <filename unknown>:0 at kOS.Safe.Execution.CPU.ExecuteInstruction (IProgramContext context, Boolean doProfiling) [0x00000] in <filename unknown>:0 [LOG 13:51:15.735] Code Fragment File Line:Col IP label opcode operand ==== ====:=== ==== ================================ 1/startup.ks 20:17 0740 @0736 push 270 1/startup.ks 20:17 0741 @0737 call 674 1/startup.ks 20:17 0742 @0738 pop 0:0 0743 push 0 0:0 0744 return 0 deep 1/autonavinit.ks 17:1 0745 @0739 push $program-autonav* 1/autonavinit.ks 17:1 0746 @0740 exists 1/autonavinit.ks 17:1 0747 @0741 br.false +4 1/autonavinit.ks 17:1 0748 @0742 br.false +11 1/autonavinit.ks 17:1 0749 @0743 push 0 1/autonavinit.ks 17:1 0750 @0744 return 0 deep 1/autonavinit.ks 17:1 0751 @0745 pop 1/autonavinit.ks 17:1 0752 @0746 push $program-autonav* 1/autonavinit.ks 17:1 0753 @0747 push _KOSArgMarker_ 1/autonavinit.ks 17:1 0754 @0748 push autonav 1/autonavinit.ks 17:1 0755 @0749 push null 1/autonavinit.ks 17:1 0756 @0750 call load() <<--INSTRUCTION POINTER-- 1/autonavinit.ks 17:1 0757 @0751 pop 1/autonavinit.ks 17:1 0758 @0752 store 1/autonavinit.ks 17:1 0759 @0753 call $program-autonav* 1/autonavinit.ks 17:1 0760 @0754 pop 1/autonavinit.ks 17:1 0761 @0755 push 0 1/autonavinit.ks 17:1 0762 @0756 return 0 deep 1/autonavinit.ks 1:11 0763 @0757 push direct 1/autonavinit.ks 1:11 0764 @0758 swap 1/autonavinit.ks 1:11 0765 @0759 storelocal 1/autonavinit.ks 1:11 0766 @0760 argbottom 1/autonavinit.ks 2:1 0767 @0761 push $brakes 1/autonavinit.ks 2:8 0768 @0762 push True 1/autonavinit.ks 2:8 0769 @0763 store 1/autonavinit.ks 3:1 0770 @0764 push _KOSArgMarker_ 1/autonavinit.ks 3:11 0771 @0765 push 1 1/autonavinit.ks 3:11 0772 @0766 call switch() FOUND IT! In the function ReplaceLabels(), there's a variable var labels = new Dictionary<string, int>(); It's complaining because the string parameter is missing. Looking further down the code, there's an if statement that is not being met, and it doesn't have an "else": private void ReplaceLabels(List<Opcode> program) { var labels = new Dictionary<string, int>(); // get the index of every label for (int index = 0; index < program.Count; index++) { if (program[index].Label != string.Empty) { if (labels.ContainsKey(program[index].Label)) { if (program[index].Label.EndsWith("-default")) continue; // This is one of those "should never happen" errors that if it happens // it means kOS devs screwed up - so dump the partially relabeled program // to the log just to help in diagnosing the bug report that may happen: // Utilities.SafeHouse.Logger.LogError("=====Relabeled Program so far is: ========="); Utilities.SafeHouse.Logger.LogError(Utilities.Debug.GetCodeFragment(program)); throw new Exceptions.KOSCompileException(LineCol.Unknown(), string.Format( "ProgramBuilder.ReplaceLabels: Cannot add label {0}, label already exists. Opcode: {1}", program[index].Label, program[index].ToString())); } labels.Add(program[index].Label, index); } } You should have an "else" condition to "if (program[index].Label != string.Empty) { //stuff}" as well as "if(labels.containsKey(program[index].Label)){//More stuff} Lesson: If you have an IF(), always follow it with ELSE().
  4. I'd be super excited for a new patch version! I think I'll wait until the official release. I can send you my save game and rover.craft if you want to try it. I'm also using RemoteTech and the RT Communotron 32, which is the only non-stock part on the rover.
  5. Made some tweaks, but I'm still getting the same dang error... Boot.ks: SET SHIP:CONTROL:PILOTMAINTHROTTLE TO 0. LIGHTS OFF. GEAR OFF. BRAKES OFF. SAS OFF. RCS OFF. FUNCTION NOTIFY { PARAMETER message, priority. IF priority = "NOMINAL" { SET col TO GREEN. } ELSE IF priority = "ALERT" { SET col TO RGB(1,0.31,0). // international orange } ELSE IF priority = "WARNING" { SET col TO RED. } HUDTEXT("kOS: " + message, 1.5, 2, 30, col, FALSE). } FUNCTION ON_DRIVE { PARAMETER filename, vol. SWITCH TO vol. LIST FILES in allFiles. FOR f IN allFiles { IF f:NAME = filename { SWITCH TO 1. RETURN TRUE. } } SWITCH TO 1. RETURN FALSE. } // First-pass at introducing artificial delay. ADDONS:RT:DELAY(SHIP) represents // the line-of-site latency to KSC, as per RemoteTech FUNCTION DELAY { SET dTime TO ADDONS:RT:DELAY(SHIP) * 3. // Total delay time SET accTime TO 0. // Accumulated time UNTIL accTime >= dTime { SET start TO TIME:SECONDS. WAIT UNTIL (TIME:SECONDS - start) > (dTime - accTime) OR NOT ADDONS:RT:HASCONNECTION(SHIP). SET accTime TO accTime + TIME:SECONDS - start. } } // Get a file from KSC FUNCTION DOWNLOAD { PARAMETER filename. DELAY(). IF ON_DRIVE(filename, 1) { DELETE filename. } IF ON_DRIVE(filename, 0) { COPY filename FROM 0. } } // Put a file on KSC FUNCTION UPLOAD { PARAMETER filename. DELAY(). IF ON_DRIVE(filename, 0) { SWITCH TO 0. DELETE filename. SWITCH TO 1. } IF ON_DRIVE(filename, 1) { COPY filename TO 0. } } // Run a library, downloading it from KSC if necessary FUNCTION REQUIRE { PARAMETER filename. IF NOT ON_DRIVE(filename, 1) { DOWNLOAD(filename). } RENAME filename TO "tmp.exec.ks". RUN tmp.exec.ks. RENAME "tmp.exec.ks" TO filename. } // THE ACTUAL BOOTUP PROCESS SET updateScript TO SHIP:NAME + ".update.ks". // If we have a connection, see if there are new instructions. If so, download // and run them. IF ADDONS:RT:HASCONNECTION(SHIP) { IF ON_DRIVE(updateScript, 0) { DOWNLOAD(updateScript). SWITCH TO 0. DELETE updateScript. SWITCH TO 1. IF ON_DRIVE("update.ks", 1) { DELETE update.ks. } RENAME updateScript TO "update.ks". RUN update.ks. DELETE update.ks. } } // If a startup.ks file exists on the disk, run that. SET bootScript TO SHIP:NAME + ".bootup.ks". IF ON_DRIVE(bootScript, 0) { DOWNLOAD(bootScript). RENAME bootScript TO "startup.ks". RUN startup.ks. IF ON_DRIVE("startup.ks", 1) { SWITCH TO 1. DELETE startup.ks. } } ELSE { WAIT UNTIL ADDONS:RT:HASCONNECTION(SHIP). WAIT 10. // Avoid thrashing the CPU (when no startup.ks, but we have a // persistent connection, it will continually reboot) REBOOT. } Relay.bootup.ks: DOWNLOAD(autoNavInit.ks). DOWNLOAD(autoNavIterate.ks). RUN autoNavInit(270). AutoNavInit.ks: PARAMETER goalHeading. BRAKES ON. NOTIFY("Starting navigation script...Done.", "NOMINAL"). WAIT 2.5. NOTIFY("Downloading navigation instructions...Done.", "NOMINAL"). WAIT 2.5. NOTIFY("Running iterative navigator...", "NOMINAL"). SWITCH TO 0. RUN autoNav(goalHeading). AutoNav.ks: // Until the goal has been reached, go through this process. PARAMETER direct. DRIVE_FORWARD(). DRIVE_BACK(). PARK(). // The loop... Functions are defined below FUNCTION DRIVE_FORWARD { UNTIL FALSE { POPULATE(direct). DECIDE_NEXT(options). NOTIFY("Selecting next waypoint.", "NOMINAL"). WAIT 0.5. DRIVE_TO(nextPoint). STOP(). WAIT 5. IF NOT ADDONS:RT:HASCONNECTION(SHIP) { BREAK. } } } FUNCTION DRIVE_BACK { UNTIL FALSE { POPULATE(360 - direct). DECIDE_NEXT(options). NOTIFY("Selecting next waypoint", "NOMINAL"). WAIT 0.5. DRIVE_TO(nextPoint). STOP(). WAIT 5. IF ADDONS:RT:HASCONNECTION(SHIP) { BREAK. } } } FUNCTION THERE_YET { PARAMETER point. IF point:DISTANCE < 10 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { PARAMETER hdg. SET offset_90 TO SIN(hdg) * ((360 * 100) / (BODY:RADIUS * 2 * CONSTANT:PI)). // duh SET offset_675 TO offset_90 * SIN(67.5). // 67.5 deg. SET offset_45 TO offset_90 * SIN(45). // 45 deg. SET offset_225 TO offset_90 * SIN(22.5). // 22.5 deg. SET op_A TO LATLNG(SHIP:GEOPOSITION:LAT + offset_225, SHIP:GEOPOSITION:LNG - offset_675). SET op_B TO LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG - offset_45). SET op_C TO LATLNG(SHIP:GEOPOSITION:LAT + offset_90, SHIP:GEOPOSITION:LNG). SET op_D TO LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG + offset_45). SET op_E TO LATLNG(SHIP:GEOPOSITION:LAT + offset_225, SHIP:GEOPOSITION:LNG + offset_675). SET options TO LIST ( op_A, op_B, op_C, op_D, op_E ). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER option. SET here TO SHIP:GEOPOSITION. SET there TO option. SET slope TO ABS(ARCTAN2(there:TERRAINHEIGHT - here:TERRAINHEIGHT, lookAhead)). IF slope < 10 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER options. SET startPos TO 0. UNTIL startPos > options:LENGTH - 1 { SET o TO options[startPos]. IF SLOPE_IS_SAFE(o) { SET nextPoint TO o. RETURN nextPoint. BREAK. } ELSE { SET startPos TO startPos + 1. } } } FUNCTION DRIVE_TO { PARAMETER point. BRAKES OFF. SET spd TO 1. // Really stinkin' slow, but safe. // Throttle control variables SET throttlePID TO PIDLOOP(0.15, 0.05, 0.1, -1.0, 1.0). SET throttlePID:SETPOINT TO spd. // Steering control variables SET steerPID TO PIDLOOP(0.15, 0.05, 0.1, -1.0, 1.0). SET steerPID:SETPOINT TO point:HEADING. CLEARSCREEN. SET thrott TO 0. SET steerVal TO 0. UNTIL THERE_YET(point) { SET thrott TO throttlePID:UPDATE(TIME:SECONDS, SHIP:GROUNDSPEED). SET steerVal TO steerPID:UPDATE(TIME:SECONDS, SHIP:HEADING). LOCK WHEELTHROTTLE TO thrott. LOCK WHEELSTEER TO steerVal. PRINT "Current Location: " + ROUND(SHIP:GEOPOSITION:LAT,3) + ", " + ROUND(SHIP:GEOPOSITION:LNG,3) at (0,3). PRINT "Next waypoint: " + ROUND(point:LAT,3) + ", " + ROUND(point:LNG, 3) AT (0,4). PRINT "Throttle: " + ROUND(thrott, 3) AT (0,9). PRINT "Steering: " + ROUND(steerVal,3) AT (0,10). WAIT 0.01. } STOP(). } FUNCTION STOP { IF GROUNDSPEED > 0.5 { LOCK WHEELTHROTTLE TO -0.5. } ELSE { UNLOCK WHEELTHROTTLE. IF NOT BRAKES { BRAKES ON. } } UNLOCK ALL. NOTIFY("Arrived!", "NOMINAL"). } FUNCTION PARK { STOP(). LIGHTS ON. FOR someAntenna IN SHIP:PARTSNAMED("RTLongAntenna2") { someAntenna:GETMODULE("ModuleRTAntenna"):DOEVENT("activate"). } } Can someone help me find my mistake(s)?
  6. Ok, here's the log file... I finally found it... (at least the part with the kOS error.) [LOG 19:10:59.261] kOS: FlightCtrlParam: Enabled: throttle False => False [LOG 19:10:59.261] kOS: FlightCtrlParam: Enabled: steering False => False [LOG 19:10:59.262] kOS: FlightCtrlParam: Enabled: wheelthrottle False => False [LOG 19:10:59.263] kOS: FlightCtrlParam: Enabled: wheelsteering False => False [LOG 19:10:59.263] kOS: FlightControl Unbinding [LOG 19:10:59.264] kOS: FlightControl Unbound [LOG 19:10:59.265] kOS: Pushing context staring with: File Line:Col IP label opcode operand [LOG 19:10:59.266] kOS: Saving and removing 9 pointers [LOG 19:10:59.271] kOS: FlightControlManager.AddTo 45e59b2a-16bb-4de8-9909-bd98dd240abb [LOG 19:10:59.271] kOS: FlightCtrlParam: Enabled: throttle False => False [LOG 19:10:59.272] kOS: FlightCtrlParam: Enabled: steering False => False [LOG 19:10:59.273] kOS: FlightCtrlParam: Enabled: wheelthrottle False => False [LOG 19:10:59.274] kOS: FlightCtrlParam: Enabled: wheelsteering False => False [LOG 19:10:59.276] kOS: Pushing context staring with: File Line:Col IP label opcode operand [LOG 19:10:59.276] kOS: Saving and removing 0 pointers [LOG 19:10:59.545] kOS: FlightControl Binding [LOG 19:10:59.546] kOS: FlightControl Bound [LOG 19:10:59.579] kOS: FunctionCopy: Volume: 0 Direction: from Filename: startup.ks [LOG 19:10:59.591] kOS: FunctionCopy: Volume: 0 Direction: from Filename: autonavinit.ks [LOG 19:10:59.602] kOS: FunctionCopy: Volume: 0 Direction: from Filename: autonaviterate.ks [LOG 19:10:59.953] Updating vessel voxel for Relay [LOG 19:11:00.182] Std dev for smoothing: 3 voxel total vol: 40.614487677163 filled vol: 3.44612579691208 [LOG 19:11:01.574] Updating vessel voxel for Relay [LOG 19:11:01.797] Std dev for smoothing: 3 voxel total vol: 40.614487677163 filled vol: 3.44612579691208 [LOG 19:11:03.243] Updating vessel voxel for Relay [LOG 19:11:03.418] Std dev for smoothing: 3 voxel total vol: 40.614487677163 filled vol: 3.44612579691208 [LOG 19:11:11.258] kOS: At autonavinit.ks on 1, line 10 RUN autoNavIterate(goalHeading). ^ Called from startup.ks on 1, line 3 RUN autoNavInit(270). ^ Called from boot.ks on archive, line 124 RUN startup.ks. ^ Called from sys:boot, line 1 (Can't show source line) ^ [LOG 19:11:11.259] System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Collections.Generic.Dictionary`2[System.String,System.Int32].get_Item (System.String key) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.ProgramBuilder.ReplaceLabels (System.Collections.Generic.List`1 program) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.ProgramBuilder.BuildProgram () [0x00000] in <filename unknown>:0 at kOS.Safe.Execution.ProgramContext.AddObjectParts (IEnumerable`1 parts) [0x00000] in <filename unknown>:0 at kOS.Function.FunctionLoad.Execute (kOS.SharedObjects shared) [0x00000] in <filename unknown>:0 at kOS.Function.FunctionManager.CallFunction (System.String functionName) [0x00000] in <filename unknown>:0 at kOS.Safe.Execution.CPU.CallBuiltinFunction (System.String functionName) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.OpcodeCall.StaticExecute (ICpu cpu, Boolean direct, System.Object destination, Boolean calledFromKOSDelegateCall) [0x00000] in <filename unknown>:0 at kOS.Safe.Compilation.OpcodeCall.Execute (ICpu cpu) [0x00000] in <filename unknown>:0 at kOS.Safe.Execution.CPU.ExecuteInstruction (IProgramContext context, Boolean doProfiling) [0x00000] in <filename unknown>:0 [LOG 19:11:11.265] Code Fragment File Line:Col IP label opcode operand ==== ====:=== ==== ================================ 1/startup.ks 3:17 0556 @0552 push 270 1/startup.ks 3:17 0557 @0553 call 526 1/startup.ks 3:17 0558 @0554 pop 0:0 0559 push 0 0:0 0560 return 0 deep 1/autonavinit.ks 10:1 0561 @0555 push $program-autonaviterate* 1/autonavinit.ks 10:1 0562 @0556 exists 1/autonavinit.ks 10:1 0563 @0557 br.false +4 1/autonavinit.ks 10:1 0564 @0558 br.false +11 1/autonavinit.ks 10:1 0565 @0559 push 0 1/autonavinit.ks 10:1 0566 @0560 return 0 deep 1/autonavinit.ks 10:1 0567 @0561 pop 1/autonavinit.ks 10:1 0568 @0562 push $program-autonaviterate* 1/autonavinit.ks 10:1 0569 @0563 push _KOSArgMarker_ 1/autonavinit.ks 10:1 0570 @0564 push autonaviterate 1/autonavinit.ks 10:1 0571 @0565 push null 1/autonavinit.ks 10:1 0572 @0566 call load() <<--INSTRUCTION POINTER-- 1/autonavinit.ks 10:1 0573 @0567 pop 1/autonavinit.ks 10:1 0574 @0568 store 1/autonavinit.ks 10:1 0575 @0569 call $program-autonaviterate* 1/autonavinit.ks 10:1 0576 @0570 pop 1/autonavinit.ks 10:1 0577 @0571 push 0 1/autonavinit.ks 10:1 0578 @0572 return 0 deep 1/autonavinit.ks 1:11 0579 @0573 push goalheading 1/autonavinit.ks 1:11 0580 @0574 swap 1/autonavinit.ks 1:11 0581 @0575 storelocal 1/autonavinit.ks 1:11 0582 @0576 argbottom 1/autonavinit.ks 3:7 0583 @0577 push _KOSArgMarker_ 1/autonavinit.ks 3:8 0584 @0578 push Starting navigation script...Done. 1/autonavinit.ks 3:46 0585 @0579 push NOMINAL 1/autonavinit.ks 3:46 0586 @0580 call $notify* 1/autonavinit.ks 3:46 0587 @0581 pop 1/autonavinit.ks 4:6 0588 @0582 push 5 [LOG 19:11:11.273] kOS: Stack dump: stackPointer = 10 018 SubroutineContext: {CameFromInstPtr 23, TriggerPointer -1} (type: SubroutineContext) 017 SubroutineContext: {CameFromInstPtr 16, TriggerPointer -1} (type: SubroutineContext) 016 kOS.Safe.Execution.VariableScope (type: VariableScope) ScopeId=22, ParentScopeId=0, ParentSkipLevels=1 IsClosure=False 015 SubroutineContext: {CameFromInstPtr 502, TriggerPointer -1} (type: SubroutineContext) 014 SubroutineContext: {CameFromInstPtr 375, TriggerPointer -1} (type: SubroutineContext) 013 SubroutineContext: {CameFromInstPtr 558, TriggerPointer -1} (type: SubroutineContext) 012 SubroutineContext: {CameFromInstPtr 541, TriggerPointer -1} (type: SubroutineContext) 011 SubroutineContext: {CameFromInstPtr 607, TriggerPointer -1} (type: SubroutineContext) 010 SP-> $program-autonaviterate* (type: String) 009 270 (type: Scalar) 008 _KOSArgMarker_ (type: KOSArgMarkerType) 007 _KOSArgMarker_ (type: KOSArgMarkerType) 006 _KOSArgMarker_ (type: KOSArgMarkerType) 005 _KOSArgMarker_ (type: KOSArgMarkerType) 004 _KOSArgMarker_ (type: KOSArgMarkerType) 003 _KOSArgMarker_ (type: KOSArgMarkerType) 002 _KOSArgMarker_ (type: KOSArgMarkerType) 001 _KOSArgMarker_ (type: KOSArgMarkerType) 000 0 (type: Scalar) [LOG 19:11:11.277] kOS: Popping context 2 [LOG 19:11:11.278] kOS: Removed Context File Line:Col IP label opcode operand
  7. I totally redid the algorithm. However, I'm still getting that "not in dictionary" error. What am I doing wrong? AutoNavInit.ks: PARAMETER goalHeading. // Navigation variables SET lookAhead TO 10. // Waypoint options will be plotted this far out in all directions SET acceptableSlope TO 10. // The new waypoint can have this much relative slope and still be good FUNCTION NOTIFY { PARAMETER message, priority. IF priority = "NOMINAL" { SET col TO GREEN. } ELSE IF priority = "ALERT" { SET col TO RGB(1,0.31,0). // international orange } ELSE IF priority = "WARNING" { SET col TO RED. } HUDTEXT("kOS: " + message, 5, 2, 30, col, FALSE). } NOTIFY("Starting navigation script...Done.", "NOMINAL"). WAIT 5. NOTIFY("Downloading navigation instructions...Done.", "NOMINAL"). WAIT 5. NOTIFY("Running iterative navigator...", "NOMINAL"). RUN autoNavIterate(goalHeading). AutoNavIterate.ks: // Until the goal has been reached, go through this process. PARAMETER direct. // The loop... Functions are defined below IF ADDONS:RT:HASCONNECTION(SHIP) { UNTIL FALSE { POPULATE(direct). DECIDE_NEXT(options). NOTIFY("Selecting next waypoint.", "NOMINAL"). WAIT 0.5. DRIVE_TO(nextPoint). STOP(). WAIT 5. IF NOT ADDONS:RT:HASCONNECTION(SHIP) { BREAK. } } } ELSE { UNTIL FALSE { POPULATE(360 - direct). DECIDE_NEXT(options). NOTIFY("Selecting next waypoint", "NOMINAL"). WAIT 0.5. DRIVE_TO(nextPoint). STOP(). WAIT 5. IF ADDONS:RT:HASCONNECTION(SHIP) { BREAK. } } } PARK(). FUNCTION THERE_YET { PARAMETER point. IF point:DISTANCE < 10 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { PARAMETER hdg. SET offset_90 TO SIN(hdg) * ((360 * lookAhead) / (BODY:RADIUS * 2 * CONSTANT:PI)). // duh SET offset_675 TO offset_90 * SIN(67.5). // 67.5 deg. SET offset_45 TO offset_90 * SIN(45). // 45 deg. SET offset_225 TO offset_90 * SIN(22.5). // 22.5 deg. SET op_A TO LATLNG(SHIP:GEOPOSITION:LAT + offset_225, SHIP:GEOPOSITION:LNG - offset_675). SET op_B TO LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG - offset_45). SET op_C TO LATLNG(SHIP:GEOPOSITION:LAT + offset_90, SHIP:GEOPOSITION:LNG). SET op_D TO LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG + offset_45). SET op_E TO LATLNG(SHIP:GEOPOSITION:LAT + offset_225, SHIP:GEOPOSITION:LNG + offset_675). SET options TO LIST ( op_A, op_B, op_C, op_D, op_E ). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER option. SET here TO SHIP:GEOPOSITION. SET there TO option. SET slope TO ABS(ARCTAN2(there:TERRAINHEIGHT - here:TERRAINHEIGHT, lookAhead)). IF slope < acceptableSlope { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER options. SET startPos TO 0. UNTIL startPos > options:LENGTH - 1 { SET o TO options[startPos]. IF SLOPE_IS_SAFE(o) { SET nextPoint TO o. RETURN nextPoint. BREAK. } ELSE { SET startPos TO startPos + 1. } } } FUNCTION DRIVE_TO { PARAMETER point. BRAKES OFF. SET spd TO 1. // Really stinkin' slow, but safe. // Throttle control variables SET throttlePID TO PIDLOOP(0.15, 0.05, 0.1, -1.0, 1.0). SET throttlePID:SETPOINT TO spd. // Steering control variables SET steerPID TO PIDLOOP(0.15, 0.05, 0.1, -1.0, 1.0). SET steerPID:SETPOINT TO point:HEADING. CLEARSCREEN. SET thrott TO 0. SET steerVal TO 0. UNTIL THERE_YET(point) { SET thrott TO throttlePID:UPDATE(TIME:SECONDS, SHIP:GROUNDSPEED). SET steerVal TO steerPID:UPDATE(TIME:SECONDS, SHIP:HEADING). LOCK WHEELTHROTTLE TO thrott. LOCK WHEELSTEER TO steerVal. PRINT "Current Location: " + ROUND(SHIP:GEOPOSITION:LAT,3) + ", " + ROUND(SHIP:GEOPOSITION:LNG,3) at (0,3). PRINT "Next waypoint: " + ROUND(point:LAT,3) + ", " + ROUND(point:LNG, 3) AT (0,4). PRINT "Throttle: " + ROUND(thrott, 3) AT (0,9). PRINT "Steering: " + ROUND(steerVal,3) AT (0,10). WAIT 0.01. } STOP(). } FUNCTION STOP { IF GROUNDSPEED > 0.5 { LOCK WHEELTHROTTLE TO -0.5. } ELSE { UNLOCK WHEELTHROTTLE. IF NOT BRAKES { BRAKES ON. } } UNLOCK ALL. NOTIFY("Arrived!", "NOMINAL"). } FUNCTION PARK { STOP(). LIST PARTS. FOR p IN PARTS { p:GETMODULE("ModuleAnimateGeneric"):DOEVENT("Extend"). p:GETMODULE("ModuleLight"):DOEVENT("Lights on"). } }
  8. Hmmm... Ok, now the driving works, but the navigation is behaving badly. It appears to want to drive straight south... How do I say, "Ok, go to the local radio horizon at this heading."?
  9. It no longer complains when I try the command RUN autonav(1000,270), but now it just does nothing at all. PARAMETER goalDistance, goalHeading. // Navigation variables SET lookAhead TO 100. // Waypoint options will be plotted this far out in all directions SET acceptableSlope TO 15. // The new waypoint can have this much relative slope and still be good SET acceptableBearingDiff TO 60. // The new waypoint can be this far off the goal and still be good // Initialize the navigation by setting a geo-point goal SET startPosition TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG). SET goalOffset TO (360 * goalDistance) / (BODY:RADIUS * 2 * CONSTANT:PI). SET goalLatOff TO goalOffset * SIN(goalHeading). SET goalLonOff TO goalOffset * COS(goalHeading). SET goal TO LATLNG(startPosition:LAT + goalLatOff, startPosition:LNG + goalLonOff). RUN autoNavIterate(goal).
  10. // Until the goal has been reached, go through this process. PARAMETER goal. // The loop... Functions are defined below UNTIL THERE_YET(goal) { POPULATE(). DECIDE_NEXT(goal, options, 0). DRIVE_TO(nextPoint). } LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 0.5. UNLOCK ALL. BRAKES ON. FUNCTION THERE_YET { PARAMETER point. SET here TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG). SET there TO point. // Crazy formula ahead!!! SET delta TO ARCTAN2(SQRT((COS(there:LAT * SIN(there:LNG - here:LNG))^2) + (COS(here:LAT) * SIN(there:LAT) - SIN(here:LAT) * COS(there:LAT) * COS(there:LNG - here:LNG) ^ 2)), (SIN(here:LAT) * SIN(there:LAT) + COS(here:LNG) * COS(there:LNG) * COS(there:LNG - here:LNG))). // Whew! SET dist TO BODY:RADIUS * delta. IF dist < 10 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { SET offset_90 TO (360 * lookAhead) / (2 * BODY:RADIUS * CONSTANT:PI). //100m north, east, south, or west. SET offset_45 TO offset_90 * SIN(45). SET options TO LIST ( LATLNG(SHIP:GEOPOSITION:LAT + offset_90, SHIP:GEOPOSITION:LNG), // N LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG + offset_45), // NE LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG + offset_90), // E LATLNG(SHIP:GEOPOSITION:LAT - offset_45, SHIP:GEOPOSITION:LNG + offset_45), // SE LATLNG(SHIP:GEOPOSITION:LAT - offset_90, SHIP:GEOPOSITION:LNG), // S LATLNG(SHIP:GEOPOSITION:LAT - offset_45, SHIP:GEOPOSITION:LNG - offset_45), // SW LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG - offset_90), // W LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG - offset_45) // W ). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER option. SET here TO SHIP:GEOPOSITION. SET there TO option. SET slope TO ABS(ARCTAN2(there:TERRAINHEIGHT - here:TERRAINHEIGHT, lookAhead)). IF slope < acceptableSlope { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION BEARING_IS_OK { PARAMETER option, goal. SET brg TO ABS(goal:BEARING - option:BEARING). // Make sure the result makes sense... IF brg > 180 { SET brg TO brg - 360. } IF brg < 60 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER goal, options, startPos. SET o TO options[startPos]. IF SLOPE_IS_SAFE(o) AND BEARING_IS_OK(o, goal) { SET nextPoint TO o. RETURN nextPoint. } ELSE { SET startPos TO startPos + 1. DECIDE_NEXT(goal, options, startPos). } } FUNCTION DRIVE_TO { PARAMETER point. SET spd TO 1. // Really stinkin' slow, but safe. // Throttle control variables SET kPT TO 0.05. SET kIT TO 0.25. SET kDT TO 0.75. SET throttlePID TO PIDLOOP(kPT, kIT, kDT, -1, 1). SET throttlePID:SETPOINT TO spd. // Steering control variables SET kPS TO (1/180). SET kIS TO 0.01. SET kDS TO 0.125. SET steerPID TO PIDLOOP(kPS, kIS, kDS, -1, 1). SET steerPID:SETPOINT TO point:HEADING. UNTIL THERE_YET(point) { SET WHEELTHROTTLE TO throttlePID:OUTPUT. SET WHEELSTEER TO steerPID:OUTPUT. } } Fixed it?
  11. https://drive.google.com/file/d/0B1BXLWa5LPIMWmw4M0xPTk1JNE0/view?usp=sharing Ok, corrected the order of parameters bug / typo. It's still not letting me iterate over the options, though... Attached is a screenshot of the error.
  12. // Until the goal has been reached, go through this process. // The loop... Functions are defined below UNTIL THERE_YET(goal) { POPULATE(). DECIDE_NEXT(options, goal). DRIVE_TO(nextPoint). } LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 0.5. UNLOCK ALL. BRAKES ON. FUNCTION THERE_YET { PARAMETER point. SET here TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG). SET there TO point. // Crazy formula ahead!!! SET delta TO ARCTAN2(SQRT((COS(there:LAT * SIN(there:LNG - here:LNG))^2) + (COS(here:LAT) * SIN(there:LAT) - SIN(here:LAT) * COS(there:LAT) * COS(there:LNG - here:LNG) ^ 2)), (SIN(here:LAT) * SIN(there:LAT) + COS(here:LNG) * COS(there:LNG) * COS(there:LNG - here:LNG))). // Whew! SET dist TO BODY:RADIUS * delta. IF dist < 10 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { SET offset_90 TO (360 * lookAhead) / (2 * BODY:RADIUS * CONSTANT:PI). //100m north, east, south, or west. SET offset_45 TO offset_90 * SIN(45). SET options TO LIST ( LATLNG(SHIP:GEOPOSITION:LAT + offset_90, SHIP:GEOPOSITION:LNG), // N LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG + offset_45), // NE LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG + offset_90), // E LATLNG(SHIP:GEOPOSITION:LAT - offset_45, SHIP:GEOPOSITION:LNG + offset_45), // SE LATLNG(SHIP:GEOPOSITION:LAT - offset_90, SHIP:GEOPOSITION:LNG), // S LATLNG(SHIP:GEOPOSITION:LAT - offset_45, SHIP:GEOPOSITION:LNG - offset_45), // SW LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG - offset_90), // W LATLNG(SHIP:GEOPOSITION:LAT + offset_45, SHIP:GEOPOSITION:LNG - offset_45) // W ). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER option. SET here TO SHIP:GEOPOSITION. SET there TO option:GEOPOSITION. SET slope TO ABS(ARCTAN2(there:TERRAINHEIGHT - here:TERRAINHEIGHT, lookAhead)). IF slope < acceptableSlope { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION BEARING_IS_OK { PARAMETER option, goal. SET brg TO ABS(goal:BEARING - option:BEARING). // Make sure the result makes sense... IF brg > 180 { SET brg TO brg - 360. } IF brg < 60 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER goal, options. SET n TO 0. UNTIL FALSE { IF SLOPE_IS_SAFE(options[n]) AND BEARING_IS_OK(options[n], goal) { SET nextPoint TO options[n]. BREAK. } ELSE IF SLOPE_IS_SAFE(options[n]) { SET nextPoint TO options[n]. BREAK. } ELSE { SET n TO n + 1. } } RETURN nextPoint. } FUNCTION DRIVE_TO { PARAMETER point. SET spd TO 1. // Really stinkin' slow, but safe. // Throttle control variables SET kPT TO 0.05. SET kIT TO 0.25. SET kDT TO 0.75. SET throttlePID TO PIDLOOP(kPT, kIT, kDT, -1, 1). SET throttlePID:SETPOINT TO spd. // Steering control variables SET kPS TO (1/180). SET kIS TO 0.01. SET kDS TO 0.125. SET steerPID TO PIDLOOP(kPS, kIS, kDS, -1, 1). SET steerPID:SETPOINT TO point:HEADING. UNTIL THERE_YET(point) { SET WHEELTHROTTLE TO throttlePID:OUTPUT. SET WHEELSTEER TO steerPID:OUTPUT. } } Ok... Revamped the autonav script, but now I'm having trouble with iteration... What's going on?
  13. I've corrected as many errors as I can, but it's still throwing the same exception. PARAMETER hdg. // 0 -> 359; 0 = north, 90 = east, etc. FUNCTION NOTIFY { PARAMETER message. HUDTEXT("kOS: " + message, 5, 2, 50, GREEN, FALSE). } FUNCTION SET_GOAL { PARAMETER theta. SET position_here TO SHIP:GEOPOSITION. SET height_here TO pos:TERRAINHEIGHT. SET planet_radius TO BODY:RADIUS. SET d TO (2 * CONSTANT:PI * planet_radius) * ARCSIN(SQRT((planet_radius + height_here)^2 - planet_radius^2) / ((planet_radius + height_here) / 360)). // Radio horizon equation SET delta TO d * 0.95. // 5% safety margin SET goal TO LATLNG(pos:LATITUDE + (delta * SIN(theta)), pos:LONGITUDE + (delta * COS(theta))). RETURN goal. } FUNCTION ARRIVED { PARAMETER this, that. SET here TO LATLNG(this:LAT, this:LNG). SET there TO LATLNG(this:LAT, that:LNG). SET dist TO BODY:RADIUS * ARCCOS((SIN(here:LNG) * SIN(there:LNG)) + (COS(here:LNG) * COS(there:LNG) * COS(ABS(here:LAT - there:LAT)))). IF dist < 10 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { SET location TO LATLNG(SHIP:GEOPOSITION). SET off_90 TO 36000/(2*CONSTANT:PI*BODY:RADIUS). SET off_675 TO off_90 * SIN(67.5). SET off_45 TO off_90 * SIN(45). SET off_225 TO off_90 * SIN(22.5). SET options TO LIST ( LATLNG(location:LAT + off_90, location:LNG), // N LATLNG(location:LAT + off_675, location:LNG + off_225), // NNE LATLNG(location:LAT + off_45, location:LNG + off_45), // NE LATLNG(location:LAT + off_225, location:LNG + off_675), // ENE LATLNG(location:LAT, location:LNG + off_90), // E LATLNG(location:LAT - off_225, location:LNG + off_675), // ESE LATLNG(location:LAT - off_45, location:LNG + off_45), // SE LATLNG(location:LAT - off_675, location:LNG + off_225), // SSE LATLNG(location:LAT - off_90, location:LNG), // S LATLNG(location:LAT - off_675, location:LNG - off_225), // SSW LATLNG(location:LAT - off_45, location:LNG - off_45), // SW LATLNG(location:LAT - off_225, location:LNG - off_675), // WSW LATLNG(location:LAT, location:LNG - off_90), // W LATLNG(location:LAT + off_225, location:LNG - off_675), // WNW LATLNG(location:LAT + off_45, location:LNG - off_45), // NW LATLNG(location:LAT + off_675, location:LNG - off_225) // NNW ). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER point. SET geo_point TO GEOPOSITION(point:LATITUDE, point:LONGITUDE). SET slope TO ABS(ARCTAN2(geo_point:TERRAINHEIGHT - SHIP:ALTITUDE, 100)). IF slope < 15 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION ANGLE_IS_REASONABLE { PARAMETER option, goal. SET angle TO ABS(goal:BEARING - option:BEARING). IF angle < 60 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE { PARAMETER options, goal. FOR o IN options { IF SLOPE_IS_SAFE(o) { IF ANGLE_IS_REASONABLE(o, goal) { SET nextpoint TO LATLNG(o:LAT, o:LNG). RETURN nextpoint. } } } } FUNCTION DRIVE_TO { PARAMETER point. LOCK turnlimit TO MIN(1, 1.5 / GROUNDSPEED). // Scale the // turning radius // based on current speed SET loopTime TO 0.01. SET loopEndTime TO TIME:SECONDS. SET eWheelThrottle TO 0. // Error between target speed and actual speed SET iWheelThrottle TO 0. // Accumulated speed error SET wtVAL TO 0. //Wheel Throttle Value SET eSteer TO 0. // Steering error SET kTurn TO 0. //Wheel turn value. SET targetspeed TO 0. //Cruise control starting speed SET targetHeading TO 90. //Used for autopilot steering SET NORTHPOLE TO LATLNG(90, 0). //Reference heading CLEARSCREEN. PRINT("Activate action group 10 to begin driving."). ON AG10 { SET runmode TO 0. } UNTIL runmode = -1 { IF SHIP:SENSORS:LIGHT < 0.75 { LIGHTS ON. } ELSE { LIGHTS OFF. } IF runmode = 0 { //Update the compass: // I want the heading to match the navball // and be out of 360' instead of +/-180' // I do this by judging the heading relative // to a latlng set to the north pole IF NORTHPOLE:BEARING <= 0 { SET cHeading TO ABS(NORTHPOLE:BEARING). } ELSE { SET cHeading TO (180 - NORTHPOLE:BEARING) + 180. } IF targetHeading > 360 { SET targetHeading TO targetHeading - 360. } ELSE IF targetHeading < 0 { SET targetHeading TO targetHeading + 360. } BRAKES OFF. SET eWT TO targetSpeed - GROUNDSPEED. SET iWT TO MIN(1, MAX(-1, iWheelThrottle + (eWheelThrottle * loopTime))). SET wtVAL TO MIN(1, MAX(-1, eWT + iWT)). SET eSteer TO targetHeading - cHeading. IF eSteer > 180 { SET eSteer TO eSteer - 360. } SET desiredSteering TO -eSteer / 10. SET kTurn TO MIN(1, MAX(-1, desiredSteering)) * turnLimit. } SET SHIP:CONTROL:WHEELTHROTTLE TO wtVAL. SET SHIP:CONTROL:WHEELSTEER TO kTurn. SET loopTime TO TIME:SECONDS - loopEndTime. SET loopEndTime TO TIME:SECONDS. IF ARRIVED(SHIP:GEOPOSITION, point:GEOPOSITION) { SET runmode TO -1. } } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON. NOTIFY("Arrived at waypoint. Setting next."). } SET_GOAL(hdg). UNTIL ARRIVED(SHIP:GEOPOSITION, goal) { POPULATE(). DECIDE(options, goal). DRIVE_TO(nextPoint). } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON. NOTIFY("Arrived at goal! Shutting down."). FOR ants IN SHIP:PARTSNAMED("rtLongAntenna2") { ants:GETMODULE("ModuleAnimateGeneric"):DOEVENT("Extend"). } LIGHTS ON. SHUTDOWN.
  14. I have something that looks promising, but it refuses to run... Can someone tell me why? PARAMETER hdg. // 0 -> 359; 0 = north, 90 = east, etc. FUNCTION NOTIFY { PARAMETER message. HUDTEXT("kOS: " + message, 5, 2, 50, GREEN, FALSE). } FUNCTION SET_GOAL { PARAMETER theta. SET pos TO SHIP:GEOPOSITION. SET h TO pos:TERRAINHEIGHT. SET r TO BODY:RADIUS. SET d TO (2 * CONSTANT:PI * BODY:RADIUS) * ARCSIN(SQRT((R+h)^2-R^2)/((R+h)/360)). // Radio horizon equation SET delta TO d * 0.95. // 5% safety margin SET goal TO LATLNG ( pos:LAT + (delta * SIN(theta)), pos:LNG + (delta * COS(theta)) ). RETURN goal. } FUNCTION ARRIVED { PARAMETER location, setpoint. SET here TO LATLNG(location:LAT, location:LNG). SET there TO LATLNG(setpoint:LAT, setpoint:LNG). SET dist TO BODY:RADIUS * ARCCOS((SIN(here:LNG) * SIN(there:LNG)) + (COS(here:LNG) * COS(there:LNG) * COS(ABS(here:LAT - there:LAT)))). IF dist < 10 { SET arrived TO TRUE. } ELSE { SET arrived TO FALSE. } RETURN arrived. } FUNCTION POPULATE { SET loc TO LATLNG(SHIP:GEOPOSITION). SET off_90 TO 36000/(2*CONSTANT:PI*BODY:RADIUS). SET off_675 TO off_90 * SIN(67.5). SET off_45 TO off_90 * SIN(45). SET off_225 TO off_90 * SIN(22.5). SET a TO LATLNG(loc:LAT + off_90, loc:LNG). // N SET b TO LATLNG(loc:LAT + off_675, loc:LNG + off_225). // NNE SET c TO LATLNG(loc:LAT + off_45, loc:LNG + off_45). // NE SET d TO LATLNG(loc:LAT + off_225, loc:LNG + off_675). // ENE SET e TO LATLNG(loc:LAT, LOC:LNG + off_90). // E SET f TO LATLNG(loc:LAT - off_225, loc:LNG + off_675). // ESE SET g TO LATLNG(loc:LAT - off_45, loc:LNG + off_45). // SE SET h TO LATLNG(loc:LAT - off_675, loc:LNG + off_225). // SSE SET i TO LATLNG(loc:LAT - off_90, loc:LNG). // S SET j TO LATLNG(loc:LAT - off_675, loc:LNG - off_225). // SSW SET k TO LATLNG(loc:LAT - off_45, loc:LNG - off_45). // SW SET l TO LATLNG(loc:LAT - off_225, loc:LNG - off_675). // WSW SET m TO LATLNG(loc:LAT, loc:LNG - off_90). // W SET n TO LATLNG(loc:LAT + off_225, loc:LNG - off_675). // WNW SET o TO LATLNG(loc:LAT + off_45, loc:LNG - off_45). // NW SET p TO LATLNG(loc:LAT + off_675, loc:LNG - off_225). // NNW SET options TO LIST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER point. SET slope TO ABS(ARCTAN2(point:TERRAINHEIGHT - SHIP:ALTITUDE, 100)). IF slope < 15 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION ANGLE_IS_REASONABLE { PARAMETER point, goal. SET angle TO ABS(goal:BEARING - point:BEARING). IF angle < 60 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE { PARAMETER options, goal. FOR o IN options { IF SLOPE_IS_SAFE(o) { IF ANGLE_IS_REASONABLE(o, goal) { SET nextpoint TO LATLNG(o:LAT, o:LNG). RETURN nextpoint. } } } } FUNCTION DRIVE_TO { PARAMETER point. LOCK turnlimit TO MIN(1, 1.5 / GROUNDSPEED). // Scale the // turning radius // based on current speed SET loopTime TO 0.01. SET loopEndTime TO TIME:SECONDS. SET eWheelThrottle TO 0. // Error between target speed and actual speed SET iWheelThrottle TO 0. // Accumulated speed error SET wtVAL TO 0. //Wheel Throttle Value SET eSteer TO 0. // Steering error SET kTurn TO 0. //Wheel turn value. SET targetspeed TO 0. //Cruise control starting speed SET targetHeading TO 90. //Used for autopilot steering SET NORTHPOLE TO LATLNG( 90, 0). //Reference heading CLEARSCREEN. PRINT("Activate action group 10 to begin driving."). ON AG10 { SET runmode TO 0. } UNTIL runmode = -1 { IF SHIP:SENSORS:LIGHT < 0.75 { LIGHTS ON. } ELSE { LIGHTS OFF. } IF runmode = 0 { //Update the compass: // I want the heading to match the navball // and be out of 360' instead of +/-180' // I do this by judging the heading relative // to a latlng set to the north pole IF NORTHPOLE:BEARING <= 0 { SET cHeading TO ABS(NORTHPOLE:BEARING). } ELSE { SET cHeading TO (180 - NORTHPOLE:BEARING) + 180. } IF targetHeading > 360 { SET targetHeading TO targetHeading - 360. } ELSE IF targetHeading < 0 { SET targetHeading TO targetHeading + 360. } BRAKES OFF. SET eWT TO targetSpeed - GROUNDSPEED. SET iWT TO MIN(1, MAX(-1, iWheelThrottle + (eWheelThrottle * loopTime))). SET wtVAL TO MIN(1, MAX(-1, eWT + iWT)). SET eSteer TO targetHeading - cHeading. IF eSteer > 180 { SET eSteer TO eSteer - 360. } SET desiredSteering TO -eSteer / 10. SET kTurn TO MIN(1, MAX(-1, desiredSteering)) * turnLimit. } SET SHIP:CONTROL:WHEELTHROTTLE TO wtVAL. SET SHIP:CONTROL:WHEELSTEER TO kTurn. SET loopTime TO TIME:SECONDS - loopEndTime. SET loopEndTime TO TIME:SECONDS. IF ARRIVED(SHIP:GEOPOSITION, point:GEOPOSITION) { SET runmode TO -1. } } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON. NOTIFY("Arrived at waypoint. Setting next."). } SET_GOAL(hdg). UNTIL ARRIVED(SHIP:GEOPOSITION, goal) { POPULATE(). DECIDE(options, goal). DRIVE_TO(nextPoint). } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON. NOTIFY("Arrived at goal! Shutting down."). FOR ants IN SHIP:PARTSNAMED("rtLongAntenna2") { ants:GETMODULE("ModuleAnimateGeneric"):DOEVENT("Extend"). } LIGHTS ON. SHUTDOWN.
  15. Where would I find the error log for kOS? Do I need to change any settings?
  16. @LAZYGLOBAL OFF. PARAMETER hdg, numberOfLengths. //use to find the initial bearing for the shortest path around a sphere from... FUNCTION CIRCLE_BEARING { PARAMETER p1, //...this point... p2. //...to this point. RETURN MOD(360 + ARCTAN2(SIN(p2:LNG - p1:LNG) * COS(p2:LAT), COS(p1:LAT) * SIN(p2:LAT) - SIN(p1:LAT) * COS(p2:LAT) * COS(p2:LNG - p1:LNG)), 360). } //use to find where you will end up if you travel from... FUNCTION CIRCLE_DESTINATION { PARAMETER p1, //...this point... b, // ...with this as your intitial bearing... d, // ...for this distance... r. // ...around a sphere of this radious. LOCAL lat IS ARCSIN(SIN(p1:LAT)*COS((d*180)/(r*CONSTANT:PI))+COS(p1:LAT)*SIN((d*180)/(r*CONSTANT:PI))*COS(b)). LOCAL lng IS 0. IF ABS(lat) <> 90 { SET lng TO p1:LNG+ARCTAN2(SIN(b)*SIN((d*180)/(r*CONSTANT:PI))*COS(p1:LAT),COS((d*180)/(r*CONSTANT:PI)) - SIN(p1:LAT)*SIN(lat)). } RETURN LATLNG(lat,lng). } //use to find the distance from... FUNCTION CIRCLE_DISTANCE { PARAMETER p1, //...this point... p2, //...to this point... radius. //...around a body of this radius. (note: if you are flying you may want to use ship:body:radius + altitude). LOCAL A IS SIN((p1:LAT - p2:LAT) / 2)^2 + COS(p1:LAT) * COS(p2:LAT) * SIN((p1:LNG-p2:LNG) / 2)^2. RETURN r * CONSTANT():PI * ARCTAN2(SQRT(A), SQRT(1 - A)) / 90. } //use to find the mid point on the outside of a sphere between... FUNCTION CIRCLE_MIDPOINT { PARAMETER p1, //...this point... p2. //...and this point. LOCAL A IS COS(p2:LAT) * COS(p2:LNG - p1:LNG). LOCAL B IS COS(p2:LAT) * SIN(p2:LNG - p1:LNG). RETURN LATLNG(ARCTAN2(SIN(p1:LAT) + SIN(p2:LAT), SQRT((COS(p1:LAT) + A)^2 + B^2)), p1:LNG+ARCTAN2(B, COS(p1:LAT) + A)). } FUNCTION THERE_YET { PARAMETER goal. IF CIRCLE_DISTANCE(point, goal, BODY:RADIUS) <= 20 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { SET off_90 TO ((360 * 100) / (CONSTANT:PI * BODY:RADIUS * 2)). SET off_675 TO off_90 * SIN(67.5). SET off_45 TO off_90 * SIN(45). SET off_225 TO off_90 * SIN(22.5). SET a TO LATLNG(SHIP:GEOPOSITION:LAT + off_90, SHIP:GEOPOSITION:LNG). // North SET b TO LATLNG(SHIP:GEOPOSITION:LAT + off_675, SHIP:GEOPOSITION:LNG + off_225). // North-northeast SET c TO LATLNG(SHIP:GEOPOSITION:LAT + off_45, SHIP:GEOPOSITION:LNG + off_45). // Northeast SET d TO LATLNG(SHIP:GEOPOSITION:LAT + off_225, SHIP:GEOPOSITION:LNG + off_675). // East-northeast SET e TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG + off_90). // East SET f TO LATLNG(SHIP:GEOPOSITION:LAT - off_225, SHIP:GEOPOSITION:LNG + off_675). // East-southeast SET g TO LATLNG(SHIP:GEOPOSITION:LAT - off_45, SHIP:GEOPOSITION:LNG + off_45). // Southeast SET h TO LATLNG(SHIP:GEOPOSITION:LAT - off_675, SHIP:GEOPOSITION:LNG + off_225). // South-southeast SET i TO LATLNG(SHIP:GEOPOSITION:LAT - off_90, SHIP:GEOPOSITION:LNG). // South SET j TO LATLNG(SHIP:GEOPOSITION:LAT - off_675, SHIP:GEOPOSITION:LNG - off_225). // South-southwest SET k TO LATLNG(SHIP:GEOPOSITION:LAT - off_45, SHIP:GEOPOSITION:LNG - off_45). // Southwest SET l TO LATLNG(SHIP:GEOPOSITION:LAT - off_225, SHIP:GEOPOSITION:LNG - off_675). // West-southwest SET m TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG - off_90). // West SET n TO LATLNG(SHIP:GEOPOSITION:LAT + off_225, SHIP:GEOPOSITION:LNG - off_675). // West-northwest SET o TO LATLNG(SHIP:GEOPOSITION:LAT + off_45, SHIP:GEOPOSITION:LNG - off_45). // Northwest SET p TO LATLNG(SHIP:GEOPOSITION:LAT + off_675, SHIP:GEOPOSITION:LNG - off_225). // North-northwest SET options TO LIST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER point. SET loc TO GEOPOSITION(point:LATITUDE, point:LONGITUDE). SET curPos TO SHIP:GEOPOSITION. SET slope TO ABS(ARCTAN2((loc:TERRAINHEIGHT - curPos:TERRAINHEIGHT), 100)). IF slope < 15 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION BEARING_IS_REASONABLE { PARAMETER point, goal. SET brg TO ABS(goal:BEARING - point:BEARING). IF brg < 60 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER options, goal. FOR o IN options { IF SLOPE_IS_SAFE(o) AND BEARING_IS_REASONABLE(point, goal) { SET nextPoint TO LATLNG(o:LAT, o:LNG). RETURN nextPoint. } } } FUNCTION DRIVE_TO { PARAMETER point. SET spd TO 5. SET loopT TO 0.01. SET loopEndT TO TIME:SECONDS. UNTIL arrived(point) { // PI controller for speed SET pWT TO spd - GROUNDSPEED. SET iWT TO MIN(1, MAX(-1, iWT + (pWT * loopT))). SET wtVal TO pWT + iWT. // Proportional control for heading SET pSteer TO COMPASS_FOR(SHIP) - point:HEADING. SET steerVal TO (pSteer / 180). // Now write the outputs to the physical systems. LOCK WHEELTHROTTLE TO wtVal. LOCK WHEELSTEER TO steerVal. SET loopT TO TIME:SECONDS - loopEndT. SET loopEndT TO TIME:SECONDS. } } GLOBAL v IS SHIP:ALTITUDE. GLOBAL r IS BODY:RADIUS. GLOBAL point IS SHIP:GEOPOSITION. GLOBAL radioHorizon IS SQRT((R+v)^2 - (R^2)). GLOBAL dist IS (360 * (0.95 * radioHorizon * numberOfLengths)) / (2 * CONSTANT:PI * BODY:RADIUS). GLOBAL goal IS CIRCLE_DESTINATION(point, hdg, dist, R). UNTIL THERE_YET(goal) { POPULATE(). DECIDE_NEXT(options, goal). DRIVE_TO(nextPoint). WAIT 5. BRAKES OFF. } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON. I'm stumped... Can you give me any feedback as to how to get this to work? To test it, just put the script on a generic rover and give the kOS terminal the command "RUN autonav(270,1).
  17. It drives in circles. Also, I made a new version, but it won't run at all... The error it gives me is "the given key is not in the dictionary". @LAZYGLOBAL OFF. PARAMETER hdg, numberOfLengths. //use to find the initial bearing for the shortest path around a sphere from... FUNCTION CIRCLE_BEARING { PARAMETER p1, //...this point... p2. //...to this point. RETURN MOD(360 + ARCTAN2(SIN(p2:LNG - p1:LNG) * COS(p2:LAT), COS(p1:LAT) * SIN(p2:LAT) - SIN(p1:LAT) * COS(p2:LAT) * COS(p2:LNG - p1:LNG)), 360). } //use to find where you will end up if you travel from... FUNCTION CIRCLE_DESTINATION { PARAMETER p1, //...this point... b, // ...with this as your intitial bearing... d, // ...for this distance... radius. // ...around a sphere of this radious. LOCAL lat IS ARCSIN(SIN(p1:LAT)*COS((d*180)/(radius*CONSTANT():PI))+COS(p1:LAT)*SIN((d*180)/(radius*CONSTANT():PI))*COS(b)). LOCAL lng IS 0. IF ABS(lat) <> 90 { SET lng TO p1:LNG+ARCTAN2(SIN(b)*SIN((d*180)/(radius*CONSTANT():PI))*COS(p1:LAT),COS((d*180)/(radius*CONSTANT():PI)) - SIN(p1:LAT)*SIN(lat)). } RETURN LATLNG(lat,lng). } //use to find the distance from... FUNCTION CIRCLE_DISTANCE { PARAMETER p1, //...this point... p2, //...to this point... radius. //...around a body of this radius. (note: if you are flying you may want to use ship:body:radius + altitude). LOCAL A IS SIN((p1:LAT - p2:LAT) / 2)^2 + COS(p1:LAT) * COS(p2:LAT) * SIN((p1:LNG-p2:LNG) / 2)^2. RETURN radius * CONSTANT():PI * ARCTAN2(SQRT(A), SQRT(1 - A)) / 90. } //use to find the mid point on the outside of a sphere between... FUNCTION CIRCLE_MIDPOINT { PARAMETER p1, //...this point... p2. //...and this point. LOCAL A IS COS(p2:LAT) * COS(p2:LNG - p1:LNG). LOCAL B IS COS(p2:LAT) * SIN(p2:LNG - p1:LNG). RETURN LATLNG(ARCTAN2(SIN(p1:LAT) + SIN(p2:LAT), SQRT((COS(p1:LAT) + A)^2 + B^2)), p1:LNG+ARCTAN2(B, COS(p1:LAT) + A)). } FUNCTION THERE_YET { PARAMETER goal. IF CIRCLE_DISTANCE(point, goal, BODY:RADIUS) <= 20 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION POPULATE { SET off_90 TO ((360 * 100) / (CONSTANT:PI * BODY:RADIUS * 2)). SET off_675 TO off_90 * SIN(67.5). SET off_45 TO off_90 * SIN(45). SET off_225 TO off_90 * SIN(22.5). SET a TO LATLNG(SHIP:GEOPOSITION:LAT + off_90, SHIP:GEOPOSITION:LNG). // North SET b TO LATLNG(SHIP:GEOPOSITION:LAT + off_675, SHIP:GEOPOSITION:LNG + off_225). // North-northeast SET c TO LATLNG(SHIP:GEOPOSITION:LAT + off_45, SHIP:GEOPOSITION:LNG + off_45). // Northeast SET d TO LATLNG(SHIP:GEOPOSITION:LAT + off_225, SHIP:GEOPOSITION:LNG + off_675). // East-northeast SET e TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG + off_90). // East SET f TO LATLNG(SHIP:GEOPOSITION:LAT - off_225, SHIP:GEOPOSITION:LNG + off_675). // East-southeast SET g TO LATLNG(SHIP:GEOPOSITION:LAT - off_45, SHIP:GEOPOSITION:LNG + off_45). // Southeast SET h TO LATLNG(SHIP:GEOPOSITION:LAT - off_675, SHIP:GEOPOSITION:LNG + off_225). // South-southeast SET i TO LATLNG(SHIP:GEOPOSITION:LAT - off_90, SHIP:GEOPOSITION:LNG). // South SET j TO LATLNG(SHIP:GEOPOSITION:LAT - off_675, SHIP:GEOPOSITION:LNG - off_225). // South-southwest SET k TO LATLNG(SHIP:GEOPOSITION:LAT - off_45, SHIP:GEOPOSITION:LNG - off_45). // Southwest SET l TO LATLNG(SHIP:GEOPOSITION:LAT - off_225, SHIP:GEOPOSITION:LNG - off_675). // West-southwest SET m TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG - off_90). // West SET n TO LATLNG(SHIP:GEOPOSITION:LAT + off_225, SHIP:GEOPOSITION:LNG - off_675). // West-northwest SET o TO LATLNG(SHIP:GEOPOSITION:LAT + off_45, SHIP:GEOPOSITION:LNG - off_45). // Northwest SET p TO LATLNG(SHIP:GEOPOSITION:LAT + off_675, SHIP:GEOPOSITION:LNG - off_225). // North-northwest SET options TO LIST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p). RETURN options. } FUNCTION SLOPE_IS_SAFE { PARAMETER point. SET loc TO GEOPOSITION(point:LATITUDE, point:LONGITUDE). SET curPos TO SHIP:GEOPOSITION. SET slope TO ABS(ARCTAN2((loc:TERRAINHEIGHT - curPos:TERRAINHEIGHT), 100)). IF slope < 15 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION BEARING_IS_REASONABLE { PARAMETER point, goal. SET brg TO ABS(goal:BEARING - point:BEARING). IF brg < 60 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER options, goal. FOR o IN options { IF SLOPE_IS_SAFE(o) AND BEARING_IS_REASONABLE(point, goal) { SET nextPoint TO LATLNG(o:LAT, o:LNG). RETURN nextPoint. } } } FUNCTION DRIVE_TO { PARAMETER point. SET spd TO 5. SET loopT TO 0.01. SET loopEndT TO TIME:SECONDS. UNTIL arrived(point) { SET pWT TO spd - GROUNDSPEED. SET iWT TO MIN(1, MAX(-1, iWT + (pWT * loopT))). LOCK WHEELTHROTTLE TO pWT + iWT. SET pSteer TO COMPASS_FOR(SHIP) - point:HEADING. LOCK WHEELSTEER TO (pSteer / 180). SET loopT TO TIME:SECONDS - loopEndT. SET loopEndT TO TIME:SECONDS. } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON. } SET h TO SHIP:ALTITUDE. SET R TO BODY:RADIUS. SET point TO SHIP:GEOPOSITION. SET radioHorizon TO SQRT((R+h)^2 - (R^2)). SET dist TO (360 * (radioHorizon * numberOfLengths)) / (2 * CONSTANT:PI * BODY:RADIUS). SET goal TO CIRCLE_DESTNATION(point, hdg, dist, R). UNTIL arrived(goal) { POPULATE(). DECIDE_NEXT(options, goal). DRIVE_TO(nextPoint). WAIT 5. BRAKES OFF. } LOCK WHEELSTEER TO 0. LOCK WHEELTHROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 1. UNLOCK ALL. BRAKES ON.
  18. Not sure whether this is the right forum, but I'm stumped on an autonavigation script I'm trying to develop for kOS. The waypoint selection code works fine, but I can't seem to actually get the rover to drive to the waypoint...help? Code is below. CLEARSCREEN. SET SHIP:CONTROL:PILOTMAINTHROTTLE TO 0. LOCK THROTTLE TO 0. SWITCH TO 0. RUN autolights. RCS OFF. SAS OFF. GEAR OFF. // My plan for autonomous navigation is an iterative algorithm. // The goal is a LATLNG() that is calculated // from the input parameter hdg in degrees clockwise from north. PARAMETER hdg, horizonMultiplier. AUTOLIGHTS(). SET dist TO SQRT((BODY:RADIUS + ALTITUDE)^2 - (BODY:RADIUS ^ 2)). // Radio horizon calculation SET distLat TO (horizonMultiplier * dist) * COS(hdg). // X offset = a multiple of the x unit vector SET distLng TO (horizonMultiplier * dist) * SIN(hdg). // Y offset = a multiple of the y unit vector SET offSetLat TO (360 * (distLat * 0.9)) / (2 * BODY:RADIUS * CONSTANT:PI). // The difference in latitude caused by moving x meters north or south SET offSetLng TO (360 * (distLng * 0.9)) / (2 * BODY:RADIUS * CONSTANT:PI). // The difference in longitude caused by moving y meters east or west SET startPos TO SHIP:GEOPOSITION. SET goal TO LATLNG(SHIP:GEOPOSITION:LAT + offSetLat, SHIP:GEOPOSITION:LNG + offSetLng). // The current position plus the offset // First the script checks to see whether it has reached the goal. FUNCTION THERE_YET { PARAMETER goal. IF goal:DISTANCE < 1 { RETURN TRUE. } ELSE { RETURN FALSE. } } // Next, it creates a list of waypoints set 5m away FUNCTION POPULATE { SET offSetA TO (360 * 100) / (BODY:RADIUS * 2 * CONSTANT:PI). SET offSetB TO offSetA * SIN(45). SET optionA TO LATLNG(startPos:LAT + offSetA, startPos:LNG). // N SET optionB TO LATLNG(startPos:LAT + offSetB, startPos:LNG + offSetB). // NE SET optionC TO LATLNG(startPos:LAT, startPos:LNG + offSetA). // E SET optionD TO LATLNG(startPos:LAT - offSetB, startPos:LNG - offSetB). // NW SET optionE TO LATLNG(startPos:LAT - offSetA, startPos:LNG). // S SET optionF TO LATLNG(startPos:LAT - offSetB, startPos:LNG + offSetB). // SW SET optionG TO LATLNG(startPos:LAT, startPos:LNG - offSetA). // W SET optionH TO LATLNG(startPos:LAT + offSetB, startPos:LNG - offSetB). // NW SET options TO LIST(optionA, optionB, optionC, optionD, optionF, optionG, optionH). PRINT("Deciding options...done.") AT (1,1). RETURN options. } // Then, it defines two helper functions - one for slope... FUNCTION SLOPE_IS_SAFE { PARAMETER option. SET location TO SHIP:GEOPOSITION. SET newHeight TO option:TERRAINHEIGHT. SET slope TO ABS(ARCTAN2((newHeight - location:TERRAINHEIGHT), 1000)). IF slope < 20 {RETURN TRUE.} ELSE {RETURN FALSE.} } // ...and one for bearing difference. FUNCTION ANGLE_IS_OK { PARAMETER goal, option. SET angle TO ABS(goal:BEARING - option:BEARING). IF angle < 60 {RETURN TRUE.} ELSE {RETURN FALSE.} } // Next, the function iterates through the list of points and evaluates the conditions. // It picks the first point that matches both FUNCTION DECIDE_NEXT { PARAMETER goal, options. PRINT("Iterating through options.") AT (1,2). FOR o IN options { IF SLOPE_IS_SAFE(o) AND ANGLE_IS_OK(goal, o) { SET nextPoint TO LATLNG(o:LAT, o:LNG). RETURN nextPoint. } } } // Finally, it drives there using PID steering and throttle. // How do I do this?!? FUNCTION DRIVE { PARAMETER p. SET desiredSpd TO 5. SET pWT TO 0. SET iWT TO 0. SET wtVAL TO 0. SET pSteer TO 0. SET iSteer TO 0. SET dSteer TO 0. SET lastPSteer TO 0. SET loopT TO 0.01. SET loopEndT TO TIME:SECONDS. SET NORTHPOLE TO LATLNG(90,0). UNTIL p:DISTANCE < 10 { SET pWT TO desiredSpd - GROUNDSPEED. SET iWT TO MIN(1, MAX(-1, iWT + (pWT * loopT))). SET wtVAL TO pWT + iWT. SET pSteer TO (p:BEARING / 180). SET dSteer TO (pSteer - lastPSteer) / (loopEndT - loopT). SET steerVAL TO -0.5 * pSteer + 0.75 * dSteer. SET lastPSteer TO pSteer. LOCK WHEELTHROTTLE TO wtVAL. LOCK WHEELSTEER TO steerVAL. PRINT("Target heading: " + p:HEADING) AT (1,1). PRINT("Bearing to target: " + p:BEARING) AT (1,2). SET lastPSteer TO pSteer. SET loopT TO TIME:SECONDS - loopEndT. SET loopEndT TO TIME:SECONDS. } } UNTIL THERE_YET(goal) { BRAKES ON. WAIT 1. POPULATE(). WAIT 1. DECIDE_NEXT(goal, options). WAIT 1. CLEARSCREEN. BRAKES OFF. DRIVE(nextPoint). UNLOCK ALL. LOCK THROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 0.25. BRAKES ON. WAIT 1. UNLOCK ALL. } UNLOCK ALL. LOCK THROTTLE TO -1. WAIT UNTIL GROUNDSPEED < 0.25. BRAKES ON. SET SHIP:CONTROL:PILOTMAINTHROTTLE TO 0. UNLOCK ALL.
  19. Gah! I don't know what I did, but now it crashes KSP... time to start over... Can someone help me develop this? I need a kOS program that takes a LATLNG and iteratively navigates to it. Steps of the iteration:
  20. UPDATE: Found the bug! // Auto Nav // Takes a LATLNG() of a goal, and iteratively navigates to it. PARAMETER goal. FUNCTION POPULATE { SET pos TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG). SET a TO 360000/(2*CONSTANT:PI*BODY:RADIUS). // 10m in any cardinal direction SET b TO SIN(45)*a. SET oA TO LATLNG(pos:LAT + a, pos:LNG). // North SET oB TO LATLNG(pos:LAT + B, pos:LNG + b). // Northeast SET oC TO LATLNG(pos:LAT, pos:LNG + a). // East SET oD TO LATLNG(pos:LAT - b, pos:LNG + b). // Southeast SET oE TO LATLNG(pos:LAT - a, pos:LNG). // South SET oF TO LATLNG(pos:LAT - b, pos:LNG - b). // Southwest SET oG TO LATLNG(pos:LAT, pos:LNG - a). //West SET oH TO LATLNG(pos:LAT + b, pos:LNG - b). // Northwest SET options TO LIST(oA, oB, oC, oD, oE, oF, oG, oH). RETURN options. } FUNCTION SLOPE_IS_OK { PARAMETER point. SET location TO LATLNG(point:LAT, point:LNG). SET slope TO ABS(ARCTAN2((location:TERRAINHEIGHT - SHIP:ALTITUDE), 10)). IF slope < 11.25 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION ANGLE_IS_OK { PARAMETER point, goal. SET angle TO ABS(goal:BEARING - point:BEARING). IF angle < 45 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER options, goal. FOR o IN options { IF SLOPE_IS_OK(o) AND ANGLE_IS_OK(goal, o) { SET nextPoint TO LATLNG(o:LAT, o:LNG). RETURN nextPoint. BREAK. } ELSE { // Just keep swimming... } } } FUNCTION DRIVE { PARAMETER waypt. CLEARSCREEN. SET spd TO 10. SET hdg TO waypt:HEADING. SET loopT TO 0.01. SET loopEndT TO TIME:SECONDS. SET pWT TO 0. SET iWT TO 0. SET dWT TO 0. SET lastPWT TO 0. SET eSteer TO 0. SET dSteer TO 0. SET lastESteer TO 0. SET wtVal TO 0. SET NORTHPOLE TO LATLNG(90,0). SET runmode TO 0. IF waypt:DISTANCE < 5 { BRAKES ON. SET runmode TO -1. } UNTIL runmode = -1 { IF NORTHPOLE:BEARING <= 0 { set cHdg TO ABS(NORTHPOLE:BEARING). } ELSE { SET cHdg TO (180 - NORTHPOLE:BEARING) + 180. } IF runmode = 0 { SET pWT TO spd - GROUNDSPEED. SET iWT TO MIN(1, MAX(-1, iWT + (pWT * loopT))). SET dWT TO ((pWT - lastPWT) / (loopEndT - loopT)). SET wtVal TO MIN(1, MAX(-1, pWT + iWT + dWT)). SET eSteer TO (hdg - cHdg) / 180. SET dSteer TO ((eSteer - lastESteer)/(loopEndT - loopT)). SET steerVal TO -eSteer + dSteer. SET SHIP:CONTROL:WHEELTHROTTLE TO wtVal. SET SHIP:CONTROL:WHEELSTEER TO steerVal. SET lastPWT TO pWT. SET lastESteer TO eSteer. SET loopT TO TIME:SECONDS - loopEndT. SET loopEndT TO TIME:SECONDS. } PRINT("pWT: " + pWT) AT (2, 5). PRINT("iWT: " + iWT) AT (2, 6). PRINT("dWT: " + dWT) AT (2,7). PRINT("eSteer: " + eSteer) AT (2, 9). PRINT("steerVal: " + steerVal) AT (2,10). } } UNTIL goal:DISTANCE < 5 { POPULATE(). DECIDE_NEXT(options, goal). DRIVE(nextPoint). BRAKES ON. WAIT 5. BRAKES OFF. } BRAKES ON.
  21. Ok, fixed the driving-in-circles thing. Now it just drives backward and doesn't control the steering or throttle at all! I think the decision-making algorithm works, though... // Auto Nav // Takes a LATLNG() of a goal, and iteratively navigates to it. PARAMETER goal. GEAR OFF. LOCK THROTTLE TO 0. SAS OFF. RCS OFF. BRAKES ON. FUNCTION POPULATE { SET pos TO LATLNG(SHIP:GEOPOSITION:LAT, SHIP:GEOPOSITION:LNG). SET a TO (360 * 1000)/(2*CONSTANT:PI*BODY:RADIUS). // 10m in any cardinal direction SET b TO SIN(45)*a. SET oA TO LATLNG((pos:LAT + a), (pos:LNG)). // North SET oB TO LATLNG((pos:LAT + b), (pos:LNG + b)). // Northeast SET oC TO LATLNG((pos:LAT), (pos:LNG + a)). // East SET oD TO LATLNG((pos:LAT - b), (pos:LNG + b)). // Southeast SET oE TO LATLNG((pos:LAT - a), (pos:LNG)). // South SET oF TO LATLNG((pos:LAT - b), (pos:LNG - b)). // Southwest SET oG TO LATLNG((pos:LAT), (pos:LNG - a)). //West SET oH TO LATLNG((pos:LAT + b), (pos:LNG - b)). // Northwest SET options TO LIST(oA, oB, oC, oD, oE, oF, oG, oH). RETURN options. } FUNCTION SLOPE_IS_OK { PARAMETER point. SET location TO LATLNG(point:LAT, point:LNG). SET slope TO ABS(ARCTAN2((location:TERRAINHEIGHT - SHIP:ALTITUDE), 10)). IF slope < 11.25 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION ANGLE_IS_OK { PARAMETER point, goal. SET angle TO ABS(goal:BEARING - point:BEARING). IF angle < 45 { RETURN TRUE. } ELSE { RETURN FALSE. } } FUNCTION DECIDE_NEXT { PARAMETER options, goal. FOR o IN options { IF SLOPE_IS_OK(o) AND ANGLE_IS_OK(goal, o) { SET nextPoint TO LATLNG(o:LAT, o:LNG). RETURN nextPoint. BREAK. } ELSE { // Just keep swimming... } } } FUNCTION DRIVE { PARAMETER waypt. SET spd TO 5. SET loopT TO 0.01. SET loopEndT TO TIME:SECONDS. SET eWT TO 0. SET iWT TO 0. SET wtVAL TO 0. SET NORTHPOLE TO LATLNG(90,0). SET eSteer TO 0. LOCK turnLimit TO MIN(1, 1.5/GROUNDSPEED). UNTIL waypt:DISTANCE < 2.5 { IF NORTHPOLE:BEARING <= 0 { SET cHead TO ABS(NORTHPOLE:BEARING). } ELSE { SET cHead TO (180 - NORTHPOLE:BEARING) + 180. } SET wtVAL TO MIN(1, MAX(-1, (-eWT + iWT))). SET eSteer TO (hdg - cHead). IF eSteer > 180 { //Make sure the headings make sense SET eSteer TO eSteer - 360. } ELSE IF eSteer < -180 { SET eSteer TO eSteer + 360. } IF spd - GROUNDSPEED > spd + spd * 0.1 // We're too fast! { LOCK THROTTLE TO -1. } ELSE IF GROUNDSPEED < spd - spd * 0.1 { LOCK THROTTLE TO 1. } SET desiredSteering TO -eSteer / 10. set kturn to min(1, max( -1, desiredSteering)). SET SHIP:CONTROL:WHEELSTEER TO kTurn. PRINT("Distance to waypoint: " + ROUND(waypt:DISTANCE, 2)) AT (2, 21). PRINT("Wheel Throttle: " + wtVAL) AT (2,22). SET loopT TO TIME:SECONDS - loopEndT. SET loopEndT TO TIME:SECONDS. } } UNTIL goal:DISTANCE < 50 { IF SHIP:SENSORS:LIGHT < 0.75 { LIGHTS ON. } ELSE { LIGHTS OFF. } CLEARSCREEN. POPULATE(). PRINT("=====Autonavigation v1.0=====") AT (0,2). PRINT("Populating options...") AT (2,5). WAIT 1. PRINT("Options: " + ROUND(oA:LAT, 5) + ", " + ROUND(oA:LNG, 2)) AT (2,10). PRINT(ROUND(oB:LAT, 5) + ", " + ROUND(oB:LNG, 2)) AT (11,11). PRINT(ROUND(oC:LAT, 5) + ", " + ROUND(oC:LNG, 2)) AT (11,12). PRINT(ROUND(oD:LAT, 5) + ", " + ROUND(oD:LNG, 2)) AT (11,13). PRINT(ROUND(oE:LAT, 5) + ", " + ROUND(oE:LNG, 2)) AT (11,14). PRINT(ROUND(oF:LAT, 5) + ", " + ROUND(oF:LNG, 2)) AT (11,15). PRINT(ROUND(oG:LAT, 5) + ", " + ROUND(oG:LNG, 2)) AT (11,16). PRINT(ROUND(oH:LAT, 5) + ", " + ROUND(oH:LNG, 2)) AT (11,17). WAIT 1. DECIDE_NEXT(options, goal). PRINT("Driving to " + "(" + ROUND(nextPoint:LAT,5) + ", " + ROUND(nextPoint:LNG, 5) + ")") AT (2,20). BRAKES OFF. IF nextPoint:BEARING > 20 { LOCK WHEELSTEER TO nextPoint. LOCK WHEELTHROTTLE TO -0.5. WAIT UNTIL nextPoint:BEARING < 30. } DRIVE(nextPoint). BRAKES ON. WAIT 5. BRAKES OFF. } BRAKES ON.
×
×
  • Create New...