Integration
Every module boundary needs an explicit contract: why the boundary exists, what
crosses it, how peers discover each other, and how failure is observed.
Draw boundaries for a reason
- Split components with different rates when sharing an executor or process can
starve the faster loop.
- Split failure domains when one component must restart, scale, or exhaust
memory without taking down another.
- Keep tightly coupled code together when neither rate nor failure isolation
justifies serialization and deployment overhead.
- Make each container a supervisable unit. Multiple processes may belong
together, but their shared lifecycle should be intentional.
Choose the boundary contract
- Inside one ROS 2 system, default to ROS topics, services, and actions.
- Crossing hosts or containers does not by itself require a new application
protocol; configure ROS discovery explicitly first.
- Use gRPC or REST at a genuine non-ROS system or organizational boundary.
- Use shared memory or zero-copy paths only after measurement shows copying is
the bottleneck.
- Treat names, schemas, QoS, time, backpressure, health, restart behavior, and
ownership as part of the interface.
Read communication selection when choosing
between ROS 2, DDS discovery options, Zenoh, gRPC, REST, or shared memory.
Package the running system
- Use separate build and runtime stages for shipped modules; leave compilers
and build-only dependencies behind.
- Give each service a health signal that proves readiness, not merely a live
process.
- Make network mode,
ROS_DOMAIN_ID, discovery, volumes, devices, and
shutdown behavior visible in the composition.
- A successful
docker compose up proves process creation, not communication.
Verify real cross-boundary messages.
Read the Dockerfile guide for build/runtime
structure and signal handling. Read compose patterns
for DDS discovery, health, domains, and networking. Use the examples only as
starting shapes and verify them in the target environment.
Use environments for one module's reproducibility and GPU/runtime contract.
Use ros2 when the failed interface is within a healthy ROS graph. Use
foxglove only when the boundary is specifically remote visualization.
Done
- Each split has a rate, failure, deployment, or ownership reason.
- Every boundary has an explicit protocol and interface contract.
- Peers discover each other in the real host/container topology.
- Health and shutdown behavior are observable and scoped to the failed unit.
- A real message or request proves each changed boundary end to end.
1---2name: integration3description: Wire robotics modules with ROS 2 interfaces, Docker Compose, or non-ROS transports.4---56# Integration78Every module boundary needs an explicit contract: why the boundary exists, what9crosses it, how peers discover each other, and how failure is observed.1011## Draw boundaries for a reason1213- Split components with different rates when sharing an executor or process can14 starve the faster loop.15- Split failure domains when one component must restart, scale, or exhaust16 memory without taking down another.17- Keep tightly coupled code together when neither rate nor failure isolation18 justifies serialization and deployment overhead.19- Make each container a supervisable unit. Multiple processes may belong20 together, but their shared lifecycle should be intentional.2122## Choose the boundary contract2324- Inside one ROS 2 system, default to ROS topics, services, and actions.25- Crossing hosts or containers does not by itself require a new application26 protocol; configure ROS discovery explicitly first.27- Use gRPC or REST at a genuine non-ROS system or organizational boundary.28- Use shared memory or zero-copy paths only after measurement shows copying is29 the bottleneck.30- Treat names, schemas, QoS, time, backpressure, health, restart behavior, and31 ownership as part of the interface.3233Read [communication selection](references/comms-selection.md) when choosing34between ROS 2, DDS discovery options, Zenoh, gRPC, REST, or shared memory.3536## Package the running system3738- Use separate build and runtime stages for shipped modules; leave compilers39 and build-only dependencies behind.40- Give each service a health signal that proves readiness, not merely a live41 process.42- Make network mode, `ROS_DOMAIN_ID`, discovery, volumes, devices, and43 shutdown behavior visible in the composition.44- A successful `docker compose up` proves process creation, not communication.45 Verify real cross-boundary messages.4647Read [the Dockerfile guide](references/dockerfile-guide.md) for build/runtime48structure and signal handling. Read [compose patterns](references/compose-patterns.md)49for DDS discovery, health, domains, and networking. Use the examples only as50starting shapes and verify them in the target environment.5152Use `environments` for one module's reproducibility and GPU/runtime contract.53Use `ros2` when the failed interface is within a healthy ROS graph. Use54`foxglove` only when the boundary is specifically remote visualization.5556## Done5758- Each split has a rate, failure, deployment, or ownership reason.59- Every boundary has an explicit protocol and interface contract.60- Peers discover each other in the real host/container topology.61- Health and shutdown behavior are observable and scoped to the failed unit.62- A real message or request proves each changed boundary end to end.