Jump to content

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


djungelorm

Recommended Posts

Is there anyway to execute a maneuver node created outside of kRPC? For example, if you created a maneuver node, could you write a kRPC script to execute the node that was created before starting the script without creating the maneuver node within kRPC? It looks like the only way kRPC recognized a node is if it is created within itself using control.addnode().

You can get a list of all the maneuver nodes for the active vessel using vessel.control.nodes. This includes maneuver nodes created outside of kRPC (by the player, or other mods).

Edited by djungelorm
Typo
Link to comment
Share on other sites

Hiya!

Just dropped by to say "Great Mod," and then ask a silly question:

When I have autopilot on, my rocket rolls around like a dog. I tried setting "vessel.auto_pilot.target_roll() = 0" but it either hangs on that line, or does not affect the rolling problem at all. My setup is as follows:

vessel.auto_pilot.engage()

vessel.auto_pilot.set_pid_parameters(40,0,0)

vessel.auto_pilot.target_pitch_and_heading(turn_angle, heading)

vessel.auto_pilot.target_roll() = 0

then I set target pitch and heading in a while loop. I always get the pitch and heading, but (again) my rocket is rolling around.

Recommendations?

Link to comment
Share on other sites

  • 3 weeks later...
Will this mod be updated to 1.0.5?
With a little luck it may just need adding a variable for core temperature, but I don't know the inside of KSP so I'm probably wrong.

BTW, I really love this mod. It saved my control console project when I had isolated the source of my recurring game crashes to KSPserialIO. Thanks to this I could solve it with a Python script. Well a Python script after having learnt Python that is, but anyway... :-)
Link to comment
Share on other sites

  • 2 weeks later...

I'm a... dangerous novice at coding... I think it's important to start with that info.

I started playing tonight with building a pretty wxpython telemetry display (basically displaying everything that's on the 'orbit, surface, and vessel info' panes of mechjeb) along with resource data and docking guidance. I'm learning Python as I go (My first thought was to try to write a library for C# and start there, as I've at least done SOME C# programming... but... I decided it was going to be easier to learn Python than to figure out how to get protocol buffers up and running on C# having not dealt with serialization, or socket programming. So... wxpython, even though I know I could make a prettier display in C#, given the number of flight instrument and data display .Net controls you can find...

But I've run into a snag - I'm trying to grab orbit data for the target vessel... but am having trouble getting my hands on the target's orbit? From what I'm reading in the API, vessel.target should return a vessel... so... I thought this would work:



but I'm getting this error:



Is there a better way to get my hands on the target's orbit to add streams for it's orbital parameters?   EDIT:   target = conn.space_center.target_vessel worked!   So, scratch that first question.

And... I've been pulling 16 streams out without noticing any real performance hit, but has anyone noticed a reaonable upper limit to how much data can be subscribed to before performance begins to degrade? I'd hate to design a big gui that grabs all you could ever want.. .but slows KSP to a crawl! Better to do a more minimal app, in that case, and have it run smoothly. So if anyone has any experience on using kRPC until performance suffers, I'd love to hear it?

Also... in the early posts in this thread there was talk of mechjeb integration... has tying in with mechjeb been given any more thought? I would LOVE to be able to send some commands (circularize at apa/pea/now/altitude, transfer planning, execute next node) and pull some data (target closest approach time, distance, and relative velocity... deltav info)... Of course i know I could calculate/implement all of this myself on the python side (or, I suppose, in the kRPC server and make a pull request there)... but... 

EDIT 1 - my code tags are looking weird and in the wrong place since the forum transition, and 2 -  I fixed my first issue, so please ignore that one -  this code got the target vessel instead : target = conn.space_center.target_vessel

vessel = conn.space_center.active_vessel

	target = vessel.target
Traceback (most recent call last):

	File "C:\PythonX\3\test3MyFrame1.py", line 10, in <module>

	target = vessel.target

	File "<string>", line 1, in <lambda>

	File "C:\Python27\lib\site-packages\krpc\client.py", line 122, in _invoke

	raise RPCError(response.error)

	RPCError: The requested feature is not implemented.
Edited by artwhaley
Link to comment
Share on other sites

I'm planning on making a service to integrate some Mechjeb functions with kRPC... but before I got into messing with the code of two plugins, both of which were obviously put together by far more advanced coders than myself, I thought I should do something simple.  I saw that ISRU control got bumped to the next version on the milestone plan...  so I took a stab at roughing in the basics of it.  

Anyone who wants to add the basic ISRU functions can grab my dll at https://www.dropbox.com/s/dm5b5dkaxnr72gc/krpcisru.dll?dl=0  and toss it in their GameData/kRPC folder.  The source code is up at : https://github.com/artwhaley/krpcisru/tree/master/krpcisru

This is very rudimentary... I'll work on rounding it out a bit more if there's interest.  

At the moment it offers the krpcisru server, only available in flight, with methods to deploy and retract drills, start and stop drills, and start and stop ISRU converters.  Examples of all :

>>> conn = krpc.connect()
>>> conn.krpcisru.deploy()
2
>>> conn.krpcisru.harvest_start()
2
>>> conn.krpcisru.harvest_stop()
2
>>> conn.krpcisru.retract()
2
>>> print(conn.krpcisru.isru_list())
Lf+Ox,Monoprop,LiquidFuel,Oxidizer,Lf+Ox,LiquidFuel,Oxidizer,MonoPropellant
>>> conn.krpcisru.isru_start("Lf+Ox")
2
>>> conn.krpcisru.isru_start("Monoprop")
1
>>> conn.krpcisru.isru_stop("Monoprop")
1
>>> conn.krpcisru.isru_stop_all()
2
>>> 

.deploy() deploys any drills (anything with ModuleAnimationGroup and a moduleType of "Drill") and returns the number of drills onboard.

.retract() obviously does the opposite, stowing any drills onboard and returns the number of drills.

.harvest_start() and _stop() start and stop the drills (anything withModuleResourceHarvester on it) and returns the number of drills.

.isru_list() returns a csv list of all ISRU converters onboard

.isru_start("NAMESTRING") starts all ISRU converters with the name in the parenthesis and quotes  (Note, the small and large ISRU stock units have slightly different names for some resource converters... so pay attention if you're writing something that may have to deal with either or both of these!) and returns the number of ISRU converters that matched the name.

.isru_stop("NAMESTRING") stops the named ISRU converter and returns the number of ISRU converters that matched the name.

.isru_stop_all() stops all ISRU converters and returns the number of ISRU converters that were actually stopped.

 

For the general community - what other functions do you need, or information do you need to be able to retrieve?  I haven't figured out the ModuleAsteroidDrill yet...  I suppose I need to fly out there and see if the standard drill module is working on asteroids these days?  

And for djungelorm...  I love what you've done so far with this plugin and hope you don't mind me meddling with it!  How can I help?  You're MORE than welcome to use my code as a starting place to add ISRU control to the main plugin.  I'm willing to add it in and submit a pull request, if you'd like, but I'd want to know where you'd like it to fit in?  I'm thinking it's own file in kRPCSpaceCenter/Services/ with a namespace of spaceCenter.isru maybe?  I also won't be insulted at all if you'd rather deal with it yourself!  In that case I'll yank my .dll down as soon as you get the new version cranked out with ISRU officially included...  Also - in the documentation I think I found a bug:  

On the "Extending kRPC" page the example shows :

   [KRPCProperty]
        public static void Throttle {
            get { return FlightInputHandler.state.mainThrottle; }
            set { FlightInputHandler.state.mainThrottle = value; }
        }

but I had to change it to 

   [KRPCProperty]
        public static float Throttle {
            get { return FlightInputHandler.state.mainThrottle; }
            set { FlightInputHandler.state.mainThrottle = value; }
        }

to get it to compile in VS2015?

Anyway... sorry for so much in one post, I'm just excited that i got this working!   Thanks again for doing something awesome for KSP!

 

Link to comment
Share on other sites

So...  my mechjeb plugin is proceeding rather well, and I'm starting on the gui now.  I think I'll start a separate thread to show off the gui and ask for feedback there, as I think the typical user for a GUI external interface to mechjeb is going to be somewhat different than the core user of kRPC that is interested in rolling their own autopilot in python.  So...  if interested, look for that thread..  I'm going to working title the python app "ExtJeb".  

But here I want to ask about the underlying kRPC extension to see if there are features others want that I'm not implementing since I'm basically building in what I need... or see near term use for.

The extension so far has these methods:  

All SmartASS functions except 'advanced'.  It does include Surface mode, which takes floats for heading, pitch and roll.  Also included is the ability to set and clear the 'force roll' feature.  These functions look like:

conn.krpcmj.sa_prograde()

conn.krpcmj.sa_surface(90,45,0)

 

Then we get into the more 'automated' bits of mechjeb.  I cherry picked the most useful bits to expose this way... so let me know if I've missed a feature you think you'd called via RPC.  At the moment the realized bits are (list of plain text descriptions, to keep it legible):

Activate Ascent Autopilot, taking parameters for altitude, inclination, and both the initial and final roll values.

Cancel Ascent Autopilot

Activate Landing Autopilot, with 'land somewhere' option

Activate Landing Autopilot, with 'land at target' option

Cancel Landing Autopilot

Activate Docking Autopilot

Cancel Docking Autopilot

Activate Rendezvous Autopilot

Cancel Rendezvous Autopilot

((not working, need to trouble shoot) Rover activate, drive to target

rover deactivate

translatron - taking arguments for vertical velocity and boolean for whether or not to cancel horizontal velocity.

translatron cancel



Execute Next Node

Execute All nodes;

Abort Node Execution;



Functions that just create maneuver nodes:

Circularize at Time

Modify Apoapsis at Time

Modify Periapsis at Time

Modify Inclination at Time

Hohmann Transfer to Target

Interplanetary Transfer to Target

Match Velocity with Target Now

Match Velocity with Target at Closest Approach

and... a function to call the mechjeb delta v sim and return atmo and vac deltav and TWR for every stage.

 

 

 Are there any other mechjeb functions you can imagine yourself wanting access to remotely?  Just let me know and I'll see what I can do!  

 

 

 

Edited by artwhaley
Link to comment
Share on other sites

Does anyone else get this error?

Quote

>>> import krpc

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    import krpc
  File "build\bdist.win-amd64\egg\krpc\__init__.py", line 3, in <module>
  File "build\bdist.win-amd64\egg\krpc\client.py", line 1, in <module>
  File "build\bdist.win-amd64\egg\krpc\types.py", line 3, in <module>
ImportError: No module named enum
>>>

Never mind; removing the enum34 egg and reinstalling it with pip did the trick.

Edited by Kerbart
Link to comment
Share on other sites

Has anyone had success getting an accurate surface referenced horizontal speed?

I feel like it should be : vessel.flight(vessel.orbit.body.reference_frame).horizontal_speed ...  and I can use that reference frame to get vertical speed and overall surface speed, and these both agree with both Mechjeb and the navball...  but horizontal velocity is returning a number that doesn't match up with mechjeb...  and I can't figure out what number it is, actually.  If my vector math's were better... I'm sure there's a way to subtract .vertical_speed from .velocity...  but I'm too far out of college algebra. 

Am I passing the wrong reference frame?  I've tried them all....  is there something else I'm doing wrong?  Or have i found a bug that needs squashing?  

Link to comment
Share on other sites

1 hour ago, artwhaley said:

Has anyone had success getting an accurate surface referenced horizontal speed?

I feel like it should be : vessel.flight(vessel.orbit.body.reference_frame).horizontal_speed ...  and I can use that reference frame to get vertical speed and overall surface speed, and these both agree with both Mechjeb and the navball...  but horizontal velocity is returning a number that doesn't match up with mechjeb...  and I can't figure out what number it is, actually.  If my vector math's were better... I'm sure there's a way to subtract .vertical_speed from .velocity...  but I'm too far out of college algebra. 

Am I passing the wrong reference frame?  I've tried them all....  is there something else I'm doing wrong?  Or have i found a bug that needs squashing?  

Looks like the implementation of horizontal_speed is wrong. I am slightly bemused as to how I could ever think the math in the code could ever be correct...

Horizontal speed is currently calculated from the total and vertical speed using: Speed - Math.Abs (VerticalSpeed)

But that's just plain wrong - the calculation should be done using Pythagoras' theorem (right?) so should be:  Math.sqrt(Speed^2 - VerticalSpeed^2)

PS. Nice work on the ISRU code and mechjeb plugin! :) will take a proper look when I have time (which is unfortunately rare these days...)

Edited by djungelorm
Link to comment
Share on other sites

Yes, exactly!  That's much better than my idea of trying to figure out how to subtract the vertical speed from the actual velocity vector!  And, simple enough that even I could code it. :P  Would you like me to fix it and make a pull request?  And, would you like me to try adding the ISRU stuff to the main DLL and pull request when I've got it all working?  Or would you rather I just keep it as a separately available .dll that people can grab if they'd like?  

Link to comment
Share on other sites

6 minutes ago, artwhaley said:

Yes, exactly!  That's much better than my idea of trying to figure out how to subtract the vertical speed from the actual velocity vector!  And, simple enough that even I could code it. :P  Would you like me to fix it and make a pull request?  And, would you like me to try adding the ISRU stuff to the main DLL and pull request when I've got it all working?  Or would you rather I just keep it as a separately available .dll that people can grab if they'd like?  

Yeah sure, by all means make a pull request :) I think the ISRU stuff should eventually be merged into the spacecenter dll, I should have some time tomorrow to look at your work and figure out to best fit it in.

Link to comment
Share on other sites

After a little thought and looking at the structure of everything, it seems to me the best way to add ISRU to space_center proper would be to add two classes to kRPCSpaceCenter>Services>Parts .  One for harvesters and one for converters?  That should keep it organized and generic to make sure fuel cells and the like are covered as well?  I'll take a look back at my code.  It was the first plugin work I'd done in over a year and I had to remember where everything was so I'm sure there are things I can clean up.  I'll wait for your okay or no-kay to really get to work on it though, in case you've got better ideas or want to do something yourself - I don't want to step on toes!

Link to comment
Share on other sites

13 minutes ago, artwhaley said:

After a little thought and looking at the structure of everything, it seems to me the best way to add ISRU to space_center proper would be to add two classes to kRPCSpaceCenter>Services>Parts .  One for harvesters and one for converters?  That should keep it organized and generic to make sure fuel cells and the like are covered as well?  I'll take a look back at my code.  It was the first plugin work I'd done in over a year and I had to remember where everything was so I'm sure there are things I can clean up.  I'll wait for your okay or no-kay to really get to work on it though, in case you've got better ideas or want to do something yourself - I don't want to step on toes!

Yeah I agree. The two classes should be implemented in the same way as, for example, solar panels: https://github.com/djungelorm/krpc/blob/master/src/kRPCSpaceCenter/Services/Parts/SolarPanel.cs

Feel free to implement it and make a pull request :)

Link to comment
Share on other sites

So I have a question about this part:

Quote

public LandingLegState State {
            get {
                switch (leg.legState) {
                case ModuleLandingLeg.LegStates.DEPLOYED:
                    return LandingLegState.Deployed;
                case ModuleLandingLeg.LegStates.RETRACTED:
                    return LandingLegState.Retracted;
                case ModuleLandingLeg.LegStates.DEPLOYING:
                    return LandingLegState.Deploying;
                case ModuleLandingLeg.LegStates.RETRACTING:
                    return LandingLegState.Retracting;
                case ModuleLandingLeg.LegStates.BROKEN:
                    return LandingLegState.Broken;
                case ModuleLandingLeg.LegStates.REPAIRING:
                    return LandingLegState.Repairing;
                default:
                    throw new ArgumentException ("Unknown landing leg state");
                }
            }
        }

(my C isn't very good at all)

Why is it returning an <enum 'LandingLegState'> LandingLegState.deployed instead of a string "deployed" or even just deployed?

Can I fix this by just replacing it with 

Quote

                case ModuleLandingLeg.LegStates.DEPLOYED:
                    return 'deployed';

?

Thank you very much for your hard work at making KSP more fun!

edit: Just looked  up enum, and it makes more sense now. Sort of.

edit: edit: Just found enum.name fixes everything:

Quote

>>vessel.parts.landing_legs[0].state.name

'deployed'

 

Edited by postalbyke
Fixing myself, fixing the look of the code boxes
Link to comment
Share on other sites

I think you totally answered that yourself, but yes - it's a way to return something that's hopefully useful for both times when you want to do something human readable AND when you want to do something more machine readable.  It's much easier to have your script make a decision based on a returned Enum than having to teach it to parse the string, then make decisions based on what it learns from that.

 

I'm trying to figure out the best way to do this with resource converters as I add them to kRPC right now, since their 'status' message holds a lot of data - % of load, which resource is missing, etc...  I'm thinking I'm going to resolve it by using two methods, one that returns an enum with the basic status - 'converting, missing resource, turned off, tank is full, overheating' and then a second method to return the status_string for those times when you just want to take whatever the part says and show it to a user...

Link to comment
Share on other sites

Any reason why even the first suborbital example completely fails at giving any pitch/heading directions to the ship? Conflict with other mods? I also can't set the SAS mode, it always defaults to False. What is happening?

Edit: After some debugging and tinkering with the script; i've learned a few things:
The autopilot DOES work, but it only has enough control if vessel.auto_pilot.rotation_speed_multiplier is set to something like 5. It will hold it's position then, however it will turn too fast and destroy the rocket when the target pitch-yaw is changed. This tells me that it's probably the PID parameters that are hopelessly out of whack. Yet i haven't changed anything, this is the stock rocket and stock script (except for some print commands). What is happening? Can't really start working on a full system (i have big plans for this) if i can't even get the stock tutorial script to work right.

Edited by lolzor
Link to comment
Share on other sites

3 hours ago, lolzor said:

Any reason why even the first suborbital example completely fails at giving any pitch/heading directions to the ship? Conflict with other mods? I also can't set the SAS mode, it always defaults to False. What is happening?

Edit: After some debugging and tinkering with the script; i've learned a few things:
The autopilot DOES work, but it only has enough control if vessel.auto_pilot.rotation_speed_multiplier is set to something like 5. It will hold it's position then, however it will turn too fast and destroy the rocket when the target pitch-yaw is changed. This tells me that it's probably the PID parameters that are hopelessly out of whack. Yet i haven't changed anything, this is the stock rocket and stock script (except for some print commands). What is happening? Can't really start working on a full system (i have big plans for this) if i can't even get the stock tutorial script to work right.

I just tried both the "sub-orbital flight" and "launch into orbit" tutorial scripts and they ran fine for me on my stock KSP 1.0.5. Do you have any mods (like FAR) installed? If so then yes, the PID parameter probably need re-tuning as the turning forces etc. will be different. Have you tried adjusting auto-pilot parameters other than rotation_speed_multiplier? Increasing the proportional gain should help if the auto-pilot control inputs are too small to turn the vessel.

Link to comment
Share on other sites

I can confirm that the autopilot is fully functional. Here's the magic I use in my launch script:

            ap.engage()
            ap.target_pitch_and_heading(self.profile.value(alt), 90)

And that works absolutely fine with me. Playing stock only, only mods are those that provide information (KER, DPAI, etc) or enhance visual experience (texture replacer, EVE, etc).

Keep in mind that, contrary to most mathematical standards, kRPC needs angles in degrees, not radians. Which is fine with me, as I find that more convenient anyway.

Link to comment
Share on other sites

Ah yes that is the problem, i use FAR (along with a metric ton of other mods). I tried the LaunchToOrbit scenario and, with the rotation_speed_multiplier set to 5, it works perfectly. I will do some tests to figure out what the optimal PID gain is.
This might be KSP`s greatest mod. I remember clamoring for this a few years ago. Now all that is needed is a remote node/manover planning tool to be really able to remotely operate a flight from start to finish like a Mission Control.

Link to comment
Share on other sites

  • 2 weeks later...

So, I'm still plodding along at my mechjeb integration for kRPC...  and I'm at a point where I probably ought to ask for some guidance from @djungelorm and anyone else who's interested in playing with it.  

EDIT:  I asked a dumb question, then managed to come up with my own dumb answer to a technical problem.  

I was trying to figure out how best to tell my service what ship to work on.  Because I'm trying not to touch any of the core kRPC or SpaceCenter code, I've decided to just give my service a property for getting and setting the ship that we're controlling the mechjeb unit on...  that way you can do something like:

conn.krpcmj.apvessel= conn.space_center.active_vessel

conn.krpcmj.sa_prograde()

con.krpcmj.apvessel = conn.space_center.target_vessel

conn.krpcmj.sa_retrograde()

To give one command to the active vessel and another to the target.   Is this the best way to handle this?

But, on to the philosophical question:

Do you want me to work towards adding my assembly to the main kRPC project when the bugs are all worked out for future distribution with kRPC, or would you rather me release it separately as a plugin to your plugin?  I'm happy to contribute to kRPC... but also don't want to try to push an entire assembly on you if I'm not adding features that you'd like your plugin to have!  I'll get the source up on github in the next day or two so you can really see what I'm doing...  but it's a fairly complete-ish interface to mechjeb's autopilot modules.

Edited by artwhaley
Got a little smarter. But just a little.
Link to comment
Share on other sites

I've got the source for my service up at : https://github.com/artwhaley/krpcmj   

My todo list on it is still -

Add controls for the rover autopilot

Address Error handling - make sure everything fails gracefully or returns a useful exception

Really dig into the maneuver planner and make sure there's not anything essential I've left out

Look at my 'helper' methods to see if any of them should be contributed to the space center service instead - they're mostly ways to get useful bits of orbital data while planning maneuvers.

As an example - here's 31 lines of code that that spawn a resupply vessel, ask you where to send it, and then launch, circularize, rendezvous and dock all without further attention.  All of this is perfectly possible with kRPC by itself, but adding mechjeb cuts some thought (and code) out. 

import krpc                                            #Typical kRPC setup stuff
conn=krpc.connect()
print("Setting Up...")
conn.space_center.launch_vessel_from_vab("resupply")    #Spawn the resupply vessel
mj=conn.krpcmj                                          #mj service
mj.apvessel=conn.space_center.active_vessel             #Assign MJ control to active vessel
targetname = raw_input('Type Name of Target Vessel:')   #tell it whom to rendezvous with

vessels=conn.space_center.vessels						#Find and set the target
for v in vessels:
    if v.name==targetname:
        conn.space_center.target_vessel=v
        print("Target Found...")

print("Launching to Rendezvous...")
mj.ascent_rdzv(conn.space_center.target_vessel)                          #Ascend to Rendezvous 
mj.ascent_alt=conn.space_center.target_vessel.orbit.apoapsis_altitude    #Sets Launch Alt to target Apoapsis
mj.ascent_inc=conn.space_center.target_vessel.orbit.inclination          #Matches Launch Inclination to Target                                             
while mj.ap_status>0:                                    				 #Waits until Ascent AP is complete
    pass

print("Activating Rendezvous Autopilot...")
mj.apvessel.control.rcs=True                    #enable RCS for maneuvering and docking
mj.rendezvous_ap=True                           #Activate Rendezvous AP to get close
while mj.ap_status>0:                           # Wait until Rendezvous AP exits
    pass

print("Activating Docking Autopilot")
ports=mj.apvessel.parts.docking_ports           #Next 3 lines set up 'Control from Here' on docking port
port = list(filter(lambda p: p.part.title == 'Clamp-O-Tron Docking Port', ports))[0]
mj.apvessel.parts.controlling=port.part

targetports=conn.space_center.target_vessel.parts.docking_ports          #Next 3 lines set target docking port
targetport=targetports[0]
conn.space_center.target_docking_port=targetport

mj.docking_ap=True                              #Activate Docking AP

 

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