Lab: Introduction to ROS2


Today's Lesson


Practice :

Create a package


A package is a container for your ROS 2 code.

      $  mkdir -p ros2_ws/src
      $  cd ros2_ws/src
      $  ros2 pkg create --build-type ament_python iml_buche_test
    

Create a node


Create start.py and place it in ros2_ws/src/iml_buche_test/iml_buche_test/

start.py

        import rclpy
        from rclpy.node import Node

        def main(args=None):

            # initialize ROS communications
            rclpy.init(args=args)
            
            # create the node
            node = Node('start_node')
            
            # start ROS2 publishers, subscribers, services, get parameters, etc
            rclpy.spin(node)
            
            # When you request to kill the node
            rclpy.shutdown()
            
        if __name__ == '__main__':
            main()
Add an entry point in the setup.py

setup.py


    #...
    entry_points={
        'console_scripts': [
            'test_python_node = iml_buche_test.start:main'
        ],
    ...
Note:
  • test_python_node will be the name of the executable,
  • start is the name of the Python file
  • my_node_name is the name of the node (written in the Python file).
  • package.xml

    Add rclpy dependency <build_type>ament_python</build_type> ... <depend>rclpy</depend>
    
         # Compile your package
      $ cd ros2_ws
      $ colcon build
    
        # source your ROS2 workspace
       $ . install/setup.bash
    
        # run
       $ ros2 run iml_buche_test test_python_node
        

    Manipulate node


    
        # change the node’s name from “my_node” to “another_node”
       $ ros2 run iml_buche_test test_python_node  --ros-args -r __node:=another_node
    
        # dans un autre terminal
       $ . install/setup.bash # source
       $ ros2 run iml_buche_test test_python_node
    
        # it could be nice to be able to see what’s going on
       $ ros2 node list
    
        # Get more details about a Node
       $ ros2 node info /another_node
        

    Create another node

    Create anotherNode.py and place it in ros2_ws/src/iml_buche_test/iml_buche_test/

    anotherNode.py

    # ROS2 Python library
               import rclpy
               from rclpy.node import Node
    
               class MyNode2(Node):
                   def __init__(self):
                       super().__init__('my_node_name_another')
                       self.create_timer(0.2, self.timer_callback)
                       
                   def timer_callback(self):
                       self.get_logger().info("Coucou -- Hello ROS2 -- this is IML ")
    
               def main(args=None):
                   rclpy.init(args=args)
                   
                   node = MyNode2()
                   
                   rclpy.spin(node)
                   rclpy.shutdown()
                   
               if __name__ == '__main__':
                   main()
           
    Do not forget to add another entry point in setup.py
    
        #...
        entry_points={
            'console_scripts': [
                'test_python_node = iml_buche_test.start:main',
                'test_python_another_node = iml_buche_test.anotherNode:main'
            ],
        ...
    Compile :
    
         $   colcon build
        
    In one terminal :
    
              $ . install/setup.bash
              $ ros2 run iml_buche_test test_python_node
           
    In another terminal :
    
                 $ . install/setup.bash
                 $ ros2 run iml_buche_test test_python_another_node
              

    Publisher/Receiver


    Create a new package in the workspace
    
               $  cd ./ros2_ws/src
        $  ros2 pkg create --build-type ament_python iml_buche_test_2
           
    publisher.py
    
            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, 'iml_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 = 'Hello World: %d' % self.i
                    self.publisher_.publish(msg)
                    self.get_logger().info('Publishing: "%s"' % msg.data)
                    self.i += 1
    
    
            def main(args=None):
                rclpy.init(args=args)
    
                minimal_publisher = MinimalPublisher()
    
                rclpy.spin(minimal_publisher)
    
    
                rclpy.shutdown()
    
    
            if __name__ == '__main__':
                main()
        
    receiver.py
    
            import rclpy
            from rclpy.node import Node
    
            from std_msgs.msg import String
    
    
            class MinimalSubscriber(Node):
    
                def __init__(self):
                    super().__init__('minimal_subscriber')
                    self.subscription = self.create_subscription(
                        String,
                        'iml_topic',
                        self.listener_callback,
                        10)
                    self.subscription  # prevent unused variable warning
    
                def listener_callback(self, msg):
                    self.get_logger().info('I heard: "%s"' % msg.data)
    
    
            def main(args=None):
                rclpy.init(args=args)
    
                minimal_subscriber = MinimalSubscriber()
    
                rclpy.spin(minimal_subscriber)
                rclpy.shutdown()
    
            if __name__ == '__main__':
                main()
        
    While running, you can display the graph
    
              $ rqt_graph