ROS学习笔记(三)

前言

关于发布方用到的几个零碎的知识点

1、初始化ROS节点


//2.初始化 ROS 节点  
    ros::init(argc,argv,"talker");//其定义如下:name必须唯一

/** @brief ROS initialization function.
 *
 * This function will parse any ROS arguments (e.g., topic name
 * remappings), and will consume them (i.e., argc and argv may be modified
 * as a result of this call).
 *
 * Use this version if you are using the NodeHandle API
 *
 * \param argc
 * \param argv
 * \param name Name of this node.  The name must be a base name, ie. it cannot contain namespaces.
 * \param options [optional] Options to start the node with (a set of bit flags from \ref ros::init_options)
 * \throws InvalidNodeNameException If the name passed in is not a valid "base" name
 *
 */
ROSCPP_DECL void init(int &argc, char **argv, const std::string& name, uint32_t options = 0);

2、 句柄:句柄的意义和作用以及句柄和指针的区别 - 菜鸟开车 - 博客园 (cnblogs.com)

相当于为他取了个简单的名字,或者专业一点:句柄就是像一个指向指针的指针

3、创建发布对象的参数含义

//4.创建发布者对象
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);
    改名                     发布者    发布的消息类型      话题     消息最多看到几个

4、消息发布这里涉及到了C++里的重载,重载函数就是多个函数具有相同的函数标识名,而参数类型或参数个数不同,函数调用时,编译器根据参数的类型以及参数的个数来区分调用的哪一个函数。下面我们用到的消息发布,他的定义里有要求发布的消息是字符串型。

消息发布:
pub.publish(msg);//用这个发布者对象发布消息,看定义,也和我们之前的创建发布者那边有关,他只能发布string的
下面是他的定义

void ros::Publisher::publish<std_msgs::String>(const std_msgs::String &message) const
还有 3 个重载

Publish a message on the topic associated with this Publisher.

二、订阅方实现

1、创建订阅方C++文件

2、编程

流程如下(与发布方区别不大)

2.1 订阅方实现

1、包含头文件

//ros里的文本类型——————>std_msgs/String.h
//1.包含头文件;
#include"ros/ros.h" //包含了标准ROS类的声明
#include"std_msgs/String.h" //文本被封装成单独的数据类型了std_msgs功能包里的string.h
#include<sstream> //支持字符串的流输入输出

消息是从发布方来的,所以这边的头文件=发布方+订阅方处理数据所要用到的 

     2.初始化 ROS 节点

    setlocale(LC_ALL,"");//防止乱码
//2.初始化 ROS 节点
    ros::init(argc,argv,"Listener");//了解定义

     3.创建节点句柄

//3.创建节点句柄
    ros::NodeHandle nh;//相当于一个重命名 NodeHandle = nh 

     4.创建订阅者对象   和  5.处理订阅到的数据

//4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("chatter",10,doMsg);

        关于doMsg的定义: 这是一个回调函数,所谓回调函数:你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。 

PS:怎么区别回调函数和普通函数?回调函数是自己定义,系统调用(系统传实参),普通函数自己定义,自己调用(自己传实参)怎么看出来是自己调用还是系统调用,回调函数的时候往往可以定义形参,系统会给该形参传递实参,例如单击响应函数的,系统调用时会传入实参,所以,普通函数调用是自己传入实参,回调函数是系统传入实参。这个domsg的参数是由发布者传过来的,所以也是系统传参。

这其实算是消息的处理了,但是只处理了一次,执行到“创建订阅者对象”这边的程序时,就跳到doMsg那边,那边的相关操作就是打印结果,随着话题“chatter”里不断的有东西进来,就会不停的跳到doMsg(类似于中断,有信号触发,就跳转。)。但是不会有任何结果输出,想要有结果输出需要假如下面第6步的代码。

void doMsg(const std_msgs::String::ConstPtr &msg){
    //通过msg获取并操作订阅到的数据
    ROS_INFO("订阅的数据:%s",msg->data.c_str());
}

     6.spin()函数

    ros::spin();

这个函数很重要 !!!

根据上面的实例,我们来捋一捋处理流程

  1. 消息发布器(发布方)在一个while里面一直循环发送“hello ——>数字”到话题(topic)chatter上。
  2. 消息订阅器(订阅方)一旦知道chatter上面有data,就会将这data作为参数传入回调函数doMsg中,但是此时还没有执行domsg函数,而是把domsg函数放到了一个回调函数队列中。
  3. 所以当发布器不断发送data到chatter上面时,就会有相应的domsg函数进入队列中,它们函数名一样,只是实参不一样。

那什么时候处理回调函数队列中的回调函数了?这就是 ros::spin() 需要做的工作了。

  • 对于spin函数,一旦进入spin函数,它就不会返回了,也不继续往后执行了,相当于它在自己的函数里面死循环了(直到ctrl+c 或者程序终止的时候才退出)。
  • 主要的工作,就是不断的检查回调函数队列里面是否有domsg函数存在,如果有的话,它就会马上去执行domsg函数。如果没有的话,它就会阻塞,不会占用CPU。

综上所述,订阅方的函数也就结束了。

三、改写 CMakeLists.txt

我们在 ROS学习笔记(一)http://配置 CMakeLists.txt里有些这部分的内容

add_executable(demo01_pub src/demo01_pub.cpp)
add_executable(demo02_sub src/demo02_sub.cpp)

 target_link_libraries(demo01_pub
   ${catkin_LIBRARIES}
 )
 target_link_libraries(demo02_sub
 ${catkin_LIBRARIES}
)

四、运行 

参考ROS学习笔记(一)https://blog.csdn.net/weixin_49909631/article/details/121982247https://blog.csdn.net/weixin_49909631/article/details/121982247

执行七、八步骤即可

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lbuera

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值