概述
上一节的课程详细的讲解了如何创建一个客户端C++代码并向一个已存在的服务发送请求,这一节我们将来学习如何自己创建一个服务,为了验证服务是有效的,我们将直接在终端(客户端)请求这个服务,为了证明服务是有效的,最好留下打印信息。
在此之前,先来了解以下ROS都给我们提供了那些内置服务类型(std_srvs):
- Empty
- Trigger
- SetBool
其中Trigger和Empty类型是最常见的两种服务类型,对于Empty,服务器和客户端之间不会交换实际数据;对于Trigger则会交换服务数据,查看Trigger的类型,结果如下:
---
bool success # indicate successful run of triggered service
string message # informational, e.g. for error messages
Trigger可以用来检查出发是否成功及一些有用的信息。
完整的流程如下:
因为前面已经创建过很多次workspace和package这里直接略过。
一、编写服务端代码
每当你需要发布一个话题,或者提供某项服务,离不开我们的节点管理器(ros::NodeHandle
)。节点管理器可以调用:
advertiseService
注册某项服务并返回服务器实例advertise
注册某个话题返回话题实例
用户可以通过话题实例发布数据pub
,需要理解的是,服务器提供的服务是由回调函数定义的,每当一个请求进来就会调用回调函数,这个回调函数第一个参数是标准Trigger服务数据类型,在这个例子里,请求的终端将发送一个标准空数据给服务器,服务器能够感知这个请求,但是并没有办法获得任何有效信息,因为它是空的;服务器通过第二个参数是标准Trigger类型,回调函数里的参数都将会在返回给调用的客户端(这里的终端)。
如果其实到这里就可以验证服务器是否对客户端进行了响应,但是为了更加直观,作者用了海龟可视化界面来显示,并通过其发送/turtle1/cmd_vel
话题控制海龟的启停。
所以这次编写的代码既涉及了服务又涉及到了话题,对于新手来说不是特别的友好。现在来看最终的程序:
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_srvs/Trigger.h> //标准服务数据类型std_srvs/Trigger
ros::Publisher turtle_vel_pub; //构造一个Publisher对象实例,用来发送消息
bool pubCommand=false;
//回调函数第一个参数是标准服务数据Trigger::Request,请求者的数据将会由这个数据传入
//回调函数第二个参数是标准服务数据Trigger::Response,请求者也会收到服务器给的数据
bool commandCallback(std_srvs::Trigger::Request &req,std_srvs::Trigger::Response &res)
{
pubCommand=!pubCommand;//取反
ROS_INFO("Publish turtle velocity command[%s]",pubCommand==true?"YES":"NO");
res.success=true;
res.message="Change turtle command state";
return true;
}
int main(int argc,char **argv)
{
ros::init(argc,argv,"turtle_command_server");
ros::NodeHandle n;
//注册一个Service 服务提供者,其服务的名称为/turtle_comand,只要有客户端请求服务就会调用回调函数commandCallback(其实就是服务内容)
ros::ServiceServer command_service=n.advertiseService("/turtle_command",commandCallback);
//注册一个Topic 话题发布者,其发布的话题为/turtle1/cmd_vel,因为话题没有反馈,就没有回调函数这一说
turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);
ROS_INFO("Ready to receive turtle command.");
ros::Rate loop_rate(10);
while(ros::ok())
{
ros::spinOnce();//spinOnce处理一次回调函数
if(pubCommand)
{
geometry_msgs::Twist vel_msg;
vel_msg.linear.x=0.5;
vel_msg.angular.z=0.2;
turtle_vel_pub.publish(vel_msg);
}
}
return 0;
}
二、编译运行
略
三、一些编程上的总结
对象 | 含义 |
---|---|
advertise<> | 节点句柄通过此方法注册话题,这个话题类型由模板参数给定。实参是话题名和缓冲长度,返回一个服务器者 |
advertiseService | 节点句柄通过此方法注册服务,这个服务没有模板参数。实参是服务名和回调函数,返回一个发布者 |
ros::Rate r(数字) | 控制循环频率,单位时间次数 |
publish(消息) | 发布者通过这个方法将指定消息发布出去 |
spinOnce() | 处理一次callback |
ros::ok() | ros是否需要退出(shutdown) |
std_msgs | 标准发布类型包 |
std_srvs | 标准服务数据类型包 |
ros::init | ros初始化操作 |
功能包中可能含有多个源文件,这些源文件可能会单独被编译成应用程序。
最后
以上就是危机耳机为你收集整理的ROS入门21讲笔记(六)代码形式写一个服务端的全部内容,希望文章能够帮你解决ROS入门21讲笔记(六)代码形式写一个服务端所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复