Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions multivehicle/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ RUN /opt/ros/jazzy/lib/mavros/install_geographiclib_datasets.sh
# Pinned protoc 33 baked offline to /opt/protoc (supports edition = "2024").
# Installed off the system path so it never shadows /usr/bin/protoc;
# setup_dashboard.sh wires it into the dashboard's third_party/protoc/.
ARG PROTOC_VERSION=33.0
# 35.x matches the RobotX_2026 upstream generation (7.35 gencode).
ARG PROTOC_VERSION=35.1
RUN <<EOF
arch="$(uname -m)"
case "${arch}" in
Expand All @@ -139,7 +140,7 @@ RUN pip3 install --no-cache-dir --break-system-packages \
'uvicorn[standard]' \
'pydantic' \
'pydantic-settings' \
'protobuf>=6.33,<8' \
'protobuf>=7.35,<8' \
'tmuxp'

# --------------------------------------------------------------------------- #
Expand Down Expand Up @@ -289,6 +290,8 @@ COPY --from=ardupilot-builder /root/auv/ardupilot/build/sitl/bin/ardusub /usr/lo
# mission_planner_2). Kept in `final` rather than `base` on purpose: touching this
# list must not invalidate the px4-builder / ardupilot-builder caches.
RUN apt-get update && apt-get install -y --no-install-recommends \
mosquitto \
mosquitto-clients \
python3-transforms3d \
ros-jazzy-navigation2 \
ros-jazzy-nav2-bringup \
Expand All @@ -299,16 +302,28 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

RUN pip3 install --no-cache-dir --break-system-packages mavsdk
# RoboCommand dev broker config (explicit listener; anonymous like upstream's
# RobotX_2026 reference broker). Note Debian's packaged mosquitto.conf sets
# `persistence true`, so retained messages survive broker restarts here —
# unlike upstream's compose broker.
COPY config/mosquitto-robocommand.conf /etc/mosquitto/conf.d/robocommand.conf

RUN pip3 install --no-cache-dir --break-system-packages \
mavsdk \
'paho-mqtt>=2.1,<3'

COPY scripts/setup_dashboard.sh /usr/local/bin/setup_dashboard.sh
RUN chmod +x /usr/local/bin/setup_dashboard.sh
RUN cat >> /root/.bashrc <<'EOF'

# bb_robotx_dashboard runtime env
export ROBOCOMMAND_HOST=localhost
export ROBOCOMMAND_PORT=9000
export ROBOCOMMAND_TEAM_ID=42
# bb_robotx_dashboard runtime env (RobotX 2026 RoboCommand over MQTT)
export MQTT_BROKER_HOST=localhost
export MQTT_BROKER_PORT=1883
export ROBOTX_TEAM_ID=RNRX
# JSON — pydantic-settings parses complex types as JSON, not CSV.
export ROBOTX_VEHICLE_IDS='["USV1","UUV1","UAV1"]'
export HEARTBEAT_PERIOD_S=1.0
export AUTO_ACK_COMMANDS=true
export DASHBOARD_LISTEN_HOST=0.0.0.0
export DASHBOARD_LISTEN_PORT=8080
export DASHBOARD_ADMIN_SECRET=bumblebee
Expand Down
5 changes: 5 additions & 0 deletions multivehicle/docker/config/mosquitto-robocommand.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# RoboCommand dev broker (RobotX 2026). Explicit listener so the broker is
# reachable beyond loopback fallback mode, matching upstream's
# RobotX_2026/mosquitto/mosquitto.conf (anonymous, no TLS).
listener 1883 0.0.0.0
allow_anonymous true
30 changes: 22 additions & 8 deletions multivehicle/docker/scripts/setup_dashboard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,18 @@ fi
did_work=0

# 1. Clone the upstream robocommand repo (provides the .proto source).
if [ ! -d "${PKG_DIR}/third_party/robocommand/proto" ]; then
echo "[setup_dashboard] cloning robocommand proto source..."
git clone https://github.com/MonkeScripts/robocommand \
"${PKG_DIR}/third_party/robocommand" || true
did_work=1
# RobotX_2026/proto is the guard: a pre-RobotX (RoboBoat-era) checkout has
# only a top-level proto/ and must be deleted, not cloned into.
RC_DIR="${PKG_DIR}/third_party/robocommand"
if [ ! -d "${RC_DIR}/RobotX_2026/proto" ]; then
if [ -d "${RC_DIR}" ]; then
echo "[setup_dashboard] ${RC_DIR} is a stale pre-RobotX checkout." >&2
echo "[setup_dashboard] delete it and re-run: rm -rf ${RC_DIR}" >&2
else
echo "[setup_dashboard] cloning robocommand proto source..."
git clone https://github.com/robonation/robocommand "${RC_DIR}" || true
did_work=1
fi
fi

# 2. Wire the image's pinned protoc 33 into third_party/protoc/ so
Expand All @@ -39,14 +46,21 @@ if [ ! -x "${PKG_DIR}/third_party/protoc/bin/protoc" ] \
ln -sf /opt/protoc/bin/protoc "${PKG_DIR}/third_party/protoc/bin/protoc"
fi

# 3. Generate the Python protobuf bindings if missing.
if [ -d "${PKG_DIR}/third_party/robocommand/proto" ] \
&& [ ! -f "${PKG_DIR}/bb_robotx_dashboard/proto/report_pb2.py" ]; then
# 3. Generate the Python protobuf bindings if missing. The sentinel is a
# RobotX-era module — keying on the old report_pb2.py would let a stale
# RoboBoat binding suppress regeneration forever.
if [ -d "${RC_DIR}/RobotX_2026/proto" ] \
&& [ ! -f "${PKG_DIR}/bb_robotx_dashboard/proto/robotx/rx_reports_pb2.py" ]; then
echo "[setup_dashboard] compiling proto bindings..."
( cd "${PKG_DIR}" && bash scripts/compile_protos.sh ) || true
did_work=1
fi

# 4. paho-mqtt 2.x fallback for containers built from a pre-MQTT image (the
# rebuilt image bakes it; apt's 1.x is not API-compatible).
python3 -c "import paho.mqtt" 2>/dev/null || \
pip3 install --break-system-packages --no-cache-dir 'paho-mqtt>=2.1,<3' || true

if [ ! -d "${PKG_DIR}/frontend/dist" ]; then
cat <<MSG
[setup_dashboard] dashboard tooling ready. Remaining manual steps:
Expand Down
15 changes: 11 additions & 4 deletions multivehicle/tmuxp/mvsim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# 2) bluerov — attach the ArduSub BlueROV2 to the running world
# 3) boat — spawn the BlueBoat USV into the running world
# 4) drone — uXRCE-DDS agent + PX4 SITL x500 + gz<->ROS bridge (-> /x500/odom)
# 5) dashboard — web backend (:8080) + sim-side LED/incident bridges
# 5) dashboard — MQTT broker (:1883) + web backend (:8080) + monitor + sim-side bridges
#
# WS_DIR=/root/HOST/my_ws tmuxp load .../mvsim.yaml

Expand Down Expand Up @@ -80,18 +80,25 @@ windows:
- cmd: ros2 launch multivehicle_sim uav_gz.launch.py model_name:=x500_mono_cam_1
enter: false

# 5. Dashboard — fake vehicle (top, RoboCommand TCP server on :9000 the backend
# connects to), web backend (middle, http://localhost:8080), and the sim-side
# 5. Dashboard — RoboCommand MQTT broker (:1883), fake per-vehicle telemetry
# (ROS 2 topics the backend relays to MQTT), web backend
# (http://localhost:8080), a raw-frame monitor, and the sim-side
# LED/incident bridges (bottom) tracking all three vehicles' /…/odom.
- window_name: dashboard
layout: even-vertical
panes:
- shell_command:
- cmd: ros2 run bb_robotx_dashboard fake_vehicle_publisher --port 9000
- cmd: mosquitto -c /etc/mosquitto/mosquitto.conf -v
enter: false
- shell_command:
- cmd: ros2 run bb_robotx_dashboard fake_vehicle_publisher
enter: false
- shell_command:
- cmd: ros2 launch bb_robotx_dashboard dashboard.launch.py
enter: false
- shell_command:
- cmd: ros2 run bb_robotx_dashboard mqtt_spy
enter: false
- shell_command:
- cmd: ros2 launch bb_robotx_dashboard robotx_2026_sim.launch.py bridges_pkg:=robotx_gz models_pkg:=bb_worlds auv_name:=bluerov auv_pose_topic:=/bluerov/odom asv_name:=blueboat asv_pose_topic:=/blueboat/odom uav_name:=x500 uav_pose_topic:=/x500/odom
enter: false
18 changes: 12 additions & 6 deletions multivehicle/tmuxp/mvsim_debug.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# 2) bluerov — BlueROV2 + ArduSub/MAVROS, then its square mission BT
# 3) boat — BlueBoat spawn + control stack + square mission
# 4) drone — XRCE agent + PX4 SITL x500 + gz bridge + offboard demo BT
# 5) dashboard — web backend (:8080) + sim-side LED/incident bridges
# 5) dashboard — MQTT broker (:1883) + web backend (:8080) + monitor + sim-side bridges
# 6) debug — free shell + Foxglove bridge
#
# Workspace dir defaults to /root/HOST/mvsim_ws and the PX4 SITL install root to
Expand Down Expand Up @@ -53,7 +53,7 @@ windows:
- cmd: ros2 launch multivehicle_sim bluerov.launch.py
enter: false
- shell_command:
- cmd: ros2 launch bluerov_tasks bluerov_square_bt.launch.py
- cmd: sleep 5 & ros2 launch bluerov_tasks bluerov_square_bt.launch.py
enter: false

# 3. BlueBoat
Expand All @@ -64,7 +64,7 @@ windows:
- cmd: ros2 launch multivehicle_sim boat.launch.py
enter: false
- shell_command:
- cmd: ros2 launch multivehicle_examples boat_control.launch.py use_mission:=true
- cmd: sleep 5 & ros2 launch multivehicle_examples boat_control.launch.py use_mission:=true
enter: false

# 4. PX4 x500 drone
Expand All @@ -81,19 +81,25 @@ windows:
- cmd: ros2 launch multivehicle_sim uav_gz.launch.py model_name:=x500_mono_cam_1
enter: false
- shell_command:
- cmd: ros2 launch multivehicle_examples px4_offboard.launch.py
- cmd: sleep 5 & ros2 launch multivehicle_examples px4_offboard.launch.py
enter: false

# 5. Dashboard
# 5. Dashboard — broker, fake ROS telemetry, backend, MQTT monitor, bridges
- window_name: dashboard
layout: even-vertical
panes:
- shell_command:
- cmd: ros2 run bb_robotx_dashboard fake_vehicle_publisher --port 9000
- cmd: mosquitto -c /etc/mosquitto/mosquitto.conf -v
enter: false
- shell_command:
- cmd: ros2 run bb_robotx_dashboard fake_vehicle_publisher
enter: false
- shell_command:
- cmd: ros2 launch bb_robotx_dashboard dashboard.launch.py
enter: false
- shell_command:
- cmd: ros2 run bb_robotx_dashboard mqtt_spy
enter: false
- shell_command:
- cmd: ros2 launch bb_robotx_dashboard robotx_2026_sim.launch.py bridges_pkg:=robotx_gz models_pkg:=bb_worlds auv_name:=bluerov auv_pose_topic:=/bluerov/odom asv_name:=blueboat asv_pose_topic:=/blueboat/odom uav_name:=x500 uav_pose_topic:=/x500/odom
enter: false
Expand Down