ROS2 Concepts in Practice #4 – Interfaces

Written by Ruben Alves

13/05/2022

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

  1. Use the rosject: https://app.theconstructsim.com/#/l/4a5c5215/
  2. ROS Development Studio (ROSDS) —▸ http://rosds.online
  3. ROS2 Courses –▸
    1. ROS2 Basics in 5 Days (Python): https://app.theconstructsim.com/#/Course/73
    2. 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).

Learn ROS2 Parameters - Run rosject

Learn ROS2 – Run rosject (example of the RUN button)

 

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:

Open a new Terminal

Open a new 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:

Open the IDE - Code Editor

Open the IDE – 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>
After saving the files, you can compile the interface with:
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"
)
As you can see so far, the same rosidl_generate_interfaces is used to compile Messages and Services.
You may have noticed that we have a line containing “—“ in the NewServiceMessage.srv file. These three “—” basically separate the Service Request from the Service Response.
The request will be “bool check“, and the fields used in a response will be “int16 number” and “string text“.
After saving the file changes, we can just compile the service interface in the same way that we compiled the message interface:
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:

Masterclass 2023 batch2 blog banner

Check Out These Related Posts

129. ros2ai

129. ros2ai

I would like to dedicate this episode to all the ROS Developers who believe that ChatGPT or...

read more

0 Comments

Submit a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Pin It on Pinterest

Share This