Simulation

The sarcam_sim package provides a Gazebo Harmonic simulation that replaces the physical hardware for development and testing. It runs the real production nodes unchanged — only the hardware drivers are swapped for simulation equivalents.

Install

The sim environment is optional and separated from the default dev environment.

pixi install -e sim          # one-time: resolves and downloads Gazebo Harmonic + ros_gz
pixi run -e sim sim-build    # build sarcam_sim (re-run after SDF/plugin changes)

Start

# Headless (default — no Gazebo GUI, faster)
pixi run -e sim sim

# With Gazebo GUI
pixi run -e sim sim -- headless:=false

# Tune for slow CPUs
pixi run -e sim sim -- real_time_factor:=0.5 image_rate_hz:=5.0

All launch arguments with defaults:

Argument

Default

Description

headless

true

Run Gazebo without GUI

real_time_factor

1.0

Physics speed (<1.0 for slow CPUs)

image_rate_hz

10.0

Camera publish rate

state_publish_rate_hz

20.0

Gimbal encoder feedback rate

wave_freq_hz

0.2

Ship wave oscillation frequency

wave_roll_amp_deg

2.0

Roll wave amplitude

wave_pitch_amp_deg

1.0

Pitch wave amplitude

enable_ui

true

Launch sarcam_ui windows

enable_detector

true

Launch sarcam_detector

Use

Verify it is running

# Camera images at ~10 Hz
ros2 topic hz /rgb/image_raw
ros2 topic hz /thermal/image_raw

# GPS fix near 54°N 8°E
ros2 topic echo /fix --once

# Gimbal encoder (x=zoom, y=tilt_rad, z=pan_rad)
ros2 topic echo /sarcam_onvif/encoder --once

# AIS raw sentences
ros2 topic echo /nmea/raw --once

Control the gimbal

The sim accepts the same ONVIF move topics as the real hardware.

# Absolute move (x=zoom, y=tilt_rad, z=pan_rad)
ros2 topic pub /sarcam_onvif/absolute_move geometry_msgs/msg/Vector3Stamped \
  "{vector: {x: 1.0, y: -0.3, z: 1.5708}}" --once

# Continuous move (x=zoom_vel, y=tilt_deg/s, z=pan_deg/s) — send zeros to stop
ros2 topic pub /sarcam_onvif/continuous_move geometry_msgs/msg/Vector3Stamped \
  "{vector: {x: 0.0, y: 0.0, z: 10.0}}"

The gamepad / virtual gamepad node (sarcam_control) starts automatically and uses the same control path.

Scene

The world is centred at 54.0°N 8.0°E (North Sea). Four target vessels are placed at fixed initial positions and move kinematically at their configured speed and course:

Name

Colour

MMSI

AIS

target_0

Red

123456789

yes

target_1

Blue

987654321

yes

target_2

Green

555000111

yes

target_3

Yellow

000000000

no (SAR)

Positions and movement parameters are in src/sarcam_sim/config/sim_world.yaml (gz_east_m, gz_north_m, course_deg, speed_kn).

How the simulation interfaces with production code

The sim replaces exactly three hardware-facing nodes. Every other node in the pipeline runs unmodified.

Replaced by sim:

Real hardware node

Sim equivalent

hopewish_node

sim_gimbal_node

gscam_node × 2 (RGB + thermal)

Gazebo cameras → sim_zoom_node

NMEA multiplexer (kplex)

sim_nmea_node

Production nodes running unchanged: hopewish_camera_info_node × 2, onvif_tf_publisher, nmea-process-all (socket driver, decoder, AIS-to-TF), ship_config_server, sarcam_detector × 2, sarcam_ui × 2, sarcam_control.

Topic / data flow

graph LR subgraph Gazebo[Gazebo Harmonic gz-sim8] GZ_RGB[RGB camera sensor] GZ_TH[Thermal camera sensor] GZ_PAN[pan_joint / JPC] GZ_TILT[tilt_joint / JPC] end subgraph sarcam_sim[sarcam_sim simulation drivers] ST[sim_targets_node\nkinematic GPS] SN[sim_nmea_node\nGGA/RMC/HDT/XDR/AIVDM] SZ[sim_zoom_node\ncrop+resize, AGC] SG[sim_gimbal_node\nencoder, camera_info, wave] end subgraph production[Production nodes unchanged] CTRL[sarcam_control] TF[onvif_tf_publisher] CI[hopewish_camera_info_node x2] NMEA[nmea-process-all\nsocket driver, decoder, ais_to_aistf] DET[sarcam_detector x2] UI[sarcam_ui x2] end GZ_RGB -->|sim/rgb/image_raw| SZ GZ_TH -->|sim/thermal/image_raw| SZ SZ -->|rgb+thermal image_raw| DET SZ -->|rgb+thermal image_raw| UI GZ_PAN -.->|joint state| SG GZ_TILT -.->|joint state| SG SG -.->|cmd_pos| GZ_PAN SG -.->|cmd_pos| GZ_TILT SG -->|encoder, heading, imu| TF SG -->|encoder| UI SG -->|rgb+thermal camera_info_raw| CI CI -->|rgb+thermal camera_info| DET CI -->|rgb+thermal camera_info| UI CTRL -->|absolute_move, continuous_move| SG ST -->|targets/fix, heading_deg| SN SN -->|UDP 10111 GGA+RMC| NMEA SN -->|UDP 10112 + AIVDM| NMEA NMEA -->|/fix| UI NMEA -->|ais + /tf| UI NMEA -->|tf ais_MMSI| DET

Simulation dataflow