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 currently writing a tutorial for the documentation site that does exactly this - so watch this space!

Excellent. In particular, I'm having trouble figuring out how to maintain surface-relative retrograde orientation during descent/landing (what MechJeb SmartASS mode calls SVEL-).

Edited by Borogove
Link to comment
Share on other sites

Excellent. In particular, I'm having trouble figuring out how to maintain surface-relative retrograde orientation during descent/landing (what MechJeb SmartASS mode calls SVEL-).

This should do it:


while True:
# Get the velocity vector relative to the surface of the body
velocity = vessel.flight(vessel.orbit.body.reference_frame).velocity
# Get the opposite direction
retrograde = (-velocity[0], -velocity[1], -velocity[2])
# Set the direction in the autopilot
vessel.auto_pilot.set_direction(retrograde, vessel.orbit.body.reference_frame)

As the velocity vector will change during descent, you'll need to keep feeding updates to the autopilot (hence the while loop).

Link to comment
Share on other sites

Accessing vessel.thrust either directly or via add-stream throws an exception:


File "/Users/russell/Library/Application Support/Steam/SteamApps/common/Kerbal Space Program/GameData/kRPC/scripts/mission.py", line 199, in update
self.update_telemetry()
File "/Users/russell/Library/Application Support/Steam/SteamApps/common/Kerbal Space Program/GameData/kRPC/scripts/mission.py", line 190, in update_telemetry
thrust = self.vessel.thrust
File "/Library/Python/2.7/site-packages/krpc/service.py", line 167, in <lambda>
fget = lambda s: getattr(s, _to_snake_case(getter.name))()
File "/Library/Python/2.7/site-packages/krpc/service.py", line 154, in <lambda>
return_type=return_type)
File "/Library/Python/2.7/site-packages/krpc/service.py", line 24, in _invoke
param_names, param_types, return_type)
File "/Library/Python/2.7/site-packages/krpc/client.py", line 103, in _invoke
raise RPCError(response.error)
krpc.error.RPCError: KRPC.Service.RPCException: Procedure 'SpaceCenter.Vessel_get_Thrust' threw an exception. System.NullReferenceException: Object reference not set to an instance of an object
at KRPCSpaceCenter.Services.Vessel.get_Thrust () [0x00000] in <filename unknown>:0
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
at KRPC.Service.Services.HandleRequest (KRPC.Service.Scanner.ProcedureSignature procedure, System.Object[] arguments) [0x00000] in <filename unknown>:0
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

Link to comment
Share on other sites

Try a different frame of reference -- you're using a vessel-relative frame, and the vessel doesn't move relative to itself.

I'll try. What throws me off is that altitude, etc do work. One would think those would be zero too then?

EDIT:

It was a good suggestion, but alas. Velocity is zero, independent of the reference frame used. Both surface_reference_frame and orbital_reference_frame (well, more specifically vessel.flight(vessel.surface_reference_frame).velocity -- for the nitpickers) return (0.0, 0.0, 0.0) when the vessel is clearly moving.

Edited by Kerbart
Link to comment
Share on other sites

Both vessel.surface_reference_frame and vessel.orbital_reference_frame are fixed relative to the vessel (just like vessel.reference_frame), so will also return 0 for the velocity. (The way these reference frames differ is the directions their axes point in).

To get surface relative velocity, you need the reference frame that is fixed relative to the planet (and rotates with the planet):

vessel.flight(vessel.orbit.body.reference_frame).velocity

For orbital velocity, you need a reference frame fixed relative to the planet being orbited, but which does not rotate with the body:

vessel.flight(vessel.orbit.body.non_rotating_reference_frame).velocity

Regarding altitude - this and some other properties aren't dependent on the reference frame. The reference frame is only needed for position, direction and velocity vectors.

Hope that helps! Btw a tutorial covering this rather confusing stuff, and a new version with lots of improvements will be released some time this weekend :)

Link to comment
Share on other sites

Both vessel.surface_reference_frame and vessel.orbital_reference_frame are fixed relative to the vessel (just like vessel.reference_frame), so will also return 0 for the velocity. (The way these reference frames differ is the directions their axes point in).

To get surface relative velocity, you need the reference frame that is fixed relative to the planet (and rotates with the planet):

vessel.flight(vessel.orbit.body.reference_frame).velocity

For orbital velocity, you need a reference frame fixed relative to the planet being orbited, but which does not rotate with the body:

vessel.flight(vessel.orbit.body.non_rotating_reference_frame).velocity

Thank you very much! I hope you can endure my questions! :)

Link to comment
Share on other sites

Of course! Questions are actually really helpful as they help me make it better by highlighting bits that are confusingly designed.

For example, I realised getting the vessel to point surface retrograde was rather unwieldy, so I'm adding a new reference frame to make it a whole lot better (the "workaround" solution I posted a while back requires a horrid while loop).

Link to comment
Share on other sites

I've released version 0.1.5 - links updated in the first post.

The list of changes is quite long, but the most notable things are:

  • The server now persists across game scene changes
  • Integration with FAR and RemoteTech API
  • Added some tutorials to the documentation: http://djungelorm.github.io/krpc/docs/tutorials.html
  • Reference frame improvements:
    • Tutorial: http://djungelorm.github.io/krpc/docs/tutorials/reference-frames.html
    • Fixed lots of bugs
    • Added Vessel.surface_velocity_reference_frame and Node.orbital_reference_frame
    • Removed Vessel.non_rotating_reference_frame and Body.surface_reference_frame
    • The default reference frame for Vessel.flight() and the auto-pilot is now Vessel.surface_reference_frame
    • Visual debugging - you can draw direction vectors in-game to visualize what's going on

Link to comment
Share on other sites

Wow, great job on the new documentation on reference frames. Three thumbs up.

Now the only feature I'm looking for is the ability to inspect and interact with parts on the vessel. I suppose the variety of different kinds of parts might make this challenging (I'm guessing that protocol buffers don't magically support C# introspection), but the use cases I currently have in mind are:

* Activate parachutes while trying to land, regardless of where the parachutes are in the vessel staging sequence

* Making a good estimate of vessel delta-V budget by walking up the staging sequence and identifying engines and fuel tanks

* Finding docking ports and setting them as the control-from-here and target points

* Finding and activating science parts

Basically, I'm used to using Mechjeb, and am trying to get my script to be a more autonomous vessel controller that can run as much of a mission without human input as possible, with a very high-level input command structure.

Link to comment
Share on other sites

Wow, great job on the new documentation on reference frames. Three thumbs up.

Now the only feature I'm looking for is the ability to inspect and interact with parts on the vessel. I suppose the variety of different kinds of parts might make this challenging (I'm guessing that protocol buffers don't magically support C# introspection), but the use cases I currently have in mind are:

* Activate parachutes while trying to land, regardless of where the parachutes are in the vessel staging sequence

* Making a good estimate of vessel delta-V budget by walking up the staging sequence and identifying engines and fuel tanks

* Finding docking ports and setting them as the control-from-here and target points

* Finding and activating science parts

Basically, I'm used to using Mechjeb, and am trying to get my script to be a more autonomous vessel controller that can run as much of a mission without human input as possible, with a very high-level input command structure.

Thanks :) I agree a parts API is an essential feature. I had a go at implementing something a while back, never quite finished it, but the design was as follows:

Add the following to the Vessel class:

  • Vessel.parts - returns a list of Part objects, one for every part in the vessel
  • Vessel.root_part - the root part, from which you can walk the tree of parts that make up the vessel

Add a Part class with methods/properties including:

  • Part.name - the name of the part, e.g. "mk1pod"
  • Part.parent and Part.children - for traversing the tree of parts that make up the vessel
  • Part.modules - a list of string names of the part modules that the part has (gives an indication of the type of part, e.g. engine/solar panel etc.)
  • Part.actions - returns a list of toggle-able actions, as strings, such as "Activate Engine" or "Toggle Torque"
  • Part.trigger_action (string actionName)
  • Part.fields - a dictionary mapping names of fields to their values (for example this would contain the part's temperature, and engines current thrust or other custom data)
  • Part.mass
  • Part.stage - which stage is the part in?
  • ... and other general properties
  • And maybe a few helper functions to make some common use cases a bit less cumbersome, such as getting the dry mass of a part (without resources)

These general lists of action/field names should mean that the API will automatically pick up new functionality added by mods etc. And I think this design will support the use cases you suggested.

Edited by djungelorm
typo
Link to comment
Share on other sites

Version 0.1.6 has been released! :)

Download link: https://kerbalstuff.com/mod/636/kRPC:%20Remote%20Procedure%20Call%20Server

The main changes are:

  • Parts API
    • Tutorial here: http://djungelorm.github.io/krpc/docs/tutorials/parts.html
    • You can now inspect the parts that make up a vessel, and traverse the parts tree
    • Interact with part fields, methods and actions (i.e. everything that appears in the right click menu of a part). This should also work with functionality added to parts via mods.
    • Classes to make interaction with of types of stock part simple, including: engines, decouplers, docking ports, landing legs, landing gear, parachutes, ...
    • Change which part the vessel is controlled from
    • All the tools you should need to write a docking autopilot!

    [*]Ability to get/set the current target

And for those of you wanting to write your own client, I've included the source for the protocol buffer messages, and compiled versions for Python, Java and C++.

Link to comment
Share on other sites

Great mod! I'm currently tinkering with writing a C++ client for this. I should have something to show for it soon!

I was wondering if it is at all possible to issue Control commands to non-active, nearby vessels? i.e. by first obtaining a list of Vessels, then pick a vessel that is not the active vessel, send it pitch/yaw/roll/throttle commands to it? Will the vessel react to these commands?

Link to comment
Share on other sites

Great mod! I'm currently tinkering with writing a C++ client for this. I should have something to show for it soon!

Cool :)

I was wondering if it is at all possible to issue Control commands to non-active, nearby vessels? i.e. by first obtaining a list of Vessels, then pick a vessel that is not the active vessel, send it pitch/yaw/roll/throttle commands to it? Will the vessel react to these commands?

It's not possible at the moment - only the active vessel can be controlled. Shouldn't be too difficult to add this feature though.

Link to comment
Share on other sites

Can kRPC use Python 3?

kRPC doesn't currently support python 3 due to it's dependency of Google's protobuf library. However, a quick Google search reveals Google has recently released a new version that supports python 3 :) I'll have a go at upgrading the library.

And how do I connect remotely?

To connect remotely (over a local network) you first need to configure the server to listen on a network interface that's connected to the network. This can be done from the server window pictured here: http://djungelorm.github.io/krpc/docs/getting-started.html#installation Click on the button next to "Address" and it'll give you a list of IP addresses for the network interfaces on your machine. You can also enter the IP address manually.

You also need to get the client to connect to the correct IP address. For example the following, but replaced with your IP address:


import krpc
conn = krpc.connect(address='123.123.123.123')

If you're trying to do this over the internet, you'll probably need to set up port forwarding on your router and get the client to connect to your routers WAN IP - depends on your set up though.

Link to comment
Share on other sites

As promised, I've put together a prototype C++ client. See my github repo for more info: https://github.com/Vivero/KNav

The repo includes a general purpose interface library I've named KRPCI, which interacts with the RPC server (I haven't implemented any support for the stream server yet).

I then wrote a tool which queries the SpaceCenter service (or any service, for that matter), and generates a header and source file for an auto-generated class, which implements all the procedures/enums/classes provided by that service. Using this tool, I create the KRPCI_SpaceCenter library, which -- as you may have guessed -- provides function calls to all the procedures provided by the SpaceCenter service.

Finally, as a use-case example, I created KNav, a small auto-pilot program which currently only has one function: it maintains your craft in a fixed-altitude hover. I'm looking forward to expanding its capabilities. Especially with the new Parts API you've added on!

This code is very very new, and I haven't tested a lot of things. Currently it only runs and compiles on Windows. Hopefully any other developers looking to implement their own C++ autopilot programs can take advantage of this code.

Link to comment
Share on other sites

What exception will be raised if you use a FAR-dependent variable like flight.terminal_velocity while FAR isn't installed?

The python client will throw a krpc.error.RPCError exception. (In fact that's the only thing a failed RPC will throw - the message will differ based on the actual error though.) You can check if FAR is installed using conn.space_center.far_available

--------- EDIT: -----------

This got me thinking. Maybe kRPC should allow custom exception types to be defined in a service, and expose them to the client. Then you could use whatever exception handling mechanism the client language has to differentiate between different sorts of errors.

Edited by djungelorm
Link to comment
Share on other sites

Does anyone know how to get all the completions in Visual Studio Community 2013 with Python Tools? Only some of them appear for me, yet everything works.

Oooo interesting, my guess is that it's because the classes and methods are dynamically created when the client connects to the server. I don't have experience with VS, so I don't know if there is an easy workaround for this.

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...