Bird
Raised Fist0
ROSframework~5 mins

Creating a publisher node in ROS

Choose your learning style10 modes available
Introduction

A publisher node sends messages to other parts of a robot system. It helps share information like sensor data or commands.

When you want to send sensor readings to other nodes.
When you need to broadcast robot status updates.
When controlling a robot by sending commands to motors.
When sharing data like camera images or GPS coordinates.
When multiple parts of a robot need to communicate continuously.
Syntax
ROS
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class MinimalPublisher(Node):
    def __init__(self):
        super().__init__('minimal_publisher')
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        timer_period = 0.5  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0

    def timer_callback(self):
        msg = String()
        msg.data = f'Hello, world! {self.i}'
        self.publisher_.publish(msg)
        self.get_logger().info(f'Publishing: {msg.data}')
        self.i += 1

def main(args=None):
    rclpy.init(args=args)
    minimal_publisher = MinimalPublisher()
    rclpy.spin(minimal_publisher)
    minimal_publisher.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

The create_publisher method sets up the topic and message type.

The timer_callback sends messages regularly.

Examples
This example shows a publisher created even if no one listens yet.
ROS
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class PublisherEmptyTopic(Node):
    def __init__(self):
        super().__init__('publisher_empty_topic')
        # Publishing to a topic with no subscribers yet
        self.publisher_ = self.create_publisher(String, 'empty_topic', 10)
        self.get_logger().info('Publisher created for empty_topic')

if __name__ == '__main__':
    rclpy.init()
    node = PublisherEmptyTopic()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
This example publishes just one message and stops.
ROS
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class SingleMessagePublisher(Node):
    def __init__(self):
        super().__init__('single_message_publisher')
        self.publisher_ = self.create_publisher(String, 'single_msg_topic', 10)
        msg = String()
        msg.data = 'Only one message'
        self.publisher_.publish(msg)
        self.get_logger().info('Published one message')

if __name__ == '__main__':
    rclpy.init()
    node = SingleMessagePublisher()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
This example publishes three messages then stops sending more.
ROS
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class PublisherEndMessage(Node):
    def __init__(self):
        super().__init__('publisher_end_message')
        self.publisher_ = self.create_publisher(String, 'end_topic', 10)
        self.i = 0
        self.timer = self.create_timer(1.0, self.timer_callback)

    def timer_callback(self):
        if self.i < 3:
            msg = String()
            msg.data = f'Message {self.i}'
            self.publisher_.publish(msg)
            self.get_logger().info(f'Publishing: {msg.data}')
            self.i += 1
        else:
            self.get_logger().info('No more messages to publish')

if __name__ == '__main__':
    rclpy.init()
    node = PublisherEndMessage()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
Sample Program

This program creates a publisher node that sends a message every second. It prints what it sends to the console.

ROS
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class MinimalPublisher(Node):
    def __init__(self):
        super().__init__('minimal_publisher')
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        self.i = 0
        self.timer = self.create_timer(1.0, self.timer_callback)

    def timer_callback(self):
        msg = String()
        msg.data = f'Hello, world! {self.i}'
        self.publisher_.publish(msg)
        self.get_logger().info(f'Publishing: {msg.data}')
        self.i += 1

def main(args=None):
    rclpy.init(args=args)
    minimal_publisher = MinimalPublisher()
    rclpy.spin(minimal_publisher)
    minimal_publisher.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()
OutputSuccess
Important Notes

Publishing messages regularly uses a timer callback to automate sending.

Time complexity is O(1) for each publish call.

Common mistake: forgetting to call rclpy.spin() so the node keeps running.

Use a publisher node when you want to send data out; use a subscriber node to receive data.

Summary

A publisher node sends messages on a topic to share information.

Use create_publisher to set up the topic and message type.

Use a timer callback to send messages regularly.

Practice

(1/5)
1. What is the main purpose of a publisher node in ROS?
easy
A. To store data in a database
B. To receive messages from other nodes
C. To compile the ROS package
D. To send messages on a topic to share information

Solution

  1. Step 1: Understand the role of a publisher node

    A publisher node sends messages to other nodes by publishing on a topic.
  2. Step 2: Compare options with the role

    Only To send messages on a topic to share information describes sending messages on a topic, which matches the publisher's role.
  3. Final Answer:

    To send messages on a topic to share information -> Option D
  4. Quick Check:

    Publisher node = sends messages [OK]
Hint: Publisher nodes send messages, subscribers receive them [OK]
Common Mistakes:
  • Confusing publisher with subscriber
  • Thinking publisher stores data
  • Assuming publisher compiles code
2. Which of the following is the correct way to create a publisher in a ROS2 Python node?
easy
A. self.createPublisher(String, 'topic_name', 10)
B. self.create_publisher(String, 'topic_name', 10)
C. create_publisher(String, 'topic_name', 10)
D. self.create_publisher('topic_name', String, 10)

Solution

  1. Step 1: Recall ROS2 Python publisher syntax

    The method is called on the node instance as self.create_publisher, with message type first, then topic name, then queue size.
  2. Step 2: Check each option's syntax

    self.create_publisher(String, 'topic_name', 10) matches the correct method name and argument order. self.createPublisher(String, 'topic_name', 10) has wrong method name casing. create_publisher(String, 'topic_name', 10) misses self. self.create_publisher('topic_name', String, 10) swaps argument order.
  3. Final Answer:

    self.create_publisher(String, 'topic_name', 10) -> Option B
  4. Quick Check:

    Correct method and argument order = self.create_publisher(String, 'topic_name', 10) [OK]
Hint: Use self.create_publisher with message type first [OK]
Common Mistakes:
  • Wrong method name casing
  • Missing self when calling method
  • Swapping topic name and message type
3. Given this ROS2 Python publisher code snippet, what will be printed when the timer callback runs?
def timer_callback(self):
    msg = String()
    msg.data = 'Hello ROS'
    self.publisher.publish(msg)
    print('Published:', msg.data)
medium
A. Published: Hello ROS
B. Hello ROS
C. Published: msg.data
D. Error: msg.data undefined

Solution

  1. Step 1: Analyze the print statement

    The print outputs the string 'Published:' followed by the value of msg.data, which is 'Hello ROS'.
  2. Step 2: Confirm msg.data value

    msg.data is assigned 'Hello ROS' before publishing, so the print shows 'Published: Hello ROS'.
  3. Final Answer:

    Published: Hello ROS -> Option A
  4. Quick Check:

    Print shows 'Published:' plus msg.data [OK]
Hint: Print uses string plus msg.data value [OK]
Common Mistakes:
  • Printing variable name instead of value
  • Assuming print shows only msg.data
  • Confusing msg.data with undefined
4. Identify the error in this ROS2 Python publisher node snippet:
def __init__(self):
    self.publisher = self.create_publisher(String, 'chatter', 10)

def timer_callback(self):
    msg = String()
    msg.data = 'Hello'
    self.publisher.publish(msg)

self.timer = self.create_timer(1.0, timer_callback)
medium
A. timer_callback is missing 'self' parameter
B. create_publisher is called with wrong arguments
C. Timer is created outside the class constructor
D. msg.data is assigned incorrectly

Solution

  1. Step 1: Check code structure and indentation

    The self.timer = self.create_timer(1.0, timer_callback) line lacks indentation and appears outside __init__ at class level, where 'self' is undefined, causing NameError.
  2. Step 2: Verify other options

    A: timer_callback includes 'self'. B: create_publisher args are correct (type, topic, qos). D: msg.data = 'Hello' is valid.
  3. Final Answer:

    Timer is created outside the class constructor -> Option C
  4. Quick Check:

    self assignments must be inside instance methods like __init__ [OK]
Hint: Create timers inside __init__ with self.create_timer(1.0, self.timer_callback) [OK]
Common Mistakes:
  • Omitting 'self' in method parameters
  • Misordering create_publisher arguments
  • Creating timer outside class context
5. You want to create a ROS2 publisher node that publishes integers incrementing every second starting from 0. Which code snippet correctly implements this behavior?
hard
A. class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 0 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(self): msg = Int32() msg.data = self.i self.publisher.publish(msg) self.i += 1
B. class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 0 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(): msg = Int32() msg.data = self.i self.publisher.publish(msg) self.i += 1
C. class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 0 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(self): msg = Int32() msg.data = 0 self.publisher.publish(msg) self.i += 1
D. class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 1 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(self): msg = Int32() msg.data = self.i self.publisher.publish(msg) self.i = 0

Solution

  1. Step 1: Check timer_callback method signatures

    Options A and C define timer_callback(self); B omits 'self', causing AttributeError on self.i and self.publisher.
  2. Step 2: Verify increment logic

    class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 0 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(self): msg = Int32() msg.data = self.i self.publisher.publish(msg) self.i += 1 initializes self.i=0 and does self.i += 1 after publishing, yielding 0,1,2,... class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 0 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(self): msg = Int32() msg.data = 0 self.publisher.publish(msg) self.i += 1 always publishes 0. class IntPublisher(Node): def __init__(self): super().__init__('int_publisher') self.publisher = self.create_publisher(Int32, 'numbers', 10) self.i = 1 self.timer = self.create_timer(1.0, self.timer_callback) def timer_callback(self): msg = Int32() msg.data = self.i self.publisher.publish(msg) self.i = 0 publishes 1 then sets self.i=0 repeatedly.
  3. Final Answer:

    self.i = 0; msg.data = self.i; self.i += 1 -> Option A
  4. Quick Check:

    self.i starts 0, increment after publish [OK]
Hint: Use self.i and increment after publishing in timer callback [OK]
Common Mistakes:
  • Missing 'self' in timer_callback
  • Not incrementing the counter
  • Resetting counter inside callback
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard