一、发布话题
#include <chrono>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using namespace std::chrono_literals;
class ExamplePublisher : public rclcpp::Node {
public:
ExamplePublisher()
: Node("example_publisher"), count_(0) {
publisher_ = this->create_publisher<std_msgs::msg::String>("example_topic", 10);
timer_ = this->create_wall_timer(500ms, std::bind(&ExamplePublisher::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::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
size_t count_;
};
int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<ExamplePublisher>());
rclcpp::shutdown();
return 0;
}
class ExamplePublisher : public rclcpp::Node
ExamplePublisher():这是ExamplePublisher类的构造函数声明。构造函数的名称与类名相同,没有返回类型。
: Node("example_publisher"), count_(0):这是构造函数的初始化列表,用于在类实例化时初始化成员变量。在这里,我们初始化了两个成员变量:
Node("example_publisher"):通过调用基类rclcpp::Node的构造函数,使用字符串"example_publisher"作为节点名,创建一个名为example_publisher的ROS节点。这使得我们的ExamplePublisher类成为一个有效的ROS节点,可以与其他ROS节点进行交互。
count_(0):将count_成员变量初始化为0。在这个示例中,count_变量用于跟踪已发布的消息数量。
接下来,在构造函数的主体中,我们创建了一个发布器和一个定时器。定时器用于周期性地触发发布器发送消息。
public:
ExamplePublisher()
: Node("example_publisher"), count_(0) {
publisher_ = this->create_publisher<std_msgs::msg::String>("example_topic", 10);
timer_ = this->create_wall_timer(500ms, std::bind(&ExamplePublisher::timer_callback, this));
}
-
publisher_ = this->create_publisher<std_msgs::msg::String>("example_topic", 10);
这行代码创建了一个发布器,用于在名为
example_topic
的话题上发布std_msgs::msg::String
类型的消息。它使用create_publisher
函数创建一个发布器实例并将其赋值给publisher_
成员变量。create_publisher
函数的参数如下:- 第一个参数是话题名称,本例中为
"example_topic"
。 - 第二个参数是队列大小,本例中为
10
。这表示发布器将在内部存储最多10个未处理的消息,以便在订阅者没有足够快地处理它们时避免消息丢失。
- 第一个参数是话题名称,本例中为
-
timer_ = this->create_wall_timer(500ms, std::bind(&ExamplePublisher::timer_callback, this));
这行代码创建了一个定时器,用于在指定的时间间隔内周期性地触发回调函数。它使用
create_wall_timer
函数创建一个定时器实例并将其赋值给timer_
成员变量。create_wall_timer
函数的参数如下:- 第一个参数是定时器的周期,即两次回调触发之间的时间间隔。在这个例子中,我们使用C++的
std::chrono_literals
库来表示500ms
(500毫秒)的时间间隔。 - 第二个参数是一个回调函数,它在定时器触发时被调用。这里,我们使用
std::bind
函数将成员函数ExamplePublisher::timer_callback
与ExamplePublisher
类的实例(this
)进行绑定。这使得在定时器触发时,会调用ExamplePublisher
类的实例的timer_callback
方法。
- 第一个参数是定时器的周期,即两次回调触发之间的时间间隔。在这个例子中,我们使用C++的
这两行代码的目的是为ExamplePublisher
节点设置发布器和定时器,使得节点可以周期性地向指定的话题发送消息。
std::bind
是C++标准库中的一个实用函数,用于将可调用对象(如函数、函数指针、成员函数指针或函数对象)与其参数进行绑定。这样绑定后的对象可以在以后的任何时间点被调用,无需再为绑定的参数提供值。std::bind
的返回值是一个可调用对象(一个函数对象),当调用该对象时,它将调用绑定的可调用对象,并将预先绑定的参数传递给它。
在之前提供的ExamplePublisher
类的代码中,我们使用std::bind
将ExamplePublisher::timer_callback
成员函数与ExamplePublisher
类的实例(this
)进行绑定:
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);
}
void timer_callback()
是ExamplePublisher
类中定义的一个成员函数。它的主要作用是在定时器触发时被调用,执行与定时器关联的操作。在这个例子中,timer_callback
函数用于定期发布消息。
void timer_callback()
是ExamplePublisher
类中定义的一个成员函数。它的主要作用是在定时器触发时被调用,执行与定时器关联的操作。在这个例子中,timer_callback
函数用于定期发布消息。
-
auto message = std_msgs::msg::String();
:创建一个std_msgs::msg::String
类型的变量message
,用于存储要发布的字符串消息。 -
message.data = "Hello, world! " + std::to_string(count_++);
:设置message.data
的值为字符串"Hello, world! "
后跟count_
变量的字符串表示。count_
变量用于跟踪已发布的消息数量,这里的count_++
表示将count_
值加1后再赋值给message.data
。 -
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
:使用RCLCPP_INFO
宏将要发布的消息记录到ROS 2日志系统。this->get_logger()
返回当前节点的日志记录器,message.data.c_str()
将message.data
转换为C风格字符串,以便RCLCPP_INFO
宏能正确处理它。 -
publisher_->publish(message);
:调用publisher_
对象的publish
方法,将message
发布到指定的话题上。
当定时器触发时,timer_callback
函数被调用,执行以上操作以将字符串消息发布到指定的话题上。
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; rclcpp::TimerBase::SharedPtr timer_; size_t count_;
这些是ExamplePublisher
类的成员变量。我们逐个解释它们的作用:
-
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
: 这是一个指向rclcpp::Publisher
对象的智能指针(SharedPtr
)。rclcpp::Publisher
用于在ROS 2系统中发布消息。在这个例子中,发布器将发布std_msgs::msg::String
类型的消息。SharedPtr
(共享指针)是一种C++智能指针,用于自动管理对象的生命周期。当共享指针的引用计数为零时,它会自动释放所指向的对象。 -
rclcpp::TimerBase::SharedPtr timer_;
: 这是一个指向rclcpp::TimerBase
对象的智能指针(SharedPtr
)。rclcpp::TimerBase
用于在ROS 2系统中创建定时器,以便周期性地触发回调函数。在这个例子中,定时器用于定期调用timer_callback
函数,以发布std_msgs::msg::String
类型的消息。 -
size_t count_;
: 这是一个size_t
类型的变量,用于跟踪已发布的消息数量。在ExamplePublisher
类的timer_callback
函数中,每次发布消息时,count_
的值会递增。
这些成员变量为ExamplePublisher
类的实例提供了必要的属性和状态,使其能够执行ROS 2发布器节点的功能。
二、订阅话题
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <chrono>
#include <memory>
using namespace std::chrono_literals;
class Publisher : public rclcpp::Node
{
public:
Publisher():Node("example_publisher"),count_(0){
publisher_0 = this->create_publisher<std_msgs::msg::String>("example_topic", 10);
timer_0 = this->create_wall_timer(500ms, std::bind(&Publisher::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_0->publish(message);
}
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_0;
rclcpp::TimerBase::SharedPtr timer_0;
size_t count_;
};
int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<Publisher>());
rclcpp::shutdown();
return 0;
}
同理