如何让搜素引擎不收录自己的网站,天津小程序网站开发公司,wordpress qq登录免费下载,找公司建网站报价目录
一、概念
二、何时使用服务
三、话题通信与服务通信的区别
四、案例
4.1 C实现
4.1.1 服务端
4.1.2 客户端
4.1.3 测试执行
4.2 Python实现
4.2.1 服务端
4.2.2 客户端
4.2.3 客户端优化——动态传参
4.2.4 客户端优化——等待服务端启动后再发起请求 一、概…目录
一、概念
二、何时使用服务
三、话题通信与服务通信的区别
四、案例
4.1 C实现
4.1.1 服务端
4.1.2 客户端
4.1.3 测试执行
4.2 Python实现
4.2.1 服务端
4.2.2 客户端
4.2.3 客户端优化——动态传参
4.2.4 客户端优化——等待服务端启动后再发起请求 一、概念
服务通信涉及两个角色 服务服务器 (Service Server) 提供特定功能或数据的节点。 它会“打广告”说“我能提供XX服务”例如“我能计算两个整数的和”。 它平时处于待命状态一旦接收到请求就执行相应的任务并返回一个结果。 服务客户端 (Service Client) 需要某个特定功能或数据的节点。 它会向服务器发送一个具体的请求例如“请帮我计算 3 和 5 的和”。 发送请求后它会暂停自己的工作一直等待直到收到服务器的响应。 二、何时使用服务
当你需要立即得到一个确切的答复或触发一个必须完成的远程操作时就应该使用服务。
典型应用场景: 查询数据: “机器人你现在的坐标是多少” 触发动作: “机械臂移动到指定位置。” / “相机拍一张照片。” 执行计算: “路径规划器帮我计算一条从A到B的最优路径。” 更改状态: “机器人切换到自动驾驶模式。” 三、话题通信与服务通信的区别
服务通信 (Service)话题通信 (Topic)通信模型请求/响应发布/订阅数据流向双向单向 同步性同步 - 客户端会阻塞等待异步 - 发布后立即返回连接关系一对一 一对多/多对多数据流类型离散的、事务性的连续的数据流主要目的执行远程调用、获取确切结果持续广播状态、传感器数据 四、案例
客户端发送两个整数服务端计算它们的和并返回
4.1 C实现
4.1.1 服务端
进入到工作空间的src目录下输入如下指令来创建一个名为“plumbing_server_client”的功能包
catkin_create_pkg plumbing_server_client roscpp rospy std_msgs 在功能包中创建一个srv目录 在srv目录中创建一个.srv文件这里命名为“AddTwoInts.srv” “AddTwoInts.srv”内容如下
int64 a
int64 b
---
int64 sum
打开功能包中的“package.xml”添加如下两行内容 build_dependmessage_generation/build_dependexec_dependmessage_runtime/exec_depend打开功能包下的“CMakeLists.txt”添加如下内容
添加“message_generation” 取消注释并添加“AddTwoInts.srv” 取消注释 取消注释 CtrlShiftB编译一下 在功能包的src目录中新建一个.cpp文件这里命名为“server.cpp” 在“server.cpp” 中添加如下代码
#include ros/ros.h
#include plumbing_server_client/AddTwoInts.h// 服务处理函数。当收到请求时ROS会调用这个函数。
// 函数的返回值是 bool 类型如果成功处理返回 true否则返回 false。
// 参数是请求对象(req)和响应对象(res)的引用。
bool add(plumbing_server_client::AddTwoInts::Request req,plumbing_server_client::AddTwoInts::Response res)
{// 从请求对象中取出数据res.sum req.a req.b;// ROS_INFO 用于在终端打印日志信息类似于C的coutROS_INFO(请求: x%ld, y%ld, (long int)req.a, (long int)req.b);ROS_INFO(发送响应: sum%ld, (long int)res.sum);return true; // 表示服务成功执行
}int main(int argc, char **argv)
{setlocale(LC_ALL,);// 1. 初始化ROS节点ros::init(argc, argv, add_two_ints_server);// 2. 创建节点句柄ros::NodeHandle n;// 3. 创建一个名为 add_two_ints 的服务// 它会调用 add 函数来处理请求ros::ServiceServer service n.advertiseService(add_two_ints, add);ROS_INFO(服务已就绪等待客户端请求...);// 4. 进入循环等待回调函数的触发ros::spin();return 0;
}
4.1.2 客户端
在功能包的src目录下添加一个.cpp文件这里命名为“client.cpp” 在“client.cpp”中添加如下代码
#include ros/ros.h
#include plumbing_server_client/AddTwoInts.h
#include cstdlib // 用于 atoll 函数int main(int argc, char **argv)
{setlocale(LC_ALL,);// 初始化ROS节点ros::init(argc, argv, add_two_ints_client);// 检查命令行参数是否正确if (argc ! 3){ROS_INFO(用法: add_two_ints_client X Y);return 1;}// 创建节点句柄ros::NodeHandle n;// 创建一个客户端连接到名为 add_two_ints 的服务// serviceClient 会一直尝试连接直到成功ros::ServiceClient client n.serviceClientplumbing_server_client::AddTwoInts(add_two_ints);// 创建一个服务对象 srvplumbing_server_client::AddTwoInts srv;// 将命令行参数转换为 long long (int64) 并填充到请求中srv.request.a atoll(argv[1]);srv.request.b atoll(argv[2]);// 调用服务// client.call() 是一个阻塞操作。它会发送请求并等待直到收到响应。// 如果服务调用成功call() 返回 true响应数据会填充到 srv.response 中。// 如果失败call() 返回 false。if (client.call(srv)){ROS_INFO(响应 Sum: %ld, (long int)srv.response.sum);}else{ROS_ERROR(调用服务失败);return 1;}return 0;
}
打开功能包中“CMakeLists.txt”文件添加如下内容 编译一下
4.1.3 测试执行
开启三个终端分别输入如下指令来依次启动ros核心、启动服务端、启动客户端
roscore //启动ros核心rosrun plumbing_server_client server //启动服务端rosrun plumbing_server_client client 15 20 //启动客户端
可以看到服务端成功计算并返回计算结果。 但是如果我们先开启客户端再开启服务端就会导致客户端抛出异常 为了避免这个问题我们可以给客户端添加如下一行代码这样就可以客户端就可以等服务端启动后再请求 client.waitForExistence();
// 或
ros::service::waitForService(add_two_ints_server); //add_two_ints_server为服务器节点名称
可以看到客户端在服务端未启动时一直等待 等服务端启动后再执行请求 4.2 Python实现
4.2.1 服务端
打开“settings.json”如果没有如下配置则需要补充 {editor.tabSize: 4,cmake.sourceDirectory: /home/chaochao/demo02_ws/src/helloworld,files.associations: {sstream: cpp},python.autoComplete.extraPaths: [/opt/ros/noetic/lib/python3/dist-packages,/home/chaochao/demo02_ws/devel/lib/python3/dist-packages]
}
新建一个文件夹“scripts” 添加一个Python文件这里命名为“server_py.py” 在“server_py.py”添加如下代码
#! /usr/bin/env python
# -*- coding: utf-8 -*-import rospy
from plumbing_server_client.srv import AddTwoInts, AddTwoIntsRequest, AddTwoIntsResponse
# from plumbing_server_client.srv import *
服务端解析客户端请求产生响应1. 导包2. 初始化 ROS 节点3. 创建服务端对象4. 处理逻辑回调函数5. spin()
# 4. 处理逻辑
def call_doInt(request):num1 request.anum2 request.bsum num1 num2response AddTwoIntsResponse() # 将结果封装进responseresponse.sum sumrospy.loginfo(服务器收到num1%d, num2%d, 响应sum%d, num1, num2, sum)return responseif __name__ __main__:# 2. 初始化 ROS 节点rospy.init_node(server)# 3. 创建服务端对象server rospy.Service(AddTwoInts, AddTwoInts, call_doInt) # AddTwoInts:服务的名称; AddTwoInts:服务的类型; call_doInt:回调函数;# 5. spin()rospy.spin()
cd到“scripts”目录下输入如下指令来给python文件添加可执行权限 chmod x *.py
打开“CMakeLists.txt”添加如下内容 编译一下然后输入如下指令测试 source ./devel/setup.bash
rosrun plumbing_server_client server_py.pysource ./devel/setup.bash
rosservice call AddTwoInts a: 12 b: 14
4.2.2 客户端
在“scripts”目录下新建一个python文件这里命名为“client_py.py” 在“client_py.py”中添加如下代码
#! /usr/bin/env python
# -*- coding: utf-8 -*-import rospy
from plumbing_server_client.srv import AddTwoInts, AddTwoIntsRequest, AddTwoIntsResponse
客户端:组织并提交请求处理服务端响应。1. 导包;2. 初始化 ROS 节点;3. 创建客户端对象;4. 组织请求数据并发送请求;5. 处理响应。
if __name__ __main__:# 2. 初始化 ROS 节点;rospy.init_node(client)# 3. 创建客户端对象;client rospy.ServiceProxy(AddTwoInts, AddTwoInts)# 4. 组织请求数据并发送请求;response client.call(12, 24)# 5. 处理响应。rospy.loginfo(响应的数据%d, response.sum)
给新建的python文件添加可执行权限 打开“CMakeLists.txt”添加如下内容 编译后通过如下命令启动服务端和客户端可以看到客户端正常接收到了服务端响应的数据
rosrun plumbing_server_client server_py.py //启动服务端rosrun plumbing_server_client client_py.py //启动客户端 4.2.3 客户端优化——动态传参
如果我们希望客户端的参数是通过命令动态传入的可以对客户端代码做如下修改 #! /usr/bin/env python
# -*- coding: utf-8 -*-import rospy, sys
from plumbing_server_client.srv import AddTwoInts, AddTwoIntsRequest, AddTwoIntsResponse
客户端:组织并提交请求处理服务端响应。1. 导包;2. 初始化 ROS 节点;3. 创建客户端对象;4. 组织请求数据并发送请求;5. 处理响应。
if __name__ __main__:# 判断参数个数if len(sys.argv) ! 3:rospy.logerr(传入参数个数有误...)sys.exit(1)# 2. 初始化 ROS 节点;rospy.init_node(client)# 3. 创建客户端对象;client rospy.ServiceProxy(AddTwoInts, AddTwoInts)# 4. 组织请求数据并发送请求;num1 int(sys.argv[1])num2 int(sys.argv[2])response client.call(num1, num2)# 5. 处理响应。rospy.loginfo(响应的数据%d, response.sum)
此时执行效果如下 4.2.4 客户端优化——等待服务端启动后再发起请求
如果在服务端未启动的情况下启动客户端会抛出异常 为了解决这个问题我们可以添加如下一行代码这样客户端就可以等待服务端启动后再发起请求 client.wait_for_service()# 或rospy.wait_for_service(AddTwoInts)