If you already have ros1 gazebo simulation packages created and working, and now you want to upgrade them to ros2. This is the the right page to visit. This page focuses on C++ packages migration.
To migrate your ros1 package to ros2 package, things that you likely need to modify include: source code, CMakeLists.txt, package.xml, XACRO/URDF file, and launch file. These are some instructions that you must read before you go about it:
https://docs.ros.org/en/humble/The-ROS2-Project/Contributing/Migration-Guide.html
https://docs.ros.org/en/eloquent/Tutorials/Launch-files-migration-guide.html
https://docs.ros.org/en/eloquent/Tutorials/Parameters-YAML-files-migration-guide.html
Here are some common issues that you will get when migrating ros1 source code to ros2:
When building the package, you get errors saying cannot find header file.
This could be due to you didn’t add required package in the CMakeList.txt file. If you want to use a header file that belongs to a package, you need to add that package name into find_package()
and ament_target_dependencies()
section in CMakeList.txt file. Another possible cause is the header file path is changed in the ros2 package. For example, in ros1, the header file path of *Imu.h*
is *sensor_msgs/Imu.h*
; in ros2, it becomes *sensor_msgs/msg/imu.hpp*
. Header file path changing is quite common in ros2. To find out the right file path, a easy way is to search the file in /opt/ros/humble/include
folder to get the actual path. Another possible cause is the header file name being slightly changed in ros2. For example, there is a header file called <gazebo_msgs/ModelState.h>
in ros1, but in ros2, it is named as <gazebo_msgs/msg/model_state.hpp>
Class or method that used in ros1 code cannot not be found in ros2.
You may able to find a substitution header file in ros2 package to replace the header file in ros1 package, but the class that used in ros1 package may completely changed or the class name is changed. What you need to do is, go to the header file, find the equivalent class and get the name to replace the old name in your source code.
Sometimes it’s possible that a method exist in ros1 class, but not ros2 class. For that situation, you need to find an equivalent substitution for that method. For example, in ros1, there is a method used to create quaternion set: tf::createQuaternionMsgFromRollPitchYaw
, which doesn’t exist in tf2 anymore. As a workaround, you can use tf2::Quaternion::setRPY()
for a replacement.
The way that ros2 prints information is changed. For example in ros1, the code could be like:
ROS_INFO("Fx:%3d Fy:%3d Fz:%3d", (int)Fx, (int)Fy, (int)Fz);
In ros2, it’s changed to:
RCLCPP_INFO(node->get_logger(), "Fx:%3d Fy:%3d Fz:%3d", (int)Fx, (int)Fy, (int)Fz);
The way of creating publisher and subscriber is changed, same as service. See here for information:
https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html
https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Service-And-Client.html
The way that ros1 and ros2 uses call back function is different. std::bind()
needs to be used, otherwise you will get error saying call back function is not static in building stage. Here is an example, in ros1, a subscriber can call a call back function like this:
ros::Subscriber force_sub;
this->force_sub = this->rosnode->subscribe(this->topic_name+"/"+"the_force", 30, &UnitreeDrawForcePlugin::GetForceCallback, this);
But in ros2, it will be like this:
rclcpp::Subscription<geometry_msgs::msg::Wrench>::SharedPtr force_sub;
force_sub = rosnode->create_subscription<geometry_msgs::msg::Wrench>(this->topic_name+"/"+"the_force", 30, std::bind(&UnitreeDrawForcePlugin::GetForceCallback, this, std::placeholders::_1));
rclcpp needs to be initialized before use. It can be initialized like this:
rclcpp::init(argc, argv);
In xacro file, if you want to find a dae file using a path relative to the package directory as below: <mesh filename="package://unitree_gazebo/go1_description/meshes/depthCamera.dae" scale="1 1 1"/>
. You need to specify install directory in the launch file like this: install_dir = get_package_prefix('unitree_gazebo')
You need to replace gazebo_ros_control
plugin in XACRO/URDF file, with gazebo_ros2_control
.