ROS msg和srv的介绍
- msg:msg文件是一个描述ROS消息字段的简单文本文件。它们用于为消息生成不同语言的源代码。
- srv:一个srv文件描述了一个service。其由两个部分组成,包括一个请求和一个响应。
msg文件存储在package包中的msg文件夹,srv文件存储在srv文件夹。
msg文件只是一个简单的文本文件,每一行包括一个字段类型和一个字段名称。字段可以使用下述类型:
int8, int16, int32, int64 (plus uint*) float32, float64 string time, duration other msg files variable-length array[] and fixed-length array[C]
其中还有一个特殊的类型ROS: Header,header包含一个时间戳和坐标框架信息,常在ROS中使用。我们常在msg文件中的第一行看到这样的内容:Header header
这里有一个例子:
Header header string child_frame_id geometry_msgs/PoseWithCovariance pose geometry_msgs/TwistWithCovariance twist
srv文件就像msg文件一样,但它包括两个部分:一个请求和一个响应。这两个部分通过一行 ‘—’ 线进行区分,这里有一个srv文件的例子:
int64 A int64 B --- int64 Sum
即A和B是请求,而Sum是响应。
使用msg
创建一个msg
首先,在前述博客:ROS学习-创建一个Package包创建的beginner_tutorials包中定义一个新的msg。命令如下:
$ roscd beginner_tutorials $ mkdir msg $ echo "int64 num" > msg/Num.msg
切换到beginner_tutorials文件夹,然后创建msg文件夹,输入"int64 num"内容到msg文件夹的Num.msg文件。
上述创建的Num.msg文件只有一行内容,当然我们也可以加入多行内容,比如说加入:
string first_name string last_name uint8 age uint32 score
不过,还有一步操作,我们需要确保msg文件转换成C++源码、Python源码,或者其他语言格式。
打开beginner_tutorials包中的package.xml文件,确保下述两行内容没有被注释掉:
<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
注意:上述内容是我们在编译期间是需要 “message_generation”,在运行期间,我们仅需要"message_runtime"。
打开CMakeLists.txt文件,在其中的find_package中加入message_generation依赖,简单修改为如下形式:
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation )
我们可能会注意到,有时即使没有调用find_package中所有依赖项的包,我们的项目也可以正常构建。这是因为catkin把我们所有的项目集中到一个中,所以如果一个之前的项目使用了find_package,且你在其中配置了相同的值,就不会出现错误。但是项目中忘记了添加对应的依赖在独立构建的过程中很容易出现中断。
同时,确保导出了message runtime 的依赖。
catkin_package( # INCLUDE_DIRS include # LIBRARIES beginner_tutorials CATKIN_DEPENDS roscpp rospy std_msgs message_runtime # DEPENDS system_lib )
同时,找到下述内容:
## Generate messages in the 'msg' folder # add_message_files( # FILES # Message1.msg # Message2.msg # )
去除其注释,并修改为下述形式:
add_message_files( FILES Num.msg )
通过手工添加.msg文件,我们能够确保CMake能够知道何时在你添加其他.msg文件之后重新配置项目。
现在,我们必须确保generate_messages()函数被调用了,找到下述内容并去除注释:
## Generate added messages and services with any dependencies listed here # generate_messages( # DEPENDENCIES # std_msgs # )
现在我们已经准备好能够从msg定义中生成源文件,如果我们想要现在去这样做可以直接跳到: msg和srv的通用步骤 中进行处理。
使用rosmsg命令
上述就是在ROS中创建一个msg所需要的全部操作,接下来,我们需要确保在ROS中能够通过rosmsg命令看到他们,命令用法如下:
$ rosmsg show [message type]
比如,对于我们创建的 beginner_tutorials中名称为Num的msg。命令变为下述形式:
$ rosmsg show beginner_tutorials/Num
输出结果为:
int64 num string first_name string last_name uint8 age uint32 score
此外,如果我们忘了哪个包Package中包含这个msg,那么我们可以直接留空Package的名字,直接使用下述命令。
$ rosmsg show Num
可以得到下述信息:
[beginner_tutorials/Num]: int64 num string first_name string last_name uint8 age uint32 score
使用srv
创建一个srv
使用下述命令,创建一个新的srv文件夹。
$ roscd beginner_tutorials $ mkdir srv
与前述手工创建一个msg文件并输入相关内容不同的是,在这里我们从其他package包中复制一个已有的srv文件。
这里,使用一个roscp命令来进行从其他包中复制到当前的beginner_tutorials的srv文件夹中。roscp命令的用法如下:
$ roscp [package_name] [file_to_copy_path] [copy_path]
例如,我们从rospy_tutorials包中复制AddTwoInts.srv文件到当前包的srv文件夹。命令变为下述形式:
$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
这里也还有一个更多的步骤,即我们需要把srv文件转换成C++, Python或者其他语言。
首先,打开beginner_tutorials包中的package.xml文件,确保下述两行内容没有被注释掉(与上述的msg过程类似):
<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
如前所述的,在编译期间,我们需要message_generation,而在运行期间,我们使用message_runtime。
接着,在CMakeLists.txt文件,找到其中的find_package并在其中加入message_generation依赖,简单修改为如下形式(如果在之前的msg介绍中已经添加则不用处理了):
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation )
注意:不用管这个message_generation的名字,它对于msg和srv都起作用。
同样,我们还需要在package.xml文件中进行同样的操作,来对services进行处理,类似于messages去除下述代码的注释,来增加需要的依赖。
# add_service_files( # FILES # Service1.srv # Service2.srv # )
并修改为如下形式,替换Service2.srv为我们自己的AddTwoInts.srv文件:
add_service_files( FILES AddTwoInts.srv )
使用rossrv命令
上述就是在ROS中创建一个srv所需要的全部操作,接下来,我们需要确保在ROS中能够通过rossrv命令看到他们,命令用法如下:
$ rossrv show <service type>
例如,我们通过下述命令来查看beginner_tutorials/AddTwoInts中的内容。
$ rossrv show beginner_tutorials/AddTwoInts
返回输出值:
int64 a int64 b --- int64 sum
当然,我们也可以使用类似与rosmsg命令的用法,省略package包的名字,而直接用srv的名字。命令如下:
$ rossrv show AddTwoInts
返回下述内容:
[beginner_tutorials/AddTwoInts]: int64 a int64 b --- int64 sum [rospy_tutorials/AddTwoInts]: int64 a int64 b --- int64 sum
说明我们在beginner_tutorials包中以及rospy_tutorials包中都找到了这个文件,内容为两个int64的请求,和一个int64 sum的相应。
msg和srv的通用步骤
去除CMakeLists.txt文件中的下述内容注释(如果上述步骤中我们已经做过,则可以跳过)。
# generate_messages( # DEPENDENCIES # # std_msgs # Or other packages containing msgs # )
去除之后变成下述形式:
generate_messages( DEPENDENCIES std_msgs )
如果我们在.msg文件中所依赖的包,这里我们依赖了std_msgs包。
现在,我们需要重新编译一下beginner_tutorials这个包,来生成新的messages。
# In your catkin workspace $ roscd beginner_tutorials $ cd ../.. $ catkin_make
在msg文件夹中的任意.msg文件都将生成所有支持语言的源码。
C++ message的头文件将生成在: ~/catkin_ws/devel/include/beginner_tutorials/文件夹中。
Python语言将生成在:~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg文件夹中。
Lisp语言将生成在:~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/文件夹中。
类似的,在srv文件夹中的任意.srv文件也会生成支持C++语言,Python语言,Lisp语言,存放在对应的文件夹中。
使用Help
我们已经看到了很多ROS工具,但是记住每个命令需要的参数可能很困难。幸运的是,大多数ROS工具都提供了自己的帮助。
例如,对于我们上述所使用的rosmsg命令:
$ rosmsg -h
返回如下值:
rosmsg is a command-line tool for displaying information about ROS Message types. Commands: rosmsg show Show message description rosmsg info Alias for rosmsg show rosmsg list List all messages rosmsg md5 Display message md5sum rosmsg package List messages in a package rosmsg packages List packages that contain messages Type rosmsg <command> -h for more detailed usage
当然,我们还可以得到关于子命令的帮助。例如第一个rosmsg show。使用命令:
$ rosmsg show -h
返回如下值:
Usage: rosmsg show [options] <message type> Options: -h, --help show this help message and exit -r, --raw show raw message text, including comments -b BAGFILE, --bag=BAGFILE show message from .bag file
简要总结回顾
我们在上述内容中使用了多个ROS命令,对这些命令进行简单总结:
rospack = ros+pack(age) : 返回ROS包的相关信息
roscd = ros+cd : 切换到ROS包或堆栈所在的路径
rosls = ros+ls : 列出ROS包中的所有文件
roscp = ros+cp : 从ROS包中复制指定的文件
rosmsg = ros+msg : 提供ROS包message定义的相关信息
rossrv = ros+srv : 提供ROS包service定义的相关信息
catkin_make : 编译工作空间中的ROS包
rosmake = 如果不在catkin工作空间中,使用这个命令进行编译ROS包。