From ec16118f33b69cff3bfc6eb36db5fd026f61f384 Mon Sep 17 00:00:00 2001 From: Ben Kearns <35475+bkearns@users.noreply.github.com> Date: Tue, 5 May 2026 14:29:59 -0700 Subject: [PATCH] feat(sim): drivable Perseverance + auto-run + cmd_vel helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User reported nothing was moving. Two real causes plus a usability gap: 1. Perseverance was true — visible but unable to move. Restructure the model: - Body link with mass/inertia carries deck, RTG, mast, arm, and rocker rails as visuals. - Six wheel links (fl/ml/rl/fr/mr/rr) with collisions, inertials, and inner-pose-rotated cylinders so the link frame stays upright and the joint axis is clean. - Six revolute joints (axis 0 1 0 in the child frame) connect each wheel to body. - DiffDrive plugin (ignition-gazebo-diff-drive-system) lists all three left + three right joints, wheel_separation 2.40, wheel_radius 0.26, listens on /model/perseverance/cmd_vel. 2. Ignition Fortress opens paused by default. `ign gazebo` without `-r` requires the user to click Play before commands take effect. Add `-r` to the entrypoint so the world auto-runs. 3. ros_gz_bridge now wires /cmd_vel ↔ /model/perseverance/cmd_vel (and the matching odometry topics) for the moon.sdf world, so ROS-side controllers can drive the rover too. 4. New Make helpers — no ROS install needed on the host: make sim-drive-fwd LX=0.5 (default) m/s make sim-drive-back make sim-drive-left spin make sim-drive-right make sim-drive-stop Each shells `ign topic` inside the sim container. Verified locally: DiffDrive subscribed to /model/perseverance/cmd_vel; ros_gz_bridge created bidirectional bridges; world unpause via /world/moon/control returns data: true; cmd_vel publish accepted. --- Makefile | 33 +++ docker/sim/entrypoint.sh | 18 +- docker/sim/models/perseverance/model.sdf | 254 ++++++++++++++++------- 3 files changed, 224 insertions(+), 81 deletions(-) diff --git a/Makefile b/Makefile index 1829ed4..bfb9d60 100644 --- a/Makefile +++ b/Makefile @@ -229,6 +229,39 @@ sim-gui: ## Open the Gazebo GUI in the default browser (command -v xdg-open >/dev/null && xdg-open "$$URL") || \ echo "Open it manually." +# Drive helpers for the perseverance rover in the moon world. These +# publish straight to the in-container Ignition topic (no ROS install +# on the host required). Override LX / AZ to vary speed. +LX ?= 0.5 +AZ ?= 0.0 +SIM_CONTAINER ?= temporal-hack-lab-sim-1 +GZ_DRIVE_TOPIC ?= /model/perseverance/cmd_vel + +.PHONY: sim-drive-fwd +sim-drive-fwd: ## Drive the rover forward (LX m/s, override LX=) + @$(CONTAINER_ENGINE) exec $(SIM_CONTAINER) bash -c \ + 'ign topic -t $(GZ_DRIVE_TOPIC) -m ignition.msgs.Twist -p "linear: {x: $(LX)}"' + +.PHONY: sim-drive-back +sim-drive-back: ## Drive the rover backward + @$(CONTAINER_ENGINE) exec $(SIM_CONTAINER) bash -c \ + 'ign topic -t $(GZ_DRIVE_TOPIC) -m ignition.msgs.Twist -p "linear: {x: -$(LX)}"' + +.PHONY: sim-drive-left +sim-drive-left: ## Spin in place, left + @$(CONTAINER_ENGINE) exec $(SIM_CONTAINER) bash -c \ + 'ign topic -t $(GZ_DRIVE_TOPIC) -m ignition.msgs.Twist -p "angular: {z: 0.5}"' + +.PHONY: sim-drive-right +sim-drive-right: ## Spin in place, right + @$(CONTAINER_ENGINE) exec $(SIM_CONTAINER) bash -c \ + 'ign topic -t $(GZ_DRIVE_TOPIC) -m ignition.msgs.Twist -p "angular: {z: -0.5}"' + +.PHONY: sim-drive-stop +sim-drive-stop: ## Stop the rover + @$(CONTAINER_ENGINE) exec $(SIM_CONTAINER) bash -c \ + 'ign topic -t $(GZ_DRIVE_TOPIC) -m ignition.msgs.Twist -p "linear: {x: 0}, angular: {z: 0}"' + # ============================================================================= # CI cluster (smoke / pre-push parity) — alternate ports so it can run # alongside `make lab-up` on the same host. Used by .git-hooks/installer-smoke.sh diff --git a/docker/sim/entrypoint.sh b/docker/sim/entrypoint.sh index 3112a6b..a17efeb 100644 --- a/docker/sim/entrypoint.sh +++ b/docker/sim/entrypoint.sh @@ -60,7 +60,10 @@ else # OGRE2 will use Mesa's llvmpipe and render to the virtual fb. export LIBGL_ALWAYS_SOFTWARE=1 export OGRE2_RTSHADERSYSTEM_WRITE_SHADERS_TO_DISK=0 - ign gazebo -v 4 "$SIM_WORLD" & + # -r: start running (not paused). Without this Fortress opens + # paused and the user has to click Play before any movement + # commands have effect. + ign gazebo -r -v 4 "$SIM_WORLD" & PIDS+=($!) echo @@ -88,8 +91,19 @@ case "$SIM_WORLD" in -r /model/vehicle_blue/odometry:=/odom & PIDS+=($!) ;; + moon.sdf) + sleep 4 + echo "[sim] starting ros_gz_bridge: /cmd_vel ↔ /model/perseverance/cmd_vel" + ros2 run ros_gz_bridge parameter_bridge \ + /model/perseverance/cmd_vel@geometry_msgs/msg/Twist@ignition.msgs.Twist \ + /model/perseverance/odometry@nav_msgs/msg/Odometry@ignition.msgs.Odometry \ + --ros-args \ + -r /model/perseverance/cmd_vel:=/cmd_vel \ + -r /model/perseverance/odometry:=/odom & + PIDS+=($!) + ;; *) - echo "[sim] no ros_gz_bridge for world '$SIM_WORLD' (no vehicle_blue)" + echo "[sim] no ros_gz_bridge wired for world '$SIM_WORLD'" ;; esac diff --git a/docker/sim/models/perseverance/model.sdf b/docker/sim/models/perseverance/model.sdf index 35fa6ad..ddb92b0 100644 --- a/docker/sim/models/perseverance/model.sdf +++ b/docker/sim/models/perseverance/model.sdf @@ -1,28 +1,35 @@ - true - + 0 0 0.65 0 0 0 700 - 120140200 + + 120140200 + 000 + + + 1.20 1.40 0.40 + 1.20 1.40 0.40 @@ -36,12 +43,10 @@ 1.10 1.30 0.04 0.30 0.28 0.25 10.55 0.51 0.46 1 - - - - -0.85 0 0.85 0 1.5708 0 - + + + -0.85 0 0.20 0 1.5708 0 0.160.45 0.25 0.22 0.18 1 @@ -49,105 +54,196 @@ 0.25 0.25 0.25 1 - - - - 0.50 0 1.30 0 0 0 - + + + 0.50 0 0.65 0 0 0 0.051.20 0.30 0.28 0.25 10.55 0.51 0.46 1 - - - 0.50 0 1.95 0 0 0 - + + 0.50 0 1.30 0 0 0 0.32 0.20 0.18 0.20 0.20 0.22 10.30 0.30 0.32 1 - 0.18 0.06 0 0 1.5708 0 + 0.68 0.06 1.30 0 1.5708 0 0.0350.06 0.05 0.05 0.05 10.10 0.10 0.10 10.6 0.6 0.6 1 - 0.18 -0.06 0 0 1.5708 0 + 0.68 -0.06 1.30 0 1.5708 0 0.0350.06 0.05 0.05 0.05 10.10 0.10 0.10 10.6 0.6 0.6 1 - - - - 0.50 -0.65 0.85 0 0 -0.4 - + + + 0.50 -0.65 0.20 0 0 -0.4 0.050.55 0.30 0.28 0.25 10.55 0.51 0.46 1 - - - 0.78 -0.55 0.85 0 1.2 -0.4 - + + 0.78 -0.55 0.20 0 1.2 -0.4 0.0450.45 0.30 0.28 0.25 10.55 0.51 0.46 1 - - - 0.95 -0.40 0.45 0 0 0 - + + 0.95 -0.40 -0.20 0 0 0 0.18 0.18 0.16 0.20 0.20 0.22 10.30 0.30 0.32 1 + + + + 0 0.95 -0.15 0 0 0 + 2.30 0.06 0.06 + 0.30 0.28 0.25 10.55 0.51 0.46 1 + + + 0 -0.95 -0.15 0 0 0 + 2.30 0.06 0.06 + 0.30 0.28 0.25 10.55 0.51 0.46 1 + - + + + + - 1.10 1.20 0.26 1.5708 0 0 - 0.260.20 - 0.06 0.06 0.06 10.12 0.12 0.12 1 + 1.10 1.20 0.26 0 0 0 + 30 + 1.61.01.6 + + 0 0 0 1.5708 0 0 + 0.260.20 + + 0 0 0 1.5708 0 0 + 0.260.20 + 0.06 0.06 0.06 10.12 0.12 0.12 1 + - 0.00 1.20 0.26 1.5708 0 0 - 0.260.20 - 0.06 0.06 0.06 10.12 0.12 0.12 1 + 0.00 1.20 0.26 0 0 0 + 30 + 1.61.01.6 + + 0 0 0 1.5708 0 0 + 0.260.20 + + 0 0 0 1.5708 0 0 + 0.260.20 + 0.06 0.06 0.06 10.12 0.12 0.12 1 + - -1.10 1.20 0.26 1.5708 0 0 - 0.260.20 - 0.06 0.06 0.06 10.12 0.12 0.12 1 + -1.10 1.20 0.26 0 0 0 + 30 + 1.61.01.6 + + 0 0 0 1.5708 0 0 + 0.260.20 + + 0 0 0 1.5708 0 0 + 0.260.20 + 0.06 0.06 0.06 10.12 0.12 0.12 1 + - 1.10 -1.20 0.26 1.5708 0 0 - 0.260.20 - 0.06 0.06 0.06 10.12 0.12 0.12 1 + 1.10 -1.20 0.26 0 0 0 + 30 + 1.61.01.6 + + 0 0 0 1.5708 0 0 + 0.260.20 + + 0 0 0 1.5708 0 0 + 0.260.20 + 0.06 0.06 0.06 10.12 0.12 0.12 1 + - 0.00 -1.20 0.26 1.5708 0 0 - 0.260.20 - 0.06 0.06 0.06 10.12 0.12 0.12 1 - - - -1.10 -1.20 0.26 1.5708 0 0 - 0.260.20 - 0.06 0.06 0.06 10.12 0.12 0.12 1 - - - - - 0 0.95 0.50 0 0 0 - - 2.30 0.06 0.06 - 0.30 0.28 0.25 10.55 0.51 0.46 1 + 0.00 -1.20 0.26 0 0 0 + 30 + 1.61.01.6 + + 0 0 0 1.5708 0 0 + 0.260.20 + + 0 0 0 1.5708 0 0 + 0.260.20 + 0.06 0.06 0.06 10.12 0.12 0.12 1 - - 0 -0.95 0.50 0 0 0 - - 2.30 0.06 0.06 - 0.30 0.28 0.25 10.55 0.51 0.46 1 + + -1.10 -1.20 0.26 0 0 0 + 30 + 1.61.01.6 + + 0 0 0 1.5708 0 0 + 0.260.20 + + 0 0 0 1.5708 0 0 + 0.260.20 + 0.06 0.06 0.06 10.12 0.12 0.12 1 + + + + bodywheel_fl + 0 1 0 + + + bodywheel_ml + 0 1 0 + + + bodywheel_rl + 0 1 0 + + + bodywheel_fr + 0 1 0 + + + bodywheel_mr + 0 1 0 + + + bodywheel_rr + 0 1 0 + + + + + wheel_fl_joint + wheel_ml_joint + wheel_rl_joint + wheel_fr_joint + wheel_mr_joint + wheel_rr_joint + 2.40 + 0.26 + /model/perseverance/cmd_vel + 20 + perseverance/odom + perseverance/base_link + 2 + 3 +