From cc907c3921b364ca5065d2a6613d186b55a22f42 Mon Sep 17 00:00:00 2001 From: monkescripts Date: Sun, 23 Aug 2026 01:09:35 +0800 Subject: [PATCH 1/4] =?UTF-8?q?docker:=20MQTT-era=20image=20=E2=80=94=20pr?= =?UTF-8?q?otoc=2035.1,=20protobuf>=3D7.35,=20paho-mqtt,=20mosquitto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit protoc bumped to 35.1 and the pip band to protobuf>=7.35,<8 so gencode and runtime sit in the same major (upstream RobotX_2026 generates with 7.35) — a deliberate base-stage change, accepting the full PX4+ArduSub rebuild for a clean slate. final stage gains paho-mqtt>=2.1 (apt ships 1.x, no VERSION2 callbacks) beside mavsdk, a mosquitto broker + clients, and an explicit-listener anonymous conf.d drop-in matching upstream's reference broker (note: Debian's mosquitto.conf sets persistence true, so retained messages survive restarts here, unlike upstream's compose broker). The baked env block swaps ROBOCOMMAND_* (TCP :9000, int team id) for MQTT_BROKER_*, string ROBOTX_TEAM_ID=RNRX, JSON ROBOTX_VEHICLE_IDS, heartbeat period and auto-ack. --- multivehicle/docker/Dockerfile | 29 ++++++++++++++----- .../docker/config/mosquitto-robocommand.conf | 5 ++++ 2 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 multivehicle/docker/config/mosquitto-robocommand.conf diff --git a/multivehicle/docker/Dockerfile b/multivehicle/docker/Dockerfile index ebd815d..790addb 100644 --- a/multivehicle/docker/Dockerfile +++ b/multivehicle/docker/Dockerfile @@ -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 <=6.33,<8' \ + 'protobuf>=7.35,<8' \ 'tmuxp' # --------------------------------------------------------------------------- # @@ -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 \ @@ -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 diff --git a/multivehicle/docker/config/mosquitto-robocommand.conf b/multivehicle/docker/config/mosquitto-robocommand.conf new file mode 100644 index 0000000..b55e3c0 --- /dev/null +++ b/multivehicle/docker/config/mosquitto-robocommand.conf @@ -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 From 843b9e0f2fe7d0df52f45897a25345ada84d4cd2 Mon Sep 17 00:00:00 2001 From: monkescripts Date: Sun, 23 Aug 2026 01:09:35 +0800 Subject: [PATCH 2/4] =?UTF-8?q?docker:=20setup=5Fdashboard.sh=20=E2=80=94?= =?UTF-8?q?=20robonation=20clone,=20RobotX=20sentinels,=20paho=20fallback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clone URL repointed from the stale MonkeScripts fork to robonation/robocommand, guarded on RobotX_2026/proto with an explicit delete-and-rerun message for pre-RobotX checkouts (cloning into a non-empty dir fails). The codegen sentinel moves from report_pb2.py — which every existing workspace already has, silently suppressing regeneration forever — to proto/robotx/rx_reports_pb2.py. A paho import check with pip fallback keeps containers from pre-MQTT images working while the image rebuilds. --- .../docker/scripts/setup_dashboard.sh | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/multivehicle/docker/scripts/setup_dashboard.sh b/multivehicle/docker/scripts/setup_dashboard.sh index c5c7562..1b86f44 100755 --- a/multivehicle/docker/scripts/setup_dashboard.sh +++ b/multivehicle/docker/scripts/setup_dashboard.sh @@ -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 @@ -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 < Date: Sun, 23 Aug 2026 01:09:35 +0800 Subject: [PATCH 3/4] =?UTF-8?q?tmuxp:=20dashboard=20window=20=E2=80=94=20b?= =?UTF-8?q?roker,=20fake=20ROS=20telemetry,=20MQTT=20monitor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pane 1's fake_vehicle_publisher --port 9000 (a TCP server that no longer exists) becomes: mosquitto in verbose mode, the rewritten ROS 2 fake telemetry publisher (no args), the web backend, a mosquitto_sub raw-frame monitor on robocommand/robotx/#, and the unchanged sim-side bridges. --- multivehicle/tmuxp/mvsim.yaml | 15 +++++++++++---- multivehicle/tmuxp/mvsim_debug.yaml | 12 +++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/multivehicle/tmuxp/mvsim.yaml b/multivehicle/tmuxp/mvsim.yaml index 5d190ea..9cdf328 100644 --- a/multivehicle/tmuxp/mvsim.yaml +++ b/multivehicle/tmuxp/mvsim.yaml @@ -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 @@ -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: mosquitto_sub -h localhost -t 'robocommand/robotx/#' -v + 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 diff --git a/multivehicle/tmuxp/mvsim_debug.yaml b/multivehicle/tmuxp/mvsim_debug.yaml index 779f397..e67d26a 100644 --- a/multivehicle/tmuxp/mvsim_debug.yaml +++ b/multivehicle/tmuxp/mvsim_debug.yaml @@ -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 @@ -84,16 +84,22 @@ windows: - cmd: 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: mosquitto_sub -h localhost -t 'robocommand/robotx/#' -v + 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 From 384906f4d2b8ecbaa7fc6b9ee6ffcbb342159800 Mon Sep 17 00:00:00 2001 From: monkescripts Date: Sun, 23 Aug 2026 15:02:22 +0800 Subject: [PATCH 4/4] Update tmuxp configurations for multivehicle examples: replace mosquitto_sub with mqtt_spy and add sleep delays for launch commands --- multivehicle/tmuxp/mvsim.yaml | 2 +- multivehicle/tmuxp/mvsim_debug.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/multivehicle/tmuxp/mvsim.yaml b/multivehicle/tmuxp/mvsim.yaml index 9cdf328..1494f1d 100644 --- a/multivehicle/tmuxp/mvsim.yaml +++ b/multivehicle/tmuxp/mvsim.yaml @@ -97,7 +97,7 @@ windows: - cmd: ros2 launch bb_robotx_dashboard dashboard.launch.py enter: false - shell_command: - - cmd: mosquitto_sub -h localhost -t 'robocommand/robotx/#' -v + - 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 diff --git a/multivehicle/tmuxp/mvsim_debug.yaml b/multivehicle/tmuxp/mvsim_debug.yaml index e67d26a..4369d38 100644 --- a/multivehicle/tmuxp/mvsim_debug.yaml +++ b/multivehicle/tmuxp/mvsim_debug.yaml @@ -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 @@ -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 @@ -81,7 +81,7 @@ 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 — broker, fake ROS telemetry, backend, MQTT monitor, bridges @@ -98,7 +98,7 @@ windows: - cmd: ros2 launch bb_robotx_dashboard dashboard.launch.py enter: false - shell_command: - - cmd: mosquitto_sub -h localhost -t 'robocommand/robotx/#' -v + - 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