Skip to content

Commit ece0751

Browse files
committed
Update AirSim launch instructions and add headless mode support
1 parent 3b594a8 commit ece0751

6 files changed

Lines changed: 69 additions & 73 deletions

File tree

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
PROJECT_NAME="airstack"
1212
# If you've run ./airstack.sh setup, then this will auto-generate from the git commit hash every time a change is made
1313
# to a Dockerfile or docker-compose.yaml file. Otherwise this can also be set explicitly to make a release version.
14-
VERSION="0.18.0-alpha.2"
14+
VERSION="0.18.0-alpha.3"
1515
# Choose "dev" or "prebuilt". "dev" is for mounted code that must be built live. "prebuilt" is for built ros_ws baked into the image
1616
DOCKER_IMAGE_BUILD_MODE="dev"
1717
# Where to push and pull images from. Can replace with your docker hub username if using docker hub.

docs/simulation/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ An open-source drone simulator built on Unreal Engine with native PX4 SITL integ
8686
- Depth-based obstacle avoidance testing (DROAN)
8787
- Environments from the Unreal Engine ecosystem
8888

89-
**Launch:** Set `SIM_IP=172.31.0.201` in `.env`, then `docker compose --profile ms-airsim --profile desktop up`
89+
**Launch:** `airstack up --env-file overrides/ms-airsim.env`
9090

9191
**Location:** `simulation/ms-airsim/`
9292

docs/simulation/ms-airsim/docker.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ The container runs `entrypoint.sh`, which:
6969
| `AUTOLAUNCH` | `true` | Auto-start on container launch |
7070
| `MS_AIRSIM_BINARY_PATH` | `/ms-airsim-env/Blocks.sh` | Path to UE4 binary inside container |
7171
| `MS_AIRSIM_ENV_DIR` | `../environments` | Host path to extracted UE4 environment |
72+
| `MS_AIRSIM_HEADLESS` | `false` | Run UE4 without a window (`-RenderOffScreen -nosound`) |
7273
| `NUM_ROBOTS` | `1` | Number of vehicles and PX4 SITL instances |
73-
| `SIM_IP` | *(set in `.env`)* | Must be `172.31.0.201` for Microsoft AirSim (legacy) |
74+
| `SIM_IP` | `172.31.0.200` | Simulator IP on `airstack_network` |
7475

7576
**Camera template variables** (override in `.env` to regenerate `settings.json`):
7677

@@ -88,9 +89,12 @@ The container runs `entrypoint.sh`, which:
8889
**Example overrides:**
8990

9091
```bash
91-
# Headless launch with two robots
92+
# Two robots
9293
NUM_ROBOTS=2 airstack up --profile ms-airsim
9394

95+
# Headless (no GUI, uses UE4's -RenderOffScreen)
96+
MS_AIRSIM_HEADLESS=true airstack up --profile ms-airsim
97+
9498
# Custom environment binary
9599
MS_AIRSIM_ENV_DIR=/data/airsim_envs MS_AIRSIM_BINARY_PATH=/ms-airsim-env/CityEnviron.sh airstack up --profile ms-airsim
96100
```
@@ -117,12 +121,9 @@ NUM_ROBOTS=2 python3 generate_settings.py
117121
**Network configuration:**
118122

119123
- **Network:** `airstack_network` (172.31.0.0/24)
120-
- **Fixed IP:** 172.31.0.201
124+
- **Fixed IP:** 172.31.0.200
121125
- **Purpose:** Communicate with robot containers via ROS 2 DDS and MAVLink UDP
122126

123-
!!! note
124-
Microsoft AirSim (legacy) uses `172.31.0.201` (Isaac Sim uses `172.31.0.200`). Only one simulator should be active at a time. Set `SIM_IP=172.31.0.201` in `.env` when using Microsoft AirSim (legacy).
125-
126127
**Port usage:**
127128

128129
| Port | Protocol | Purpose |
@@ -312,15 +313,15 @@ AIRSIM_CAM_FOV=120 airstack up --profile ms-airsim
312313

313314
**MAVROS won't connect (robot container):**
314315

315-
- Verify `SIM_IP=172.31.0.201` is set in `.env`
316+
- Verify `SIM_IP=172.31.0.200` is set in `.env`
316317
- Ensure PX4 SITL has started (look for `[mavlink]` output in the PX4 tmux window)
317318
- Check MAVLink ports match: offboard `24541+i`, onboard `24581+i`
318319

319320
**No depth images on ROS 2 topics:**
320321

321322
- Verify the camera names in `settings.json` match those in `bridge.yaml`
322323
- Check bridge node output for connection errors (tmux bridge window)
323-
- Echo the topic: `ros2 topic echo /robot_1/sensors/front_camera/depth --once`
324+
- Echo the topic: `ros2 topic echo /robot_1/sensors/front_stereo/depth --once`
324325

325326
**ROS 2 topics not visible from robot container:**
326327

docs/simulation/ms-airsim/index.md

Lines changed: 50 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ To build the images first:
4343
airstack image-build --profile ms-airsim
4444
```
4545

46-
The container runs two tmux windows:
46+
The container runs `1 + 2*NUM_ROBOTS` tmux windows:
4747
- **Window 0**: AirSim binary (Unreal Engine rendering)
48-
- **Window 1**: ROS 2 bridge node (depth + camera_info publisher)
48+
- **Windows 1..N**: one PX4 SITL instance per robot
49+
- **Windows N+1..2N**: one ROS 2 bridge node per robot (depth + stereo RGB + camera_info)
4950

5051
To attach to the tmux session:
5152

@@ -61,31 +62,29 @@ A video is below:
6162
## Architecture
6263

6364
```
64-
┌──────────────────────┐ ┌──────────────────────┐
65-
│ MS-AirSim Container │ │ Robot Container │
66-
│ (172.31.0.201) │ │ │
67-
│ │ │ │
68-
│ AirSim Binary │ │ MAVROS ◄──── MAVLink UDP ────► PX4 SITL
69-
│ │ │ │ │ │
70-
│ ▼ │ │ ▼ │
71-
│ PX4 SITL │ │ Interface Layer │
72-
│ (TCP lockstep) │ │ │ │
73-
│ │ │ ▼ │
74-
│ Bridge Node ────────ROS 2 DDS────► Perception │
75-
│ (depth + │ │ │ │
76-
│ camera_info) │ │ ▼ │
77-
│ │ │ DROAN (disparity │
78-
│ │ │ expansion + planner)│
79-
└──────────────────────┘ └──────────────────────┘
80-
airstack_network (172.31.0.0/24)
65+
┌────────────────────────────────┐ ┌──────────────────────┐
66+
│ MS-AirSim Container │ │ Robot Container │
67+
│ (172.31.0.200) │ │ │
68+
│ │ │ │
69+
│ AirSim Binary (UE4) │ │ MAVROS │
70+
│ ▲ │ │ │ ▲ │
71+
│ │ │ TCP 4560+i │ │ │ │
72+
│ │ ▼ (lockstep) │ │ │ │
73+
│ PX4 SITL ×N ─── MAVLink UDP ─┼─────┼─► 24540+i/24580+i │
74+
│ ▲ │ │ │ │
75+
│ │ │ │ ▼ │
76+
│ Bridge Node ×N ─── ROS 2 DDS─┼─────┼─► Perception → DROAN │
77+
│ (stereo RGB + depth + info) │ │ │
78+
└────────────────────────────────┘ └──────────────────────┘
79+
airstack_network (172.31.0.0/24)
8180
```
8281

8382
**Data flow:**
8483

85-
1. Microsoft AirSim (legacy) simulates physics and renders depth images
86-
2. PX4 SITL runs in lockstep with AirSim via TCP (port 4560)
87-
3. Robot container connects to PX4 via MAVROS (UDP 14540/14580)
88-
4. Bridge node publishes depth + camera_info to ROS 2 topics
84+
1. AirSim simulates physics and renders stereo RGB + depth for each vehicle
85+
2. N PX4 SITL instances run in lockstep with AirSim via TCP (port `4560+i`)
86+
3. MAVROS in the robot container connects to PX4 SITL via MAVLink UDP (offboard `24540+i`, onboard `24580+i`)
87+
4. Bridge nodes (one per robot) publish stereo RGB + depth + camera_info to ROS 2 topics
8988
5. `disparity_expansion` converts depth to disparity for DROAN
9089

9190
## Configuration
@@ -101,65 +100,55 @@ Key settings:
101100
| `SimMode` | `Multirotor` | Drone simulation |
102101
| `ClockType` | `SteppableClock` | Lockstep with PX4 |
103102
| `VehicleType` | `PX4Multirotor` | PX4 SITL vehicle |
104-
| `TcpPort` | `4560` | PX4 lockstep connection |
105-
| `ControlPortLocal` | `14540` | MAVLink offboard port |
106-
| `ControlPortRemote` | `14580` | MAVLink onboard port |
103+
| `TcpPort` | `4560 + i` | PX4 lockstep connection (per robot `i`) |
104+
| `ControlPortLocal` | `24540 + i` | AirSim MAVLink proxy local port (moved off `14540+i` so it doesn't intercept PX4 ↔ MAVROS traffic) |
105+
| `ControlPortRemote` | `24580 + i` | AirSim MAVLink proxy remote port |
107106

108-
### Camera
107+
`settings.json` is generated at container start from [`settings.json.j2`](https://github.com/.../simulation/ms-airsim/config/settings.json.j2) via [`generate_settings.py`](https://github.com/.../simulation/ms-airsim/config/generate_settings.py), which expands per-robot port offsets, spawn positions, and camera parameters.
109108

110-
The default configuration uses a single forward-facing depth camera:
109+
### Cameras
111110

112-
- Resolution: 480x300
113-
- FOV: 90 degrees
114-
- Position: 20cm forward, 10cm up from body center
111+
The default configuration is a forward-facing **stereo pair** (left + right) plus aligned depth:
115112

116-
To modify camera settings, edit `settings.json` under `Vehicles.drone1.Cameras.front_camera`.
113+
| Property | Default | `.env` override |
114+
|----------|---------|-----------------|
115+
| Resolution | 480×300 | `AIRSIM_CAM_WIDTH`, `AIRSIM_CAM_HEIGHT` |
116+
| FOV | 110° | `AIRSIM_CAM_FOV` |
117+
| Baseline (2 × Y offset) | 0.12 m | `AIRSIM_CAM_Y` |
118+
| Forward (X) offset | 0.4 m | `AIRSIM_CAM_X` |
119+
| Pitch || `AIRSIM_CAM_PITCH` |
120+
121+
Cameras are defined per vehicle in the generated `settings.json` under `Vehicles.drone<i>.Cameras`.
117122

118123
### Bridge node parameters
119124

120125
Located at `simulation/ms-airsim/ros_ws/src/ms_airsim_ros_bridge/config/bridge.yaml`:
121126

122127
| Parameter | Default | Description |
123128
|-----------|---------|-------------|
124-
| `ms_airsim_ip` | `127.0.0.1` | AirSim API address |
125-
| `camera_name` | `front_camera` | AirSim camera name |
126-
| `vehicle_name` | `drone1` | AirSim vehicle name |
127-
| `publish_rate` | `15.0` | Depth publish rate (Hz) |
128-
| `robot_name` | `robot_1` | ROS 2 topic namespace |
129+
| `ms_airsim_ip` | `127.0.0.1` | AirSim API address (same container, so localhost) |
130+
| `publish_rate` | `15.0` | Camera / depth publish rate (Hz) |
131+
| `robot_name` | `robot_1` | ROS 2 topic namespace (set per-instance by the entrypoint to `robot_<i>`) |
132+
| `clock_rate` | `50.0` | `/clock` publish rate (Hz) |
129133

130134
### Environment variables
131135

132136
| Variable | Default | Description |
133137
|----------|---------|-------------|
134-
| `SIM_IP` | `172.31.0.200` | Simulation container IP. Set to `172.31.0.201` for Microsoft AirSim (legacy) |
138+
| `SIM_IP` | `172.31.0.200` | Simulation container IP |
135139
| `MS_AIRSIM_ENV_DIR` | `simulation/ms-airsim/environments` | Host path to extracted AirSim environment |
136140
| `MS_AIRSIM_BINARY_PATH` | `/ms-airsim-env/LinuxNoEditor/Blocks.sh` | Path to binary inside container |
137141

138142
## Published ROS 2 Topics
139143

140144
| Topic | Type | Description |
141145
|-------|------|-------------|
142-
| `/{robot_name}/sensors/front_camera/depth` | `sensor_msgs/Image` | Depth image (32FC1, meters) |
143-
| `/{robot_name}/sensors/front_camera/camera_info` | `sensor_msgs/CameraInfo` | Camera intrinsics (P matrix) |
144-
145-
## Adding Stereo Cameras
146-
147-
To switch from depth-only to stereo (for full disparity-based DROAN), add a second camera to `settings.json`:
148-
149-
```json
150-
"Cameras": {
151-
"front_left": {
152-
"CaptureSettings": [{"ImageType": 0, "Width": 480, "Height": 300, "FOV_Degrees": 90}],
153-
"X": 0.2, "Y": -0.06, "Z": -0.1
154-
},
155-
"front_right": {
156-
"CaptureSettings": [{"ImageType": 0, "Width": 480, "Height": 300, "FOV_Degrees": 90}],
157-
"X": 0.2, "Y": 0.06, "Z": -0.1
158-
}
159-
}
160-
```
161-
162-
This creates a stereo pair with 12cm baseline (matching ZED cameras). The bridge node would need to be extended to publish rectified stereo images.
146+
| `/{robot_name}/sensors/front_stereo/left/image_rect` | `sensor_msgs/Image` | Left RGB image |
147+
| `/{robot_name}/sensors/front_stereo/left/camera_info` | `sensor_msgs/CameraInfo` | Left camera intrinsics |
148+
| `/{robot_name}/sensors/front_stereo/right/image_rect` | `sensor_msgs/Image` | Right RGB image |
149+
| `/{robot_name}/sensors/front_stereo/right/camera_info` | `sensor_msgs/CameraInfo` | Right camera intrinsics |
150+
| `/{robot_name}/sensors/front_stereo/depth` | `sensor_msgs/Image` | Depth image (32FC1, meters) |
151+
| `/clock` | `rosgraph_msgs/Clock` | Simulation clock from AirSim |
163152

164153
### Project status
165154

@@ -179,6 +168,6 @@ Microsoft archived AirSim. For a maintained successor, see [Project AirSim](http
179168

180169
**MAVROS won't connect:**
181170

182-
- Verify `SIM_IP=172.31.0.201` is set in `.env`
171+
- Verify `SIM_IP=172.31.0.200` is set in `.env` (default)
183172
- Ensure PX4 SITL has started (check AirSim console for MAVLink messages)
184-
- Check port configuration: offboard=14540, onboard=14580
173+
- Check port configuration: offboard=24540+i, onboard=24580+i

simulation/ms-airsim/docker/docker-compose.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ services:
2626
- NUM_ROBOTS=${NUM_ROBOTS:-1}
2727
- AUTOLAUNCH=${AUTOLAUNCH:-true}
2828
- MS_AIRSIM_BINARY_PATH=${MS_AIRSIM_BINARY_PATH:-/ms-airsim-env/Blocks.sh}
29+
- MS_AIRSIM_HEADLESS=${MS_AIRSIM_HEADLESS:-false}
2930
deploy:
3031
resources:
3132
reservations:

simulation/ms-airsim/docker/entrypoint.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ set -e
33

44
NUM_ROBOTS="${NUM_ROBOTS:-1}"
55
MS_AIRSIM_BINARY_PATH="${MS_AIRSIM_BINARY_PATH:-/ms-airsim-env/LinuxNoEditor/Blocks.sh}"
6+
MS_AIRSIM_HEADLESS="${MS_AIRSIM_HEADLESS:-false}"
67

78
# Generate settings.json from template
89
python3 /home/ms-airsim/Documents/AirSim/generate_settings.py
910

1011
# Start tmux session
1112
tmux new -d -s ms-airsim
1213

13-
# Launch Microsoft AirSim (legacy) UE4 binary
14-
tmux send-keys -t ms-airsim "sudo -u ms-airsim $MS_AIRSIM_BINARY_PATH" ENTER
14+
# Launch Microsoft AirSim (legacy) UE4 binary (optionally headless via -RenderOffScreen)
15+
UE4_FLAGS=""
16+
if [ "$MS_AIRSIM_HEADLESS" = "true" ]; then
17+
UE4_FLAGS="-RenderOffScreen -nosound"
18+
fi
19+
tmux send-keys -t ms-airsim "sudo -u ms-airsim $MS_AIRSIM_BINARY_PATH $UE4_FLAGS" ENTER
1520

1621
# Wait for AirSim API to be ready
1722
python3 -c "

0 commit comments

Comments
 (0)