Jump to content

[1.3] kOS Scriptable Autopilot System v1.1.3.0


erendrake

Recommended Posts

after studying  PROFILERESULT(), is gets much clearer. ;-)

one question left:
how the reduce power consumtion for user-input ?

I run a lot of code but still one "on ag1 {preserve. ...}" consumes 99% of the energy over time. This seems unbalanced.

I can work around it in most cases, but not for userinput (on button1:pressed , on abort , ... )

(A weird workaround would be a second core powered down, powered up in the action groups, checking for changes then)
 

Link to comment
Share on other sites

17 hours ago, hvacengi said:

Does this reliably happen to you every time?  I had a similar error one time (but only once) in a convoluted set of steps (dock with station in orbit, transfer to the mun, undock, try to land, crash into the surface destroying the entire lander, revert to launch) so I wasn't able to reproduce it.  The method itself that throws the error is actually pretty simple, and I thought it was already null safe.  I suspect that it is somehow related to docking (since both of our instances involved docking) but I'm not really sure how that's possible.  I only see one error in the log you linked, did I miss the first one somewhere, or are you referring to the AGExt error?  The AGExt error is in a set of error fixes that are pending for the next release (and I really need to finish making the review edits).

Yes it happens every time when the vessels dock. I'm not exactly sure what I'm referring to either. That's just the area where docking happens and thighs most likely went wrong. Maybe it's because of some sort of cyclic docking because there are two ports? If you want I can send you the save and the script to reproduce it.

EDIT: Turns out all it does is just unlock STEERING and THROTTLE. I have to reassign those after docking but then it continues fine.

Edited by EmbersArc
Link to comment
Share on other sites

17 hours ago, sebseb7 said:

I run a lot of code but still one "on ag1 {preserve. ...}" consumes 99% of the energy over time. This seems unbalanced.

I'm not sure what exactly you mean by "99%", do you mean over time it consumes the full storage capacity of the probe or that it consumes 99% of the largest "kOS Average Power" field?  By default the parts that ship with the mod consume 0.000004EC per instruction.  If you look at the profile of the `on` trigger, you'll see that every tick it evaluates the condition.  I just checked the simple example of `on ag1 { reboot. }` with no other program running and read an average power of 0.003EC/s.  If you are still executing logic at the same time, the other instructions will also add up.  Even if you are not executing any code at all, there is at least one instruction executed every tick (the end of program instruction) so there is no way to reach exactly 0EC/s (though it's pretty close when not running a program).  If you have a bunch of other triggers active at the same time as your AG1 trigger, each condition evaluation will consume more power.  If you're seeing the EC/s always maxed out (the max should be 0.4EC/s at 2000 IPU and 50FPS) and your program should be idle, we might need to look into potential wasted instructions in the script somewhere.

11 hours ago, EmbersArc said:

Yes it happens every time when the vessels dock. I'm not exactly sure what I'm referring to either. That's just the area where docking happens and thighs most likely went wrong. Maybe it's because of some sort of cyclic docking because there are two ports? If you want I can send you the save and the script to reproduce it.

EDIT: Turns out all it does is just unlock STEERING and THROTTLE. I have to reassign those after docking but then it continues fine.

Do you mean that by unlocking the two controls you can prevent the error entirely?  Or do you mean that the effect is that the steering and throttle both get unlocked upon docking?  This is "more" possible with throttle than steering, since the two use separate methods to subscribe to "autopilot events" (for now), but may still be possible with both if the previous vessel, the one that had the locks enabled, is not the dominant vessel.  That is to say if the ship you're flying technically gets destroyed because it's merged with the 2nd craft it is possible for the timing to be such that the locks are thrown away.

But I'm more curious to see if it removed the error messages entirely.  And if you could clarify: did just the throttle/steering lock issue happen every time, or did the error message happen every time?  I haven't tested docking on the ground much, but I have extensive docking tests in orbit and haven't seen that error message, so I'm curious to see if I need to add a new test case.

There's also a chance that the claw is complicating things.  While it is very similar to a docking port, it isn't exactly the same.  I just found out that it doesn't increase the count of "elements" on a vessel.  So it's possible that it's "docking" behavior is enough different that we get unexpected behaviors.

Edited by hvacengi
Link to comment
Share on other sites

2 hours ago, hvacengi said:

I'm not sure what exactly you mean by "99%", do you mean over time it consumes the full storage capacity of the probe or that it consumes 99% of the largest "kOS Average Power" field? 

simple example: 
I have a battery with 100 EC

in a given period of time all the code I run consumes 1 EC, while the ONE trigger that is ALWAYS active on ag1 consumes 99 EC.

so all the launch, transfer, landing, deorbit, etc, etc code, consumes 1%, and the one trigger for opening the gui consumes 99%. 

So most of the battery of the vessel is not there for all the calculations, but just for the one trigger for user interaction. 

Edited by sebseb7
Link to comment
Share on other sites

2 hours ago, sebseb7 said:

simple example: 
I have a battery with 100 EC

in a given period of time all the code I run consumes 1 EC, while the ONE trigger that is ALWAYS active on ag1 consumes 99 EC.

so all the launch, transfer, landing, deorbit, etc, etc code, consumes 1%, and the one trigger for opening the gui consumes 99%. 

So most of the battery of the vessel is not there for all the calculations, but just for the one trigger for user interaction. 

How do you come by that figure of how much EC is consumed by the various portions of the code?  Depending on the timing of the mission and how complex your other script logic is, it is very possible that the trigger is executed often enough to be a significant contributor to the total EC usage.  So my question is: when only the `on ag1` trigger is running, what is the value for "kOS Average Power" on the right click menu of the cpu part?

I'm trying to figure out if you are observing higher than expected power consumption, or if you're just commenting on/observing the intended behavior that an idle waiting processor still consumes power.

If the power consumption is higher than expected I will want to test the script you are running, preferably with the original craft file and/or a save file.  If our power consumption is broken, we need to fix it.

Link to comment
Share on other sites

2 hours ago, hvacengi said:

How do you come by that figure of how much EC is consumed by the various portions of the code?  Depending on the timing of the mission and how complex your other script logic is, it is very possible that the trigger is executed often enough to be a significant contributor to the total EC usage.  So my question is: when only the `on ag1` trigger is running, what is the value for "kOS Average Power" on the right click menu of the cpu part?

I'm trying to figure out if you are observing higher than expected power consumption, or if you're just commenting on/observing the intended behavior that an idle waiting processor still consumes power.

If the power consumption is higher than expected I will want to test the script you are running, preferably with the original craft file and/or a save file.  If our power consumption is broken, we need to fix it.

if I let the ship just do its housekeeping task it consumes just 0.1EC per hour. If I also activate a trigger to wait for a single key input it consumes 10EC per hour. 

any active trigger consumes >= 0.001/s  (depending on the length of the expression), the trigger is never really executed, just the "on ag1" part. 

I observe totally expected power consumption. 

The point is: over the long run, is feels unbalanced that waiting for a keypress consumes 99% of the energy. 

suggestion: events you don't have to poll. or some kind of powersave mode, where you can "underclock" the cpu, if you're just waiting for input.
If you open a gui window with a lot of "on buttonx:pressed" triggers, power consumption goes way up, just to watch for the buttons. 

1 hour ago, TheRagingIrishman said:

I'm an experienced KSP player and a competent programmer (self-taught Java and a few other languages) and would love to get into KOS. 2 questions I have are

  1. is the stuff on http://ksp-kos.github.io/KOS_DOC/index.html up to date?
  2. what IRL language is kerboscript most similar to?

 

is up-to-date. difficult to compare kerboscript. the concept is weird, but fun. 

it feels a little bit like microcontroller software development. 

I started learning kerboscript a few weeks ago and now launch, deorbit/chute sequence, land on mun, ascent from mun, node exeution, etc. etc. is working fine already. 

plotting in realtime is also fun: 

 

Link to comment
Share on other sites

13 hours ago, hvacengi said:

Or do you mean that the effect is that the steering and throttle both get unlocked upon docking?  This is "more" possible with throttle than steering, since the two use separate methods to subscribe to "autopilot events" (for now), but may still be possible with both if the previous vessel, the one that had the locks enabled, is not the dominant vessel.  That is to say if the ship you're flying technically gets destroyed because it's merged with the 2nd craft it is possible for the timing to be such that the locks are thrown away.

Yes that's what I mean. It happens every time the vessels dock and I can confirm that both throttle and steering get unlocked.

13 hours ago, hvacengi said:

But I'm more curious to see if it removed the error messages entirely.  And if you could clarify: did just the throttle/steering lock issue happen every time, or did the error message happen every time?  I haven't tested docking on the ground much, but I have extensive docking tests in orbit and haven't seen that error message, so I'm curious to see if I need to add a new test case.

The "ADDON BINDER: Cannot resolve assembly: AGExt, Culture=neutral, PublicKeyToken=null" message seems to disappear when I re-lock throttle and steering.

This however is not that big of a problem. More annoying is the first error I described:

wdbs6j1.png

I'm not sure if it's related. That's the one that pops up about in about 40% of the cases when I launch the script.

The log also regularly prints this error:  "kOS: SteeringManager.Update: Value is <null>"

Link to comment
Share on other sites

5 hours ago, sebseb7 said:


suggestion: events you don't have to poll. or some kind of powersave mode, where you can "underclock" the cpu, if you're just waiting for input.
If you open a gui window with a lot of "on buttonx:pressed" triggers, power consumption goes way up, just to watch for the buttons.

Hold on, this is the first you mentioned that these triggers are for the GUI - I assume you mean @Waz 's gui system?  Because in current (not-GUI) kOS, an "on" trigger shouldn't consume a lot of power.  Every tick it wakes up, performs the few instructions that are in your boolean conditions in the triggers, and then goes back to sleep.  That should be nowhere near as much electric drain as when you're just running a busy loop - not even close.  Is the GUI system doing something more than that?

 

Edited by Steven Mading
Link to comment
Share on other sites

5 minutes ago, Steven Mading said:

Hold on, this is the first you mentioned that these triggers are for the GUI - I assume you mean @Waz 's gui system?  Because in current (not-GUI) kOS, an "on" trigger shouldn't consume a lot of power.  Every tick it wakes up, performs the few instructions that are in your boolean conditions in the triggers, and then goes back to sleep.  That should be nowhere near as much electric drain as when you're just running a busy loop - not even close.  Is the GUI system doing something more than that?

I don't think that's what he is saying.  I think he's just saying that if you add a bunch of triggers all evaluating simultaneously, their combined power draw can add up very quickly.  I assume (but would like confirmation) that the EC/s of 10 active button "pressed" triggers is equal to 10 times the EC/s of a single button "pressed" trigger.  @sebseb7 please correct me if I am incorrect in that assumption.

6 hours ago, sebseb7 said:

if I let the ship just do its housekeeping task it consumes just 0.1EC per hour. If I also activate a trigger to wait for a single key input it consumes 10EC per hour.

...

suggestion: events you don't have to poll. or some kind of powersave mode, where you can "underclock" the cpu, if you're just waiting for input.
If you open a gui window with a lot of "on buttonx:pressed" triggers, power consumption goes way up, just to watch for the buttons. 

Again, I would need to look at your script to be able to comment on the performance.  If your "house keeping" uses a lot of "wait" commands to pause execution, yes it will be more power efficient.  A straight "wait 1." command will consume a total of 2 instructions over the entire 1 second wait period.  The cpu already "underclocks", it effectively reduces the clock speed to be exactly the number of instructions that you want to execute that physics tick.  And "wait" is the power save mode.  If you instead poll ag1 from inside your wait loop, you'll save a large number of instructions.  If the loop waits only 1s, you should see about 1/50th the EC/s for the polling and there would not be a substantial delay.

We have talked about allowing kOS to call user delegates based on certain game conditions similar to events.  But it requires a change to how instructions are currently executed.  Given the existing backlog of features and bugs, I don't know where it falls on the priority list.  But that's a discussion best suited for Github, where we can track and assign the issue, as well as keep the conversation around the feature in a single thread.

You would have hated the prior EC usage model, which was based solely on the size of the current hard disk.  It didn't matter if you used 1 instruction or 2000, the EC/s remained the same.

Link to comment
Share on other sites

2 minutes ago, hvacengi said:

I don't think that's what he is saying.  I think he's just saying that if you add a bunch of triggers all evaluating simultaneously, their combined power draw can add up very quickly.  I assume (but would like confirmation) that the EC/s of 10 active button "pressed" triggers is equal to 10 times the EC/s of a single button "pressed" trigger.  @sebseb7 please correct me if I am incorrect in that assumption.

Again, I would need to look at your script to be able to comment on the performance.  If your "house keeping" uses a lot of "wait" commands to pause execution, yes it will be more power efficient.  A straight "wait 1." command will consume a total of 2 instructions over the entire 1 second wait period.  The cpu already "underclocks", it effectively reduces the clock speed to be exactly the number of instructions that you want to execute that physics tick.  And "wait" is the power save mode.  If you instead poll ag1 from inside your wait loop, you'll save a large number of instructions.  If the loop waits only 1s, you should see about 1/50th the EC/s for the polling and there would not be a substantial delay.

We have talked about allowing kOS to call user delegates based on certain game conditions similar to events.  But it requires a change to how instructions are currently executed.  Given the existing backlog of features and bugs, I don't know where it falls on the priority list.  But that's a discussion best suited for Github, where we can track and assign the issue, as well as keep the conversation around the feature in a single thread.

You would have hated the prior EC usage model, which was based solely on the size of the current hard disk.  It didn't matter if you used 1 instruction or 2000, the EC/s remained the same.

again. I don't observe anything incorrect, no need to look at specific code 

Its just that I made my code very power-efficient, and the last remaining big power consumer is: the triggers.

Of corse I could use my own trigger system, where I have one big loop with a dynamic wait. that sure consumes much less power. 

if all my code would be:
on ag1 {stage.}
 

this consumes way too much power compared to other operations (It does draw exactly as much has expected). Its just my feeling that this is unbalanced. A loop with a wait would be cheaper, but this would be normally the job of the trigger. to deliver a more efficient method than looping. 

the way it is implemented now leads to a lot of dirty hacks to conserve power. for example: 
on ag1 {stage.}
would be much cheaper to have just "stage." in the boot script and to power up the core using the ag1 action group. This way no power is consumed while waiting for a keypress but still I have my action on ag1. 
 

1 hour ago, Steven Mading said:

Hold on, this is the first you mentioned that these triggers are for the GUI - I assume you mean @Waz 's gui system?  Because in current (not-GUI) kOS, an "on" trigger shouldn't consume a lot of power.  Every tick it wakes up, performs the few instructions that are in your boolean conditions in the triggers, and then goes back to sleep.  That should be nowhere near as much electric drain as when you're just running a busy loop - not even close.  Is the GUI system doing something more than that?

 

it had nothing to do with the gui.

Link to comment
Share on other sites

Ok I have now written a script that can get different ships to orbit reasonably effectively and another scipt that can transfer to low mun orbit from LKO.

However when I started to write a script that could land the ship on mun I noticed that alt:radar seems measure altitude to "sea-level" rather than to the actual ground.

I couldnt understand why I was hitting the ground so fast every time so I told the script to print alt:radar on every iteration of the loop and it turned out that it printed the same numbers as the big altitude meter in the game shows (and that measures to "sea-level"). Simultaneously KER confirmed my results by showing the actual altitude to surface which was almost 3 km less...

Is alt:radar working properly for everyone else?

Edited by tseitsei89
Link to comment
Share on other sites

18 hours ago, sebseb7 said:

 

this consumes way too much power compared to other operations (It does draw exactly as much has expected). Its just my feeling that this is unbalanced. A loop with a wait would be cheaper.

These two shouldn't be significantly different in power draw:

// trigger way:
on ag0 {
  print "action group 0 changed its value".
}.
wait until false. // sit forever doing nothing.

// equivalent loop way:
set prev_ag_val to ag0.
until prev_ag_val <> ag0 {
  wait 0.
}.
print "action group 0 changed its value".

Both wake up once a tick and run the few instructions needed to perform the check.

The reason it can't be done as an interrupt is because the ``on`` trigger works with any generic expression of any sort that returns any value.  It keeps a memory of the previous value the expression returned and compares it to the new value it returned this time around.  If they are unequal, it fires the trigger off, else it returns and does nothing.  Because it works with anything, not just action groups - it has to be designed to run any generic expression you choose to put in there, and that means it has to execute some instructions to push the expression's return value onto the stack.  You could just as easily do something like:

ON x+y/3*myfunc()*2 {
  do_stuff().
}

What I don't understand from your description is your claim that doing it with "a loop with a wait" is cheaper.  What might be cheaper is implementing a second, new, system of firing off events you can register to, but that's not "a loop with a wait" either.  The polling is going to be pretty much the same whether done with ON or with your own homemade loop.  What's needed to get rid of that power draw is something that is neither the ON trigger nor a user loop, but an ability to register a user function with kOS and have kOS execute it when it decides to (using its own C# code to make the decision whether its time to invoke the callback, and not running any kerboscript code if the answer is no.)

Edited by Steven Mading
Link to comment
Share on other sites

to conserve power I now do:

until false {
   test_for_key().
   wait 0.5.
}

on (event) call() could be a feature of the architecture, not of the compiler. then it would be "cheaper".

but in the end this is not really an issue. 
 

Link to comment
Share on other sites

3 hours ago, sebseb7 said:

to conserve power I now do:

until false {
   test_for_key().
   wait 0.5.
}

on (event) call() could be a feature of the architecture, not of the compiler. then it would be "cheaper".

but in the end this is not really an issue. 
 

Ahhh. Now it finally becomes clear.  I don't remember seeing you mention the 0.5 before.  In order to do the *same* thing, you'd need that to be a WAIT 0 rather than a WAIT 0.5.  (As I was showing in my examples above, and assumed you were doing from your descriptions of the loop being designed to have the "same" effect.  This is not the "same" effect.  With the trigger, the program would respond within about 1/25th of a second.  You decided you didn't need that quick response so you slowed it down.)

We could maybe add the ability to pick a "frequency" to triggers to get the same effect:

EVERY 0.5 ON AG10 { stuff },  or EVERY 0.5 WHEN Foo THEN { stuff }

Link to comment
Share on other sites

1 hour ago, Steven Mading said:

Ahhh. Now it finally becomes clear.  I don't remember seeing you mention the 0.5 before.  In order to do the *same* thing, you'd need that to be a WAIT 0 rather than a WAIT 0.5.  (As I was showing in my examples above, and assumed you were doing from your descriptions of the loop being designed to have the "same" effect.  This is not the "same" effect.  With the trigger, the program would respond within about 1/25th of a second.  You decided you didn't need that quick response so you slowed it down.)

We could maybe add the ability to pick a "frequency" to triggers to get the same effect:

EVERY 0.5 ON AG10 { stuff },  or EVERY 0.5 WHEN Foo THEN { stuff }

every microcontroller has a counter that gets decremented by x per cycle and calls a function when reaching zero. 

Such timers allow the dynamic chance of the sleep period (decrements per cylcle).

So something like:

set delay to 0.5
every delay when true then { set delay to new_delay. return true.} 
would be nice.

usually you have at least 4 registers (the address of the function, the counter, the decrement and the configuration register (on/off,up/down,etc)).


for debugging power consumption a statistic info where I can see all currently active triggers with their expressions would be great.

Edited by sebseb7
Link to comment
Share on other sites

3 minutes ago, sebseb7 said:

every microcontroller has a counter that gets decremented by x per cycle and calls a function when reaching zero. 

Such timers allow the dynamic chance of the sleep period.

So something like:

set delay to 0.5
every delay when true then { set delay to new_delay. return true.} 

would be nice.

for debugging power consumption a statistic info where I can see all currently active triggers with their expressions would be great.

Right now every trigger can return a true or false value for whether or not to preserve the trigger.

A much simpler looking design would be to just let you return a number, and that's the number of seconds to wait before checking the trigger again.

Due to the odd runtime type dynamic nature of kOS, you could even return either a boolean or a number.  If its a number we assume you meant "true" as well as telling us the delay (thus return 0 would be different from return false.  return 0 would mean check the trigger again as fast as possible, and return false would mean don't check the trigger again.)

Link to comment
Share on other sites

Is there a way to check if a vessel name is valid? I'm trying to write 'set Target to Vessel("name")' in a way that does not crash the program if the vessel name does not exist (because it is docked to something larger).

Link to comment
Share on other sites

6 hours ago, pellinor said:

Is there a way to check if a vessel name is valid? I'm trying to write 'set Target to Vessel("name")' in a way that does not crash the program if the vessel name does not exist (because it is docked to something larger).

You could loop through all vessels in the game (LIST TARGETS IN my_list...), comparing their names to the one you're looking for, until you either find one or finish the list.

Link to comment
Share on other sites

3 hours ago, ElWanderer said:

You could loop through all vessels in the game (LIST TARGETS IN my_list...), comparing their names to the one you're looking for, until you either find one or finish the list.

Must have overlooked that. Thanks!

Link to comment
Share on other sites

This is one of the most awesome mods I have ever tried! The possibilities are endless! I am just new to this so struggling with my first bits of code.

I know the WHEN/THEN triggers are not specifically for beginners, but I think I understand the logic & syntax behind them so I would like to use them - sadly I still cannot make my simple code work. 

I want to make a script that turns my Drills ON or OFF depending on the current Electric Charge levels on my ship. I solved this (most surely not the right way, but did it anyways).

EDIT: figured out the script is stuck waiting for WAIT UNTIL SHIP:ELECTRICCHARGE < 100 hence WHEN:SHIPWATER = 144 is never executed. However re-wrote the code and still can't make it work, details in next posts.

My main issue is that I want to set-up a Trigger with WHEN/THEN and PRESERVE it for my program to keep checking whether the condition is met or not as this might happen in the future and not the first time the flow of the code reads the WHEN/THEN statement.

My WHEN/THEN statement needs to check whether my Water tanks (resource I am extracting with my Drills) are full or not. If they are, the Drills need to be shut-down.

The code I have written is the following:

CLEARSCREEN. PRINT "==== EXECUTING DRILLING SCRIPT - DRILLING PROGRAM ACTIVATED".

WAIT UNTIL SHIP:ELECTRICCHARGE>100.
 {
  TOGGLE AG2.                                    //Action Group that deploys the Drills
  PRINT "===== DRILLS ACTIVATED".
  SET AG2 TO FALSE.
 }

WAIT UNTIL SHIP:ELECTRICCHARGE<100.
 {
  TOGGLE AG3.                                    //Action Group that shuts-down the Drills
  PRINT "===== DRILLS SHUT-DOWN".
  SET AG3 TO FALSE.
 }

WHEN SHIP:WATER=144 THEN {                       //Trigger I am having issues with and cannot make it work
 TOGGLE AG3.                                     //Trigger I am having issues with and cannot make it work
 PRINT"===== WATER FULL, DRILLS SHUT-DOWN".      //Trigger I am having issues with and cannot make it work
 PRESERVE.}.                                     //Trigger I am having issues with and cannot make it work
RUN DRILLING.                                    //VERY LAME solution for not being able to work the WHEN/THEN statements. 
                                                 //As I don't know how to make my code to keep checking if EC is < or > than 100, I need to
                                                 //do this to get the code running again (would love to learn how to avoid this very disgraceful solution)

I would really love a helping hand from the experts out there! 

Keep in mind -as one can obviously infer from reading my disgusting code- I am an utter beginner. I understand the logic of the operations but still not familiar with the syntax and best-practices.

Cheers and thanks in advance! :D

Edited by hypervelocity
Link to comment
Share on other sites

9 minutes ago, hypervelocity said:

<snip>

I would really love a helping hand from the experts out there!

Cheers and thanks in advance! :D

I'm not an expert, but from my limited experience I would suggest changing the trigger from "WHEN SHIP:WATER=144 THEN..." to "WHEN SHIP:WATER<144 THEN..." (or >, whatever works best for you).

Or is it throwing some kind of error message? In that case I probably don't know what to do.

Edited by EpicSpaceTroll139
Link to comment
Share on other sites

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