创建简单的服务和客户端

创建服务端和客户端

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)


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   TNTksals  阅读(96)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示