Jump to content

[1.3] kOS Scriptable Autopilot System v1.1.3.0


erendrake

Recommended Posts

Well, it is actually possible if our script does not lock throttle or steering. You can run a script like this on the launchpad


wait until alt:radar > 50000.
print "Cuting throttle".
set ship:control:mainthrottle to 0.

The script will not interfere with your manual controls until the wait condition triggers

Actually I tried running your script and it didn't work either.

But the good news is I found out the solution: It should have been written as


wait until alt:radar > 50000.
print "Cuting throttle".
set ship:control:pilotmainthrottle to 0. // Notice it's not mainthrottle, but rather, pilotmainthrottle.

Link to comment
Share on other sites

Sorry, I meant via code. I'm currently using shutdown and it's annoying how one has to turn the power back on an you lose any command history

if the code is running in a loop the break command might work for you.

Ok spoke to soon on the pathfinder script working:(.

I have a bug in my path-finding script that I only run into when it has been running for a long time. I don't know if this is a bug with my script or a kos bug but i am getting this:

uc?export=view&id=0B2X2pcwft9VdcGZya2NrZ1Z1RDQ

p2 (point 2) when printed appears to be a geo-position(as it should be) and the suffixes lat and lng give the correct behaviour but :terrainheight fails and I can't work out why as it has run lots(possibly thousands) of times already as part of this script without issue.

I have included the code if anyone wants to try and reproduce this (it's a bit of a mess sorry). It "should" encountor the error if you leave it running over night (also set the IPU to 2000). Any help fixing this would be greratly apreciated, thanks.

wip.ks


clearscreen.
Set startTime to Time.
print "Started at: "+Time:Clock.
set slat to ship:latitude. //start lat.
set slng to ship:longitude. //start lng.
if slng < 0 {
set slng to (slng+360).
}.

set flat to -90. //finish lat.
set flng to 0. //finish lng.
if flng < 0 {
set flng to (flng+360).
}.

if body = kerbin or body = eve or body = laythe {
set water to 1.
}
else {
set water to 0.
}.

Set dx to 1.
set dy to 1.
set samplerate to 100.
set slopefactor to 800.
set traversefactor to 1. //not yet used

//=====Vertex info list=======
// 0 - geolocation.
// 1 - checked connections.
// 2 - grid pos x
// 3 - grid pos y
// 4 - vertex cost.
// 5 - x of previous vertex in shortest path.
// 6 - y of previous vertex in shortest path.


//====Set up grid sphere======= This will be replaced with a cube projection when i get round to it.
set grid to list(). //x coordinate on grid
set x to 0.
set y to -90.
until x = 360 {
grid:add(list()). //y coordiante on grid
until y >= 90-dy {
set y to round(y+dy,1). //rounding to remove floating point error that creeps in (dont know how it gets there)
grid[grid:length-1]:add(list()). //vertex info
grid[grid:length-1][grid[grid:length-1]:length-1]:add(latlng(y,x)).
grid[grid:length-1][grid[grid:length-1]:length-1]:add(0).
grid[grid:length-1][grid[grid:length-1]:length-1]:add((grid:length-1)).
grid[grid:length-1][grid[grid:length-1]:length-1]:add((grid[grid:length-1]:length-1)).
}.
set y to -90.
set x to x + dx.
}.
set vertextotal to grid:length*grid[0]:length.
Print "Grid setup complete.".
run gs_distance(grid[0][round(grid[0]:length/2)][0],grid[1][round(grid[1]:length/2)][0],body:radius).
set startlimit to 1.5*result.
//==============================

//=====Set up start/finish======
set start to list().
start:add(latlng(slat,slng)).
start:add(0).
start:add(-1).
start:add(-1).

set finish to list().
finish:add(latlng(flat,flng)).
finish:add(0).
finish:add(-2).
finish:add(-2).
finish:add(0).
//==============================

//==Set up neighbors / visited==
set neighbors to list().
set visited to list().
visited:add(finish).
if finish[0]:lat < (dy - 90) {
set pos to 0.
until pos >= grid:length-1 {
neighbors:add(grid[pos][0]).
set pos to pos +1.
}.
}
else if finish[0]:lat > (90 - dy) {
set pos to 0.
until pos >= grid:length -1 {
neighbors:add(grid[pos:index][grid[pos]:length - 1]).
set pos to pos +1.
}.
}
else {
set x to floor(finish[0]:lng)/dx.
set y to (floor(finish[0]:lat)+90) / dy.
neighbors:add(grid[x][y]).
neighbors:add(grid[x+1][y]).
neighbors:add(grid[x+1][y+1]).
neighbors:add(grid[x][y+1]).
}.
neighbors:add(start).
//==============================

//======Pathfinding=============
set activeVertex to finish.
set vertexcount to 0.
until activeVertex = start {
Print "Checking vertex at" +activeVertex[0].

//calculate weighting.
for vertex in neighbors {
if vertex[0]:terrainheight < 0 and water = 1 {
set vertex[1] to 8.
}
else {
set cost to 0.
set swimming to false.
run gs_distance(activevertex[0],vertex[0],body:radius).
set gsdist to result.
print "Distance to "+vertex[0]+" is "+gsdist.
log "Distance to "+vertex[0]+" is "+gsdist to debug.
set floorgsdist to floor(gsdist/samplerate).
set count to 0.
set p1 to activevertex[0].
until count >= floorgsdist or swimming = true {
run gs_bearing(p1,vertex[0]).
set gsbear to result.
run gs_destination(p1,gsbear,samplerate,body:radius).
set p2 to result.
if p2:terrainheight < 0 {
set swimming to true.
print "Can't cross water at "+p2.
}
else {
set cost to cost + samplerate + (slopefactor*abs(p1:terrainheight-p2:terrainheight)/samplerate).
}.
set p1 to p2.
set count to count + 1.
}.
if swimming = false {
run gs_distance(p1,vertex[0],body:radius).
set gsdist to result.
set cost to cost + gsdist + (slopefactor*abs(p1:terrainheight-vertex[0]:terrainheight)/gsdist).
if vertex:length < 5 {
set vertex[1] to vertex[1]+1.
vertex:add(activevertex[4]+cost).
vertex:add(activevertex[2]).
vertex:add(activevertex[3]).
Set listmax to visited:length-1.
set listmin to 0.
until listmin > listmax {
set listmid to floor((listmax+listmin)/2).
if vertex[4] > visited
[listmid][4] {
set listmin to listmid+1.
}
else if vertex[4] < visited
[listmid][4] {
set listmax to listmid-1.
}
else {
set listmin to listmid.
set listmax to listmid-1.
}.
}.
if listmin = visited:length {
visited:add(vertex).
}
else {
visited:insert(listmin,vertex).
}.
}
else if activevertex[4]+cost < vertex[4] {
set listmax to visited:length-1.
set listmin to 0.
until listmin > listmax {
set listmid to floor((listmax+listmin)/2).
if vertex[4] > visited
[listmid][4] {
set listmin to listmid+1.
}
else if vertex[4] < visited
[listmid][4] {
set listmax to listmid-1.
}
else {
set listmin to listmid.
set listmax to listmid-1.
}.
}.
if vertex[0] = visited
[listmin][0]{
visited:remove(listmin).
}.
set vertex[1] to vertex[1]+1.
set vertex[4] to activevertex[4]+cost.
set vertex[5] to activevertex[2].
set vertex[6] to activevertex[3].
Set listdmax to visited:length-1.
set listmin to 0.
until listmin > listmax {
set listmid to floor((listmax+listmin)/2).
if vertex[4] > visited
[listmid][4] {
set listmin to listmid+1.
}
else if vertex[4] < visited
[listmid][4] {
set listmax to listmid-1.
}
else {
set listmin to listmid.
set listmax to listmid-1.
}.
}.
if listmin = visited:length {
visited:add(vertex).
}
else {
visited:insert(listmin,vertex).
}.
}
else {
set vertex[1] to vertex[1]+1.
}.
}
else {
set vertex[1] to vertex[1]+1.
}.
if vertex[2] = -1 {
set start to vertex.
}
else {
set x to vertex[2].
set y to vertex[3].
set grid[x][y] to vertex.
}.
}.
}.
print "remove active vertex from visited list".
visited:remove(0).
print "select new active vertex".
set activevertex to visited[0].
// set vertexcount to vertexcount+1.
// set timetaken to time-starttime.
// Print "Time taken: " +Timetaken:clock +" " at (0,1).
// print "Vertecies Checked: "+vertexcount+" of "+vertextotal+" " at (0,2).
if activevertex = start {}
else {
print "create new neighbors list".
set neighbors to list().
run gs_distance(start[0],activevertex[0],body:radius).
if result < startlimit {
neighbors:add(start).
}.
set nx to -1.
until nx > 1 {
if nx = 0 {
set z to 2.
}
else {
set z to 1.
}.
set ny to -1.
until ny > 1 {
set vx to activevertex[2]+nx.
if vx < 0 {
set vx to grid:length-1.
}
else if vx > grid:length-1 {
set vx to 0.
}.
set vy to activevertex[3]+ny.
if vy < 0 or vy > grid[activevertex[2]]:length-1 {
set vy to activevertex[3].
if vx < grid:length / 2 {
set vx to vx + (grid:length / 2).
}
else {
set vx to vx - (grid:length / 2).
}.
}.
if grid[vx][vy][1] < 8 {
neighbors:add(grid[vx][vy]).
}.
set ny to ny + z.
}.
set nx to nx + 1.
}.
// print "remove active vertex from neighbors".
// set pos to 0.
// until pos = neighbors:length {
// print "checking neighbors["+pos+"]".
// if neighbors[pos] = activevertex {
// neighbors:remove(pos).
// set pos to neighbors:length-1.
// }.
// set pos to pos+1.
// }.
}.
}.
print "rout calculated".
//==============================

//=====Save waypoint list=======
set rout to list().
set activevertex to start.
Until activevertex = finish {
if activevertex[5] = -2 {
set activevertex to finish.
}
else {
set activevertex to grid[activevertex[5]][activevertex[6]].
}.
rout:add(activevertex[0]).
}.
Log rout to waypoints.
//any angle smoothing pass
//==============================


//====Driving===================

gs_bearing.ks


declare parameter p1,p2.
set result to 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)).

gs_destination.ks


declare parameter p1, b, d, radius. //(start point,bearing,distance,radius(planet/moon)).
set resultA to (d*180)/(radius*constant():pi).
set resultB to arcsin(sin(p1:lat)*cos(resultA)+cos(p1:lat)*sin(resultA)*cos().
set resultC to p1:lng+arctan2(sin(*sin(resultA)*cos(p1:lat),cos(resultA)-sin(p1:lat)*sin(resultB)).
set result to latlng(resultB,resultC).

gs_distance.ks


declare parameter p1, p2, radius. //(point1,point2,radius(planet/moon)).
set resultA to sin((p1:lat-p2:lat)/2)^2 + cos(p1:lat)*cos(p2:lat)*sin((p1:lng-p2:lng)/2)^2.
set result to radius*constant():PI*arctan2(sqrt(resultA),sqrt(1-resultA))/90.

Edited by TDW
Link to comment
Share on other sites

if the code is running in a loop the break command might work for you.

I suppose I could have specified this is not for a loop. Nor do I want to have to program code to make sure it is a loop just so I can do a clean exit

Link to comment
Share on other sites

Actually I tried running your script and it didn't work either.

But the good news is I found out the solution: It should have been written as


wait until alt:radar > 50000.
print "Cuting throttle".
set ship:control:pilotmainthrottle to 0. // Notice it's not mainthrottle, but rather, pilotmainthrottle.

Oops, I just copied your code without thinking, of course it is PILOTMAINTHROTTLE

- - - Updated - - -

I suppose I could have specified this is not for a loop. Nor do I want to have to program code to make sure it is a loop just so I can do a clean exit

I suggest you file an issue here: https://github.com/KSP-KOS/KOS/issues

Link to comment
Share on other sites

@Gaiiden

Using reboot. instead will mean that you don’t have the irritation of having to turn the console back on, you still loss command history though.

Just had an idea it's not exactly best practice though :wink:

SET nonExistantList[1] to x.

will cause an exception that will end your script and you will still have your command history and the terminal will still be open.

Link to comment
Share on other sites

So... what replaced heading(pitch,roll,yaw)? - It still produces a R()otation, but if you try to use it it gives a cast error?

SET Pitch to 90.
SET Roll to -90.
SET Yaw TO 0.

LOCK STEERING TO HEADING(Pitch, Yaw, Roll).

Now gives "cannot cast from source type to destination type. (Cannot show kOS Error Location - error might really be internal. See kOS devs.)"

Ah, you lost the optional third argument when you tidied it up.

I can use this instead, but it would be nice if it could find it's way back into the language....

LOCK STEERING TO HEADING(0,0)*R(0-Pitch, Yaw, Roll).

Edited by JoCRaM
missed the Direction indicator
Link to comment
Share on other sites

Ah, you lost the optional third argument when you tidied it up.

I can use this instead, but it would be nice if it could find it's way back into the language....

LOCK STEERING TO HEADING(0,0)*(0-Pitch, Yaw, Roll).

That was never in the language.

what is (0-Pitch, Yaw, Roll) ?

Is it an R(), a Q(), a V() ? You just typed a tuple without the preceding letter identifying what type of tuple, and that was never a thing in the language.

Link to comment
Share on other sites

That was never in the language.

what is (0-Pitch, Yaw, Roll) ?

Is it an R(), a Q(), a V() ? You just typed a tuple without the preceding letter identifying what type of tuple, and that was never a thing in the language.

Ooops, you're right, it was R(0-Pitch, Yaw, Roll).

The three argument form was in 0.92 - https://github.com/Nivekk/KOS/blob/f87b56f0ec27019798ef2ef85451133dd84e137d/Expression.cs#L434-L444

Link to comment
Share on other sites

is this a script error or a bug. github issue 674

Generally it's unnecessary to raise the same question both here, in reddit, and on github. When you make a github issue, the devs definitely see it right away. We both have alerts set to notice when a new one is posted there.

- - - Updated - - -

Ooops, you're right, it was R(0-Pitch, Yaw, Roll).

The three argument form was in 0.92 - https://github.com/Nivekk/KOS/blob/f87b56f0ec27019798ef2ef85451133dd84e137d/Expression.cs#L434-L444

There's a chance we may be able to eventually put the optional 3rd argument to HEADING back in place. The reason it was removed was that a change to the architecture made it impossible for a function to count how many arguments it was being passed. It had to hardcode a fixed number of args and stick with it. So optional Args didn't really work well anymore. But we may be on the way to being able to query how many args were passed, and make the built-in functions (like HEADING()) able to behave differently depending.

But even if so, it would still be a long way off yet. But it *might* come back some day.

Link to comment
Share on other sites

There's a chance we may be able to eventually put the optional 3rd argument to HEADING back in place.

But even if so, it would still be a long way off yet. But it *might* come back some day.

Any chance of a HEADING3, or ROLLHEADING, or something similar in the interim? I'd do it myself but, while this is trivial change, working out how to use Windows as a build environment (or, in fact, anything other than a games launcher) is beyond me.

Edited by JoCRaM
Link to comment
Share on other sites

Any chance of a HEADING3, or ROLLHEADING, or something similar in the interim? I'd do it myself, but while the programming is trivial, working out how to use Windows as a build environment (or, in fact, anything other than a games launcher) is beyond me.

it is easy using kOS:


set pitchvector to heading(160,90-pitch).
lock steering to lookdirup(pitchvector:vector, ship:facing:topvector).

you can replace ship:facing:topvector with any vector pointing at "up" for the roll you like

Edited by Ziw
Link to comment
Share on other sites

it is easy using kOS:


set pitchvector to heading(160,90-pitch).
lock steering to lookdirup(pitchvector:vector, ship:facing:topvector).

you can replace ship:facing:topvector with any vector pointing at "up" for the roll you like

I'm glad it's easy.

Forgive me if I seem dense, but I've not fiddled about with vector maths for 14 months, I'd just like to get my existing scripts working in KSP 0.90. what do I replace my lock with in this fragment

SET yaw TO 90.
SET pitch TO 90.
SET roll TO -90.

LOCK STEERING TO HEADING(pitch,yaw,roll)

given yaw pitch and roll will be fiddled with by other bits of the code, e.g.

 WHEN ALT:RADAR > 40 +MASS then {
SET mark TO TIME:SECONDS.
LOCK roll TO (TIME:SECONDS - mark)*7-90.
IF MASS < 50 {
LOCK roll TO -90-((ALT:RADAR-50)*.7).
}.
RUN att("reorientation start",missT).

WHEN ABS(roll)<1 then {
RUN att("reorientation end",missT).
LOCK roll TO 45 - (pitch/2).
}.
}.
WHEN VERTICALSPEED>100 THEN {
LOCK pitch TO 90 - [...].
PRINT "fakity turn started".
}

Unless I'm missing something "LOCK STEERING TO HEADING(0,0)*R(yaw,0-pitch,roll)." is going to be simpler?

Edited by JoCRaM
Link to comment
Share on other sites

Some variant of this might work for you:


// Assuming you have these three variables already:
// __compass__, __pitch__, __roll__
// (the underscores are just there to help you see where they plug into the
// code below)
//

// make pointVec the vector direction to point:
lock pointVec to heading( __compass__, __pitch__):vector.

// make topVec the vector pointing to the desired topward direction of your ship:
lock topVec to angleaxis( __roll__, pointVec) * ship:up:vector.

// make a lookdirup out of those two:
lock STEERING to LOOKDIRUP( pointVec, topVec).

Link to comment
Share on other sites

is there any way to print the same message to the console and a log file without having to use two separate commands? Just double-checking before I bother to add an issue for it.

Not that I have found.

If it is so that you can view printed messages after they go off the screen you could use telnet. It keeps everything and has a scroll bar, at least it does in the Linux terminal.

Link to comment
Share on other sites

If it is so that you can view printed messages after they go off the screen you could use telnet. It keeps everything and has a scroll bar, at least it does in the Linux terminal.

Good point, I forgot I've been meaning to take the time to get that set up

Link to comment
Share on other sites

Hey! Really love the mod (although admittedly I'm terrible at it lmao - wish I'd kept up my maths since school...) :D

I was just wondering if there are any plans eventually to add RPM IVA support?

Several people have started projects to do this but all have petered out without results. I dont have time to implement it but I would be happy to work with someone who wants to make it happen.

Link to comment
Share on other sites

Not that I have found.

If it is so that you can view printed messages after they go off the screen you could use telnet. It keeps everything and has a scroll bar, at least it does in the Linux terminal.

In the telnet server's current implementation you can't quite use the scrollback buffer reliably that way. It only works if the things you printed to the screen were printed *slowly* to the screen. If you spew a lot of text to the screen all at once, such as with a PRINT SHIP:PARTS. or a LIST FILES, or something like that, then the rate at which it gets printed exceeds the rate at which the telnet server updates the client. So let's say that LIST FILES ends up spewing about 3 screenfulls of text all at once. Chances are very high that the telnet server will only send your telnet client the characters of the lastmost screenful of that.

The telnet server's goal is to make your telnet window look like the in-game GUI Window, which it does by diff'ing what it believes your telnet client window actually looks like at the moment against what the window should look like at the moment, and sending the right characters to make the difference happen. It does this about 20 times a second. If the printout is faster than that, then the telnet server only tries to make your client look like it should NOW, not to send it the intervening text that has already scrolled by before it ever got sent to you.

That being said, you can hit PageUp or PageDown to scrollback, but that's actually causing the server to send you new screenfulls, in our software, rather than it being your telnet client doing it (and it also works in the in-game GUI terminal to do that).

Edited by Steven Mading
DISABLING SMILEYS SHOULDN'T REQUIRE "GO ADVANCED" DAMMIT!!
Link to comment
Share on other sites

Hi!

Is there a possibility to display flight data in a graphic and not only in values?

Depends what you mean. You can do ASCII art style graphs and GUIs in the terminal and vecdraw lets you create on screen arrows. But you have to write/ find a script that turns your numerical flight data into a graph.

Link to comment
Share on other sites

So I got the four necessary mods, downloaded the .craft. All installed fine but when I opened it in the SPH the legs were missing. The knee and ankle joints were there but nothing in between. Could someone give me a mirror download or some advice (I.e should I use earlier versions of IR or tweakscale, etc)

Thanks in advance for your time,

Eerf

Link to comment
Share on other sites

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