How to create your own service message
Create a New Package
In ROS2, the custom message topics and services have to be created in a CPP Package. It could be done in the same package we have been using for all the examples. But we are going to create a new package, so we can practice importing from different packages.
So, we will create a new package for the creation of our custom service messages:
cd ~/ros2_ws/src ros2 pkg create service_custom_msg --dependencies std_msgs rclcpp
Create Custom Service Message
For this example, we are going to create a Custom Service Message that will help us calculate the area of a triangle.
The message file will be named
TriangleArea.srv and it should be something like this:
float64 base # The distance of of the base of the triangle float64 height # The height of the triangle --- bool success # Did it achieve it?
Now, let's create the file in our package
cd ~/ros2_ws/src/service_custom_msg mkdir srv touch srv/TriangleArea.srv
Prepare CMakeLists.txt and package.xml for Custom Service Compilation
Set Up CMakeLists.txt
Here you need to add the dependencies that your custom message needs. Add the following packages, which are responsible for the topics and services message generators in ROS2:
find_package(builtin_interfaces REQUIRED) find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(service_custom_msg "srv/TriangleArea.srv" DEPENDENCIES builtin_interfaces)
At the end, you should have something like this:
cmake_minimum_required(VERSION 3.5) project(service_custom_msg) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(std_msgs REQUIRED) find_package(rclcpp REQUIRED) # For Message Generation find_package(builtin_interfaces REQUIRED) find_package(rosidl_default_generators REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # remove the line when a copyright and license is present in all source files set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # remove the line when this package is a git repo set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() rosidl_generate_interfaces(service_custom_msg "srv/TriangleArea.srv" DEPENDENCIES builtin_interfaces) ament_package()
Set Up package.xml
Here you needed to add the following dependencies, which are for message generation and for any dependencies added in the custom message:
<depend>builtin_interfaces</depend> <depend>rosidl_default_generators</depend> <member_of_group>rosidl_interface_packages</member_of_group>
It's important to add the
member_of_group tag to avoid this error:
CMake Error at /opt/ros/bouncy/share/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake:129 (message): Packages installing interfaces must include '<member_of_group>rosidl_interface_packages</member_of_group>' in their package.xml
And we have to change the package version to 3, otherwise we won't be able to use member_group.
At the end, you should have something like this:
<?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <package format="3"> <name>service_custom_msg</name> <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="email@example.com">ubuntu</maintainer> <license>TODO: License declaration</license> <buildtool_depend>ament_cmake</buildtool_depend> <depend>std_msgs</depend> <depend>rclcpp</depend> <depend>builtin_interfaces</depend> <depend>rosidl_default_generators</depend> <test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_common</test_depend> <member_of_group>rosidl_interface_packages</member_of_group> <export> <build_type>ament_cmake</build_type> </export> </package>
Compile Service Message
Once we have our
package.xml files ready, it's time to compile our custom Service message.
colcon build --symlink-install --packages-select services_custom_msg
If everything goes OK, you will get something like this:
VERY IMPORTANT: After the message generation, you have to source again your ROS2 workspace. Otherwise, you won't be able to see the messages generated through the ROS2 service commands, and you will think that it didn't work.
Now we can list all the Service messages available and filter by name with the following command:
ros2 srv list | grep service_custom_msg/srv/TriangleArea
You should get something like this:
Finally, we can also visualize the contents of the new message generated:
ros2 srv show service_custom_msg/TriangleArea
You will get something like this:
If you had this output, the message was generated.
Also, you can test this tutorial in ROSDS, using a ROSject which already contains all the code described in it. You can get the ROSject by clicking on the button below:
Above: Get ROSDS ROSject
The link above will take yo a page like the below one:
Now, you just need to Sign In (or Sign Up if you don't have an account yet) to ROSDS in order to launch the ROSject.