我的ROS学习笔记(四)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

发布者程序包含了很多之前不懂的知识,刚开始也许只能复制粘贴代码来运行实例,但最终目的还是为了自己能够编写这些代码。因此,弄明白哪部分代码是什么意思非常有必要,不能做一个复制粘贴机器!

一、包含消息类型声明

每一个消息类型都有一个相对应 C++头文件。你需要在你的程序中为每一个用到的消息类型包含这个头文件,代码如下所示:

#include <package_name/type_name.h>

功能包名应该是定义消息类型的包的名称,而不一定是你自己的包的名称。在 程序中,我们想发布一条类型为 geometry_msgs/Twist 的消息(名为 geometry_msgs 的包所拥有的类型为 Twist 的消息),我们应该这样:

#include <geometry_msgs/Twist.h>

这个头文件的目的是定义一个 C++类,此类和给定的消息类型含有相同的数据类型成员。这个类定义在以包名命名的域名空间中。这样命名的实际影响是当引用 C++代码中的消息类时,你将会使用双分号(::)来区分开包名和类型名,双分号也称为范围解析运 算 符 。例程中,头文件定义了一个名为geometry_msgs::Twist 的类。

二、创建发布者对象

发布消息的实际工作是由类名为ros::Publisher的一个对象来完成的 。类似下面这行的代码创建了我们需要的对象:

ros::Publisher pub = node_handle.advertise<message_type>(topic_name, queue_size);

node_handle 是 ros::NodeHandle 类的一个对象,是你在程序的开始处创建的。我们将调用这个对象的 advertise 方法。

message_type 部分,其正式名称为模板参数,是我们要发布的消息的数据类型。这个应该是上面讨论过的头文件中定义的类 名 。 在 例 程 中 , 我 们 使 用geometry_msgs::Twist 类。

topic_name 是一个字符串,它包含了我们想发布的话题的名称。它应该和 rostopic list 或者 rqt_graph 中展示的话题名称一致,但通常没有前斜杠(/)。我们丢掉前斜杠使话题名为一个相对名称;第 5 章解释了相对名称的机制和目的。在此例程中,话题名为 turtle1/cmd_vel。

advertise 最后的参数是一个整数,表示这个发布者发布的消息序列的大小。在大多数情况下,一个相对比较大的值,比方说 1000,是合适的。如果你的程序迅速发布比队列可以容纳的更多的消息,最早进入队列的未发送的消息将被丢弃。

如果你想从同一个节点发布关于多个话题的消息,你需要为每个话题创建一个独立的 ros::Publisher 对象。

三、创建并填充消息对象

我们创建消息对象本身。当我们创建 ros::Publisher 对象时已经引用了消息类。对于消息类型的每
个域,这个类都有一个可公共访问的数据成员。
我们使用 rosmsg show命令看到消息类型geometry_msgs/Twist 有两个顶层域(linear 和 angular),每个域都包含了三个子域(x、 y 和 z)。每个子域是一个 64 位的浮点数,许多 C++编译器称为 double 型。表 中的代码创建了一个geometry_msgs::Twist 对象,并且把伪随机数赋值给其中两个数据成员:

geometry_msgs::Twist msg;
msg.linear.x = double(rand())/double(RAND_MAX);
msg.angular.z = 2*double(rand())/double(RAND_MAX) - 1;

四、发布消息

在所有的前期工作完成后,使用 ros::Publisher 对象的publish 方法可以很简单地发布消息。例如下面所示:
pub.publish(msg);
这个方法将所给的消息添加到发布者的输出消息队列中,从这里,它会尽快被发送到相同话题的订阅者那里。

五、消息发布循环

1.节点是否停止工作的检查

publisher的 while 循环的条件是:
ros::ok()
通俗地说,这个函数检查我们的程序作为 ROS 节点是否仍处于运行良好的状态。它会一直返回 true,除非这个节点有某种原因使其停止工作。有如下几个原因会使 ros::ok()返回 false:
1.你可能对节点使用了 rosnode kill 命令。
2. 你可能给程序发送了一个终止信号(Ctrl-C)。

2.控制消息发布频率

publisher的最后一个新 知识点是它使用了

ros::Rate对象 :

ros::Rate rate(2);
这个对象控制循环运行速度,其构造函数中的参数以赫兹(Hz)为单位,即每秒钟的循环数。这个例子创建了旨在规范每秒钟执行两个迭代循环的速率对象。邻近每次循环迭代的结尾,我们调用此对象的 sleep 方法:

rate.sleep();
每次调用此方法时就会在程序中产生延迟。延迟的持续时间被用来阻止循环的迭代速率超过指定的速率。没有这种控制,程序会以计算机允许的最快速度发布消息,这样会占满发布和订阅的序列,并且浪费计算和网络资源(在作者的电脑上,一个不加控制的程序会每秒发布大约 6300 条消息。)。


 * 该例程将发布/person_info话题,自定义消息类型learning_topic::Person

 
#include <ros/ros.h>
#include "learning_topic/Person.h"

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "person_publisher");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
    ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);

    // 设置循环的频率
    ros::Rate loop_rate(1);

    int count = 0;
    while (ros::ok())
    {
        // 初始化learning_topic::Person类型的消息
    	learning_topic::Person person_msg;
		person_msg.name = "Tom";
		person_msg.age  = 18;
		person_msg.sex  = learning_topic::Person::male;

        // 发布消息
		person_info_pub.publish(person_msg);

       	ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d", 
				  person_msg.name.c_str(), person_msg.age, person_msg.sex);

        // 按照循环频率延时
        loop_rate.sleep();
    }

    return 0;
}

总结

**编译publisher程序的时候,因为 程序使用了来自 geometry_msgs 包的消息类型,我们必须声明对这个包的依赖关系。**这和之前添加roscpp依赖库很相似,分别修改 CMakeLists.txt 文件的 find_package 行 来 声 明geometry_msgs,以及在 package.xml 文件中添加新的依赖项就行了。
(如果要问怎么添加,添加什么的话,我就不告诉你!)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值