Dummy robot: from observation to a visible system¶
The dummy_robot demo combines a map server, fake joint states, fake laser data, robot_state_publisher, TF, launch,
and RViz. It is a strong ROSCon demonstration because the robot and laser result remain visible after the interface
work.
The tutorial starts and finishes with the complete robot. NoDL operations remain node-scoped, so the detailed
walkthrough later selects dummy_laser as one worked node without treating it as the whole demo.
The reviewed source is
dummy_sensors/src/dummy_laser.cpp.
Note
This is a prototype tutorial. It exercises the real robot and the current observation/validation tools. Generated NoDL drafts, composition, forward generation, semantic diff, and conformance remain design targets.
Proposed complete flow (design preview)¶
This is the tutorial we want a user to follow once the missing NoDL features exist. Read the commands in this section as
the proposed product experience, not as commands available on main today. The current verified flow later on this
page records the executable subset.
1. Run the original robot¶
ros2 launch dummy_robot_bringup dummy_robot_bringup_launch.py
RViz shows the robot and the changing laser scan. This is the baseline: dummy_laser owns its scan-generation loop;
NoDL will only take responsibility for its ROS interface.
2. Recover a draft interface from the running node¶
ros2 nodl describe /dummy_laser --output nodl/dummy_laser.observed.nodl.yaml
The command writes a schema-valid NoDL draft. It identifies the scan publisher, its sensor_msgs/msg/LaserScan type,
and its observed QoS. Infrastructure endpoints can be retained with an explicit diagnostic option, but do not dominate
the default application-facing draft.
3. Curate and compose the authored interface¶
The author keeps the endpoint that matters and adds semantic documentation. Reusable NoDL fragments supply the common
node and TF endpoint declarations without pretending that a /tf endpoint proves a specific frame path.
ros2 nodl compose nodl/dummy_laser.observed.nodl.yaml \
--fragment ros2:node-base \
--fragment tf:scan-frame \
--output nodl/dummy_laser.nodl.yaml
ros2 nodl validate nodl/dummy_laser.nodl.yaml
The resulting document describes the scan publisher and its QoS. The system test still separately requires the
world → single_rrbot_hokuyo_link transform path needed for visualization.
4. Build the NoDL-forward variant¶
ros2 nodl generate nodl/dummy_laser.nodl.yaml --language cpp --output generated/dummy_laser
colcon build --packages-select nodl_dummy_robot_demo
Generation creates the ROS interface binding. The existing C++ scan calculation, loop rate, message timestamps, and business logic remain application code.
5. Run and compare the NoDL-forward robot¶
ros2 launch nodl_dummy_robot_demo dummy_robot.launch.py interface:=nodl
ros2 nodl conform /dummy_laser --file nodl/dummy_laser.nodl.yaml
Conformance reports that the expected NoDL interface and observed runtime interface agree. RViz still shows the robot and scan, which makes the migration result visible rather than terminal-only.
6. Demonstrate a meaningful failure¶
Start a deliberately regressed conventional variant. Its launch remaps the relative scan name to
scan_regressed; the node source remains unchanged.
ros2 launch nodl_dummy_robot_demo dummy_robot.launch.py \
interface:=conventional scan_remap:=scan_regressed
ros2 nodl conform /dummy_laser --file nodl/dummy_laser.nodl.yaml
RViz is still configured for /scan, so the laser display becomes empty. Conformance reports a semantic diff with the
expected /scan publisher missing and the unexpected /scan_regressed publisher observed. This makes deployment and
launch drift visible without modifying the application source.
Restart the NoDL-forward variant, rerun conformance, and finish with the working robot in RViz:
ros2 launch nodl_dummy_robot_demo dummy_robot.launch.py interface:=nodl
ros2 nodl conform /dummy_laser --file nodl/dummy_laser.nodl.yaml
Current implementation details¶
The remaining material is the executable subset on current main. It validates the tutorial’s starting point while the
proposed complete flow above defines the capabilities still to implement.
Start the existing robot¶
Build the upstream packages:
colcon build --packages-select dummy_map_server dummy_sensors dummy_robot_bringup
Source the workspace, then start the demo:
ros2 launch dummy_robot_bringup dummy_robot_bringup_launch.py
The launch starts:
/dummy_map_server;/robot_state_publisher;/dummy_joint_states;/dummy_laser;RViz.
RViz should display the robot and its changing laser scan.
List the nodes that make up the running system:
ros2 node list
The expected application nodes are:
/dummy_joint_states
/dummy_laser
/dummy_map_server
/robot_state_publisher
rviz2 also appears when the visualizer is running.
Observe the system one node at a time¶
NoDL currently describes one node at a time. There is no describe-system command, so record each participating node
explicitly:
mkdir -p /tmp/dummy_robot_observed
ros2 nodl describe /dummy_map_server --no-params \
-o /tmp/dummy_robot_observed/dummy_map_server.yaml
ros2 nodl describe /dummy_joint_states --no-params \
-o /tmp/dummy_robot_observed/dummy_joint_states.yaml
ros2 nodl describe /dummy_laser --no-params \
-o /tmp/dummy_robot_observed/dummy_laser.yaml
ros2 nodl describe /robot_state_publisher --no-params \
-o /tmp/dummy_robot_observed/robot_state_publisher.yaml
This explicit list is useful documentation: it shows the system boundary and preserves each node’s ownership. A future launch- or system-level manifest can reference these node documents without changing their node-scoped meaning.
Warning
The saved files are raw rosgraph_msgs/Node serializations. Current main does not convert them into NoDL documents.
This step exposes the first missing CLI behavior. The desired default is for ros2 nodl describe NODE to emit a
schema-valid draft NoDL document. Raw observation should remain available through an explicit diagnostic option.
Curate one worked node: dummy_laser¶
The source creates a sensor_msgs/msg/LaserScan publisher on relative topic scan with depth 10. Its loop computes
range values, timestamps messages, and sets single_rrbot_hokuyo_link as the message frame.
Inspect the dummy_laser observation from the system inventory, then curate this source-level document:
---
nodl_version: 2
description: Fake laser publisher from the dummy_robot demo.
publishers:
- name: scan
type: sensor_msgs/msg/LaserScan
description: Synthetic laser scan used by the RViz robot demo.
qos:
history: KEEP_LAST
depth: 10
reliability: RELIABLE
Validate it:
ros2 nodl validate examples/nodl_tutorial_verification/nodl/dummy_laser.nodl.yaml
The document describes the publisher. It does not describe the 30 Hz loop, generated range values, message timestamps, or real-time behavior.
The manual translation exposes another missing part of Describe: it needs a policy for framework endpoints such as
/rosout, parameter services, and /parameter_events. The default draft should focus on the node’s public application
interface, while an option should retain infrastructure for diagnostics.
Verify behavior outside NoDL¶
Confirm that laser messages still arrive:
ros2 topic echo /scan --once
Confirm the laser frame participates in the running TF tree:
ros2 run tf2_ros tf2_echo world single_rrbot_hokuyo_link
Stop tf2_echo after it reports a transform.
TF topics are not frame semantics¶
robot_state_publisher publishes transforms used to place the laser scan in RViz. A NoDL document can describe its
/tf and /tf_static topic endpoints. Those endpoints do not prove that a particular frame path exists.
For this robot, single_rrbot_hokuyo_link appears in LaserScan.header.frame_id. A separate system test must verify
that the transform is available from the configured RViz fixed frame.
Keep these claims separate:
Claim |
Appropriate check |
|---|---|
The node publishes or subscribes to |
NoDL endpoint description and future conformance |
The laser frame connects to the robot frame tree |
TF lookup in a running system |
RViz can render the scan |
Visual or headless application test |
Register the curated document¶
The tutorial verification package registers the document during its build. Confirm that the package builds:
colcon build --packages-select nodl_tutorial_verification
Registration makes the expected document discoverable by package and executable identity. Current main does not yet
provide a ros2 nodl verb to print or locate a registered document. That lookup is another CLI gap exposed by the
tutorial.
Current verified flow¶
The workflow available on main is:
Start the existing robot.
Inventory its nodes.
Observe each node into a separate raw runtime record.
Select
dummy_laseras the worked node.Inspect stable application fields.
Curate, validate, and register its NoDL document.
Verify laser messages and the required transform separately.
Finish with the complete working robot in RViz.
This flow is useful for evaluating the demo, but it still has manual translation and comparison steps.
CLI capabilities exposed by the tutorial¶
The workflow identifies these required verbs or verb behaviors:
Need |
Candidate command |
Available on |
|---|---|---|
Observe one node as raw graph data |
|
Observation exists; |
Describe one node as draft NoDL |
|
No |
Validate authored or curated NoDL |
|
Yes |
Find a registered document |
|
No |
Flatten reusable node fragments |
|
No |
Generate interface bindings |
|
No |
Compare two NoDL interfaces |
|
No |
Check a running node |
|
No |
The command names are candidate UX, not accepted interfaces. This tutorial intentionally avoids a describe-system
requirement. It keeps node descriptions separate and leaves system membership to launch or a future manifest.
Suggested regression¶
In an intentionally broken launch variant, remap dummy_laser’s relative scan name to scan_regressed. RViz remains
configured for /scan, so the missing laser is immediately visible. Future conformance output should identify the
missing expected /scan publisher and unexpected observed /scan_regressed publisher. This tests deployment and
launch drift without modifying C++ application logic.
Why work through dummy_laser¶
It has one clear application endpoint.
Its behavior remains meaningful after interface migration.
Its output participates in the robot’s TF-dependent visualization.
A topic-remapping regression is easy to explain and visible in RViz.
The demo can recover to a visually working state.