Jump to content

[1.8.x to 1.12.x] kRPC: Remote Procedure Call Server (v0.5.1, 2nd March 2023)


djungelorm

Recommended Posts

I'm working on putting together a new release this evening. The way vectors are passed around is going to change to use lists (this should interface better with math libraries like numpy) and the resources stuff will be fixed up to match the staging on the game ui. I'll provide more details when I make the release.

2. Can I run multiple threads using a kRPC connection?

I'd like to run a thread monitoring conditions for staging in a separate thread:


def run_thread():
while liquid_fuel() > 0:
time.sleep(1)
control.activate_next_stage()

If not: events might be an elegant alternative as they spare the effort of polling.

The client connection isn't thread safe, so you can't use the objects from multiple threads without guarding the method calls with locks (or similar). I'll have a look into making it thread safe. What you can do in the meantime is have a separate connection for each thread, as the server supports multiple connections.

I plan to add something like events in the future, so we can avoid all these horrid polling loops, although it's low on the priority list at the moment.

Link to comment
Share on other sites

I've made a new release (see OP for download link). There are lots of changes (see github for the full list), but here are the highlights:

New features:

  • Added various new functions, including SpaceCenter.Vessels and SpaceCenter.Bodies. See the wiki for details.
  • Added support for collections. Procedures can now return or be passed lists, dictionaries and sets.

Fixes and improvements:

  • Added support for action group 0 and abort action group
  • Fixed bug with maneuver node reference frame
  • Clarified the altitude properties for Flight objects
  • Improved the Resources methods

Note that Flight.altitude has been renamed to Flight.true_altitiude, and Flight.true_altitude has been renamed to Flight.absolute_altitude (which is the standard aviation terminology).

I'm going to be away on holiday for 2 weeks, so development is going to pause for a bit. See you soon!

Link to comment
Share on other sites

Two questions:

1. How do I instantiate a vector in Python?

As an example I'd like to take

import krpc
p = krpc.space_center.active_vessel.flight().prograde
pn = norm(p)
[B]v = (1,0,0) # what is the correct type to use here? Geometry.Vector3?[/B]
a = cross(pn,v)

You can create a Geometry.Vector3 as follows:


v = krpc.schema.Geometry.Vector3()
v.x = 1
v.y = 0
v.z = 0

This isn't particularly elegant, so I'm considering ditching the Geometry.Vector3 type altogether in future versions. Now that kRPC supports collections, it could return a vector as a list of floats.

Link to comment
Share on other sites

Documentation question:

double CelestialBody.atmosphere_pressure

Pressure of the atmosphere at the surface in kPa.

Sure it is at the surface (SFC)?

I guess it is at mean sea level (MSL) or the mean radius (for planets and moons without oceans).

Btw:

â—¦Rename Flight.Altitude to Flight.TrueAltitude

â—¦Rename Flight.TrueAltitude to Flight.AbsoluteAltitude

â—¦Add Flight.SurfaceAltitude

â—¦Add Flight.Elevation

How about:

1. SurfaceAltitude (above surface, either rock or sea) [now absolute_altitude]

2. MeanAltitude (above MSL, or mean) [now true_altitude]

3. BedrockAltitude (above hard surface) [now surface_altitude]

4. elevation is self explanatory.

Edited by baloan
Link to comment
Share on other sites

In Autopilot methods the description says:

Points the vessels Vessel.up_direction in the direction

but I think it should read Vessel.direction. Vessel.direction in kOS corresponds to FACING which is the direction of the rocket or plane axis.

UP in kOS always points away from the center of the celestial body through the ship.

Another one:

clear_heading() should be replaced with disengage()

Edited by baloan
Link to comment
Share on other sites

I'm using a second thread for staging. It actually works!

def stage_thread(name_):
ksp = krpc.connect(name=name_)
print 'Connected to server, version', ksp.krpc.get_status().version

space_center = ksp.space_center
vessel = space_center.active_vessel
control = vessel.control
resources = vessel.resources

oxi0 = resources.amount('SolidFuel', stage=4, cumulative=False)
time.sleep(1)
oxi1 = resources.amount('SolidFuel', stage=4, cumulative=False)
ops = oxi0 - oxi1
time_to_flameout = oxi1 / ops
print "Booster flameout in {} sec".format(time_to_flameout)
time.sleep(time_to_flameout - 1)
print "Checking for flameout".format(time_to_flameout)

while True:
oxidizer = resources.amount('SolidFuel', stage=4, cumulative=False)
if oxidizer < 0.1:
control.activate_next_stage()
break
time.sleep(0.1)

while True:
lox = resources.amount('LiquidFuel', stage=3, cumulative=False)
if lox < 0.1:
control.activate_next_stage()
time.sleep(1)
control.activate_next_stage()
break
time.sleep(0.1)

Called from the main program like this:

def main():
stage = Thread(target=stage_thread, args=["Autostage",])
...

Link to comment
Share on other sites

During launch I observer time lag in the main while loop. My guess this is due to the many round-trips for RPC the code is doing. My code queries a few parameters in the while loop.

Wouldn't it be nice if the KSP based code pushes all telemetry data every 100ms to the kRPC client? In the kRPC client a background thread receives the data and applies it to shadow variables in the Python space. Since the main idea is to reduce latency and round-trips it makes most sense to collect all telemetry data in one protobuf message and send this one buffer every 100ms. RPC calls will only be necessary for control type or auto_pilot requests to the vessel. Any data queries can be satisfied from the local cache.

I thought about implementing this optimization but realized it involves KSP side changes.

Any plans to implement something like this?

Link to comment
Share on other sites

in your documentation for the space_center is a vessel.target command. but if i try using it i get this exception

RPCError: KRPC.Service.RPCException: Procedure 'SpaceCenter.Vessel_get_Target' threw an exception. System.NotImplementedException: The requested feature is not implemented.

at KRPC.Service.Services.HandleRequest (KRPC.Service.Scanner.ProcedureSignature procedure, KRPC.Schema.KRPC.Request request) [0x00000] in <filename unknown>:0

at KRPC.Service.RequestContinuation.Run () [0x00000] in <filename unknown>:0

at KRPC.KRPCServer.ExecuteContinuation (KRPC.Service.RequestContinuation continuation) [0x00000] in <filename unknown>:0

is this feature not yet implemented as the exception says or is something else amiss?

Link to comment
Share on other sites

I am trying to determine burn end time for arbitrary maneuver nodes.

Node.delta_v is not updated during a burn while on the UI the remaining delta_v counts down. So it can't be used.

Thinking about it I see potential alternative solutions:

1. pre-calculate burn time and thrust (difficult because neither thrust nor vessel mass are available)

2. cross check against the target speed in flight.velocity. I am wondering though whether flight in orbit reference frame will do? Probably you will have to use flight in maneuver reference frame. Can I simply add node.vector to flight.velocity in maneuver reference frame? Anyone knows?

@nubnax: can reproduce vessel.target issue. Same here.

Edited by baloan
Link to comment
Share on other sites

I just wanted to inform you that I won't be creating client modules in C++ (or any other language). Although it's a fun and interesting project, I just don't have the time to do it and play KSP, and I would rather do that.

I will still happily use this mod, but using the python client modules.

Link to comment
Share on other sites

  • 2 weeks later...

I am currently looking into building an automated script to rocket-soft-land pods (similar to what SpaceX is promising from DragonFly). For this to work beautiful, I plan on doing the main thrust as late as possible.

Therefore, my question is: Is there a way to get the currently possible thrust (similarly to how MechJeb is displaying it) for every - or even just the current - stage, either in TWR or Newton, and ideally in vacuum, current altitude and sea level configurations.

Thank you in advance for the answers, and thank you for enabling me to use python to program my rockets!

Edit: Also, current mass, and maybe ISP/maximum fuel flow for the engines would be great.

Edit 2: Is there a way to get the current body a vessel is in flight on? That is, the Celestial Body representing it.

Edited by 3_14159
Link to comment
Share on other sites

I'm back from my 2 week holiday, time to answer your queries and resume development!

Documentation question:

double CelestialBody.atmosphere_pressure

Pressure of the atmosphere at the surface in kPa.

Sure it is at the surface (SFC)?

It's at MSL/mean radius. Docs updated to clarify this.

Btw:

How about:

1. SurfaceAltitude (above surface, either rock or sea) [now absolute_altitude]

2. MeanAltitude (above MSL, or mean) [now true_altitude]

3. BedrockAltitude (above hard surface) [now surface_altitude]

4. elevation is self explanatory.

I've named them according to the standard aviation terms from here: http://en.wikipedia.org/wiki/Altitude#Altitude_in_aviation_and_in_spaceflight I think that's the clearest way of doing it.

I'm using a second thread for staging. It actually works!

It will work most of the time, but might behave strangely if the threads try to send data over the connection at the same instant. I'll update the client to be thread safe so that it always works in the next release.

During launch I observer time lag in the main while loop. My guess this is due to the many round-trips for RPC the code is doing. My code queries a few parameters in the while loop.

Wouldn't it be nice if the KSP based code pushes all telemetry data every 100ms to the kRPC client? In the kRPC client a background thread receives the data and applies it to shadow variables in the Python space. Since the main idea is to reduce latency and round-trips it makes most sense to collect all telemetry data in one protobuf message and send this one buffer every 100ms. RPC calls will only be necessary for control type or auto_pilot requests to the vessel. Any data queries can be satisfied from the local cache.

I thought about implementing this optimization but realized it involves KSP side changes.

Any plans to implement something like this?

You could achieve this caching behaviour by writing your own background thread that polls the telemetry and caches it in python. Another option would be to add an RPC that provides all of the required telemetry in one RPC call (so you don't repeat the RPC invocation overhead). I'd like to keep this sort of service-specific behaviour separate from any client-side code. Otherwise, in the future when we have multiple client libraries for multiple languages, if the service code changes we'd have to modify every client library. Which would be a pain to maintain.

in your documentation for the space_center is a vessel.target command. but if i try using it i get this exception

...

is this feature not yet implemented as the exception says or is something else amiss?

Yeah it's not been implemented yet.

I am trying to determine burn end time for arbitrary maneuver nodes.

Node.delta_v is not updated during a burn while on the UI the remaining delta_v counts down. So it can't be used.

Thinking about it I see potential alternative solutions:

1. pre-calculate burn time and thrust (difficult because neither thrust nor vessel mass are available)

2. cross check against the target speed in flight.velocity. I am wondering though whether flight in orbit reference frame will do? Probably you will have to use flight in maneuver reference frame. Can I simply add node.vector to flight.velocity in maneuver reference frame? Anyone knows?

I'll add an RPC to get the remaining delta-v. That'd probably be the easiest way of support this use case. Regarding adding node.vector and flight.velocity, flight will need to be in the maneuver reference frame.

I am currently looking into building an automated script to rocket-soft-land pods (similar to what SpaceX is promising from DragonFly). For this to work beautiful, I plan on doing the main thrust as late as possible.

Therefore, my question is: Is there a way to get the currently possible thrust (similarly to how MechJeb is displaying it) for every - or even just the current - stage, either in TWR or Newton, and ideally in vacuum, current altitude and sea level configurations.

Thank you in advance for the answers, and thank you for enabling me to use python to program my rockets!

Edit: Also, current mass, and maybe ISP/maximum fuel flow for the engines would be great.

Edit 2: Is there a way to get the current body a vessel is in flight on? That is, the Celestial Body representing it.

This sort of thing hasn't been implemented yet. I plan to add functionality for getting max thrust/current thrust/TWR/total mass/dry mass/ISP etc. for the vessel as a whole, for the current stage and also on a per part/engine basis.

You can get the body currently being orbited using:


vessel = conn.active_vessel
body = vessel.orbit.body

The object returned by vessel.orbit.body is documented here: https://github.com/djungelorm/krpc/wiki/SpaceCenter-Service#celestial-body-objects

Link to comment
Share on other sites

I've taken on the problem of doing this in C++.

So far my merit list is connecting, getting the version, and querying getservices to a file.

PROC  SpaceCenter:WarpTo
double UT
double maxRate
PROC SpaceCenter:get_ActiveVessel
-> uint64
-- Property.Get(ActiveVessel)
-- ReturnType.Class(SpaceCenter.Vessel)
PROC SpaceCenter:get_Vessels
-> KRPC.List
-- Property.Get(Vessels)
-- ReturnType.List(Class(SpaceCenter.Vessel))
(omitted)

I believed I had the protocol down.

And then... it stopped working as documented.

I call get_ActiveVessel. Simply leaving the craft on the pad and krpc running, I got these hex returns on the socket:

a8 63 b2 2c ed d6 40 1a 01

or trying again

81 39 bf 41 4d 21 d7 40 1a 01 01

or again

fe e0 2f 7f 39 48 d7 40 1a 01 01

or

ee c2 d3 ef 76 bc d7 40 1a 01 01 01 01

There's nothing left to get from the socket afterwards.

The leading varint of the last one claims the following data element is greater than 4GB rather than 8 bytes.

All I can see from the logs is that it received a message and sent a reply.

This happens regardless of the get_activeVessel call being the first on the connection or following a successful getservices.

Link to comment
Share on other sites

It will work most of the time, but might behave strangely if the threads try to send data over the connection at the same instant. I'll update the client to be thread safe so that it always works in the next release.

I mean I'm using two threads with one connection each. "Sending data over the (same) connection" will not happen in that setup.

Link to comment
Share on other sites

I've named them according to the standard aviation terms from here: http://en.wikipedia.org/wiki/Altitud...in_spaceflight I think that's the clearest way of doing it.

I disagree. I am a pilot and I've never used the terms absolute and true altitude while flying. Altitudes are given in MSL and "above ground" or SFC/AGL. That's how it is referred to in aviation charts. Surface is not defined in the wiki page. I think it is confusing how surface_altitude and absolute_altitude is defined in kRPC.

Edited by baloan
Link to comment
Share on other sites

Another option would be to add an RPC that provides all of the required telemetry in one RPC call (so you don't repeat the RPC invocation overhead).

That sounds like a good start.

I'd like to keep this sort of service-specific behaviour separate from any client-side code. Otherwise, in the future when we have multiple client libraries for multiple languages, if the service code changes we'd have to modify every client library. Which would be a pain to maintain.

Sooner or later there will be breaking changes in the protocol. It is a wise move to add some kind of versioning when the connection is negotiated. That way client library migration can be done independently. It's not a cure but it lessens the pain.

Link to comment
Share on other sites

I disagree. I am a pilot and I've never used the terms absolute and true altitude while flying. Altitudes are given in MSL and "above ground" or SFC/AGL. That's how it is referred to in aviation charts. Surface is not defined in the wiki page. I think it is confusing how surface_altitude and absolute_altitude is defined in kRPC.

Oh OK, I guess wikipedia is misleading then. I'll defer to your better judgement and rename them as you suggest. I find the current names a bit confusing too, but assumed they were the standard terms.

https://github.com/djungelorm/krpc/issues/62

Edited by djungelorm
Add link to github issue
Link to comment
Share on other sites

  • 2 weeks later...

Very impressed with this mod. I've always been interested in the possibility of some self built automation and I am glad to see such a thing is possible.

Thanks for all your hard work djungelorm.

Edited by Loran
Link to comment
Share on other sites

  • 3 weeks later...

This mod looks incredible, and I'm really looking forward to making my own library of autopiloting scripts, but I'm having problems installing the Python client.

I downloaded the server plugin, but when I entered "C:\Python34\Scripts\pip.exe install krpc" in the windows Command Prompt it started downloading/unpacking it but then returned an error:

pip.exceptions.InstallationError: Command python setup.py egg_info failed with error code 1 in C:\Users\Tom\AppData\Local\Temp\pip_build_Tom\protobuf

I would love to be able to start using this mod so any suggestions of what I've done wrong would be greatly appreciated!

Link to comment
Share on other sites

Hi Mango, glad you like the mod :D

The problem is that you need to use python version 2.

The protobuf python package (that the krpc client depends on) doesn't support python 3. I'll look into improving the installer to make the error message a bit more meaningful.

Link to comment
Share on other sites

  • 4 weeks later...

Oh wow! I would definately like to see a Lua client library for this.

Not sure if I could write it myself, maybe I'll give it a shot now it's summer and I haven't got .... to do anyway. Any idea on how hard it would be?

Link to comment
Share on other sites

Oh wow! I would definately like to see a Lua client library for this.

Not sure if I could write it myself, maybe I'll give it a shot now it's summer and I haven't got .... to do anyway. Any idea on how hard it would be?

Would most definitely be cool to see a Lua library, I think it would bring allot of people into modding.

Link to comment
Share on other sites

I found a way to integrate lua into python with lunatic-python (and vice versa). This might be a quick way to support lua utilizing the python client library instead of writing a new one in(/for) lua. Howerver, I can now run lua statements from python, but I have no idea how to procede from here.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...