ROS2机器人编程简述humble-第二章-Publishing and Subscribing .3.2

news/2023/6/9 20:20:56

ROS2机器人编程简述humble-第二章-Controlling the Iterative Execution .3.1

官方示例pub和sub使用std_msgs/msg/string.hpp,数据类型std_msgs::msg::String。

这本书中使用是std_msgs/msg/int32.hpp,数据类型:std_msgs::msg::Int32。

对于机器人系统而言,实际情况下pub/sub对应于传感器数据的发布和接收。

比如激光/图像等。

ros2案例通常都用类来实现各种功能,需要具备现代C++基础。

具体参考:

蓝桥ROS机器人之现代C++学习笔记支持C++17(已完成)

推荐掌握C++17/20之后,也就是在此基础上开启ROS2的学习之路。

不推荐如下方式:

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/int32.hpp"using namespace std::chrono_literals;int main(int argc, char * argv[])
{rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("publisher_node");auto publisher = node->create_publisher<std_msgs::msg::Int32>("int_topic", 10);std_msgs::msg::Int32 message;message.data = 0;rclcpp::Rate loop_rate(500ms);while (rclcpp::ok()) {message.data += 1;publisher->publish(message);rclcpp::spin_some(node);loop_rate.sleep();}rclcpp::shutdown();return 0;
}

std_msgs::msg::Int32推荐如下

pub发布:

#include "rclcpp/rclcpp.hpp"#include "std_msgs/msg/int32.hpp"using namespace std::chrono_literals;
using std::placeholders::_1;class PublisherNode : public rclcpp::Node
{
public:PublisherNode(): Node("publisher_node"){publisher_ = create_publisher<std_msgs::msg::Int32>("int_topic", 10);timer_ = create_wall_timer(500ms, std::bind(&PublisherNode::timer_callback, this));}void timer_callback(){message_.data += 1;publisher_->publish(message_);}private:rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr publisher_;rclcpp::TimerBase::SharedPtr timer_;std_msgs::msg::Int32 message_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);auto node = std::make_shared<PublisherNode>();rclcpp::spin(node);rclcpp::shutdown();return 0;
}

String

#include <chrono>
#include <functional>
#include <memory>
#include <string>#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"using namespace std::chrono_literals;/* This example creates a subclass of Node and uses std::bind() to register a
* member function as a callback from the timer. */class MinimalPublisher : public rclcpp::Node
{public:MinimalPublisher(): Node("minimal_publisher"), count_(0){publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));}private:void timer_callback(){auto message = std_msgs::msg::String();message.data = "Hello, world! " + std::to_string(count_++);RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());publisher_->publish(message);}rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;size_t count_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MinimalPublisher>());rclcpp::shutdown();return 0;
}

sub接收:

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/int32.hpp"using std::placeholders::_1;class SubscriberNode : public rclcpp::Node
{
public:SubscriberNode(): Node("subscriber_node"){subscriber_ = create_subscription<std_msgs::msg::Int32>("int_topic", 10,std::bind(&SubscriberNode::callback, this, _1));}void callback(const std_msgs::msg::Int32::SharedPtr msg){RCLCPP_INFO(get_logger(), "Hello %d", msg->data);}private:rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr subscriber_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);auto node = std::make_shared<SubscriberNode>();rclcpp::spin(node);rclcpp::shutdown();return 0;
}

String

#include <memory>#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using std::placeholders::_1;class MinimalSubscriber : public rclcpp::Node
{public:MinimalSubscriber(): Node("minimal_subscriber"){subscription_ = this->create_subscription<std_msgs::msg::String>("topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));}private:void topic_callback(const std_msgs::msg::String & msg) const{RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str());}rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MinimalSubscriber>());rclcpp::shutdown();return 0;
}

注意,代码的区别。

另一个重点!!!

rclcpp::QoS

pub和sub的QoS要匹配!

ROS 2提供了多种服务质量(QoS)策略,允许调整节点之间的通信。使用正确的服务质量策略集,ROS 2可以像TCP一样可靠,也可以像UDP一样尽最大努力,其间有许多可能的状态。与ROS 1不同,ROS 1主要只支持TCP,ROS 2受益于底层DDS传输在有损无线网络环境中的灵活性,在这种环境中,“尽力而为”策略更为合适,或者在实时计算系统中,需要正确的服务质量配置文件来满足截止日期。

一组QoS“策略”组合起来形成一个QoS“配置文件”。考虑到为给定场景选择正确的QoS策略的复杂性,ROS 2为常见用例(例如传感器数据)提供了一组预定义的QoS配置文件。同时,开发人员可以灵活地控制QoS配置文件的特定策略。

可以为发布者、订阅、服务服务器和客户端指定QoS配置文件。QoS配置文件可以独立地应用于上述实体的每个实例,但是如果使用不同的配置文件,则它们可能不兼容,从而阻止消息的传递。

QoS兼容性

注意:本节涉及发布者和订阅,但内容同样适用于服务器和客户端。

可以独立地为发布者和订阅配置QoS配置文件。只有当发布者和订阅之间具有兼容的QoS配置文件时,才会建立该对之间的连接。

QoS配置文件兼容性是基于“请求与提供”模型确定的。订阅请求的QoS配置文件是它愿意接受的“最低质量”,而发布者提供的QoS配置是它能够提供的“最高质量”。仅当所请求的QoS配置文件的每个策略不比所提供的QoS配置的每个策略更严格时,才进行连接。多个订阅可以同时连接到单个发布者,即使它们请求的QoS配置文件不同。发布者与订阅之间的兼容性不受其他发布者和订阅的影响。

下表显示了不同策略设置的兼容性及其结果:

可靠性QoS策略的兼容性:

Publisher

Subscription

Compatible

Best effort

Best effort

Yes

Best effort

Reliable

No

Reliable

Best effort

Yes

Reliable

Reliable

Yes

耐久性QoS策略的兼容性:

Publisher

Subscription

Compatible

Volatile

Volatile

Yes

Volatile

Transient local

No

Transient local

Volatile

Yes

Transient local

Transient local

Yes

最后期限QoS策略的兼容性:

假设x和y是任意有效的持续时间值。

Publisher

Subscription

Compatible

Default

Default

Yes

Default

x

No

x

Default

Yes

x

x

Yes

x

y (where y > x)

Yes

x

y (where y < x)

No

活泼QoS策略的兼容性:

Publisher

Subscription

Compatible

Automatic

Automatic

Yes

Automatic

Manual by topic

No

Manual by topic

Automatic

Yes

Manual by topic

Manual by topic

Yes

租赁期限QoS策略的兼容性:

假设x和y是任意有效的持续时间值。

Publisher

Subscription

Compatible

Default

Default

Yes

Default

x

No

x

Default

Yes

x

x

Yes

x

y (where y > x)

Yes

x

y (where y < x)

No

为了建立连接,所有影响兼容性的策略都必须兼容。例如,即使请求的和提供的QoS配置文件对具有兼容的可靠性QoS策略,但它们具有不兼容的耐久性QoS策略,仍然不会建立连接。

未建立连接时,发布者和订阅之间不会传递任何消息。有检测这种情况的机制,这将在后面的章节中介绍。

服务质量事件

某些QoS策略可能有与之相关的事件。开发人员可以为每个发布者和订阅提供由这些QoS事件触发的回调函数,并以他们认为合适的方式处理它们,类似于主题上接收的消息的处理方式。

开发人员可以订阅与发布者关联的以下QoS事件:

错过了提供的截止日期

发布者未在期限QoS策略规定的预期持续时间内发布消息。

失去活力

出版商未能在租约期限内表明其活跃程度。

提供不兼容的QoS

发布者遇到了同一主题的订阅,该订阅请求提供的QoS配置文件无法满足的QoS配置,导致发布者与该订阅之间没有连接。

开发人员可以订阅与订阅相关联的以下QoS事件:

请求的截止日期已错过

订阅在期限QoS策略规定的预期持续时间内未收到消息。

生活改变了

订阅已注意到订阅主题的一个或多个发布者未能在租约期限内显示其活跃状态。

请求的不兼容QoS

订阅遇到了同一主题的发布者,该发布者提供的QoS配置文件不满足请求的QoS配置,导致订阅与该发布者之间没有连接。

具体参考书和官网,如上是机器翻译。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4562606.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

极大似然估计详解,写的太好了!

极大似然估计 以前多次接触过极大似然估计&#xff0c;但一直都不太明白到底什么原理&#xff0c;最近在看贝叶斯分类&#xff0c;对极大似然估计有了新的认识&#xff0c;总结如下&#xff1a; 贝叶斯决策 首先来看贝叶斯分类&#xff0c;我们都知道经典的贝叶斯公式&#xff…

极大似然估计求解多项式分布参数

本文作者&#xff1a;合肥工业大学 管理学院 钱洋 email&#xff1a;1563178220qq.com 内容可能有不到之处&#xff0c;欢迎交流。 未经本人允许禁止转载。 #原因 今天晚上&#xff0c;老师在看LDA数学八卦的时候&#xff0c;问我一个问题&#xff0c;如下图所示&#xff1a; …

windows安装npm和cnpm

npm: 代码的包管理器&#xff0c;但是服服器在国外&#xff0c;每一次启动项目都要下载一些依赖&#xff0c;耗时之久&#xff0c;官网下载链接戳 npm。 cnpm&#xff1a;这是淘宝团队出的npm的镜像&#xff0c;可用此代替官方的只读版本&#xff0c;官网链接 cnpm。 先安装np…

DTX-1800还需要校准吗?

尽管DTX-1800已经停产&#xff0c;但是市场上普遍的应用还存在相当大的体量&#xff0c;随着福禄克已经停止支持&#xff0c;那么很多行业客户都在问一个问题&#xff0c;我的DTX-1800还需要校准吗&#xff1f;答案是肯定的。由于原厂是建议每满一年就需要返厂校准一次&#xf…

int 和 Integer 有什么区别?为什么要有包装类?

基本数据类型 在 Java 中&#xff0c;一共有 8 种基本类型&#xff08;primitive type&#xff09;&#xff0c;其中有 4 种整型、2 种浮点类型、1 种用于表示 Unicode 编码的字符类型 char 和 1 种用于表示真假值的 boolean 类型。 4 种整型&#xff1a;int、short、long、by…

DTX-1800精度恢复,调教之路?

自2004到2016&#xff0c;FLUKE DTX-1800长达12年的生命周期&#xff0c;可说是蔚为壮观&#xff0c;同时&#xff0c;其市场上的保有量也是可谓惊人。其经典程度不言而语&#xff0c;眼下已是2022年2月&#xff0c;但在实际的布线系统验收中&#xff0c;不乏其的身影频频出现。…

Fluke DTX-CHA001/DTX-CHA001A/DTX-CHA002的区别

Fluke DTX-CHA001/DTX-CHA001A/DTX-CHA002的区别如下&#xff1a; DTX-CHA001&#xff1a;六类通道适配器&#xff0c;可以测试六类及以下规格网线&#xff08;向下兼容&#xff09; DTX-CHA001A&#xff1a;优化用于测试外部串扰的六类通道适配器&#xff0c;可以测试六类及以…

福禄克FLUKE DTX-1800和DSX2-8000系列电缆认证分析仪如何导出测试报告?

绝大多数业内人士&#xff0c;都采用福禄克公司的DTX-1800和DSX2-8000系列电缆认证分析仪对综合布线或线缆进行验收。毕竟福禄克在这个领域的权威性和技术先进性&#xff0c;是无庸置疑的。而且导出的报告&#xff0c;尤其是原始报告&#xff0c;是不可更改的&#xff0c;行业内…