Jump to content

kOS Scriptable Autopilot System 0.9


KevinLaity

Recommended Posts

Using check's lat/lon trick to figure out surface velocity bearing I've made a suicide burn landing program. Great mod OP, its pretty fun figuring this stuff out.

To test it launch a craft that can land with a reasonably centered COT and reasonable TWR, run the program, and then get some altitude. The program engages after you start descending. It figures out the required constant throttle power and heading to zero out your velocity at altitude = TargetH, and executes it when the required throttle to do the maneuver gets over thrmargin (.7) .

 clearscreen.
print "Started...".

set gl to 9.81.

set TargetH to 10 .
set targetv to -.9 .

set thr to 0 .

set thrmargin to 0.7 .
set tlmargin to 0.8 .

set theta to 0 .
set tl to 0 .

set E to ( TargetH - ALT:RADAR ) .
set D to 0 .

print "waiting...".

until verticalspeed < -1 {

}.

print "Suicide Burn..." .

SAS off.

until ( abs(E) < 10 ) AND ( ( abs(verticalspeed) < 2 ) OR ( tl < 0 ) ) {

set TMR to ( maxthrust / mass ) + 0.01 .
set E to ( TargetH - ALT:RADAR ) .

set tl to 2 * tlmargin * E / verticalspeed - .5 .
set thr to ( ( (verticalspeed / tl - gl) ^ 2 + surfacespeed ^ 2 / tl ^ 2 ) ^ .5) / TMR .

set q to (surfacespeed * verticalspeed)/( verticalspeed^2 - 2*E).
set aq to abs(q).
set theta to (-90)*( q^5 + 83.29*q^3 + 518.1*q )/( aq^5 + 96.08*aq^3 + 535.5*aq + 597.9 ).

set lat1 to latitude .
set lon1 to longitude .
set lat2 to latitude .
set lon2 to longitude .

set bearingw to ( lon2 - lon1 ) / cos( lat2 ) .
set bearingn to ( lat2 - lat1 ) .

set bearingm to ( bearingw^2 + bearingn^2 )^.5 + 0.000001 .

lock steering to up + R( theta * bearingn / bearingm , theta * bearingw / bearingm , 180) .

if thr < 0 {
lock throttle to 0 .
}.
if thr > 1 {
lock throttle to 1 .
}.
if ( thr < 1 ) AND ( thr > thrmargin ) {
lock throttle to thr.
}.

print "tl: " + tl + " " at (20,0).
print "bw: " + bearingw/bearingm + " " at (20,1).
print "the: " + theta + " " at (20,2).
}.

print "Hovering..." .

until abs(verticalspeed) < .05 {

set theta to surfacespeed.

set WTR to (mass*gl/maxthrust).
set D to (-.2) * ( verticalspeed - targetv ) * WTR.
set thr to D + WTR* cos( theta ).

set lat1 to latitude.
set lon1 to longitude.
set lat2 to latitude.
set lon2 to longitude.

set bearingw to ( lon2 - lon1 ) / cos( lat2 ) .
set bearingn to ( lat2 - lat1 ) .

set bearingm to ( bearingw^2 + bearingn^2 )^.5 + 0.000001 .

lock steering to up + R( theta*bearingn/bearingm, theta*bearingw/bearingm , 180) .

if thr < 0 {
lock throttle to 0. } .
if thr > 1 {
lock throttle to 1 . } .
if (thr < 1) AND (thr > 0) {
lock throttle to thr. } .
} .

print "Landed.".

set throttle to 0.

unlock steering.
print "Exiting..".

I also figured out an approximation to the atan function that might be useful to people. It has a max error about 2 degrees, but its precise enough for this. The code below executes theta = atand( q ) .


set q to something.
set aq to abs(q).
set theta to (-90)*( q^5 + 83.29*q^3 + 518.1*q )/( aq^5 + 96.08*aq^3 + 535.5*aq + 597.9 ).

Link to comment
Share on other sites

This is a pretty good mod OP, its quite fun coming up with this stuff.

Using check's lat/lon surface velocity trick I've come up with a fully automated suicide burn landing program using some kinematics math.

To test it launch a craft with a reasonably centered COT and reasonable TWR. Run the program, then get some altitude on the craft. The program will kick in once its starts descending.

It will try to zero your horizontal and vertical velocity at altitude = TargetH . Once it zeros your vertical velocity it switches to hover mode, which zeros horizontal velocity and descends at targetv .


clearscreen.
print "Started...".

set gl to 9.81.

set TargetH to 5 .
set targetv to -.9 .

set thr to 0 .

set thrmargin to 0.7 .
set tlmargin to 0.8 .

set theta to 0 .
set tl to 0 .

set E to ( TargetH - ALT:RADAR ) .
set D to 0 .

print "waiting...".

until verticalspeed < -2 {
}.

print "Suicide Burn..." .

SAS off.

until ( abs(E) < 10 ) AND ( ( abs(verticalspeed) < 2 ) OR ( tl < 0 ) ) {

set TMR to ( maxthrust / mass ) + 0.01 .
set E to ( TargetH - ALT:RADAR ) .

set tl to 2 * tlmargin * E / verticalspeed - .5 .
set thr to ( ( (verticalspeed / tl - gl) ^ 2 + surfacespeed ^ 2 / tl ^ 2 ) ^ .5) / TMR .

set q to (surfacespeed * verticalspeed)/( verticalspeed^2 - 2*E).
set aq to abs(q).
set theta to (-90)*( q^5 + 83.29*q^3 + 518.1*q )/( aq^5 + 96.08*aq^3 + 535.5*aq + 597.9 ).

set lat1 to latitude .
set lon1 to longitude .
set lat2 to latitude .
set lon2 to longitude .

set bearingw to ( lon2 - lon1 ) / cos( lat2 ) .
set bearingn to ( lat2 - lat1 ) .

set bearingm to ( bearingw^2 + bearingn^2 )^.5 + 0.000001 .

lock steering to up + R( theta * bearingn / bearingm , theta * bearingw / bearingm , 180) .

if thr < 0 {
lock throttle to 0 .
}.
if thr > 1 {
lock throttle to 1 .
}.
if ( thr < 1 ) AND ( thr > thrmargin ) {
lock throttle to thr.
}.

print "tl: " + tl + " " at (20,0).
print "bw: " + bearingw/bearingm + " " at (20,1).
print "the: " + theta + " " at (20,2).
}.

print "Hovering..." .

until abs(verticalspeed) < .05 {

set theta to surfacespeed * 5.

set WTR to (mass*gl/maxthrust).
set D to (-.2) * ( verticalspeed - targetv ) * WTR.
set thr to D + WTR* cos( theta ).

set lat1 to latitude.
set lon1 to longitude.
set lat2 to latitude.
set lon2 to longitude.

set bearingw to ( lon2 - lon1 ) / cos( lat2 ) .
set bearingn to ( lat2 - lat1 ) .

set bearingm to ( bearingw^2 + bearingn^2 )^.5 + 0.000001 .

lock steering to up + R( theta*bearingn/bearingm, theta*bearingw/bearingm , 180) .

if thr < 0 {
lock throttle to 0. } .
if thr > 1 {
lock throttle to 1 . } .
if (thr < 1) AND (thr > 0) {
lock throttle to thr. } .
} .

print "Landed.".

set throttle to 0.

unlock steering.
print "Exiting..".

I also came up with an approximation to the atan function. It has a maximum error of about 2 degrees, but its close enough for this. The code calculates theta = atand( q ).


set q to something.
set aq to abs(q).
set theta to (-90)*( q^5 + 83.29*q^3 + 518.1*q )/( aq^5 + 96.08*aq^3 + 535.5*aq + 597.9 ).

Link to comment
Share on other sites

Nice that the surface:vector is there. Feels like a waste of time that I went through the effort of finding it from the latitude and longitude, but it's better now that it's there.

Is there anything in the underlying mod API that lets you detect the existence of scatter rocks? If you have terrain scatter on, I think it would be a fun challenge to write a rover script that tries to head toward a destination location, BUT has to have the logic to stop and steer around rocks on the way. Right now there's no way to detect a rock without hitting it and noticing there's something preventing motion. Anyway, it's a good update. I like it.

From my understanding, ground scatter (rocks) don't have a collision mesh and as such wouldn't stop you, you just plow through them. Though that may change in the future...what with sample collection (maybe, but not likely).

Link to comment
Share on other sites

First thing 1st. I think it is a bit strange for a plugin created after 0.20 to use the old legacy directories.

Instead of <KSP directrory>/plugins it should be in <KSP directrory>/GameData/KOS/plugins

This is mostly fixed in 0.6. I've been working on this mod since 0.18, which is why it started out in that structure.

I hadn't realized by the time I released the mod that the official structure had changed, and afterward it seemed like there were a lot more important things to take care of.

Link to comment
Share on other sites

with the new surface velocity vector couldn't you make a simple surface retrograde in code by putting it like this?


lock steering to surface:velocity * V(-1,-1,-1)

Or something like that? I never learned vector math in school but it seems like that would point you in the reverse direction right?

Link to comment
Share on other sites

From my understanding, ground scatter (rocks) don't have a collision mesh and as such wouldn't stop you, you just plow through them. Though that may change in the future...what with sample collection (maybe, but not likely).

Wow. I guess now that I think of it I never actually tried driving straight through the rocks. I just assumed they were real physical barriers and took care to never run into them.

Link to comment
Share on other sites

with the new surface velocity vector couldn't you make a simple surface retrograde in code by putting it like this?


lock steering to surface:velocity * V(-1,-1,-1)

Or something like that? I never learned vector math in school but it seems like that would point you in the reverse direction right?

The problem is that in real vector math there's more than one type of "multiply" and I'm not entirely sure which type is being done here.

Link to comment
Share on other sites

Anyone tried the new version to see if "BREAK." works now? I know we can get around it with a variety of IF statements, but if it's in the documentation it should work.

Also, I'm having trouble having variables operate on themselves, e.g. SET x TO x + 1. I'm having to write SET Y TO X. SET X TO Y+1. Last thing we should be doing on a restricted memory computer!

And these two issues combined makes my code's readability horrible. I'm happy about comments though!

Link to comment
Share on other sites

VECTORS' XYZ's WORK NOW!

It doesn't seem to be documented anywhere, but I just tested it and noticed that this now works:


set vec to V(1,2,3).
set xPart to vec:x.
set yPart to vec:y.
set zPart to vec:z.

This is major. If we can get the 3 parts now, then that opens up a lot of new options. For example, dot products and cross products and scalar magnitudes.

With dot products for example, you can answer the question "how close are these two vectors to being parallel to each other?"

With access to the 3 parts, we can calculate things like inclination-altering burn directions (the normal and antinormal directions will be perpendicular to the prograde vector).

Thank You. THIS, more than anything else, is what I've been wishing for. I have no idea if it appeared in this version or an earlier one, but I just tried it on a whim and was glad it now exists.

Link to comment
Share on other sites

VECTORS' XYZ's WORK NOW!

It doesn't seem to be documented anywhere, but I just tested it and noticed that this now works:


set vec to V(1,2,3).
set xPart to vec:x.
set yPart to vec:y.
set zPart to vec:z.

This is major. If we can get the 3 parts now, then that opens up a lot of new options. For example, dot products and cross products and scalar magnitudes.

With dot products for example, you can answer the question "how close are these two vectors to being parallel to each other?"

With access to the 3 parts, we can calculate things like inclination-altering burn directions (the normal and antinormal directions will be perpendicular to the prograde vector).

Thank You. THIS, more than anything else, is what I've been wishing for. I have no idea if it appeared in this version or an earlier one, but I just tried it on a whim and was glad it now exists.

I have no idea what any of this means, but I hope you do something awesome with it :)

Link to comment
Share on other sites

Seems like all you would need to do though is to just flip the vector around though.

I wrote that before I found out that we now have access to :x, :y, and :z seperately now. That didn't used to be supported, which limited the usefulness of vectors. Yes, of course now that we can get the x y and z parts all you have to do is this:


set surfProVec to vector:surface.
set surfRetroVec to V( 0 - surfProVec:x, 0 - surfProVec:y, 0 - surfProVec:z ).

(The reason it says: "0 - surfProVec:x" instead of just "-surfProVec:x" is that I haven't tested yet to see if unary minus signs are being parsed correctly yet. They didn't used to be.)

Link to comment
Share on other sites

It means you could making a docking script, if you know how to do the maths.

Except that I just discovered that support for this:

lock steering to up * V(1,2,3).

just went away. I can't use the V() expression with "up" or "north" or "steering" anymore in 0.6.

So now I'm trying to figure out how I'm supposed to convert from xyz distances to the new angle-based steering when the language no longer supports that expression, and it doesn't have the arc trig functions (arcsin, arccos, arctan) to convert from vector lengths to angles.

I'm getting the impression that despite giving us more information the removal of that expression "up * V(1,2,2)" may make it actually harder in the new version.

I'm still messing with it trying to figure out how to do what I used to be able to do.

Link to comment
Share on other sites

set tAngle to up + V(x,y,z) + R(0,0,roll).

Yup. This worked yesterday. Now it's broken. I'm pretty sure that is not desired behavior.

I really don't want to have to redo all my steering once again. The new method is nice.

Though as Steven points out, we still need the old way to work also for various reasons.

Link to comment
Share on other sites

In 0.6 the ability to steer by a vector seems to be impossible now. How do I do this? Am I missing something?

As far as I can tell, in 0.6 only the following methods of steering now work:

The up + R(...) method.

The up + Q(...) method.

The new HEADING ... BY ... method.

These methods, that worked in 0.5, no longer work:

up + V(...)

up * V(...)

They now say "Expression error."

It seems that support for steering by vector has been removed.

This is a problem because without the reverse trig functions arctan, arccos, and arcsin, I don't know how to convert a vector's XYZ into the necessary angles.

Which means I can't steer using the new vector:surface. The math functions needed to transform those XYZ's into angles aren't there.

I'm considering implementing one of the approximation methods for the arc trig functions by series or by interpolation, just to get around this hurdle, and that seems a bit excessive, as the hurdle feels entirely artificial.

Right now because of the loss of the V() functions, 0.6 actually is less useful than 0.5 and I'm sad that I installed over the top of 0.5. I'd like to go back until these problems are dealt with.

I wouldn't mind the change to only be able to steer by angle if it was accompanied by the math functions to allow us to get an angle from the lengths of a vector (arcsin, arccos, arctan).

The sad irony is that in the same update that gave us the very useful velocity:surface vector, the ability to use that vector went away.

Edited by Steven Mading
Link to comment
Share on other sites

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