Jump to content

[KSP 1.12.x] kOS v1.4.0.0: kOS Scriptable Autopilot System


Dunbaratu

Recommended Posts

26 minutes ago, maculator said:

Thhe original script is running right now on a plane flying arround kerbin, the scrip in 0:/boot is altered and I wanted to copy the unaltered version to a backup, just in case.

So go to that craft, kill the boot script when it fires up, then enter this in the terminal?

COPYPATH("1:/boot/my_script.ks","0:/boot/my_script.backup.ks").

It's possible you accidentally created a folder named "1" on the archive at some point.

PS. It can be good practice to use some kind of code versioning/change management set-up. I put my scripts on GitHub so I can track changes and keep online backups.

Edited by ElWanderer
Link to comment
Share on other sites

I'm trying to get the velocity vector at a manouvre node, which I was expecting to be

SET NodeVel to VELOCITYAT(SHIP , TIME + MyNode:ETA).

However if I VECDRAW it on screen it looks to be 70 or 80 degrees out and a bit shorted than I'd expect (I didn't think to check the magnitude at the time and on a different machine now).  A bit of Googling suggested there was an issue with the frame of reference, but that was an old Reddit post and I can't find anything recent about it so I assume I'm using it incorrectly.  Any advice?

Link to comment
Share on other sites

On 2018-03-31 at 11:02 PM, ElWanderer said:

I looked up a previous solution I've given for your kind of question (https://www.reddit.com/r/Kos/comments/66pdll/question_about_steering_and_vectors/). It does involve even more vector manipulation than my previous example, I'm afraid:

// VELOCITY:SURFACE should be the same as SRFPROGRADE:VECTOR
LOCK horizon TO VXCL(UP:VECTOR,VELOCITY:SURFACE). 
LOCK STEERING TO 
    LOOKDIRUP(ANGLEAXIS(pitchAngle(),
                        VCRS(horizon,BODY:POSITION))*horizon,
              UP:VECTOR).

That pitches up (or possibly down), by whatever number the pitchAngle() function returns. The VCRS (vector cross) of the horizon and a vector pointed at the centre of the planet (straight down, I guess, should be equivalent to -UP:VECTOR) returns a vector that is at 90 degrees to both (pointed at the horizon to starboard), meaning it can be used as an axis to rotate our steering vector around, to pitch up or down.

If you don't mind me asking, is there an easier way to do this? Something like combining lookdirup(srfretrograde:vector, up:vector) with angleaxis(pitch, facing:starvector)?

Link to comment
Share on other sites

On ‎31‎/‎03‎/‎2018 at 8:05 PM, maculator said:

I got a question, if somebody wants to push me in the right direction (literally).

I got my small script to hold my planes altitude and direction:

  Hide contents


clearscreen.
core:part:getmodule("kOSProcessor"):doevent("Open Terminal").
set terminal:charheight to 18.
set terminal:width to 30.
set terminal:height to 14.
set terminal:brightness to 1.

if alt:radar < 10 {
	print "we're landed... bye.".
	wait 2.
	shutdown.
} else {
	sas off.
	set alt_t to ship:altitude.
	print "target altitude: " + round(alt_t).
	set WhyDoesItHaveToBeThatComplicated to ship:bearing * -1.
	set angle to 0.
	lock angle2 to angle.
	print "heading " + round(WhyDoesItHaveToBeThatComplicated).
	lock steering to Heading(WhyDoesItHaveToBeThatComplicated, angle).
	until false {
		if ship:altitude > (alt_t + 100) {
			set angle to angle - 1.
			print "down " + angle.
			lock steering to heading(WhyDoesItHaveToBeThatComplicated, angle2).
		}
		if ship:altitude < (alt_t - 100) {
			set angle to angle + 1.
			print "up " + angle.
			lock steering to heading(WhyDoesItHaveToBeThatComplicated, angle2).
		}
		if ship:altitude > (alt_t - 100) and ship:altitude < (alt_t + 100) {
			print "hold " + angle.
			lock steering to heading(WhyDoesItHaveToBeThatComplicated, angle2).
		}
		lock steering to heading(WhyDoesItHaveToBeThatComplicated, angle2).
		print angle.
		print "wait".
		wait 10.
	}
}

 

And I really would like it to hold a sort of "global" direction, unaffected by the compass.

Right now it goes like this:


lock steering to Heading(WhyDoesItHaveToBeThatComplicated, angle2).

Is there a way to tell it to just hold the direction unaffected by compass?

I red through the documentation but that stuff is a bit much for me :S

Thank you!

Not sure I completely understand what you're trying to do, as direction is what the compass gives you, but a couple of thoughts assuming you're just trying to fly straight and levelish and your issue is the pitch changes.

  • Once you've locked the steering, you don't need to relock it in each IF statement, you can just re-set Angle2 and it will adjust to that elevation.
  • You might want to take a look at PID loops, with your current setup as soon as you go over/under you limits you make a change and wait to see it's effect, with a PID loop it looks at how quickly your altitude is changing as well.  Not tried it on aircraft but on a hovering VTOL a PID loop got me stable at my target altitude in just a couple of oscillations.

If you mean you want to keep heading the same direction when overflying the poles then that's a more complex problem.

Edited by RizzoTheRat
Link to comment
Share on other sites

1 hour ago, Black-Two- said:

If you don't mind me asking, is there an easier way to do this? Something like combining lookdirup(srfretrograde:vector, up:vector) with angleaxis(pitch, facing:starvector)?

Depends what you're trying to achieve. Do you want a certain pitch relative to the horizon, or to the pro/retrograde vector?

Using the starboard facing vector as an axis of rotation for pitch will only work when your pro/retrograde vector and facing forevector are aligned (i.e. along the same compass bearing). If they're not aligned, you'd get increasingly weird results.

Link to comment
Share on other sites

26 minutes ago, ElWanderer said:

Depends what you're trying to achieve. Do you want a certain pitch relative to the horizon, or to the pro/retrograde vector?

Using the starboard facing vector as an axis of rotation for pitch will only work when your pro/retrograde vector and facing forevector are aligned (i.e. along the same compass bearing). If they're not aligned, you'd get increasingly weird results.

I want to use it for a constant altitude vacuum landing, so it should be alright, right?

Link to comment
Share on other sites

12 minutes ago, Black-Two- said:

I want to use it for a constant altitude vacuum landing, so it should be alright, right?

Hmmm. As you decelerate horizontally, your retrograde vector will want to pitch up... if you can control your vertical velocity (i.e. keep it at zero) then it'll counter that and keep the retrograde horizontal, so the assumptions should hold true. If you lose control, it'll rapidly become an incorrect solution, I fear. It sounds worryingly circular...

Personally, I switched to a controlled altitude descent a while back - I no longer zero out v-speed but let it drop such that my final suicide burn will be very near the ground (I have to scan ahead to work out the minimum safe v-speed). That does require knowing at what angle above the horizon to pitch.

Edited by ElWanderer
Link to comment
Share on other sites

2 hours ago, ElWanderer said:

Hmmm. As you decelerate horizontally, your retrograde vector will want to pitch up... if you can control your vertical velocity (i.e. keep it at zero) then it'll counter that and keep the retrograde horizontal, so the assumptions should hold true. If you lose control, it'll rapidly become an incorrect solution, I fear. It sounds worryingly circular...

Personally, I switched to a controlled altitude descent a while back - I no longer zero out v-speed but let it drop such that my final suicide burn will be very near the ground (I have to scan ahead to work out the minimum safe v-speed). That does require knowing at what angle above the horizon to pitch.

Fair enough, but just to clarify, my original was (supposed to be) whether there's an easier way to combine lookdirup with angleaxis than the one you posted :)

Link to comment
Share on other sites

15 minutes ago, Black-Two- said:

Fair enough, but just to clarify, my original was (supposed to be) whether there's an easier way to combine lookdirup with angleaxis than the one you posted :)

Well, angleaxis is to rotate the steering vector, the lookdirup I wrote was to keep a plane the right way up. To keep a rocket from rotating unnecessarily, I'd put a FACING:TOPVECTOR as the second lookdirup argument instead.

As to the general idea of doing it more easily - there probably are shorter solutions if you know how to rotate directions. I do not, so tend to use angleaxis - the idea of rotating a vector around the axis formed of a second one is something my brain *can* grasp!

Link to comment
Share on other sites

@RizzoTheRat Thanks. I didn't know I don't have to lock the steering each loop. PID loop is where I'm heading, but I wanted to do it step by step on my wn as far as I can. I now added the first "damper" to the script that lowers the angle back a tick when passing the hold part.

The script allready works as I want it to: toggle cpu locks the altitude and heading and holds it for me. Now I'm just for fun trying to make it a pid loop. But step by step.

Link to comment
Share on other sites

10 hours ago, maculator said:

@RizzoTheRat Thanks. I didn't know I don't have to lock the steering each loop. PID loop is where I'm heading, but I wanted to do it step by step on my wn as far as I can. I now added the first "damper" to the script that lowers the angle back a tick when passing the hold part.

The script allready works as I want it to: toggle cpu locks the altitude and heading and holds it for me. Now I'm just for fun trying to make it a pid loop. But step by step.

Yeah, PID loops work well but I'm with you, it's nice to try and work your way up to it rather than plug in a ready made solution.  With my hovering VTOL I found a PID loop did a great job of controlling the throttle to hold an altitude, but setting the throttle to give an upward acceleration of a little bit more or less than gravity if it moved outside my altitude limits (so similar approach to yours) worked well and was actually coped with changing the thrust angle better.

I've not tried with atmospheric craft but for rockets I've found most things can be solved by working out the required velocity vector, and then the acceleration required to hit that velocity.  Aeroplanes are a bit more complicated though as you don't know the coefficients of lift or drag without measuring them, but they change with speed, so I'd expect PID loops to be the way forward. 

As I understand it anything that's Locked gets checked every cycle, where a Set only happens the once, so I tend to Lock the throttle and Steering to variables right at the start, and then just set those variables within my loops.

Link to comment
Share on other sites

23 hours ago, RizzoTheRat said:

I'm trying to get the velocity vector at a manouvre node, which I was expecting to be

SET NodeVel to VELOCITYAT(SHIP , TIME + MyNode:ETA).

However if I VECDRAW it on screen it looks to be 70 or 80 degrees out and a bit shorted than I'd expect (I didn't think to check the magnitude at the time and on a different machine now).  A bit of Googling suggested there was an issue with the frame of reference, but that was an old Reddit post and I can't find anything recent about it so I assume I'm using it incorrectly.  Any advice?

The reference frame below 100 km at Kerbin is rotating, and inertial above. That means, if you set NodeVel at one moment when ship is below 100 km and plot it some significant time later, the vector would be off because coordinate axes have rotated. The workaround I use is to express vectors in a coordinate frame where X axis is SolarPrimeVector, Z axis is V(0, 1, 0) (guaranteed to be the same direction in game) and Y axis is vcrs(SolarPrimeVector, V(0, 1, 0)).

Respective functions to convert a vector to and from that reference frame:

function toIRF {
// changes to inertial right-handed coordinate system where ix = SPV, iy = vcrs(SPV, V(0, 1, 0)), iz = V(0, 1, 0)
  parameter oldVec, SPV to SolarPrimeVector.
  return V( oldVec:x * SPV:x + oldVec:z * SPV:z, oldVec:z * SPV:x - oldVec:x * SPV:z, oldVec:y).
}

function fromIRF {
// changes from inertial right-handed coordinate system where ix = SPV, iy = vcrs(SPV, V(0, 1, 0)), iz = V(0, 1, 0)
  parameter irfVec, SPV to SolarPrimeVector.
  return V( irfVec:x * SPV:x - irfVec:y * SPV:z, irfVec:z, irfVec:x * SPV:z + irfVec:y * SPV:x ).
}

With this, you'll need to

SET NodeVel to toIRF(VELOCITYAT(SHIP , TIME + MyNode:ETA):ORBIT).

to have the velocity vector in an inertial frame. To plot it, you need to convert that vector back to the standard reference frame:

SET NodeVelDraw TO VECDRAW().
SET NodeVelDraw:SHOW TO TRUE.
SET NodeVelDraw:STARTUPDATER TO {return POSITIONAT(ship, Time + MyNode:ETA).}.
SET NodeVelDraw:VECUPDATER TO {return fromIRF(NodeVel).}.

 

Link to comment
Share on other sites

Thanks,  that's going to take a bit of time to get my head around.

I'm now wondering if it'd be simpler just to loft everything over 100km, but that might make my SSTO returns a bit trickier :-D 

 

ETA:

The more I think about it the more of a pain in the cheeks it is.  My intention is to add the node DeltaV to ships velocity at that node, and then burn on an acceleration vector to get to that velocity.  This allows me to reuse a chunk of code from my circularization burn, which aims to hit the velocity vector required for a circular orbit at the ships current altitude, which I would then put in to a function.  However in order to use the velocity at the node I'd have to convert everything in to this other co-ordinate system, which is a lot of extra calculations.

@Pand5461, Is SPV a recognised variable or do you have define it?  It gets mentioned in the documentation but I've not seen anything on how to reference it.

Presumably the Z Axis V(0,1,0) is straight up, normal to the plane of the solar system?  In which case what happens when your orbiting a body on an inclined plane like Minmus?  Will V(0,1,0) on Minmus be different to V(0,1,0) around the sun? 

Any particular reason why you go with a Right handed co-ordinate system rather than sticking with Left?  I know Right makes more sense but I think I'd probably confuse myself switching between left and right.

Edited by RizzoTheRat
Link to comment
Share on other sites

9 hours ago, RizzoTheRat said:

As I understand it anything that's Locked gets checked every cycle

That's a common misconception, and it's easy to see why so many users think this, because it *is* true of the first locks they usually use, which are throttle and steering.  But it's not true of *all* locks in general.  Throttle and steering are actually special exceptions to the general case (I will cover this in the next paragraph below).  And a lot of this is kOS's own fault, really.  When you are presented with the exception case first before learning the general case, it often muddies your understanding of what's happening.  None of the current devs are happy about this, but "lock throttle" and "lock steering" have such a long history (from the first ever release from Kevin Nivekk) that it's a very scary thing now to contemplate changing how it works and thus breaking *every single script* that currently exists or ever has been written in the past, including every example you are likely to find on a google search.)

Locks *in general* don't get recalculated once per cycle.  They get recalculated on the fly only just at the moment when their value is being queried by some other part of your program.  If you *wanted* to query them once per cycle, you could with something like this trigger:
 

LOCK myLock to (some_expression_here).

// then, later:
WHEN TRUE THEN { set myVariable to myLock. return true. }

And it would then re-run some_expression_here once per cycle as it keeps re-executing the trigger.

All that is happening in the case of the locks named "throttle", "steering", "wheelsteering" and "wheelthrottle", is the secret hidden fact that the kOS compiler is inserting code into your program that in fact does do something almost exactly like that.  It would look a little bit like this if it was written in kerboscript:

WHEN TRUE THEN { set kOSInternalThrottle to throttle. return true.}
WHEN TRUE THEN { set kOSInternalSteering to steering. return true.}
WHEN TRUE THEN { set kOSInternalWheelThrottle to wheelthrottle. return true.}
WHEN TRUE THEN { set kOSInternalWheelSteering to wheelsteering. return true.}

(That's not exactly identical to what kOS is doing internally, but I can't quite express in kerboscript what kOS is inserting into your program, because what kOS is inserting into your program is written in "kOS assembly language" so to speak, and doesn't quite have an exact kerboscript equivalent.  But this is pretty close.)

Link to comment
Share on other sites

10 hours ago, ElWanderer said:

Are the versions compatible, though? Last I heard, v2 Trajectories and kOS aren't compatible yet:

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

It's being worked on.  I'm in contact with one of the devs for Trajectories:

https://github.com/KSP-KOS/KOS/pull/2220#issuecomment-378620584

Link to comment
Share on other sites

how can you please receive data in one until please ?

	LOCK THROTTLE TO 1.0.   
	WHEN MAXTHRUST = 0 THEN {
    STAGE.
    PRESERVE.
}.
	LOCK STEERING TO UP.
	UNTIL SHIP:ALTITUDE > 9000
{
  PRINT "Altitude :".
  PRINT ROUND(SHIP:ALTITUDE,0).
  PRINT "Apoapsis:".
  PRINT ROUND(SHIP:APOAPSIS,0).
  PRINT "Periapsis:".
  PRINT ROUND(SHIP:PERIAPSIS,0).
  PRINT "Velocity:".
  PRINT ROUND(SHIP:VELOCITY:SURFACE:MAG,1).
  WAIT 0.1.
......how can you please receive data in one until?
}.
	LOCK THROTTLE TO 0.
	SET SHIP:CONTROL:PILOTMAINTHROTTLE TO 0.
	

 

 

greeting.
 

Link to comment
Share on other sites

1 hour ago, funkheld said:

how can you please receive data in one until please ?

The lines of code in your Until will run every 0.1 seconds until it hits 9000m so it is receiving data as it goes if that's what you mean.  If you mean how do you trip out of the loop if something else happens, you could have multiple criteria to drop you out of the loop.

Incidentally you can print to a specific point on the screen, which will be overwritten each time rather than it all scrolling off the screen, I find it makes for much easier reading of outputs, but bear in mind if the programme crashes the error report will often overwrite it as it will start from the cursor point.

eg.

Until ship:Altitude>9000 or OtherParameter=True{
	Print "Altitude : " + Round(Ship:Altitude,1) + " Meters  " at (0,20).
	Print "Apoapsis : " + Round(Ship:apoapsis,1) + " Meters  " at (0,21).
	Print "Speed    : " + Round(Ship:velocity:mag,1) + " m/s  " at (0,22).
}

 

Edited by RizzoTheRat
Link to comment
Share on other sites

I wanted a command from tcp to kos in a loop and work off in the loop

------------------------------

until false {
......I wanted a command from tcp to kos in a loop and work off in the loop
}

 

greeting

Edited by funkheld
Link to comment
Share on other sites

17 hours ago, Steven Mading said:

Locks *in general* don't get recalculated once per cycle.  They get recalculated on the fly only just at the moment when their value is being queried by some other part of your program.

 

Not to be rude, but does it make any practical difference?

Link to comment
Share on other sites

On 04.04.2018 at 11:56 AM, RizzoTheRat said:

My intention is to add the node DeltaV to ships velocity at that node, and then burn on an acceleration vector to get to that velocity. 

There's an example script for that that works like a charm in most cases: https://ksp-kos.github.io/KOS/tutorials/exenode.html

On other questions:

On 04.04.2018 at 11:56 AM, RizzoTheRat said:

Is SPV a recognised variable or do you have define it?  It gets mentioned in the documentation but I've not seen anything on how to reference it.

Presumably the Z Axis V(0,1,0) is straight up, normal to the plane of the solar system?  In which case what happens when your orbiting a body on an inclined plane like Minmus?  Will V(0,1,0) on Minmus be different to V(0,1,0) around the sun? 

Any particular reason why you go with a Right handed co-ordinate system rather than sticking with Left?  I know Right makes more sense but I think I'd probably confuse myself switching between left and right.

SPV is not a pre-defined variable but hey, I can name a parameter of a function whatever I want. It's an optional parameter, so if none provided it will take SolarPrimeVector which is a pre-defined variable.

V(0,1,0) always points to the "Celestial north pole" of Kerbin, and all bodies in stock game or any planet pack (except when Principia is installed) have collinear axes of rotation. That's how KSP's engine is designed. Orbital planes differ, however, so all bodies have axial tilt exactly equal to the inclination of their orbits to the in-game XZ plane. The reason why ecliptics in RSS has such weird inclination is to mimic real-life Earth's axial tilt to the ecliptic plane - RSS devs could not tilt Earth axis, so they tilted the orbital plane.

As for using right-hand coordinates, I used those functions for reproducing Shuttle PEG guidance algorithm, and all the vector products in the papers I took it from are in right-handed system. Converting vectors from kOS to a right-handed frame required less mental acrobatics than figuring out the correct order of operands every time I had to code an equation with a vector product.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...