Jump to content

[1.3] kOS Scriptable Autopilot System v1.1.3.0


erendrake

Recommended Posts

Is there anyway to add the terminal system so that you can telnet into the game and do a loadship("shipname"); and have it load up a ship that has a kOS module on it and then once it is loaded either a boot script takes over and starts going or you can from the telnet switch to the ship's CPU and begin doing whatever?

Link to comment
Share on other sites

2 hours ago, Lookerksy said:

When I try to use IRServo:MoveTo(), I got a Error saying:
"Object reference not set to an instance of an object"
Could anyone tell me how shall I correct it?

[...]

PS: KSP 1.1.2 64x + kOS 0.20.1 + IR-2.0.2-Final-Full

kOS has a pending request to update IR to use the API for 2.0+.  It will be included in the next kOS update, which we hope to do soon.

Link to comment
Share on other sites

20 hours ago, MAFman said:

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.


// 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.

Can you provide additional details.  When you say that it doesn't drive to the "waypoint", do you mean it doesn't drive at all, it drives the wrong way, it goes in a circle, or it flys to the Mun instead (OK, so that last one isn't very likely... :P).  Have you tried using `print` statements to determine what the outputs of your PID's are doing? I know you said the selection code works, but have you verified using vector draws that you have the actual correct position not just a valid point?

EDIT: I forgot to include my obligatory remark about lock: don't repeatedly call locks within a loop.  A lock by definition will automatically update itself, and specifically within steering locks you add extra overhead because it forces additional calls to the function `toggleflybywire` (which you should not call manually btw).  If you want to update your lock from within a loop you should instead lock to a variable, and then set the value of that variable from inside your loop.

Edited by hvacengi
Link to comment
Share on other sites

3 hours ago, LostS77 said:

Is there anyway to add the terminal system so that you can telnet into the game and do a loadship("shipname"); and have it load up a ship that has a kOS module on it and then once it is loaded either a boot script takes over and starts going or you can from the telnet switch to the ship's CPU and begin doing whatever?

Some one is working on that, but it has proven to have some complications.  You can find it both at the issue and the pull request:

https://github.com/KSP-KOS/KOS/issues/1596

https://github.com/KSP-KOS/KOS/pull/1628

Link to comment
Share on other sites

On 6/17/2016 at 10:29 PM, jwbrase said:

Is there any way of setting up a trigger on something like a keystroke or a joystick button?

Directly, no, but you can always look at the actions that said keystroke or botton does.   I've done WAIT UNTIL ship:control:pilotyaw<>0. before to pause until I hit W.

You probably don't want to use pilot controls in your case; other options include waiting for SAS or an action group toggle to no longer equal its previous value.

For Joystick problems, you might want the advanced fly by wire (I think) mod.

Link to comment
Share on other sites

On 6/17/2016 at 10:04 PM, luizopiloto said:

Why is there no BEEP. command? :(

While it is not written as a built in function, printing the ascii "BEL" character will result in a "beep".  I have a wrapper function written like this:

function beep {
	print char(7).
}

Sorry about the delay in response.  Apparently I missed the post.

Link to comment
Share on other sites

45 minutes ago, hvacengi said:

While it is not written as a built in function, printing the ascii "BEL" character will result in a "beep".  I have a wrapper function written like this:


function beep {
	print char(7).
}

Sorry about the delay in response.  Apparently I missed the post.

No worries, you have also missed Stevens post :)

To much staring in code, I guess. Waiting for that IR code merge to try some stuff with it. Thanks for all effort on this mod so far.

Link to comment
Share on other sites

7 minutes ago, kcs123 said:

No worries, you have also missed Stevens post :)

To much staring in code, I guess. Waiting for that IR code merge to try some stuff with it. Thanks for all effort on this mod so far.

Huh... yeah. Maybe I need to increase my ADHD med dosage.  Working on the update, I have 2 things on my docket before getting to the IR pull request, but we're working towards a release since we've added a number of features that got skipped in the last two releases.

Edited by hvacengi
Link to comment
Share on other sites

13 minutes ago, hvacengi said:

Huh... yeah. Maybe I need to increase my ADHD med dosage.  Working on the update, I have 2 things on my docket before getting to the IR pull request, but we're working towards a release since we've added a number of features that got skipped in the last two releases.

Take your time, there probably will be some time until other moders catch up with 1.1.3. release, so it will be some time that myself and plenty of other people will stick to previous release until then.

Link to comment
Share on other sites

On 6/21/2016 at 0:30 PM, hvacengi said:

Can you provide additional details.  When you say that it doesn't drive to the "waypoint", do you mean it doesn't drive at all, it drives the wrong way, it goes in a circle, or it flys to the Mun instead (OK, so that last one isn't very likely... :P).  Have you tried using `print` statements to determine what the outputs of your PID's are doing? I know you said the selection code works, but have you verified using vector draws that you have the actual correct position not just a valid point?

EDIT: I forgot to include my obligatory remark about lock: don't repeatedly call locks within a loop.  A lock by definition will automatically update itself, and specifically within steering locks you add extra overhead because it forces additional calls to the function `toggleflybywire` (which you should not call manually btw).  If you want to update your lock from within a loop you should instead lock to a variable, and then set the value of that variable from inside your loop.

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.

 

Link to comment
Share on other sites

11 hours ago, MAFman said:

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".

Without having the error log I can't comment directly.  But that message is usually shown when you have naming conflicts between functions and variables, or you haven't declared a function.  My best guess is that you have an issue due to calling `arrived(goal)` and `arrived(point)` while I don't see any definition for a function or delegate named `arrived`.

Link to comment
Share on other sites

@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).

Edited by MAFman
Code was incomplete
Link to comment
Share on other sites

On 24.06.2016. at 9:30 PM, MAFman said:

Can you give me any feedback as to how to get this to work?

I'm not expert when come to kOS, bit this few lines looks suspisious to me:

On 24.06.2016. at 9:30 PM, MAFman said:

GLOBAL v IS SHIP:ALTITUDE.

GLOBAL r IS BODY:RADIUS.

Both variable names, "V" and "R" are also used as keywords in kOS. Example, from kOS documentation:

set myVec to V(0,90,0).
lock steering to UP + R(20,0,0).

That might cause some undesired conflict. I haven't checked the rest of your code, there might be some other oversight somewhere.

Link to comment
Share on other sites

19 hours ago, MAFman said:

Where would I find the error log for kOS? Do I need to change any settings?

It's just the standard KSP log file that comes from Unity - the sample place where everything else in the game goes.  For some inexplicable reason I just do not understand at all, Unity puts the standard log file under different names in different places on different OS's (even though it doesn't have to for any real OS reasons, and it claims the whole point of Unity is to be cross platform).

Here's where to find it depending on your OS:

  • Windows: (where-ever-your-KSP-is-Installed)\KSP_x64\KSP_x64_DATA\output_log.txt , if running in 64-bit mode.  (remove the "_x64" parts if you run in 32-bit mode).
  • Mac OSX: ~/Library/Logs/Unity/Player.log
  • Linux: ~/.config/unity3d/Squad/Kerbal Space Program/Player.log

(There's no reason the Windows version couldn't also have had it in the user's own home folder like the Unixes do, but for some weird reason, it doesn't.  And for some weird reason it uses a different filename ("output_log.txt" vs "Player.log").)

 

Link to comment
Share on other sites

6 hours ago, kcs123 said:

I'm not expert when come to kOS, bit this few lines looks suspisious to me:

Both variable names, "V" and "R" are also used as keywords in kOS. Example, from kOS documentation:

set myVec to V(0,90,0).
lock steering to UP + R(20,0,0).

That might cause some undesired conflict. I haven't checked the rest of your code, there might be some other oversight somewhere.

I've successfully used R and V as variable names without issue.  This is a good thing, since they're the conventional mathematical terms for position and velocity vectors.  I have no idea what would happen if you assigned a delegate to them though.

@MAFman:

On 6/24/2016 at 8:49 AM, hvacengi said:

Without having the error log I can't comment directly.  But that message is usually shown when you have naming conflicts between functions and variables, or you haven't declared a function.  My best guess is that you have an issue due to calling `arrived(goal)` and `arrived(point)` while I don't see any definition for a function or delegate named `arrived`.

This appears to still be the case in your current version.  Also:

On 6/24/2016 at 0:30 PM, MAFman said:

FUNCTION POPULATE
{
	// [...]
	SET a TO LATLNG(SHIP:GEOPOSITION:LAT + off_90, SHIP:GEOPOSITION:LNG). // North
	// [...]
	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.
}

 

It's not necessary to use all the intermediate variables here; you can save some space (and IPU) by just constructing the LIST() all-in-one-go.  (You could also save some typing by assigning ship:geoposition to a variable).

FUNCTION POPULATE
{
	RETURN LIST(
		LATLNG(SHIP:GEOPOSITION:LAT + off_90, SHIP:GEOPOSITION:LNG), // North
		// [...]
		LATLNG(SHIP:GEOPOSITION:LAT + off_675, SHIP:GEOPOSITION:LNG - off_225)
	).
}

(It's perfectly legal to have a statement take multiple lines)

Link to comment
Share on other sites

On 6/23/2016 at 8:32 PM, Razorfang said:

Has anyone had issues with NRE spam when trying to adjust timewarp? I know other mods are having issues since 1.1.3, and I wonder if this one has the same problem.

I had a similar problem from RT that I resolved yesterday by upgrading ContractConfigurator and I think Waypoint Manager.

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

2 hours ago, superdavekerman said:

I had a similar problem from RT that I resolved yesterday by upgrading ContractConfigurator and I think Waypoint Manager.

It's a known bug - 1.1.3 altered the arguments to the warp function so it needs 1 more than it used to.  (Ironically, in the source code form, it doesn't *look* like it needs one more, because it's a defaulted argument, but the way defaulted arguments work in pre-compiled languages like C#, the caller needs to be recompiled to supply the default arg even though the source code looks no different.  Code compiled before the default argument was in the method's definition doesn't end up populating the default arg.)

The problem is that 1.1.3 came right when the development code was in a state of flux.  It's not easy to *just* release one change and one change only to fix that problem  There's other stuff tied up in there that isn't ready yet.

 

Link to comment
Share on other sites

Well, I encountered another issue. It is related to IsNull checking feature. I didn't found any info is it already available in kOS or not.

I got this in my code:

set CraftMaxThrust to SHIP:AVAILABLETHRUST.

It calculate everything fine with "CraftMaxThrust variable as long as craft have fuel. Once it runs out of fuel, that variable become NaN.
Obviously it throws error in any calculations later on with NaN.

Not a big deal, but I would like to put safe checks in script, if craft runs out of fuel to prevent kOS throwing error.
Is there already a way to use IsNull function in kOS ?

Link to comment
Share on other sites

54 minutes ago, kcs123 said:

Well, I encountered another issue. It is related to IsNull checking feature. I didn't found any info is it already available in kOS or not.

I got this in my code:


set CraftMaxThrust to SHIP:AVAILABLETHRUST.

It calculate everything fine with "CraftMaxThrust variable as long as craft have fuel. Once it runs out of fuel, that variable become NaN.
Obviously it throws error in any calculations later on with NaN.

Not a big deal, but I would like to put safe checks in script, if craft runs out of fuel to prevent kOS throwing error.
Is there already a way to use IsNull function in kOS ?

Could you please post an issue for us on github so that we can make sure it's on our checklist for the next release?

Link to comment
Share on other sites

1 hour ago, hvacengi said:

Could you please post an issue for us on github so that we can make sure it's on our checklist for the next release?

I don't have github account, so it will take some time to create one. When I create account I would probably use it for other stuff than KSP, so I need to get more familiar with github first.

Anyway, I was able to sort out my issue, it was negative number uder SQRT function. It works fine as long as TWR is greater than 1, but it fails when it is not.
Regardless, that IsNull feature would be usefull for idiotproof scripts. This line of code was actualy gave error:

set FallTime to -1 * ship:verticalspeed/(2*(((CraftMaxThrust - CraftWeight) / SHIP:MASS) - Body_g))  + SQRT(ship:verticalspeed^2 +4 * (((CraftMaxThrust - CraftWeight) / SHIP:MASS) - Body_g)*FallAltitude )/(2*(((CraftMaxThrust - CraftWeight) / SHIP:MASS) - Body_g)).

And other variables that were set before that line were:

set Body_g to SHIP:BODY:MU / (SHIP:BODY:RADIUS+altitude)^2.
set CraftWeight to SHIP:MASS * Body_g.
set CraftMaxThrust to SHIP:AVAILABLETHRUST.
  
local FallTime is 0.
// additional +20m for safety, alt:radar is measured from COM that is much higher of safety altitude
local FallAltitude is alt:radar - HoverAlt.

As you probably guessed, it is part of suicide power landing script that I currently try to improve with new built in pidloop instead of old library and slowing down ground speed in more efficient way. Impreovement was necessary due to few rocket tip over on landing due to too high ground speed. Yep, even 1 m/s of ground speed can tip over rocket on Mun, especialy if terain slope is uneven.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...