ROS通信——C++实现

2023-05-16

一、普通话题通信

创建功能包:

catkin_create_pkg package roscpp rospy std_msgs

创建发布者:

# include "ros/ros.h"
# include "std_msgs/String.h"

using namespace std;

int main (int argc, char** argv)
{
    //处理乱码问题
    setlocale(LC_ALL, "");
    //初始化ROS节点
    ros::init(argc,argv,"pub");
    //创建句柄
    ros::NodeHandle nh;
    //创建发布者
    ros::Publisher pub = nh.advertise<std_msgs::String>("topic",100);

    std_msgs::String msg;
    //设置10HZ的循环周期
    ros::Rate rate(10);
    //先休眠3秒,防止出现前几条数据丢失的现象
    ros::Duration(3).sleep();
    //只要程序正常,ros::ok就返回true
    while (ros::ok)
    {
        //msg中只有一个成员data,用来储存字符串
        msg.data = "Hello ROS";
        //发布消息,括号里面的要和上面的消息类型一致
        pub.publish(msg);
        //打印日志,后面要加上c_str()否则会乱码
        ROS_INFO("%s",msg.data.c_str());
        //休眠,配合10HZ的循环周期
        rate.sleep();
    }
    return 0;
}

创建订阅者:

# include "ros/ros.h"
# include "std_msgs/String.h"

void callback(const std_msgs::String::ConstPtr& msg)
{
    ROS_INFO("%s", msg->data.c_str());
}

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

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

    ros::NodeHandle nh;

    ros::Subscriber sub = nh.subscribe("topic", 100, callback);
    
    //循环等待回调函数
    ros::spin();

    return 0;
}

编译配置:在Cmakelist中添加:

add_executable(test1 src/test1.cpp)
target_link_libraries(test1 ${catkin_LIBRARIES})

二、自定义话题通信 

Vscode这部分实现代码补全的配置:

1. 自定义的消息配置完成后打开devel下面的include目录,在终端中打开,然后输入pwd找到自定义信息的路径

2. 复制路径到c_cpp_properties.json文件的include下面:

实现发布者发布两个整数,接收者实现求和

创建功能包:

catkin_create_pkg package roscpp rospy std_msgs

创建自定义消息:message.msg文件

注意:这里不要写为int

int32 num1
int32 num2

创建发布者:

# include "ros/ros.h"
# include "package/message.h"//package为功能包名,message为自己定义的message.msg名
# include <iostream>

using namespace std;

int main (int argc, char** argv)
{
    ros::init(argc,argv,"pub");

    ros::NodeHandle nh;

    ros::Publisher pub = nh.advertise<package::message>("topic",100);

    package::message msg;

    while (ros::ok)
    {
	int a,b;

	cin >> a >> b;	
	
        msg.num1 = a;

        msg.num2 = b; 

        pub.publish(msg);

        cout<<"num1="<<a<<"  "<<"num2="<<b<<endl; 
    }
    return 0;
}

创建订阅者:

# include "ros/ros.h"
# include "package/message.h"
# include <iostream>

void callback(const package::message::ConstPtr& msg)
{
    int sum;

    sum = msg->num1 + msg->num2;

    ROS_INFO("sum = %d", sum);
}

int main (int argc, char** argv)
{
    ros::init(argc, argv, "sub");

    ros::NodeHandle nh;

    ros::Subscriber sub = nh.subscribe("topic", 100, callback);

    //循环等待回调函数
    ros::spin();

    return 0;
}

环境配置:

在package.xml中加入:

<build_export_depend>message_generation</build_export_depend>

<exec_depend>message_runtime</exec_depend>      

在Cmakelist中加入:   

(1) find_package(catkin REQUIRED COMPONENTS message_generation)

(2) add_message_files(
                       FILES
                       message.msg//自己创建的msg中的文件
                      )                             
    
(3) generate_messages(
                       DEPENDENCIES
                       std_msgs
                      )

(4) catkin_package(
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
                  )
(5)
add_executable(pub src/pub.cpp)
target_link_libraries(pub ${catkin_LIBRARIES})
add_dependencies(pub ${PROGECT_NAME}_gencpp)

add_executable(sub src/sub.cpp)
target_link_libraries(sub ${catkin_LIBRARIES})
add_dependencies(sub ${PROGECT_NAME}_gencpp)

三、服务通信

实现客户端输入两个整数,服务端实现相加

创建功能包:

catkin_create_pkg package roscpp rospy std_msgs 

创建自定义消息:

#客户端
int32 num1
int32 num2
---
#服务端
int32 sum

创建client:

#include <cstdlib>
#include "ros/ros.h"
#include "package/message1.h"

int main(int argc, char **argv)
{
  // ROS节点初始化
  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;
  
  // 创建一个client,请求add_two_int service,service消息类型是learning_communication::AddTwoInts
  ros::ServiceClient client = n.serviceClient<package::message1>("add_two_ints");
  
  //等待服务器启动,也就是先启动客户端的解决办法
  //方法1
  //ros::service::waitForService("add_two_ints");
  //方法2
  //client.waitForExistence();

  // 创建learning_communication::AddTwoInts类型的service消息
  package::message1 srv;
  srv.request.a = atoll(argv[1]);
  srv.request.b = atoll(argv[2]);
  
  // 发布service请求,等待加法运算的应答结果
  if (client.call(srv))//client.call(srv)发送服务请求,得到的回应自动放在srv.sum中
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  return 0;
}

创建server:

#include "ros/ros.h"
#include "package/message1.h"

// service回调函数,输入参数req,输出参数res
bool add(package::message1::Request  &req,
         package::message1::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节点初始化
  ros::init(argc, argv, "add_two_ints_server");
  
  // 创建节点句柄
  ros::NodeHandle n;

  // 创建一个名为add_two_ints的server,注册回调函数add()
  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  
  // 循环等待回调函数
  ROS_INFO("Ready to add two ints.");
  ros::spin();

  return 0;
}

环境配置:

在package.xml中加入:

<build_export_depend>message_generation</build_export_depend>

<exec_depend>message_runtime</exec_depend>      

在Cmakelist中加入:   

(1) find_package(catkin REQUIRED COMPONENTS message_generation)

(2) add_service_files(
                       FILES
                       message.msg//自己创建的srv中的文件
                      )                             
    
(3) generate_messages(
                       DEPENDENCIES
                       std_msgs
                      )

(4) catkin_package(
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
                  )
(5)
add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROGECT_NAME}_gencpp)

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

四、注意

自定义话题通信和服务通信不能一起使用

五、参数服务器

创建功能包:

catkin_create_pkg roscpp rospy std_msgs
# include "ros/ros.h"

using namespace std;

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

    ros::init(argc, argv, "param");
    ros::NodeHandle n;
    //参数新增
    //方案1:n
    n.setParam("type", "car");
    n.setParam("num", 100);
    //方案2:ros::param
    ros::param::set("type_param", "bicycle");
    ros::param::set("num_param", 500);

    //参数修改
    //方案1:n
    n.setParam("type", "big_car");
    //方案2:ros::param
    ros::param::set("type_param", "big_bicycle");

    //参数查询
    //方案1:param,99为默认值,如果没找到就默认为99
    int radius = n.param("num", 99);
    ROS_INFO("num=%d",radius);
    //方案2:getParam
    int radius1 = 0;
    bool result = n.getParam("num", radius1);
    if (result)
    {
        ROS_INFO("num=%d",radius1);
    }
    //方案3:getParamCached
    int radius2 = 0;
    bool result2 = n.getParamCached("num", radius2);
    if (result2)
    {
        ROS_INFO("num=%d",radius2);
    }
    
    //参数删除
    //方案1:n.deleteParam
    bool result5 = n.deleteParam("num");
    if (result5)
    {
        ROS_INFO("删除成功");
    }
    //方案2:ros::param::del
    bool result6 = ros::param::del("num");
    if (result6)
    {
        ROS_INFO("删除成功");
    }
    else
    {
        ROS_INFO("删除失败");
    }
    
    return 0;
}

配置环境:

#配置参数服务器
add_executable(canshu src/canshu.cpp)
target_link_libraries(canshu ${catkin_LIBRARIES})

六、动作通信

创建功能包:

catkin_create_pkg package roscpp rospy std_msgs actionlib actionlib_msgs

创建服务端:

# include "ros/ros.h"
# include "actionlib/server/simple_action_server.h"
# include "package/dataAction.h"

typedef actionlib::SimpleActionServer<package::dataAction> Server;

void callback(const package::dataGoalConstPtr& goal,Server* server)
{
    //解析提交的目标值
    int goal_num = goal->num;
    ROS_INFO("客户提交的目标值是%d",goal_num);
    //产生连续反馈
    ros::Rate rate(10);
    int result = 0;
    ROS_INFO("开始连续反馈...");
    for (size_t i = 1; i <= goal_num; i++)
    {
        //累加
        result+=i;
        //休眠
        rate.sleep();
        //产生连续反馈
        package::dataFeedback fb;
        fb.progress=i/(double)goal_num;
        server->publishFeedback(fb);
    }
    //最终结果
    package::dataResult result1;
    result1.result=result;
    server->setSucceeded(result1);
}

int main (int argc, char* argv[])
{   
    setlocale(LC_ALL,"");
    ros::init(argc,argv,"action_server");
    ros::NodeHandle n;
    //创建server服务对象
    //SimpleActionServer(ros::NodeHandle n, 
    //                    std::__cxx11::string name, 
    //                  boost::function<void (const package::dataGoalConstPtr &)> execute_callback, 
    //                   bool auto_start)
    //第一个参数:NodeHandle;
    //第二个参数:话题名称;
    //第三个参数:回调函数;
    //第四个参数:是否自动执行
    Server server(n,"action",boost::bind(&callback,_1,&server),false);
    server.start();//如果第四个参数为false则需要调用该函数启动服务

    ros::spin();
    return 0;
}

创建客户端:

​

# include "ros/ros.h"
# include "actionlib/client/simple_action_client.h"
# include "package/dataAction.h"

//激活回调
void active_cb()
{
    ROS_INFO("客户端服务连接建立...");
}

//联系反馈回调
void feedback_cb(const package::dataFeedbackConstPtr &feedback)
{
    ROS_INFO("当前进度是:%.2f",feedback->progress);
}

//相应成功时回调
void done_cb(const actionlib::SimpleClientGoalState &state, const package::dataResultConstPtr &result)
{
    if (state.state_==state.SUCCEEDED)
    {
        ROS_INFO("相应成功,最终结果是:%d",result->result);
    }
    else
    {
        ROS_INFO("请求失败");
    }
}

int main (int argc, char* argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc, argv, "action_client");
    ros::NodeHandle n;
    //创建action客户端对象
    actionlib::SimpleActionClient<package::dataAction> client(n,"action");
    //发送请求
    //注意:先等待服务器启动
    ROS_INFO("等待服务器启动.....");
    client.waitForServer();
    //建立连接---回调函数
    //处理连续反馈---回调函数
    //处理最终反馈---回调函数
    /*
        void sendGoal(const package::dataGoal &goal, 
        boost::function<void (const actionlib::SimpleClientGoalState &state, const package::dataResultConstPtr &result)> done_cb = actionlib::SimpleActionClient<package::dataAction>::SimpleDoneCallback(), 
        boost::function<void ()> active_cb , 
        boost::function<void (const package::dataFeedbackConstPtr &feedback)> feedback_cb)
    */
    package::dataGoal goal;
    goal.num=100;
    client.sendGoal(goal,&done_cb,&active_cb,&feedback_cb);
    ros::spin();
    return 0;
}

[点击并拖拽以移动]
​

配置环境:

在CMakelist中:

#配置动作通信
add_executable(action_server src/action_server.cpp)
target_link_libraries(action_server ${catkin_LIBRARIES})
add_dependencies(action_server ${PROJECT_NAME}_gencpp)

#配置动作通信
add_executable(action_client src/action_client.cpp)
target_link_libraries(action_client ${catkin_LIBRARIES})
add_dependencies(action_client ${PROJECT_NAME}_gencpp)

七、动态参数

创建功能包:

catkin_make_pkg package roscpp rospy std_msgs dynamic_reconfigure

创建服务端:

# include "ros/ros.h"
# include "dynamic_reconfigure/server.h"
# include "package/drConfig.h"

void cd(package::drConfig &config, uint32_t level)
{
    ROS_INFO("修改后的数据是:%d",config.int_param);
}

int main(int argc, char *argv[])
{
    ros::init(argc,argv,"dr_server");
    ros::NodeHandle n;
    //创建服务端对象
    dynamic_reconfigure::Server<package::drConfig> server;
    //回调函数解析修改后的参数
    server.setCallback(boost::bind(&cd,_1,_2));
    ros::spin();
    return 0;
}

创建客户端:

新建cfg文件夹,再建立**.cfg文件(python文件)

#! /usr/bin/env python

from dynamic_reconfigure.parameter_generator_catkin import *

gen = ParameterGenerator()

gen.add("int_param",int_t,0,"int_param_int",10,1,100)

exit(gen.generate("package","dr_client","dr"))

配置环境:

CMakelist中:添加

#配置动态参数
generate_dynamic_reconfigure_options(
  cfg/dr.cfg
)

#配置动态参数
add_executable(dr01_server src/dr01_server.cpp)
add_dependencies(dr01_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(dr01_server ${catkin_LIBRARIES})

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS通信——C++实现 的相关文章

  • C++之虚拟继承与继承的小总结

    本来是想将虚拟继承的部分写在上一篇的 xff0c 但是虚拟继承的分析实在有些复杂 xff0c 为了方便我自己回顾 xff0c 就干脆单写一篇吧 我们之前说过了 xff0c 虚拟继承可以解决菱形继承的二义性以及数据冗余的问题 xff0c 实际

随机推荐

  • C++之初识多态(Visual Studio 2019)

    此文章关于多态的代码全部是使用Visua Studio2019 x86 实现的 xff0c C 43 43 多态在不同编译器中的实现细节可能不同 xff0c 所以部分情况下相同代码运行结果可能不同 xff0c 在此声明 目录 多态的概念 多
  • C工程与寄存器封装(lv9-day13)

    文章目录 C工程与寄存器封装1 C语言工程简介2 启动文件3 C语言实现LED闪烁3 1 C语言与汇编分别是怎么操作寄存器的3 2 用C语言实现LED闪烁 4 寄存器的封装4 1 第一种封装方式 xff08 宏定义 xff09 4 2 第二
  • C++中auto的用法

    目录 1 auto初始化 1 1auto还可以与指针 xff0c 引用以及const进行组合 xff0c 但是在不同场景下会有相对应的推导规则 1 1 1指针和引用 1 1 2const 2 增强for循环 3 auto的限制 C 43 4
  • 自定义函数实现strcat函数功能

    strcat函数定义 字符串追加 连接函数 它的功能就是在一个字符串后面追加上另外一个字符串 char strcat char destination const char source 特点 xff08 与strcpy类似 xff09 x
  • STM32实现智能加湿

    开发前的准备需要如下的材料 xff1a 雾化模块1个 STM32F103开发板一个 风扇驱动模块1个 xff08 可用继电器代替 xff09 我们采用的继电器是低电平触发的所以我们在使用的时候只用给它一个低电平的信号就可以控制它了 USB转
  • Qt项目实战:愤怒的小鸟(联机版)

    前言 本文章会详细介绍难点的内容 xff0c 不附带全部源码 xff0c 会将关键代码进行展示 因为只有截图 xff0c 这里在每一个动作和界面都添加了音效与BGM 同时附加了CG展示 素材和音效全部放在下面了 xff0c 需要可自行提取
  • Ubuntu中安装openCV时Cmake问题解决

    1 执行Cmake的语句指令 sudo cmake D CMAKE BUILD TYPE 61 Release D CMAKE INSTALL PREFIX 61 usr local 2 当执行完上述指令后遇见以下问题解决策略 问题1 xf
  • 使用 RGB-D 相机(Astra)实现 YOLO v3 实时目标检测

    设备和环境 xff1a 奥比中光RGB D相机 xff08 Astra xff09 xff1b Ubuntu16 04 首先 xff0c 先将自己的RGB D相机的环境与依赖构建好 xff0c 然后进行以下步骤构建darknet ros 1
  • Arduion应用U8g2库实现字符滚动效果

    由于U8g2库中没有可以位移的函数 xff0c 所以简单编写了一个可以实现字符滚动的代码 主要是为了记录一下自己学习Arduion的过程 算是一个记事本吧 xff01 当然如果你对于这方面有所需求 xff0c 可以拿去使用 主要是利用显示器
  • C语言老鼠走迷宫(单路径)算法详细讲解

    最近在学习C语言的一些经典算法 xff0c 其中遇到了一点困难 xff0c 导致卡进度了 琢磨了很久 xff0c 在绘制流程图时 xff0c 突然灵感大开理解了 xff0c 老鼠走迷宫算法的奇妙 所以写了这个 xff0c 一来是方便以后右和
  • 关于二分搜索法条件判断的研究

    最近在写二分搜索法时 xff0c 发现了几个现象 xff0c 在不同的条件设定之下 xff0c 系统会出现几种bug xff1a 1 当搜索的值 lt 最小值 时系统都会一直在循环内执行 2 当搜索的值 gt 最大值 时系统都会一直在循环内
  • C++ 库函数<string>示例

    最近在学C 43 43 自己整理了一部分C 43 43 库函数 lt string gt 的一些 函数 主要都是C 43 43 的 想到以后可能会用到 所以打算记录一下 方便自己也方便了大家 在啃这些函数的时候有很多借鉴之处 xff0c 在
  • 两台电脑间的串口通信

    目录 一 准备工作 二 实验过程 三 实验结果 一 准备工作 1 两台笔记本电脑 2 2个usb转串口模块 3 杜邦线若干 4 秒表 二 实验过程 两个串口线分别连接两台电脑 连线方式 xff1a 3V3 3V3 xff0c GND GND
  • c++ primer plus学习笔记(1)——基础知识

    本人还有一星期要开始期末考试了 xff0c 复习c 43 43 时顺便挖个坑 xff0c 之后会详细更新 目录 1 初识源代码 1 1 c 43 43 程序的产生 1 2 代码例 1 3 标记 空白 2 简单数据类型 2 1 变量名 2 2
  • C语言:sizeof和strlen计算字符串大小

    大家清楚 sizeof 和 strlen 的区别吗 xff1f sizeof是运算符 xff0c 确定的是字符所占空间大小 xff0c 参数可以有数组 指针 类型 对象 函数等 strlen是C语言的标准库函数 xff0c 确定是字符串的大
  • Python--爬虫--requests进阶,cookie/session模拟登录

    目录 一 原理 二 实际操作 三 结果 四 问题与总结 一 原理 以下内容为使用requests库发送请求 xff0c 使用cookie session模拟登录 xff08 并且登录时只需输入账号与密码 xff09 我们在使用搜索引擎访问网
  • linux系统移植U-boot与kernel的搭载流程(交互模式下)

    Linux系统移植四大部分 xff1a 搭建交叉开发环境 bootloader的选择和移植 本文选用bootloader下的U boot uImage的配置 编译与移植 根文件系统的制作 全部已完成 xff0c 本文只讲解 如何搭载这些东西
  • FreeRTOS任务创建、删除| FreeRTOS三

    目录 一 FreeRTOS任务创建与删除有关函数 1 1 创建 删除任务的API函数 1 1 1 动态创建任务 1 1 2 静态创建任务 1 1 3 删除任务 二 FreeRTOS任务创建与删除 xff08 动态方法 xff09 2 1 实
  • (学习)基于STM32的串口通信打印数据(HAL库+CubeMX)

    当我们在进行开发的时候 xff0c 通常需要将一些参数进行调整来达到效果 xff0c 这个时候就需要将单片机上的信息通过串口通信传送到PC机上来直观显示 一 基本的专有名词和原理介绍 USART xff1a 只能异步通信 USART xff
  • ROS通信——C++实现

    一 普通话题通信 创建功能包 xff1a catkin create pkg package roscpp rospy std msgs 创建发布者 xff1a include 34 ros ros h 34 include 34 std