ROS通信机制--服务通信讲解C++代码示例

前言

        ros服务通信是一种请求响应的模式,有服务端和客户端。服务端接受客户端请求的数据后,响应数据到客户端。服务名在服务端和客户端需要配置一致才可建立通信。

        本案例为实现简单的数据求和。客户端请求中有两个数据,服务端响应这两个数据的和。

一、配置srv文件 

 1、首先在功能包目录下创建一个名为“srv”的文件夹,之后在“srv”文件夹下创建一个.srv文件。我这里的文件名为AddInts.srv。目录结构如下:

  2、在AddInts.srv中自定义数据类型,num1、num2为请求的2个数据,sum为响应的数据,输入:

int32 num1
int32 num2
---
int32 sum

注意:请求的数据和响应的数据之间需要用 --- 分割。

 3、打开package.xml文件添加2行配置:

  <!--如果编译时需要message文件就要导入message_generation-->
  <build_depend>message_generation</build_depend>
 
  <!--如果运行时需要message文件就要导入message_runtime-->
  <exec_depend>message_runtime</exec_depend>

 4、打开CmakeLists.txt,找到以下几条语句,增加以下配置: 

#编译时依赖
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  #增加message_generation,编译时需要依赖message_generation
  message_generation
)
#添加自定义的srv文件,意味着编译srv目录下的AddInts.srv文件
add_service_files(
  FILES
  AddInts.srv
)
#注释放开,不需要修改。意味着如果要编译AddInts.srv 要依赖于std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)
#运行时依赖message_runtime(这儿不配置也能编译通过)
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES pub_sub
 CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)

5、编译,编译成功后查看devel/include/xxxx下是否生成了AddInts.h、AddIntsRequest.h、AddIntsResponse.h文件。如果成功生成了,那么你的配置是没有问题的。如果编译失败或没有生成.h文件,那么请检查前面的配置是否正确。

 二、编写代码

1、编写代码之前,打开c_cpp_properties.json文件,添加AddInts.h所在的目录。我这里的目录是“"/home/sun/demo_pub_sub/devel/include”,建议后面直接写上/**

2、创建server.cpp(服务端)、client.cpp(客户端)两个文件,写入以下代码(注意包含AddInts.h头文件): 

server.cpp(服务端)

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


bool callBack(server_client::AddInts::Request& req,server_client::AddInts::Response& resp)
{
    //请求数据req
    int num1 = req.num1;
    int num2 = req.num2;

    ROS_INFO("server收到的请求数据为:num1 = %d,num2 = %d",num1,num2);

    //返回的响应数据resp
    resp.sum = num1 + num2;

    return true;

}


int main(int argc, char *argv[])
{
    //解决中文乱码输出
    setlocale(LC_ALL,"");

    //初始化ros节点(节点名唯一)
    ros::init(argc,argv,"server");

    //创建ros句柄
    ros::NodeHandle nh;

    //创建服务对象,callBack(自定义回调函数,参数名为...Request,...Response,返回值为bool类型)
    ros::ServiceServer server = nh.advertiseService("AddInts",callBack);

    ROS_INFO("服务启动....");

    //回头处理回调函数
    ros::spin();

    return 0;
}

client.cpp(客户端)

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


int main(int argc, char *argv[])
{

    //解决中文输出乱码
    setlocale(LC_ALL,"");

    //初始化ros节点(节点名唯一)
    ros::init(argc,argv,"client");

    //创建ros句柄
    ros::NodeHandle nh;

    //创建客户端对象
    ros::ServiceClient client = nh.serviceClient<server_client::AddInts>("AddInts");
    
    //请求数据
    server_client::AddInts ai;
    ai.request.num1 = 100;
    ai.request.num2 = 200;

    //发送请求,返回值为bool类型
    bool ret = client.call(ai);

    if(ret)
    {
        ROS_INFO("请求成功,响应结果:%d",ai.response.sum);
    }
    else
    {
        ROS_ERROR("请求失败....");
        return -1;
    }


    return 0;
}

编写CmakeLists.txt,加入以下几行:

add_executable(server src/server.cpp)
add_executable(client src/client.cpp)
add_dependencies(server ${PROJECT_NAME}_gencpp)
add_dependencies(client ${PROJECT_NAME}_gencpp)
target_link_libraries(server
  ${catkin_LIBRARIES}
)

target_link_libraries(client
  ${catkin_LIBRARIES}
)

 4、vscode中 ctrl + shift + B 编译

三、运行

1、在工作空间目录下打开终端,依次运行以下三个程序:

  • roscore
  • rosrun server_client server
  • rosrun server_client client

注意:这里有可能运行时报错 “package xxxx  not found”的错误。只需要在每个终端窗口中都运行一遍source ./devel/setup.bash ,再次运行时就没有报错了。   

2、查看终端(左侧为roscore,右上为server,右下client 。可以看出客户端请求了2个数据为100、200到服务端。服务端响应数据之和300。

 

(END) 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值