Bird
Raised Fist0
ROSframework~10 mins

Creating a subscriber node in ROS - Visual Walkthrough

Choose your learning style10 modes available
Concept Flow - Creating a subscriber node
Start Node Initialization
↓
Initialize ROS Node
↓
Create Subscriber
↓
Wait for Messages
↓
Callback Function Triggered
↓
Process Message
↓
Continue Waiting for Messages
↩Loop back to Wait for Messages
This flow shows how a ROS subscriber node starts, waits for messages, and processes each message via a callback function.
Execution Sample
ROS
import rclpy
from std_msgs.msg import String

def callback(msg):
    print(f'Received: {msg.data}')

rclpy.init()
node = rclpy.create_node('listener')
node.create_subscription(String, 'chatter', callback, 10)
rclpy.spin(node)
rclpy.shutdown()
This code creates a ROS subscriber node that listens to the 'chatter' topic and prints received string messages.
Execution Table
StepActionEvaluationResult
1Call rclpy.init()Initialize ROS client libraryROS initialized
2Create node named 'listener'Node createdNode object ready
3Create subscription to 'chatter' topicSubscription set with callbackSubscriber listens for messages
4Call rclpy.spin(node)Wait for messagesNode waits and processes incoming messages
5Message received on 'chatter'Callback function called with messagePrints 'Received: <message data>'
6Continue spinningWait for next messageLoop back to step 4
7Shutdown calledClean up resourcesROS client library shutdown
ExitNo more messages or shutdown calledExit spin loopNode stops running
💡 Node stops when shutdown is called or process is terminated
Variable Tracker
VariableStartAfter InitAfter Node CreationAfter SubscriptionDuring SpinAfter Shutdown
rclpyNot initializedInitializedInitializedInitializedInitializedShutdown
nodeNoneNoneNode objectNode objectNode objectNode object (inactive)
subscriptionNoneNoneNoneSubscription objectActiveInactive
Key Moments - 3 Insights
Why does the callback function run only after rclpy.spin(node) is called?
Because rclpy.spin(node) starts the loop that listens for incoming messages and triggers the callback when a message arrives, as shown in execution_table step 4 and 5.
What happens if you create the subscription but do not call rclpy.spin(node)?
The node will not process any messages because the spin loop is not running to receive and dispatch messages, so the callback never triggers (see execution_table step 3 vs step 4).
Why do we call rclpy.shutdown() at the end?
To cleanly stop the ROS client library and release resources, preventing errors or hanging processes, as shown in execution_table step 7.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what happens at step 5?
AROS client library is initialized
BThe callback function is called with the received message
CThe node is created
DThe node shuts down
💡 Hint
Check the 'Action' and 'Result' columns at step 5 in the execution_table
At which step does the node start waiting for messages?
AStep 6
BStep 2
CStep 4
DStep 7
💡 Hint
Look for when rclpy.spin(node) is called in the execution_table
If you skip calling rclpy.shutdown(), what is the likely effect?
AResources may not be released properly
BThe node will never receive messages
CThe callback will not run
DThe node will create multiple subscriptions
💡 Hint
Refer to the explanation in key_moments about shutdown and execution_table step 7
Concept Snapshot
ROS Subscriber Node Quick Guide:
- Initialize ROS with rclpy.init()
- Create a node with rclpy.create_node('name')
- Create a subscription with node.create_subscription(msg_type, topic, callback, qos)
- Use rclpy.spin(node) to wait and process messages
- Shutdown cleanly with rclpy.shutdown()
Full Transcript
This visual execution guide shows how to create a subscriber node in ROS. First, the ROS client library is initialized. Then, a node named 'listener' is created. Next, a subscription to the 'chatter' topic is set up with a callback function that prints received messages. The node enters a spin loop to wait for messages. When a message arrives, the callback runs and processes it. This loop continues until shutdown is called, which cleans up resources and stops the node. Key points include that the callback only runs during spinning, and shutdown is important for clean exit.

Practice

(1/5)
1.

What is the main purpose of a subscriber node in ROS?

easy
A. To send messages to other nodes
B. To listen and react to messages published on a topic
C. To create new topics for communication
D. To store messages permanently

Solution

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

    A subscriber node listens to messages sent on a specific topic in ROS.
  2. Step 2: Compare options with the subscriber role

    Only To listen and react to messages published on a topic describes listening and reacting to messages, which matches the subscriber's purpose.
  3. Final Answer:

    To listen and react to messages published on a topic -> Option B
  4. Quick Check:

    Subscriber node = listens to messages [OK]
Hint: Subscriber nodes always listen to topics, not send [OK]
Common Mistakes:
  • Confusing subscriber with publisher
  • Thinking subscriber creates topics
  • Assuming subscriber stores messages permanently
2.

Which of the following is the correct way to create a subscriber in ROS 2 Python?

node.create_subscription(____, 'chatter', callback, 10)
easy
A. std_msgs.msg.String
B. String
C. std_msgs/String
D. string

Solution

  1. Step 1: Identify the correct message type import

    In ROS 2 Python, message types are imported as modules, e.g., std_msgs.msg.String.
  2. Step 2: Match the correct syntax for create_subscription

    The first argument must be the full message type class, so std_msgs.msg.String is correct.
  3. Final Answer:

    std_msgs.msg.String -> Option A
  4. Quick Check:

    Message type = std_msgs.msg.String [OK]
Hint: Use full message type path with .msg in ROS 2 Python [OK]
Common Mistakes:
  • Using just 'String' without module path
  • Using slash notation like 'std_msgs/String'
  • Using lowercase 'string' instead of class name
3.

Given this ROS 2 Python subscriber code snippet, what will be printed when a message with data 'Hello' arrives?

def callback(msg):
    print(f'Received: {msg.data}')

node.create_subscription(std_msgs.msg.String, 'chatter', callback, 10)
medium
A. Received: msg.data
B. Hello
C. Received: Hello
D. msg.data

Solution

  1. Step 1: Understand the callback function

    The callback prints 'Received: ' followed by the message's data attribute.
  2. Step 2: Substitute the message data value

    When the message data is 'Hello', the print outputs 'Received: Hello'.
  3. Final Answer:

    Received: Hello -> Option C
  4. Quick Check:

    Prints 'Received: ' + msg.data [OK]
Hint: Callback prints 'Received: ' plus message data [OK]
Common Mistakes:
  • Printing just the data without prefix
  • Printing the variable name instead of its value
  • Confusing string formatting syntax
4.

What is wrong with this ROS 2 Python subscriber code?

def callback(msg):
    print(msg.data)

node.create_subscription(std_msgs.msg.String, 'chatter', callback())
medium
A. Missing message type in create_subscription
B. Queue size argument is missing but required
C. Topic name should be a variable, not a string
D. Callback is called immediately instead of passed as a function

Solution

  1. Step 1: Check how callback is passed

    The code uses callback() which calls the function immediately instead of passing the function reference.
  2. Step 2: Understand correct callback usage

    We must pass callback without parentheses so it is called on message arrival.
  3. Final Answer:

    Callback is called immediately instead of passed as a function -> Option D
  4. Quick Check:

    Pass callback function, not call it [OK]
Hint: Pass callback without () to create_subscription [OK]
Common Mistakes:
  • Adding parentheses to callback in subscription
  • Omitting queue size argument (optional in some versions)
  • Using variable instead of string for topic name
5.

You want to create a subscriber node that listens to the topic 'sensor_data' and prints only messages where the data is greater than 10. Which callback function correctly implements this?

def callback(msg):
    # Fill in the condition
    if ____:
        print(f"Data: {msg.data}")
hard
A. msg.data > 10
B. msg.data >= 10
C. msg.data < 10
D. msg.data == 10

Solution

  1. Step 1: Understand the requirement

    We want to print messages only if data is greater than 10, so the condition must check msg.data > 10.
  2. Step 2: Compare options with condition

    msg.data > 10 matches exactly 'greater than 10'. Others check equal or less, which do not meet the requirement.
  3. Final Answer:

    msg.data > 10 -> Option A
  4. Quick Check:

    Condition for data > 10 is msg.data > 10 [OK]
Hint: Use > 10 to filter messages with data above 10 [OK]
Common Mistakes:
  • Using >= instead of > changes condition
  • Using < or == prints wrong messages
  • Not adding any condition prints all messages
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