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

client/cpp/ProjectAirsimClientLib/

High-level client API for connecting to the server, loading worlds, and controlling robots.

client/cpp/ProjectAirSimMessageLib/

Message serialization helpers used by the client.

client/cpp/NNGI/

NNG-based transport wrapper.

client/cpp/example_user_apps/HelloDrone/

Minimal example application.

client/cpp/example_user_apps/HelloWheeledVehicle/

Native wheeled-vehicle control example.

client/cpp/example_user_apps/CppClientScenarios/

Scenario-oriented example application.

client/cpp/example_user_apps/UserScenarioTemplate/

Starting point for custom C++ user scenarios.

client/cpp/scripts/

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.sh on Linux and must be available on PATH on 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

client/cpp/build_linux/Debug/

Release

client/cpp/build_linux/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.