17.ROS编程学习:通信的各种进阶使用c++

目录

一、以话题通信的c++初始化节点api进阶使用

1.初始化节点代码提示与c++话题通信例程

2.初始化节点使用进阶

3.初始化节点参数解读

4.初始化节点加options参数效果

二、话题通信发布方对象进阶

1.创建发布者代码提示与c++话题通信例程

2.创建发布者api进阶

3.改进后结果分析

三、回头函数加深理解

1.ros::spinOnce();

2.ros::spin();

参考学习资料:B站赵虚左的ROS课程

一、以话题通信的c++初始化节点api进阶使用

1.初始化节点代码提示与c++话题通信例程

初始化函数的代码提示:(可通过ctrl+shift+空格查看代码提示)

void init(int &argc, char **argv, const std::string& name, uint32_t options = 0);

之前练习的话题通信的c++实现例程:
2.ROS编程学习:话题通信c++_机械专业的计算机小白的博客-优快云博客https://blog.youkuaiyun.com/wzfafabga/article/details/127081895

2.初始化节点使用进阶

pub.cpp

修改内容:

ros::init(argc,argv,"publisher");
ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    // ros::init(argc,argv,"publisher";
    ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
    ros::NodeHandle n;
    ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);
    std_msgs::String msg;
    ros::Rate rate(10);
    int count = 0;
    while (ros::ok())
    {
        count++;
        std::stringstream ss;
        ss << "hello -->" << count;
        msg.data = ss.str();
        pub.publish(msg);
        ROS_INFO("发布数据:%s", msg.data.c_str());
        rate.sleep();
        ros::spinOnce();
    }
    return 0;
}

3.初始化节点参数解读

一.概念

1.ROS初始化函数

void init(int &argc, char **argv, const std::__cxx11::string &name, uint32_t options = 0U)
ros::init(argc,argv,"publisher");

2.参数
argc 封装实参的个数,n+1个,因为第一个参数为文件名,并不是想要配置的参数.
argv 封装实参的数组,第0个元素为文件名.
name 为节点命名,这个必须具有唯一性,如果启动一个节点后,再启动相同的节点前一个节点会被shudown.
options 特定情况下,同一个节点要启动两次,而且需要都正常运行.原理是每个节点名后自动添加一个随机数,让其节点名不同.
3.返回值:空void

二.用法
argc+argv: ①通过主函数中的int argc, char  *argv[]传入实参②按照特定格式传入实参,ROS加以使用,实现设置全局参数,给节点重命名。
options:实现相同节点多次启动ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);

主函数中的argc和argv的用法详见如下优化客户端部分,如下这个服务通信例子调用了实参个数和实参组成的数组。

7.ROS编程学习:自定义服务数据c++调用_机械专业的计算机小白的博客-优快云博客https://blog.youkuaiyun.com/wzfafabga/article/details/127383302?spm=1001.2014.3001.5501

4.初始化节点加options参数效果

初始化节点加了options的结果:

启动ROS Master

roscore

 启动发布者节点

rosrun sub_pub pub

再次启动相同的发布者节点 

rosrun sub_pub pub

 两个节点能一起运行

查看所有节点名 

rosnode list
rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosnode list
/publisher_1666695811703949824
/publisher_1666695832571769067
/rosout

发现创建的发布者节点名/publisher后面自动加了随机数,使得节点不重名,以至于能一起运行。

二、话题通信发布方对象进阶

1.创建发布者代码提示与c++话题通信例程

.创建发布者代码提示(可通过ctrl+shift+空格查看代码提示)

ros::Publisher advertise<M>(const std::__cxx11::string &topic, uint32_t queue_size, bool latch = false)

利用到c++实现的话题通信中的创建发布者部分

(1条消息) 2.ROS编程学习:话题通信c++实现_机械专业的计算机小白的博客-优快云博客https://blog.youkuaiyun.com/wzfafabga/article/details/127081895

2.创建发布者api进阶

pub.cpp

改动的部分:

ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);
ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000,true);
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    // ros::init(argc,argv,"publisher";
    ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
    ros::NodeHandle n;
    // ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);
    ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000,true);
    std_msgs::String msg;
    ros::Rate rate(10);
    int count = 0;
    while (ros::ok())
    {
        count++;
        std::stringstream ss;
        ss << "hello -->" << count;
        msg.data = ss.str();
        pub.publish(msg);
        ROS_INFO("发布数据:%s", msg.data.c_str());
        rate.sleep();
        ros::spinOnce();
    }
    return 0;
}

latch参数介绍:

其中最后一个参数是latch是一个布尔值,它的作用是在发布方停止发布消息时保留最后一次的发布消息留给订阅者,这是为了防止发布方不停的发布消息导致占用性能,在处理静态数据时需要这个参数为true。如果latch为false,发布方停止发布数据时,订阅方是接收不到消息的。

例子小车路径规划时,地图是不变的,故没必要不停的刷新地图,造成性能的浪费,故在地图的发布方的latch参数设置为true。

改动pub.cpp使得其发布10条消息停止发布

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    // ros::init(argc,argv,"publisher";
    ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
    ros::NodeHandle n;
    // ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);
    ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000,true);
    std_msgs::String msg;
    ros::Rate rate(10);
    int count = 0;
    while (ros::ok())
    {
        count++;
        std::stringstream ss;
        ss << "hello -->" << count;
        msg.data = ss.str();
        if(count <= 10)
        {
            pub.publish(msg);
            ROS_INFO("发布数据:%s", msg.data.c_str());
            rate.sleep(); 
        }
        // pub.publish(msg);
        // ROS_INFO("发布数据:%s", msg.data.c_str());
        // rate.sleep();
        ros::spinOnce();
    }
    return 0;
}

3.改进后结果分析

启动ROSMaster

roscore

启动发布者,发布10条消息停止发布

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub pub
[ INFO] [1666786808.842602969]: 发布数据:hello -->1
[ INFO] [1666786808.943626137]: 发布数据:hello -->2
[ INFO] [1666786809.043588395]: 发布数据:hello -->3
[ INFO] [1666786809.143665020]: 发布数据:hello -->4
[ INFO] [1666786809.243587508]: 发布数据:hello -->5
[ INFO] [1666786809.342738647]: 发布数据:hello -->6
[ INFO] [1666786809.443286320]: 发布数据:hello -->7
[ INFO] [1666786809.543143779]: 发布数据:hello -->8
[ INFO] [1666786809.642728771]: 发布数据:hello -->9
[ INFO] [1666786809.742740936]: 发布数据:hello -->10

启动订阅者,订阅到最后一条数据

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub sub
[ INFO] [1666787054.272108779]: 订阅的数据为:hello -->10

三、回头函数加深理解

1.ros::spinOnce();

回一次头且写在ros::spinOnce();后面的代码还会运行。

实验:

pub.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    // ros::init(argc,argv,"publisher";
    ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
    ros::NodeHandle n;
    // ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);
    ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000,true);
    std_msgs::String msg;
    ros::Rate rate(1);
    int count = 0;
    while (ros::ok())
    {
        count++;
        std::stringstream ss;
        ss << "hello -->" << count;
        msg.data = ss.str();
        if(count <= 10)
        {
            pub.publish(msg);
            ROS_INFO("发布数据:%s", msg.data.c_str());
            rate.sleep(); 
        }
        // pub.publish(msg);
        // ROS_INFO("发布数据:%s", msg.data.c_str());
        // rate.sleep();
        ros::spinOnce();
        ROS_INFO("实验:看看这行代码运行情况");
    }
    return 0;
}

ros::spinOnce();效果,看出回一次头下面的代码正常运行

rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub pub
[ INFO] [1666787480.639928822]: 发布数据:hello -->1
[ INFO] [1666787481.641120474]: 实验:看看这行代码运行情况
[ INFO] [1666787481.641195387]: 发布数据:hello -->2
[ INFO] [1666787482.640193316]: 实验:看看这行代码运行情况
[ INFO] [1666787482.640266774]: 发布数据:hello -->3
[ INFO] [1666787483.640754102]: 实验:看看这行代码运行情况
[ INFO] [1666787483.640828620]: 发布数据:hello -->4
[ INFO] [1666787484.640382732]: 实验:看看这行代码运行情况
[ INFO] [1666787484.640486097]: 发布数据:hello -->5

2.ros::spin();

不停回头,不停在回调函数中循环,意味着节点不停,回调函数循环不停,所以不停回头函数后的代码不能运行。

实验:

sub.cpp

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

void huidiao(const std_msgs::String::ConstPtr & msggg)
{
    ROS_INFO("订阅的数据为:%s", msggg->data.c_str());
}

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "subscriber");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe<std_msgs::String>("chongfu", 1000, huidiao);
    ros::spin();
    ROS_INFO("实验:看看这行代码运行情况");
    return 0;
}

启动订阅者和发布者

rosrun sub_pub sub
rosrun sub_pub pub
rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosrun sub_pub sub
[ INFO] [1666787805.552861795]: 订阅的数据为:hello -->1
[ INFO] [1666787806.306914044]: 订阅的数据为:hello -->2
[ INFO] [1666787807.307552251]: 订阅的数据为:hello -->3
[ INFO] [1666787808.306867980]: 订阅的数据为:hello -->4
[ INFO] [1666787809.307330567]: 订阅的数据为:hello -->5
[ INFO] [1666787810.307291604]: 订阅的数据为:hello -->6
[ INFO] [1666787811.307101347]: 订阅的数据为:hello -->7
[ INFO] [1666787812.307234292]: 订阅的数据为:hello -->8
[ INFO] [1666787813.307128563]: 订阅的数据为:hello -->9
[ INFO] [1666787814.307039999]: 订阅的数据为:hello -->10

回头函数后面的代码没有运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值