Use cases

ROS 2 for Robotics Students: Nodes, Topics, Services, Actions and tf2 Explained

The Kopik team7 min read

ROS 2 organises a robot's software as a graph of nodes, each doing one logical job. Nodes exchange data through three kinds of interface. Topics carry continuous streams, services handle short request/response calls, and actions handle long tasks with feedback and cancellation. Alongside these, the tf2 library tracks how the robot's coordinate frames relate to one another over time. Learn these well and the rest of ROS 2 becomes far easier to follow.

This guide is aimed at undergraduates and postgraduates using ROS 2 for coursework, a group design project or a dissertation. It sticks to the official ROS 2 Lyrical Luth documentation. If a lecturer's slides and a blog post disagree, you can check the source text in the ROS 2 documentation base.

Start with the graph, not the code

The documentation describes a node as a participant in the ROS 2 graph that communicates with other nodes through a client library, such as rclcpp for C++ or rclpy for Python. Nodes may sit in the same process, in separate processes or on separate machines. They connect through discovery. When a node starts, it advertises itself to other nodes on the same ROS domain, keeps advertising periodically, and announces when it goes offline.

That domain is set by the ROS_DOMAIN_ID environment variable. All nodes use domain 0 by default. Nodes on the same domain can discover each other freely, and nodes on different domains cannot. The docs give a safe range of 0 to 101 inclusive. This is useful in a shared university lab: give each group its own number so that your teleop node doesn't steer the robot on the next bench.

Nodes can also expose parameters, configurable values that change behaviour at run time without recompiling. For a project you will typically keep them in a YAML file and load it at start-up with ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>. While the node runs, ros2 param list and ros2 param get <node_name> <parameter_name> let you inspect them. Lyrical also lets ros2 param get <param name> query a parameter on every node at once.

Three ways for nodes to communicate

According to the interfaces overview, nodes typically communicate through topics (continuous data streams), services (synchronous request/response for short tasks) and actions (long-running tasks with feedback). Each interface is defined in a .msg, .srv or .action file.

Topics

Topics form a strongly typed, anonymous publish/subscribe system, which the documentation compares to a device bus in electrical engineering. Any publisher and subscriber on the same topic name can communicate, and there can be zero or more of each. Because subscribers do not care who sent the data, tools can join without disturbing anything. The docs point out that ros2 bag record simply creates a new subscriber to the topics you choose.

Services

A service is a remote procedure call. The documentation's example is a server that receives two numbers a and b, adds them and returns sum. Services should return quickly, because the client is usually waiting. You should run only one service server per name, while any number of clients may call it.

Actions

An action is a long-running call with feedback that can be cancelled or pre-empted. The docs illustrate it with a Fibonacci server that sends partial sequences as feedback before returning the full result. Each goal has a unique ID, so a server can keep a separate state for each goal. The documentation stresses that pre-emption should always be implemented cleanly by action servers.

Choosing the right interface: common student mistakes

  • Using a service for something slow. The docs say services should never be used for longer-running processes, especially ones that might need to be pre-empted. Use an action instead.
  • Using an action for a quick query. Actions carry overhead in setting up and monitoring the connection. For a short call, such as querying a node's state or a quick inverse kinematics calculation, a service is the better choice.
  • Polling a service for sensor data. Continuous data such as sensor readings and robot state belongs on a topic.
  • Starting two servers with the same name. For both services and actions, the docs state it is undefined which server will receive client requests.
  • Making services depend on state. The guidelines say services should never change or depend on state, to avoid unwanted side effects for other nodes.

Coordinate frames with tf2

tf2 is the transform library, which keeps track of multiple coordinate frames over time. It stores the relationships between frames in a tree buffered in time, so you can transform points or vectors between any two frames at any moment. It can ask, for example, where the head frame was relative to the world frame 5 seconds ago. It also works across a distributed system, so frame information is available to every ROS 2 component on any computer.

One subtlety is easy to get wrong. The docs explain that transforms published in geometry_msgs/msg/Transform represent the frame formulation, which is the inverse of transforming data from one frame to another. When you query, lookupTransform takes a source frame and a target frame. The documentation recommends the transform<T>(target_frame, ...) methods where possible, because they read the source frame_id from the data and write the target frame_id for you.

Static transforms for sensors that never move

Static transforms define the relationship between a robot base and its sensors or other non-moving parts. The docs give the example of reasoning about laser scan measurements in a frame at the centre of the laser scanner. Rather than coding a broadcaster, use the tool that tf2_ros provides:

ros2 run tf2_ros static_transform_publisher --x 0 --y 0 --z 1 --yaw 0 --pitch 0 --roll 0 --frame-id world --child-frame-id mystaticturtle

This publishes a 1-metre offset along z with no rotation between world and mystaticturtle. The quaternion form replaces the angles with --qx 0 --qy 0 --qz 0 --qw 1. Roll, pitch and yaw rotate about the x, y and z axes respectively, and the same tool can be declared as a node in XML, YAML or Python launch files.

A turtlesim lab session to test yourself

  1. Install turtlesim (sudo apt install ros-lyrical-turtlesim), then start it with ros2 run turtlesim turtlesim_node and the keyboard controller with ros2 run turtlesim turtle_teleop_key.
  2. Run ros2 node info /turtlesim. It lists the node's publishers, subscribers, services and actions, whereas ros2 node list only shows names.
  3. Measure a stream with ros2 topic hz /turtle1/pose.
  4. Inspect an action definition with ros2 interface show turtlesim_msgs/action/RotateAbsolute. The sections are the goal (theta), the result (delta) and the feedback (remaining).
  5. Send a goal with ros2 action send_goal /turtle1/rotate_absolute turtlesim_msgs/action/RotateAbsolute "{theta: -1.57}" --feedback and watch the feedback arrive.
  6. Run the tf2 follow demo with ros2 launch turtle_tf2_py turtle_tf2_demo.launch.py, then check a frame with ros2 run tf2_ros tf2_echo world turtle1.

Revision tip

If you can explain why a waypoint navigation request is an action, a battery reading is a topic and a reset command is a service, you have understood the core of the documentation's guidance.

Check a concept against the official text

Kopik's ROS 2 base indexes the Lyrical Luth concepts and tutorials and cites the passage behind every answer. It is handy for revision or for checking a claim before it goes into your dissertation. Try “What's the actual difference between a Reentrant and a Mutually exclusive callback group in rclcpp?”

More expert bases are listed in the catalogue. Note that this one covers core ROS 2 only, not Nav2 or MoveIt 2.

Frequently asked questions

What is a node in ROS 2?

A node is a participant in the ROS 2 graph that uses a client library to communicate with other nodes. It is typically the unit of computation, and each node should do one logical thing.

Can a ROS 2 topic have several publishers?

Yes. The documentation says there may be zero or more publishers and zero or more subscribers on any topic, and ros2 topic info shows how many are connected.

Why does a second turtlesim window open when I remap the node name?

Each call to ros2 run turtlesim turtlesim_node starts a new node with its own window. Remapping __node names that new node; it does not rename the /turtlesim node already running.

What does ROS_DOMAIN_ID do?

It separates logical networks on the same physical network. Nodes on the same domain discover each other, and nodes on different domains do not. The default is 0, and the docs recommend a value between 0 and 101 inclusive.

Is tf2 only for mobile robots?

No. The documentation's examples include world, base, gripper and head frames, so it applies to arms and humanoids as much as to mobile bases. Any system with several coordinate frames that change over time can use it.

Get the Kopik newsletter

New knowledge bases, RAG guides and product news. One email every week or two, unsubscribe in one click.

By subscribing you agree to receive our newsletter. We never share your address.