This pages is now largely unnecessary Edit

This page was written and then later the same day a new update came out that gives all this information directly without needing to do this work, so it's largely moot now.

(  For newer more up to date information on a faster, simpler way to decipher this information that works after verision 0.61, please see the post 0.61 version of this page.  )

Finding surface-relative prograde and retrograde directions Edit

As of this writing, (KOS version 0.5), the KOS system only provides ways to get the orbital-relative prograde and retrograde directions. For landing purposes it's really handy to have the surface-relative versions of them. Although they are not provided you can (sort of) calculate them from the location of the vessel and how it moves over time. This page is a tutorial on how to do that, with some example programs that do it for you.

The difference between surface and orbital directions. Edit

This should be known to people who've played KSP a while, but just in case it's not here's a quick review: In space there is no such thing as "THE" one and only right frame of reference with "THE" one and only right coordinate grid. there are many ways to describe position all of which are equally valid and which to use depends on circumstances. When talking about your position you have to pick an origin point and say "I'm talking about my position relative to that point." Because position depends on origin frame of reference, so too does velocity. You might be standing on the equator of Earth and think of yourself as standing perfectly still, and relative to the surface of the earth you are. But relative to the center of the Earth you're going about 1000 miles per hour eastward because the whole surface is traversing an entire earth circumference a day.

It's that difference that is represented by the two modes on the navball called "surface" and "orbital". A person on the Earth's equator with a surface velocity of zero has an orbital velocity of about a thousand miles an hour due east.

KOS 0.5 only gives you the orbital prograde and retrograde vectors, and when you get the velocity, you're getting the orbital velocity.

This tutorial gives an example of how to get the surface-relative direction by watching the data you do have available and making use of it.

The goal Edit

The goal is to produce the right values for X, Y, and Z that form a vector corresponding to your surface-relative velocity. Once you have that you can obtain the directions to use with a LOCK STEERING command.

What data do we have to work with Edit

While exact XYZ positioning relative to the surface is not available what IS available is the altitude, latitude, and longitude relative to the current main body being orbited. Since latitude and longitude are relative to the surface, they represent your position relative to the moving ground rather than to space, so they're exactly what we need for the purpose of making a surface-relative retrograde direction.

Z is easy Edit

We are mostly concerned with finding the X and Y directions. The upward direction doesn't require any special work because that IS provided by KOS in the form of the verticalspeed variable.

X and Y speeds Edit

So the basic way to break down the goal is to figure out distance traveled in the X and Y directions and divide it by how long it took to travel that distance. That's the speed.

The X and Y distances Edit

The logic used for working out the distances from the latitude and longitude is this:

  • For two points A and B on the surface of a circle if the points are very close to each other, the distance in a straight line between points A and B on a circle is VERY close to the portion of the circumference of the circle contained in the arc between those two points. (It approaches zero difference as the sweep arc approaches zero).
  • If an angle is expressed in radians instead of degrees, then the angle IS the circumference traversed around a unit circle by the arc of that angle sweep of the circle - that is the very definition of radians.
  • To convert from degrees to radians, multiply degrees by pi/180.

Therefore you can get the distance traveled from the latitude change by just multiplying the distance to the center of the planet (or moon) by the change in longitude degrees times the conversion from degrees to radians, or in other words, this:

  • r = (planet's radius at sea level + craft's altitude above sea level).
  • change in latitude as radians = (change in latitude as degrees * pi / 180 ).
  • distance traveled northward = r * (change in latitude as radians).

I will call the northward travel the "Y" direction and southward travel the "negative Y" direction, because that's the way that latitude numbers go in the system.

To get the distance traveled by longitude, it's a bit more complex because longitude lines are not all the same distance apart. At the equator longitude and latitude degrees are the same 'size', but as you travel toward the poles, longitude lines squeeze tighter together. At the poles there is the degenerate case where all longitudes are the same because all the lines converge. But as it turns out, it's not THAT much more complex. You simply calculate what the distance would have been at the equator where longitude lines are largest, which is the same formula as for latitude, and then multiply it by the cosine of the latitude - the higher the latitude the smaller the cosine of latitude gets.

  • distance traveled eastward = r * (change in longitude as radians ) * cos(latitude).

I will call eastward travel the "X" direction and westward travel the "negative X" direction, again because that's the direction that longitude numbers are oriented in the code.

So putting it all together we get ... Edit

The following bit of code from the program implements what was described above:

 set surfRelNorth to ( (bodyRadius+sdAlt)*sdDegToRad*(sdLat-sdPLat) ) / (sdTime-sdPTime).
 set surfRelEast to ( (bodyRadius+sdAlt)*sdDegToRad*(sdLon-sdPLon) * cos(sdLat) ) / (sdTime-sdPTime).
 set surfRelUp to sdVS.
 set surfPrograde to up * V( 0 - surfRelEast, surfRelNorth, surfRelUp ).
 set surfRetrograde to up * V( surfRelEast, 0-surfRelNorth, 0-surfRelUp )

AIR DRAG : or ("Why doesn't the direction line up with the navball?) Edit

If you think the program is broken and measuring the directions wrongly because you tested it on Kerbin and the marker seemed way off from the marker on the navball, remember that this program is measuring your ACTUAL velocity experienced, Whereas the marker on the navball is measuring the predicted velocity - the prediction does not take into account air drag. Air drag can be a major factor that means your *REAL* surface direction is quite a bit more vertical than the one predicted on the navball. If you test this on a place without atmosphere like the Mun, you'll see it does match up to the navball's surface markers perfectly there

Now, the actual code. Edit

The code comes in three files:

  • prepsurfdyn. A program to run once before starting your main loop.
  • getsurfdyn. A program to run once per iteration of your main loop that sets the variables fot you to use.
  • testsurfdyn. A program that shows how to use the above programs in a crude example.

These files are shown below.

How to use Edit

Install the three files (you only need the first 2 if you don't want to run the demo) into your archive directory, copy them to your craft, and you can write code like so:

run prepsurfdyn.
until 0 {
  run getsurfdyn.
  ... do stuff here with the variables that were set by the getsurfdyn program ...
  ... each time the loop re-runs you get new updated values in the variables...

The variables set by the getsurfdyn program that you can now use are:

These three variables allow you to make a vector of the relative-to-surface velocity.


These Directions are suitable for use with LOCK STEERING commands:


To try it out: Put these files into your archive, copy them to your vessel, get the vessel in motion above the Mun or Kerbin, and run testsurfdyn. The test just lets you point at your surface-relative prograde or retrograde directions, switching between them with ALT-1 or ALT-2 (press ALt-3 to end it). That's all it does. It's just a demo of the tool. A real program of course would do a lot more with that information.

If you try this on Kerbin and the direction seems way off, please make sure you've read the section titled "AIR DRAG" above before claiming it doesn't work.

File 1 - prepsurfdyn.txt Edit

Cut and Paste it from here and call it prepsurfdyn.txt and put it in your archive: ====

set sdPTime to missiontime.
set sdPLon to longitude.
set sdPLat to latitude.
set sdPAtl to altitude.
set sdDegToRad to 3.1415927 / 180.

File 2 - getsurfdyn.txt Edit

Cut and Paste it from here and call it getsurfdyn.txt and put it in your archive:

set sdTime to missiontime.
set sdLon to longitude.
set sdLat to latitude.
set sdVS to verticalspeed.
set sdSS to surfacespeed.
set sdAlt to altitude.

set surfRelSpeed to ( sdSS^2 + sdVS^2 ) ^ 0.5 .

set surfRelNorth to ( (bodyRadius+sdAlt)*sdDegToRad*(sdLat-sdPLat) ) / (sdTime-sdPTime).
set surfRelEast to ( (bodyRadius+sdAlt)*sdDegToRad*(sdLon-sdPLon) * cos(sdLat) ) / (sdTime-sdPTime).

set surfRelUp to sdVS.

set surfPrograde to up * V( 0 - surfRelEast, surfRelNorth, surfRelUp ).
set surfRetrograde to up * V( surfRelEast, 0-surfRelNorth, 0-surfRelUp ).

set sdPLat to sdLat.
set sdPLon to sdLon.
set sdPTime to sdTime.
set sdPAlt to sdAlt.

File 3 - testsurfdyn.txt Edit

Cut and Paste it from here and call it testsurfdyn.txt and put it in your archive. At the moment it's set up to only be runnable from either Kerbin or the Mun, but you can see how you'd alter it for other planets:

set bodyRadius to 60000.
if body = "Kerbin" { set bodyRadius to 60000. }.
if body = "Mun" { set bodyRadius to 20000. }.

print "    alt-1 to lock to surface prograde. ".
print "    alt-2 to lock to surface retrograde. ".
print "    alt-3 to quit. ".
print " ".
set mySteer to up.
sas off.
lock steering to mySteer.
set direct to "pro".
set done to false.

run prepsurfdyn.

until done {
  on AG1 set direct to "pro".
  on AG2 set direct to "retro".
  on AG3 done on.

  run getsurfdyn.

  if direct = "pro" {
    set mySteer to surfPrograde.
  if direct = "retro" {
    set mySteer to surfRetrograde.
  print "East,North,Up = ( " + surfRelEast + ", " + surfRelNorth + ", " + surfRelUp + ")".
unlock steering.


If you want a steering direction based on, but not exactly like the surface prograde or retrograde vectors, here's how they're made, so you can see how to make your own:

surfPrograde =

  • up * V( 0 - surfRelEast, surfRelNorth, surfRelUp ).

surfRetrograde =

  • up * V( surfRelEast, 0 - surfRelNorth, 0 - surfRelUp )

It may seem odd that the signs aren't all the same. This is because the conventions used for which direction is positive in the east-west axis appears to be inverted when expressing it in longitude (east = positive) from what it is in the coordinate space of the game (west = positive).

So, for example, if you wanted to steer in a direction that's slightly more northward than surface prograde you might us this direction:

  up * V( surfRelEast, surfRetNorth*2, surfRelUp ).

to create a vector in which the northerly direction has been doubled. Here's one example: When getting hear the ground on a landing, I don't want to slavishly follow the retrograde vector anymore because it will start to swing wildly as the vertical speed approaches zero. So here's an example handling that that builds a custom direction vector when near the ground instead of using the retrograde direction vector:

An example of using your own steering direction Edit

You might not want to follow the retrograde marker all the way down to the landing because as you slow your vertical speed the retrograde marker can suddenly swing wildly off to the side. when vertical speed approaches zero. At this point the last thing in the world you'd want your lander to do is suddenly try to twist sideways to follow it. You want it to stay mostly upward and just gently move a tiny bit to the side. This example code shows how you might do that. As long as the altitude is above 100, it just follows the surface retrograde mark. But once it gets close to the ground it abandons the surface retrograde mark and instead operates on a vector that's hardcoded to always point up even if verticalspeed goes positive for a bit, and also it greatly reduces the magnitude of the horizontal components of the direction: ```

 (steering is already locked to 'mySteer' at this point.)
 set newDir to surfRetrograde .
 (Assume myAlt is your altitude above sea level OR ground level, whichever is closer).
 if myAlt < 100 {
   set x to surfRelEast / 20 .
   set y to (0 - surfRelNorth) / 20 .
   set z tp abs(surfRelUp) .
   set newDir to up * V( x, y, z ) .
 set mySteer to newDir .


Ad blocker interference detected!

Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.