Unit 15 · lab
Lab: Build a Repeatable ROS 2 Bringup and Verify the Runtime
This lab turns robotnix_bringup into actual startup infrastructure.
You will install a launch directory, write a Python launch file, rebuild the package, launch a named talker/listener pair, remap their communication to /robotnix/demo, inspect the graph from a second shell, override the topic argument, and preserve one stale-install failure.
Your final artifact is a Bringup Verification Record.
Choose your lane
Local Jazzy lane
Use this lane if you have ROS 2 Jazzy and demo_nodes_cpp available.
You will run the launch and collect graph evidence from a second terminal.
Supplied-evidence lane
If local ROS execution is unavailable, write the exact package and launch files, then use the supplied launch/graph evidence in this lab.
Label it supplied bringup evidence.
Guided example: source file exists, launch file not found
You create:
src/robotnix_bringup/launch/demo_pair.launch.py
but ros2 launch cannot find it.
If the package prefix resolves, the next question is not whether ROS is installed. Inspect the package install path and CMakeLists.txt.
The source launch directory must be installed:
install(
DIRECTORY launch
DESTINATION share/${PROJECT_NAME}
)
Then the package must be rebuilt.
That is the pattern for the lab: identify the failing layer before changing unrelated code.
Part 1: Add the launch install rule
Update CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
project(robotnix_bringup)
find_package(ament_cmake REQUIRED)
install(
DIRECTORY launch
DESTINATION share/${PROJECT_NAME}
)
ament_package()
Create:
~/robot_ws/src/robotnix_bringup/launch/
Part 2: Write demo_pair.launch.py
Use:
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
def generate_launch_description():
topic_name = LaunchConfiguration("topic_name")
return LaunchDescription([
DeclareLaunchArgument(
"topic_name",
default_value="/robotnix/demo",
description=(
"Topic used by the demo talker/listener pair"
),
),
Node(
package="demo_nodes_cpp",
executable="talker",
name="talker_demo",
output="screen",
remappings=[
("/chatter", topic_name),
],
),
Node(
package="demo_nodes_cpp",
executable="listener",
name="listener_demo",
output="screen",
remappings=[
("/chatter", topic_name),
],
),
])
Check that both nodes use the same topic_name substitution.
Part 3: Rebuild and source
Run:
source /opt/ros/jazzy/setup.bash
cd ~/robot_ws
colcon build --packages-select robotnix_bringup
source install/setup.bash
ros2 pkg prefix robotnix_bringup
Preserve:
- build summary;
- resolved package prefix.
If either fails, repair that layer before launch.
Part 4: Launch the default configuration
Terminal A:
ros2 launch \
robotnix_bringup \
demo_pair.launch.py
Local lane: leave the launch active.
Supplied lane: use this transcript:
[INFO] [launch]: starting robotnix demo pair
[INFO] [talker_demo]: process started
[INFO] [listener_demo]: process started
Part 5: Verify from Terminal B
Source the same environment:
source /opt/ros/jazzy/setup.bash
source ~/robot_ws/install/setup.bash
Then run:
ros2 node list
ros2 topic list -t
ros2 topic info /robotnix/demo
Supplied graph evidence:
/talker_demo
/listener_demo
Supplied topic evidence:
/robotnix/demo [std_msgs/msg/String]
Type: std_msgs/msg/String
Publisher count: 1
Subscription count: 1
Record each command separately.
Part 6: Inspect one message
Local lane:
ros2 topic echo /robotnix/demo --once
Supplied lane:
data: 'Hello World: 1'
Label it supplied.
This adds one message observation to the bringup evidence.
Part 7: Stop the launch and verify shutdown
Stop Terminal A with:
Ctrl+C
Then rerun:
ros2 node list
Record whether /talker_demo and /listener_demo disappear from the graph.
Supplied lane: both demo nodes are absent after the supplied stop event.
Part 8: Override the launch argument
Restart with:
ros2 launch \
robotnix_bringup \
demo_pair.launch.py \
topic_name:=/robotnix/test
Inspect:
ros2 topic list -t
Expected topic:
/robotnix/test [std_msgs/msg/String]
Record that the same launch source produced a different runtime topic through one launch argument.
Part 9: Create a stale-install failure
Stop the launch.
Edit the source default to:
/robotnix/stale_test
Do not rebuild yet.
Run the installed launch file again.
Local lane: record which default appears.
Supplied lane: use this result:
observed installed default: /robotnix/demo
source default: /robotnix/stale_test
Explain the mismatch.
Then repair:
cd ~/robot_ws
colcon build --packages-select robotnix_bringup
source install/setup.bash
Relaunch and verify the installed behavior now matches the edited source.
Part 10: Build the Bringup Verification Record
Your artifact must contain:
Installed launch source
- source path;
- CMake install rule;
- package prefix.
Launch contract
- package/executable/name for both nodes;
- default
topic_name; - remapping rule.
Default launch evidence
- launch transcript;
- node list;
- topic name/type;
- endpoint counts;
- one message if available.
Shutdown evidence
Record post-stop node state.
Argument override
Record /robotnix/test and the command that selected it.
Stale-install failure
Preserve source default, installed behavior, missing rebuild, repair, and verified result.
Java boundary
State why this launch file does not start or integrate a WPILib Java application.
Success criteria
Your record is complete when another student can answer:
- How is the launch directory installed?
- Which package provides the talker/listener executables?
- Which runtime node names are expected?
- Why does the demo topic become
/robotnix/demo? - How can the topic be changed without copying the launch file?
- Which second-shell commands verify the runtime?
- What did the stale-install case teach about source versus installed resources?
- Which Java/WPILib behavior remains outside this ROS bringup?
A successful bringup is not "the launch command ran." It is a startup contract that another student can reproduce and verify.