Skip to content

feat: multi-ECU aggregation demo with static peer and mDNS discovery#56

Open
bburda wants to merge 18 commits intomainfrom
feat/multi-ecu-aggregation-demo
Open

feat: multi-ECU aggregation demo with static peer and mDNS discovery#56
bburda wants to merge 18 commits intomainfrom
feat/multi-ecu-aggregation-demo

Conversation

@bburda
Copy link
Copy Markdown
Contributor

@bburda bburda commented Mar 31, 2026

Description

New headless Docker demo showcasing multi-instance peer aggregation from ros2_medkit#327. Three containers simulate three ECUs of a robotics system (perception/planning/actuation), each running its own gateway + fault_manager. Perception ECU acts as the primary aggregator.

Key features demonstrated:

  • Static peer URL discovery (Planning ECU)
  • mDNS auto-discovery (Actuation ECU)
  • Parent component robot-alpha with 3 sub-components (one per ECU)
  • 3 cross-ECU Functions: autonomous-navigation (6 hosts from 3 ECU), obstacle-avoidance (4 hosts), task-execution (5 hosts)
  • DDS isolation via ROS_DOMAIN_ID (10/20/30) + domain_bridge for cross-ECU data flow
  • Parameter-based fault injection per ECU
  • Transparent request proxy to remote ECU apps
  • Scripts API per ECU component

Verified with:

  • MCP server (PR ros2_medkit_mcp#14): 38/38 applicable tests pass
  • Web UI connected to aggregated gateway
  • Fault injection + restore scripts
  • Cross-ECU data flow via domain_bridge

Related Issue

Depends on ros2_medkit#327 (feat/entity-model-and-aggregation branch)

Before merge

  • Change ROS2_MEDKIT_REF in Dockerfile from feat/entity-model-and-aggregation to main after ros2_medkit#327 is merged

Checklist

  • Tested locally
  • README updated (if needed)

bburda added 10 commits March 30, 2026 20:20
Perception ECU: lidar_driver, camera_driver, point_cloud_filter, object_detector
Planning ECU: path_planner, behavior_planner, task_scheduler
Actuation ECU: motor_controller, joint_driver, gripper_controller

All nodes follow sensor_diagnostics pattern with parameter-based
fault injection and /diagnostics publishing.
3x params (perception/planning/actuation with gateway + fault_manager config)
3x manifests (robot-alpha parent component, 3 sub-components, 3 cross-ECU functions)
2x domain_bridge (planning bridges /perception/detections, actuation bridges /planning/commands)
Each launch file starts ECU-specific nodes + gateway + fault_manager + diagnostic_bridge.
Planning and actuation include domain_bridge for cross-domain topic bridging.
Single image (ros:jazzy-ros-base), ECU_LAUNCH env var selects launch file.
3 ECU services with isolated ROS_DOMAIN_ID (10/20/30) + web UI.
Host-side: run-demo, stop-demo, 4 inject scripts, restore-normal
Container: Scripts API auto-discovery per ECU component (inject + restore)
Gateway runs in /diagnostics namespace, not /perception|planning|actuation.
Params were under wrong top-level key, causing gateway to use defaults
(127.0.0.1, runtime_only, aggregation disabled).
…nodes

- Actuation ECU needs aggregation.enabled=true for mDNS announce to work
  (the aggregation subsystem must be active for announce/discover flags)
- Changed unmanifested_nodes from warn to hide in all 3 manifests to
  filter infrastructure nodes (diagnostic_bridge, fault_manager, etc.)
…es ignore

- Added medkit-gateway, medkit-fault-manager, medkit-diagnostic-bridge
  as manifest apps on each ECU sub-component
- Changed unmanifested_nodes from hide to ignore (correct enum value)
- Gateway infra nodes now appear per-ECU instead of polluting as orphans
Copilot AI review requested due to automatic review settings March 31, 2026 20:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new headless Docker-based demo (demos/multi_ecu_aggregation/) that showcases ros2_medkit multi-instance peer aggregation across three simulated ECUs (perception/planning/actuation), including static peer configuration, mDNS discovery, DDS isolation via ROS_DOMAIN_ID, domain bridging, and fault-injection scripts.

Changes:

  • Introduces a new ROS 2 package (multi_ecu_demo) with simulated Perception/Planning/Actuation nodes that publish data and /diagnostics.
  • Adds Docker + Compose orchestration and host/container scripts for running the demo and injecting/restoring faults.
  • Adds gateway configs/manifests and domain_bridge configs to demonstrate cross-ECU aggregation and topic bridging.

Reviewed changes

Copilot reviewed 45 out of 46 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
demos/multi_ecu_aggregation/stop-demo.sh Stops the demo stack with optional cleanup flags.
demos/multi_ecu_aggregation/src/planning/task_scheduler.cpp Planning ECU task-state publisher + diagnostics + fault injection.
demos/multi_ecu_aggregation/src/planning/path_planner.cpp Planning ECU path generator reacting to detections + diagnostics.
demos/multi_ecu_aggregation/src/planning/behavior_planner.cpp Planning ECU command generator from planned path + diagnostics.
demos/multi_ecu_aggregation/src/perception/point_cloud_filter.cpp Perception ECU LaserScan→PointCloud2 converter/filter + diagnostics.
demos/multi_ecu_aggregation/src/perception/object_detector.cpp Perception ECU fake detector driven by timer + point cloud freshness tracking.
demos/multi_ecu_aggregation/src/perception/lidar_driver.cpp Perception ECU simulated LaserScan publisher + fault injection.
demos/multi_ecu_aggregation/src/perception/camera_driver.cpp Perception ECU simulated Image publisher + fault injection.
demos/multi_ecu_aggregation/src/actuation/motor_controller.cpp Actuation ECU Twist→JointState publisher + diagnostics + fault injection.
demos/multi_ecu_aggregation/src/actuation/joint_driver.cpp Actuation ECU JointState integrator publishing joint_state + diagnostics.
demos/multi_ecu_aggregation/src/actuation/gripper_controller.cpp Actuation ECU Twist→gripper JointState + diagnostics + fault injection.
demos/multi_ecu_aggregation/run-demo.sh Builds/starts the demo stack with optional update/no-cache/attached mode.
demos/multi_ecu_aggregation/restore-normal.sh Host-side helper to call “restore-normal” scripts on all ECUs via Scripts API.
demos/multi_ecu_aggregation/README.md Full demo documentation: architecture, discovery, APIs, scripts, troubleshooting.
demos/multi_ecu_aggregation/package.xml Declares the multi_ecu_demo ROS 2 package and dependencies.
demos/multi_ecu_aggregation/launch/planning.launch.py Launches Planning ECU nodes + gateway + fault_manager + bridge.
demos/multi_ecu_aggregation/launch/perception.launch.py Launches Perception ECU nodes + gateway (aggregation enabled) + fault_manager.
demos/multi_ecu_aggregation/launch/actuation.launch.py Launches Actuation ECU nodes + gateway (mDNS announce) + fault_manager + bridge.
demos/multi_ecu_aggregation/inject-sensor-failure.sh Host script to trigger perception ECU fault injection via Scripts API.
demos/multi_ecu_aggregation/inject-planning-delay.sh Host script to trigger planning ECU delay injection via Scripts API.
demos/multi_ecu_aggregation/inject-gripper-jam.sh Host script to trigger actuation ECU gripper jam via Scripts API.
demos/multi_ecu_aggregation/inject-cascade-failure.sh Host script to trigger a multi-ECU fault scenario via Scripts API.
demos/multi_ecu_aggregation/Dockerfile Builds a self-contained demo image (ROS 2 + ros2_medkit + demo package).
demos/multi_ecu_aggregation/docker-compose.yml Defines 3 ECU services + web UI on a shared bridge network.
demos/multi_ecu_aggregation/container_scripts/planning-ecu/restore-normal/script.bash In-container restore script (planning).
demos/multi_ecu_aggregation/container_scripts/planning-ecu/restore-normal/metadata.json Scripts API metadata (planning restore).
demos/multi_ecu_aggregation/container_scripts/planning-ecu/inject-planning-delay/script.bash In-container injection script (planning delay).
demos/multi_ecu_aggregation/container_scripts/planning-ecu/inject-planning-delay/metadata.json Scripts API metadata (planning delay).
demos/multi_ecu_aggregation/container_scripts/perception-ecu/restore-normal/script.bash In-container restore script (perception).
demos/multi_ecu_aggregation/container_scripts/perception-ecu/restore-normal/metadata.json Scripts API metadata (perception restore).
demos/multi_ecu_aggregation/container_scripts/perception-ecu/inject-sensor-failure/script.bash In-container injection script (lidar failure).
demos/multi_ecu_aggregation/container_scripts/perception-ecu/inject-sensor-failure/metadata.json Scripts API metadata (lidar failure).
demos/multi_ecu_aggregation/container_scripts/actuation-ecu/restore-normal/script.bash In-container restore script (actuation).
demos/multi_ecu_aggregation/container_scripts/actuation-ecu/restore-normal/metadata.json Scripts API metadata (actuation restore).
demos/multi_ecu_aggregation/container_scripts/actuation-ecu/inject-gripper-jam/script.bash In-container injection script (gripper jam).
demos/multi_ecu_aggregation/container_scripts/actuation-ecu/inject-gripper-jam/metadata.json Scripts API metadata (gripper jam).
demos/multi_ecu_aggregation/config/planning_params.yaml Planning ECU gateway/node/fault_manager params.
demos/multi_ecu_aggregation/config/planning_manifest.yaml Planning ECU SOVD manifest (components/apps/functions).
demos/multi_ecu_aggregation/config/perception_params.yaml Perception ECU gateway params (aggregation + discover + static peer URL).
demos/multi_ecu_aggregation/config/perception_manifest.yaml Perception ECU SOVD manifest.
demos/multi_ecu_aggregation/config/domain_bridge/planning_bridge.yaml Domain bridge config: detections 10→20.
demos/multi_ecu_aggregation/config/domain_bridge/actuation_bridge.yaml Domain bridge config: commands 20→30.
demos/multi_ecu_aggregation/config/actuation_params.yaml Actuation ECU gateway/node/fault_manager params (mDNS announce).
demos/multi_ecu_aggregation/config/actuation_manifest.yaml Actuation ECU SOVD manifest.
demos/multi_ecu_aggregation/CMakeLists.txt Builds/installs all demo nodes and launch/config resources.
.gitignore Adds an ignore entry under the demo launch directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 45 out of 46 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

bburda added 7 commits April 2, 2026 15:40
…creation

- Add shellcheck source=/dev/null directives to all container scripts
- Add shellcheck disable=SC2086 for remaining COMPOSE_CMD usages
- Fix clock type mismatch in object_detector (RCL_ROS_TIME -> RCL_SYSTEM_TIME)
- Fix config comment in actuation_params.yaml (aggregation is enabled)
- Recreate wall timer on rate parameter change in all demo nodes,
  consistent with the pattern already used in object_detector
…demo

Code quality:
- Fix copyright headers to SPDX format in all 10 source files
- Fix namespace inconsistency: actuation files now use multi_ecu_demo
- Add blocking sleep comments in path_planner and point_cloud_filter
- Fix inject-cascade-failure.sh header comment (wrong parameters)
- Use error counter pattern in inject-cascade-failure.sh

Infrastructure:
- Add check-demo.sh readiness script (polls health, shows entity counts)
- Add smoke test (tests/smoke_test_multi_ecu.sh) using smoke_lib.sh
- Add CI profile services to docker-compose.yml (headless, no web UI)
- Add build-and-test-multi-ecu job to CI workflow
- Share Docker image across ECU services (multi-ecu-demo:local)

UX/correctness:
- Add fault-clearing curl calls to all 3 restore scripts
- Add gateway reachability check to host-side injection scripts
- Use demo-specific container_name for web UI (multi_ecu_web_ui)
- Quote ECU_LAUNCH in Dockerfile CMD
- Update top-level README with new demo entry
…s in smoke test

- Replace hyphens with underscores in domain_bridge YAML node names
  (ROS 2 node names only allow alphanumerics and underscores)
- Make peer ECU component checks non-fatal in smoke test since
  component aggregation depends on gateway version
ECU components (perception-ecu, planning-ecu, actuation-ecu) have
parent_component_id=robot-alpha, so they appear under
/components/robot-alpha/subcomponents, not /components.
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.

2 participants