我是靠谱客的博主 危机耳机,最近开发中收集的这篇文章主要介绍ROS入门21讲笔记(六)代码形式写一个服务端,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

上一节的课程详细的讲解了如何创建一个客户端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可以用来检查出发是否成功及一些有用的信息。

完整的流程如下:

开始
创建工作空间
创建package
编写服务节点代码
修改CMakeLists.txt并编译
roscore rosrun
rosservice pub 服务 数据
结束

因为前面已经创建过很多次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::initros初始化操作

功能包中可能含有多个源文件,这些源文件可能会单独被编译成应用程序。

最后

以上就是危机耳机为你收集整理的ROS入门21讲笔记(六)代码形式写一个服务端的全部内容,希望文章能够帮你解决ROS入门21讲笔记(六)代码形式写一个服务端所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部