1. msg 和 srv
- 简介
- msg:是文本文件,描述消息的字段,自动生成不同语言的源代码;
- srv:描述一个服务的请求与响应。
msg文件存放在软件包的msg目录下,srv文件则存放在srv目录下。msg字段可使用的类型为:
- int8, int16, int32, int64 (以及 uint*)
- float32, float64
- string
- time, duration
- 其他msg文件
- variable-length array[] 和 fixed-length array[C]
ROS中还有一个特殊的数据类型:Header,它含有时间戳和ROS中广泛使用的坐标帧信息。在msg文件的第一行经常可以看到Header header。
- msg使用流程
2.1 创建msg
打开package.xml确保包含以下两行:$ roscd beginner_tutorials $ mkdir msg $ echo "int64 num" > msg/Num.msg
打开CMakeLists.txt,找到find_package,添加message_generation依赖项,改成如下所示:<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
找到add_message_files代码块,改成:find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation )
add_message_files( FILES Num.msg )
确保generate_messages()函数被调用。找到generate_messages代码块,去掉注释。
2.2 使用消息
如果rosmsg可以识别生成的消息,说明msg创建没有问题。
$ rosmsg show [message type]
rosmsg可用命令:
rosmsg show Show message description
rosmsg list List all messages
rosmsg md5 Display message md5sum
rosmsg package List messages in a package
rosmsg packages List packages that contain messages
- 使用srv
3.1 创建srv
srv文件格式类似如下:
我们可以从另外一个包中复制一个srv,使用:int64 A int64 B --- int64 Sum
$ roscp [package_name] [file_to_copy_path] [copy_path]
$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
类似于msg,srv也需要配置依赖message_generation等依赖。配置方式于上节类似。最后将add_service_files注释打开即可。
3.2 使用rossrv
如果srv创建成功,rossrv可以进行查看:
$ rossrv show <service type>
2. 简单的发布与订阅
2.1. 编写发布节点
$ roscd beginner_tutorials
$ mkdir src
$ cd src
创建talker.cpp文件并粘贴以下内容:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
2.2 编写订阅节点
创建listener.cpp,粘贴以下内容:
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}
2.3 构建节点
在CMakeLists.txt文件中增加以下内容:
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
2.4 测试
运行发布者:
$ rosrun beginner_tutorials talker
运行订阅者:
$ rosrun beginner_tutorials listener
3. 简单服务与客户端
3.1 创建srv
$ roscd beginner_tutorials
mkdir srv
创建AddTwoNum.srv文件,并粘贴以下内容:
int64 A
int64 B
---
int64 Sum
CMakeLists.txt需进行以下修改:
- 为find_package调用添加message_generation依赖项;
- 将AddTwoNum.srv加入到add_service_files项中;
- 打开generate_messages项
编译并用rossrv查看srv是否生成成功。
3.2 编写服务节点代码
在beginner_tutorials包中创建src/add_two_ints_server.cpp文件并粘贴以下内容进去:
#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
bool add(beginner_tutorials::AddTwoInts::Request &req,
beginner_tutorials::AddTwoInts::Response &res)
{
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server");
ros::NodeHandle n;
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
3.3 编写客户端代码
在beginner_tutorials包中创建src/add_two_ints_client.cpp文件并粘贴以下内容进去:
#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
#include <cstdlib>
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_client");
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y");
return 1;
}
ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
beginner_tutorials::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}
3.4 构建节点
在CMakeLists.txt中新增以下内容:
add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp)
add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)