ROS系列:服务通信(一)

提示:学习记录


前言

学习服务通信机制


一、服务通信

服务通信:基于请求响应的模式,用于偶然的、对实时性有要求、有一定逻辑处理需求的数据传输场景;

二、流程步骤

0、server注册
1、client注册
2、rosmaster实现信息匹配
3、client发送请求request
4、server发送响应respond

1.定义srv文件

代码如下(示例):
使用---把请求和响应分隔开;
在这里插入图片描述

2.编辑配置文件

秘诀:xml文件添俩行,txt文件添二行加二段

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)

add_service_files(
  FILES
  AddInts.srv

)

generate_messages(
  DEPENDENCIES
  std_msgs
)

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES plumbing_server_client
 CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)

3.编译后生成中间文件路径可以添加进入相关配置文件配置vscode

,“xxx/xxx工作空间/devel/include/***”

4.程序编写(c++)

1.服务端

#include "ros/ros.h"
#include "plumbing_server_client/AddInts.h"

/**
 * @brief 服务端实现
 * 解析客户端提交的数据,并运算产生响应
 * 1、包含头文件
 * 2、初始化ros节点
 * 3、创建节点句柄
 * 4、创建服务对象
 * 5、处理请求并产生响应
 * 6、spin()一定要加,循环则是spinOnce
 * @param argc
 * @param argv
 * @return int
 */
bool doNums(plumbing_server_client::AddInts::Request &request,
            plumbing_server_client::AddInts::Response &response){
    //1、处理请求
    int num1 = request.num1;
    int num2 = request.num2;
    ROS_INFO("收到的请求数据是:num1=%d,num2=%d",num1,num2);
    // 2、组织响应
    int sum=num1+num2;
    response.sum = sum;
    ROS_INFO("求和结果sum=%d",sum);

    return true;
}
int main(int argc, char  *argv[])
{
    setlocale(LC_ALL,"");
    ROS_INFO("服务端已启动");
    //  * 2、初始化ros节点
    ros::init(argc, argv, "HeiShui"); //保证名称唯一
    //  * 3、创建节点句柄
    ros::NodeHandle nh;

    //  * 4、创建服务对象 服务起了个话题名称addInts
    ros::ServiceServer server = nh.advertiseService("addInts",doNums);
    //  * 5、处理请求并产生响应
    //  * 6、spin()一定要加,循环则是spinOnce
    ros::spin();
    return 0;
}

2.客户端

在这里插入代码片

3.配置CMakeList.txt
4.执行
在这里插入图片描述

总结

出现错误:问题1.rosservice call关键字后加话题名称,但并没有tab补齐,弹幕说空一格再2下tab补齐也没有出现:
在这里插入图片描述
解决办法:首先尝试使用加斜线的方式,并按下2次tab查找当前话题,但并没有成功;自定义消息或者服务信息,调用时出现错误ERROR: Unable to load type [xxx]:可能的原因是当前使用的终端的工作环境没有更新导致无法找到自定义的消息。执行更新终端的工作环境,网上搜索到的相关经验,但是我已经配置了工作环境,所以并不是该种问题,反思创建AddInts时一开始写成Addints,编译后把i换成了跟老师一样的大写,因此/devel目录下出现addints相关的头文件,但后续用的时AddInts相关头文件,因此决定删除整个功能包,重新尝试:
在这里插入图片描述
rosservice call /AddInts 后可以tab补齐,功能正常,成功解决问题!
问题2:在这里插入图片描述
出现错误:[ WARN] [1664201474.083411553]: Shutdown request received.
[ WARN] [1664201474.084911617]: Reason given for shutdown: [[/HeiShui] Reason: new node registered with same name]
解决办法:粗心大意,原因是CMakeLists.txt之中add_executable(demo02_client src/demo01_server.cpp)重复指向同一个cpp文件,因此运行时发生冲突;修改后解决问题。
问题3:在这里插入图片描述

解决办法:原因是在服务通信之中,属于异步通信,因此在通信时,服务端应该优先客户端运行。
这里也要提一下后面提到的客户端挂起选项:
在这里插入图片描述
在这里插入图片描述
问题5:错误类型error: invalid conversion from ‘char*’ to ‘plumbing_server_client::AddIntsRequest_<std::allocator >::_num1_type’ {aka ‘int’} [-fpermissive]
35 | ai.request.num1 = argv[1];

解决办法:学会使用argc与argv进行动态传参,但没有对argv[]进行一个字符串的转化:在这里插入图片描述
结束!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ros::NodeHandle是ROS中的一个重要类,用于与ROS系统进行通信和交互。它提供了一系列方法和功能,用于创建和管理ROS节点、发布和订阅ROS话题、调用和提供ROS服务等。 以下是ros::NodeHandle的一些常见用法和功能: 1. 创建NodeHandle对象: ```cpp #include <ros/ros.h> int main(int argc, char** argv) { // 初始化ROS节点 ros::init(argc, argv, "my_node"); // 创建NodeHandle对象 ros::NodeHandle nh; // 其他操作... return 0; } ``` 2. 发布和订阅ROS话题: ```cpp #include <ros/ros.h> #include <std_msgs/String.h> int main(int argc, char** argv) { ros::init(argc, argv, "my_node"); ros::NodeHandle nh; // 创建发布者 ros::Publisher pub = nh.advertise<std_msgs::String>("my_topic", 10); // 创建订阅者 ros::Subscriber sub = nh.subscribe("my_topic", 10, callback); // 其他操作... ros::spin(); return 0; } void callback(const std_msgs::String::ConstPtr& msg) { // 处理接收到的消息 } ``` 3. 调用和提供ROS服务: ```cpp #include <ros/ros.h> #include <std_srvs/Empty.h> bool my_service(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res) { // 处理服务请求 return true; } int main(int argc, char** argv) { ros::init(argc, argv, "my_node"); ros::NodeHandle nh; // 创建服务服务ros::ServiceServer server = nh.advertiseService("my_service", my_service); // 创建服务客户端 ros::ServiceClient client = nh.serviceClient<std_srvs::Empty>("my_service"); // 其他操作... return 0;} ``` 4. 获取ROS参数: ```cpp #include <ros/ros.h> int main(int argc, char** argv) { ros::init(argc, argv, "my_node"); ros::NodeHandle nh; // 获取参数 int my_param; nh.getParam("my_param", my_param); // 设置参数 nh.setParam("my_param", 123); // 其他操作... return 0; } ``` 这些只是ros::NodeHandle的一部分功能,它还提供了许多其他方法和功能,用于与ROS系统进行更高级的交互和通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会是要长脑子了吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值