Robot Operating System: Practical Guide for Migrating from ROS1 to ROS2

Create a new ROS2 Package with the Python Build System

Create the Package

ros2 pkg create --build-type ament_python radu_bot

Add Dependencies to the Package.xml

  • rviz2: Contains the RViz simulation tool
  • urdf: C++ parser for the URDF file format
  • joint_state_publisher: Publishes the state of all non-static joints for an URDF-described robot. This package reads the parameter robot_description from the ROS parameter server to build a representation of the robot. Then, it continuously publishes messages that contain name, position, velocity and effort of each joint.
  • robot_state_publisher: This package reads the robot_description parameter and the joint_states published by the aforementioned package to calculate a 3D pose estimation of the robot. The messages are published as tf2 messages, which allow all other ROS nodes to coherently access all coordinate frames (world, links of your robot) over time.
  • controller_manager: This packages allows direct access to a robot, which means that the robots hardware, is actuators and sensors, are wrapped in a common format which can be used by other ROS nodes and tools, including RViz and Gazebo.
  • xacro: With XACRO, you can define XML macros to be used in creating URDF files, which drastically reduces the amount of code you need to write and enables flexible “builds” of your robot, e.g. adding tags specifically required for Gazebo.
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>radu_bot</name>
<version>0.1.0</version>
<description>Simulation of the RADU bot</description>
<maintainer email="devcon@admantium.com">devcon</maintainer>
<license>UNLICENSED</license>
<depend>urdf</depend> <depend>joint_state_publisher</depend>
<depend>joint_state_publisher_gui</depend>
<depend>robot_state_publisher</depend>
<depend>rviz2</depend>
<depend>xacro</depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
sudo apt-get install ros-foxy-joint-state-publisher-gui ros-foxy-xacro
rosdep update
rosdep install --from-paths src --ignore-src --rosdistro foxy -y

Migrate the Launch File

<launch>
<param name="robot_description" textfile="$(find car-robot)/urdf/bot.urdf"/>
<arg name="rvizconfig" default="$(find urdf_tutorial)/rviz/urdf.rviz" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"/>
<node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" />
</launch>
  • The param declaration defines the standard parameter name robot_description. It refers to the URDF file that contains your robot definition.
  • The arg declaration loads the rviz configuration file, it includes the settings so that our robot will be displayed automatically.
  • Two control nodes, the robot_state_publisher and the joint_state_publisher are created - these nodes are interfaces between the robot and rviz
  • Finally, we start the rviz node and pass the configuration file to it.
<param name="robot_description" textfile="$(find car-robot)/urdf/bot.urdf"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
robot_description = open(robot_description_path).read()robot_state_publisher_node = launch_ros.actions.Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_description}]
)
def generate_launch_description():
return launch.LaunchDescription([
robot_state_publisher_node
])
import launch
from launch.substitutions import Command, LaunchConfiguration
import launch_ros
import os
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
package_name = 'radu_bot'
pkg_share = launch_ros.substitutions.FindPackageShare(package=package_name).find(package_name)
robot_description_path = os.path.join(pkg_share, 'urdf/robot.urdf')
rviz_config_path = os.path.join(pkg_share, 'config/urdf_config.rviz')
robot_state_publisher_node = launch_ros.actions.Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_description}]
)
joint_state_publisher_node = launch_ros.actions.Node(
package='joint_state_publisher',
executable='joint_state_publisher',
name='joint_state_publisher'
)
joint_state_publisher_gui_node = launch_ros.actions.Node(
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui',
name='joint_state_publisher_gui'
)
rviz_node = launch_ros.actions.Node(
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', rviz_config_path],
)
return launch.LaunchDescription([
joint_state_publisher_node,
joint_state_publisher_gui_node,
robot_state_publisher_node,
rviz_node
])

Build Configuration

import os
from glob import glob
from setuptools import setup
package_name = 'radu_bot'setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name, 'launch'), glob('launch/*')),
(os.path.join('share', package_name, 'urdf'), glob('urdf/*')),
(os.path.join('share', package_name, 'config'), glob('config/*')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='devcon',
maintainer_email='devcon@admantium.com',
description='Simulation of the RADU robot',
license='UNLICENSED',
tests_require=['pytest'],
entry_points={
'console_scripts': [
],
},
)

Adding the Robot Model

Building the Package

$> colcon build --symlink-install --event-handlers console_direct+ --packages-up-to radu_bot
$Y ros2 launch radu_bot rviz.launch.py
[INFO] [launch]: All log files can be found below /home/devcon/.ros/log/2021-05-29-18-33-52-275784-giga-20756
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [joint_state_publisher-1]: process started with pid [20758]
[INFO] [joint_state_publisher_gui-2]: process started with pid [20760]
[INFO] [robot_state_publisher-3]: process started with pid [20762]
[INFO] [rviz2-4]: process started with pid [20764]
[robot_state_publisher-3] Parsing robot urdf xml string.
[robot_state_publisher-3] Link left_wheel_backside had 0 children
[robot_state_publisher-3] Link left_wheel_frontside had 0 children
[robot_state_publisher-3] Link right_wheel_backside had 0 children
[robot_state_publisher-3] Link right_wheel_frontside had 0 children
[robot_state_publisher-3] [INFO] [1622306032.679044506] [robot_state_publisher]: got segment base_link
[robot_state_publisher-3] [INFO] [1622306032.681243514] [robot_state_publisher]: got segment left_wheel_backside
[robot_state_publisher-3] [INFO] [1622306032.681317837] [robot_state_publisher]: got segment left_wheel_frontside
[robot_state_publisher-3] [INFO] [1622306032.681341170] [robot_state_publisher]: got segment right_wheel_backside
[robot_state_publisher-3] [INFO] [1622306032.681363438] [robot_state_publisher]: got segment right_wheel_frontside
[rviz2-4] [INFO] [1622306033.746836459] [rviz2]: Stereo is NOT SUPPORTED
[rviz2-4] [INFO] [1622306033.750165429] [rviz2]: OpenGl version: 4.6 (GLSL 4.6)
[rviz2-4] [INFO] [1622306033.857522813] [rviz2]: Stereo is NOT SUPPORTED
[joint_state_publisher-1] [INFO] [1622306034.345835955] [joint_state_publisher]: Waiting for robot_description to be published on the robot_description topic...
[rviz2-4] Parsing robot urdf xml string.
Centering
[joint_state_publisher_gui-2] [INFO] [1622306035.104035974] [joint_state_publisher_gui]: Centering

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store