创建简单的服务和客户端
创建服务端和客户端
ROS message(msg与srv介绍)
msg
简介
- ROS 使用简化的消息描述语言来描述 ROS 节点发布的数据值(又名消息)
- ROS消息类型,即是ROS话题的格式,可视为ROS的数据类型,基本上是指同一个意思
- 消息描述存储在ROS包的 msg/ 子目录中的 .msg 文件中
- msg文件就是简单的文本文件,每行都有一个字段类型和字段名称,用于为不同编程语言编写的消息生成源代码
基本类型
- int8,,int16, int32, int64 (以及 uint*)
- float32, float64
- string
- time,duration
- 其他 msg文件
msg类型 | C++对应类型 | Python对应类型 |
---|---|---|
bool | uint8_t | bool |
int8 | int8_t | int |
int16 | int16_t | int |
int32 | int32_t | int |
int64 | int64_t | int,long |
uint8 | uint8_t | int |
uint16 | uint16_t | int |
uint32 | uint32_t | int |
uint64 | uint64_t | int,long |
float32 | float | float |
float64 | float | float |
string | std:string | str,bytes |
time | ros:Time | rospy.Time |
duration | ros::Duration | rospy.Duration |
srv
简介
- ROS 使用简化的服务描述语言(“srv”)来描述 ROS 服务类型
- 服务描述存储在ROS包的 srv/ 子目录中的 .srv 文件中
- 一个srv文件描述一个服务。它由两部分组成:请求(request)和响应(response),以“---”分隔,上方表示 request数据类型,下面是 response类型
例如:
int8 FOO=1
int8 BAR=2
int8 foobar
another_pkg/AnotherMessage msg
---
uint32 SECRET=123456
another_pkg/YetAnotherMessage val
CustomMessageDefinedInThisPackage value
uint32 an_integer
创建
- 从另一个包复制现有的srv定义,而不是手动创建新的srv
roscd finaltest
mkdir srv
roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
- 使用rossrv查看能否识别
rossrv show finaltest/AddTwoInts
配置
package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
注意,在构建时,其实只需要message_generation
,而在运行时,我们只需要message_runtime
CMakeLists.txt
- 将message_generation加在括号闭合前即可
find_package(catkin REQUIRED COMPONENTS
std_msgs
message_generation
)
- 表示要编译的服务类型文件,生成头文件
add_service_files(
FILES
AddTwoInts.srv
Person.srv
)
- 添加生成消息的依赖,默认的时候要添加 std_msgs
generate_messages(
DEPENDENCIES
std_msgs
)
- 设置运行依赖
catkin_package(
CATKIN_DEPENDS message_runtime
)
编写服务端节点
- 在finaltest包中创建src/add_two_ints_server.cpp文件
#include <ros/ros.h>
#include "finaltest/AddTwoInts.h"
/**
* 服务端实现: 解析客户端发送的请求, 并反馈给客户端
* 1.包含头文件
* 2.初始化ROS节点
* 3.创建节点句柄
* 4.创建服务对象
* 5.处理请求并反馈
* 6.spin()
*/
// service 回调函数,输入参数req,输出参数res
bool add(finaltest::AddTwoInts::Request & req, finaltest::AddTwoInts::Response & res)
{
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", long (req.a), long (req.b)); // 显示请求数据
ROS_INFO("sending back response: [%ld]", long (res.sum)); // 设置反馈数据
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server"); // ROS节点初始化
ros::NodeHandle n; // 创建节点句柄
// 创建一个名为 add_two_ints 的 server,注册回调函数 add
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two ints.");
ros::spin(); // 循环等待回调函数
return 0;
}
编写客户端节点
- 在finaltest包中创建src/add_two_ints_client.cpp文件
#include <ros/ros.h>
#include "finaltest/AddTwoInts.h"
#include <cstdlib>
/**
* 客户端实现: 提交两个整数, 并处理相应的结果
* 1.包含头文件
* 2.初始化ROS节点
* 3.创建节点句柄
* 4.创建客户端对象
* 5.发送请求并接收反馈
*/
int main(int argc, char **argv)
/*
* argc 是 argument count的缩写,表示传入main函数的参数个数;
*
* argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,
* 并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,
* 所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;
*/
{
ros::init(argc, argv, "add_two_ints_client"); // 初始化ROS节点
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y");
return 1;
}
ros::NodeHandle n; // 创建节点句柄
// 为 add_two_ints 服务创建一个客户端,连接名为 add_two_ints 的 service
ros::ServiceClient client = n.serviceClient<finaltest::AddTwoInts>("add_two_ints");
// 初始化 finaltest::AddTwoInts 的请求数据
finaltest::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
// 等待服务启动
client.waitForExistence();
// ros::service::waitForService("add_two_ints");
if (client.call(srv)) // 请求服务调用
{
ROS_INFO("Sum: %ld", long (srv.response.sum));
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}
配置CMakeLists.txt
- 添加到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 ${PROJECT_NAME}_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 ${PROJECT_NAME}_gencpp)