Chapter 3 Summary: Python Integration with rclpy
Generated by: Summary workflow Time to Review: 5-7 minutes Covers: Key concepts, mental models, and common mistakes
Key Takeaways
1. rclpy is the Python Interface to ROS 2
- rclpy allows you to create ROS 2 nodes in Python
- Nodes inherit from the
Nodeclass - Every node must call
rclpy.spin()to stay alive and process callbacks
2. Publishers Send Velocity Commands
- Create publishers for
Twistmessages to/cmd_vel - Twist contains linear velocity (m/s) and angular velocity (rad/s)
- Publish repeatedly in a control loop (10 Hz typical), not just once
3. Control Loops Must Run Repeatedly
- Use timers to create periodic callbacks (every 0.1 seconds for 10 Hz)
- Publish velocity commands in each callback
- Robot receives repeated commands and moves smoothly
4. Parameters Configure Behavior at Runtime
- Declare parameters with default values
- Read parameter values in code
- React to parameter changes without restarting
5. Actions Are for Goal-Reaching Tasks
- Actions send goals with feedback and results
- Action servers execute goals and send progress
- Use actions for navigation, manipulation, long-running tasks
6. Python Control Integrates with Chapter 2 Robots
- URDF defines robot structure (Chapter 2)
- Python code publishes commands (Chapter 3)
- Gazebo receives commands and moves robot
Mental Models
Model 1: Node as an Active Process
Node = Executable Process
┌─────────────────────────────┐
│ VelocityController Node │
├─────────────────────────────┤
│ Publisher: /cmd_vel │
│ Timer: 0.1 sec (10 Hz) │
│ Callback: timer_callback() │
│ │
│ While spinning: │
│ Every 0.1 sec: │
│ - Create Twist message │
│ - Publish to /cmd_vel │
│ - Gazebo reads message │
│ - Robot moves │
└─────────────────────────────┘
Model 2: Control Loop as Repeated Publication
WRONG (One-shot):
Publish Twist -> Robot moves once -> Stop
RIGHT (Control loop):
Publish Twist ─┐
Publish Twist ─┼─> Robot moves smoothly
Publish Twist ─┤ (receives repeated commands)
Publish Twist ─┘
Model 3: Parameter-Based Configuration
Parameter Server
┌──────────────────────┐
│ max_velocity: 1.0 │
│ robot_name: "arm1" │
│ enable_logging: true │
└──────────────────────┘
│ read
v
Python Node reads at runtime
│
v
Behavior changes (without recompile)
Model 4: Action Pattern for Goal-Seeking
ACTION PATTERN:
Client Server
│ │
├─ Send Goal: "Move to 10" ─>│
│ │
│<──── Feedback: "at 3" ────┤
│<──── Feedback: "at 5" ────┤
│<──── Feedback: "at 8" ────┤
│ │
│<─── Result: "Success" ────┤
│ │
Concept Map
rclpy (Python Interface)
├─ Node (Executable process)
│ ├─ Publisher (sends messages to topics)
│ │ └─ Twist (velocity message: linear + angular)
│ ├─ Timer (periodic callbacks)
│ │ └─ Control loop (e.g., 10 Hz)
│ ├─ Parameter (configuration value)
│ │ └─ Declare, Read, React to changes
│ └─ Action (goal-oriented communication)
│ ├─ Action Server (executes goals)
│ ├─ Action Client (sends goals)
│ └─ Feedback + Result (progress + completion)
│
└─ Integration with Chapter 2
└─ Python code controls URDF robots in Gazebo
Common Mistakes and How to Avoid Them
Mistake 1: Publishing Velocity Once Instead of in a Loop
Problem:
msg = Twist()
msg.linear.x = 1.0
publisher.publish(msg) # Publish once
# Robot doesn't move sustainably
Fix: Use a timer callback:
self.timer_ = self.create_timer(0.1, self.timer_callback)
def timer_callback(self):
msg = Twist()
msg.linear.x = 1.0
self.publisher_.publish(msg) # Publish every 0.1 sec
Mistake 2: Forgetting to Declare Parameter Before Using It
Problem:
# Directly try to read parameter
value = self.get_parameter('max_velocity').value
# Parameter doesn't exist -> ERROR
Fix: Declare first:
self.declare_parameter('max_velocity', 1.0)
value = self.get_parameter('max_velocity').value
Mistake 3: Publishing to Wrong Topic
Problem:
publisher = self.create_publisher(Twist, '/my_topic', 10)
# Gazebo listens to /cmd_vel, not /my_topic
# Robot doesn't respond
Fix: Use standard topic:
publisher = self.create_publisher(Twist, '/cmd_vel', 10)
Mistake 4: Not Spinning the Node
Problem:
def main():
rclpy.init()
node = VelocityController()
# Missing: rclpy.spin(node)
node.destroy_node()
# Node exits immediately
Fix: Add spin():
def main():
rclpy.init()
node = VelocityController()
rclpy.spin(node) # Keep node alive
node.destroy_node()
Mistake 5: Confusing Service (Ch1) with Action (Ch3)
Wrong Use:
- Service: "Navigate to location" (expects immediate response)
- Action: "Print hello" (doesn't need feedback)
Right Use:
- Service: "Get robot battery level" (one-shot query)
- Action: "Navigate to location" (long-running, needs feedback)
Mistake 6: Not Handling Parameter Changes
Problem:
# Read parameter once in __init__
max_vel = self.get_parameter('max_velocity').value
# If parameter changes at runtime, code doesn't know
Fix: Read parameter in callback:
def timer_callback(self):
max_vel = self.get_parameter('max_velocity').value
# Reads fresh value each time
Quick Reference: Common Patterns
Creating and Using a Publisher
# In __init__:
self.publisher_ = self.create_publisher(Twist, '/cmd_vel', 10)
# In callback:
msg = Twist()
msg.linear.x = 0.5
self.publisher_.publish(msg)
Using Parameters
# In __init__:
self.declare_parameter('max_velocity', 1.0)
# In callback:
max_vel = self.get_parameter('max_velocity').get_parameter_value().double_value
Control Loop with Timer
# In __init__:
self.timer_ = self.create_timer(0.1, self.timer_callback) # 10 Hz
# Callback runs every 0.1 seconds
def timer_callback(self):
# Publish commands
self.publisher_.publish(msg)
Comparison: Chapter 1 vs Chapter 2 vs Chapter 3
| Aspect | Ch1: ROS 2 Basics | Ch2: URDF | Ch3: Python |
|---|---|---|---|
| What: | How ROS 2 works | Robot description | Robot control |
| Learn: | Nodes, topics, services | Links, joints, physics | Publishers, parameters, actions |
| Build: | Node examples | URDF files | Python nodes |
| Use: | Understand communication | Describe robots | Control robots |
| Integration: | Foundation for all | Defines robot structure | Uses Chapter 2 robots |
What You Can Now Do
✅ Write Python ROS 2 nodes that control robots ✅ Publish velocity commands to make robots move ✅ Create control loops at fixed frequency (10 Hz) ✅ Configure code using parameters (runtime changes) ✅ Implement goal-reaching behaviors (actions) ✅ Integrate Python control with URDF robots (Chapter 2) ✅ Debug node communication using ROS 2 CLI tools
What Comes Next
Advanced Topics (Future Modules)
- Custom message types (beyond standard Twist)
- Launch files for multi-node systems
- Sensor integration (cameras, lidar, IMU)
- Real robot deployment and safety
Applications
- Mobile robot navigation
- Robot arm manipulation
- Autonomous systems
- Sensor-based behaviors
Next Chapter (If Available)
- Advanced ROS 2 patterns
- Multi-robot coordination
- Real robot integration
Review Checklist
Before moving to next material, verify you:
- Understand rclpy node structure and inheritance
- Can create publishers and send Twist messages
- Know why control loops must run repeatedly
- Can declare and read parameters
- Understand difference between service and action
- Know when to use each communication pattern
- Can implement simple velocity controllers
- Completed all 3 exercises
If you checked all boxes, you've mastered Chapter 3!
Practice Problems (Optional)
Try these without references:
- Easy: Write pseudocode for a node that publishes constant forward velocity
- Medium: Explain why
rclpy.spin()is necessary - Medium: Design a parameter-based controller that limits robot speed
- Hard: When would you use an action instead of a service? Give 2 examples
Resources for Deeper Learning
Official ROS 2 Documentation
ROS 2 Command Line Tools
ros2 node list- List all nodesros2 topic list- List all topicsros2 topic echo /cmd_vel- Monitor topic messagesros2 param list- List all parametersros2 param set- Change parameter value
Next Steps
- Immediate: Review the exercises and run your solutions
- Practice: Modify code examples to experiment
- Challenge: Create a robot that moves in a specific pattern
- Next Chapter: Advanced ROS 2 topics or real robot integration
Summary Status: Complete Last Updated: 2025-11-30 Chapter Completion: Ready for final quality evaluation