Skip to content

fix(simulation): Gazebo Harmonic Name() API + SITL integration (Phases A–C + GUI)#49

Merged
macaris64 merged 4 commits into
masterfrom
fix/gz-harmonic-name-api
Apr 25, 2026
Merged

fix(simulation): Gazebo Harmonic Name() API + SITL integration (Phases A–C + GUI)#49
macaris64 merged 4 commits into
masterfrom
fix/gz-harmonic-name-api

Conversation

@macaris64

Copy link
Copy Markdown
Owner

Summary

  • fix: gz::sim::Model::Name(ecm) and World::Name(ecm) return std::string in Gazebo Harmonic (gz-sim8), not std::optional<std::string> — removes four invalid .value_or() calls that caused Docker build failures
  • feat(Phase A): Port all 4 Gazebo plugins from Classic (ModelPlugin, physics::ModelPtr, transport::NodePtr) to Harmonic ECM-based API (ISystemConfigure, ISystemPreUpdate/PostUpdate, JointVelocityCmd, ExternalWorldWrenchCmd); convert gazebo.Dockerfile to two-stage multi-stage build with compiled .so files
  • feat(Phase B): Wire ros_gz_bridge in the ROS 2 Docker image; add use_external_gz arg to sim.launch.py; set GZ_IP/GZ_PARTITION env vars in Compose for gz-transport cross-container peer discovery
  • feat(Phase C): New sim_adapter cFS app — receives CCSDS SPPs on UDP 5700, validates APID (0x500–0x57F) and CRC-16/CCITT-FALSE, routes to Software Bus; guarded by #ifndef CFS_FLIGHT_BUILD; 6/6 CMocka tests passing
  • feat(GUI): make run opens Gazebo 3D window on a desktop (X11 forwarded via /tmp/.X11-unix; Mesa llvmpipe software renderer — no GPU required); falls back to headless when $DISPLAY is unset

Test plan

  • ctest --test-dir build --output-on-failure — all 14 unit tests pass (includes 6 new sim_adapter tests)
  • cmake -B build_flight -DCFS_FLIGHT_BUILD=1 && cmake --build build_flight && nm build_flight/apps/sim_adapter/CMakeFiles/sim_adapter.dir/fsw/src/sim_adapter.c.o | grep SIM_ADAPTER || echo "GUARD OK" — no sim_adapter symbols in flight build
  • docker compose build gazebo — Dockerfile compiles all 4 plugins without error
  • make run on a Linux desktop with $DISPLAY set — Gazebo window opens; make run on headless CI — no error, Gazebo runs server-only
  • docker exec sakura_ros2 ros2 node list/gz_bridge present after stack starts

🤖 Generated with Claude Code

macaris64 and others added 4 commits April 25, 2026 23:03
- CMakeLists: replace find_package(gazebo) with gz-sim8/gz-transport13/gz-plugin2
- Headers: inherit gz::sim::System+ISystemConfigure+ISystemPreUpdate/PostUpdate
  instead of ModelPlugin; drop all <gazebo/...> includes; use gz::sim::Entity
  members and gz::transport::Node (value, not pointer)
- Sources: Configure() replaces Load(); PreUpdate()/PostUpdate() replace
  WorldUpdateBegin callbacks; joint velocities via JointVelocityCmd component;
  forces via ExternalWorldWrenchCmd; topic names use /model/<name>/cmd_vel
  absolute path (no tilde); GZ_ADD_PLUGIN replaces GZ_REGISTER_MODEL_PLUGIN
- Fix: remove .value_or() from gz::sim::Model::Name() and World::Name()
  calls — Harmonic returns std::string directly, not std::optional<std::string>
- Dockerfile: convert to two-stage multi-stage build; add X11/Mesa GUI
  packages (libgl1-mesa-dri, libx11-6, etc.) for display forwarding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ros2.Dockerfile: install ros-${ROS_DISTRO}-ros-gz-bridge/sim; fall back
  to git-cloning ros_gz from source if apt overlay lacks the packages
- sim.launch.py: add use_external_gz arg with UnlessCondition so the
  Compose gazebo service is not double-started inside the ROS 2 container
- compose.yaml: set GZ_IP/GZ_PARTITION env vars on both gazebo and ros2
  services (required for gz-transport peer discovery across bridge network);
  change ros2 depends_on gazebo to service_healthy; pass use_external_gz:=true
  in the launch command; add Gazebo GUI support via DISPLAY passthrough,
  /tmp/.X11-unix bind-mount, LIBGL_ALWAYS_SOFTWARE=1 for Mesa llvmpipe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…un support

sim_adapter (Phase C):
- New SITL-only cFS app: receives CCSDS SPPs on UDP port 5700, validates
  APID (0x500–0x57F) and CRC-16/CCITT-FALSE, routes valid packets to the
  cFE Software Bus via SIM_INJECT_HK_MID
- Entire body guarded by #ifndef CFS_FLIGHT_BUILD — zero symbols in flight image
- 6 CMocka unit tests (all passing): CRC known vector, short packet, APID
  out of range, CRC mismatch, valid packet routed, init socket failure
- _defs/mids.h: add SIM_ADAPTER_CMD_MID 0x1D00, SIM_ADAPTER_HK_MID 0x0D01
- Priority 95 in cfe_es_startup.scr (between MCU gateways and CDH)

Gazebo GUI (make run):
- Makefile: run xhost +local:docker before compose up; print display status
- compose.yaml gazebo: DISPLAY passthrough + /tmp/.X11-unix bind-mount +
  LIBGL_ALWAYS_SOFTWARE=1; command detects $$DISPLAY at runtime — full GUI
  when display available, server-only (-s) when headless

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cppcheck [variableScope]: move bytes_recv declaration inside the while loop
body in SIM_ADAPTER_AppMain — cppcheck --enable=all reports variableScope
when a variable is declared at function scope but only used in a sub-block.

apid-mid-lint [R1]: add Sim Injection Sub-Allocation section to
docs/interfaces/apid-registry.md with an explicit row for APID 0x501
(SIM_ADAPTER_HK_MID). The range row 0x500-0x57F only registers 0x500 in
the lint's set; 0x501 needed its own explicit row to satisfy R1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@macaris64 macaris64 merged commit cb33871 into master Apr 25, 2026
12 checks passed
@macaris64 macaris64 deleted the fix/gz-harmonic-name-api branch April 25, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant