ROS学习---服务通信

更新命令行,ctrl+c

1.自定义srv

1.1定义srv文件

服务通信中,数据分成两部分,请求与响应,在 srv 文件中请求和响应使用---分割,具体实现如下:

功能包下新建 srv 目录,添加 xxx.srv 文件,内容:

                  

                  CMakeLists.txt编辑 srv 相关配置

 1.2 编辑配置文件package.xml

 

需求:

编写服务通信,客户端提交两个整数至服务端,服务端求和并响应结果到客户端。

分析:

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:

  1. 服务端
  2. 客户端
  3. 数据

流程:

  1. 编写服务端实现;
  2. 编写客户端实现;
  3. 编辑配置文件;
  4. 编译并执行。

0.VScode的配置

需要像之前自定义 msg 实现一样配置c_cpp_properies.json 文件

{
  "configurations": [
    {
      "browse": {
        "databaseFilename": "${workspaceFolder}/.vscode/browse.vc.db",
        "limitSymbolsToIncludedHeaders": false
      },
      "includePath": [
        "/opt/ros/melodic/include/**",
        "/home/su/catkin_ws/src/learning_topic/include/**",
        "/usr/include/**",
        "/home/su/demo05_ws/devel/include/**"//添加此处
      ],
      "name": "ROS",
      "intelliSenseMode": "gcc-x64",
      "compilerPath": "/usr/bin/gcc",
      "cStandard": "gnu11",
      "cppStandard": "c++14"
    }
  ],
  "version": 4
}

路径的获取:在集成终端中打开

 

编辑配置文件package.xml

server.cpp

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

/*
    需求: 
        编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
        服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
        客户端再解析

    服务器实现:
        1.包含头文件
        2.初始化 ROS 节点
        3.创建 ROS 句柄
        4.创建 服务 对象
        5.回调函数处理请求并产生响应
        6.由于请求有多个,需要调用 ros::spin()

*/
// bool 返回值由于标志是否处理成功
bool doReq(plumbing_server_client::AddInts::Request& req,
          plumbing_server_client::AddInts::Response& resp){
    int num1 = req.num1;
    int num2 = req.num2;

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

    //逻辑处理
    if (num1 < 0 || num2 < 0)
    {
        ROS_ERROR("提交的数据异常:数据不可以为负数");
        return false;
    }

    //如果没有异常,那么相加并将结果赋值给 resp
    resp.sum = num1 + num2;
    return true;


}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    // 2.初始化 ROS 节点
    ros::init(argc,argv,"AddInts_Server");
    // 3.创建 ROS 句柄
    ros::NodeHandle nh;
    // 4.创建 服务 对象
    ros::ServiceServer server = nh.advertiseService("AddInts",doReq);
    ROS_INFO("服务已经启动....");
    //     5.回调函数处理请求并产生响应
    //     6.由于请求有多个,需要调用 ros::spin()
    ros::spin();
    return 0;
}

client.cpp

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

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");

    // 调用时动态传值,如果通过 launch 的 args 传参,需要传递的参数个数 +3
    if (argc != 3)
    // if (argc != 5)//launch 传参(0-文件路径 1传入的参数 2传入的参数 3节点名称 4日志路径)
    {
        ROS_ERROR("请提交两个整数");
        return 1;
    }


    // 2.初始化 ROS 节点
    ros::init(argc,argv,"AddInts_Client");
    // 3.创建 ROS 句柄
    ros::NodeHandle nh;
    // 4.创建 客户端 对象
    ros::ServiceClient client = nh.serviceClient<plumbing_server_client::AddInts>("AddInts");
   //ROS中内置了相关函数,这些函数可以让客户端启动后挂起,等待服务器启动
    //等待服务启动成功
    //方式1
    ros::service::waitForService("AddInts");
    //方式2
    // client.waitForExistence();
    // 5.组织请求数据
   plumbing_server_client::AddInts ai;
    ai.request.num1 = atoi(argv[1]);
    ai.request.num2 = atoi(argv[2]);
    // 6.发送请求,返回 bool 值,标记是否成功
    bool flag = client.call(ai);
    // 7.处理响应
    if (flag)
    {
        ROS_INFO("请求正常处理,响应结果:%d",ai.response.sum);
    }
    else
    {
        ROS_ERROR("请求处理失败....");
        return 1;
    }

    return 0;

}

2.参数服务器

设置参数

param_set.cpp

#include"ros/ros.h"

int main(int argc,char*argv[])
{
   ros::init(argc,argv,"set_param_c");

   ros::NodeHandle nh;

   //方案1增
   nh.setParam("type","xiaobai");
   nh.setParam("radius",0.15);
  
  //方案二ros::param
  ros::param::set("type_param","xiaohuang");
  ros::param::set("radius_param",0.15);
  
  //改,方案1
  nh.setParam("radius",0.2);
  //方案二
  ros::param::set("radius",0.25);
  
    return 0;
}

获取参数

param_get.cpp

#include "ros/ros.h"

int main(int argc,char*argv[])
{
   setlocale(LC_ALL,"");

   ros::init(argc,argv,"get_param");

   ros::NodeHandle nh;

   //1.param
   double radius=nh.param("radius",0.5);//0.5为赋予的默认值
   ROS_INFO("radius=%.2f",radius);

   //2.getParam
   double radius1=0.0;
//    bool result =nh.getParam("radius1",radius1);
    
 //3.getParamCached与getParam类似,只是性能上有提升,一般测试下,看不出来
 bool result =nh.getParamCached("radius",radius1);
 if(result)
 {
     ROS_INFO("获取的半径是:%2.f",radius1);
 }

 else{
     ROS_INFO("获取的数据错误");
 }
 
 //getParamNames()
 std::vector<std::string> names;
 nh.getParamNames(names);
 //右值引用
for(auto &&name:names)
{
   ROS_INFO("遍历的元素:%s",name.c_str());
}

//5.hasParam
bool flag1 =nh.hasParam("radius");
bool flag2=nh.hasParam("radius1");
ROS_INFO("radius存在吗?%d",flag1);
ROS_INFO("radius1存在吗 %d",flag2);

//6.searchParam
std::string key;
nh.searchParam("radius",key);
ROS_INFO("搜索结果:%s",key.c_str());


    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值