Lab 5.3. ROS Package, msg, srv
Estimated time to complete this lab: 1 hour
Objectives
At the end of this self-learning lab, you should be able to:
- recognize the workspace-package-node file structure in ROS
- create a package in ROS
- know the function of
catkin_make
,CMakeLists.txt
andpackage.xml
- create your own msg and srv
Preparations
There are no preparations needed! In this lab, you will create a package, node, msg and srv from scratch.
Section 1. What is a package?
Recommended reading: m2_wiki – ROS (II: Package):
- Software in ROS is organized in packages.
- A package may contain whatever what constitutes a useful module, such as:
- ROS nodes
- ROS-independent library
- dataset, configuration files
When should I create a new package?
Create a package if your functionality doesn't fit into any of the existing packages!
- Packages should contain enough functionality to be useful and easy-to-consume, but not too much that the package is heavyweight and difficult to use.
- Functions in a package should be independent and similar.
- Ideally, one package maps to one Git repository, and only 1 or 2 developers are working on a package at any time.
Workspace-package structure
- A workspace contains multiple packages. For example,
catkin_ws
is a workspace that contains packages namedpackage_1
andpackage_2
. - Packages are usually placed under the
/src
directory of a catkin workspace. - Each package must have its own folder.
workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin
package_1/
CMakeLists.txt -- CMakeLists.txt file for package_1
package.xml -- Package manifest for package_1
src/ -- Source files for pakcage_1
msg/ -- Message files for package_1
srv/ -- Service files for package 1
...
package_n/
CMakeLists.txt -- CMakeLists.txt file for package_n
package.xml -- Package manifest for package_n
src/ -- Source files for pakcage_n
msg/ -- Message files for package_n
srv/ -- Service files for package n
- a package must include:
- a catkin compliant package.xml file.
- This provides metadata about the package.
- a CMakeLists.txt which uses catkin.
- This provides information to build the package.
- Nodes, msg and srv can go under the
/src
,/msg
and/srv
subdirectories of a package respectively.
Try it yourself: Creating a package
- Change to the source space directory of your catkin workspace.
$ cd ~/catkin_ws/src
- Now use the
catkin_create_pkg
command to create a new package calledpack1
which has the dependencies ofstd_msgs
,roscpp
, androspy
:
$ cd ~/catkin_ws/src
$ catkin_create_pkg pack1 std_msgs roscpp rospy
- This will create a `pack1` folder under `catkin_ws/src/`
- `pack1` now contains a `package.xml` and `CMakeLists.txt`, which have been generated with the `catkin_create_pkg` command arguments.
- Now, navigate to your workspace root (
catkin_ws/
) and runcatkin_make
- This will build the packages in the catkin workspace, and let ROS recognize that there is a new package in the workspace.
- We will further elaborate on
catkin_make
later this lab.
$ cd ~/catkin_ws/
$ catkin_make
- You can also verify that ROS recognizes the new package using
rospack list
:
$ rospack list | grep pack1
pack1 /home/m2/catkin\_ws/src/pack1
- If you see
pack1
in the list of packages, then you have successfully created a new package! We will put some useful codes in it later on.
In the following sections, we will (very) briefly introduce CMakeLists.txt and package.xml. You are recommended to open up these files while you read this lab. If you find it confusing, feel free to skip to Section 2, you can still create a msg/srv later on.
CMakeLists.txt
- The build system of ROS is catkin.
-
We are referring to the CMakeLists.txt inside a package (
pack1/CMakeLists.txt
),
Don't mix it up with the CMakeLists.txt in the root of the ROS workspace (catkin_ws/CMakeLists.txt
)! Leave the workspace root CMakeLists.txt alone. -
This file is a CMake file for everything that needs to be compiled in this ROS package, including:
- programs written in C++
- note that Python nodes do NOT need to be compiled.
- messages, services, actions
- even if you are using Python, some code is needed to be generated for msg and srv, which is built via CMake.
- exported dependencies.
- programs written in C++
ROS package dependencies (more advanced, optional)
- A package dependency is some external package that is required in order for the current package to be able to be compiled.
- All ROS packages used must be declared in CMakeLists.txt and package.xml.
- For example, if
std_msgs
is to be used, the line
find_package(catkin REQUIRED)
Should be changed to:
find_package(catkin REQUIRED COMPONENTS std_msgs)
If another package called m2_umd
is needed, append it to the end of this line like:
find_package(catkin REQUIRED COMPONENTS std_msgs m2_umd)
catkin_make
- This is the command to rebuild a ROS workspace.
- Run this command at the root of the ROS workspace (NOT the root of a ROS package).
- The rebuild process will throw weird warnings and errors if package.xml or CMakeLists.txt of any package in the workspace is not configured correctly.
- For common errors in catkin_make, please see the article in m2_wiki: https://github.com/m2robocon/m2_wiki/wiki/ROS-(Part-II:-Package)#common-error-locations
You need to catkin_make
when:
- Adding/removing a package
- Editing C++ code/headers
- Editing dependencies (package.xml or CMakeLists.txt)
- Editing messages/services/actions.
Note that editing Python codes does not need a catkin_make
. That's why we like Python as we don't have to deal with as many issues in the build system. Also, when program running time is not a critical concern, we can afford to use Python, which allows us to skip the build process when testing programs, enabling faster development speed.
package.xml
- This file includes all information readable by catkin and humans about the package.
ROS package dependencies
- Add
<depend>rospy</depend>
if you are writing Python. - Add
<depend>roscpp</depend>
if you are writing C++. - Add
<depend>[package_name]</depend>
if you are using that package.- E.g. if you are using std_msgs, add
<depend>std_msgs</depend>
- E.g. if you are using m2_umd, add
<depend>m2_umd</depend>
- E.g. if you are using std_msgs, add
Milestone
Now that we know what these "package configuration files" do, we can add our own msg and srv!
Section 2. Creating a msg and srv
- msg: a text file that describes the fields of a ROS message.
- srv: a text file that describes a services. It is split into two parts: request and response.
- msg files are stored in the
msg
directory of a package, and srv files are stored in thesrv
directory.
Field types (for both msg and srv)
For details, see http://wiki.ros.org/msg
- bool
- int8, int16, int32, int64, float32, float64
- Signed numbers should be used in most general cases.
- string
- time, duration, Header
- variable length array[] and fixed-length array[len]
- other msg files
Try it yourself: Create a new msg
Let's create a new message type that can be used to handle the output of a distance sensor. In Robocon, the distance sensor is often used to find the distance between the robot and a fence or obstacle.
- Create a new directory named
msg
underpack1
, and underpack1/msg/
, create a new text file namedDistanceSensorStatus.msg
- By ROS naming convention, message file names should be in CamelCase.
$ roscd pack1
$ mkdir msg && cd msg
$ touch DistanceSensorStatus.msg
- Type the following inside
DistanceSensorStatus.msg
- For each message field, you should add a line
[type] [name]
- For each message field, you should add a line
DistanceSensorStatus.msg
int32 status
float32 distance
- E.g. The first line: there is a field named `status` whose data type is `int32`.
You have already created a new message file! However, some changes are needed to be made in CMakeLists.txt and package.xml in order for the message to be useable by packages in ROS. Before that, let's create a srv which has a similar structure!
Try it yourself: Create a new srv
Let's create a new service type that can be used to handle the output shifted value of a distance sensor. In Robocon, even if the robot is fully touching a wall, a distance sensor pointed in the normal direction to the wall may not be reading 0 value due to the placement of sensor. Output shift eliminates such inconvenience.
- Create a new directory named
srv
under pack1, and underpack1/srv/
, create a new text file namedSetDistanceSensorShift.srv
- By ROS coding convention, service file names should be in CamelCase.
$ roscd pack1
$ mkdir srv && cd srv
$ touch SetDistanceSensorShift.srv
- Type the following inside
SetDistanceSensorShift.srv
- Same as msg, for each service field, you should add
[type] [name]
- For a srv, you must add the line
---
You must do this even if the Request and/or Response part of the service are empty. - The fields above
---
are the Request part, while those below---
are the Response part.
- Same as msg, for each service field, you should add
SetDistanceSensorShift.srv
float32 distance
---
bool success
string message
I just want to use my own msg and srv, how come I need to learn about CMakeLists.txt?
You need to make modifications to those files in order for them to be used in ROS!
CMakeLists.txt: Modifications for message and service
- add
message_generation
to the list ofCOMPONENTS
infind_package
:
# Do not just add this to your CMakeLists.txt, modify the
existing text to add message_generation before the closing
parenthesis
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
- add
message_runtime
to the list ofCATKIN_DEPENDS
incatkin_package
Make sureCATKIN_DEPENDS
is uncommented (remove the first#
) as well:
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES pack1
CATKIN_DEPENDS roscpp rospy message_runtime
# DEPENDS system_lib
)
- uncomment
generate_messages
generate_messages( # uncommented!
DEPENDENCIES
std_msgs
)
- messages: uncomment the block of
add_message_files
, replace the list of.msg
files with the.msg
files in your package
add_message_files(
FILES
# Message1.msg
# Message2.msg
DistanceSensorStatus.msg
)
- services: uncomment the block of
add_service_files
, replace the list of.srv
files with the.srv
files in your package
add_service_files(
FILES
SetDistanceSensorShift.srv
)
package.xml: Modifications for message and service
- Open package.xml, and make sure these two lines are in it and uncommented:
Uncomment a line in xml by removing the
<!--
at the front and-->
at the back.
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
catkin_make: build the package again, and verify your msg/srv has been generated
- We need to run
catkin_make
in order for the msg and srv code to be generated.
$ cd ~/catkin_ws/
$ catkin_make
- You can verify that ROS has seen your msg/srv by using
rosmsg list
/rossrv list
$ rosmsg list | grep "pack1"
pack1/DistanceSensorStatus
$ rossrv list | grep "pack1"
pack1/SetDistanceSensorShift
- You can even see the fields of a msg/srv in the command line using
rosmsg show
/rossrv show
$ rosmsg show pack1/DistanceSensorStatus
int32 status
float32 distance
$ rossrv show pack1/SetDistanceSensorShift
float32 distance
---
bool success
string message
Checklist and Assignment
Completion
Congratulations! You have successfully create a msg and srv in ROS!
You can even test the msg and srv with a node. The example package created in this lab is stored in m2cs_ros_tutorial/pack1/
, and the nodes are stored in pack1/src
. You should find the nodes similar to those introduced in Lab 5.1 and 5.2.
Now, you should have enough knowledge to finish Assignment 2 (Automatic path)
- Understand CMakeLists.txt, package.xml, catkin_make
- Create a msg and srv
References
- ROS Tutorial – Creating a ROS Package: http://wiki.ros.org/ROS/Tutorials/CreatingPackage
- m2_wiki – ROS II: Package: https://github.com/m2robocon/m2_wiki/wiki/ROS-(Part-II:-Package)
- ROS Tutorial – Creating a ROS msg and srv: http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv