Project AirSim C++ Client
The Project AirSim C++ client is a native client library for connecting to a
running Project AirSim simulation server. It provides the same main programming
model as the Python client–a Client, a World, and robot-specific objects
such as Drone–for applications that need a C++17 interface.
The C++ client source is in client/cpp/.
Client layout
The main C++ client components are:
Path |
Purpose |
|---|---|
|
High-level client API for connecting to the server, loading worlds, and controlling robots. |
|
Message serialization helpers used by the client. |
|
NNG-based transport wrapper. |
|
Minimal example application. |
|
Native wheeled-vehicle control example. |
|
Scenario-oriented example application. |
|
Starting point for custom C++ user scenarios. |
|
Linux helper scripts for building and running scenario examples. |
The public API headers are under:
client/cpp/ProjectAirsimClientLib/Include/ProjectAirsimClient/
Most applications should include the aggregate header:
#include <ProjectAirsimClient/ProjectAirsimClient.h>
All public client types are in the microsoft::projectairsim::client
namespace. The examples commonly use this alias:
namespace pasc = microsoft::projectairsim::client;
Prerequisites
To build the C++ client, install:
CMake 3.20 or newer
A C++17 compiler
Ninja when using the repository build wrapper. It is installed by
setup_linux_dev_tools.shon Linux and must be available onPATHon Windows.The MSVC C++ toolchain from Visual Studio 2022 Build Tools on Windows. The Visual Studio IDE is not required.
The Linux CMake build fetches third-party dependencies such as NNG,
nlohmann-json, and msgpack on first configure. Eigen3 is used from the system
when available, or fetched automatically.
Building on Linux
From the repository root, build the C++ client with:
./build_cpp_client.sh debug
./build_cpp_client.sh release
# Build and run the mocked unit tests (no simulator required)
./build_cpp_client.sh debug --tests
Build outputs are placed under:
Build |
Output directory |
|---|---|
Debug |
|
Release |
|
The main static libraries are generated in the selected build directory:
libProjectAirsimClient.a
libProjectAirSimMessageLib.a
libNNGI.a
Example executables are generated in the same directory, including:
hello_drone
hello_wheeled_vehicle
cpp_client_scenarios
user_scenario_template
You can also build the client manually with CMake:
cmake -S client/cpp -B client/cpp/build_linux/Debug -DCMAKE_BUILD_TYPE=Debug
cmake --build client/cpp/build_linux/Debug -j$(nproc)
Building on Windows
From a Windows command prompt, use the repository build wrapper:
build_cpp_client.cmd debug
build_cpp_client.cmd release
build_cpp_client.cmd debug --tests
Build artifacts are placed under:
client\cpp\build_windows\Debug\
client\cpp\build_windows\Release\
The client links statically; no client DLL directory needs to be added to
PATH for hello_drone.exe.
Running HelloDrone
Start a Project AirSim simulation environment first, either from Unreal Editor with the Project AirSim plugin or from a packaged environment such as Blocks.
The hello_drone example connects to the simulation server, loads
scene_basic_drone.jsonc, arms Drone1, takes off, moves up, lands, and
disconnects.
On Linux:
./client/cpp/build_linux/Debug/hello_drone \
--simhost 127.0.0.1 \
--simconfig client/python/example_user_scripts/sim_config
On Windows:
client\cpp\build_windows\Debug\hello_drone.exe ^
--simhost 127.0.0.1 ^
--simconfig client\python\example_user_scripts\sim_config
The --simconfig directory must contain the scene file and related robot
configuration files. The repository includes ready-to-run examples in:
client/python/example_user_scripts/sim_config/
Running HelloWheeledVehicle
With the Unreal simulator running, build and run the native wheeled-vehicle example from the repository root:
cmake --build client/cpp/build_linux/Debug --target hello_wheeled_vehicle -j$(nproc)
./client/cpp/build_linux/Debug/hello_wheeled_vehicle
The example loads scene_wheeled_vehicle.jsonc and controls the configured
AWheeledVehiclePawn through WheeledVehicle::SetThrottle, SetSteering,
and SetBrakes. Each method returns a Status and writes whether the control
was accepted to its boolean output argument. WheeledVehicle does not expose
SetParameter.
The example reports failure if it cannot confirm at least 1 m of horizontal motion; successful RPC responses alone do not count as successful driving.
world->Initialize(client) without a scene file attaches by discovering the
scene topic root and robot names from the existing topics. It does not reload
the scene or request its configuration. GetConfiguration() remains empty
when attaching this way; it is populated only when World loads a configuration
file. Reinitialize World to discover an externally loaded scene.
Creating a C++ application
For a custom Linux CMake application, build the client first and then link
against the generated libraries. The simplest in-repository workflow is to add a
new executable target to client/cpp/CMakeLists.txt, link it to
ProjectAirsimClient, and rebuild.
For example:
add_executable(my_drone_app
example_user_apps/MyDroneApp/MyDroneApp.cpp
)
target_link_libraries(my_drone_app
PRIVATE
ProjectAirsimClient
)
if(NOT WIN32)
target_link_libraries(my_drone_app PRIVATE Threads::Threads)
endif()
Then build the target:
cmake --build client/cpp/build_linux/Debug --target my_drone_app -j$(nproc)
For custom scenarios, start from:
client/cpp/example_user_apps/UserScenarioTemplate/UserScenarioTemplate.cpp
The helper script can build and run a scenario target from
client/cpp/build_local:
cmake -S client/cpp -B client/cpp/build_local -DCMAKE_BUILD_TYPE=Debug
./client/cpp/scripts/run_cpp_user_scenario.sh --target user_scenario_template
Minimal client code
The following shows the basic C++ client flow. See
client/cpp/example_user_apps/HelloDrone/HelloDrone.cpp for a complete example
with argument parsing and error handling.
#include <ProjectAirsimClient/ProjectAirsimClient.h>
#include <iostream>
#include <memory>
namespace pasc = microsoft::projectairsim::client;
int main() {
auto client = std::make_shared<pasc::Client>();
if (client->Connect("127.0.0.1") != pasc::Status::OK) {
return 1;
}
auto world = std::make_shared<pasc::World>();
if (world->Initialize(client,
"scene_basic_drone.jsonc",
"client/python/example_user_scripts/sim_config",
2.0f) != pasc::Status::OK) {
return 1;
}
auto drone = std::make_shared<pasc::Drone>();
if (drone->Initialize(client, world, "Drone1") != pasc::Status::OK) {
return 1;
}
bool ok = false;
drone->EnableAPIControl(&ok);
drone->Arm(&ok);
drone->TakeoffAsync().Wait();
drone->MoveByVelocityAsync(0.0f, 0.0f, -1.0f, 4.0).Wait();
drone->LandAsync().Wait();
drone->Disarm(&ok);
drone->DisableAPIControl(&ok);
client->Disconnect();
return 0;
}
Async operations
Movement APIs return AsyncResult. Call Wait() to block until the operation is
complete and retrieve its Status.
auto takeoff = drone->TakeoffAsync();
pasc::Status status = takeoff.Wait();
You can also poll for completion, but still call Wait() afterward to retrieve
the final status:
auto move = drone->MoveByVelocityAsync(0.0f, 0.0f, -1.0f, 4.0);
while (!move.FIsDone()) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
pasc::Status status = move.Wait();
More examples
Additional example applications are available under:
client/cpp/example_user_apps/
The scenario runner scripts under client/cpp/scripts/ demonstrate common
flight, sensor, rover, environment actor, lidar, radar, and battery workflows.
Copyright (C) Microsoft Corporation.
Copyright (C) 2025 IAMAI CONSULTING CORP
MIT License. All rights reserved.