What we are going to learn
In this video, you’ll understand what is a ROS2 interface, the common language behind ROS2 messages, services, and actions.
You will also learn:
- How to create and compile your own ROS2 Message Interfaces
- How to create and compile your own ROS2 Service Interfaces
List of resources used in this post
- Use the rosject: https://app.theconstructsim.com/#/l/4a5c5215/
- ROS Development Studio (ROSDS) —▸ http://rosds.online
- ROS2 Courses –▸
- ROS2 Basics in 5 Days (Python): https://app.theconstructsim.com/#/Course/73
- ROS2 Basics in 5 Days (C++): https://app.theconstructsim.com/#/Course/61
Opening the rosject
In order to better understand ROS2 Interfaces, we need to have ROS2 installed in our system, and sometimes it is also useful to have some simulations. To make your life easier, we already prepared a rosject that you can use, with ROS2 already installed: https://app.theconstructsim.com/#/l/4a5c5215/.
You can download the rosject on your own computer if you want to work locally, but just by copying the rosject (clicking the link), you will have a setup already prepared for you.
After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject (below you have a rosject example).
After pressing the Run button, you should have the rosject loaded. Let’s now head to the next section to really get some real practice.
ROS2 Interfaces overview
ROS2 Interfaces is a common language behind ROS2 messages, services, and actions.
Let’s start listing the interfaces. For that, let’s first open a terminal:
After the terminal is open, you can list the interfaces with the command ros2 interface list. The output would be something similar to the following:
ros2 interface list Messages: action_msgs/msg/GoalInfo action_msgs/msg/GoalStatus action_msgs/msg/GoalStatusArray actionlib_msgs/msg/GoalID actionlib_msgs/msg/GoalStatus actionlib_msgs/msg/GoalStatusArray bond/msg/Constants bond/msg/Status builtin_interfaces/msg/Duration builtin_interfaces/msg/Time cartographer_ros_msgs/msg/LandmarkEntry cartographer_ros_msgs/msg/LandmarkList cartographer_ros_msgs/msg/SensorTopics cartographer_ros_msgs/msg/StatusCode cartographer_ros_msgs/msg/StatusResponse cartographer_ros_msgs/msg/SubmapEntry cartographer_ros_msgs/msg/SubmapList cartographer_ros_msgs/msg/SubmapTexture cartographer_ros_msgs/msg/TrajectoryOptions checking_interfaces/msg/NewMsg control_msgs/msg/DynamicJointState control_msgs/msg/GripperCommand control_msgs/msg/InterfaceValue control_msgs/msg/JointComponentTolerance control_msgs/msg/JointControllerState control_msgs/msg/JointJog control_msgs/msg/JointTolerance control_msgs/msg/JointTrajectoryControllerState control_msgs/msg/PidState controller_manager_msgs/msg/ControllerState controller_manager_msgs/msg/HardwareInterface diagnostic_msgs/msg/DiagnosticArray diagnostic_msgs/msg/DiagnosticStatus diagnostic_msgs/msg/KeyValue dwb_msgs/msg/CriticScore dwb_msgs/msg/LocalPlanEvaluation dwb_msgs/msg/Trajectory2D dwb_msgs/msg/TrajectoryScore example_interfaces/msg/Bool example_interfaces/msg/Byte example_interfaces/msg/ByteMultiArray example_interfaces/msg/Char example_interfaces/msg/Empty example_interfaces/msg/Float32 example_interfaces/msg/Float32MultiArray example_interfaces/msg/Float64 example_interfaces/msg/Float64MultiArray example_interfaces/msg/Int16 example_interfaces/msg/Int16MultiArray example_interfaces/msg/Int32 example_interfaces/msg/Int32MultiArray example_interfaces/msg/Int64 example_interfaces/msg/Int64MultiArray example_interfaces/msg/Int8 example_interfaces/msg/Int8MultiArray example_interfaces/msg/MultiArrayDimension example_interfaces/msg/MultiArrayLayout example_interfaces/msg/String example_interfaces/msg/UInt16 example_interfaces/msg/UInt16MultiArray example_interfaces/msg/UInt32 example_interfaces/msg/UInt32MultiArray example_interfaces/msg/UInt64 example_interfaces/msg/UInt64MultiArray example_interfaces/msg/UInt8 example_interfaces/msg/UInt8MultiArray example_interfaces/msg/WString gazebo_msgs/msg/ContactState gazebo_msgs/msg/ContactsState gazebo_msgs/msg/EntityState gazebo_msgs/msg/LinkState gazebo_msgs/msg/LinkStates gazebo_msgs/msg/ModelState gazebo_msgs/msg/ModelStates gazebo_msgs/msg/ODEJointProperties gazebo_msgs/msg/ODEPhysics gazebo_msgs/msg/PerformanceMetrics gazebo_msgs/msg/SensorPerformanceMetric gazebo_msgs/msg/WorldState geometry_msgs/msg/Accel geometry_msgs/msg/AccelStamped geometry_msgs/msg/AccelWithCovariance geometry_msgs/msg/AccelWithCovarianceStamped geometry_msgs/msg/Inertia geometry_msgs/msg/InertiaStamped geometry_msgs/msg/Point geometry_msgs/msg/Point32 geometry_msgs/msg/PointStamped geometry_msgs/msg/Polygon geometry_msgs/msg/PolygonStamped geometry_msgs/msg/Pose geometry_msgs/msg/Pose2D geometry_msgs/msg/PoseArray geometry_msgs/msg/PoseStamped geometry_msgs/msg/PoseWithCovariance geometry_msgs/msg/PoseWithCovarianceStamped geometry_msgs/msg/Quaternion geometry_msgs/msg/QuaternionStamped geometry_msgs/msg/Transform geometry_msgs/msg/TransformStamped geometry_msgs/msg/Twist geometry_msgs/msg/TwistStamped geometry_msgs/msg/TwistWithCovariance geometry_msgs/msg/TwistWithCovarianceStamped geometry_msgs/msg/Vector3 geometry_msgs/msg/Vector3Stamped geometry_msgs/msg/Wrench geometry_msgs/msg/WrenchStamped libstatistics_collector/msg/DummyMessage lifecycle_msgs/msg/State lifecycle_msgs/msg/Transition lifecycle_msgs/msg/TransitionDescription lifecycle_msgs/msg/TransitionEvent map_msgs/msg/OccupancyGridUpdate map_msgs/msg/PointCloud2Update map_msgs/msg/ProjectedMap map_msgs/msg/ProjectedMapInfo nav2_msgs/msg/BehaviorTreeLog nav2_msgs/msg/BehaviorTreeStatusChange nav2_msgs/msg/Costmap nav2_msgs/msg/CostmapFilterInfo nav2_msgs/msg/CostmapMetaData nav2_msgs/msg/Particle nav2_msgs/msg/ParticleCloud nav2_msgs/msg/SpeedLimit nav2_msgs/msg/VoxelGrid nav_2d_msgs/msg/Path2D nav_2d_msgs/msg/Pose2D32 nav_2d_msgs/msg/Pose2DStamped nav_2d_msgs/msg/Twist2D nav_2d_msgs/msg/Twist2D32 nav_2d_msgs/msg/Twist2DStamped nav_msgs/msg/GridCells nav_msgs/msg/MapMetaData nav_msgs/msg/OccupancyGrid nav_msgs/msg/Odometry nav_msgs/msg/Path pcl_msgs/msg/ModelCoefficients pcl_msgs/msg/PointIndices pcl_msgs/msg/PolygonMesh pcl_msgs/msg/Vertices pendulum_msgs/msg/JointCommand pendulum_msgs/msg/JointState pendulum_msgs/msg/RttestResults rcl_interfaces/msg/FloatingPointRange rcl_interfaces/msg/IntegerRange rcl_interfaces/msg/ListParametersResult rcl_interfaces/msg/Log rcl_interfaces/msg/Parameter rcl_interfaces/msg/ParameterDescriptor rcl_interfaces/msg/ParameterEvent rcl_interfaces/msg/ParameterEventDescriptors rcl_interfaces/msg/ParameterType rcl_interfaces/msg/ParameterValue rcl_interfaces/msg/SetParametersResult rmw_dds_common/msg/Gid rmw_dds_common/msg/NodeEntitiesInfo rmw_dds_common/msg/ParticipantEntitiesInfo rosgraph_msgs/msg/Clock sensor_msgs/msg/BatteryState sensor_msgs/msg/CameraInfo sensor_msgs/msg/ChannelFloat32 sensor_msgs/msg/CompressedImage sensor_msgs/msg/FluidPressure sensor_msgs/msg/Illuminance sensor_msgs/msg/Image sensor_msgs/msg/Imu sensor_msgs/msg/JointState sensor_msgs/msg/Joy sensor_msgs/msg/JoyFeedback sensor_msgs/msg/JoyFeedbackArray sensor_msgs/msg/LaserEcho sensor_msgs/msg/LaserScan sensor_msgs/msg/MagneticField sensor_msgs/msg/MultiDOFJointState sensor_msgs/msg/MultiEchoLaserScan sensor_msgs/msg/NavSatFix sensor_msgs/msg/NavSatStatus sensor_msgs/msg/PointCloud sensor_msgs/msg/PointCloud2 sensor_msgs/msg/PointField sensor_msgs/msg/Range sensor_msgs/msg/RegionOfInterest sensor_msgs/msg/RelativeHumidity sensor_msgs/msg/Temperature sensor_msgs/msg/TimeReference shape_msgs/msg/Mesh shape_msgs/msg/MeshTriangle shape_msgs/msg/Plane shape_msgs/msg/SolidPrimitive statistics_msgs/msg/MetricsMessage statistics_msgs/msg/StatisticDataPoint statistics_msgs/msg/StatisticDataType std_msgs/msg/Bool std_msgs/msg/Byte std_msgs/msg/ByteMultiArray std_msgs/msg/Char std_msgs/msg/ColorRGBA std_msgs/msg/Empty std_msgs/msg/Float32 std_msgs/msg/Float32MultiArray std_msgs/msg/Float64 std_msgs/msg/Float64MultiArray std_msgs/msg/Header std_msgs/msg/Int16 std_msgs/msg/Int16MultiArray std_msgs/msg/Int32 std_msgs/msg/Int32MultiArray std_msgs/msg/Int64 std_msgs/msg/Int64MultiArray std_msgs/msg/Int8 std_msgs/msg/Int8MultiArray std_msgs/msg/MultiArrayDimension std_msgs/msg/MultiArrayLayout std_msgs/msg/String std_msgs/msg/UInt16 std_msgs/msg/UInt16MultiArray std_msgs/msg/UInt32 std_msgs/msg/UInt32MultiArray std_msgs/msg/UInt64 std_msgs/msg/UInt64MultiArray std_msgs/msg/UInt8 std_msgs/msg/UInt8MultiArray stereo_msgs/msg/DisparityImage test_msgs/msg/Arrays test_msgs/msg/BasicTypes test_msgs/msg/BoundedSequences test_msgs/msg/Builtins test_msgs/msg/Constants test_msgs/msg/Defaults test_msgs/msg/Empty test_msgs/msg/MultiNested test_msgs/msg/Nested test_msgs/msg/Strings test_msgs/msg/UnboundedSequences test_msgs/msg/WStrings tf2_msgs/msg/TF2Error tf2_msgs/msg/TFMessage trajectory_msgs/msg/JointTrajectory trajectory_msgs/msg/JointTrajectoryPoint trajectory_msgs/msg/MultiDOFJointTrajectory trajectory_msgs/msg/MultiDOFJointTrajectoryPoint turtlesim/msg/Color turtlesim/msg/Pose unique_identifier_msgs/msg/UUID visualization_msgs/msg/ImageMarker visualization_msgs/msg/InteractiveMarker visualization_msgs/msg/InteractiveMarkerControl visualization_msgs/msg/InteractiveMarkerFeedback visualization_msgs/msg/InteractiveMarkerInit visualization_msgs/msg/InteractiveMarkerPose visualization_msgs/msg/InteractiveMarkerUpdate visualization_msgs/msg/Marker visualization_msgs/msg/MarkerArray visualization_msgs/msg/MenuEntry Services: action_msgs/srv/CancelGoal cartographer_ros_msgs/srv/FinishTrajectory cartographer_ros_msgs/srv/StartTrajectory cartographer_ros_msgs/srv/SubmapQuery cartographer_ros_msgs/srv/WriteState checking_interfaces/srv/NewServiceMessage composition_interfaces/srv/ListNodes composition_interfaces/srv/LoadNode composition_interfaces/srv/UnloadNode control_msgs/srv/QueryCalibrationState control_msgs/srv/QueryTrajectoryState controller_manager_msgs/srv/ConfigureController controller_manager_msgs/srv/ConfigureStartController controller_manager_msgs/srv/ListControllerTypes controller_manager_msgs/srv/ListControllers controller_manager_msgs/srv/ListHardwareInterfaces controller_manager_msgs/srv/LoadConfigureController controller_manager_msgs/srv/LoadController controller_manager_msgs/srv/LoadStartController controller_manager_msgs/srv/ReloadControllerLibraries controller_manager_msgs/srv/SwitchController controller_manager_msgs/srv/UnloadController diagnostic_msgs/srv/AddDiagnostics diagnostic_msgs/srv/SelfTest dwb_msgs/srv/DebugLocalPlan dwb_msgs/srv/GenerateTrajectory dwb_msgs/srv/GenerateTwists dwb_msgs/srv/GetCriticScore dwb_msgs/srv/ScoreTrajectory example_interfaces/srv/AddTwoInts example_interfaces/srv/SetBool example_interfaces/srv/Trigger gazebo_msgs/srv/ApplyBodyWrench gazebo_msgs/srv/ApplyJointEffort gazebo_msgs/srv/ApplyLinkWrench gazebo_msgs/srv/BodyRequest gazebo_msgs/srv/DeleteEntity gazebo_msgs/srv/DeleteLight gazebo_msgs/srv/DeleteModel gazebo_msgs/srv/GetEntityState gazebo_msgs/srv/GetJointProperties gazebo_msgs/srv/GetLightProperties gazebo_msgs/srv/GetLinkProperties gazebo_msgs/srv/GetLinkState gazebo_msgs/srv/GetModelList gazebo_msgs/srv/GetModelProperties gazebo_msgs/srv/GetModelState gazebo_msgs/srv/GetPhysicsProperties gazebo_msgs/srv/GetWorldProperties gazebo_msgs/srv/JointRequest gazebo_msgs/srv/LinkRequest gazebo_msgs/srv/SetEntityState gazebo_msgs/srv/SetJointProperties gazebo_msgs/srv/SetJointTrajectory gazebo_msgs/srv/SetLightProperties gazebo_msgs/srv/SetLinkProperties gazebo_msgs/srv/SetLinkState gazebo_msgs/srv/SetModelConfiguration gazebo_msgs/srv/SetModelState gazebo_msgs/srv/SetPhysicsProperties gazebo_msgs/srv/SpawnEntity gazebo_msgs/srv/SpawnModel lifecycle_msgs/srv/ChangeState lifecycle_msgs/srv/GetAvailableStates lifecycle_msgs/srv/GetAvailableTransitions lifecycle_msgs/srv/GetState logging_demo/srv/ConfigLogger map_msgs/srv/GetMapROI map_msgs/srv/GetPointMap map_msgs/srv/GetPointMapROI map_msgs/srv/ProjectedMapsInfo map_msgs/srv/SaveMap map_msgs/srv/SetMapProjections nav2_msgs/srv/ClearCostmapAroundRobot nav2_msgs/srv/ClearCostmapExceptRegion nav2_msgs/srv/ClearEntireCostmap nav2_msgs/srv/GetCostmap nav2_msgs/srv/LoadMap nav2_msgs/srv/ManageLifecycleNodes nav2_msgs/srv/SaveMap nav_msgs/srv/GetMap nav_msgs/srv/GetPlan nav_msgs/srv/LoadMap nav_msgs/srv/SetMap pcl_msgs/srv/UpdateFilename rcl_interfaces/srv/DescribeParameters rcl_interfaces/srv/GetParameterTypes rcl_interfaces/srv/GetParameters rcl_interfaces/srv/ListParameters rcl_interfaces/srv/SetParameters rcl_interfaces/srv/SetParametersAtomically rosbag2_interfaces/srv/GetRate rosbag2_interfaces/srv/IsPaused rosbag2_interfaces/srv/Pause rosbag2_interfaces/srv/PlayNext rosbag2_interfaces/srv/Resume rosbag2_interfaces/srv/Seek rosbag2_interfaces/srv/SetRate rosbag2_interfaces/srv/TogglePaused sensor_msgs/srv/SetCameraInfo slam_toolbox/srv/AddSubmap slam_toolbox/srv/Clear slam_toolbox/srv/ClearQueue slam_toolbox/srv/DeserializePoseGraph slam_toolbox/srv/LoopClosure slam_toolbox/srv/MergeMaps slam_toolbox/srv/Pause slam_toolbox/srv/SaveMap slam_toolbox/srv/SerializePoseGraph slam_toolbox/srv/ToggleInteractive std_srvs/srv/Empty std_srvs/srv/SetBool std_srvs/srv/Trigger test_bond/srv/TestBond test_msgs/srv/Arrays test_msgs/srv/BasicTypes test_msgs/srv/Empty tf2_msgs/srv/FrameGraph turtlesim/srv/Kill turtlesim/srv/SetPen turtlesim/srv/Spawn turtlesim/srv/TeleportAbsolute turtlesim/srv/TeleportRelative visualization_msgs/srv/GetInteractiveMarkers Actions: action_tutorials_interfaces/action/Fibonacci control_msgs/action/FollowJointTrajectory control_msgs/action/GripperCommand control_msgs/action/JointTrajectory control_msgs/action/PointHead control_msgs/action/SingleJointPosition example_interfaces/action/Fibonacci nav2_msgs/action/BackUp nav2_msgs/action/ComputePathThroughPoses nav2_msgs/action/ComputePathToPose nav2_msgs/action/DummyRecovery nav2_msgs/action/FollowPath nav2_msgs/action/FollowWaypoints nav2_msgs/action/NavigateThroughPoses nav2_msgs/action/NavigateToPose nav2_msgs/action/Spin nav2_msgs/action/Wait test_msgs/action/Fibonacci test_msgs/action/NestedMessage tf2_msgs/action/LookupTransform turtlesim/action/RotateAbsolute
As you can see in the output above, the same command returned Messages, Actions, and Services.
Creating our first ROS2 Interface (a message)
If you are using the rosject provided at the beginning of this post, there is already a ROS2 Package called checking_interfaces on the /home/user/ros2_ws/src/checking_interfaces path. The package also already contains a message on the ~/ros2_ws/src/checking_interfaces/msg/NewMsg.msg path.
If you are not using the provided rosject, you can create a package with:
mkdir -p /home/user/ros2_ws/src cd /home/user/ros2_ws/src ros2 pkg create --build-type ament_cmake checking_interfaces
The output would be similar to the following:
going to create a new package package name: checking_interfaces destination directory: /home/user/ros2_ws/src package format: 3 version: 0.0.0 description: TODO: Package description maintainer: ['user <user@todo.todo>'] licenses: ['TODO: License declaration'] build type: ament_cmake dependencies: [] creating folder ./checking_interfaces creating ./checking_interfaces/package.xml creating source and include folder creating folder ./checking_interfaces/src creating folder ./checking_interfaces/include/checking_interfaces creating ./checking_interfaces/CMakeLists.txt
If you are using the rosject you do not need to create the message msg/NewMsg.msg, but for learning purposes, let’s see how to create it.
~/ros2_ws/src/checking_interfaces$ ls ~/ros2_ws/src/checking_interfaces$ ls msg/NewMsg.msg
cd ~/ros2_ws/src/checking_interfaces mkdir msg cd msg touch NewMsg.msg
Then, paste the following content on the NewMsg.msg file:
bool check int16 number string text
If you are wondering how to know which types are accepted for the properties of the new message, the types available are:
ROS2 build-in-types
Type name | C++ | Python | DDS type | |
---|---|---|---|---|
bool | bool | builtins.bool | boolean | |
byte | uint8_t | builtins.bytes* | octet | |
char | char | builtins.str* | char | |
float32 | float | builtins.float* | float | |
float64 | double | builtins.float* | double | |
int8 | int8_t | builtins.int* | octet | |
uint8 | uint8_t | builtins.int* | octet | |
int16 | int16_t | builtins.int* | short | |
uint16 | uint16_t | builtins.int* | unsigned short | |
int32 | int32_t | builtins.int* | long | |
uint32 | uint32_t | builtins.int* | unsigned long | |
int64 | int64_t | builtins.int* | long long | |
uint64 | uint64_t | builtins.int* | unsigned long long | |
string | std::string | builtins.str | string | |
wstring | std::u16string | builtins.str | string |
Compiling our ROS2 Interface
In order to compile our ROS2 Interface, we have to touch the ~/ros2_ws/src/checking_interfaces/CMakeLists.txt file. Again, if you are using the rosject we provided, everything is already prepared for you. For learning purposes, let’s open the file to modify it. Let’s start by opening the Code Editor:
After the Code Editor is open, feel free to open the checking_interfaces/CMakeListst.txt file.
Around line 13 of the CMakeListst.txt file, we have to add the following lines:
find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/NewMsg.msg" )
The first line mentioned above includes the rosidl_default_generators package, which will be used to “compile” our message to make it available for Python and C++, so that our nodes can use the interface.
In the rosidl_generate_interfaces we add the name of the interface (message, service, or action) that we want to compile, which in this case is “msg/NewMsg.msg”.
After setting up the CMakeLists.txt file, you also have to set up the checking_interfaces/package.xml file. We have to add rosidl_default_generators as a build dependency, we also need to add the rosidl_default_runtime execution dependency, and we also need the rosidl_interface_packages “member of group”. In the end, the lines you would need to add are:
<build_depend>rosidl_default_generators</build_depend> <exec_depend>rosidl_default_runtime</exec_depend> <member_of_group>rosidl_interface_packages</member_of_group>
In the end, the final package.xml file would be as follows:
<?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>checking_interfaces</name> <version>0.0.0</version> <description>TODO: Package description</description> <maintaineremail="user@todo.todo">user</maintainer> <license>TODO: License declaration</license> <buildtool_depend>ament_cmake</buildtool_depend> <build_depend>rosidl_default_generators</build_depend> <exec_depend>rosidl_default_runtime</exec_depend> <member_of_group>rosidl_interface_packages</member_of_group> <test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_common</test_depend> <export> <build_type>ament_cmake</build_type> </export> </package>
cd ~/ros2_ws/ colcon build --packages-select checking_interfaces
The package should compile with no errors:
... This may be promoted to an error in a future release of colcon-core. Starting >>> checking_interfaces Finished <<< checking_interfaces [5.27s] Summary: 1 package finished [5.87s]
After the package is compiled, we can now source the installation folder so that ROS can find what we have compiled so far:
source install/setup.bash
If we now list the interfaces again and search for our NewMsg, we should be able to find it:
ros2 interface list | grep New # ... checking_interfaces/msg/NewMsg # ...
As we can see in the output above, we have a message called NewMsg.
Using the interface we just created
If we have just created the checking_interfaces/msg/NewMsg, we should be able to use it. We can check its definition with:
ros2 interface show checking_interfaces/msg/NewMsg
which shows the exact thing we defined in the NewMsg.msg file:
bool check int16 number string text
Let’s now create a publisher in a topic called /testing using this message:
ros2 topic pub /testing checking_interfaces/msg/NewMsg
After pressing ENTER, we should see the message being published with default values:
publisher: beginning loop publishing #1: checking_interfaces.msg.NewMsg(check=False, number=0, text='') publishing #2: checking_interfaces.msg.NewMsg(check=False, number=0, text='') publishing #3: checking_interfaces.msg.NewMsg(check=False, number=0, text='') publishing #4: checking_interfaces.msg.NewMsg(check=False, number=0, text='') publishing #5: checking_interfaces.msg.NewMsg(check=False, number=0, text='') publishing #6: checking_interfaces.msg.NewMsg(check=False, number=0, text='') publishing #7: checking_interfaces.msg.NewMsg(check=False, number=0, text='') ...
You can of course set the values of the message:
ros2 topic pub /testing checking_interfaces/msg/NewMsg "{check: true, number: 7, text: 'Be perfect' }" # WHICH OUTPUTS publisher: beginning loop publishing #1: checking_interfaces.msg.NewMsg(check=True, number=7, text='Be perfect') publishing #2: checking_interfaces.msg.NewMsg(check=True, number=7, text='Be perfect') publishing #3: checking_interfaces.msg.NewMsg(check=True, number=7, text='Be perfect') ...
Creating our second ROS2 Interface (a service)
Similar to when defining our message, we already have a service defined on ~/ros2_ws/src/checking_interfaces/srv/NewServiceMessage.srv, but we will be following the process for learning purposes in case you are not using the rosject we provided, or wants to learn with hands-on.
cd ~/ros2_ws/src/checking_interfaces mkdir srv cd srv touch NewServiceMessage.srv
You can now open the NewServiceMessage.srv file with the Code Editor and paste the following content on it:
bool check --- int16 number string text
In order to compile the service interface, you have to open the CMakeLists.txt file again and add “srv/NewServiceMessage.srv” right after “msg/NewMsg.msg” that we added earlier around line 15 of our CMakeLists.txt file. The rosidl_generate_interfaces section of the file would be like:
find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/NewMsg.msg" "srv/NewServiceMessage.srv" )
cd ~/ros2_ws/ colcon build --packages-select checking_interfaces source install/setup.bash
If you now list the interfaces, you should be able to easily find our NewServiceMessage.
ros2 interface list | grep New checking_interfaces/msg/NewMsg checking_interfaces/srv/NewServiceMessage
Congratulations. You now know how to easily create ROS2 Interfaces. Please go ahead and try to create ROS2 Action Interfaces yourself, or you can also check the courses that we have listed at the end of this post.
Youtube video
So this is the post for today. Remember that we have the live version of this post on YouTube. If you liked the content, please consider subscribing to our youtube channel. We are publishing new content ~every day.
Keep pushing your ROS Learning.
Related Courses & Training
If you want to learn more about ROS and ROS2, we recommend the following courses:
- ROS2 Basics in 5 Days (Python): https://app.theconstructsim.com/#/Course/73
- ROS2 Basics in 5 Days (C++): https://app.theconstructsim.com/#/Course/61
0 Comments