Adding New APIs to AirSim#

Adding new APIs requires modifying the source code. Much of the changes are mechanical and required for various levels of abstractions that AirSim supports. The main files required to be modified are described below along with some commits and PRs for demonstration. Specific sections of the PRs or commits might be linked in some places, but it'll be helpful to have a look at the entire diff to get a better sense of the workflow. Also, don't hesitate in opening an issue or a draft PR also if unsure about how to go about making changes or to get feedback.

Implementing the API#

Before adding the wrapper code to call and handle the API, it needs to be implemented first. The exact files where this will occur varies depending on what it does. Few examples are given below which might help you in getting started.

Vehicle-based APIs#

moveByVelocityBodyFrameAsync API for velocity-based movement in the multirotor's X-Y frame.

The main implementation is done in MultirotorBaseApi.cpp, where most of the multirotor APIs are implemented.

In some cases, additional structures might be needed for storing data, getRotorStates API is a good example for this, here the RotorStates struct is defined in 2 places for conversion from RPC to internal code. It also requires modifications in AirLib as well as Unreal/Plugins for the implementation.

These APIs need to interact with the simulation environment itself, hence it's likely that it'll be implemented inside the Unreal/Plugins folder.

simSetWind API shows an example of modifying the physics behaviour and adding an API + settings field for the same. See the PR for details about the code.

RPC Wrappers#

The APIs use msgpack-rpc protocol over TCP/IP through rpclib developed by Tamás Szelei which allows you to use variety of programming languages including C++, C#, Python, Java etc. When AirSim starts, it opens port 41451 (this can be changed via settings) and listens for incoming request. The Python or C++ client code connects to this port and sends RPC calls using msgpack serialization format.

To add the RPC code to call the new API, follow the steps below. Follow the implementation of other APIs defined in the files.

  1. Add an RPC handler in the server which calls your implemented method in RpcLibServerBase.cpp. Vehicle-specific APIs are in their respective vehicle subfolder.

  2. Add the C++ client API method in RpcClientBase.cpp

  3. Add the Python client API method in client.py. If needed, add or modify a structure definition in types.py

Testing#

Testing is required to ensure that the API is working as expected. For this, as expected, you'll have to use the source-built AirSim and Blocks environment. Apart from this, if using the Python APIs, you'll have to use the airsim package from source rather than the PyPI package. Below are 2 ways described to go about using the package from source -

  1. Use setup_path.py. It will setup the path such that the local airsim module is used instead of the pip installed package. This is the method used in many of the scripts since the user doesn't need to do anything other than run the script. Place your example script in one of the folders inside PythonClient like multirotor, car, etc. You can also create one to keep things separate, and copy the setup_path.py file from another folder. Add import setup_path before import airsim in your files. Now the latest main API (or any branch currently checked out) will be used.

  2. Use a local project pip install. Regular install would create a copy of the current source and use it, whereas Editable install (pip install -e . from inside the PythonClient folder) would change the package whenever the Python API files are changed. Editable install has the benefit when working on several branches or API is not finalized.

It is recommended to use a virtual environment for dealing with Python packaging so as to not break any existing setup.

When opening a PR, make sure to follow the coding guidelines. Also add a docstring for the API in the Python files, and please include any example scripts and settings required in the script as well.