Search code examples
python-3.xrosros2

How to publish batch of images in a python node with ROS 2?


I have a publisher in ROS 2 which publishes an image message as following:

#!/usr/bin/env python3
# Revision $Id$

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from cv_bridge import CvBridge
from sensor_msgs.msg import Image
import cv2
import numpy as np


class MinimalPublisher(Node):

    def __init__(self):

        super().__init__('minimal_publisher')
        self.publisher_ = self.create_publisher(Image, 'Image', 10)
        timer_period = 0.5  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0
        self.im_list = []
        
        self.cv_image = cv2.imread('test.jpg') ### an RGB image 
        self.bridge = CvBridge()
       
    def timer_callback(self):
        
        self.publisher_.publish(self.bridge.cv2_to_imgmsg(np.array(self.cv_image), "bgr8"))
        self.get_logger().info('Publishing an image')
       

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()

It works fine with a single image. But I want to publish a batch of images with the given shape:

[12, 3, 224, 224] => [batch, channel, width, height]

I tried to send it as a list of images but it failed. How to do so?

More info:

python 3.6
ROS 2 - eloquent (build from source)
Ubuntu 18


Solution

  • Finally, I built a custom message as follows:

    sensor_msgs/Image[ 2 ] data

    The batch size is 2.

    Then, add it to my publisher as follows:

    #!/usr/bin/env python3
    # Revision $Id$
    
    
    import rclpy
    from rclpy.node import Node
    from custom_batch.msg import Batch #### import custom message
    from cv_bridge import CvBridge
    from sensor_msgs.msg import Image
    import cv2
    import numpy as np
    
    
    class MinimalPublisher(Node):
    
        def __init__(self):
            super().__init__('minimal_publisher')
            self.publisher_ = self.create_publisher(Batch, 'Image', 10) #### change here
            timer_period = 0.5  # seconds
            self.timer = self.create_timer(timer_period, self.timer_callback)
            self.i = 0
            self.im_list = []
            self.cv_image1 = cv2.imread('3.jpg')
            self.cv_image2 = cv2.imread('2.jpg')
            self.bridge = CvBridge()
    
        def timer_callback(self):
    
            #### custom message
            my_msg = Batch()
            my_msg.data[0] = self.bridge.cv2_to_imgmsg(np.array(self.cv_image1), "bgr8")
            my_msg.data[1] = self.bridge.cv2_to_imgmsg(np.array(self.cv_image2), "bgr8")
            #####
            self.publisher_.publish(my_msg) ## custom message
            self.get_logger().info('Publishing a batch of images')
    
    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()
    

    You can find useful instruction about custom message in ROS2 here.