How to create a simple Publisher Node with C++ – ROS

In this tutorial, we’ll learn how to create a simple ROS node using C++ that sends text messages to a topic.
This is one of the fundamental skills in the ROS ecosystem — allowing different programs (called nodes) to talk to each other via topics.

🔍  What is a ROS Node and a Topic?

In ROS (Robot Operating System), software is organized into small, independent processes called nodes.
Nodes communicate by publishing and subscribing to topics — named channels that carry specific types of data.

For example:

  • A camera node might publish images on /camera/image_raw

  • A motor controller might subscribe to /cmd_vel to receive movement commands.

Nodes and topics decouple your software, so different parts of your robot can evolve independently and work together via message passing.

🚀 What We’ll Build

We’ll:

  • Create a new C++ package inside an existing ROS workspace

  • Write a publisher node in C++

  • Build and run it

  • Monitor its output via ROS command-line tools

The node will:

  • Publish a string message on a topic named /chatter

  • Run in a loop at a fixed frequency

  • Display a counter alongside the message

📦 Prerequisite: A ROS Workspace

If you haven’t created a ROS workspace yet, follow this clear tutorial first:
How to Create a ROS2 Workspace

Once your workspace is ready and sourced, continue from here.

📦 Create a New Package

Inside your workspace’s src folder:

				
					cd ~/ros_cpp_ws/src
catkin_create_pkg tutorial_publisher roscpp std_msgs

				
			

Explanation:

  • tutorial_publisher is the package name.

  • roscpp is the C++ client library for ROS.

  • std_msgs provides standard message types like strings and numbers.

Now your project structure looks like:

📄 Write the Publisher Node

Let’s create a new C++ file inside src/:

				
					cd ~/ros_cpp_ws/src/tutorial_publisher/src
touch simple_publisher.cpp

				
			

Open it in your text editor, and paste the following code:

				
					#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char **argv)
{
    ros::init(argc, argv, "simple_publisher_cpp");

    ros::NodeHandle nh;

    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10);

    ros::Rate loop_rate(10);

    int counter = 0;

    while (ros::ok())
    {
        std_msgs::String msg;

        std::stringstream ss;
        ss << "Hello world " << counter;
        msg.data = ss.str();

        pub.publish(msg);

        ros::spinOnce();

        loop_rate.sleep();

        ++counter;
    }

    return 0;
}

				
			

🔍 Code Explained Step by Step

Let’s carefully go through this code line by line.

Include Required Headers

				
					#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

				
			
  • ros/ros.h → core ROS C++ library.
    Provides functions for initializing ROS, creating publishers, setting rates, etc.

  • std_msgs/String.h → defines a simple message type for sending strings.

  • <sstream> → C++ standard library class for creating string streams.
    Used to format the message string with a counter.

Main Function

				
					int main(int argc, char **argv)

				
			

This is the starting point of any C++ program.
The parameters argc and argv are used by ROS to process command-line arguments.

Initialize the ROS Node

				
					ros::init(argc, argv, "simple_publisher_cpp");

				
			
  • Initializes the ROS node.

  • "simple_publisher_cpp" is the unique name of this node within the ROS system.

Create a NodeHandle

				
					ros::NodeHandle nh;

				
			
  • A NodeHandle is your connection to the ROS network.

  • You use it to create publishers, subscribers, and interact with the parameter server.

Define a Publisher

				
					ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10);

				
			
  • Creates a publisher object called pub.

  • It will send messages on a topic named "chatter" with message type std_msgs::String.

  • The 10 is the queue size: how many messages to buffer if the subscriber is too slow.

Set the Loop Rate

				
					ros::Rate loop_rate(10);

				
			
  • Controls the frequency of the loop.

  • 10 means the loop runs 10 times per second (10Hz).

Initialize a Counter

				
					int counter = 0;

				
			
  • Tracks the number of messages published.

  • Added to the message text so each message is unique.

Main Publishing Loop

				
					while (ros::ok())

				
			
  • Runs as long as ROS is active.

  • Exits cleanly if the node is shut down with Ctrl+C or rosnode kill.

Inside the loop:

Create a Message

				
					std_msgs::String msg;

				
			
  • Declares a message object of type std_msgs::String.

Prepare the Message Text

				
					std::stringstream ss;
ss << "Hello world " << counter;
msg.data = ss.str();

				
			
  • Uses a stringstream to build the message text by appending the counter.

  • Assigns the final string to the message’s data field.

Publish the Message

				
					pub.publish(msg);

				
			

Sends the message out on the "chatter" topic.

Process ROS Callbacks

				
					ros::spinOnce();

				
			
  • Checks for any incoming messages or service callbacks.

  • Not strictly necessary for a simple publisher with no subscribers, but good practice.

Sleep to Maintain Loop Rate

				
					loop_rate.sleep();

				
			

Waits to ensure the loop runs exactly at 10Hz.

Increment the Counter

				
					++counter;

				
			

Increases the counter by 1 for the next message.

Exit the Program

				
					return 0;

				
			

Cleanly exits the program when the loop finishes.

🏗️ Add the Node to CMakeLists.txt

Open your CMakeLists.txt and add:

				
					add_executable(simple_cpp_publisher src/simple_publisher.cpp)

target_link_libraries(simple_cpp_publisher
  ${catkin_LIBRARIES}
)

				
			

This tells CMake how to build your program and link it with ROS libraries.

🛠️ Build the Package

From your workspace root:

				
					cd ~/ros_cpp_ws
catkin_make
source devel/setup.bash

				
			

🚀 Run the Publisher

First, start the ROS master:

				
					roscore

				
			

Then, in a new terminal:

				
					source ~/ros_cpp_ws/devel/setup.bash
rosrun tutorial_publisher simple_cpp_publisher

				
			

📡 Monitor the Topic

In another terminal:

 
				
					rostopic list

				
			

Then, in a new terminal:

				
					/chatter
/rosout

				
			

Check the messages being published:

				
					rostopic echo /chatter

				
			

You’ll see:

				
					data: "Hello world 0"
data: "Hello world 1"
...

				
			

Check topic information:

				
					rostopic info /chatter

				
			

Check message frequency:

				
					rostopic hz /chatter

				
			

It should report a rate around 10Hz.

Want to learn more?

You can find a detailed explaination of the workspace in the "Robotics and ROS 2 - Learn by Doing! Manipulators" course
DISCOUNT
en_US