Jump to content

kOS Scriptable Autopilot System 0.9


KevinLaity

Recommended Posts

I froze KSP! I tested it and it will freeze a fresh kOS. This should give a Syntax error.

Set DirectionX to R(100,100,100.

razark, I had the same problem when creating programs to use as resusable functions. It isn't just THROTTLE or STEERING, it is other LOCK variables as well.

Code example 1: Only THROTTLE lock inherits from parent

Set x to 1.
lock throttle to x. // causes throttle to 100%
lock y to x.
run ProgA.
set x to 0.5. // throttles down to 50%.
print y. // prints "1" not "0.5" as expected
print throttle. //prints "0.5" as expected
Program Ended.
print y. // prints 0.5 as expected
//throttle remains at 50%

I am thinking that THROTTLE is passed as a reference (pointer) and easily inherits the LOCK from the parent program (or kOS console). Other LOCK variables are passed as a value instead of a reference. Once out of the program, the LOCK returns to normal in the parent that originally LOCKed the variable.

Code example 2: No lock inherits from child
run ProgB.
Set x to 1.
LOCK THrottle to x. //Throttle to 100%
LOCK y to x.
run ProgC.
set x to 0.5. //Throttle to 50%
print y. //Prints 1 - expected 0.5
Program Ended.
print y. //prints 0.5 as expected
Program Ended.
//Throttle value remains 1 but returns to 0%
set x to 0.75. // Throttle remains at 0%.
print y. //prints 0.5 - expected 0.75.

It appears that LOCKs made in a child program are converted to SET variables when it returns to the parent program (or console).

Link to comment
Share on other sites

Maybe you could start with the terminal's ID number, then add to it for root parts?

This would also mean you could run two terminals without interfering with each other's parts.

This was my suggestion for saveable bus parts, but it got buried without being replied to.

Link to comment
Share on other sites

We're definitely on the right track with this. But I want to have a part-registration model where parts register themselves with kOS.

I think there's a few benefits to that:

- LIST PARTS can be made list only the kOS compatible parts

- I can then easily address individual parts

- The mod developer can decide exactly what messages to get

- We can potentially offer bindings that work with SET, PRINT etc

- We can potentially give mod developers the ability to come up with their own commands.

I like the idea of registering with KOS but it may be a more interesting ride than you might think.

I've taken apart enough of Infernal Robotics (to use my favorite example) to know that it maintains its own internal list of parts that it uses for its servo groupings.

When you click a GUI element the event goes to the DLL which looks up the parts and starts a physics change on each one of them.

It's pretty slick and perhaps some of the coding techniques can be borrowed for this project as well, perhaps store a master list of API functions in a list alongside the actual method calls and part IDs.

The gotcha with addressing parts individually is that sometimes you want to address more than one part at once

The gotcha with SendMessage is that it's a broadcast over the entire gameobject, so technically all parts will "listen" to a sent message but only the ones that implement a given method will actually do anything about it.

The reason for all this foofaraw is that IR, for all its ability, stores its own part grouping independent of the game. To my knowledge IR is the only mod that does things this way but it's an interesting approach that addresses a lot of limitations in the core game and more mod authors may pick up on it if there is sufficient complexity in their mod that they need it.

IR Servo Groups are different than KSP Action Groups and are only addressable via the IR plugin DLL method calls that every part instantiates.

It may be possible to just enumerate the parts and then get the methods off each part and then call the individual parts to get the rest of it and build a tree internal to KOS. I'll have to do some playing on that one.

Link to comment
Share on other sites

You can, but I was having problems with it.
If I run a program from inside another program, the steering and throttle commands don't seem to respond.

For example:


//Program1
...
IF [i]condition[/i] { RUN [i]program2[/i]. }.
...
//End Program1


//Program2
...
PRINT "Prograde".
LOCK STEERING TO PROGRADE.
LOCK THROTTLE TO 1.
PRINT "Burning.".
...
//End Program2

When condition is met, program2 runs. It will print "Prograde", but the ship never turns. Likewise, the "Burning" message is printed, but the throttle never activates. SAS is off. I'm trying to set up a menu system, and I'd rather not stick all my code into one program. Any ideas?

Program runs fine on it's own, but steering and throttle commands have no result when run from another program.

I noticed that steering and throttle don't cooperate with me unless I have them in lowercase. You might try that.

Link to comment
Share on other sites

I've been working on a reentry program for my shuttle and come to find out that the longitude coordinates don't make sense. I can do one orbit, and they kind of correspond to the coordinates displayed by MechJeb or the Kethane grid, but recently discovered that it jumps from -74 degrees to 298 degrees, and then counts up into the 400s where it jumps back down to something else.

Since I'm trying to coordinate a reentry program based on ground coordinates, it would be nice to have them stay the same throughout a flight. I don't mean to be overly critical, I just wanted to see if there was anything I had missed, or if this is a feature that has yet to be fully developed. I can't tell you how much I love this mod. It has enabled me to create programs that get asymmetrical shuttles into orbit and (occasionally) get shuttles back to the runway with extreme accuracy.

Link to comment
Share on other sites

I would definitely like kOS to be able to interact with MechJeb. Would be really nice to launch a LazTek Falcon and to let the spent stages return to KSC on their own, while taking care of the payload. Unload-distance should be no matter, as this is taken care for by another plugin (TT NeverUnload).

Greetz

AN

Link to comment
Share on other sites

I noticed that steering and throttle don't cooperate with me unless I have them in lowercase. You might try that.

It's not the capitalization. Note the part that said "Program runs fine on it's own...". The code is actually lowercase.

Link to comment
Share on other sites

It's not the capitalization. Note the part that said "Program runs fine on it's own...". The code is actually lowercase.

Ahh, my mistake. Guess that's what I get for skimming over the post.

Link to comment
Share on other sites

Just started playing with this. It's neat. I like the idea.

But. There are some things that really can be irritating:

1 - Why can't we edit with our own text editor? There are lots of programming editors out there that are really good. Lacking their features can be really annoying once code gets longer. It would be nice if there was just a way to access the programs as raw text files and edit them behind the scenes with whatever tool we want. Me, I'm really old-school and use "vi", but to each his own. But the point is, let us pick.

2 - The picky nerd in me really rankles at referring to scalar speed as "velocity". Velocity is a term that physicists use ONLY when talking about a vector. When the directional information is removed, then it's called just "speed". In this game, the *actual* velocity is VELOCITY * PROGRADE. (Scalar speed times the prograde direction to get the velocity vector.) Please consider calling it just "speed" to avoid confusion. The longer you wait to do this the harder it will be to make the change because people will be mad that their scripts broke.

3 - Are there comments in the syntax? If not there really should be. I tried "//" because some of the examples in the readme appear to be using that, but it doesn't seem to work and registers as a syntax error.

4 - Consider an alternative to the WHEN statement that actually re-executes the section every single time the condition happens in the checking cycle, effectively turning the body into an infinite loop with an if condition at the top. This would feel a lot like how event handling works in many languages. In fact I thought this is what WHEN did until I found out the hard way it only executes once. It seems to set up a watch for a condition, and then immediately unregister it after it triggers. Perhaps the new statement could be called the WHENEVER statement.

The way it works now it's impossible to set up a check to re-trigger continually as long as a condition is true, since that would mean having to contain the body of the WHEN statement inside the body of the WHEN statement.

5. Consider WHEN conditions that get to live on past the end of the current program file. Since program files are the only way to effectively name subroutines, and since WHEN conditions do not fire once the program is terminated, it's not possible right now to make a named routine that sets up a condition to trigger. It would be nice to be able to, say, set up a routine to trigger when the altitude is low, and then turn it on with: "IF blah THEN RUN STARTLOWALTITUDEWATCHER.". But right now that doesn't work because when STARTLOWALTITUDEWATCHER finishes executing, all the WHEN conditions it set up go away.

6. Is it possible to activate the editor somehow inside the VAB? Right now all the code has to be typed out in the launchpad and that can be a problem when you have a battery operated kOS needing solar power and it's night. It seems really odd to be unable to write code for the computer for a vehicle until it's on the launchpad.

Link to comment
Share on other sites

I'm brainstorming and trying to discover avenues that can be explored that will meet as many of the possible use cases KOS could run into.

Here's what I've dreamed up so far, it's loosely based on a couple of networking protocols like IPX and TCP/IP and how a OBDII car network works (including OnStar or alarm gateway to an outside controller if you're into that).

KOS-NET Protocol <-- Right amount of description, probably not kerbal enough but will do for a working name until somebody comes up with something better.

Definition/Specifications

Version 0.00a

  • Supports network, part group, part class, individual part and method registration via broadcast to all KOS enabled parts inside the current vehicle.
  • Every KOS part has the capability to be a network client and controller in one, that way if two vehicles are created from one and they both have KOS on board, they both will have a viable network.
  • Supports basic stock part class integration - possible inheritance based new part class that would act as a drop-in replacement for existing part classes to add KOS support. Template for other authors?
  • Most users aren't going to be interested in addressing every docking light of their orbital shipyard individually. They're likely to be interested in addressing things as definable groups or by type.
  • Grouping and naming of individual parts in the VAB/SPH that stamps a field containing the group name onto the part instance - is this possible?
  • Supports rudimentary routing between different vehicles via doing a sendmessage to another vessel if somebody wants to write the distance/time delayed router code.
  • Stock and stock derived parts wouldn't have the full KOS functionality but there's no reason they couldn't be made to work.
  • Broadcast network simulated via Sendmessage is still the most viable message passing protocol because it just sends to all parts and doesn't care about things like part IDs.
  • Every part with public methods already supports sendmessage so less work is required to get things talking and more can be done to figure out what they need to talk about.
  • When KOS boots up or on part dock/detach/stage, it would broadcast a registration command to all parts inside the current vessel ID, they would respond with their payload including vessel ID.
  • Supports remote part discovery because the discovery command contains the originating network for the discovery request. Once routing is working, the rest falls into place.
  • KOS enabled parts register themselves by class, group name, name they'd respond to, type and method calls available (DHCP/DNS analogues) every time a network init broadcast is detected
  • This network model sidesteps the issues with traversing the entire part tree every time you need to refresh the parts list and the parts list being essentially a list of random IDs.
  • Internet-like resiliency to the vehicle network so when bits are docked or fall off (on purpose or accidently) the network can reshape dynamically without a lot of overhead.

Link to comment
Share on other sites

I get an error on line 21 of this code. Why? As far as I can tell everything is correct.

The only thing I could think of is if there is some odd reason that nesting an UNTIL inside a WHEN is not allowed. But I can't see why that would be the case.

Before you say it, obviously the text that says "// SYNTAX ERROR IS HERE. THIS IS LINE 21." was not originally in the code. Don't cite that as the reason for the error. I added that to show where the line is in this forum.


PRINT "HOVER ACTIVATED. ".
PRINT "WILL TRIGGER WHEN GROUND IS NEAR.".
PRINT "YOU MUST APPROACH GROUND GENTLY ENOUGH ".
PRINT "FOR YOUR TWR TO KILL FALlING SPEED.".
PRINT "THE APPROACH ABOVE 200 METERS IS NOT ".
PRINT "HOVER'S RESPONSIBILITY.".

SET COMMENT TO "ALT:RADAR IS -1 WHEN TOO HIGH ".
SET COMMENT TO "FOR RADAR TO WORK".

WHEN ALT:RADAR > 5 AND ALT:RADAR < 200 THEN
{
PRINT "SLOWING DESCENT.".
LOCK STEERING TO RETROGRADE.
UNTIL ALT:RADAR <= 5
{
IF VELOCITY > ALT:RADAR/5.0
LOCK THROTTLE TO THROTTLE + 0.05 .
IF VELOCITY <= ALT:RADAR/5.0
LOCK THROTTLE TO THROTTLE - 0.05 .
}.
}. // SYNTAX ERROR IS HERE. THIS IS LINE 21.

WHEN ALT:RADAR > 0 AND ALT:RADAR <= 5 THEN
{
PRINT "HOVERING.".
UNTIL ALT:RADAR >= 0 AND ALT:RADAR <= 1
{
IF VERTICALSPEED < 0
{
LOCK STEERING TO RETROGRADE.
LOCK THROTTLE TO THROTTLE + 0.05 .
}.
IF VERTICALSPEED > 0
{
LOCK STEERING TO PROGRADE.
LOCK THROTTLE TO THROTTLE - 0.05 .
}.
}.
}.

UNTIL ALT:RADAR >= 0 AND ALT:RADAR <= 1
{
PRINT "NOT ACTIVE YET.".
}.
PRINT "DONE.".

Edited by Steven Mading
Link to comment
Share on other sites

Just started playing with this. It's neat. I like the idea.

But. There are some things that really can be irritating:

1 - Why can't we edit with our own text editor? There are lots of programming editors out there that are really good. Lacking their features can be really annoying once code gets longer. It would be nice if there was just a way to access the programs as raw text files and edit them behind the scenes with whatever tool we want. Me, I'm really old-school and use "vi", but to each his own. But the point is, let us pick.

2 - The picky nerd in me really rankles at referring to scalar speed as "velocity". Velocity is a term that physicists use ONLY when talking about a vector. When the directional information is removed, then it's called just "speed". In this game, the *actual* velocity is VELOCITY * PROGRADE. (Scalar speed times the prograde direction to get the velocity vector.) Please consider calling it just "speed" to avoid confusion. The longer you wait to do this the harder it will be to make the change because people will be mad that their scripts broke.

3 - Are there comments in the syntax? If not there really should be. I tried "//" because some of the examples in the readme appear to be using that, but it doesn't seem to work and registers as a syntax error.

4 - Consider an alternative to the WHEN statement that actually re-executes the section every single time the condition happens in the checking cycle, effectively turning the body into an infinite loop with an if condition at the top. This would feel a lot like how event handling works in many languages. In fact I thought this is what WHEN did until I found out the hard way it only executes once. It seems to set up a watch for a condition, and then immediately unregister it after it triggers. Perhaps the new statement could be called the WHENEVER statement.

The way it works now it's impossible to set up a check to re-trigger continually as long as a condition is true, since that would mean having to contain the body of the WHEN statement inside the body of the WHEN statement.

5. Consider WHEN conditions that get to live on past the end of the current program file. Since program files are the only way to effectively name subroutines, and since WHEN conditions do not fire once the program is terminated, it's not possible right now to make a named routine that sets up a condition to trigger. It would be nice to be able to, say, set up a routine to trigger when the altitude is low, and then turn it on with: "IF blah THEN RUN STARTLOWALTITUDEWATCHER.". But right now that doesn't work because when STARTLOWALTITUDEWATCHER finishes executing, all the WHEN conditions it set up go away.

6. Is it possible to activate the editor somehow inside the VAB? Right now all the code has to be typed out in the launchpad and that can be a problem when you have a battery operated kOS needing solar power and it's night. It seems really odd to be unable to write code for the computer for a vehicle until it's on the launchpad.

1: you *can* edit files in the archive with any editor you like.

2: velocity *is* a vector.

6: you could add a new program to the archive folder before launch with your text editor of choice

Link to comment
Share on other sites

1: you *can* edit files in the archive with any editor you like.

I tried. I got "unrecognized term ''. " (that's two single-tick quotes with no string between them. The program is complaining that it doesn't recognize a zero-length term that's "in" my file. how Zen. All files "contain" zero length strings. An infinite number of them in fact. I have no idea what triggered this but it appeared after trying to use simple TextEdit on the achive file.)

2: velocity *is* a vector.

Then the readme file should be updated to show this. There's a section with the vectors listed and Velocity isn't one of them.

6: you could add a new program to the archive folder before launch with your text editor of choice

It's not ideal but it works. It just doesn't allow syntax checking until on the launchpad.

Link to comment
Share on other sites

I tried. I got "unrecognized term ''. " (that's two single-tick quotes with no string between them. The program is complaining that it doesn't recognize a zero-length term that's "in" my file. how Zen. All files "contain" zero length strings. An infinite number of them in fact. I have no idea what triggered this but it appeared after trying to use simple TextEdit on the achive file.)

Then the readme file should be updated to show this. There's a section with the vectors listed and Velocity isn't one of them.

It's not ideal but it works. It just doesn't allow syntax checking until on the launchpad.

Hm, I've had no trouble running programs I edited externally myself.

Could it be a line break problem? I saw some special handling for windows \r\n in the source code...

I don't see how being able to write scripts in the VAB/SPH would give you any syntax checking, but it would be nice to have.

Link to comment
Share on other sites

I get an error on line 21 of this code. Why?

It's the end of the UNTIL statement where you used an unrecognized operator. There's currently no "<=" or ">=" operators in kOS, you need to rework the logic using only "<" or ">".

I also have no problems with external editors. I prefer "joe", but you can use your evil editor if you prefer... :P

Incidentially, open a terminal and just type:

print 1>2.

(notice the output)

print 1<2.

(notice the output)

print 1>=2.

(notice the error -- look familiar? I suspect your problem has nothing to do with the external editor, it's just the lack of support for that operator)

Edited by Gaius
Link to comment
Share on other sites

Hm, I've had no trouble running programs I edited externally myself.

Could it be a line break problem? I saw some special handling for windows \r\n in the source code...

I assumed it was an ascii character it didn't know how to print in the font of the in-game console.

But after some more work I discovered that it's just confusing and misleading error reporting from the interpreter. What actually caused the error was many lines earlier, and it was that the language doesn't understand the less-than-or-equal-to operator "<=". It was complaining on the "=" sign but then reporting it very weirdly. I eventually got it through trial and error deleting different things until it stopped complaining. Whne I changed this:

UNTIL ALT:RADAR <= 10

to this

UNTIL ALT:RADAR < 10.00001

then it stopped complaining.

I don't see how being able to write scripts in the VAB/SPH would give you any syntax checking, but it would be nice to have.

Presumably it would be possible to pull out the parsing module from the C code for the plugin and make an external command-line tool. But at that point you're now dealing with platform compatibility issues. Also, the language seems to be interpreted on the fly rather than precompiled so I doubt it would be that much help. For example if you have an if condition then the body won't be syntax checked until the if condition is true in-game.

Link to comment
Share on other sites

(notice the error -- look familiar? I suspect your problem has nothing to do with the external editor, it's just the lack of support for that operator)

Sort of. The error was there all along but was being masked by an earlier error that the editor made go away.

It was because of the very confusing error message that I looked to the editor as the cause. It was telling me the term it didn't like was something that it was printing on the console as a nullstring. I assumed it wasn't really a nullstring, as that would be a silly thing to call a "term" in the syntax, but that it was trying to print some unprintable character. As it turns out, the error message really is printing a nullstring as the term it complains about, which is really misleading. I'd have expected it to complain about the '=' if that was the problem.

Link to comment
Share on other sites

Special variables like THROTTLE and STEERING do NOT in fact work if capitalized.

This fails: LOCK STEERING TO UP.

This works: LOCK steering TO up.

The description on the spaceport for this mod shows all the variables in uppercase. That is misleading and confusing if they don't really work when uppercased. Either the instructions should not be showing them uppercased, or the mod should be made to accept them uppercased. One or the other.

Link to comment
Share on other sites

Is there a way to multiply a scalar times a vector to change its magnitude, or reverse it? (for example (-1 * velocity) to the exact opposite vector to the velocity vector.)

Or conversely, can we explode out the component parts of a vector to do the work ourselves? (i.e. get the value of prograde.x, prograde.y and prograde.z as three different scalars for example. Then we could do our own math on them and rebuild the resulting 3 numbers into a vector again.)

Link to comment
Share on other sites

4 - Consider an alternative to the WHEN statement that actually re-executes the section every single time the condition happens in the checking cycle, effectively turning the body into an infinite loop with an if condition at the top. This would feel a lot like how event handling works in many languages. In fact I thought this is what WHEN did until I found out the hard way it only executes once. It seems to set up a watch for a condition, and then immediately unregister it after it triggers. Perhaps the new statement could be called the WHENEVER statement.

The way it works now it's impossible to set up a check to re-trigger continually as long as a condition is true, since that would mean having to contain the body of the WHEN statement inside the body of the WHEN statement.

I've been thinking on this, and concluded an IF inside an UNTIL will typically be the right approach for responding to a recurring situation. The use case for WHEN seems to be when a set of events might happen once each in arbitrary order, which is fairly niche.

Is there a way to multiply a scalar times a vector to change its magnitude, or reverse it? (for example (-1 * velocity) to the exact opposite vector to the velocity vector.)

Or conversely, can we explode out the component parts of a vector to do the work ourselves? (i.e. get the value of prograde.x, prograde.y and prograde.z as three different scalars for example. Then we could do our own math on them and rebuild the resulting 3 numbers into a vector again.)

Accessing the elements of a vector will also be essential for calculating the magnitude.

Edit: It's revealed in the 0.4 video (and apparently nowhere else) you can do X:pitch, X:roll, and X:yaw on R() structures. No word on V().

Edited by rhoark
Link to comment
Share on other sites

I've been thinking on this, and concluded an IF inside an UNTIL will typically be the right approach for responding to a recurring situation. The use case for WHEN seems to be when a set of events might happen once each in arbitrary order, which is fairly niche.

While you are correct that you can replace this looping model:

The WHENEVER trigger happens.

... do a thing.

The WHENEVER rigger is still true.

... do a thing again.

The WHENEVER trigger is still true.

... do a thing again.

The WHENEVER trigger is not true anymore.

done.

with this one:

The WHEN trigger is true.

loop until WHEN trigger is false.

.. do a thing.

done.

What you CANNOT do is replace THIS looping model the same way:

The WHENEVER trigger happens.

... do a thing.

The WHENEVER rigger is still true.

... do a thing again.

The WHENEVER trigger is still true.

... do a thing again.

The WHENEVER trigger is not true anymore.

A few minutes later the WHENEVER trigger happens again.

... do a thing.

The WHENEVER rigger is still true.

... do a thing again.

The WHENEVER trigger is not true anymore.

done.

Your suggested solution only allows one run through the loop. The WHEN condition still won't happen a second time after the loop is over. This makes it impossible to set up a program that watches for a condition and then responds to it a particular way MORE THAN ONCE.

Edited by Steven Mading
Link to comment
Share on other sites

You can. The IF condition is the thing you want to respond to, and the UNTIL condition is for when you're done caring about the IF condition.


until stage:liquidfuel < 50 {
if alt:radar < 200 { lock throttle to 1. }.
if alt:radar > 1000 { lock throttle to 0.}.
}.

Edited by rhoark
Link to comment
Share on other sites

I've been thinking on this, and concluded an IF inside an UNTIL will typically be the right approach for responding to a recurring situation. The use case for WHEN seems to be when a set of events might happen once each in arbitrary order, which is fairly niche.

Accessing the elements of a vector will also be essential for calculating the magnitude.

Edit: It's revealed in the 0.4 video (and apparently nowhere else) you can do X:pitch, X:roll, and X:yaw on R() structures. No word on V().

Gaaah so much undocumented stuff here. (Call me an old school grognard but I really dislike the modern trend of people wanting to use video clips as the primary means of documenting how software works over using the written word. Looking things up in a video takes longer and it's harder to skim.)

Link to comment
Share on other sites

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