Coder Social home page Coder Social logo

mit-ll / spacegym-kspdg Goto Github PK

View Code? Open in Web Editor NEW
43.0 14.0 8.0 22.22 MB

Non-cooperative satellite operations challenge problems implemented in the Kerbal Space Program game engine

License: MIT License

Python 100.00%
autonomous-controller autonomous-vehicles differential-games kerbal-space-program non-cooperative-game reinforcement-learning satellite-constellation space openai-gym

spacegym-kspdg's Introduction

KSPDG: Kerbal Space Program Differential Games

Announcement: 2nd Annual Non-Cooperative Space Operations Challenge @ AIAA SciTech 2025

Join us at AIAA SciTech 2025 for a software design competition where participants develop autonomous agents for maneuvering satellites engaged in non-cooperative space operations.

Interested teams should sign up at https://www.surveymonkey.com/r/2MB8JDW, then they will be notified of upcoming meetings.

  • Participants will develop agents capable of solving several challenge problems related to non-cooperative space operations, e.g., pursuing an evasive satellite, multi-satellite proximity operations, etc.
  • Participants are encouraged to develop agents using a range of technologies, e.g., reinforcement learning, optimal control, game theoretical techniques, etc.
  • Participants’ agents will be evaluated on a range of metrics, such as time to completion of mission, fuel consumption, relative distances achieved, etc.
  • The participant pool will undergo a series of elimination events and teams with the best performing agents will be invited to present their agents via a live demonstration during a special session at AIAA SciTech in January 2025
  • Monthly meetings will be held in the lead up to SciTech to allow technical exchanges between participants, MIT Lincoln Laboratory developers, and AIAA SciTech organizers.

There is no cost to participate and membership and/or SciTech registration is not required.

KSPDG Overview

This library provides a suite of differential game (DG) challenge problems / environments set in the orbital domain built within the Kerbal Space Program (KSP) game engine. The intent of the KSPDG library is to provide benchmark challenge problems for evaluating autonomous control and AI algorithms applied to non-cooperative space operations.

The KSP differential game environments are implemented using the OpenAI Gym (or more specifically Gymnasium which is the drop-in-replacement, maintained fork of Gym) and PettingZoo standards. Non-GUI control of the KSP game engine is enabled by kRPC and control of physically distant spacecraft is enabled by PhysicsRangeExtender.

Design Principles

  • Differential Games in the Orbital Domain
    • First and foremost, KSPDG defines a set of differential games (e.g. pursuit-evasion) to be solved in the orbital domain.
  • Standardized API
    • KSPDG uses the OpenAI Gym API for agent interactions to provide an industry-standard interface for control algorithms and agents
  • Open Source and Extensible
    • KSPDG is made open source so that the broader community can create new scenarios/environments for benchmarking
  • Evaluation, Not Training
    • KSPDG provides evaluations environments, NOT training environments for reinforcement learning algorithms. There are several reasons for this.
    • Practically speaking, KSP was not designed for the massively parallel, faster-than-real-time, headless execution typically needed for large-scale RL training.
    • From a more principled perspective, it can be argued that non-trainable evaluation environments are of vital importance to the RL research community as they act as the true "test set" for which you cannot overfit your agents upon because they cannot be directly trained upon.
    • Furthermore, trainable environments tend to imply that RL is the most effective solution method. We make no such assumption; indeed optimal control techniques and numerical differential game solvers may produce superior results in terms of development time, robustness, and optimality.
  • Environments, Not Agents
    • Similar to other "gym" libraries, KSPDG only provides environments (aka scenarios, challenge problems), not the agents that solve those environments. Developing agents that best solve the KSPDG environments is work for the broader community.
  • Non-Blocking Step Function
    • In KSPDG, game time does not pause while agents make decisions. This is a defining characteristic of KSPDG as best matches the real world and provides an inherent penalty to decision and control policies that take a long time to compute.

Environments / Challenge Scenarios

KSPDG is collection of orbital challenge problems defined within different scenario groups (i.e. "evaluation environments" to use nomenclature from reinforcement learning literature). As of Sep 2023, the challenge problems thus far implemented in KSPDG can be grouped into the following types of scenarios

In future development plans include scenarios with features like partial observability, multi-agent inspection problems with vision-based observation spaces, and head-to-head scenarios that leaverage the Luna Multiplayer mod that allow direct competition between two different AI players (current scenarios involve testing AI against pre-scipted bot adversaries)


Citation

DOI

@inproceedings{allen2023spacegym,
  title={SpaceGym: Discrete and Differential Games in Non-Cooperative Space Operations},
  author={Allen, Ross E and Rachlin, Yaron and Ruprecht, Jessica and Loughran, Sean and Varey, Jacob and Viggh, Herbert},
  booktitle={2023 IEEE Aerospace Conference},
  pages={1--12},
  year={2023},
  organization={IEEE}
}

Disclaimer

DISTRIBUTION STATEMENT A. Approved for public release. Distribution is unlimited.

This material is based upon work supported by the Under Secretary of Defense for Research and Engineering under Air Force Contract No. FA8702-15-D-0001. Any opinions, findings, conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the Under Secretary of Defense for Research and Engineering.

© 2024 Massachusetts Institute of Technology.

Subject to FAR52.227-11 Patent Rights - Ownership by the contractor (May 2014)

SPDX-License-Identifier: MIT

The software/firmware is provided to you on an As-Is basis

Delivered to the U.S. Government with Unlimited Rights, as defined in DFARS Part 252.227-7013 or 7014 (Feb 2014). Notwithstanding any copyright notice, U.S. Government rights in this work are defined by DFARS 252.227-7013 or DFARS 252.227-7014 as detailed above. Use of this work other than as specifically authorized by the U.S. Government may violate any copyrights that exist in this work.


Installation

The installation process includes several components:

⚠️ Note These instructions have been written and verified on a macOS. They have been partially tested on Ubuntu 18.04 as well. Other operating systems should be similar with deviations on file and directory names

Install KSP & Making History Expansion

  1. Purchase and Download Kerbal Space Program and Making History expansion: https://store.privatedivision.com/game/buy-kerbal-space-program-ksp
    • Make sure to purchase Direct Download / DRM Free Private Division as the platform. Make sure you are buying KSP1 and not the recently released KSP2; none of this will work on KSP2!
    • Download the most recent version of KSP "On Final Approach" Portable (.zip). As of this writing and testing, the most recent version was v1.12.5
    • Download the most recent version of Making History expansion pack. As of this writing the most recent version was v1.12.1
  2. Unzip ksp-osx-1.12.5.zip to desired location; for simplicity, all instructions assume the unzipped KSP folder is placed on the Desktop
  3. Attempt to open the KSP game executable/app (e.g. KSP.app on Mac)

⚠️ Troubleshooting

  • On a Mac, you might run into an error where you can't open the KSP app because the developer can't be verified.
  • To change these preferences on your Mac, choose Apple menu > System Preferences, click Security & Privacy
  • Under the General tab there should be a notification saying something like "KSP.app was blocked ..." if you've attempted to open the KSP app. Click the "Open Anyway" button next to the notification

⚠️ Troubleshooting

  • On a Mac, after enabling KSP to be opened in Security and Privacy, you may encounter a bug where the game loading screen stalls indefinitely
  • The workaround is to move the KSP.app icon onto the desktop and then back into the KSP_osx directory. For some reason bash commands didn't seem to work to fix this bug. Had to manually open Finder, drag the KSP.app icon onto the Desktop, and then drag it back into the KSP_osx/ directory
  1. Unzip KSP-Making_History_Expansion-en-us-mac-1.12.1.zip
  2. Follow the instructions in the Instructions-xxx-xx-xx.txt file located in the unzipped Making History Expansion directory.

Instructions:

  1. Copy the two other files located in this folder (.command and .zip) to the folder where the KSP app is located
  2. Once you have copied the files, double click the .command file Thats it! Enjoy the Making History Expansion of Kerbal Space Program!
  1. Test installation by opening KSP (e.g. KSP.app on Mac). When main screen has loaded, select Start Game and you should see options for Play Missions and Mission Builder to confirm that the Making History Expansion was successfully installed

Install KSPDG Mission Save Files

For each differential game environment there are associated mission files created using the "Making History" expansion pack that serves to populate the KSP game engine with the necessary spacecraft in the appropriate orbits. There is also a number of mission save files for in-game software development testing purposes.

The save files are located in this repo under ksp_files/saves/missions and ksp_files/Missions; both sets are necessary to populate the differential game environments. These mission save files must be downloaded and manaully installed into the correct directory of the KSP game installation.

Copy the contents of ksp_files/saves/missions/ and ksp_files/Missions directory into your local installation of KSP. For example, on a Mac with this repo and KSP's install directories on the desktop this would look like:

git clone [email protected]:mit-ll/spacegym-kspdg.git
cd spacegym-kspdg
cp -r ksp_files/saves/missions/. ~/Desktop/KSP_osx/saves/missions
cp -r ksp_files/Missions/. ~/Desktop/KSP_osx/Missions

Install kRPC Server

kRPC is what allows external scripts and processes (such as python programs) to send commands to and control the KSP game engine

  1. Download latest version of kRPC from the GitHub link on the kRPC Getting Started Page. As of this writing, you should download krpc-0.5.2.zip. NOTE: make sure to download a full version, not just the python package; v0.5.2 is a full version but v0.5.3 is just the python package
  2. Unzip krpc-0.5.2/ folder to ~/Desktop/krpc-0.5.2/
  3. Create a new directory in KSP's GameData directory and move all of the krpc contents there
mkdir ~/Desktop/KSP_osx/GameData/kRPC
mv ~/Desktop/krpc-0.5.2/* ~/Desktop/KSP_osx/GameData/kRPC/

Install PhysicsRangeExtender

By default in KSP, high-fidelity physical simulation of spacecraft is only performed for spacecraft very near to the active spacecraft (e.g. only around 2km). PhysicsRangeExtender allows for better simulation (e.g. thusting maneuvers) of more distant spacecraft.

  1. Clone PhysicsRangeExtender (assumed to be cloned to Desktop in these instructions, but you can put it wherever you like since you will be copying things from the clone to GameData)
  2. Copy necessary subfolder from PhysicsRangeExtender to your KSP install's GameData folder
# clone PhysicsRange Extender locally
cd ~/Desktop
git clone [email protected]:jrodrigv/PhysicsRangeExtender.git

# copy the necessary game data for the mod into your KSP install
mkdir ~/Desktop/KSP_osx/GameData/PhysicsRangeExtender
cp -r ~/Desktop/PhysicsRangeExtender/PhysicsRangeExtender/Distribution/GameData/PhysicsRangeExtender/* ~/Desktop/KSP_osx/GameData/PhysicsRangeExtender/

Install kspdg

If you have not yet done so, clone this repository locally on your machine

git clone [email protected]:mit-ll/spacegym-kspdg.git

To install this package, run:

cd spacegym-kspdg
pip install -e . 
# if you plan to further develop the kspdg package, install the testing optional dependencies
# pip install -e .[testing]

For development of this package, we recommend using the conda environment defined in environment.yml. To create and activate this environment, run:

cd spacegym-kspdg
conda env create -f environment.yml
conda activate kspdg

⚠️ Troubleshooting

(mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e'))
  • The workaround for Mac users with M1 chipsets is described here. For Python 3.9, the workaround entails cloning pyerfa locally, checking out a specific version, and installing in the conda environment
# get pyerfa source code and switch to specific release of pyerfa
git clone --recursive https://github.com/liberfa/pyerfa/
cd pyerfa
git fetch origin
git checkout v2.0.0.1

# install specific version of pyerfa in conda environment
conda activate kspdg
pip install .

Install Luna Multiplayer (LMP)

Future Work

Verify Installation

NOTE: Because the KSPDG environments are inexorably linked to the KSP game engine, many of the library's unit/integration test can only be run when a particular game mission file has been loaded and running. This means that verifying installation and testing during code development is a bit more involved than just a single pytest call

Serverless Tests: Quick test to run without KSP game engine running nor kRPC server connection

cd spacegym-kspdg
conda activate kspdg
pytest tests/serverless_tests/

KSP In-Game Tests: These tests require the KSP game engine to be running, the test-specific mission to be loaded, and a connection to the kRPC server

  1. Start KSP game application.
  2. Select Start Game > Play Missions > Community Created > pe1_i3 > Continue
  3. In kRPC dialog box click Add server. Select Show advanced settings and select Auto-accept new clients. Then select Start Server
  4. In a bash terminal:
cd spacegym-kspdg
conda activate kspdg
pytest tests/ksp_ingame_tests/test_pe1_i3.py

# for additional tests, load a different mission in KSP: 
# ESC > Quit to Main Menu > Exit to Main Menu > Play Missions > `lbg1_i2` > Continue
pytest tests/ksp_ingame_tests/test_lbg1_i2.py

# ESC > Quit to Main Menu > Exit to Main Menu > Play Missions > `sb1_i5` > Continue
pytest tests/ksp_ingame_tests/test_sb1_i5.py
  1. You should see the KSP game reset and focus on a vehicle that then performs several orientation and propulsive maneuvers. The pytest command should then indicate the number of passed tests.

⚠️ Troubleshooting If you are using a Mac with an arm64 architecture (e.g. M1 chipset) and recieve an error like (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), please refer to instructions in the kspdg library installation section about installing pyerfa from source.


Example: Hello KSPDG

Here we provide a "hello world" example of implementing a pursuit agent in the simple Pursuit-Evade environment. This agent simply points at the pursuer and burns full throttle (Do you think that can interecept even a non-maneuvering evader? Try it and find out!)

  1. Start KSP game application.
  2. Select Start Game > Play Missions > Community Created > pe1_i3 > Continue
  3. In kRPC dialog box click Add server. Select Show advanced settings and select Auto-accept new clients. Then select Start Server
from kspdg.pe1.e1_envs import PE1_E1_I3_Env

# instantiate and reset the environment to populate game
env = PE1_E1_I3_Env()
env.reset()

# Environment automatically orients pursuer toward target
# therefore a niave pusuit policy to to simply burn at full
# thrust in pursuer's body-forward direction.
# Do this until the episode 
# (Do you think it can intercept even a non-maneuvering evader??)
is_done = False
act = {
    "burn_vec": [1.0, 0, 0, 1.0], # burn vector in x, y, z, and duration [s]
    "vec_type": 0,  # burn vector as throttle values (if =1, burn vector represents thrust in [N])
    "ref_frame": 0  # burn_vec expressed in agent vessel's right-handed body frame. 
                    # i.e. forward throttle, right throttle, down throttle, 
                    # Can also use rhcbci (1) and rhntw (2) ref frames
}
while not is_done:
    obs, rew, is_done, info = env.step(act)

# printout info to see evaluation metrics of episode
print(info)

# close the environments to cleanup any processes
env.close()

See scripts/example_hello_kspdg.py for more details


Example: Agent-Environment Runner

Even though KSPDG environments are Gym (Gymnasium) environments, they require special handling because they must manage server connections to the KSP game engine, as well as handle the non-blocking nature of KSPDG environments (i.e. simulation time continues during and between calls to env.step()) which requires parallel processes for the environment interactions and agent's policy computation.

Therefore we have defined a Agent-Environment Runner class that helps manage these interactions. Users can define agents by extending the BaseAgentEnvRunner and execute their agents as follows

  1. Start KSP game application.
  2. Select Start Game > Play Missions > Community Created > pe1_i3 > Continue
  3. In kRPC dialog box click Add server. Select Show advanced settings and select Auto-accept new clients. Then select Start Server
  4. In a terminal, run python scripts/example_agent_runner.py

See scripts/example_agent_runner.py for more details


Example: Agent-Environment Evaluator for SciTech Challenge

This example walks through how to evaluate agents for scoring purpose in the AIAA SciTech 2024 Challenge. Due to the GUI-based interface of KSP that requires manual interaction, there is not a straight-forward process for hosting a centralized evaluation server upon which participants can submit agents. Instead we have adopted a decentralized process where agents are evaluated locally on particapants' own computers. Participants will then upload their evaluation results to a centralized scoreboard where they will be authenticated and ranked against other participants.

⚠️ Honor System While we have taken some steps to prevent falsification of results, there is still potential for cheating. Therefore this competition works largely on the honor system.

If you think you are doing something inappropriate or unfair, you probably are.

We reserve the right to disqualify teams for unsporting behavior

The agent evaluation process uses a compiled python script located in evaluation/evaluate.cpython-312.pyc which takes a command-line argument pointing to a Agent-Env runner configuration file. The configuration file contains several pieces of information, inlcuding:

  • user name and pass key for authentication on the public leaderboard
  • The kspdg environment that is too be evaluated.
  • path to the user-defined agent to be evaluated, the agent's class name, any input arguments needed to instantiate the agent, and an agent nickname to distinguish it from other agents on the leaderboard that may be instantiated from the agent class (e.g. if the user runs the same agent multiple times or with different input arguements)

See `evaluation/configs/example_eval_cfg.yaml`` for an example of the config file

Here is a basic example for running an agent-environment evaluation. As with other examples, you begin by:

  1. Start KSP game application.
  2. Select Start Game > Play Missions > Community Created > pe1_i3 > Continue
  3. In kRPC dialog box click Add server. Select Show advanced settings and select Auto-accept new clients. Then select Start Server
conda activate kspdg # while it is not strictly necessary to use conda environments, it is encouraged for development and debugging purpose
cd evaluation # working directory is important due to relative path in cfg.yaml
python evaluate.cpython-312.pyc configs/example_eval_cfg.yaml   # assuming your conda env has python 3.12
                                                                # ohterwise call evaluate.cpython-39.pyc for python 3.9

This should output to a file in the results/ subdirectory with a name like kspdg_results_20231018_125336.txt. That file has JSON-formatted results that look like

{
    "agent_env_results": {
        "is_episode_done": true,
        "closest_approach": 235.2028250841451,
        "closest_approach_time": 200.80000000002892,
        "closest_approach_speed": 77.87944143686991,
        "closest_approach_pursuer_fuel_usage": 651.595703125,
        "pursuer_fuel_usage": 782.56884765625,
        "evader_fuel_usage": 0.0,
        "weighted_score": 983.3304428262093,
        "expected_deltav_at_final_time": 47.97165399572631
    },
    "user_id": "Team Baselines",
    "user_key": "b1bb536a-fe95-4dea-8564-4c8305ac963a",
    "kspdg_version": "0.0.23",
    "agent_name": "Naive-Ned",
    "scenario_environment": "PE1_E1_I3_V1"
}
1313515906

This results file will then be sent to the authentication and scoreboard server for official ranking in the KSPDG Challenge.

INSTRUCTIONS FOR UPLOADING RESULTS TO COMPETITION SCOREBOARD HAVE BEEN EMAILED TO PARTICIPANTS


Cautionary Notes

Here are some things you should NOT do as they will break/invalidate the proper functioning of the KSPDG environments

  • Do not manually switch focus between different spacecraft in the KSP game engine while evaluating an agent. This can cause silent errors with the scipted agent's policies
  • Do not save-over the mission save files. If you do so inadvertantly, you will need to re-download the orignal from this repo and copy these back into your local KSP game directory

References

Throughout the documentation and code comments we refer to aerospace literature such as "Vallado Chp 3" for brevity. However this assumes anyone reading this code knows that "Vallado" is short hand for David Vallado's "Fundamentals of Astrodynamics and Applications", which is an unfair assumption to make. Here we list some of our short-hand references

  • Vallado, David A. Fundamentals of astrodynamics and applications. Vol. 12. Springer Science & Business Media, 2001.
    • short hands: "Vallado"
    • There are multiple editions with slightly different section layouts. We try to specify which edition when referencing specific figures/sections but mostly pulling from 3rd or 4th edition
  • Bate, R. R., Mueller, D. D., & White, J. E. (1971). Fundamentals of astrodynamics. Fundamentals of astrodynamics.
    • short hands: "BMW", "Bate, Mueller, White"

Code Notation

Coordinate transforms are used throughout this code base. Without a rigorous notation it can become very difficult to determine the meaning of any particular variable. for example and ambiguous variable name like pursuer_pos seems to imply the position of a "pursuer" spacecraft, but position relative to what? Relative to a planet or relative to another spacecraft? Furthermore it says nothing of what coordinate frame that variable is expressed within. The pursuer position relative to the planet can be expressed in earth-centered inertial (ECI), perifocal, or even within another satellite's RSW frame (see Vallado, 3rd Edition, Sec 3.3 for frame descriptions). Each of these expressions lead to different numerical values for vector representations of the same physical vector

To make matters worse, kRPC---the crucial library that provides a python interface for controlling Kerbal Space Program---uses left-handed coordinate systems!! This will lead to much confusion if not pedantically handled.

To reduce the confusion we will strive to use the following notation for vector variables: w_x_y__z

  • w is a description of the vector. For example pos, vel may be using in the w position to represent position and velocity vectors, respectively
  • x_y is read as "x with respect to y". For example, if we want a vector for the position of satellite A with respect to satellite B we would have the partial variable name: pos_satA_satB
  • __z is read as "expressed in z". We need not only describe what the physical represents (i.e. w_x_y), we need to also described what coordinate frame the physcial vector is being expressed within; this is the purpose of __z. Therefore if we want a variable for the position of satellite A with respect to satellite B expressing in the right-handed earth-centered inertial coordinates we would write: pos_satA_satB__rheci

Here are some abbreviations and acronyms used throughout the code

  • lhntw = left-handed NTW coordinate frame (y-axis parallel to velocity vector, x-axis in orbital plane along---but not necessarily parallel to---radial in direction, z-axis perpendicular to complete left-handed system) based on kRPC's Vessel orbital_reference_frame
  • rhntw = right-handed NTW coordinate frame (y-axis parallel to velocity vector, x-axis in orbital plane along---but not necessarily parallel to---radial out direction, z-axis perpendicular to complete right-handed system) as described in Vallado 3rd ed. sec. 3.3.3
  • rhrsw = right-handed RSW (radial, along-track, normal) coordinate frame described in Vallado 3rd Edition, Sec 3.3.3
  • lhrsw = left-handed variant RSW coordinate frame (anti-radial, along-track, normal). Note that kRPC does not have a default lhrsw frame; the orbital_reference_frame is in fact an NTW frame
  • rhcbci = right-handed celestial-body-centered inertial coordinate frame. This is a right-handed version of kRPC's Celestial Body non_rotating_reference_frame. In the real-world this would be approximately equivalent to earth centered inertial (ECI)) coords (see Vallado 3rd ed, sec 3.3.2 on Geocentric Equitorial Coordinate System IJK) except in kerbal you aren't necessarily orbiting the earth and their is often no axial tilt to the celestial body
  • lhcbci = left-handed celestial-body-centered inertial coordinate frame based on kRPC's Celestial Body non_rotating_reference_frame
  • lhvbody = left-handel vessel-centered, vessel-fixed body coordinates that align with kRPC's Vessel.reference_frame. x-axis points out right side of vessel, y-axis points forward on vessel, z-axis points down. Vessel-fixed implies tha the reference frame rotates with the vessel. Note that v is often omitted or replaced with some identifier abbreviation of the particular vessel; e.g. lhpbody could be left-handed pursuer vessel body coords
  • rhvbody = right-handed vessel-centered, vessel-fixed body coordinates. x-axis points out forward of vessel, y-axis points out right side on vessel, z-axis points down

spacegym-kspdg's People

Contributors

rallen10 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spacegym-kspdg's Issues

Duplicate Scenario Listings On Leaderboard

In the drop down menu to select scenarios, duplicates of the scenario exist (e.g. two separate PE1_E3_I3_V1 options), each of which contains different set of results. These are supposed to combined into a single entry

[Failed test] test_pursuit_v20220516

Testing failures

When executing the pursuit-evasion test to verify the installation of everything, code errors were thrown.

Pursuit evasion error

As the following image shows, both tests fail because of TypeError: Can't instantiate abstract class PursuitEnvV20220516 with abstract method bot_policy.

Trazability

When following the error, bot_policy is an abstract method from PursuitEnvV20220516 class. I haven't found why this error is thrown since the function bot_policy is not called nor defined elsewhere, on the current scope which I think the error is located in these files src/kspdg/pe20220516/pursuit_v20220516.py, src/kpsdg/base_env.py and tests/ksdp_ingame_tests/test_pursuit_v20220516.py.

When commenting the function bot_policy the test is able to connect to the game, thus when selecting the mission and running the test a new error is thrown regarding self.logger from base_env.py. For both tests the error is the same.

================================================= test session starts =================================================
platform win32 -- Python 3.11.6, pytest-7.4.3, pluggy-1.3.0
rootdir: C:\Users\Bl1tty\Documents\Uni\New folder\spacegym-kspdg
collected 2 items

tests\ksp_ingame_tests\test_pursuit_v20220516.py EE                                                              [100%]

======================================================= ERRORS ========================================================
__________________________________ ERROR at setup of test_convert_rhntw_to_rhpbody_0 __________________________________

    @pytest.fixture
    def pursuit_v20220516_env():
        '''setup and teardown of the PursuitEnvV20220516 object connected to kRPC server'''
>       env = PursuitEnvV20220516()

tests\ksp_ingame_tests\test_pursuit_v20220516.py:22:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\kspdg\pe20220516\pursuit_v20220516.py:103: in __init__
    self.reset()
src\kspdg\base_envs.py:61: in reset
    self._connect_and_load_on_reset()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <kspdg.pe20220516.pursuit_v20220516.PursuitEnvV20220516 object at 0x0000014BC88E21D0>

    def _connect_and_load_on_reset(self) -> None:
        """Connect to KRPC server and load mission save file
        """

        # remove prior connection if it exists
        if hasattr(self, 'conn'):
            self.close()

        # establish krpc connect to send remote commands
        self.conn = krpc.connect(name='kspdg_env')
>       self.logger.info("Connected to kRPC server")
E       AttributeError: 'PursuitEnvV20220516' object has no attribute 'logger'

src\kspdg\base_envs.py:91: AttributeError
________________________________ ERROR at setup of test_get_combined_rcs_properties_0 _________________________________

    @pytest.fixture
    def pursuit_v20220516_env():
        '''setup and teardown of the PursuitEnvV20220516 object connected to kRPC server'''
>       env = PursuitEnvV20220516()

tests\ksp_ingame_tests\test_pursuit_v20220516.py:22:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\kspdg\pe20220516\pursuit_v20220516.py:103: in __init__
    self.reset()
src\kspdg\base_envs.py:61: in reset
    self._connect_and_load_on_reset()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <kspdg.pe20220516.pursuit_v20220516.PursuitEnvV20220516 object at 0x0000014BC9EDD050>

    def _connect_and_load_on_reset(self) -> None:
        """Connect to KRPC server and load mission save file
        """

        # remove prior connection if it exists
        if hasattr(self, 'conn'):
            self.close()

        # establish krpc connect to send remote commands
        self.conn = krpc.connect(name='kspdg_env')
>       self.logger.info("Connected to kRPC server")
E       AttributeError: 'PursuitEnvV20220516' object has no attribute 'logger'

src\kspdg\base_envs.py:91: AttributeError
=============================================== short test summary info ===============================================
ERROR tests/ksp_ingame_tests/test_pursuit_v20220516.py::test_convert_rhntw_to_rhpbody_0 - AttributeError: 'PursuitEnvV20220516' object has no attribute 'logger'
ERROR tests/ksp_ingame_tests/test_pursuit_v20220516.py::test_get_combined_rcs_properties_0 - AttributeError: 'PursuitEnvV20220516' object has no attribute 'logger'
================================================== 2 errors in 3.13s ==================================================

So, the problem here is that the logger from the parent of PursuitEnvV20220516 which is KSPDGBaseEnv class, is not instantiated, in order to solve this error, add super().__init__() at the start of the constructor from PursuitEnvV20220516 class, thus instancing the object for KSPDGBaseEnv.

After writing this small fix and executing again the test, it is able to connect to the server and execute the different actions, nevertheless, both tests fail.

================================================= test session starts =================================================
platform win32 -- Python 3.11.6, pytest-7.4.3, pluggy-1.3.0
rootdir: C:\Users\Bl1tty\Documents\Uni\New folder\spacegym-kspdg
collected 2 items

tests\ksp_ingame_tests\test_pursuit_v20220516.py FF                                                              [100%]

====================================================== FAILURES =======================================================
___________________________________________ test_convert_rhntw_to_rhpbody_0 ___________________________________________

pursuit_v20220516_env = <kspdg.pe20220516.pursuit_v20220516.PursuitEnvV20220516 object at 0x0000025C40683450>

    def test_convert_rhntw_to_rhpbody_0(pursuit_v20220516_env):
        '''check along-track vec in right-hand NTW frame transforms to forward in right-hand pursuer body coords'''

        # rename for ease of use
        env = pursuit_v20220516_env
        env.conn.space_center.target_vessel = None
        env.vesPursue.control.rcs = False
        time.sleep(0.5)
        v_exp__rhpbody = [1, 0, 0]

        # vector pointing along track
        v__rhntw = [0, 1, 0]
        env.vesPursue.control.sas_mode = env.vesPursue.control.sas_mode.prograde
        time.sleep(0.5)   # give time to re-orient
        v__rhpbody = pursuit_v20220516_env.convert_rhntw_to_rhpbody(v__rhntw)
        assert np.allclose(v__rhpbody, v_exp__rhpbody, atol=1e-2)

        # vector pointing radial out
        v__rhntw = [1, 0, 0]
        env.vesPursue.control.sas_mode = env.vesPursue.control.sas_mode.radial
        time.sleep(2.0)   # give time to re-orient
        v__rhpbody = pursuit_v20220516_env.convert_rhntw_to_rhpbody(v__rhntw)
        assert np.allclose(v__rhpbody, v_exp__rhpbody, atol=1e-2)

        # vector pointing normal
        v__rhntw = [0, 0, 1]
        env.vesPursue.control.sas_mode = env.vesPursue.control.sas_mode.normal
        time.sleep(2.0)   # give time to re-orient
        v__rhpbody = pursuit_v20220516_env.convert_rhntw_to_rhpbody(v__rhntw)
        assert np.allclose(v__rhpbody, v_exp__rhpbody, atol=1e-2)

        # vector pointing retrograde
        v__rhntw = [0, -1, 0]
        env.vesPursue.control.sas_mode = env.vesPursue.control.sas_mode.retrograde
        time.sleep(2.0)   # give time to re-orient
        v__rhpbody = pursuit_v20220516_env.convert_rhntw_to_rhpbody(v__rhntw)
        assert np.allclose(v__rhpbody, v_exp__rhpbody, atol=1e-2)

        # vector pointing in-radial
        v__rhntw = [-1, 0, 0]
        env.vesPursue.control.sas_mode = env.vesPursue.control.sas_mode.anti_radial
        time.sleep(2.0)   # give time to re-orient
        v__rhpbody = pursuit_v20220516_env.convert_rhntw_to_rhpbody(v__rhntw)
>       assert np.allclose(v__rhpbody, v_exp__rhpbody, atol=1e-2)
E       assert False
E        +  where False = <function allclose at 0x0000025C3F235670>([0.9999407167113323, -0.010492435996298122, -0.002910644206096047], [1, 0, 0], atol=0.01)
E        +    where <function allclose at 0x0000025C3F235670> = np.allclose

tests\ksp_ingame_tests\test_pursuit_v20220516.py:69: AssertionError
------------------------------------------------ Captured stdout setup ------------------------------------------------
Changing active vehicle...
Activating stability assist...
Re-orienting Pursuer and Evader...
Activating reaction control systems...
------------------------------------------------ Captured stderr setup ------------------------------------------------
kspdg.base_envs - INFO - Connected to kRPC server
------------------------------------------------- Captured log setup --------------------------------------------------
INFO     kspdg.base_envs:base_envs.py:90 Connected to kRPC server
_________________________________________ test_get_combined_rcs_properties_0 __________________________________________
....
....
------------------------------------------------ Captured stdout call -------------------------------------------------
Pursuer detected! Executing evasive maneuvers
=============================================== short test summary info ===============================================
FAILED tests/ksp_ingame_tests/test_pursuit_v20220516.py::test_convert_rhntw_to_rhpbody_0 - assert False
FAILED tests/ksp_ingame_tests/test_pursuit_v20220516.py::test_get_combined_rcs_properties_0 - assert False
================================================= 2 failed in 42.23s ==================================================

Reproduce error (same as stated on README):

  1. Start KSP game
  2. Select Start Game > Play Missions > Community Created > > Continue
  3. In kRPC dialog box click Add server. Select Show advanced settings and select Auto-accept new clients. Then select Start Server
  4. Execute pytest tests/ksp_ingame_tests/test_pursuit_v20220516.py

pursuit_evasion_test

Remove poliastro requirement

Poliastro is recently archived and will not be maintained. Furthermore, using poliastro as a dependency effectively pins our python version to <3.12 because poliastro depends on astropy-helpers---which itself is deprecated and will not be maintained---which raises the error

ModuleNotFoundError: No module named 'imp'

while using python 3.12 because imp has been deprecated in 3.12

Currently poliastro is only used in utils for functions that are not essential to the kspdg library (e.g. a time of flight calculator used to compute a mostly-obsolete performance metric).

On top of this; poliastro is a dependency-heavy library; removing it as a dependency will make kspdg more flexible and less likely to get stuck in dependency hell.

Get info in example_agent?

Hi,

If I understand correctly, the evaluation is done with an AgentRunner class, like this:

if __name__ == "__main__":
    naive_agent = NaivePursuitAgent()    
    runner = AgentEnvRunner(
        agent=naive_agent, 
        env_cls=PE1_E1_I3_Env, 
        env_kwargs=None,
        runner_timeout=100,     # agent runner that will timeout after 100 seconds
        debug=True)
    runner.run()

And the Agent class defines the get_action method like this:

class KSPDGBaseAgent(ABC):
    @abstractmethod
    def get_action(self, observation):
        raise NotImplementedError("Must be implemented by child class")

Therefore, the agent can only access the observation space, but not the updated info of the environment nor the reward. However, in the hello_world example the agent is coded like this:

while not is_done:
    obs, rew, is_done, info = env.step(act)

So the call to step can return everything needed (obs, reward, finished, and info).

How can you get everything that you get in the format of the hello_world, but encapsuled under the interface of KSPDGBaseAgent.get_action?

Thank you!
Víctor

[Failer test] test_pe1_e1_i3.py

Testing failures

When executing the pursuit-evasion (pe1_e1_i3) the first test fails. A note, when selecting the mission, there are two "saves" but only one works (0h 0m on it). This may not be a problem, because maybe for testing there is one save and for the problem program there is another. Either way, it would be helpful to detail it.

saves image

Trazability

When loading the mission with 0h 0m, and executing the test via pytest tests/ksp_ingame_tests/test_pe1_e1_i3.py, the following error is thrown.

tests\ksp_ingame_tests\test_pe1_e1_i3.py F.......                                                                [100%]

====================================================== FAILURES =======================================================
________________________________________ test_observation_dict_list_convert_0 _________________________________________

pe1_e1_i3_env = <kspdg.pe1.e1_envs.PE1_E1_I3_Env object at 0x0000023F723D3810>

    def test_observation_dict_list_convert_0(pe1_e1_i3_env):
        '''check that converting between lists and dict to not alter observation'''
        # ~~ ARRANGE ~~
        env = pe1_e1_i3_env

        # collect current observation as list
        obs_list = env.get_observation()

        # ~~ ACT ~~
        # convert obs to dict
        obs_dict = env.observation_list_to_dict(obs_list)

        # convert obs back to list
        obs_list_new = env.observation_dict_to_list(obs_dict)

        # ~~ ASSERT ~~
        # check that all observations are equal
>       assert np.allclose(obs_list, obs_list_new)

tests\ksp_ingame_tests\test_pe1_e1_i3.py:43:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tfm_env\Lib\site-packages\numpy\core\numeric.py:2241: in allclose
    res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

a = [5.299999999999975, 6684.9755859375, 1199.992431640625, 707758.0091506173, -248150.0999515668, -0.0005483742130386832, ...]
b = [5.299999999999975, 6684.9755859375, 1199.992431640625, 707758.0091506173, -248150.0999515668, -0.0005483742130386832, ...]
rtol = 1e-05, atol = 1e-08, equal_nan = False

    @array_function_dispatch(_isclose_dispatcher)
    def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
        """
        Returns a boolean array where two arrays are element-wise equal within a
        tolerance.

        The tolerance values are positive, typically very small numbers.  The
        relative difference (`rtol` * abs(`b`)) and the absolute difference
        `atol` are added together to compare against the absolute difference
        between `a` and `b`.

        .. warning:: The default `atol` is not appropriate for comparing numbers
                     that are much smaller than one (see Notes).

        Parameters
        ----------
        a, b : array_like
            Input arrays to compare.
        rtol : float
            The relative tolerance parameter (see Notes).
        atol : float
            The absolute tolerance parameter (see Notes).
        equal_nan : bool
            Whether to compare NaN's as equal.  If True, NaN's in `a` will be
            considered equal to NaN's in `b` in the output array.

        Returns
        -------
        y : array_like
            Returns a boolean array of where `a` and `b` are equal within the
            given tolerance. If both `a` and `b` are scalars, returns a single
            boolean value.

        See Also
        --------
        allclose
        math.isclose

        Notes
        -----
        .. versionadded:: 1.7.0

        For finite values, isclose uses the following equation to test whether
        two floating point values are equivalent.

         absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`))

        Unlike the built-in `math.isclose`, the above equation is not symmetric
        in `a` and `b` -- it assumes `b` is the reference value -- so that
        `isclose(a, b)` might be different from `isclose(b, a)`. Furthermore,
        the default value of atol is not zero, and is used to determine what
        small values should be considered close to zero. The default value is
        appropriate for expected values of order unity: if the expected values
        are significantly smaller than one, it can result in false positives.
        `atol` should be carefully selected for the use case at hand. A zero value
        for `atol` will result in `False` if either `a` or `b` is zero.

        `isclose` is not defined for non-numeric data types.
        `bool` is considered a numeric data-type for this purpose.

        Examples
        --------
        >>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])
        array([ True, False])
        >>> np.isclose([1e10,1e-8], [1.00001e10,1e-9])
        array([ True, True])
        >>> np.isclose([1e10,1e-8], [1.0001e10,1e-9])
        array([False,  True])
        >>> np.isclose([1.0, np.nan], [1.0, np.nan])
        array([ True, False])
        >>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True)
        array([ True, True])
        >>> np.isclose([1e-8, 1e-7], [0.0, 0.0])
        array([ True, False])
        >>> np.isclose([1e-100, 1e-7], [0.0, 0.0], atol=0.0)
        array([False, False])
        >>> np.isclose([1e-10, 1e-10], [1e-20, 0.0])
        array([ True,  True])
        >>> np.isclose([1e-10, 1e-10], [1e-20, 0.999999e-10], atol=0.0)
        array([False,  True])
        """
        def within_tol(x, y, atol, rtol):
            with errstate(invalid='ignore'), _no_nep50_warning():
                return less_equal(abs(x-y), atol + rtol * abs(y))

        x = asanyarray(a)
        y = asanyarray(b)

        # Make sure y is an inexact type to avoid bad behavior on abs(MIN_INT).
        # This will cause casting of x later. Also, make sure to allow subclasses
        # (e.g., for numpy.ma).
        # NOTE: We explicitly allow timedelta, which used to work. This could
        #       possibly be deprecated. See also gh-18286.
        #       timedelta works if `atol` is an integer or also a timedelta.
        #       Although, the default tolerances are unlikely to be useful
        if y.dtype.kind != "m":
            dt = multiarray.result_type(y, 1.)
            y = asanyarray(y, dtype=dt)

>       xfin = isfinite(x)
E       TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

tfm_env\Lib\site-packages\numpy\core\numeric.py:2348: TypeError
------------------------------------------------ Captured stderr setup ------------------------------------------------
kspdg.base_envs - INFO - Connected to kRPC server
kspdg.base_envs - INFO - Changing active vehicle...
kspdg.base_envs - INFO - Activating Pursuer SAS, RCS and orienting to Evader...
------------------------------------------------- Captured log setup --------------------------------------------------
INFO     kspdg.base_envs:base_envs.py:90 Connected to kRPC server
INFO     kspdg.base_envs:pe1_base.py:199 Changing active vehicle...
INFO     kspdg.base_envs:pe1_base.py:205 Activating Pursuer SAS, RCS and orienting to Evader...
=============================================== short test summary info ===============================================
FAILED tests/ksp_ingame_tests/test_pe1_e1_i3.py::test_observation_dict_list_convert_0 - TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any su...
======================================= 1 failed, 7 passed in 107.01s (0:01:47) =======================================

Data extraction mods

Following my question during the kick-off meeting about the possibility of using KSP mods to extract data that can potentially augment the observation space, these are the mods I was talking about:

  1. KSP Data Export: It extracts the following information:
Vessel
- Surface Velocity
- G-Force
- Acceleration
- Thrust
- TWR
- Mass
 
Position
- Altitude (Terrain)
- Altitude (Sea Level)
- Downrange Distance
- Latitude
- Longitude

Orbit
- Apoapsis
- Periapsis
- Inclination
- Orbital Velocity

Target
- Distance
- Target Velocity

Resources
- Stage DeltaV
- Vessel DeltaV

Science
- Air Pressure
  1. Kaptain's Log:
Events Recorded (not complete)

- Flight Log Recorded
- Part Died
- Launch
- Stage Separation
- Part Couple (dock)
- Vessel Modified
- Stage Activate
- Orbit Closed (enter orbit, not from a launch)
- Orbit Escaped (achieve escape velocity)
- Vessel Recovered
- Landed
- Crew Modified
- Progress Record
- Kerbal Passed Out From Gee Force
- Crew Killed
- Crew Transferred
- Dominant Body Change (SOI change)
- Flag Plant
- Crew On EVA
- Manual Entry

Data items being captured are:
- Vessel name (or Kerbal name)
- Universal Time
- UTC time
- Mission Time
- Situation
- Body (which SOI is the vessel in)
- Control level
- Altitude
- Speed
- Event type
- Notes (entered by player)
- Screenshot (both full size and thumbnail)
``

Best!
Víctor

Add Competition Rules

There are some competition rules that can be partially enforced in software but are also partially reliant on the "honor code" for participants. Therefore it is necessary to document these rules. For example:

  • Do not alter the evaluation metrics of your agents or falsify the reported metrics
  • Do not attempt to take control of another spacecraft within the KSP game engine (i.e. change active vessel) unless that is explicitly part of the environment's action space

File submission

Hi,

While trying to submit my own results, I found that an error didn't let me submit them. I figured out that the name that i was using for the agent used a whitespace and the evaluation makes some sort of hash that will detect if i change any data from the results. How do I proceed? Do i have to try to get the same results from my agent?

Thanks in advance.

Make score printout optional/configurable

in v0.5.1, a score printout to terminal was added. This can be useful during competitions but noisy during development; should make this an optional flag that sets whether or not score is printed.

Create unit test for Physics Range Extender (PRE)

The PRE mod is necessary for many environments to execute as intended. However, the environments won't necessarily error out if PRE is not installed, thus representing a "silent failure". Write a unit test that will fail if PRE is not installed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.