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