Project AirSim ROS2 C++ Bridge
Project AirSim provides a ROS2 C++ bridge package named
projectairsim_ros2_cpp. The package is located under:
ros/projectairsim_ros2_cpp
The bridge is an rclcpp node that connects to Project AirSim through the
Project AirSim C++ client API, discovers simulator topics, republishes supported
payloads as typed ROS2 messages, and exposes command services/actions.
Requirements
The bridge has been built and tested with ROS2 Humble. Source your ROS2 installation before building or running the node:
source /opt/ros/humble/setup.bash
The package depends on:
Dependency |
Used for |
|---|---|
|
ROS2 CMake package build |
|
Custom service/action generation |
|
ROS2 C++ node |
|
|
|
poses and path goals |
|
occupancy grid service responses |
|
simulation clock topic |
|
sensor topics |
|
topic info and raw JSON fallback topics |
|
TF broadcasting |
Build
From the repository root:
source /opt/ros/humble/setup.bash
cd ros
colcon build --packages-select projectairsim_ros2_cpp
source install/setup.bash
Test
The ROS2 C++ package includes C++ contract tests for the generated topics, services, and action interfaces.
source /opt/ros/humble/setup.bash
cd ros
colcon test --packages-select projectairsim_ros2_cpp
colcon test-result --all --verbose
Run
Start Project AirSim first. Then, from ros:
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 run projectairsim_ros2_cpp projectairsim_ros2_cpp_node --ros-args \
-p scene_config:=scene_drone_sensors.jsonc \
-p sim_config_path:=../client/python/example_user_scripts/sim_config
If Project AirSim is not reachable at 127.0.0.1, set address to the host
running the simulator:
ros2 run projectairsim_ros2_cpp projectairsim_ros2_cpp_node --ros-args \
-p address:=<projectairsim_host_ip> \
-p scene_config:=scene_drone_sensors.jsonc \
-p sim_config_path:=../client/python/example_user_scripts/sim_config
If a scene is already loaded and should not be changed by the bridge, omit
scene_config. In that mode the node connects to the existing simulator scene,
adopts the discovered scene topic root, and starts topic and clock publishing
when Project AirSim reports topic information.
Parameters
Parameter |
Default |
Description |
|---|---|---|
|
|
Project AirSim server address. Set this when the simulator runs on another host or network namespace. |
|
|
Project AirSim pub-sub topic port. |
|
|
Project AirSim service request port. |
|
empty |
Scene config file to load at startup. Relative names are resolved against |
|
|
Directory containing scene, robot, and environment config files. |
|
|
Delay after loading a scene before topic discovery. |
|
|
Native Project AirSim topic root to rewrite. |
|
|
ROS topic root used when publishing bridged topics. |
|
|
Publish unsupported Project AirSim topics as |
|
|
Broadcast TF transforms from |
|
|
Parent frame used for TF transforms. |
|
|
Periodic topic discovery interval. |
|
|
Periodic |
|
|
Vehicle used for single-drone services/actions. |
|
|
Root namespace for command services and actions. |
Topics
List ROS2 topics:
ros2 topic list -t
The bridge subscribes to native Project AirSim topics such as /Sim/... and republishes them under /ProjectAirsim/... by default.
Robot state topics use the vehicle name as frame_id; camera image and
camera-info topics use a unique sanitized camera frame so they can participate
in TF without colliding with the vehicle frame.
Implemented typed topic conversions:
Project AirSim topic suffix |
ROS2 topic suffix |
ROS2 topic type |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
camera topics |
same suffix |
|
|
|
|
The bridge also publishes:
Topic |
Type |
Description |
|---|---|---|
|
|
JSON list of Project AirSim topic paths from the first discovery pass after startup or scene load. |
|
|
Project AirSim simulation time from |
|
|
Vehicle and camera transforms when |
To echo a topic:
ros2 topic echo /ProjectAirsim/<scene_name>/robots/<vehicle_name>/actual_pose
If you want raw JSON fallback topics for unsupported Project AirSim topics:
ros2 run projectairsim_ros2_cpp projectairsim_ros2_cpp_node --ros-args \
-p publish_unmatched_as_json:=true
Services
List services:
ros2 service list -t
Single-vehicle services use the configured vehicle_name, default Drone1:
Service |
Type |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Global, group, and scene services:
Service |
Type |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Examples:
ros2 service call /projectairsim/Drone1/arm projectairsim_ros2_cpp/srv/Arm \
"{wait_on_last_task: true}"
ros2 service call /projectairsim/Drone1/takeoff projectairsim_ros2_cpp/srv/Takeoff \
"{wait_on_last_task: true}"
ros2 service call /projectairsim/Drone1/move_to_position projectairsim_ros2_cpp/srv/MoveToPosition \
"{x: 5.0, y: 0.0, z: -3.0, velocity: 2.0, timeout_sec: 10.0, drive_train_type: 0, yaw_is_rate: true, yaw: 0.0, lookahead: -1.0, adaptive_lookahead: 1.0, wait_on_last_task: true}"
ros2 service call /projectairsim/Drone1/land projectairsim_ros2_cpp/srv/Land \
"{wait_on_last_task: true}"
Reload a scene at runtime:
ros2 service call /projectairsim/load_scene projectairsim_ros2_cpp/srv/LoadScene \
'{scene_file: "scene_drone_sensors.jsonc", is_primary_client: true}'
Use is_primary_client: true when this bridge should ask Project AirSim to load
the scene. Use is_primary_client: false when another client has already loaded
the scene and this bridge should attach to it.
Create a voxel grid file:
ros2 service call /projectairsim/create_voxel_grid projectairsim_ros2_cpp/srv/CreateVoxelGrid \
'{position_x: 0.0, position_y: 0.0, position_z: -4.0, ncells_x: 20, ncells_y: 20, ncells_z: 10, resolution: 1.0, n_z_resolution: 10, output_file: "/tmp/projectairsim_voxel_grid.binvox"}'
Return a ROS2 occupancy grid. The 3D voxel grid is projected into a 2D
nav_msgs/OccupancyGrid; a cell is occupied if any voxel in its Z column is
occupied.
ros2 service call /projectairsim/occupancy_grid projectairsim_ros2_cpp/srv/OccupancyGrid \
"{position_x: 0.0, position_y: 0.0, position_z: -4.0, ncells_x: 20, ncells_y: 20, ncells_z: 10, res: 1.0, n_z_resolution: 10}"
Get simulation time in nanoseconds:
ros2 service call /projectairsim/get_clock projectairsim_ros2_cpp/srv/GetClock "{}"
Get the scene origin geo point:
ros2 service call /projectairsim/get_origin_geo_point projectairsim_ros2_cpp/srv/GetOriginGeoPoint "{}"
Call any Project AirSim C++ client request-backed API by method path and JSON parameters:
ros2 service call /projectairsim/request projectairsim_ros2_cpp/srv/RawRequest \
'{method: "/Sim/GetBuildCommitHash", json_parameters: "{}"}'
/projectairsim/request is a generic escape hatch for Project AirSim server
request paths. Prefer typed ROS2 services when one exists. For generic calls,
use a method path and JSON payload supported by the Project AirSim server.
Actions
The bridge provides a MoveOnPath action:
Action |
Type |
|---|---|
|
|
List actions:
ros2 action list -t
Send a path goal:
ros2 action send_goal /projectairsim/Drone1/move_on_path projectairsim_ros2_cpp/action/MoveOnPath \
"{path: [{pose: {position: {x: 5.0, y: 0.0, z: -3.0}, orientation: {w: 1.0}}}, {pose: {position: {x: 5.0, y: 5.0, z: -3.0}, orientation: {w: 1.0}}}], velocity: 2.0, timeout_sec: 20.0, lookahead: -1.0, adaptive_lookahead: 1.0, drive_train_type: 0, yaw_is_rate: true, yaw: 0.0, wait_on_last_task: true}"
Common Workflow
Use three terminals. Run the ROS2 commands from the repository root unless noted otherwise:
Start Project AirSim.
Start the bridge:
source /opt/ros/humble/setup.bash
cd ros
source install/setup.bash
ros2 run projectairsim_ros2_cpp projectairsim_ros2_cpp_node --ros-args \
-p scene_config:=scene_drone_sensors.jsonc \
-p sim_config_path:=../client/python/example_user_scripts/sim_config
Inspect and command from ROS2:
source /opt/ros/humble/setup.bash
cd ros
source install/setup.bash
ros2 topic list -t
ros2 service list -t
ros2 action list -t
Then call services such as arm, takeoff, move, and land.
Resolved Limitations And Remaining Gaps
The ROS2 C++ bridge provides typed ROS2 coverage for the high-priority areas below:
Area |
Status |
|---|---|
Radar typed messages |
Implemented as |
Camera info topics |
Implemented as |
TF broadcasting |
Implemented for vehicle pose and camera pose payloads; controlled by |
Segmentation and object material/texture services |
Implemented as typed ROS2 services. |
Remaining gaps are narrower typed wrappers for Project AirSim request paths that
currently require /projectairsim/request, plus richer typed conversions for
specialized sensor/status payloads that do not yet have dedicated ROS message
contracts.
Copyright (C) IAMAI CONSULTING CORP
MIT License. All rights reserved.