KontrolSystem2 icon indicating copy to clipboard operation
KontrolSystem2 copied to clipboard

Is lost of communication an issue?

Open PhilouDS opened this issue 1 year ago • 20 comments

Hi, I tried to run my script to go to the Mun. When I start my transfer burn, I have no connection with KSC. I don't know if it's related but my staging script doesn't work during that burn! I had no problem during the gravity turn nor during the circularization.

FYI: I'm using the mod CommNext (https://spacedock.info/mod/3560/CommNext). I don't know if it's relevant.

It could be a problem with my craft.

PhilouDS avatar Mar 13 '24 19:03 PhilouDS

The problem was from my transfer script sorry.

PhilouDS avatar Mar 13 '24 22:03 PhilouDS

Hum, nice, I was seeking for a worthy successor of Remote Tech. Thank you ^^. My Sat Constellation Launcher will be usefull.

lefouvert avatar Mar 13 '24 22:03 lefouvert

On that note: Creating bindings for the CommNet is on the todo list. Still trying to figure out how it is working internally though

untoldwind avatar Mar 14 '24 09:03 untoldwind

On that note: Creating bindings for the CommNet is on the todo list. Still trying to figure out how it is working internally though

okay... it seems that my stage problem comes from wait_until(fn() -> vessel.staging.ready) when I lose the communication.

Also, activating the sas with vessel.autopilot.enabled = true doesn't seem to work when the vessel is out of communication. It's less important but good to know. (I try to don't use SAS. In KSP1, some probes don't have SAS (or a limited one). Maybe, this will be the case in KSP2.)

PhilouDS avatar Mar 14 '24 10:03 PhilouDS

Back again here. Even without wait_until(fn() -> vessel.staging.ready), I have problem sometimes to stage without communication. This is my script.

pub fn check_staging (vessel: Vessel) -> Unit = {
  let check = false
  const engine_in_stage = list_engine_stage(vessel, vessel.staging.current)
  if (vessel.staging.current > 0) {
    if (engine_in_stage.length == 0 ||
      engine_in_stage.filter(fn(eng) -> eng.has_ignited && eng.is_flameout).length != 0) {
      check = true
    }
  }
  yield()
  if (!check && engine_in_stage.filter(fn(eng) -> !eng.has_ignited).length > 0) {
    check = true
  }
  yield()
  if (check) {
    CONSOLE.print_at(15,0,"Staging")
    yield()
    trigger_staging(vessel)
  }
  yield()
  CONSOLE.clear_line(15)
}

pub fn trigger_staging (vessel: Vessel) -> Unit = {
  //wait_until(fn() -> vessel.staging.ready)
  vessel.staging.next()
  yield()
}

fn list_engine_stage (vessel: Vessel, stage_num: int) -> ksp::vessel::ModuleEngine[] = {
  let list_engine: ksp::vessel::ModuleEngine[] = []
  for (prt in vessel.staging.parts_in_stage(stage_num)) {
    if (prt.is_engine) {
      list_engine += prt.engine_module.value
    }
  }
  list_engine
}

Last time the staging didn't occur, it was weird because the CONSOLE.print_at(15,0,"Staging") blinked. That means that the line was printed and then cleared. So trigger_staging actually wasn't trigger. Maybe the lack of communication, maybe something else. Sometimes, it seems random.

PhilouDS avatar Mar 14 '24 20:03 PhilouDS

As far as I know, lost of communication 'issue' is an expected behavior. It's as if the KSC made the computations and send result orders to your probe, which one trigger action on the vessel.

For KOs analogy, it's like if you run your script from Archive.

I don't think KS is think to be one or other way, but it link your script to actual game input. And if you dont have a Kerbal on board, without a working communication web, you can't control an occluded probe. Like without KS mod.

lefouvert avatar Mar 15 '24 03:03 lefouvert

I have not checked it yet, but there is the vessel.is_controllable flag. To my understanding of the internal API that one should flip once the vessel is out of comm range.

So maybe wait_until(fn() -> vessel.staging.ready || !vessel.is_controllable) will do the trick? Of course then you still have to deal with an un-controllable vessel somehow ;)

untoldwind avatar Mar 15 '24 07:03 untoldwind

@untoldwind !vessel.is_controllable didn't work. The stage string didn't blink anymore. That means that the script was stuck in the wait_until loop. Using vessel.connection_status == ConnectionNodeStatus.Disconnected was better. The blink stage was here again so the script exists the wait_until loop but the staging is not triggered!

Some screenshots with this little test:

use { sleep, wait_until, yield, current_time } from ksp::game
use { CONSOLE } from ksp::console
use { CONSOLE_WINDOW } from ksp::ui
use { vec2 } from ksp::math
use { Vessel, AutopilotMode, ConnectionNodeStatus } from ksp::vessel

pub fn main_flight (vessel: Vessel) -> Unit = {
  CONSOLE.clear()
  
  CONSOLE_WINDOW.open()
  CONSOLE_WINDOW.size = vec2(500,600)

  vessel.autopilot.enabled = false
  vessel.autopilot.mode = AutopilotMode.Autopilot
  
  sleep(0.5)

  vessel.set_throttle(0)

  CONSOLE.print_line($"vessel controllable? {vessel.is_controllable}")
  CONSOLE.print_line($"connection status? {vessel.connection_status}")
  wait_until(fn() -> vessel.staging.ready || vessel.connection_status == ConnectionNodeStatus.Disconnected)

  const t0 = current_time()
  
  for (i in 0...100) {
    vessel.set_throttle(i)
    CONSOLE.print_at(3,0,i.to_string())
    sleep(0.05)
  }
}

First screenshot: full connection. No problem. image

The second screenshot shows that the vessel is controllable for KS2 but not for KSP. Indeed, I can't control the throttle or the direction manually. I can activate the SAS manually image

3rd screenshot. No more power in the batteries. I can't control anything manually, not even the SAS. KS2 says the vessel is controllable. image

Throttle: When the vessel is disconnected, KS2 can set the throttle only to 1 or 0!

My opinion:

  • vessel.is_controllable isn't reliable (even with no electricity left).
  • When a script is running, lack of connexion shouldn't be a problem. At the moment, it is. That means I can't even stage while I'm in the opposite side of the mun, or set my throttle.
  • @lefouvert for kOS analogy: you can run a script from the archive only if you have communication. But, once the script is running, the vessel is fully operational with the script, even after a lost of communication. And that's the point! For me, a running script must always be in control of the vessel.

PhilouDS avatar Mar 15 '24 13:03 PhilouDS

@PhilouDS for KOs analogy : yes your script still running after communiction loss. But that was a part of the numerous memory leak. Once the script is in game loaded, it stay available while it shouldn't. That's how onboard script variables can be confused with Archive scripts variables. In short, most of us had happily exploited a bug. For me, a running script run from where it's loaded. Elsewhere, there is no point to have onboard script limitation. 5Ko hard drive, but infinite RAM ? Don't seems legit. Link it to real life : You can code new program for your probe from Earth, you can send it to your probe, but you can't exceed probe abilities. I promise you I would like to be able to run some software a place, and it «magicaly» act else where. In facts, it's possible, but this magic is supported by heavy networks ^^ Or commNet in KSP :P

For the 0-100 thrust toggle, isn't this related to the intermediate comm's status «poor connexion» which allow only a few controls ? (I don't think we have access to this state in KS). I believe there was something like this in KSP1 and I wouldn't be surprised if it was reintroduced in KSP2

For Kontrol System, as thoses considerations are not in the scope, I can only link it to game inputs abilities. You have network or kerbals in the vessel : it's fully controlable, you don't have at least one of them, you can't control your probe. Should it change ? Don't know.

What concerns me is that the script does not resume after reacquiring communications.

lefouvert avatar Mar 15 '24 14:03 lefouvert

This is quite interesting, I guess I have to do some digging how the underlying VesselComponent.IsControllable is actually calculated. Maybe you can checkout if at least the vessel.control_status field gives proper results.

untoldwind avatar Mar 15 '24 14:03 untoldwind

@untoldwind the two results I had with control_status were Disconnected or Connected and they seem to be reliable during my test.

@lefouvert If I wanted to do like IRL, i'll play RP1 😅 but I see what you mean... and that means that it will be more difficult to create my first keostationary network. If I ask untoldwind to create parts like kOS, they will rip my head off 😂 It could be doable to patch the probes and capsule to had some memory value to load a script inside the memory probe and run it from the probe directly.

@untoldwind How does to2 load library? I try to explain: if I write use {function} from library to use a function. Does to2 "load it in the script" and when it sees it in the script, it uses it... Or, when it reaches a line using function, only then it looks at the line use {function} to see the origin library?

PhilouDS avatar Mar 15 '24 14:03 PhilouDS

Ad 1): There are actually two status-fields on vessel vessel.control_status and vessel.connection_status (and the aforementioned vessel.is_controllable). I think at least one of these is somewhat redundant and probably should be dropped to avoid confusion.

Ad 2): There are two answers to this.

  • In the compiler the use declaration just creates an alias in the context of the file. I.e.
    use { current_time } from ksp::game
    
    fn my_func() -> float = {
      current_time()
    }
    
    is identical to
    fn my_func() -> float = {
      ksp::game::current_time()
    }
    
  • Under the hood:
    • Each to2-file is converted into a static class (pretty much the same as public static class MyTo2File in C#).
    • Every function in a to2-file becomes a static method in that class
    • ... so calling a function from another to2-file becomes a call to that static method
    • The nice thing about this is: It does not matter where that static method comes from, so calls to2 -> to2, to2 -> C#, and C# -> to2 are all the same.
    • In the example above: ksp::game::current_time() will create a method call to https://github.com/untoldwind/KontrolSystem2/blob/f3d458328b9553d2fea0417712fcacb42b98f424/KSP2Runtime/KSPGame/KSPGameModule.cs#L18

untoldwind avatar Mar 15 '24 15:03 untoldwind

With full control: image Communication lost: image No more power: image

So control_status seems to work well.

And I don't understand but throttle works well too. It changes from 0 to 1 without comnet, even without power... But in my script, it didn't 😠

for (i in 0...100) {
    vessel.set_throttle(i.to_float/100)
    CONSOLE.print_at(3,0,i.to_string())
    sleep(0.1)
  }

PhilouDS avatar Mar 15 '24 22:03 PhilouDS

Internally vessel.set_throttle hooks up an autopilot that is active until released (i.e. the release method on the returned ThrottleManager).

In theory an autopilot should behave the same as regular pilot input ... but maybe there is something that bypasses the control_status check.

untoldwind avatar Mar 16 '24 08:03 untoldwind

What is the best to use in a while loop? set_throttle or manage_throttle. Are there big differences?

PhilouDS avatar Mar 16 '24 12:03 PhilouDS

.set_throttle. manage_throttle take a function, which means it autoupdate, which is the purpose of your while loop.

update an autoupdate function in this context don't make sense. (I don't mean your question don't make sense, I guess you didn't know)

In most case, you can assume than something which take a function as parameter will autoupdate in function of... your function, and your function is supposed to describe the evolution of the value you would put into a set_something. So, except if your context changes, their is no point to update a manage_something.

lefouvert avatar Mar 16 '24 13:03 lefouvert

If vessel.set_throttle is called the previously hooked up ThrustManager is updated (i.e. there should not be multiple autopilots concurrent autopilots).

Though the preferred pattern is this.

const throttle_manager = vessel.manage_throttle(fn(deltaT) -> ... some magic code to calculate the desired thrust ...)

... some code to wait for the some criteria ...

throttle_manager.release() // Throttle control is given back to the pilot (should reset to 0)

Alternative pattern with while loop:

const throttle_manager = vessel.set_throttle(0.5) // set some starting throttle, e.g. 0.5 = half thrust

while(... some condition ...) {
  throttle_manager.throttle = ... updated throttle ...
  yield() // or sleep()
}

throttle_manager.release() // Throttle control is given back to the pilot (should reset to 0)

untoldwind avatar Mar 16 '24 15:03 untoldwind

Okay, I see. Thanks.

2 more questions 😅 1- What's set_throttle_provider for? 2- What's deltaT for in manage_throttle? Is this for the time? Can I use it inside the magic code?

PhilouDS avatar Mar 16 '24 17:03 PhilouDS

If you create a the ThrottleManager via vessel.manage_throttle(...), the set_throttle_provider(...) is a way to replace the original function with a new one. As the name suggests: throttle-provider is a function that returns/provides the desired throttle.

The deltaT is the time that has passed since the last call of that function, which is helpful if you are using some kind of PID loop to calculate a throttle.

Some "simple" examples from the std:: lib. E.g.

  • The maneuver node execution helper: https://github.com/untoldwind/KontrolSystem2/blob/ef55d06c67328cdef2337b839dabe4481881b497/KSP2Runtime/to2/std/vac.to2#L44
    • I.e. the throttle is based on the available thrust and the remaining delta-V of the maneuver node (so that it eases out at the end)
  • The vaccum touchdown (i.e. the final step of a landing in vacuum): https://github.com/untoldwind/KontrolSystem2/blob/ef55d06c67328cdef2337b839dabe4481881b497/KSP2Runtime/to2/std/land/vac.to2#L303
    • Here the throttle is calculated by a PID loop to hold a given vertical speed ... which in turn is calculated from the altitude of the vessel
    • ... I guess this one could be re-written to use deltaT instead of current_time(), it's been a while since I worked on this

untoldwind avatar Mar 16 '24 18:03 untoldwind

This issue is stale because it has been open for 60 days with no activity.

github-actions[bot] avatar May 16 '24 02:05 github-actions[bot]

This issue was closed because it has been inactive for 14 days since being marked as stale.

github-actions[bot] avatar May 30 '24 02:05 github-actions[bot]