ROBOT PROGRAMMING
USING ROS2
2
CONTENTS
Introduction To ROS
Setting up ROS 2
ROS2 topics and services
ROS2 simulation
Where to find help for ROS2?
3
INTRODUCTION TO ROS
History of ROS • Started in 2007 by Keenan Wyrobek and Eric Berger at
Stanford
• Robot Operating System (ROS) is evolved from a practice in
academic research to an industry application.
• Robotic arms (Franka Emika, ABB, Universal Robots)
• Autonomous vehicles (Nvidia, Apex.AI)
• Warehouses (Clearpath robotics, Novus Hitech Smart
Robotics (India), etc.)
• Aerospace and Defence (NASA, etc.)
Source: Willow Garage
4
What is ROS?
ROS is a set of software libraries
and tools for building robot
applications (source: ROS
website)
WHY ROS?
5
• It is an open-source middleware (not an OS).
• Built on Data Distribution Service (DDS)
• provides secure and reliable communication
• Has development environment
• Visualization tools and introspection tools
• Rapid Testing
• Numerous modules that support developing robot software tools
• Very Active Community for support
Source: Internet
6
How ROS works?
Data Distribution Service (DDS)
• Standard enables data exchanges using
a publisher and subscriber approach
• A communication layer in ROS 2
ROS Middleware (RMW)
• Provides communication infrastructure
for ROS2 and DDS (can ignore this
mechanism)
ROS Client Library (RCL)
• High-level interface of building and
running robot programs
• Implemented through rclcpp, rclpy and
other languages like java, rust
Source Internet
7
How ROS works? (Contd.)
/scan
localization
Computation graph (Model for
lidar programming): Network of nodes
/pose • Consists of Nodes that talk with
Object each other
camera recognition
• Communicate through topics
or services or actions
/object /rosout
EKF
/image • Communicated via a structured
standard / custom messages
speed • Each Node is a process that either
controller /cmd_vel
work independently or depends on
Encoder /odom another node
ticks
/tf • It can be sensor data or
Odometry
perception pipeline or
/ticks controllers etc.
Robot state
publisher
8
SETTING UP ROS2
ROS2 Workspace $ source /opt/ros/$ROS_DISTRO/setup.bash
<name of your workspace> $ echo "source /opt/ros/ROS_DISTRO/setup.bash" >>
---- build ~/.bashrc
---- install $ source ~/.bashrc
---- log
---- src
$ mkdir –p <name of your workspace>/src
---- <pacakge 1> $ cd <name of your workspace>
---- ...
---- <package n>
Import packages (if any)
Remember run this $ colcon build –symlink install
command from root of $ echo "export ROS_DOMAIN_ID=<YOURS CHOICE>"
your workspace >>~/.bashrc
$ echo "export ROS_LOCALHOST_ONLY=1" ~/.bashrc
9
SETTING UP ROS2 (CONTD.)
ROS2 Package (Python) $ cd <path to your workspace>/<name of your
<package name> workspace>/src
---- resource/<package name> $ ros2 pkg create --build-type ament_python --
---- setup.cfg license Apache-2.0 <package name>
---- setup.py package name: my_package
destination directory: /home/shravista/test_ws/src
---- <package name> package format: 3
version: 0.0.0
---- ---- __init__.py description: TODO: Package description
maintainer: ['shravista <shravistakashyap@gmail.com>']
licenses: ['TODO: License declaration']
build type: ament_python
dependencies: []
ROS2 Package (C++) creating folder ./my_package
creating ./my_package/package.xml
creating source folder
<package name> creating folder ./my_package/my_package
creating ./my_package/setup.py
---- inc/ude/<package name> creating ./my_package/setup.cfg
creating folder ./my_package/resource
---- src
creating ./my_package/resource/my_package
creating ./my_package/my_package/__init__.py
creating folder ./my_package/test
---- CMakelists.txt creating ./my_package/test/test_copyright.py
creating ./my_package/test/test_flake8.py
---- package.xml creating ./my_package/test/test_pep257.py
$ cd ..;
$ colcon build –-symlink-install –packages-select
my_package;
$ source install/setup.bash
10
ROS2 TOPICS AND SERVICES
Terminal 1 -> Publish to a topic
$ ros2 topic pub /my_topic std_msgs/msg/String "{data: 'Hello I am learning
ROS 2'}"
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hii I am learning ROS 2')
Terminal 2 -> subscribed to a topic
$ ros2 topic echo /my_topic
data: Hii I am learning ROS 2
---
data: Hii I a learning ROS 2
---
11
ROS2 TOPICS
Source : ROS2 documentation
12
ROS2 TOPICS -
Publisher (contd.)
Let's create a node to publish into a topic Terminal 1 -> run the simulation
1. Writing program $ ros2 launch rosbot_xl_gazebo
a) Create a .py file
b) Import rclpy modules simulation.launch.py
c) Import ros interfaces (geometry_msgs/msg/Twist)
d) Create a class that inherits on rclpy.Node
e) Create a publisher Terminal 2 -> run your node
f) Program you msg
g) Publish your message $ cd <root of your workspace>
2. Edit package.xml $ colcon build –symlink-install –
a) <exec_depend>rclpy</exec_depend> packages-select <package_name>
b) <exec_depend>geometry_msgs</exec_depend>
$ ros2 run <package_name> <nodeName>
3. Edit setup.py
a) entry_points={
'console_scripts': [
'<nodeName>=my_package.<fileName>:main',
],
},
13
ROS2 TOPICS -
Publisher (contd.)
Different methods of publishing content Terminal 1 -> run the simulation
1. Loop $ ros2 launch rosbot_xl_gazebo
a) for loop or while loop with a simulation.launch.py
while rclpy.ok():
# create message
# send message Terminal 2 -> run your node
# spin the node once
# add delay using sleeping function $ cd <root of your workspace>
$ colcon build –symlink-install –
2. Timers packages-select <package_name>
a) For periodic publishing $ ros2 run <package_name> <nodeName>
self.timer = self.create_timer(0.1, self.timer_callback)
def timer_callback(self):
# create message
# send message
14
ROS2 TOPICS -
Publisher (contd.)
1. ROS 2 logging reveals a node's internal activity.
2. It usual targets are
a) Console
b) Log files
c) /rosout
3. Have severity level
Don't use print statements a) DEBUG
rathen utilize the power of ros b) INFO
logging messages c) WARN
d) ERROR OR FATAL
self.get_logger().info(f'Moving in circle with linear velocity {self.linear_velocity} m/s and radius {self.radius} m')
self.get_logger().warn(f'Moving in circle with linear velocity {self.linear_velocity} m/s and radius {self.radius} m')
self.get_logger().error(f'Moving in circle with linear velocity {self.linear_velocity} m/s and radius {self.radius} m')
self.get_logger().fatal(f'Moving in circle with linear velocity {self.linear_velocity} m/s and radius {self.radius} m')
15
ROS2 TOPICS -
Subscriber(contd.)
Let's create a node to publish into a topic
1. Writing program
a) Create a .py file
b) Import rclpy modules
c) Import ros interfaces $ cd <root of your workspace>
d) Create a class that depends on rclpy.Node
e) Create a subscriber
$ colcon build –symlink-install
f) Create a callback function –packages-select <package_name>
g) spin the node $ ros2 run <package_name>
2. Edit package.xml <nodeName>
a) <exec_depend>rclpy</exec_depend>
b) <exec_depend>geometry_msgs</exec_depend>
3. Edit setup.py
a) entry_points={
'console_scripts': [
'<nodeName>=my_package.<fileName>:main',
],
},
16
ROS2 Parameters
A parameter is a configuration value Terminal 1 -> run the simulation (using
of a node. turtlesim)
$ ros2 run turtlesim turtlesim_node
What you can do with it?
1. Read parameters
Terminal 2 -> run the simulation (using
2. Change parameters
turtlesim)
3. Load into a file
4. Dump them from a file $ ros2 run turtlesim
turtle_teleop_key
# declare parameters Terminal 3 -> look for parameters
self.declare_parameter('Kp', 5.0)
$ ros2 param list
# read parameters
self.get_parameter('Kp').get_parameter_value().double_value
# set parameters
self.set_parameters([rclpy.parameter.Parameter('Kp', rclpy.Parameter.Type.DOUBLE, Kp)])
17
ROS2 Launch Files
Launch System. Creating launch file
What you can do with it? 1. Import libraries
1. Run large number of nodes from launch import LaunchDescription
2. Configure the nodes like from launch_ros.actions import Node
parameters
3. Start nodes with user-defined 2. Define the generate_launch_description function
settings
4. XML, YAML, Python – possible def generate_launch_description():
move_in_circle_node = Node(
ways to write launch files package='my_package',
executable='moveInCircle',
name='move_in_circle',
output='screen',
parameters=[{'Kp': 5.0}])
ld = LaunchDescription()
ld.add_action(move_in_circle_node)
return ld
18
ROS2 Launch Files
Contd.
Versatility of Launch files
1. Passing arguments from launch files
3. Tell ros2 file system where your packages 2. Include other launch files
can be found ( in setup.py) 3. Execute shell commands
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
# in addition to the above imports, you may need to import other necessary modules
('share/' + package_name, ['package.xml']),
from launch.actions import DeclareLaunchArgument
(os.path.join('share', package_name, 'launch'),
from launch.substitutions import LaunchConfiguration
glob('launch/*.launch.py')),
],
# below the generate_launch_description()
def generate_launch_description():
4. Compile the package, if this setting is for the Kp = LaunchConfiguration('Kp', default='5.0')
move_in_circle_node = Node(
first time package='my_package',
executable='moveInCircle',
name='move_in_circle',
Terminal 1 -> How to launch file in ROS2 output='screen',
parameters=[{'Kp': Kp}])
$ colcon build –symlink-install ld = LaunchDescription()
ld.add_action(DeclareLaunchArgument('Kp', default_value='5.0',
-–packages-select <package description='Proportional gain for the controller'))
name> ld.add_action(move_in_circle_node)
return ld
19
ROS2 SERVICES
20
ROS2 Services- Server
Let's create a node to publish into a topic
1. Writing program # import required service interfaces
a) Create a .py file from my_interfaces.srv import TakePicture
b) Import rclpy modules # create a service
c) Import ros interfaces (srv, msg(if requried)) self.srv = self.create_service(TakePicture, 'take_picture',
d) Create a class that depends on rclpy.Node self.take_picture_callback)
e) Create a service server
# create a callback
f) create a callback to service and respond to the request received def take_picture_callback(self, request, response):
g) Spin your node self.total_pictures = request.number_of_pictures
2. Edit package.xml self.pathToFolder = request.folder_path
# do something
a) <exec_depend>rclpy</exec_depend> response.success = True
b) <exec_depend><your srv interface></exec_depend>
3. Edit setup.py return response
a) entry_points={
'console_scripts': [
'<nodeName>=my_package.<fileName>:main',
],
},
21
ROS2 Services- client
Let's create a node to publish into a topic
1. Writing program # import required service interfaces
a) Create a .py file from my_interfaces.srv import TakePicture
b) Import rclpy modules
# create a service
c) Import ros interfaces (srv, msg(if requried))
self.srv = self.create_client(TakePicture, 'take_picture')
d) Create a class that depends on rclpy.Node while not self.client.wait_for_service(timeout_sec=1.0):
e) Create a service client self.get_logger().info('Service not available, waiting again...')
f) Wait for the server to be ready self.get_logger().info('Service is available.')
g) Write a request and wait for the response till service server def send_request(self, number_of_pictures, folder_path):
respond. request = TakePicture.Request()
h) Spin your node till future complete request.number_of_pictures = number_of_pictures
2. Edit package.xml request.folder_path = folder_path
future = self.client.call_async(request)
a) <exec_depend>rclpy</exec_depend> return future
b) <exec_depend><your srv interface></exec_depend> # in main function you need something like this
3. Edit setup.py rclpy.spin_until_future_complete(picture_service_client, future)
a) entry_points={
'console_scripts': [
'<nodeName>=my_package.<fileName>:main',
],
},
22
ROS2 TOOLS $ rviz2
RVIZ
1. Visualize robot
2. Visualize Topics
a) Image
b) Lidar
3. Visualize transforms (tf)
23
ROS2 TOOLS $ rqt_graph
Rqt Graph
1. Visualize Nodes talking to
each other
24
ROS2 SIMULATION
TF - Tree • Transformation tree
o Consists of a parent link and child link(s).
o Describes about the relative location of child link and
parent link
• Visualization tools
o rviz, rqt_tf_tree
• tf2_ros is a package used for listening to frame
transformations and modifying it
25
ROS2 SIMULATION
Universal Robot Description • URDF files describe
Format (URDF) - in general o Robot overall structure
Simulation Description o Type of joints like (prismatic, revolute)
Format (SDF) - gazebo o Physical parameters like mass, inertia
Gazebo Ignition o Include gazebo ros plugins to interact with gazebo
o Not suitable for closed-loop kinematics
• SDF files are particular to gazebo
o Not used in this course
26
ROS SIMULATION
Gazebo
• A physics simulator
o Can simulate a physical
environment
o Supports various sensors like
▪ Joint encoders
▪ Camera
▪ Lidar
▪ etc.
27
ROBOT DESCRIPTION
<Package Name> • Resources
…. launch o https://docs.ros.org/en/humble/Tutorials/Intermediate/U
…. …. <launch files> RDF/URDF-Main.html
…. mesh
o Note: for beginners please leave the following topics
…. ….. <stl, collada files>
▪ Using URDF with robot_state_publisher (C++)
…. urdf ▪ Using URDF with robot_state_publisher (Python)
…. …. <robot description
file> o For exporting the urdf files from urdf
…. src
▪ https://docs.ros.org/en/humble/Tutorials/Intermedia
…. CMakeLists.txt
te/URDF/Exporting-an-URDF-File.html
…. packages.xml
28
ROBOT DESCRIPTION (CONTD...)
Adding gazebo elements • Resources:
o https://control.ros.org/humble/doc/gz_ros2_control/doc/
index.html
o Note that this might not work with gazebo ignition. If
that happens, (ping chidres@iisc.ac.in)
29
WHERE TO FIND HELP?
ROS2 is an open-source 1. https://docs.ros.org/en/humble/index.html
software that is been widely 2. https://robotics.stackexchange.com/
contributed by people
3. https://discourse.ros.org/
around the world.
4. Online community
30
USEFUL RESOURCES
• https://roboticsbackend.com/
• https://articulatedrobotics.xyz/
• https://youtube.com/playlist?list=PLLSegLrePWgJudpPUof4-nVFHGkB62Izy&feature=shared
• https://roboticseabass.com/
• https://www.theconstruct.ai/
• https://articulatedrobotics.xyz/tutorials/mobile-robot/hardware/raspberry-pi/
THANK
YOU
Shravista Kashyap
chidres@iisc.ac.in