通过下方指令先创建一个ros2工作空间,必须包含src文件,而后进入该工作空间
src -> source 意思是源代码,用于存放各种功能包。
# 创建并进入工作空间下的src文件
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
在src文件下创建一个功能包。
# 在工作空间的src目录下创建包(使用C++)
# 包名: hello_world_pkg,依赖: rclcpp
ros2 pkg create hello_world_pkg --build-type ament_cmake --dependencies rclcpp
在pkg的src文件中创建一个c++节点,则文件结构如下所示:
ros2_ws/
└── src/
└── hello_world_pkg/
├── CMakeLists.txt
├── package.xml
└── src/
└──publisher_node
.cpp
而后我们先简单的写一个发布者的节点
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp" // 使用ROS 2标准字符串消息类型
#include <chrono>
// 创建发布者节点类
class PublisherNode : public rclcpp::Node {
public:
PublisherNode() : Node("string_publisher") {
// 创建发布者,参数说明:
// 1. 话题名称:"topic"
// 2. 队列大小:10
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
// 创建定时器,每秒发布一次消息
timer_ = this->create_wall_timer(
std::chrono::seconds(1), // 1秒间隔
[this]() { this->publish_message(); } // Lambda回调
);
RCLCPP_INFO(this->get_logger(), "发布者节点已启动,每秒发布一次消息...");
}
private:
// 发布消息函数
void publish_message() {
auto message = std_msgs::msg::String();
message.data = "Hello ROS 2 - " + std::to_string(count_++);
// 发布消息
publisher_->publish(message);
// 打印日志
RCLCPP_INFO(this->get_logger(), "发布消息: '%s'", message.data.c_str());
}
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
size_t count_ = 0; // 消息计数器
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
auto node = std::make_shared<PublisherNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
在写一个订阅者的节点:
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
// 创建订阅者节点类
class SubscriberNode : public rclcpp::Node { //这个是继承操作
public:
SubscriberNode() : Node("string_subscriber") {//必须在构造函数的初始化列表里进行节点定义
// 创建订阅者,参数说明:
// 1. 话题名称:"topic"(需与发布者一致)
// 2. 队列大小:10
// 3. 回调函数:使用Lambda处理接收到的消息
subscription_ = this->create_subscription<std_msgs::msg::String>(
"topic",
10,
[this](const std_msgs::msg::String::SharedPtr msg) {
this->message_callback(msg);
});
RCLCPP_INFO(this->get_logger(), "订阅者节点已启动,等待消息...");
}
private:
// 消息接收回调函数
void message_callback(const std_msgs::msg::String::SharedPtr msg) {
RCLCPP_INFO(this->get_logger(), "收到消息: '%s'", msg->data.c_str());
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
auto node = std::make_shared<SubscriberNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
写好两个节点代码以后需要修改一下cmake和package.xml文件
cmake:在 ament_package() 前添加
# 添加可执行文件
add_executable(publisher_node src/publisher_node.cpp)
# 添加需要的依赖
ament_target_dependencies(publisher_node rclcpp std_msgs)
add_executable(subscriber_node src/subscriber_node.cpp)
ament_target_dependencies(subscriber_node rclcpp std_msgs)
# 安装可执行文件
install(TARGETS
publisher_node
subscriber_node
DESTINATION lib/${PROJECT_NAME}
)
在package.xml中确认是否有rclcpp 和 std_msgs的依赖,没有则需要添加上
<depend>rclcpp</depend>
<depend>std_msgs</depend>
而后在工作空间下进行编译
cd ~/ros2_ws
# 这里创建了两个新的节点,所以需要使用完整的编译方式
colcon build
# 如果没有创建新的节点而是修改了节点代码这可以使用简易编译的方法加快编译速度
colcon build --symlink-install
# 单独编译一个包可以使用
colcon build --package-select hello_world_pkg
# 如果需要清楚编译记录这运行下面指令
rm -rf build install log
# 编译后source一下源文件即可运行节点,但需要在两个终端中运行
###############终端一#################
source install/setup.bash
ros2 run test_pkg publisher_node###############终端二#################
source install/setup.bash
ros2 run test_pkg subscriber_node
终端显示结果:发布者:
订阅者: