Jump to content

[1.3] kOS Scriptable Autopilot System v1.1.3.0


erendrake

Recommended Posts

4 hours ago, Meltdown said:

That's not correct. If one is treating one file as one script without any declaration of functions, the script will eventually lock one out of the terminal. If one is implementing a userinput, the script can surely check the state each cycle. If one is inputting new commands while a script is running, those inputs are getting queued up and executed after the actual program has ended (like in any other PL where "run mycode.extension" will just do that). Loops are also like in any other PL, one can make them run in the backround or keep the script from executing further until a certain condition is met. One can even run a whole program nested inside an until-loop by the use of delegates. Check out http://ksp-kos.github.io/KOS_DOC/language/flow.html and http://ksp-kos.github.io/KOS_DOC/language/delegates.html for more info.

What I'm looking to do is have a program clear the screen and print info to the terminal every cycle of the loop.  All the basic loops seemed to bog down the computer or just lock up the program.  This seems to work perfect for what I want to do even though the documentation says to avoid waits inside when loops, but when its running I can't type into the terminal anymore until I stop the program.    

DECLARE run IS TRUE. //is the program loop running
DECLARE runstep IS 0. //count the loops for displaying

//main program loop, run while the program is in run mode
WHEN run = TRUE THEN {

	clearscreen.

	print "NavCom Status" at(1,1).
	print "Runstep : " + runstep.

	SET runstep TO runstep + 1.
	WAIT 1.
	RETURN TRUE.
}

WAIT UNTIL run = FALSE.

I've read through both those pages in the documentation, and most everything else at this point, the term userinput does not match anything   I did see a page about how to read the terminal, but nowhere have I seen talk about how to still type into the terminal while a loop is executing.  Perhaps there is a wait for input command, but for my application I don't want to stop the loop to look for user input.  A working example for what I'm looking for would be great. 

Edited by eberkain
Link to comment
Share on other sites

1 hour ago, eberkain said:

What I'm looking to do is have a program clear the screen and print info to the terminal every cycle of the loop.  All the basic loops seemed to bog down the computer or just lock up the program.  This seems to work perfect for what I want to do even though the documentation says to avoid waits inside when loops, but when its running I can't type into the terminal anymore until I stop the program.    


DECLARE run IS TRUE. //is the program loop running
DECLARE runstep IS 0. //count the loops for displaying

//main program loop, run while the program is in run mode
WHEN run = TRUE THEN {

	clearscreen.

	print "NavCom Status" at(1,1).
	print "Runstep : " + runstep.

	SET runstep TO runstep + 1.
	WAIT 1.
	RETURN TRUE.
}

WAIT UNTIL run = FALSE.

I've read through both those pages in the documentation, and most everything else at this point, the term userinput does not match anything   I did see a page about how to read the terminal, but nowhere have I seen talk about how to still type into the terminal while a loop is executing.  Perhaps there is a wait for input command, but for my application I don't want to stop the loop to look for user input.  A working example for what I'm looking for would be great. 

I don't think it's possible to get the REPL working while the compiler is trying to evaluate your loop. My formulation was hereof missleading as I ment the direct game inputs like the arrowkeys, WASD or +mouse. I might be totally wrong, probably some other user can serve you a solution with more experience in kOS.

Link to comment
Share on other sites

Edit: FIXED It

I got my problem fixed and then produced th next one^^, In one file it all works - split it in different ones it complains that my function would be an undefined variable...

I'm just doing basic stuff and been experimenting in sandbox to understand multiple files, but I'm stuck.

So here is what used to work if put in one file, but refuses to when split up:

FIX: Needs the following in the boot sequenc (if the script with the functions doesn't run they wont do anything *facepalm*):

runpath("1:/lib1.ks").
Spoiler

//The boot script (works, but I wanted to pass all the info I got).
//test_boot.ks

clearscreen.
set ship:control:pilotmainthrottle to 0.
copypath("0:/test_libary.ks","1:/lib1.ks").
copypath("0:/test.ks","1:/prog1.ks").
runpath("1:/prog1.ks").
deletepath("1:/test_boot.ks").

//------------------------------------------------------------------

//the libary - just two simple functions
//test_libary.ks

function printhud {
	parameter message.
	
	hudtext(message, 5, 2, 20, green, false).
}

//hasfile checks if file x exists on volume y
function hasfile {
	parameter name.
	parameter volume.
	
	switch to volume. list files in filecheck.
	for file in filecheck {
		if file:name = name {
			switch to 1.
			return true.
		}
	}
	switch to 1.
	return false.
}

//-------------------------------------------------

//And the actual "program" to test wether those functions do actually work
//test.ks

if hasfile("4test.ks", 0) = true {		//the 4 is supposed to be there to make it return "false".
	printhud("test.ks exists on 0:/").
} else {
	printhud("test.ks does not exists on 0:/").
}

wait 5.
printhud("we made it to the end of test.ks!").

 

I'm sure its some noobish missunderstanding of how KOS handels stuff :/ but I couldn't find a solution.

cheers and thanks for any help.

Edited by maculator
I'm an idiot
Link to comment
Share on other sites

4 hours ago, eberkain said:

nowhere have I seen talk about how to still type into the terminal while a loop is executing

"When " is not a loop!

It is trigger, checked each physics tick. Each time you use "wait 1." in it whole script stops for 1 second. You do not see it because "main part" of your script is endless wait loop.

Link to comment
Share on other sites

Quote

So, once in a loop, there is no way to send new commands to the program?

@eberkain, quite opposite. That is why we have triggers or events that can be created with WHEN or ON commands.

In your example, you should use UNTIL loop, instead of WHEN trigger. Also, you should avoid to declare variable names with same as keyword/command used in kOS language. Any programming language will be confused with it. I pointing to "run" variable that is also legacy command for "runpath".

You should also avoid to clear screen inside loop, you will get bad flickering effect on terminal screen because of that. Also, since you have said that you have experience with C++ and C# languages, you can take advantage of functions to make all code more "clear" adn easier to read and understand.

Here is some example what I mean:

set terminate to false. // main variable preventing script to end
set output to "".
set MyAction to false.


clearscreen.
// this will be printed only once on terminal, to avoid flickering
print "kOS autopilot Keys:                         ". // Row 0.
print "     Action Group 4 : Toggle something      ".
print "                                            ".
print "                                            ".
print "     Press CTRL + C to terminate program    ".
print "--------------------------------------------".
print "                                            ". // Row No:6
print "Speed   :                                   ". // Row No:7
print "Altitude:                                   ". // Row No:8

// some simple function to display data on demand inside loop
function display_block{
  parameter output. // mandatory parameter
  parameter startCol is 0.  // optional parameter
  parameter startRow is 6. // define where the block of text should be positioned

  print output at (startCol,startRow).
  print round(SHIP:AIRSPEED,2) + " "at (10,startRow+1).
  print round(SHIP:ALTITUDE,2) at (10,startRow+2).
}.
// kOS will be aware of this function existance in rest of code

// Defining trigger or event with "ON" command
on AG4 {
    toggle MyAction. // if it was false value will be true or oposite
	
	if MyAction = true {
		set output to "Autopilot is active ".
	}
	else
	{
		set output to "Autopilot is passive".
		// you can put some other commands here, to unlock controls or something
	}.
	
	
    preserve. // ensurance that AG is triggered again on demand
}.
// --- end of trigger definitions ----

// -------- initialization of script before main loop
set some_other_variable to "something." // to be used for something in main program

// -------------------------------------------
// main program executing in loop until CTRL+C
until terminate {
	// Print dynamic data on terminal
	display_block(output). // function call
	if MyAction = true {
		// put some custom code here when kOS control craft
	}.
}.
// end of main program
// -------------------------------------------

 

And I got ninjaed while writting this example :)

 

Link to comment
Share on other sites

function download {
	parameter name.
	parameter volume.
	
	if hasfile(name, 1) {
		delete name.
	}
	if hasfile (name, volume) {
		copypath(volume + ":/" + name,"1:/" +name).	//<-----THIS looks really unnecessary complicated to me....
	}
}

Since [copy name from volume.] is depreciated and prints that ugly message on my screen I went for the above solution, it works but I wonder if there is a better and cleaner way?

Link to comment
Share on other sites

1 hour ago, kcs123 said:

until terminate {
	// Print dynamic data on terminal
	display_block(output). // function call
	if MyAction = true {
		// put some custom code here when kOS control craft
	}.
}.

 

If this is supposed to execute once per frame, you should add a "wait 0." at the beginning or at the end of the loop. Otherwise
* it would execute multiple loops until the IPU run out (wasting EC).
* at the end of the frame, the last loop would be interrupted at some random line. Such interruptions have caused a few hard to find bugs for me.

For example this looks like perfectly safe code:

if HasTarget
  print Target:Name.

However, suppose that one frame ends after the first line is executed (with HasTarget=true), and then the target is lost. In this case kOS will execute the second line, and fail with the error that there is no target. I had something like that in a docking function that would sporadically fail in this way. Since then I sometimes add "wait 0." at the start of a section that should happen within one frame.

Link to comment
Share on other sites

2 minutes ago, pellinor said:

you should add a "wait 0."

Huh. I thought that "wait 0." is exactly same that you want to wait just one physical thick, or in other word not have to wait at all.
Anyhow, I actualy have that command in some of my scripts, but for reasons that I was experimenting with various values above zero and zero. Haven't noticed issues using it or not inside loop and it didn't cause significant change in EC consuption. But also, it has been a while since I played KSP. I almost skiped whole 1.2.2. release and 1.2.3. is almost published, things might be changed in both, kOS and KSP.

I always tend to put commands that belongs to some "if" condition inside curly brackets even if there is just single line of code. Just my old habit for easier reading and understanding code when you revised it after several months. That also saved me from nasty bugs that come out of blue.

Anyhow, above is just example of loop usage without any actual calculations/commands inside.

Link to comment
Share on other sites

{
	global file is lex(
	"xcopy",xcopy@,
	"erase", erase@,
	"erase_all",erase_all@,
	"download", download@
	).
	function xcopy {
	Parameter file, orig, trgt.
		switch to trgt.
		if exists(file) {
			erase(file,trgt).
		}
		switch to orig.
		copypath(file ,trgt + ":/").
		switch to trgt.
		runpath(file).
	}
	function erase {
	Parameter File, vol.
	switch to vol.
	deletepath(File).
	}
	function erase_all {
		parameter vol.
		switch to vol.
		list files in file.
		for x in file {
			erase(x,vol).
		}
	}
	function download {
	Parameter file, vol.
	xcopy(file,vol,1).
	}
}
//use it like this : file["xcopy"]("test.ks",0,1).
file["xcopy"]("testme.ks",0,1).
print "xcopy okay".
file["download"]("testme2.ks",0).
print "download okay".

Handle with care! I just had a glance at it and it works. I really don't want to harm or damage your files! I repeat, be cautious with it.

Quote

maculato


function download {
	parameter name.
	parameter volume.
	
	if hasfile(name, 1) {
		delete name.
	}
	if hasfile (name, volume) {
		copypath(volume + ":/" + name,"1:/" +name).	//<-----THIS looks really unnecessary complicated to me....
	}
}

Since [copy name from volume.] is depreciated and prints that ugly message on my screen I went for the above solution, it works but I wonder if there is a better and cleaner way?

 

Edited by Meltdown
Jeez the forum ate my quoting!
Link to comment
Share on other sites

On 4/3/2017 at 3:56 AM, Steven Mading said:

Do you get the same bug if you decouple the launch clamps by using DOEVENT or DOACTION instead of AGX?

After a bit of keyboard banging.. Yup..afraid the same problem is still there.

At 200m it should rotate to 90 degrees.

https://youtu.be/KSAaIjW-o8k

 

The code used to extract the modules

Function ListParts
{
Global P is "".
Global MOD is "".
	Clearscreen.
	FOR P IN SHIP:PARTS 
	{
	//=== TOWERS ===
		IF P:TAG = "Tower1"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Tower1Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Tower2"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Tower2Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Tower3"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Tower3Mod to P:GETMODULE(MOD).
				}
			}
		}

	//=== BASE CLAMPS ===
		IF P:TAG = "Clamp1"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Clamp1Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Clamp2"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Clamp2Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Clamp3"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Clamp3Mod to P:GETMODULE(MOD).
				}
			}
		}

	//=== STAGE-1 ENGINES ===
		IF P:TAG = "Stg1_Eng1"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng1Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Stg1_Eng2"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng2Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Stg1_Eng3"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng3Mod to P:GETMODULE(MOD).
				}
			}
		}

		IF P:TAG = "Stg1_Eng4"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng4Mod to P:GETMODULE(MOD).
				}
			}
		}
	}
}

Code used for DOACTIONs..

	Set ThisTime to 10.
	Until ThisTime < 1
	{   
		Set ThisTime to ThisTime - 1.
		Print ThisTime + " " at (22,4).
		Print THROTTLE at (22,14).
		If ThisTime = 4
		{
			Print "Activated   " at (22,12).
			Lock THROTTLE to 1.0.
			Stg1_Eng1Mod:doaction("activate engine",TRUE).
			Stg1_Eng2Mod:doaction("activate engine",TRUE).
			Stg1_Eng3Mod:doaction("activate engine",TRUE).
			Stg1_Eng4Mod:doaction("activate engine",TRUE).
//			Stage.
//			Toggle(AG250).
			SAS OFF.
			SET SASMODE to "STABILITYASSIST".
		}
		Wait 1.
	}
	Tower1Mod:doaction("release clamp",TRUE).
	Tower2Mod:doaction("release clamp",TRUE).
	Tower3Mod:doaction("release clamp",TRUE).
	Clamp1Mod:doaction("release clamp",TRUE).
	Clamp2Mod:doaction("release clamp",TRUE).
	Clamp3Mod:doaction("release clamp",TRUE).
//	Stage.
//	Toggle(AG249).
//--- TOWERS AND CLAMPS ---//
	Print "Activated   " at (22,18).
	Print "Activated   " at (22,20).
	wait 2.

 

Edited by ColKlonk2
Link to comment
Share on other sites

5 hours ago, kcs123 said:

@eberkain, quite opposite. That is why we have triggers or events that can be created with WHEN or ON commands.

In your example, you should use UNTIL loop, instead of WHEN trigger. Also, you should avoid to declare variable names with same as keyword/command used in kOS language. Any programming language will be confused with it. I pointing to "run" variable that is also legacy command for "runpath".

You should also avoid to clear screen inside loop, you will get bad flickering effect on terminal screen because of that. Also, since you have said that you have experience with C++ and C# languages, you can take advantage of functions to make all code more "clear" adn easier to read and understand.

Here is some example what I mean:


set terminate to false. // main variable preventing script to end
set output to "".
set MyAction to false.


clearscreen.
// this will be printed only once on terminal, to avoid flickering
print "kOS autopilot Keys:                         ". // Row 0.
print "     Action Group 4 : Toggle something      ".
print "                                            ".
print "                                            ".
print "     Press CTRL + C to terminate program    ".
print "--------------------------------------------".
print "                                            ". // Row No:6
print "Speed   :                                   ". // Row No:7
print "Altitude:                                   ". // Row No:8

// some simple function to display data on demand inside loop
function display_block{
  parameter output. // mandatory parameter
  parameter startCol is 0.  // optional parameter
  parameter startRow is 6. // define where the block of text should be positioned

  print output at (startCol,startRow).
  print round(SHIP:AIRSPEED,2) + " "at (10,startRow+1).
  print round(SHIP:ALTITUDE,2) at (10,startRow+2).
}.
// kOS will be aware of this function existance in rest of code

// Defining trigger or event with "ON" command
on AG4 {
    toggle MyAction. // if it was false value will be true or oposite
	
	if MyAction = true {
		set output to "Autopilot is active ".
	}
	else
	{
		set output to "Autopilot is passive".
		// you can put some other commands here, to unlock controls or something
	}.
	
	
    preserve. // ensurance that AG is triggered again on demand
}.
// --- end of trigger definitions ----

// -------- initialization of script before main loop
set some_other_variable to "something." // to be used for something in main program

// -------------------------------------------
// main program executing in loop until CTRL+C
until terminate {
	// Print dynamic data on terminal
	display_block(output). // function call
	if MyAction = true {
		// put some custom code here when kOS control craft
	}.
}.
// end of main program
// -------------------------------------------

 

And I got ninjaed while writting this example :)

 

Thanks for the example, I follow everything.  I'm not too worried about best practices or the like, just experimenting to see if what I want to do is even possible.  Is there a way to respond to something other than an action group?  Lets say I have a state variable called display_mode.  If it is a 1 the program displays one set of info, if it is a 2 the program displays something else.  That I can do.  What are the possible ways that I can respond to user input to change the value of display_mode?  I don't want to tie it to action groups though, I'm going to need all the action groups for other things.  So I was asking if there was a way to type a command into the console while in a loop.  My current plan is to put the output for each display_mode into a different script, and when I want to change modes I send a CTRL+C command to the terminal and then a new run command to launch a different display script. 

Link to comment
Share on other sites

9 hours ago, eberkain said:

Thanks for the example, I follow everything.  I'm not too worried about best practices or the like, just experimenting to see if what I want to do is even possible.  Is there a way to respond to something other than an action group?  Lets say I have a state variable called display_mode.  If it is a 1 the program displays one set of info, if it is a 2 the program displays something else.  That I can do.  What are the possible ways that I can respond to user input to change the value of display_mode?  I don't want to tie it to action groups though, I'm going to need all the action groups for other things.  So I was asking if there was a way to type a command into the console while in a loop.  My current plan is to put the output for each display_mode into a different script, and when I want to change modes I send a CTRL+C command to the terminal and then a new run command to launch a different display script. 

I have put action group in example above to ON command as most obvious and easiest to use. But it can be tied to any other variable that can change value. You can also use WHEN command instead, for example, to send STAGE button when craft is run out of fuel/thrust.

Also, in future versions of kOS you can build GUI window for command imput instead of terminal, to enter values trough buttons, checkboxes adn similar. There was discussion about it couple months ago, you can find it in this thread 10 -20 pages back. Example from alpha GUI version of kOS:

Uaspb5X.jpg

On picture is shown GUI to choose autopilot flight mode, to execute maneuver node in space, gently land powered rocket or to hover at certain altitude or to maintain desired vertical speed. You can choose to lock steering trough input boxes or you can continue to control craft trough WASD keys while autopilot control throttle to do hovering. That is just simple example, you can build even more advanced stuff, but under the hud is similar code structure like shown in previous post.

You can also use parameter at begining of script for desired display mode. The following is example from my rocket launch script that actualy use only sequence of commands until reaching orbit without endless loop.

// Arguments for program must be on top
parameter MyHeading is 90. // initial heading for orbit - influence starting inclination
parameter MyApoapsis is 120000. // Desired APOAPSIS of orbit
parameter ApETA is 27. // time before reaching Apoapsis when circularization burn start
clearscreen.

// example of usage to run from terminal
print "Use double quote and numbers for parameters".
print "Example: runpath('/rlaunch',90,120000)".

// function that will display dynamic data on terminal
function DynamicDisplay{
  parameter output. // dynamic data - mandatory parameter
  parameter startCol is 17.
  parameter startRow is 9. // define where the block of text should be positioned

  print output at (startCol,startRow).
  print round(SHIP:AIRSPEED,2) + " "at (10,startRow+1).
  print round(SHIP:ALTITUDE,2) at (10,startRow+2).
}.

wait until SHIP:MAXTHRUST > 0. // waiting idle until staged once for launch

// kOS is not aware of triggers yet. It will not automaticaly stage on it's own

// staging whenever ship is out of fuel
// "WHEN" command is trigger or event. Command inside brackets will run when condition is met
// "PRESERVE." command ensure that event will be triggered again when craft run out of fuel again
// kOS CPU is not aware of this until it reached for first time
when SHIP:MAXTHRUST = 0 then {
	STAGE.
	print "Staged".
	DynamicDisplay("Staged                 ").
	preserve.
}.


// after this point kOS is aware of trigger and it will stage craft when it is out of fuel/thrust

// put some other code here to lock steering/thrust to something until desired apoapsis is reached

// some more code to circularize orbit when craft is near apoapsis

Now, instead of heading and apoapsis as arguments, you can use display_mode as argument, to display data that you need on terminal. And inside of DynamicDisplay function you can put additional IF command that will print output only for desired display mode.

You can also tie WHEN trigger to craft speed or altitude that will execute display function only when craft reach certain speed instead on each physical frame tick.

Above is just rude example of usage, not whole script code. Only your imagination is limit of possible usage in your own scripts.

Edited by kcs123
Link to comment
Share on other sites

I really like this addon but I have 2 problems with the last version of kOS...


1 - When I click on the kOS icon, nothing happens. It's not working either with the stock toolbar and the blizzy78's addon.

2 - I can't paste any text in the kOS terminal.

 

Can I do something to fix one or both of these bugs?

 

Here is the errors I get in KSP.log

When I press the Toolbar button:

[EXC 00:43:44.895] NullReferenceException: Object reference not set to an instance of an object
	kOS.Screen.KOSToolbarWindow.Open ()
	kOS.Screen.KOSToolbarWindow.CallbackOnClickBlizzy ()
	kOS.Screen.KOSToolbarWindow.<AddBlizzyButton>b__39_0 (kOS.Screen.ClickEvent e)
	kOS.Screen.Button.clicked (System.Object realEvent)
	Toolbar.Command.click ()
	UnityEngine.Debug:LogException(Exception)
	Toolbar.Log:log(LogLevel, Exception, String, Object[])
	Toolbar.Log:error(Exception, String, Object[])
	Toolbar.Command:click()
	Toolbar.Button:click()
	Toolbar.Button:drawInToolbar(Rect, Boolean)
	Toolbar.Toolbar:drawButtons()
	Toolbar.Toolbar:draw()
	Toolbar.ToolbarManager:OnGUI()
[ERR 00:43:45.424] [Toolbar] [ERROR] error while handling click event: kOS.kOSButton

 

When I try to paste some text inside of a kOS terminal:

[EXC 01:19:26.981] Exception: Can't access internal member 'GUIUtility.systemCopyBuffer' it may have been removed / renamed
	MuMech.MuUtils.GetSystemCopyBufferProperty ()
	MuMech.MuUtils.get_SystemClipboard ()
	MuMech.MechJebCore.Update ()

Thanks in advance.

Link to comment
Share on other sites

1 hour ago, kcs123 said:

I have put action group in example above to ON command as most obvious and easiest to use. But it can be tied to any other variable that can change value. You can also use WHEN command instead, for example, to send STAGE button when craft is run out of fuel/thrust.

Also, in future versions of kOS you can build GUI window for command imput instead of terminal, to enter values trough buttons, checkboxes adn similar. There was discussion about it couple months ago, you can find it in this thread 10 -20 pages back. Example from alpha GUI version of kOS:

Uaspb5X.jpg

On picture is shown GUI to choose autopilot flight mode, to execute maneuver node in space, gently land powered rocket or to hover at certain altitude or to maintain desired vertical speed. You can choose to lock steering trough input boxes or you can continue to control craft trough WASD keys while autopilot control throttle to do hovering. That is just simple example, you can build even more advanced stuff, but under the hud is similar code structure like shown in previous post.

You can also use parameter at begining of script for desired display mode. The following is example from my rocket launch script that actualy use only sequence of commands until reaching orbit without endless loop.


// Arguments for program must be on top
parameter MyHeading is 90. // initial heading for orbit - influence starting inclination
parameter MyApoapsis is 120000. // Desired APOAPSIS of orbit
parameter ApETA is 27. // time before reaching Apoapsis when circularization burn start
clearscreen.

// example of usage to run from terminal
print "Use double quote and numbers for parameters".
print "Example: runpath('/rlaunch',90,120000)".

// function that will display dynamic data on terminal
function DynamicDisplay{
  parameter output. // dynamic data - mandatory parameter
  parameter startCol is 17.
  parameter startRow is 9. // define where the block of text should be positioned

  print output at (startCol,startRow).
  print round(SHIP:AIRSPEED,2) + " "at (10,startRow+1).
  print round(SHIP:ALTITUDE,2) at (10,startRow+2).
}.

wait until SHIP:MAXTHRUST > 0. // waiting idle until staged once for launch

// kOS is not aware of triggers yet. It will not automaticaly stage on it's own

// staging whenever ship is out of fuel
// "WHEN" command is trigger or event. Command inside brackets will run when condition is met
// "PRESERVE." command ensure that event will be triggered again when craft run out of fuel again
// kOS CPU is not aware of this until it reached for first time
when SHIP:MAXTHRUST = 0 then {
	STAGE.
	print "Staged".
	DynamicDisplay("Staged                 ").
	preserve.
}.


// after this point kOS is aware of trigger and it will stage craft when it is out of fuel/thrust

// put some other code here to lock steering/thrust to something until desired apoapsis is reached

// some more code to circularize orbit when craft is near apoapsis

Now, instead of heading and apoapsis as arguments, you can use display_mode as argument, to display data that you need on terminal. And inside of DynamicDisplay function you can put additional IF command that will print output only for desired display mode.

You can also tie WHEN trigger to craft speed or altitude that will execute display function only when craft reach certain speed instead on each physical frame tick.

Above is just rude example of usage, not whole script code. Only your imagination is limit of possible usage in your own scripts.

I follow that too.  Thanks for the help.  While I know that a program in a loop can be setup to react to vessel status changes, that is the whole point of making an autopilot right?  It is still not user input.  I'm afraid the GUI would not apply for me, in my situation I'm not going to have a mouse to use.  So I think I'm back to my original statement more or less.  Once a program is in a loop, there is no way to send user input to it, outside of using action groups, which is still just a reaction to a vessel status change, not truly user input.  My workaround is to use the TELNET feature, setup a putty window on a second screen, use an AutoHotKey script that is setup to respond to keyboard and joystick button presses and send corresponding commands to the terminal   Each of those is setup to first send a ctrl+c firs to stop the running program, then a run script command with any new parameters that I'm looking to utilize.  I think it will work no problem, and at the end of the day, will make coding simpler since each section is going to be a different program, as opposed to having everything in a single state machine design style program. 

Link to comment
Share on other sites

Well, there is always more ways to skin an animal :)

Using telnet is one of options. You can also use new communication feature that allow you to send messages between vessels or between different kOS CPUs on same vessel. One of thing to consiser if you are low on available action groups to use Action Groups Extended mod along with kOS.

For example you can create one progam to run at continious loop that have all options you need and set to respond on some variable changes. And have another kOS CPU that will have set of small scripts that does not do much, only sending communication message to main kOS CPU that have to be programed to respond on those messages.

I just provided some examples how you can do stuff. Each user have to find his own way what option suits him best.

Link to comment
Share on other sites

6 hours ago, Frank Einstein said:

I really like this addon but I have 2 problems with the last version of kOS...


1 - When I click on the kOS icon, nothing happens. It's not working either with the stock toolbar and the blizzy78's addon.

2 - I can't paste any text in the kOS terminal.

 

Can I do something to fix one or both of these bugs?

 

Here is the errors I get in KSP.log

When I press the Toolbar button:


[EXC 00:43:44.895] NullReferenceException: Object reference not set to an instance of an object
	kOS.Screen.KOSToolbarWindow.Open ()
	kOS.Screen.KOSToolbarWindow.CallbackOnClickBlizzy ()
	kOS.Screen.KOSToolbarWindow.<AddBlizzyButton>b__39_0 (kOS.Screen.ClickEvent e)
	kOS.Screen.Button.clicked (System.Object realEvent)
	Toolbar.Command.click ()
	UnityEngine.Debug:LogException(Exception)
	Toolbar.Log:log(LogLevel, Exception, String, Object[])
	Toolbar.Log:error(Exception, String, Object[])
	Toolbar.Command:click()
	Toolbar.Button:click()
	Toolbar.Button:drawInToolbar(Rect, Boolean)
	Toolbar.Toolbar:drawButtons()
	Toolbar.Toolbar:draw()
	Toolbar.ToolbarManager:OnGUI()
[ERR 00:43:45.424] [Toolbar] [ERROR] error while handling click event: kOS.kOSButton

 

When I try to paste some text inside of a kOS terminal:


[EXC 01:19:26.981] Exception: Can't access internal member 'GUIUtility.systemCopyBuffer' it may have been removed / renamed
	MuMech.MuUtils.GetSystemCopyBufferProperty ()
	MuMech.MuUtils.get_SystemClipboard ()
	MuMech.MechJebCore.Update ()

Thanks in advance.

On the second problem: MuMech isn't kOS.  That problem isn't coming from us.

On the first problem:  Is that the only exception in your log file?  Were there other exceptions at points earlier in the file before that one?  Because to me that exception looks like the symptom of the problem, not the cause of it.

In general, the first advice when someone says this happens is:

1 - Be certain the release of kOS you are using matches the release of KSP you are using.  Each kOS release is advertised to only work for the newest KSP that was out at the time it was released.  I know this is a pain but there's not much we can do about it because changes SQUAD makes to KSP often mandate changes to the kOS mod that cause it to not be backward compatible with older versions of KSP.  (i.e. renaming a method in the API and changing how you call it:  So kOS MUST call Thing.foo(a) to work with older KSP but MUST call Thing.Baz(a,b) to work with newer KSP.  There's just no real way to make one version of kOS that satisfies those two contradictory rules when that sort of thing happens.)

2 - Try deleting the entire GameData/kOS folder and re-downloading the ZIP and re-installing it, just to ensure you didn't accidentally screw up something about the installation the first time.  This symptom can often happen as a result of just missing one file (like an image PNG or something like that) in the installation.  Once the attempt to open that one file fails, the exception that gets thrown can cause it to abort before it completes lots of other initialization steps and thus trigger all sorts of other problems.  This is why I want to see the exception that happens from kOS *first* in your output log.  It would be strange for this one you're showing to be the first exception thrown.

 

 

 

17 hours ago, ColKlonk2 said:

After a bit of keyboard banging.. Yup..afraid the same problem is still there.

At 200m it should rotate to 90 degrees.

https://youtu.be/KSAaIjW-o8k

 

The code used to extract the modules


Function ListParts
{
Global P is "".
Global MOD is "".
	Clearscreen.
	FOR P IN SHIP:PARTS 
	{
	//=== TOWERS ===
		IF P:TAG = "Tower1"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Tower1Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Tower2"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Tower2Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Tower3"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Tower3Mod to P:GETMODULE(MOD).
				}
			}
		}

	//=== BASE CLAMPS ===
		IF P:TAG = "Clamp1"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Clamp1Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Clamp2"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Clamp2Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Clamp3"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "LaunchClamp"
				{
					SET Clamp3Mod to P:GETMODULE(MOD).
				}
			}
		}

	//=== STAGE-1 ENGINES ===
		IF P:TAG = "Stg1_Eng1"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng1Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Stg1_Eng2"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng2Mod to P:GETMODULE(MOD).
				}
			}
		}
		IF P:TAG = "Stg1_Eng3"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng3Mod to P:GETMODULE(MOD).
				}
			}
		}

		IF P:TAG = "Stg1_Eng4"
		{
			FOR MOD IN P:MODULES
			{
				IF MOD = "ModuleEnginesRF"
				{
					SET Stg1_Eng4Mod to P:GETMODULE(MOD).
				}
			}
		}
	}
}

Code used for DOACTIONs..


	Set ThisTime to 10.
	Until ThisTime < 1
	{   
		Set ThisTime to ThisTime - 1.
		Print ThisTime + " " at (22,4).
		Print THROTTLE at (22,14).
		If ThisTime = 4
		{
			Print "Activated   " at (22,12).
			Lock THROTTLE to 1.0.
			Stg1_Eng1Mod:doaction("activate engine",TRUE).
			Stg1_Eng2Mod:doaction("activate engine",TRUE).
			Stg1_Eng3Mod:doaction("activate engine",TRUE).
			Stg1_Eng4Mod:doaction("activate engine",TRUE).
//			Stage.
//			Toggle(AG250).
			SAS OFF.
			SET SASMODE to "STABILITYASSIST".
		}
		Wait 1.
	}
	Tower1Mod:doaction("release clamp",TRUE).
	Tower2Mod:doaction("release clamp",TRUE).
	Tower3Mod:doaction("release clamp",TRUE).
	Clamp1Mod:doaction("release clamp",TRUE).
	Clamp2Mod:doaction("release clamp",TRUE).
	Clamp3Mod:doaction("release clamp",TRUE).
//	Stage.
//	Toggle(AG249).
//--- TOWERS AND CLAMPS ---//
	Print "Activated   " at (22,18).
	Print "Activated   " at (22,20).
	wait 2.

 

I'm still trying to debug a problem I found in the development version of kOS where it doesn't handle vessel spliltting or joining quite right, and it's hard to produce predictably.  All kOS Steering happens via a SteeringManager, which there is supposed to be one of per vessel, and when the vessel splits into two vessels (i.e. staging) it's supposed to recalculate that relationship and attach a new SteeringManager to the new vessel that contains the kOS unit, even if it's a newly spawned vessel.  There may be something not working about this, but I'm not the expert in how that part of kOS works. 

Link to comment
Share on other sites

An interesting point is that this problem wasn't around with KSP versions v1.05 and v1.13, as all worked well there.

It's probably the change in KSP v1.2+ that's broken it  - This could be the starting point for debugging ?

Link to comment
Share on other sites

15 hours ago, Steven Mading said:

On the second problem: MuMech isn't kOS.  That problem isn't coming from us.

On the first problem:  Is that the only exception in your log file?  Were there other exceptions at points earlier in the file before that one?  Because to me that exception looks like the symptom of the problem, not the cause of it.

In general, the first advice when someone says this happens is:

1 - Be certain the release of kOS you are using matches the release of KSP you are using.  Each kOS release is advertised to only work for the newest KSP that was out at the time it was released.  I know this is a pain but there's not much we can do about it because changes SQUAD makes to KSP often mandate changes to the kOS mod that cause it to not be backward compatible with older versions of KSP.  (i.e. renaming a method in the API and changing how you call it:  So kOS MUST call Thing.foo(a) to work with older KSP but MUST call Thing.Baz(a,b) to work with newer KSP.  There's just no real way to make one version of kOS that satisfies those two contradictory rules when that sort of thing happens.)

2 - Try deleting the entire GameData/kOS folder and re-downloading the ZIP and re-installing it, just to ensure you didn't accidentally screw up something about the installation the first time.  This symptom can often happen as a result of just missing one file (like an image PNG or something like that) in the installation.  Once the attempt to open that one file fails, the exception that gets thrown can cause it to abort before it completes lots of other initialization steps and thus trigger all sorts of other problems.  This is why I want to see the exception that happens from kOS *first* in your output log.  It would be strange for this one you're showing to be the first exception thrown.

 

Thank you for your reply.

I think it is important to say that I am using the last version of kOS (1.0.3) with the last version of KSP (1.2.2). I am using around 80 addons with KSP, so I guess that my kOS bug is much probably coming from a compatibility problem with an other addon. I tried to look in the log for other errors but there is so many it's not an easy task. I have to mention every of my addons are all working fine despite of many errors in the log file. kOS is also working fine, I can run scripts, copy them, delete them, etc... The only problem is the toolbar button that is not working in any of the scenes. (Space Center, VAB, Ship, etc...) I found that the bug that doesn't allow me to paste in the kOS terminal comes from the MechJeb2 addon (MuMech), which is the last release.

If it can help you to find the bug about my non-working toolbar button, I uploaded my full log file on Mediafire. During this log, all I did is open my last saved game, clicked the kOS toolbar button a few times, then I went into a ship with a kOS module and I tried to paste some text into a kOS terminal, then I closed the game.

KSP_2017-04-09_00h48.log

Link to comment
Share on other sites

While you are speaking about alpha version of kOS...

It would be good for kOS script to be able to get/get the view, how player look at the ship. I think it is not hard.

Get can be used as input direction to control some behaviour. To control from mouse for example.

Set can be used to get better view. For example view from the ship to the target.

 

Link to comment
Share on other sites

Hi I got a thing I wonder about:

If I want to compare two numbers and since they're never 100% exact numbers what's the best way to deal with it?

1. do it like if x+1<y and add/subtrackt a bit of one.

2. make a function that detects if theyre close enough: a - var. < b and a + var. > b

3 use the round() function kos provides?

 

And if I put "return [stuff]" in a function will it, if the conditions are met, kind of "replace" itself with [stuff]?!

 

thanks

Edited by maculator
german and english grammar hickups
Link to comment
Share on other sites

5 minutes ago, maculator said:

If I want to compare two numbers and since they're never 100% exact numbers what's the best way to deal with it?

if abs(x-y)<b ...

or

if abs(x/y-1)<b...

based on if you want absolute or relative difference.

Link to comment
Share on other sites

5 minutes ago, maculator said:

Hi I got a thing I wonder about:

If I want to compare two numbers and since they're never 100% exact numbers what's the best way to deal with it?

1. do it like if x+1<y and add/subtrackt a bit of one.

2. make a function that detects if theyre close enough: a - var. < b and a + var. > b

3 use the round() function kos provides?

 

And if I put "return [stuff]" in a function will it, if the conditions are met, kind of "replace" itself with [stuff]?!

 

thanks

Depends on application for the rest of code how you want to use it, but I think that MAX function might suit better for thing that you need. It returns value of bigger variable that can be used in IF conditions later on.

Link to comment
Share on other sites

 

 

29 minutes ago, maculator said:

Hi I got a thing I wonder about:

If I want to compare two numbers and since they're never 100% exact numbers what's the best way to deal with it?

1. do it like if x+1<y and add/subtrackt a bit of one.

2. make a function that detects if theyre close enough: a - var. < b and a + var. > b

3 use the round() function kos provides?

 

And if I put "return [stuff]" in a function will it, if the conditions are met, kind of "replace" itself with [stuff]?!

 

thanks

 

// [Int,Int] ==> [Boolean]
function is_equal{
Parameter n,m.
	if mod(n,m) <> 0 return false.
	else return true.
}

This will work for any natural number.

Have a look at the function; It takes two arguments and is returning a boolean. If you call it in the kOS Window with "Print is_equal(1,2).", the compiler reads it like this :

print is_equal(1,2)

print is equal(false)

print false

 

Link to comment
Share on other sites

I'll search for mod in the documentation, thanks.

Right now I'm using this:

function circa {
	parameter a, b, tolerance.
	
	if (a - tolerance) < b and (a + tolerance) > b {
		return true.
	}
}

 

Link to comment
Share on other sites

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