Jump to content

[1.12.x] kRPC: Control the game using C#, C++, Java, Lua, Python, Ruby, Haskell, C (Arduino)... (v0.5.4)


djungelorm

Recommended Posts

I've created a repository for code examples here: https://github.com/krpc/krpc-library It currently just contains a readme and license file - not sure what we want the structure to be, I guess that will evolve over time. Also, I've followed the licensing pattern used by the kOS community library - i.e. it's MIT license (more details in the readme) 

If you want to add to it, just make a pull request and I'll approve it. And if you're keen and want to help review and merge pull requests, just let me know your github username. I'd be more than happy to add you to the repo permissions!

Link to comment
Share on other sites

On 6/27/2017 at 11:29 PM, Kerbart said:

I took the liberty—and with his permission—to clean up @artwhaley's code a little bit and make it conform to common Python coding practices a bit more. It's basically the same code, I tested it, but it's been refactored for increased readability, which makes it easier to adapt it later. Art suggested that we start looking in some repository for krpc code—github, perhaps? I'm all for it and I'll be more than happy to help out. But without further ado, here's the latest* version of Art's launch script:

*I'd almost say final, but that'd be a fallacy; code is never "done," after all.


import krpc
import time

# ----------------------------------------------------------------------------
# Launch parameters
# ----------------------------------------------------------------------------
MAX_AUTO_STAGE = 0  # last stage to separate automatically
REFRESH_FREQ = 5    # refresh rate
ALL_FUELS = ('LiquidFuel', 'SolidFuel')

# ----------------------------------------------------------------------------
# Main loop
# ----------------------------------------------------------------------------
def main():
    conn = krpc.connect()
    sc = conn.space_center
    v = sc.active_vessel

    # continue checking until user quits program
    while True:
        # check autostage 'REFRESH_FREQ' times per second
        for t in range(REFRESH_FREQ):
            autostage(v)
            time.sleep(1.0 / REFRESH_FREQ)
        show_stage_stats(v) # Every second, print the fuel data per stage!

# ----------------------------------------------------------------------------
# staging logic
# ----------------------------------------------------------------------------
def autostage(vessel):
    '''activate next stage when there is no fuel left in the current stage'''
    if out_of_stages(vessel):
        return
    res = get_resources(vessel)
    interstage = True   # flag to check if this is a fuel-less stage
    for fueltype in ALL_FUELS:
        if out_of_fuel(res, fueltype):
            next_stage(vessel)
            return
        if res.has_resource(fueltype):
            interstage = False
    if interstage:
        next_stage(vessel)

def show_stage_stats(vessel):
    '''for each available stage, bottom to top, show available fuel'''
    print('')
    # iterate from largest stage to final stage to be used
    for stage_num in stages_bottom_to_top(vessel):
        res = get_resources(vessel)
        for fueltype in ALL_FUELS:
            if res.max(fueltype) > 0:
                frac = res.amount(fueltype) / res.max(fueltype)
                print('Stage {}   - {} percentage: {:3.0%}'.format(
                   stage_num,
                   fueltype,
                   frac))

# ----------------------------------------------------------------------------
# Helper functions
# ----------------------------------------------------------------------------
def out_of_stages(vessel):
    '''True if no more stages left to activate'''
    return vessel.control.current_stage <= MAX_AUTO_STAGE

def get_resources(vessel):
    '''get resources of the vessel in the decouple stage'''
    return vessel.resources_in_decouple_stage(
       vessel.control.current_stage - 1,
       cumulative=False)

def out_of_fuel(resource, fueltype):
    '''return True if there is fuel capacity of the fueltype, but no fuel'''
    return resource.max(fueltype) > 0 and resource.amount(fueltype) == 0

def next_stage(vessel):
    '''activate the next stage'''
    vessel.control.activate_next_stage()

def stages_bottom_to_top(vessel):
    '''return an iterator that lists all available stage numbers, bottom to top'''
    return range(vessel.control.current_stage - 1, MAX_AUTO_STAGE - 1, -1)

# ----------------------------------------------------------------------------
# Activate main loop
# ----------------------------------------------------------------------------
main()

Changes made to the code:

  • "magic numbers" captured in constants
  • constants are listed in caps, to make them recognizable as constants
  • every function has a (simple) docstring, making code reuse easier
  • complex expressions are wrapped in functions, making the code "self documenting" as well as easier to maintain
  • cleaned up the fuel stats, by using the python formatting codes instead of concatenating the output together.

Thats really nice, I didn't even think about using def things, and its really cool how you guys kept cleaning up the same code, it looks really nice! Also can't wait to see that github thing!

But I do have a problem, I still can't connect, on this computer. The other works just fine, but this one keeps saying it actively refused it, and yeah, i did have my server started and all that.

Also, I think I found a mistake or two in that code, you set v = conn.sc.active_vessel, but later, you refer to v as vessel instead(I think that wouldn't work)...It starts at staging logic, and goes until the end.

And the other one is that you multi-line comments seem as if they are registering as if they are just in single thing(--> those  'Hi' ). That could fatally break the code and send your rocket to the kraken.

EDIT: Oh, and does this work with BurnTogether, like could I use code to set a ship as a leader, and the rest as a follower?

Also, I got connections working now!

Edited by Axilourous
BurnTogether question
Link to comment
Share on other sites

2 hours ago, Axilourous said:

Also, I think I found a mistake or two in that code, you set v = conn.sc.active_vessel, but later, you refer to v as vessel instead(I think that wouldn't work)...It starts at staging logic, and goes until the end.

It's not a mistake; it's something that you can do in functions (the "def things"). In the main loop, for brevity, the vessel has been given a name tag "v". That is really just a name tag that points to a bunch of data and code, somewhere in the memory of your computer. Since "bunch of data and code" sounds vague and is quite the mouth full, programmers refer to that as an "object." Consider a real life object, a 1962 Chevrolet Corvette you found in an old barn. It's a piece of rust, but you're restoring it. You refer to it as "the dreamcar," while your girlfriend/wife refers to it as "the money pit," or sometimes "the rust bucket." Three names, yet it's all the same object.

What gets passed around to the functions is the object, and how it's called inside a function... is up to the programmer. In the main loop "v" is good enough as it's easy to see what it is, but for the functions that take care of specialized tasks it might not be immediately clear what "v" means and "vessel" is a clearer label.

 

I don't think you can control multiple vessels at once but perhaps @djungelorm can give the definitive answer on that?

 

Not sure I understand your comments about the comments; can you clarify?

Link to comment
Share on other sites

I'm glad you got the connections working -  because I was out of mod related ideas and was going to start wondering about loopback adapters and other network settings that could be keeping the computer from connecting to itself... but sure shouldn't be.

Kerbart's right on the 'v' and 'vessel' thing!   The other reason I initially called it vessel inside all the other functions was that it's quite possible that someone will import that file into another program and then when you start typing "function_name(...."   it's handy if it pops up and reminds you that you should supply a vessel and a flight object, or space_center or whatever is required.

You actually CAN control multiple vessels at once within some limits...  though they have to all be inside physics range (4km, typically?) to be able to access most functions and properties.  I haven't played with 'burn together' but if the features you need are exposed as fields, events or actions you should be able to access them.  Here's the documentation bit for that feature -  https://krpc.github.io/krpc/python/api/space-center/parts.html#module   To find the right vessels you can iterate through conn.space_center.vessels . 

 

 

Edited by artwhaley
Link to comment
Share on other sites

4 minutes ago, MysticPing said:

Urgh I was so excited to try this but I simply cannot get the c# library to work. connection has no member called "SpaceCenter" which means I can't get anywhere or do anything.

Posting a bit of code might help, as we have to guess now.

SpaceCenter is a method, not an attribute, of your connection (returning a SpaceCenter object). Did you call it as a method? Flying blind here, so I have to make guesses.

Edited by Kerbart
Link to comment
Share on other sites

I'm sorry, have to go soon to work a night shift so a bit frustrated. 

using KRPC.Client;
using KRPC.Client.Services.KRPC;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var connection = new Connection(name: "Vessel Name"))
            {
                var spaceCenter = connection.SpaceCenter();
                var vessel = spaceCenter.ActiveVessel;
                System.Console.WriteLine(vessel.Name);
            }
        }
    }
}

Is the code. From the C# Documentation. I can connect to the KSP client and I can acces connection.kRPC() but not SpaceCenter()

Visual studio tells me that connection has this: indCdNB.png

 

 

edit: obCAqB7.png

Edited by MysticPing
Link to comment
Share on other sites

Apologies for the frustration! You need to add "using KRPC.Client.Services.SpaceCenter".

That will add the extension method to the connection object that is needed to get an instance of the space center service.

As far as I can tell the example in the docs is correct: http://krpc.github.io/krpc/csharp/client.html#interacting-with-the-server

Link to comment
Share on other sites

On 7/2/2017 at 11:19 PM, Kerbart said:

It's not a mistake; it's something that you can do in functions (the "def things"). In the main loop, for brevity, the vessel has been given a name tag "v". That is really just a name tag that points to a bunch of data and code, somewhere in the memory of your computer. Since "bunch of data and code" sounds vague and is quite the mouth full, programmers refer to that as an "object." Consider a real life object, a 1962 Chevrolet Corvette you found in an old barn. It's a piece of rust, but you're restoring it. You refer to it as "the dreamcar," while your girlfriend/wife refers to it as "the money pit," or sometimes "the rust bucket." Three names, yet it's all the same object.

What gets passed around to the functions is the object, and how it's called inside a function... is up to the programmer. In the main loop "v" is good enough as it's easy to see what it is, but for the functions that take care of specialized tasks it might not be immediately clear what "v" means and "vessel" is a clearer label.

 

I don't think you can control multiple vessels at once but perhaps @djungelorm can give the definitive answer on that?

 

Not sure I understand your comments about the comments; can you clarify?

Oh okay, that does make sense actually, thanks for answering.

What I meant with the comments was that the words were green, not red, comments are red usually...

#Comment
'''Comment thats not red'''
'Not a comment' 
#^ can be used like 
vessel.resources.amount('LiquidFuel')

^ They are different, I don't know if that's just just the forums, or if its actually not working...

@artwhaley, I don't need to control them at the same time, Just be able to switch and use the part that BurnTogether adds. BurnTogether adds 1 part, you put that part on all the ships you want to follow you(plus yourself), then if you right-click, there are options, like Set As Leader, or Set As Follower(There are others.) I want to know If you can

a.) Switch Vessels with a script, and

b.) access that part to make myself a Leader, and others as a Follower.

also, here is the link to BurnTogether if you want to know more, or I just failed at explaining:

 

Edited by Axilourous
Link to comment
Share on other sites

9 minutes ago, Axilourous said:

Oh okay, that does make sense actually, thanks for answering.

What I meant with the comments was that the words were green, not red, comments are red usually...

^ They are different, I don't know if that's just just the forums, or if its actually not working...

Aah, "triple quotes" are multi-line strings. If you put them right after a definition (of a function or class) they get picked up as a "docstring" and will show up when you generate documentation or invoke the help function on them.

Edited by Kerbart
Link to comment
Share on other sites

1 minute ago, Kerbart said:

Aah, "triple quotes" are multi-line strings. If you put them right after a definition (of a string or class) they get picked up as a "docstring" and will show up when you generate documentation or invoke the help function on them.

Oh, okay

Link to comment
Share on other sites

 The green parts are actually a 'docstring.'  It's a language feature that can be used by automatically generated documentation engines and such. 

The general recommendation, though of course practices differ,  seems to be that 'docstrings are for users and comments are for coders. '  comments explain what you need to know to change a function,  the doc string should explain what you need to know to call it. 

Link to comment
Share on other sites

On 7/4/2017 at 6:58 PM, Axilourous said:

 

@artwhaley, I don't need to control them at the same time, Just be able to switch and use the part that BurnTogether adds. BurnTogether adds 1 part, you put that part on all the ships you want to follow you(plus yourself), then if you right-click, there are options, like Set As Leader, or Set As Follower(There are others.) I want to know If you can

a.) Switch Vessels with a script, and

b.) access that part to make myself a Leader, and others as a Follower.

 

Here's an example of how to do this:

import krpc

conn = krpc.connect()
leader = conn.space_center.active_vessel
follower = [v for v in conn.space_center.vessels if v != leader][0]

print 'leader =', leader.name
print 'follower =', follower.name

leader_module = leader.parts.modules_with_name('BurnTogether')[0]
leader_module.set_action('Set as Leader', True)

follower_module = leader.parts.modules_with_name('BurnTogether')[0]
follower_module.set_action('Set as Follower', True)

As far as I can tell, you don't actually have to switch to the other vessel to interact with the part. This code chooses the follower to be the first vessel it finds that is not the active vessel. You will need to make this smarter if you have more than 2 vessels in your save game.

This code also uses the module class to interact with the actions on the part. In general, if something is available in the right click menu of a part, it will be accessible via the module class (as an action, event or field). This includes mods.

Also, switching vessels is very easy - just set the active_vessel property to a vessel object. For example:

conn.space_center.active_vessel = follower

 

Edited by djungelorm
Typo
Link to comment
Share on other sites

I've been having problems with the autopilot when a ship is using RCS only for steering. Usually it will continually "button mash", inputting control inputs in basically all rotational directions, and some times is slowly creeps over to the vector or pitch and heading I give it. I am using RP-0, thus RealFuel mod if that makes any difference. I've tried adjusting the different variables in the autopilot but since I really have no clue what is causing the issue I feel like I am just stabbing in the dark. When an engine kicks in it starts pointing in the correct direction. Anyone have any advice? Maybe a setting I am missing?

Link to comment
Share on other sites

I haven't seen this problem before, so I don''t have a super quick and simple answer.  My first though, without pouring through the code of the mods... is that RealFuel or something else you've got installed with it could be changing the way RCS torque and/or engine torque are calculated by the autopilot's auto tuning routines?  You could try reducing the stopping time or increasing the overshoot allowance in the autopilot settings?  Just increasing the Kp seems like it ought to help you get pointed in the right direction.  If it goes the right way and starts massively overshooting, then we know it's working and we just need to fine tune parameters.   If with increased P gain it still points the wrong way, we'll know it really is fighting itself.  Try doubling or quadrupling the first number in the pitch and yaw PID gains, and to do that you'll have to turn autotune to False.

The pitch and heading part of the autopilot honestly always 'just works' for me...  so I'm really leaning towards mod interactions.  You don't have throttle controlled avionics installed do you?  Someone had a conflict with that changing their vessel's orientation even when not engaged a couple of weeks ago.  

Other things that might help us - since I probably have a different mod list a craft file isn't totally useful, but a picture or description of the vessel with the RCS layout might help, along with the code you're using and going ahead and asking KRPC what the values of things like 

Vessel.moment_of_inertia

vessel.available_torque

vessel.available_rcs_torque

vessel.available_engine_torque

are?   Sorry for not having a quick "Oh, you forgot to flip the 'don't point the wrong way' switch" answer for you, but we'll get there I'm sure!

Link to comment
Share on other sites

This mod sounds fantastic. It's exactly what I didn't know I absolutely needed, and I would love to use it.

However.

The configure script for the C++ install would appear to be quite, quite broken when trying to install through Cygwin. The script itself fails at checking for asio.hpp usability and presence. Examination of config.log reveals that the problem stems from a plethora of g++ compiler errors, stemming from a missing -D__USE_WIN32_SOCKETS compiler flag somewhere. I would try and add the flag in myself, except that configure doesn't actually appear to contain the compiler call in question. The error occurs at line 16700 in configure.

What am I doing wrong/is there any way to fix this?

Link to comment
Share on other sites

@IncongruousGoat I never tested it with Cygwin, so I'm not surprised it didn't work first time! I've made the necessary changes to fix the build scripts - can you try out this pre-release version and let me know if it works for you too? https://krpc.s3.amazonaws.com/deploy/bug/cygwin/939.1/client/krpc-cpp-0.3.10-21-gf4883cb.zip

And in case you're interested, these are the changes I made: https://github.com/krpc/krpc/commit/f4883cb6d32ff11ecc2ab39f021e10b174f8e020

On 09/07/2017 at 0:07 PM, CodeNeko said:

I've been having problems with the autopilot when a ship is using RCS only for steering. Usually it will continually "button mash", inputting control inputs in basically all rotational directions, and some times is slowly creeps over to the vector or pitch and heading I give it. I am using RP-0, thus RealFuel mod if that makes any difference. I've tried adjusting the different variables in the autopilot but since I really have no clue what is causing the issue I feel like I am just stabbing in the dark. When an engine kicks in it starts pointing in the correct direction. Anyone have any advice? Maybe a setting I am missing?

This is likely due to the RCS torque calculations being horrifically broken in KSP (since 1.2 I think). Relevant bug reports:

http://bugs.kerbalspaceprogram.com/issues/13547

https://github.com/krpc/krpc/issues/354

Probably worth rolling our own RCS torque calculation code (like mechjeb does), but I haven't had time to look into this yet.

Link to comment
Share on other sites

@IncongruousGoat the library should be installed to /usr/local/lib/libkrpc.a

It appears that /usr/include/lib is not a default library path for GCC on Cygwin, but I managed to successfully compile an example app using the following:

g++ test.cpp -std=c++11 -D__USE_W32_SOCKETS -D_WIN32_WINNT=0x0501 -L/usr/local/lib -lkrpc -lprotobuf -lmswsock -lws2_32

A cleaner fix might be to add /usr/local/lib to your LIBRARY environment variable (https://cygwin.com/ml/cygwin/2003-02/msg00306.html)

Link to comment
Share on other sites

13 hours ago, djungelorm said:

@IncongruousGoat the library should be installed to /usr/local/lib/libkrpc.a

It appears that /usr/include/lib is not a default library path for GCC on Cygwin, but I managed to successfully compile an example app using the following:

g++ test.cpp -std=c++11 -D__USE_W32_SOCKETS -D_WIN32_WINNT=0x0501 -L/usr/local/lib -lkrpc -lprotobuf -lmswsock -lws2_32

A cleaner fix might be to add /usr/local/lib to your LIBRARY environment variable (https://cygwin.com/ml/cygwin/2003-02/msg00306.html)

That appears to have sorted it. Thank you.

Link to comment
Share on other sites

On 10/07/2017 at 0:58 AM, artwhaley said:

I haven't seen this problem before, so I don''t have a super quick and simple answer.  My first though, without pouring through the code of the mods... is that RealFuel or something else you've got installed with it could be changing the way RCS torque and/or engine torque are calculated by the autopilot's auto tuning routines?  You could try reducing the stopping time or increasing the overshoot allowance in the autopilot settings?  Just increasing the Kp seems like it ought to help you get pointed in the right direction.  If it goes the right way and starts massively overshooting, then we know it's working and we just need to fine tune parameters.   If with increased P gain it still points the wrong way, we'll know it really is fighting itself.  Try doubling or quadrupling the first number in the pitch and yaw PID gains, and to do that you'll have to turn autotune to False.

The pitch and heading part of the autopilot honestly always 'just works' for me...  so I'm really leaning towards mod interactions.  You don't have throttle controlled avionics installed do you?  Someone had a conflict with that changing their vessel's orientation even when not engaged a couple of weeks ago.  

Other things that might help us - since I probably have a different mod list a craft file isn't totally useful, but a picture or description of the vessel with the RCS layout might help, along with the code you're using and going ahead and asking KRPC what the values of things like 

Vessel.moment_of_inertia

vessel.available_torque

vessel.available_rcs_torque

vessel.available_engine_torque

are?   Sorry for not having a quick "Oh, you forgot to flip the 'don't point the wrong way' switch" answer for you, but we'll get there I'm sure!

Thanks for the help. I boosted the Stopping Time up to something stupid by accident when I was meaning to lower it and that got it starting to move in the right direction. It at least gives me some control over the ship now which is nice.

 

 

On 12/07/2017 at 1:56 AM, djungelorm said:

This is likely due to the RCS torque calculations being horrifically broken in KSP (since 1.2 I think). Relevant bug reports:

http://bugs.kerbalspaceprogram.com/issues/13547

https://github.com/krpc/krpc/issues/354

Probably worth rolling our own RCS torque calculation code (like mechjeb does), but I haven't had time to look into this yet.

Ah, is that so. I'll have to investigate into a better solution then. Maybe I'll get something good enough for a pull request....but I doubt it.

 

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