This tutorial is created by Robotics Ambassador Ernest
Rosbotics Ambassador Program https://www.theconstruct.ai/robotics-ambassador/
Overview
- In this tutorial I’ll answer this question from the Robotics Stack Exchange and show you how to create custom interfaces using a field type that is a msg from a package, and not just a primitive built-in-type.
- Ideally you should already have an understanding of the basics of creating custom interfaces with the built-in field types (including best practices such as creating a package dedicated to your interface definitions). If not, The Robotics Back-End has a great tutorial.
- I’ll be using The Construct’s ROS development studio (rosject) and doing it in a ROS2 Humble workspace called
ros2_ws
. You can access this rosject here.
Recreating the error: Creating the custom srv
Create a new package named custom_interfaces
. This package, however, has to be a CMake
package (default when using ros2 pkg create
). Currently, there is no way to generate custom interfaces in a pure Python package. However, you can create a custom interface in a CMake package and then use it in a Python node.
cd ~/ros2_ws/src/ ros2 pkg create custom_interfaces
Next, remove the include
and src
directories and create a directory named srv
inside your package. Inside this directory, create the srv file TurnCamera.srv
:
cd ~/ros2_ws/src/custom_interfaces rm -rf include rm -rf src mkdir srv touch srv/TurnCamera.srv
Paste this inside TurnCamera.srv
:
float32 deg_turn --- sensor_msgs/Image camera_image
Then add the following lines to the CMakeLists.txt
file:
find_package(rosidl_default_generators REQUIRED) find_package(sensor_msgs REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "srv/TurnCamera.srv" )
And also the following lines to the package.xml
file within the <package>
element:
<buildtool_depend>rosidl_default_generators</buildtool_depend> <exec_depend>rosidl_default_runtime</exec_depend> <member_of_group>rosidl_interface_packages</member_of_group>
Finally compile the package by running this in the terminal:
cd ~/ros2_ws colcon build --packages-select custom_interfaces
You should get this error:
Starting >>> custom_interfaces --- stderr: custom_interfaces In file included from /home/user/ros2_ws/build/custom_interfaces/rosidl_typesupport_cpp/custom_interfaces/srv/turn_camera__type_support.cpp:7: /home/user/ros2_ws/build/custom_interfaces/rosidl_generator_cpp/custom_interfaces/srv/detail/turn_camera__struct.hpp:134:10: fatal error: sensor_msgs/msg/detail/image__struct.hpp: No suchfile or directory 134 | #include "sensor_msgs/msg/detail/image__struct.hpp" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. gmake[2]: *** [CMakeFiles/custom_interfaces__rosidl_typesupport_cpp.dir/build.make:86: CMakeFiles/custom_interfaces__rosidl_typesupport_cpp.dir/rosidl_typesupport_cpp/custom_interfaces/srv/turn_camera__type_support.cpp.o] Error 1 gmake[1]: *** [CMakeFiles/Makefile2:414: CMakeFiles/custom_interfaces__rosidl_typesupport_cpp.dir/all] Error 2 gmake: *** [Makefile:146: all] Error 2 --- Failed <<< custom_interfaces [20.3s, exited with code 2] Summary: 0 packages finished [20.8s] 1 package failed: custom_interfaces 1 package had stderr output: custom_interfaces
Fixing the error: Adding a dependency
So what was the issue?
Well the OP did not pass the dependencies to rosidl_generate_interfaces
by specifying other packages that their custom interface used. In this case, they did not specify the dependency on sensor_msgs
which their custom srv TurnCamera.srv
used.
They added the find_package
line (in green) but did not add the DEPENDENCIES
line (in red) in the CMakeLists.txt
file. Both lines are necessary when using a msg from another package as a field type:
find_package(rosidl_default_generators REQUIRED) find_package(sensor_msgs REQUIRED) # Add packages that the custom interfaces depend on rosidl_generate_interfaces(${PROJECT_NAME} "srv/TurnCamera.srv" DEPENDENCIES sensor_msgs # Add packages that the custom interfaces depend on )
After adding this line, recompile and source the workspace:
cd ~/ros2_ws colcon build --packages-select custom_interfaces source install/setup.bash
It should work now!
Starting >>> custom_interfaces Finished <<< custom_interfaces [21.1s] Summary: 1 package finished [21.5s]
You can verify that your custom srv has been created successfully by running these two commands:
ros2 interface list | grep custom
ros2 interface show custom_interfaces/srv/TurnCamera
You should get these results respectively:
custom_interfaces/srv/TurnCamera
float32 deg_turn --- sensor_msgs/Image camera_image std_msgs/Header header # builtin_interfaces/Time stamp int32 sec uint32 nanosec string frame_id # Header frame_id should be optical frame of camera # origin of frame should be optical center of cameara # +x should point to the right in the image # +y should point down in the image # +z should point into to plane of the image # If the frame_id here and the frame_id of the CameraInfo # message associated with the image conflict # the behavior is undefined uint32 height # uint32 width # string encoding # # taken from the list of strings in include/sensor_msgs/image_encodings.hpp uint8 is_bigendian # uint32 step # uint8[] data #
The same principles should apply for custom msgs and actions with field types that are msgs from packages rather than simply the primitive built-in-types.
0 Comments