Cheat sheet

ROS 2 command line cheat sheet

The ros2 topic, node, service, param, bag, action, interface, launch, run, pkg and doctor commands for ROS 2 Jazzy, with QoS flags, a runnable QoS mismatch demo and the gotchas that waste the most time.

ROS 2Last verified 14 Nov 2026· ROS 2 Jazzy Jalisco (ros2cli 0.32), checked in the ros:jazzy-ros-base container

This sheet is for anyone debugging a running ROS 2 system from a terminal. Every command and flag below was checked against ros2 <command> -h in the ros:jazzy-ros-base container on 14 November 2026, and against the Jazzy documentation. The target is ROS 2 Jazzy Jalisco (LTS, May 2024). Lyrical Luth (LTS, May 2026) adds options, for example to ros2 param get, so check -h on newer distributions. New to ROS 2? Start with hello ROS 2 and the glossary entries node, topic, service, action and QoS.

Before anything else

source /opt/ros/jazzy/setup.bash          # every new shell, or add it to ~/.bashrc
source install/setup.bash                 # your workspace, after colcon build
printenv | grep -E 'ROS_(DISTRO|DOMAIN_ID|AUTOMATIC_DISCOVERY_RANGE)|RMW_IMPLEMENTATION'
ros2 doctor --report | less               # platform, network, middleware and package checks

Topics

ros2 topic list -t                         # names with types
ros2 topic info /scan -v                   # publishers, subscribers and the QoS of each
ros2 topic echo /odom --once               # one message, then exit
ros2 topic echo /odom --field pose.pose.position
ros2 topic echo /scan --no-arr             # hide long arrays
ros2 topic echo /joint_states --csv > joints.csv
ros2 topic hz /camera/image_raw            # rate, averaged over a window
ros2 topic bw /camera/image_raw            # bandwidth
ros2 topic delay /scan                     # age of messages, from header.stamp
ros2 topic find sensor_msgs/msg/Imu
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.1}, angular: {z: 0.0}}"
ros2 topic pub -r 10 /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.1}}"   # 10 Hz until Ctrl-C
ros2 topic pub -t 5 -w 1 /chatter std_msgs/msg/String "{data: hello}"       # 5 messages, after 1 subscriber matches

Nodes

ros2 node list
ros2 node list -a                          # include hidden nodes
ros2 node info /controller_manager         # its topics, services and actions

Services

ros2 service list -t
ros2 service type /add_two_ints
ros2 service find std_srvs/srv/Trigger
ros2 service call /reset std_srvs/srv/Empty
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 2, b: 3}"
ros2 service echo /add_two_ints            # needs service introspection enabled on the client or server

Parameters

ros2 param list /camera_driver
ros2 param get /camera_driver exposure
ros2 param set /camera_driver exposure 20
ros2 param describe /camera_driver exposure
ros2 param dump /camera_driver > camera.yaml
ros2 param load /camera_driver camera.yaml
ros2 param delete /camera_driver debug_mode

Bags

The default storage format in Jazzy is MCAP. In Jazzy, topics are passed with --topics, and the bare positional list is deprecated.

ros2 bag record -a -o run_01                         # all topics and services
ros2 bag record --topics /tf /tf_static /odom /scan -o nav_test
ros2 bag record -e '/camera/.*' -o cams              # regex
ros2 bag record --topics /scan -d 60 -o split_bag    # new file every 60 s
ros2 bag info nav_test
ros2 bag play nav_test -r 0.5                        # half speed
ros2 bag play nav_test --clock -l                    # publish /clock and loop
ros2 bag play nav_test --topics /scan --start-offset 10

When you play a bag with --clock, run the nodes under test with use_sim_time set to true, or their timestamps will not match the data.

Actions

ros2 action list -t
ros2 action info /navigate_to_pose
ros2 action type /navigate_to_pose
ros2 action send_goal -f /fibonacci example_interfaces/action/Fibonacci "{order: 5}"   # -f prints feedback

Interfaces

ros2 interface list
ros2 interface packages
ros2 interface package sensor_msgs
ros2 interface show geometry_msgs/msg/Quaternion   # fields x, y, z, w
ros2 interface proto geometry_msgs/msg/Twist       # a YAML template to paste into pub or call

Run and launch

ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp talker --ros-args -r __node:=talker_2 -r chatter:=chatter_2
ros2 run demo_nodes_cpp parameter_blackboard --ros-args -p a_string:=hello --params-file demo_params.yaml
ros2 run demo_nodes_cpp talker --ros-args --log-level debug
ros2 run --prefix 'gdb -ex run --args' demo_nodes_cpp talker
ros2 launch nav2_bringup tb3_simulation_launch.py --show-args
ros2 launch my_robot bringup.launch.py use_sim_time:=true
ros2 launch my_robot bringup.launch.py --print       # show the launch description without running it

Packages and the daemon

ros2 pkg list
ros2 pkg executables demo_nodes_cpp
ros2 pkg prefix rclpy
ros2 pkg create my_pkg --build-type ament_python --dependencies rclpy std_msgs --node-name my_node
ros2 pkg xml my_pkg
ros2 daemon stop && ros2 daemon start                 # clears a stale discovery cache
ros2 doctor hello                                     # check that hosts see each other

QoS flags

ros2 topic echo and ros2 topic pub take the same QoS options.

Flag Values
--qos-profile default, system_default, sensor_data, services_default, parameters, parameter_events, action_status_default, best_available
--qos-reliability reliable, best_effort, system_default, best_available
--qos-durability volatile, transient_local, system_default, best_available
--qos-history, --qos-depth keep_last with a depth, or keep_all

The help text in Jazzy says that, by default, echo and pub pick reliability and durability compatible with the endpoints already running. You need the flags when the other side starts later, or when you want to test a specific profile.

ros2 topic echo /map --qos-durability transient_local --qos-reliability reliable
ros2 topic pub /scan_status std_msgs/msg/String "{data: ok}" --qos-reliability best_effort

The compatibility rules from the Jazzy QoS page:

Publisher Subscriber Connects
Best effort Best effort Yes
Best effort Reliable No
Reliable Best effort Yes
Reliable Reliable Yes
Volatile Transient local No
Transient local Volatile Yes, new messages only
Transient local Transient local Yes, including the stored history

This block shows the second row in practice. It runs in the Jazzy container: one best-effort publisher, one reliable and one best-effort subscriber.

# ros2
import rclpy
from rclpy.qos import QoSProfile, ReliabilityPolicy
from std_msgs.msg import String

rclpy.init()
node = rclpy.create_node("qos_check")
best_effort = QoSProfile(depth=10, reliability=ReliabilityPolicy.BEST_EFFORT)
reliable = QoSProfile(depth=10, reliability=ReliabilityPolicy.RELIABLE)
received = {"reliable_sub": 0, "best_effort_sub": 0}

pub = node.create_publisher(String, "scan_status", best_effort)
node.create_subscription(String, "scan_status", lambda m: received.__setitem__("reliable_sub", received["reliable_sub"] + 1), reliable)
node.create_subscription(String, "scan_status", lambda m: received.__setitem__("best_effort_sub", received["best_effort_sub"] + 1), best_effort)

for i in range(40):
    pub.publish(String(data=f"msg {i}"))
    rclpy.spin_once(node, timeout_sec=0.05)
print("best-effort publisher ->", received)   # the reliable subscription stays at 0
node.destroy_node()
rclpy.shutdown()

Output on ROS 2 Jazzy, with the timestamp and the matching publisher-side warning removed:

[WARN] [qos_check]: New subscription discovered on topic 'scan_status', requesting incompatible QoS. No messages will be sent to it. Last incompatible policy: RELIABILITY
best-effort publisher -> {'reliable_sub': 0, 'best_effort_sub': 38}

A late subscriber to a latched-style topic such as /map or /robot_description gets nothing unless both sides use transient local durability.

Gotchas

Symptom Cause Fix
ros2 topic list shows nothing from the other machine Different ROS_DOMAIN_ID, discovery limited by ROS_AUTOMATIC_DISCOVERY_RANGE, or a firewall blocking multicast Match the domain ID on both machines, check the discovery range, run ros2 doctor hello on both
A node you killed still appears in the list The CLI daemon caches discovery ros2 daemon stop, then retry
echo shows nothing, info -v shows both ends QoS mismatch Compare the QoS in ros2 topic info -v, then use the flags above
Package 'x' not found right after a build Workspace not sourced in this shell source install/setup.bash
TF lookups fail during bag playback Nodes use wall time, bag has old stamps ros2 bag play --clock and use_sim_time:=true
ros2 param set returns but nothing changes The node reads the parameter only at start-up Restart the node, or add a parameter callback in the code
pub messages vanish The publisher exits before discovery completes Use -w 1, or -t N with a rate
Two simulators on one network fight over topics Same domain on a shared network Give each robot or developer its own ROS_DOMAIN_ID