Jump to content

[1.3] kOS Scriptable Autopilot System v1.1.3.0


erendrake

Recommended Posts

Athlete Rover update.

Everything works! I just have to find some more time to write routines for bug walking, unloading from lander, leg leveling,

Also looking to climb over a low wall, jump like a rabbit with a cushioned landing, operate as a forklift, and panic stop mode (no flipping over when braking hard).

                 .--.       .--.
\ /"
|\ `\___/' /|
\\ .-'@ @`-. //
|| .'_________`. ||
\\.'^ Y ^`.//
.' | `.
: | :
: ATHLETE :
: Ver.1 :
: _ | _ :
:. (_) | (_) :
__::. | :__
/.--::. | :--.\
__//' `::. | .' `\\__
`--' //`::. | .'\\ `--'
|| `-.__|__.-' ||
|| ||
// \\
|/ \|

Link to comment
Share on other sites

The ship's raw position IS V(0,0,0) in kOS terminology. The weird contradictory coordinate system of underlying KSP is re-origined at the current ship's CoM for all position vectors in kOS (although it's not re-rotated to something sane - it stays at the underlying rotation). Oddly enough, it's still not origined at the vessel for VELOCITY purposes (which would zero your velocity if it was), but rather it reports the velocity at which the rest of the objects in the universe are passing you by.

The problem then must be my syntax for the origin point of the vector. Sorry if this is a very easy answer, but I haven't played with programming since Basic and Pascal in high school and geometry/trig was around that time as well.

Here's the code:


lock t1 to ship:position.
lock pv to port:portfacing:vector.


set pm1 to ship:modulesnamed("ModuleDockingNode").
for portmod in pm1 {set port to portmod:part.}.

set aa to vecdrawargs ( t1,pv,RGB(0,1,0.5), "axis", 5, true ).

Link to comment
Share on other sites

Have you ever wished for a method of measuring slopes within line of sight without flying over the spot or derriving samples of ground altitude measurements ?

Fortunately you can do just that using the LaserDist mod, kOS and some math.

  • Mount a number of laser distance sensors (using IR for rotation if desired) in such a way that you have one central laser beam and a number of other beams in a cone or pyramid like fashion.
    laser.png
  • Optional: Designate one (origin-)part of your vessel to be used as the origin of your local coordinate system.
    Using part:FACING:INVERSE you can transform the orientation of the sensors into something sane for your vessel's frame of reference.
  • Collect distance measurements and calculate the vector from origin to where the beam hit the ground.
    (Problem: its unclear/undocumented where exactly the beams originate from in relation to the pose of the sensor part)
  • Compute Covariance Matrix Z (3x3) as follows:
    Let p0 be the point where the central beam hits and pj ; j > 0 the other points.
    Z := 1/(number of sensors) * SUMi [( pi - p0) * (pi - p0)T]
  • Invert Z using the general formula for 3x3 matrix inversion ( see https://ardoris.wordpress.com/2008/07/18/general-formula-for-the-inverse-of-a-3x3-matrix/ or http://mathworld.wolfram.com/MatrixInverse.html )
  • Compute the eigenvector v corresponding to the most significant eigenvalue l of Z-1 using the power method. This is the eigenvector corresponding to the least signficant eigenvalue of Z.
    1. initialize v with something other than 0
    2. iterate vk+1 = (Z-1 * vk) / ||(Z-1 * vk)|| until value hasn't changed much

    [*]This vector can either point towards the sky or the ground. If that matters then check which case it is and flip it around as needed.

    [*]You can now compare the normal vector with vector from central point p0 to the center of the body (direction of gravity at that point) you're orbiting.

The resulting eigenvector is the one corresponding to the least signficant eigenvalue of Z.

Z describes how the points are distributed around p0 and its Eigenvectors describe a new orthogonal base where each vector is chosen so that the variance (of the points) along its direction is maximized (but each additional vector is orthogonal to the previous ones). ( See http://en.wikipedia.org/wiki/Principal_component_analysis too).

The vector orthogonal to two (orthogonal) vectors that maximize the variance is an approximation of the normal in the center point provided that the other points are reasonably close together and provide enough resolution when sampling the surface.

So far I've implemented all necessary matrix operations (on lists) but given the non existance of variable scopes and return values actually reusing code is a complete nightmare with KOS. It always turns into frustrating spaghetti.

Given that the type system is weak sauce too its almost tempting to try mod a Python interpreter into KSP instead.

Edited by Idranel
Link to comment
Share on other sites

The problem then must be my syntax for the origin point of the vector. Sorry if this is a very easy answer, but I haven't played with programming since Basic and Pascal in high school and geometry/trig was around that time as well.

Here's the code:


lock t1 to ship:position.
lock pv to port:portfacing:vector.


set pm1 to ship:modulesnamed("ModuleDockingNode").
for portmod in pm1 {set port to portmod:part.}.

set aa to vecdrawargs ( t1,pv,RGB(0,1,0.5), "axis", 5, true ).

Your description is missing the most important bit: What is it about this that doesn't work? are you getting an error message? Is something not showing up on screen?

- - - Updated - - -

Have you ever wished for a method of measuring slopes within line of sight without flying over the spot or derriving samples of ground altitude measurements ?

Your method seems to be doing an awful lot of extra work, given that kOS provides you with vector cross product operators already, which is what I suspect all your matrix math ends up doing anyway. The matrix operations behind a vector cross product are handled for you by the Unity engine, and we pass that on to you with a kOS function VCRS( vector1, vector2).

You should be able to get a normal vector to a point on the ground using just 3 sample points, and a cross product.

Once you've got the location of 3 points A,B,C, then you can do this:


set ABvector to B - A.
set ACvector to C - A.
set AB_cross_AC to VCRS(ABvector,ACvector). // normal to the slope at that spot.
set angle to VANG(AB_cross_AC, ship:UP). // slope angle (assuming that the impact
// point is near enough in latitude/longitude to the
// ship that the difference in UP between the ship location and the hit location is negligable).

Link to comment
Share on other sites

Have you ever wished for a method of measuring slopes within line of sight without flying over the spot or derriving samples of ground altitude measurements ?

Fortunately you can do just that using the LaserDist mod, kOS and some math.

You have no idea how well timed this is!!!

http://forum.kerbalspaceprogram.com/threads/69678-0-23-FTAS-v1-The-Fox-Terrain-Avoidance-System

Link to comment
Share on other sites

Your description is missing the most important bit: What is it about this that doesn't work? are you getting an error message? Is something not showing up on screen?

Sorry, the problem is the origin position of the vector drawn on screen appears several meters away from the port:position that I set it to. I discovered, however, that if I set the magnitude to 1 (in the original code I was using from the github docs it was 5), then it appears exactly as I expect it to. I've attached screenshot below to show what I mean.

This is with mag set to 1: http://i.imgur.com/PoScCGL.png

This is with mag set to 5: http://i.imgur.com/OA4buTc.png

It's not currently part of an overall program, I'm just trying to learn how everything works.

Link to comment
Share on other sites

Your description is missing the most important bit: What is it about this that doesn't work? are you getting an error message? Is something not showing up on screen?

Sorry, the problem is the origin position of the vector drawn on screen appears several meters away from the port:position that I set it to. I discovered, however, that if I set the magnitude to 1 (in the original code I was using from the github docs it was 5), then it appears exactly as I expect it to. I've attached screenshot below to show what I mean.

This is with mag set to 1: http://i.imgur.com/PoScCGL.png

This is with mag set to 5: http://i.imgur.com/OA4buTc.png

It's not currently part of an overall program, I'm just trying to learn how everything works.

Yeah thats the effect of the scale operator. It mulitplies both the offset start position and the vector itself. That may be silly. If nobody is using it that way i may remove the part about multiplying the start pos and just multiply the vector size only.

In the mean time to get what you want just multiply 5 by the second argument only.

Link to comment
Share on other sites

Yeah thats the effect of the scale operator. It mulitplies both the offset start position and the vector itself. That may be silly. If nobody is using it that way i may remove the part about multiplying the start pos and just multiply the vector size only.

In the mean time to get what you want just multiply 5 by the second argument only.

Thank you that works great. Now I'm just figuring out the movement and steering.

Here's a fun thing I discovered: if you have a inline docking port and set 'control from here' on that port, then attempt lock steering to up. It will spin around like mad, at least the small probe I have in the pictures above does. I think its because the torque and the center of mass are not lines up with port.

It will lock with no problem as long as I leave the control on the probe computer.

Link to comment
Share on other sites

Thank you that works great. Now I'm just figuring out the movement and steering.

Here's a fun thing I discovered: if you have a inline docking port and set 'control from here' on that port, then attempt lock steering to up. It will spin around like mad, at least the small probe I have in the pictures above does. I think its because the torque and the center of mass are not lines up with port.

It will lock with no problem as long as I leave the control on the probe computer.

I noticed that too and reported it as issue number 397, but I didn't look into the cause because I was leaving the steering up to erendrake to deal with while I worked on other stuff, and I wasn't even sure it was real as I had a lot of other problems at the same time and it was hard to isolate one bug from another. If you're able to perfectly recreate it with a known craft and a known set of actions, it would be great if you could add your information to that bug report.

Link to comment
Share on other sites

Your description is missing the most important bit: What is it about this that doesn't work? are you getting an error message? Is something not showing up on screen?

- - - Updated - - -

Your method seems to be doing an awful lot of extra work, given that kOS provides you with vector cross product operators already, which is what I suspect all your matrix math ends up doing anyway. The matrix operations behind a vector cross product are handled for you by the Unity engine, and we pass that on to you with a kOS function VCRS( vector1, vector2).

You should be able to get a normal vector to a point on the ground using just 3 sample points, and a cross product.

Once you've got the location of 3 points A,B,C, then you can do this:


set ABvector to B - A.
set ACvector to C - A.
set AB_cross_AC to VCRS(ABvector,ACvector). // normal to the slope at that spot.
set angle to VANG(AB_cross_AC, ship:UP). // slope angle (assuming that the impact
// point is near enough in latitude/longitude to the
// ship that the difference in UP between the ship location and the hit location is negligable).

This method works for arbitrary point cloud neighborhoods without prior knowledge of their structure.

Its commonly used to compute normals in 3D laser scan data.

If you're limited to three points then the vector cross product makes more sense.

Edited by Idranel
Link to comment
Share on other sites

Can you help me to analyze this problem?

I'm thinking about make a script that can calculate the vector of thrusting, so when I combine the use of IR, it can make the thrust vector adaptive to the center of mass.

As what I know, probably I can do it by collecting the facing and current thrust data of all active engines, and calculate the resultant vector.

So, do you agree with it? and can it be more simple? or, is there a function I missed that can get that?

Link to comment
Share on other sites

This method works for arbitrary point cloud neighborhoods without prior knowledge of their structure.

Its commonly used to compute normals in 3D laser scan data.

If you're limited to three points then the vector cross product makes more sense.

What additional information do you get from 6 points in a plane that didn't already exist from just 3 points in plane? If you know they're all in a plane, once you have 3, any more are just gravy. If you don't know that they're all in a plane, then basically the concept of a "normal" vector to the not-plane doesn't make sense anyway.

Or is the unspoken assumption in your math that you assume your points are not in a plane but are sort of close to being in a plane and you're trying to find the approximate average plane that runs through the cloud of them? (in KSP terms, since KSP terrain is made of flat polygons, that would mean the points are not all hitting the same polygon and you want the average plane between the angles of the different polygons you've hit.) I'd still go with the cross-product in that case, and just get the resulting vector from multiple tuples of 3 points, turning them into unit length vectors so as not to weight them, and then average them into one vector.

i.e. if you have point A in the middle, and then points B,C,D,E, around A, then get the normals:

AB X AC / |AB X AC|,

AC X AD / |AC X AD|,

AD X AE / |AD X AE|,

AE X AB / |AE X AB|,

and average their coordinates together, to get average slope around point A.

It's good enough and it's a lot faster because you're allowing the underlying (very fast) 3D engine do the math, instead of doing it in the slow world of kOS script code. A cross product is normally a matrix operation with lots of components, but when you let the 3D engine do it for you, it's often translated into hardware instructions, as vector operators have to happen so often in graphics that a typical graphics card will provide you with the ability to do them itself. The 3D engine will abstract all that away so long as you use its function calls to do the operation and don't try to run all the steps yourself.

But at any rate the whole point of kOS is to let you do it yourself and if you want to use the cloud method by all means go for it.

I do agree that the lack of local variables and user-defined functions is rather severely limiting and could use fixing. It's on the long list of "stuff to get around to some day".

Edited by Steven Mading
Link to comment
Share on other sites

I'm trying to work out the distance between two gps points (lat/long). I can capture lat/long for two ponts well enough. That's the easy bit. The trig bit with kOS has me scratching my head. I googled this and this is java (which I don't know, but it's pretty self-evident):


function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}

function deg2rad(deg) {
return deg * (Math.PI/180)
}

Do I need to convert to radians like this function does and is all that trig possible?

I'm measuring small distance - in the hundreds of meters. Does that remove the need for some of that trig? Like, trig on really small numbers will return really small numbers type of thing?

Link to comment
Share on other sites

I'm trying to work out the distance between two gps points (lat/long). I can capture lat/long for two ponts well enough. That's the easy bit. The trig bit with kOS has me scratching my head. I googled this and this is java (which I don't know, but it's pretty self-evident):


function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}

function deg2rad(deg) {
return deg * (Math.PI/180)
}

Do I need to convert to radians like this function does and is all that trig possible?

I'm measuring small distance - in the hundreds of meters. Does that remove the need for some of that trig? Like, trig on really small numbers will return really small numbers type of thing?

just have the 2 spots use the function :distance.

example:

print spot1:distance.

print spot1:bearing.

print spot2:distance.

print spot2:bearing.

now you have distance to each and angle between the two. from that you can form a triangle and calculate the rest.

btw there are approximations for sinus functions, if the angle IN RADIANS is very small then sin(angle) ~ angle. that is if the angle IN RADIANS is below 1.

Link to comment
Share on other sites

I can't use distance sadly.

Distance from the CPU_Vessel to this point on the surface.

I want two random points on the surface - not from craft to surface. I have a lat/long and another lat/long - how can kOS work out the distance between them?

edit: oh - I see - triangulate. Interesting.

Link to comment
Share on other sites

But at any rate the whole point of kOS is to let you do it yourself and if you want to use the cloud method by all means go for it.

I thought maybe you didn't find my stuff interesting. But I can see now I am admired like a small child who discovers how to build a sandcastle.

- - - Updated - - -

I have been studying my C#.

I know I have a long way to go, but I have an idea for kOS that I would like to try and figure out and program myself.

I've already created a local clone of the github etc. and played around with that. I'm cognizant that I can compile my own versions of the dll and so on.

Unless someone wants to usurp this, I am hoping to create a class that allows me to write the contents of a :getfield to the screen using MonoBehaviour.PostScreenMessage

Please tell me I am on the right track?

Link to comment
Share on other sites

I thought maybe you didn't find my stuff interesting. But I can see now I am admired like a small child who discovers how to build a sandcastle.

- - - Updated - - -

I have been studying my C#.

I know I have a long way to go, but I have an idea for kOS that I would like to try and figure out and program myself.

I've already created a local clone of the github etc. and played around with that. I'm cognizant that I can compile my own versions of the dll and so on.

Unless someone wants to usurp this, I am hoping to create a class that allows me to write the contents of a :getfield to the screen using MonoBehaviour.PostScreenMessage

Please tell me I am on the right track?

Why limit the scope to just :GetField? Why not just allow a script to print whatever string it feels like to a PostScreenMessage, regardless of whether it's coming from a :GETFIELD or something else? Just implement it at the basic string level and you get :getfield for free that way, along with all sorts of other stuff.

Link to comment
Share on other sites

I can't use distance sadly.

I want two random points on the surface - not from craft to surface. I have a lat/long and another lat/long - how can kOS work out the distance between them?

edit: oh - I see - triangulate. Interesting.

Exactly using a bit of tangens, but this only works if there is a 90° angle somewhere, I tried to calculate the other sides but had no luck. the information you have in this case is not enough to calculate the triangle entirely.

Link to comment
Share on other sites

Exactly using a bit of tangens, but this only works if there is a 90° angle somewhere, I tried to calculate the other sides but had no luck. the information you have in this case is not enough to calculate the triangle entirely.

er, non-right angled trig says hello

dist = sqrt (spot1:distance ^ 2 + spot2:distance ^ 2 - 2 * spot1:distance * spot2:distance * cos ( spot1:bearing - spot2:bearing) )

scuse the non-kOS syntax...

Edited by Crzyrndm
Link to comment
Share on other sites

meh I wasnt aware of this, trigonometry was never my cup of tea, but yeah that should work

SET dist TO sqrt((spot1:distance)^2 + (spot2:distance)^2 - 2 * spot1:distance * spot2:distance * cos (spot1_2_angle).

SET spot1_2_angle to (spot1:bearing - spot2:bearing).

you might need to fiddle around with spot:bearing and a lil IF magic to sum them up correctly, and depending on situation there could arise problems

Edited by VentZer0
Link to comment
Share on other sites

I noticed that too and reported it as issue number 397, but I didn't look into the cause because I was leaving the steering up to erendrake to deal with while I worked on other stuff, and I wasn't even sure it was real as I had a lot of other problems at the same time and it was hard to isolate one bug from another. If you're able to perfectly recreate it with a known craft and a known set of actions, it would be great if you could add your information to that bug report.

Sure, it does it every time. That's why I'm now trying to figure the angles to the port so I can get it to align with a target. I thought it should be 90 degree angle but I see I'm going to need to read a lot more.

I'll try to put a bug report up today.

Link to comment
Share on other sites

I don't know which to quote so I'll just say with two distances at right angles to the craft (eg directly north and directly east) then I can use Pythagoras to get the hypotenuse.

I didn't mention that before but yeah, it's now relevant and an option. :) this is the second last puzzle to my problem. :)

Link to comment
Share on other sites

Sure, it does it every time. That's why I'm now trying to figure the angles to the port so I can get it to align with a target. I thought it should be 90 degree angle but I see I'm going to need to read a lot more.

I'll try to put a bug report up today.

In my case my goal was to make a raw-steering (not LOCK STEERING) example of how to do docking from one weirdly aimed docking port to another, as a proof of concept of the new direction and position suffixes for parts, so because I was trying to do it with raw SHIP:CONTROL techniques the fact that LOCK STEERING didn't work right was of lesser priority to what I was trying to do.

But yeah, that reminds me that I never did make the example video for that test case like I meant to. I really should.

- - - Updated - - -

I can't use distance sadly.

I want two random points on the surface - not from craft to surface. I have a lat/long and another lat/long - how can kOS work out the distance between them?

edit: oh - I see - triangulate. Interesting.

Does this work for you?


// Assumes that at this point of your script,
// lat1, long1, and lat2, long2 are the latitude and longitude of the 2 points you're interested in.
//
SET geoPos1 to LATLNG(lat1,long1).
SET geoPos2 to LATLNG(lat2,long2).
print "Position vector of geoPos1 is " + geoPos1:POSITION.
print "Position vector of geoPos2 is " + geoPos2:POSITION.
print " --- ".
set vector1To2 to (geoPos2:POSITION - geoPos1:POSITION).
print "Straight line vector distance from pos1 to pos2, "
print "(ignoring terrain and surface curvature)"
print "is this: " + vector1To2:MAG.

Link to comment
Share on other sites

In my case my goal was to make a raw-steering (not LOCK STEERING) example of how to do docking from one weirdly aimed docking port to another, as a proof of concept of the new direction and position suffixes for parts, so because I was trying to do it with raw SHIP:CONTROL techniques the fact that LOCK STEERING didn't work right was of lesser priority to what I was trying to do.

But yeah, that reminds me that I never did make the example video for that test case like I meant to. I really should.

LoL

That would be very helpful. I'm having a hell of a time trying to get the side port to position itself correctly. I suppose I could just get the position of the port, then use raw control to position of the control ship's port until the positions zero out. I think that would work...

Link to comment
Share on other sites

Or is the unspoken assumption in your math that you assume your points are not in a plane but are sort of close to being in a plane and you're trying to find the approximate average plane that runs through the cloud of them? (in KSP terms, since KSP terrain is made of flat polygons, that would mean the points are not all hitting the same polygon and you want the average plane between the angles of the different polygons you've hit.) I'd still go with the cross-product in that case, and just get the resulting vector from multiple tuples of 3 points, turning them into unit length vectors so as not to weight them, and then average them into one vector.

Yes this is assumed here.

Picking two vectors spanning such a plane more or less arbitrarily works well enough if things are mostly flat.

For anything hilly (the question remains whether or not KSP terrain actually gets bumpy enough) you'll probably want a higher resolution.

But admittedly it might not be worth going through the trouble considering how slow it'll be in comparison.

Fortunately in native code this stuff is fast enough to be useful.

Edited by Idranel
Link to comment
Share on other sites

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