一、msg和srv介绍
msg: msg文件使用简单的文本格式声明一个ROS message的各个域。仅需要创建一个msg文件,就可以使用它来生成不同语言的message定义代码。
srv:srv文件则声明了一个服务,包括request(请求)和response(响应)。
msg文件和srv文件分别存储在包的msg目录和srv目录下。
1、msg文件
msgs是简单的txt文件,每行定义一个信息域,每行的格式为:
信息域的名称 信息域的类型
信息域的类型有以下几种:
int8, int16, int32, int64 (plus uint*)
float32, float64
string
time, duration
other msg files
variable-length array[] and fixed-length array[C]
这里是一个示例,此例使用了一个Header类型,一个原始字符串类型,还有两个其他预定义好的其他类型:
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
2、srv文件
srv文件和msg文件类似,唯一不同的是它包含两个部分——request和response。两部分用---
分隔:
int64 A
int64 B
---
int64 Sum
上面的示例中,A和B是request,Sum是response。
二、使用msg
1、创建一个msg
让我们在前面创建的包beginner_tutorials
中使用msg文件定义一个msg,如果此包已被删除的话,请参考本系列的第一篇文章重新创建这个包。
首先进入包目录:
roscd beginner_tutorials
创建一个msg目录:
mkdir msg
然后使用以下方式创建Num.msg
文件(你也可以自行创建,使用编辑器编辑后保存):
echo "int64 num" > msg/Num.msg
上面创建的文件仅包含一行,当然你也可以向其中添加更多的信息域,每个一行,例如:
string first_name
string last_name
uint8 age
uint32 score
创建好之后,我们需要确保msg文件能够被转换为c++/python或者其他语言的代码。
打开package.xml
文件,确保里面存在这两行且去掉它们的注释:
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
需要指出,在构建阶段我们需要 "message_generation"
, 而在运行时我们需要 "message_runtime"
。
然后打开包目录下的CMakeLists.txt
文件,在find_message
调用中添加message_generation
依赖,让你可以生成ROS信息。
如下所示,括号里添加一项message_generation
即可:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
你也许注意到有时你构建项目的时候,即使你没有在CMakeLists.txt
中调用find_package
,仍然构建正常。这是因为catkin
将你所有的项目集成到一起,只要你之前的项目调用了find_package
,现在的项目就会被配置为相同的调用。但是这是存在隐患的,当你独立构建一个项目的时候,缺少find_package
调用会导致构建失败。
然后同上面类似,确保你加入了message_runtime
依赖,如图所示:
然后找到如下代码段:
去掉注释,改为:
add_message_files(
FILES
Num.msg
)
然后,确保generate_messages()
函数被调用:
去掉注释,修改为:
generate_messages(
DEPENDENCIES
std_msgs
)
现在所有的文件都准备好了,总结一下,大概有这么几个步骤:
- 在msg目录下使用msg文件语法定义一个msg
- 修改
CmakeLists.txt
,在find_package
调用中,添加message_generation
依赖 - 修改
CmakeLists.txt
,在catkin_message
下添加message_runtime
依赖 - 修改
CmakeLists.txt
,去掉add_message_files
注释,添加我们自己定义的msg文件 - 修改
CmakeLists.txt
,去掉generate_messages()
的注释
三、使用rosmsg
我们可以使用rosmsg
命令查看我们定义的msg的详细信息,以确保它能被ROS正确识别:
rosmsg show beginner_tutorials/Num
会得到:
int64 num
如果你忘了msg位于哪个包中,你也可以省略包名:
rosmsg show Num
得到:
[beginner_tutorials/Num]:
int64 num
四、使用srv
1、创建一个srv
同样是先定义srv文件:
roscd beginner_tutorials
mkdir srv
避免手动创建的麻烦,我们可以使用roscp
命令从其他包里拷贝一份srv
文件出来,用法:
roscp [package_name] [file_to_copy_path] [copy_path]
在这里,我们从rospy_tutorials
拷贝一份srv
文件出来:
roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
同上面类似的,确保srv文件能够被转为代码,我们需要向package.xml
中添加内容:
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
这里前一步创建msg的时候已经做过了,所以在这里我们可以省略这一步。
同样的,添加message_generation
依赖,我们也做过了:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
接下来就是要将我们的srv文件添进项目了:
找到这段:
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
去掉注释且修改为:
add_service_files(
FILES
AddTwoInts.srv
)
可以发现,创建srv的流程同msg基本一致。
2、使用rossrv
我们可以使用rossrv
命令查看我们创建的服务的信息,确保它被ROS正确识别:
rossrv show beginner_tutorials/AddTwoInts
得到:
int64 a
int64 b
---
int64 sum
类似于rosmsg
,你也可以省略包名:
$ rossrv show AddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum
[rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum
五、使用msg和srv的基本流程
1、msg依赖
我们在前面已经做过这一步,修改CMakeLists.txt
:
# generate_messages(
# DEPENDENCIES
# # std_msgs # Or other packages containing msgs
# )
去掉注释,然后添加我们依赖的任何包:
generate_messages(
DEPENDENCIES
std_msgs
)
这里解释一下依赖的问题,像前面介绍的那样,我们在编写msg文件时,不止可以使用原生的int、string等类型,有时候也会用到其他包里预定义好的信息类型,比如前面的例子中的geometry_msgs/PoseWithCovariance pose
,当我们需要用到其他包里定义好的信息时,我们就要声明对其他包的依赖,比如上面的例子里我们就要声明一个geometry_msgs
的依赖。
而在前面的例子中,我们的msg文件中只有这一行:
int64 num
仅仅使用了原生的int类型,所以我们只需要声明std_msgs
依赖即可。
2、开始构建
所有的msg和srv文件已定义好,CmakeLists.txt文件也已经修改好,现在我们就可以构建我们的beginner_tutorial
包了。
现在我们位于beginner_tutorial
包的目录下,执行以下命令进入工作空间的顶层目录:
cd ../..
执行:
catkin_make install
现在,msg目录下的所有.msg文件,都会生成ROS支持的语言的源代码,C++的头文件在~/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/
里。
同msg的位置类似,C++的srv头文件与msg头文件位于同一目录下,而python和lisp在msg目录之外存在一个srv目录存放srv文件生成的代码。
六、获取帮助
我们已经学习了很多ROS命令,记住每个命令的参数和用法是很困难的,我们可以使用帮助查看具体用法。
例如:
rosmsg -h
或者:
rosmsg show -h
七、复习
rospack = ros+pack(age) : provides information related to ROS packages
roscd = ros+cd : changes directory to a ROS package or stack
rosls = ros+ls : lists files in a ROS package
roscp = ros+cp : copies files from/to a ROS package
rosmsg = ros+msg : provides information related to ROS message definitions
rossrv = ros+srv : provides information related to ROS service definitions
catkin_make : makes (compiles) a ROS package rosmake = ros+make : makes (compiles) a ROS package (if you‘re not using a catkin workspace)