写一个publisher
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #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; }
|
代码审查
#include "rclcpp/rclcpp.hpp"
表示你可以使用ROS2系统中最常用的一些功能,#include "std_msgs/msg/string.hpp"
则是用于发送消息所使用的ROS的String类型
同时,前面的头文件include也表示自己引入过的依赖,这在package和CMakeList里面也一定要添加。
下面一行表示创建了一个类MinimalPublisher,继承与Node。因此这里的每一个this都指代Node
1
| class MinimalPublisher : public rclcpp::Node
|
public的构造函数,初始化count_为0,在构造函数里面,publisher的消息类型被初始化为String,topic的名字为“topic”,能接受的存储消息队列大小极限为10。下面timer被初始化,每一秒会调用timer_callback两次。
1 2 3 4 5 6 7 8
| 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)); }
|
timer_callback函数是设置消息的地方,RCLCPP_INFO
是可以确保消息会打印出来
1 2 3 4 5 6 7 8
| 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); }
|
最后是main函数,是node实际执行的地方,rclcpp::init会初始化ROS2,rclcpp:spin是开始处理数据的地方,包括callbacks
1 2 3 4 5 6 7
| int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<MinimalPublisher>()); rclcpp::shutdown(); return 0; }
|
添加依赖至package.xml
首先,确保<description>
, <maintainer>
and <license>
这三个标签的内容以及填写完毕,然后在ament_cmake
buildtool_depend依赖项的后面添加以下依赖
1 2
| <depend>rclcpp</depend> <depend>std_msgs</depend>
|
CMakeLists.txt
现在打开CMakeLists.txt,在find_package(ament_cmake REQUIRED)的后面添加以下两句话
1 2
| find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED)
|
之后,需要添加executable,命名为talker,这样我们就可以使用ros2 run来跑结点
1 2
| add_executable(talker src/publisher_member_function.cpp) ament_target_dependencies(talker rclcpp std_msgs)
|
最后添加以下install,这样才可以让ros2 run来找到可执行结点
1 2 3
| install(TARGETS talker DESTINATION lib/${PROJECT_NAME})
|
现在可以清理以下CMakeLists,清理一些没有用的部分和注释,像下面所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| cmake_minimum_required(VERSION 3.5) project(cpp_pubsub)
# Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif()
find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED)
add_executable(talker src/publisher_member_function.cpp) ament_target_dependencies(talker rclcpp std_msgs)
install(TARGETS talker DESTINATION lib/${PROJECT_NAME})
ament_package()
|
写一个subscriber
代码审查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #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::SharedPtr 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; }
|
其实,subscriber和publisher基本一样,现在他的名字是minimal_subscriber,注意这里没有timer,因为订阅者只是反馈订阅到消息之后的动作
topic_callback接受消息,并且简单利用了RCLCPP_INFO打印了一下消息,在这里 main函数和package.xml和之前是一模一样的
CMakeList.txt
重新打开CMakeLists, 添加一下订阅者的结点,并且安装到对应的目录下
1 2 3 4 5 6 7
| add_executable(listener src/subscriber_member_function.cpp) ament_target_dependencies(listener rclcpp std_msgs)
install(TARGETS talker listener DESTINATION lib/${PROJECT_NAME})
|
build and run
首先我们要确保自己已经安装了依赖
1
| rosdep install -i --from-path src --rosdistro foxy -y
|
然后开始编译
运行
1
| ros2 run package_name node_name
|