How to write Python ROS2 Node made easy for begginers

Introduction

Robot Operating System 2 (ROS2) represents a significant shift in the design and approach to robotic middleware. It’s tailored for modern robotics applications, offering

  • improved security
  • Reliability
  • Scalability

But this enhancement brought complexity to its structure for starters and introduced a steep learning curve. The key things you need are Python basic syntax understanding.

Starting Point

No understanding of

  • ROS2 python Node Structure
  • How to select a message type
  • Customize ROS2 Node template

Learning outcomes

Easily able to

  • Publish data on different messages
  • Control Publishing messages speed
  • Single-Node Publishing and Subscribing

ROS2 Python Node High Level Strucutre

1. Importing Libraries

import rclpy
from std_msgs import String

2. Minimal Publisher Class

self.publisher = (msgtype ,topic)
self.timer = run callback function 
   every X ms (publish data at a fixed frequency )

3. Call-back function for Publishing

def callback(self){
   msg object create
   msg_data fill in
   publish(msg)

4. Main Function Call

def main(){
rclcpp spin (class)
}
ros2 python nodes

Compiling and Running a ROS2 node

I would recommend you get the publisher – subscriber code and build it according to the wiki. Then we will understand by making changes inside of it.

  1. Writing a Python Node
import rclpy
def main():
    rclpy.create node
    node.publish data

2. To compile, we add it into our package, setup.py

entry_points[node]

3. Build the package

colcon build

4. We run using ros2 run command

ros2 run your_package_name node

ROS2 Python Publisher Node Understanding

Code Snippet requires an understanding of Python concepts, but for utilising a basic template for your purpose, you need to just understand four points.

  1. Defining which message type to work on

Finding ROS2 Message types

ros2 interface show <name> ( example : ros2 interface show sensor_msgs/msg/Imu )

2. message on which you want to communicate

For a string data Message

from std_msgs.msg import String

For Integer data message

from std_msgs.msg import Int32

For IMU sensor data message

from sensor_msgs.msg import Imu

3. Publisher Function call with Topic definition and class member

## For a string message
      self.publisher_ = self.create_publisher(String, 'string_topic', 10)

## For a int32 message
      self.publisher_ = self.create_publisher(Int32, 'int_topic', 10)

## For a imu sensor message
      self.publisher_ = self.create_publisher(Imu, 'imu_topic', 10)

4. We have to fill and publishing message data

Int32 Data

msg = Int32()
msg.data = count
self.publisher_.publish(msg)

String Data

msg = String()
msg.data = "Hi Robotisim"
self.publisher_.publish(msg)

Imu Sensor data ( this is not a general data like above , it is designed for real imu sensor data carriage )

msg = Imu()
msg.header.stamp = self.get_clock().now().to_msg()
msg.angular_velocity.x = 0.0
msg.angular_velocity.y = 0.0
msg.angular_velocity.z = 1.0
msg.linear_acceleration.x = 0.2
msg.linear_acceleration.y = 0.3
msg.linear_acceleration.z = 0.4
self.publisher_.publish(msg)

ROS2 Python Subscriber Node Understanding

  1. The definition of subscriber is dependent on publisher data type and topic name

For a string data type

self.subscription = self.create_subscription(String, 'string_topic', self.topic_callback, 10)
  1. We have here data type as String
  2. Topic name is string_topic
  3. callback function on each message received is topic_callback

For Imu data

  1. We have here data type as Imu
  2. Topic name is imu_topic
  3. callback function on each message received is topic_callback
self.subscription_ = self.create_subscription(Imu, 'imu_topic', self.imu_callback, 10)

2. Call back functions to process received data

This message type only contains a single entry

For Int32

def topic_callback(self, msg):
    self.get_logger().info('I heard: "%d"' % msg.data)

For Imu data

void topic_callback(const sensor_msgs::msg::Imu::SharedPtr msg)
{
    RCLCPP_INFO(this->get_logger(), "Received IMU data: Angular velocity Z: '%f'", msg->angular_velocity.z);
}

There are other fields that you can find through ros2 interface command


Single-Node Publishing and Subscribing

There are many cases where we have to subscribe a data as well as publish data within a single node. For that scenario, we apply our programming concepts to ROS2 Python node.Below is the code that shows the implementation of the concept.you will observe that the additions are in public initialization and private functions

We recommend you apply the four-step ROS2 Python node structure explained initially to the below-listed node.

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

class IntAndIMUPublisherSubscriber(Node):
    def __init__(self):
        super().__init__('int_and_imu_publisher_subscriber')
        self.count_ = 0

        # Publisher for Int32 data
        self.int_publisher_ = self.create_publisher(Int32, 'int_topic', 10)

        # Subscriber for Imu data
        self.imu_subscription_ = self.create_subscription(
            Imu, 'imu_topic', self.imu_callback, 10)

        # Timer to periodically publish Int32 data
        self.timer_ = self.create_timer(1.0, self.timer_callback)

    def timer_callback(self):
        msg = Int32()
        msg.data = self.count_
        self.count_ += 1
        self.get_logger().info('Publishing: %d' % msg.data)
        self.int_publisher_.publish(msg)

    def imu_callback(self, msg):
        self.get_logger().info('Received IMU data: Angular velocity Z: "%f"' % msg.angular_velocity.z)

def main(args=None):
    rclpy.init(args=args)
    node = IntAndIMUPublisherSubscriber()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

FAQs for ROS2 Python Nodes

Why should I use Python for ROS2 development?

  • Python is an excellent choice for ROS2 development due to its simplicity and ease of use. Python allows for rapid development and prototyping, making it ideal for experimenting with new ideas and testing concepts quickly. The extensive range of available libraries and tools in Python further enhances its capabilities, allowing you to implement complex functionalities with minimal code. Python’s readability and community support make it a popular choice for beginners and for developing applications that don’t require the high performance and real-time capabilities of C++.

How do I handle dependencies and environment setup for ROS2 Python nodes?

  • Managing dependencies and setting up the environment for ROS2 Python nodes can be done efficiently using virtual environments and package management tools like pip. It is recommended to use a virtual environment to isolate your project’s dependencies. You can create a virtual environment and install necessary packages

Can I use Python to develop real-time applications in ROS2?

  • While Python is not inherently designed for real-time applications, it can still be used for certain real-time robotics tasks with careful consideration. Python’s Global Interpreter Lock (GIL) can be a limitation for real-time performance, but you can mitigate this by offloading critical real-time tasks to C++ nodes and using Python for higher-level logic and coordination.

ROS2 Python Nodes Quiz

Leave a Comment

Your email address will not be published. Required fields are marked *

Review Your Cart
0
Add Coupon Code
Subtotal
Total Installment Payments
Bundle Discount

 
Scroll to Top