Introduction to ROS2
Part 1: Getting started
Where to find ROS 2 distributions
Getting started tutorials
Quick overview of Docker
Check out docker/Dockerfile
Create a workspace
ros2 pkg create --build-type ament_python --node-name example_node example_package
.
└── example_package
├── example_package
│ ├── __init__.py
│ └── example_node.py
├── package.xml
├── resource
│ └── example_package
├── setup.cfg
├── setup.py
└── test
├── test_copyright.py
├── test_flake8.py
└── test_pep257.py
4 directories, 9 files
Build a package:
colcon build
Source the built binaries:
. install/setup.bash
Run a node:
ros2 run my_package my_node
Part 2: Topics
Create a new docker instance
and Open 2 windows:
docker exec -it optimistic_wu bash
Create a topic:
Build topic publisher class under example_topic/example_publisher.py
Highlights:
self.create_publisher(String, 'topic', 10)
self.create_timer(period, self.callback)
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class ExamplePublisher(Node):
def __init__(self):
super().__init__('example_publisher')
self.publisher_ = self.create_publisher(String, '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)
example_publisher = ExamplePublisher()
rclpy.spin(example_publisher)
example_publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Dont forget to add entry to setup.cfg!
entry_points={
'console_scripts': [
'example_publisher = example_topic.example_node:main',
'example_subscriber = example_topic.example_subscriber:main',
],
},
Create a subscriber:
Build topic subscriber class under example_topic/example_publisher.py
Highlights:
self.subscription = self.create_subscription(String, 'topic', listener_callback, 10)
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class ExampleSubscriber(Node):
def __init__(self):
super().__init__('example_subscriber')
self.subscription = self.create_subscription(
String,
'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)
example_subscriber = ExampleSubscriber()
rclpy.spin(example_subscriber)
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Create a service:
Build service class under example_service/example_service.py
Highlights:
self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
add_two_ints_callback(self, request, response):
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
class MinimalService(Node):
def __init__(self):
super().__init__('minimal_service')
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
def add_two_ints_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))
return response
def main(args=None):
rclpy.init(args=args)
minimal_service = MinimalService()
rclpy.spin(minimal_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
Call the service from the command line:
ros2 service list
ros2 service call /add_two_ints ex/srv/AddTwoInts "{a: 32,b: 90}"
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
class ExampleService(Node):
def __init__(self):
super().__init__('minimal_service')
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
def add_two_ints_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))
return response
def main(args=None):
rclpy.init(args=args)
example_service = ExampleService()
rclpy.spin(example_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
Dont forget to add entry to setup.cfg!
ros2 run gazebo_ros spawn_entity.py -file /workspace/models/iris_with_standoffs/model.sdf -entity drone
/workspace/ardupilot/Tools/autotest/sim_vehicle.py -v ArduCopter -f gazebo-iris -I 1
ros2 run mavros mavros_node fcu_url:=udp://0.0.0.0:14561@14565 target_component_id:=1 fcu_protocol:=v2.0
ros2 service call /drone1/mavros/set_mode mavros_msgs/srv/SetMode "{custom_mode: GUIDED}"
ros2 service call /drone1/mavros/cmd/arming mavros_msgs/srv/CommandBool "{value: true}"
ros2 service call /drone1/mavros/cmd/takeoff mavros_msgs/srv/CommandTOL "{altitude: 1}"
ros2 service call /drone1/mavros/cmd/land mavros_msgs/srv/CommandTOL "{}"
ros2 topic pub /drone1/mavros/setpoint_position/local geometry_msgs/msg/PoseStamped "{pose:{position: {x: 1, z: 5}}}"
ros2 topic pub /drone1/mavros/setpoint_position/local geometry_msgs/msg/PoseStamped "{pose:{position: {x: -20, y: -20, z: 1}}}"
ros2 service call /drone1/mavros/set_mode mavros_msgs/srv/SetMode "{custom_mode: RTL}"