使用c++完成一个ros service项目的编写

本文介绍了在ROSMelodic环境下,如何使用rosservice实现节点间的双向有应答通信,包括创建工作空间、定义msg和srv消息类型,以及在C++中编写client和服务端的示例代码。
摘要由CSDN通过智能技术生成

ROS通信机制

编译平台

本项目依赖于ubuntu18.04,ROS版本为ROS melodic ,运行于windows10上面的虚拟机

ros service

ros service是节点之间通讯的另一种方式。服务允许节点发送一个请求(request)并获得一个响应(response),本文使用c++完成了一个基础了ROS service项目的编写。
rosservice于前面文章中提到的ros topic一个显著的区别是,service是双向有应答机制的通讯方式,而topic只是完成了简单的接受消息和处理消息的任务。

创建工作空间

mkdir -p catkin_test/src

使用mkdir命令创建一个工作空间
然后我们cd进入catkin_test,使用catkin_make对工作空间进行编译,完成工作空间的注册和初始化
在这里插入图片描述
在这里插入图片描述
编译完成后会出现build和devel两个文件夹,当这两个文件夹产生,就代表这个工作空间创建成功。
创建一个名为test的功能包

cd src
catkin_create_pkg test roscpp rospy std_msgs

在正式的cpp文件编写之前,我们需要做一点准备。创建在两个节点之间沟通的“消息”。
使用ROS完成的这个功能,我们需要有两个节点,这俩个节点为别作为client和service,即一个作为客户端一个作为服务端。我们在srvz中规定了他们之间是如何通信的,而msg规定了srv中传递的消息是什么类型的。

msg和srv

首先我们需要明确一下msg和srv两个概念
msg:msg 文件是描述 ROS 消息字段的简单文本文件。它们用于生成不同语言消息的源代码。
SRV:SRV 文件描述服务。它由两部分组成:请求和响应。
这是ROS官网上的解释。
我们将msg文件放在msg文件夹下,将srv文件放在srv文件夹下。
在功能包下建立两个新建文件夹,msg与srv:
在这里插入图片描述
接下来分别在msg和srv下创建msg文件和srv文件
在这里插入图片描述

在test_1.msg中填入下列内容

int64 a
int64 b
int64 sum

在test_2.srv填入一下内容

int64 a
int64 b
---
int64 sum

在msg中规定了通信中主要涉及有三个数据,数据类型均为int64
在srvz中我们规定了int64 a与int64 b为请求数据,int6 sum为响应数据

client

在src下完成client.cpp和listner,cpp的创建
client.cpp

#include<ros/ros.h>
#include<std_msgs/String.h>
#include"test1/test_2.h"

int main(int argc,char **argv)
{
    ros::init(argc,argv,"add_two_ints_client");
    if(argc != 3)
    {
        ROS_INFO("usage: add_two_ints_client X Y");
        return 1;
    }
    ros::NodeHandle n;
    ros::ServiceClient client = n.serviceClient<test1::test_2>("add_two_ints");
    test1::test_2 srv;
    srv.request.a = atoll(argv[1]);
    srv.request.b=atoll(argv[2]);
    if (client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
    return 0;
}

server,cpp

#include<ros/ros.h>
#include"std_msgs/String.h"
#include"test/test.h"
bool add(test1::test_2::Request &req,
        test1::test_2::Response &res)
        {
            res.sum=req.a+req.b;
            ROS_INFO("request: x=%ld,y=%ld",(long int)req.a,(long int)req.b);
            ROS_INFO("sending back response: [%ld]", (long int)res.sum);
            return true;
        }

int main(int argc,char **argv)
{
    ros::init(argc, argv, "add_two_ints_server");
    ros::NodeHandle n;
    ros::ServiceServer service = n.advertiseService("add_two_ints", add);
    ROS_INFO("Ready to add two ints.");
    ros::spin();
    return 0;
}

cmakelist.txt修改

接下来最重要的就是cmakelist的修改
修改find_package添加

message_generation

在这里插入图片描述

添加msg和srv
在这里插入图片描述
添加msg和srv的依赖项
将刚才编辑好的client和listener做成可执行文件

功能包依赖项
在这里插入图片描述

添加可执行文件
在这里插入图片描述
修改package.xml
添加下列内容
在这里插入图片描述
然后我们返回工作空间下编译

catkin_make

在编译的过程中可以看到生成了一个massage和一个服务
在这里插入图片描述
这个工程就算是构建成功了,接下来运行一下
在运行之前需要先启动roscore
打开一个新的终端

roscore

然后需要source一下

source ./devel/setup.bash

启动service

 rosrun test1 service 

此时会输出一个日志

[ INFO] [1705819135.358506874]: Ready to add two ints.

就是等待两个int类型的数字输入
接下来打开一个新的终端打开客户端输入这两个数字

~/catkin_test$ source ./devel/setup.bash 
~/catkin_test$ rosrun test1 client 2 4

在这里插入图片描述
返回这样的输出就说明服务端接收到我们输入的数据并完成了处理(相加)并将结果返回回来
接下来详细梳理一下代码
server.cpp

#include<ros/ros.h>
#include"std_msgs/String.h"
#include"test/test.h"
bool add(test1::test_2::Request &req,
        test1::test_2::Response &res)
        {
            res.sum=req.a+req.b;//求和
            ROS_INFO("request: x=%ld,y=%ld",(long int)req.a,(long int)req.b);
            ROS_INFO("sending back response: [%ld]", (long int)res.sum);//输出日志
            return true;
        }
//bool类型函数,将srv里面的请求和应答读入节点,test1为功能包的名字,test_2为我们刚才创建好的srv文件
int main(int argc,char **argv)
{
    ros::init(argc, argv, "add_two_ints_server"); //初始化节点,节点名add_two_ints_server
    ros::NodeHandle n;//创建句柄
    ros::ServiceServer service = n.advertiseService("add_two_ints", add); //创建一个服务
    ROS_INFO("Ready to add two ints.");
    ros::spin();//ROS消息回调处理函数
    return 0;
}

client.cpp

#include<ros/ros.h>
#include<std_msgs/String.h>
#include"test1/test_2.h"

int main(int argc,char **argv)
{
    ros::init(argc,argv,"add_two_ints_client"); //初始化节点
    if(argc != 3)
    {
        ROS_INFO("usage: add_two_ints_client X Y");
        return 1;
    }         //错误处理,如果输入参数不对则报错
    ros::NodeHandle n;          //创建句柄
    ros::ServiceClient client = n.serviceClient<test1::test_2>("add_two_ints");  //创建客户端
    test1::test_2 srv;  
    srv.request.a = atoll(argv[1]);
    srv.request.b=atoll(argv[2]);     //将输入的参数读到srv里面
    if (client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);        
  }//如果服务端做出相应则打印相应结果
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }//else则报错
    return 0;
}
  • 23
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值