30% off your first 3 months

Get the deal

Write your first ROS 2 node in Python

by DuckyHelperNov 12, 20265 min read
Robotics

TL;DR:

  • A ROS 2 node is a small program that talks to other nodes by publishing and subscribing to named topics.

  • You will write one node that publishes an integer counter twice a second, then watch it from a second terminal.

  • No robot is needed, only a computer with ROS 2 installed.

Robot software is rarely one big program. A camera driver, a motor controller and a planner each run as their own piece and pass messages to each other. ROS 2 is the most common toolkit for wiring those pieces together, and the smallest useful piece is a node that publishes a number.

What you will build

You will write a node called counter that publishes an integer on a topic named count. It sends one message every 0.5 seconds, so two per second. In a second terminal you will read that topic and check that the numbers go up by one each time.

The point of the exercise is not the counter. It is the shape: a node owns a publisher, a timer drives it, and anything else on the network can listen without the publisher knowing who is there. Once that pattern feels ordinary, sensor drivers, motor controllers and planners all look like variations on it.

What you need

  • A computer with a ROS 2 distribution installed. Follow the official installation page for your operating system, since the exact steps differ between versions.

  • Python 3, which comes with ROS 2 installs.

  • A terminal and a text editor.

  • No wiring and no hardware.

Set up a workspace and a package

ROS 2 code lives in a workspace, a folder with a src directory inside. Each program you write belongs to a package. In every new terminal you first load ROS 2 with the setup script your installation provides (a source command), otherwise the ros2 command is not found.

mkdir -p ~/ros_ws/src
cd ~/ros_ws/src
ros2 pkg create --build-type ament_python first_node
# creates ~/ros_ws/src/first_node/ with setup.py and a first_node/ folder

The code, step by step

Create the file first_node/first_node/counter.py. The node does three things: create a publisher, create a timer, and publish inside the timer's callback.

import rclpy
from rclpy.node import Node
from std_msgs.msg import Int32


class Counter(Node):
    def __init__(self):
        super().__init__('counter')
        self.pub = self.create_publisher(Int32, 'count', 10)
        self.n = 0
        self.timer = self.create_timer(0.5, self.tick)  # every 0.5 s

    def tick(self):
        msg = Int32()
        msg.data = self.n
        self.pub.publish(msg)
        self.get_logger().info(f'published {self.n}')
        self.n += 1


def main():
    rclpy.init()
    node = Counter()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

The 10 in create_publisher is the queue size: how many unsent messages are kept if a subscriber is slow. rclpy.spin keeps the program alive so the timer can fire. Without it, the script would exit at once.

Next, tell the package how to start it. In setup.py, find the entry_points block and set it to the following. Also add <depend>std_msgs</depend> to package.xml.

entry_points={
    'console_scripts': [
        'counter = first_node.counter:main',
    ],
},

Build, run and echo the topic

  1. Build: From ~/ros_ws, run colcon build. Then load the result with source install/setup.bash.

  2. Run the node: Run ros2 run first_node counter. You should see a line such as published 0 twice a second.

  3. Watch it from a second terminal: Open a new terminal, load ROS 2 and your workspace again, then run ros2 topic echo /count. The numbers should climb by one per message.

  4. Check the rate: Run ros2 topic hz /count. It should report close to 2.0 messages per second.

Check that the numbers make sense

The timer period is 0.5 s, so the rate is 1 / 0.5 s = 2 Hz. If you leave the node running for 10 seconds you expect about 10 s × 2 Hz = 20 messages, so the counter should be near 19 or 20 (it starts at 0). If you see a much lower rate, a busy computer or a blocked callback is usually the cause. If echo shows nothing, the two terminals are probably not using the same ROS setup, or the topic names differ by a typo.

Also try stopping the node with Ctrl+C and starting it again. The counter restarts at 0, because the number lives only in that running program. If you wanted it to survive restarts you would have to save it somewhere yourself, which is a useful reminder that a node holds no hidden memory.

One more habit worth building: run ros2 node list and ros2 topic list while the node runs. You should see /counter and /count. These two commands answer most 'is my node even there?' questions, and you will use them constantly on larger robots.

Make it better

  • Write a second node that subscribes to count and logs only the even numbers.

  • Turn the 0.5 into a parameter so you can change the rate without editing code.

  • Replace Int32 with a message that carries a sensor reading and publish a made-up temperature.

A subscriber is the mirror image of this program: it calls create_subscription with the same message type and topic name, plus a function that runs for each message that arrives.

Keep each node small and give it one job. Two small nodes that talk over a topic are easier to test and replace than one large program.

Stay safe

Before this node drives real hardware: This counter is harmless, but nodes that publish motor commands are not. Keep the robot's wheels off the ground for first tests, keep an emergency stop within reach, and make sure the robot stops if messages stop arriving.

Frequently asked questions

Why does ros2 say the package or executable is not found?

You probably did not run the source install/setup.bash step in that terminal, or the entry point name in setup.py does not match the name you pass to ros2 run.

Can I edit the code without rebuilding?

With the option colcon build --symlink-install, edits to Python files take effect on the next run without a rebuild.

Get started

DuckyHelper can
do more

It sees your screen and works in any app you use. Try it for 10 minutes, no card.

Get it for Mac, Windows or Linux

Share

Questions and jobs

Do anything

Ask it a question or hand it a job, in any app.

Doing jobs for you is in early access on Mac. Asking works on Mac, Windows and Linux.