机器人和自动化技术的普及正在改变世界,而ROS2(Robot Operating System 2)作为新一代机器人开发框架,为开发者提供了强大的工具和灵活性。如果你是一名C++开发者,ROS2将是你进入机器人领域的理想起点。这篇教程将带你从环境配置到编写第一个C++节点,逐步掌握ROS2的核心开发流程。
一、环境配置:搭建高效的开发环境
1. 系统准备
在Ubuntu系统中,确保你的环境支持UTF-8编码。如果你尚未设置,请执行以下命令:
# 安装必要的工具并设置UTF-8编码
sudo apt update && sudo apt install locales -y
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
2. 添加ROS2仓库
接下来,你需要将ROS2的官方仓库添加到你的系统中:
# 安装证书工具
sudo apt install curl gnupg lsb-release
# 添加官方GPG密钥
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
-o /usr/share/keyrings/ros-archive-keyring.gpg
# 添加Rolling版本仓库源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
3. 安装ROS2核心
更新仓库并安装ROS2的核心组件:
# 更新并安装完整桌面版
sudo apt update
sudo apt install ros-rolling-desktop
# 安装开发工具链
sudo apt install \
build-essential \
cmake \
python3-colcon-common-extensions \
python3-rosdep2 \
python3-vcstool
4. 环境初始化
配置ROS2的环境变量,以便系统能够识别ROS2的命令和工具:
# 将ROS2的环境变量添加到bashrc中
echo "source /opt/ros/rolling/setup.bash" >> ~/.bashrc
# 立即生效
source ~/.bashrc
5. 依赖管理初始化
通过rosdep
工具管理ROS2的依赖项:
# 初始化rosdep
sudo rosdep init
rosdep update
二、创建工作空间与包:构建你的第一个ROS2项目
1. 初始化工作空间
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
colcon build # 构建空工作空间
2. 创建C++包
在src
目录下创建一个新的C++包:
cd ~/ros2_ws/src
ros2 pkg create my_cpp_pkg --build-type ament_cmake --dependencies rclcpp std_msgs
-
ament_cmake
:ROS2的C++构建系统(基于CMake) -
--dependencies
:指定依赖项(rclcpp
是C++核心库,std_msgs
包含基础消息类型)
三、编写C++节点:发布者与订阅者示例
1. 编写发布者节点
在my_cpp_pkg/src
目录下创建publisher_node.cpp
:
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using namespace std::chrono_literals;
class PublisherNode : public rclcpp::Node {
public:
PublisherNode() : Node("cpp_publisher") {
publisher_ = create_publisher<std_msgs::msg::String>("topic", 10);
timer_ = create_wall_timer(1s, [this]() {
auto message = std_msgs::msg::String();
message.data = "Hello, ROS2!";
publisher_->publish(message);
RCLCPP_INFO(get_logger(), "Publishing: '%s'", message.data.c_str());
});
}
private:
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char** argv) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<PublisherNode>());
rclcpp::shutdown();
return 0;
}
2. 编写订阅者节点
在同一目录下创建subscriber_node.cpp
:
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class SubscriberNode : public rclcpp::Node {
public:
SubscriberNode() : Node("cpp_subscriber") {
subscriber_ = create_subscription<std_msgs::msg::String>(
"topic", 10,
[this](const std_msgs::msg::String::SharedPtr msg) {
RCLCPP_INFO(get_logger(), "Received: '%s'", msg->data.c_str());
});
}
private:
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscriber_;
};
int main(int argc, char** argv) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<SubscriberNode>());
rclcpp::shutdown();
return 0;
}
四、配置CMakeLists.txt:构建与管理项目
修改my_cpp_pkg/CMakeLists.txt
文件,添加节点代码的构建配置:
cmake_minimum_required(VERSION 3.8)
project(my_cpp_pkg)
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(publisher_node src/publisher_node.cpp)
ament_target_dependencies(publisher_node rclcpp std_msgs)
install(TARGETS publisher_node DESTINATION lib/${PROJECT_NAME})
# 添加订阅者节点
add_executable(subscriber_node src/subscriber_node.cpp)
ament_target_dependencies(subscriber_node rclcpp std_msgs)
install(TARGETS subscriber_node DESTINATION lib/${PROJECT_NAME})
# 导出依赖
ament_export_dependencies(rclcpp std_msgs)
ament_package()
五、构建与运行:启动你的第一个ROS2项目
1. 构建项目
在工作空间根目录下运行以下命令进行构建:
cd ~/ros2_ws
colcon build --packages-select my_cpp_pkg
source install/setup.bash # 激活当前工作空间
2. 启动节点
在不同的终端中分别运行发布者和订阅者节点:
# 终端1:发布者
ros2 run my_cpp_pkg publisher_node
# 终端2:订阅者
ros2 run my_cpp_pkg subscriber_node
六、调试与优化:高效开发技巧
1. 调试工具
-
使用
gdb
调试C++节点:ros2 run --prefix 'gdb -ex run' my_cpp_pkg publisher_node
-
实时查看节点通信:
ros2 topic echo /topic
2. 日志系统
-
设置日志级别:
export RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message}" export RCUTILS_LOGGING_SEVERITY=DEBUG # 更改为DEBUG级别
七、进阶学习路径:不断探索与提升
1. 核心内容
-
自定义消息/服务接口:创建
.msg
、.srv
文件并编译 -
生命周期节点管理:使用
rclcpp_lifecycle
管理节点状态 -
多线程与回调组:理解
MultiThreadedExecutor
和回调组的用途
2. 工具链推荐
-
可视化调试:安装
RQt
、rviz2
、plotjuggler
-
性能分析:使用
ros2trace
跟踪实时性能
3. 推荐资源
-
官方文档:docs.ros.org
-
GitHub示例:ros2/examples
-
书籍:《Programming ROS2 with C++》
通过这篇教程,你已经成功搭建了ROS2的开发环境并完成了第一个C++节点的编写。接下来,你可以继续探索ROS2的更多功能,如自定义消息、服务接口与多机协作等。ROS2的世界广阔而充满挑战,期待你在这个领域取得更大的成就!
推荐阅读:ROS2 入门简介