Unit 16 · lesson
Two Healthy Runtimes Are Not Automatically Integrated
By now you can build and launch a ROS 2 workspace reliably. You also have a separate Java/WPILib application model from earlier units.
It is tempting to say:
The Java side works, the ROS side works, so the integrated robot works.
That conclusion skips the most important missing piece: the integration path.
Name the two runtimes separately
Java/WPILib runtime
This side can contain:
- Java classes and interfaces;
- WPILib subsystems and commands;
- JUnit tests;
- WPILib telemetry/logging;
- simulation or robot-specific execution.
ROS 2 runtime
This side can contain:
- ROS nodes;
- topics;
- services;
- actions;
- parameters;
- launch files;
- package/workspace infrastructure.
Both can be healthy independently.
That does not create a shared data path.
An integration path needs an explicit component
If Java/WPILib data is supposed to reach ROS 2, something must intentionally translate or transport it.
Possible architecture categories include:
bridge process
adapter process
network protocol boundary
shared external middleware
file/socket/message gateway
The exact implementation is a later engineering choice.
This course does not invent one and call it done.
The important architectural rule is:
Name the component that crosses the boundary, the data it owns, the direction of flow, and the evidence that proves the crossing occurred.
Do not call robotnix_bringup the bridge
robotnix_bringup currently owns:
- launch files;
- ROS startup configuration;
- ROS-side demo startup.
It does not contain code that reads WPILib data or publishes Java state into ROS.
A bringup package can launch a future bridge process if one is selected and installed, but launch configuration is not itself the bridge implementation.
That distinction prevents architecture diagrams from lying.
Define an integration contract before implementing one
Suppose a future system needs to send a Java obstacle-guard state into ROS.
A useful contract might record:
Producer
WPILib Java application
Data
obstacle stop decision
Direction
Java -> ROS
Proposed interface
not selected yet
Required evidence
Java-side emitted value
bridge received value
ROS-side published value
subscriber received value
matching timestamp/correlation identifier
Until those records exist, the correct status is:
integration not demonstrated
That is better than hiding uncertainty behind an arrow in a diagram.
Data ownership must be clear
If both Java and ROS independently calculate:
shouldStop
which one is authoritative?
If they disagree, what happens?
A mixed-runtime design should define:
- source of truth;
- transformation rules;
- units;
- freshness requirements;
- failure behavior;
- startup dependency;
- shutdown behavior.
Without that contract, integration can create duplicate logic and conflicting decisions.
Units and types must survive the boundary
Earlier Java code used names such as:
double rangeMeters;
ROS messages use typed fields and message definitions.
An integration layer must preserve meaning, not just numbers.
If Java sends:
42
and ROS interprets it as meters while Java meant centimeters, the transport can be technically successful and the system still be wrong.
The boundary needs a data contract.
Startup order can matter
Imagine a future bridge depends on both:
- the Java source being available;
- the ROS graph being ready.
Then startup questions include:
- What happens if ROS starts first?
- What happens if Java starts first?
- Does the bridge reconnect?
- Does stale data remain buffered?
- How is readiness reported?
A launch file can orchestrate ROS-side processes, but a mixed-runtime startup runbook must document dependencies outside that launch boundary too.
Failure should remain local when possible
If the Java application exits, should the ROS graph collapse completely?
If one ROS node restarts, should the Java robot application stop?
The answer depends on system requirements, but the architecture should define failure propagation intentionally.
A bridge that turns every small failure into a whole-system failure is tightly coupled.
A bridge that silently drops all failures is also unsafe.
The right policy is explicit and testable.
Evidence for integration must cross the same boundary
Suppose Java logs:
stopDecision=true
and ROS separately shows:
/motor_guard alive
That does not prove the ROS node received the Java decision.
A stronger integrated evidence chain would need matching data across the bridge.
For example:
Java event ID 482 -> value true
bridge input ID 482 -> true
ROS publication ID 482 -> true
ROS subscriber receives ID 482 -> true
The exact mechanism can differ. The principle is traceability across the boundary.
Build a Java-to-ROS Integration Contract
Create these sections.
Runtime A
Describe the Java/WPILib application and what evidence proves it is running correctly.
Runtime B
Describe the ROS 2 bringup/runtime and what evidence proves it is running correctly.
Proposed boundary
Name the future adapter/bridge responsibility without pretending it exists yet.
Data contract
Record:
field names
units
direction
freshness requirement
source of truth
Startup contract
State which runtime or bridge can start first and how readiness should be checked.
Failure contract
State what happens if either side disappears.
Verification contract
List the evidence required before claiming data crossed the boundary successfully.
Worked review
Claim:
robotnix_bringuplaunched correctly and Java JUnit tests pass, so Java is connected to ROS.
Repair:
The ROS bringup and Java component tests have independent evidence of correctness. No Java-to-ROS bridge, shared data contract, or cross-runtime message trace has been demonstrated, so integration remains unverified.
That is the correct course boundary.
Your turn
Write a one-page integration contract for this hypothetical requirement:
The WPILib Java application produces
batteryPercentand ROS monitoring software needs to receive the same value with source identity and freshness information.
Include:
- Java producer;
- ROS consumer responsibility;
- field name and unit;
- freshness/timestamp requirement;
- future bridge responsibility;
- evidence needed on both sides;
- failure behavior if updates stop.
Do not choose a Java ROS client library just to fill the blank. The architecture contract comes before implementation selection.
In the final lesson, you will combine the workspace, bringup, graph, and integration boundaries into a startup runbook another student can execute from a clean machine state.