MPL_ROS与ROS 2迁移指南:从ROS Kinetic到ROS 2 Foxy的完整迁移方案
MPL_ROS与ROS 2迁移指南:从ROS Kinetic到ROS 2 Foxy的完整迁移方案
【免费下载链接】mpl_rosA ROS wrapper for trajectory planning based on motion primitives项目地址: https://gitcode.com/gh_mirrors/mp/mpl_ros
欢迎来到MPL_ROS(Motion Primitive Library ROS)的ROS 2迁移完整指南!🚀 本文将详细介绍如何将基于运动基元的轨迹规划库从传统的ROS Kinetic平滑迁移到现代化的ROS 2 Foxy环境。无论您是机器人开发者还是ROS迁移新手,这篇指南都将为您提供清晰的步骤和实用的技巧。
MPL_ROS是一个强大的ROS包装器,专门用于基于运动基元(Motion Primitives)的轨迹规划。该项目在ROS 1生态系统中已经相当成熟,但随着ROS 2的普及,迁移到新平台成为了必然趋势。本文将带您了解从ROS Kinetic到ROS 2 Foxy的完整迁移方案。
📊 ROS 1与ROS 2架构对比
在开始迁移之前,让我们先了解两个版本的核心差异:
| 特性 | ROS 1 (Kinetic) | ROS 2 (Foxy) |
|---|---|---|
| 通信机制 | TCPROS/UDPROS | DDS (Data Distribution Service) |
| 节点生命周期 | 简单启动/关闭 | 完善的状态机管理 |
| 参数系统 | 基于XML | 动态参数服务 |
| 构建系统 | catkin | colcon + ament |
| Python版本 | Python 2.7 | Python 3.8+ |
MPL_ROS在2D占用网格地图中的轨迹规划效果
🔧 迁移准备与工具链
1. 环境配置检查
在开始迁移前,请确保您的系统满足以下要求:
- Ubuntu 20.04 (ROS 2 Foxy官方支持)
- ROS 2 Foxy Fitzroy已安装
- Python 3.8或更高版本
- CMake 3.5+
- 必要的依赖包:
libsdl1.2-dev,libsdl-image1.2-dev
2. 项目结构分析
MPL_ROS项目包含以下关键包,每个都需要单独迁移:
- motion_primitive_library- 核心轨迹规划算法
- planning_ros_msgs- ROS消息定义
- planning_ros_utils- ROS工具和插件
- mpl_external_planner- 外部规划器
- mpl_test_node- 测试节点和示例
MPL_ROS在3D体素地图中的轨迹规划效果
📝 消息定义迁移
ROS 1消息文件分析
在planning_ros_msgs/msg/目录中,MPL_ROS定义了多个自定义消息类型:
- VoxelMap.msg- 体素地图数据
- PrimitiveArray.msg- 运动基元数组
- PathArray.msg- 路径数组
- Trajectory.msg- 轨迹数据
ROS 2消息迁移步骤
步骤1:创建新的package.xml
ROS 2使用不同的package.xml格式:
<?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <package format="3"> <name>planning_ros_msgs</name> <version>0.0.0</version> <description>ROS 2 messages for MPL planning library</description> <maintainer email="sikang@seas.upenn.edu">sikang</maintainer> <license>Apache-2.0</license> <buildtool_depend>ament_cmake</buildtool_depend> <depend>std_msgs</depend> <depend>geometry_msgs</depend> <depend>nav_msgs</depend> <depend>sensor_msgs</depend> <member_of_group>rosidl_interface_packages</member_of_group> <test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_common</test_depend> </package>步骤2:更新CMakeLists.txt
cmake_minimum_required(VERSION 3.5) project(planning_ros_msgs) # 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(rosidl_default_generators REQUIRED) find_package(std_msgs REQUIRED) find_package(geometry_msgs REQUIRED) find_package(nav_msgs REQUIRED) find_package(sensor_msgs REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/VoxelMap.msg" "msg/PrimitiveArray.msg" "msg/PathArray.msg" "msg/Trajectory.msg" DEPENDENCIES std_msgs geometry_msgs nav_msgs sensor_msgs ) ament_export_dependencies(rosidl_default_runtime) ament_export_include_directories(include) ament_package()VoxelMap消息的类结构图
🔄 节点代码迁移
ROS 1节点示例分析
以mpl_test_node/src/map_planner_node.cpp为例,ROS 1代码结构:
#include <ros/ros.h> int main(int argc, char **argv) { ros::init(argc, argv, "test"); ros::NodeHandle nh("~"); ros::Publisher map_pub = nh.advertise<planning_ros_msgs::VoxelMap>("voxel_map", 1, true); // ROS 1参数获取 double goal_x; nh.param("goal_x", goal_x, 2.4); ros::spin(); return 0; }ROS 2节点迁移版本
#include "rclcpp/rclcpp.hpp" #include "planning_ros_msgs/msg/voxel_map.hpp" class MapPlannerNode : public rclcpp::Node { public: MapPlannerNode() : Node("map_planner_node") { // ROS 2参数声明 this->declare_parameter("goal_x", 2.4); this->declare_parameter("goal_y", 16.6); this->declare_parameter("goal_z", 0.05); // 获取参数值 double goal_x = this->get_parameter("goal_x").as_double(); // 创建发布者(ROS 2风格) map_pub_ = this->create_publisher<planning_ros_msgs::msg::VoxelMap>( "voxel_map", rclcpp::QoS(10).reliable().transient_local() ); // 定时器回调 timer_ = this->create_wall_timer( std::chrono::milliseconds(100), std::bind(&MapPlannerNode::timer_callback, this) ); } private: void timer_callback() { auto message = planning_ros_msgs::msg::VoxelMap(); // 填充消息... map_pub_->publish(message); } rclcpp::Publisher<planning_ros_msgs::msg::VoxelMap>::SharedPtr map_pub_; rclcpp::TimerBase::SharedPtr timer_; }; int main(int argc, char **argv) { rclcpp::init(argc, argv); auto node = std::make_shared<MapPlannerNode>(); rclcpp::spin(node); rclcpp::shutdown(); return 0; }PrimitiveArray消息的类结构图
🚀 Launch文件迁移
ROS 1 Launch文件示例
mpl_test_node/launch/map_planner_node/test.launch:
<launch> <node pkg="mpl_test_node" type="map_planner_node" name="test_primitive" output="screen"> <param name="goal_x" value="2.4"/> <param name="goal_y" value="16.6"/> </node> </launch>ROS 2 Launch文件迁移
创建对应的Python launch文件:
from launch import LaunchDescription from launch_ros.actions import Node from launch.substitutions import LaunchConfiguration from launch.actions import DeclareLaunchArgument def generate_launch_description(): return LaunchDescription([ DeclareLaunchArgument( 'goal_x', default_value='2.4', description='Goal X coordinate' ), DeclareLaunchArgument( 'goal_y', default_value='16.6', description='Goal Y coordinate' ), Node( package='mpl_test_node', executable='map_planner_node', name='test_primitive', output='screen', parameters=[{ 'goal_x': LaunchConfiguration('goal_x'), 'goal_y': LaunchConfiguration('goal_y'), 'goal_z': 0.05, 'v_max': 2.0, 'a_max': 1.0 }] ) ])🛠️ 构建系统迁移
ROS 1构建配置
ROS 1使用catkin构建系统,CMakeLists.txt示例:
cmake_minimum_required(VERSION 2.8.3) project(mpl_test_node) find_package(catkin_simple REQUIRED) find_package(motion_primitive_library REQUIRED) catkin_simple() cs_add_executable(map_planner_node src/map_planner_node.cpp) target_link_libraries(map_planner_node ${catkin_LIBRARIES})ROS 2构建配置
ROS 2使用ament_cmake,CMakeLists.txt需要更新:
cmake_minimum_required(VERSION 3.5) project(mpl_test_node) # 默认使用C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) find_package(planning_ros_msgs REQUIRED) find_package(motion_primitive_library REQUIRED) # 添加可执行文件 add_executable(map_planner_node src/map_planner_node.cpp) ament_target_dependencies(map_planner_node rclcpp std_msgs planning_ros_msgs ) # 链接库 target_link_libraries(map_planner_node ${motion_primitive_library_LIBRARIES} ) # 安装目标 install(TARGETS map_planner_node DESTINATION lib/${PROJECT_NAME} ) # 导出依赖 ament_export_dependencies(rclcpp std_msgs planning_ros_msgs) ament_package()📊 迁移检查清单
代码层面检查
头文件更新✅
#include <ros/ros.h>→#include "rclcpp/rclcpp.hpp"- 消息头文件路径更新
命名空间迁移✅
ros::→rclcpp::- 消息类型:
planning_ros_msgs::VoxelMap→planning_ros_msgs::msg::VoxelMap
参数系统更新✅
nh.param()→declare_parameter()+get_parameter()
发布者/订阅者✅
advertise()→create_publisher()- QoS配置需要显式设置
构建系统检查
package.xml格式✅
- format="2" → format="3"
- 依赖声明更新
CMakeLists.txt✅
find_package(catkin)→find_package(ament_cmake)- 构建目标配置更新
依赖管理✅
- 确保所有ROS 1依赖都有对应的ROS 2版本
运行时检查
启动系统✅
.launch文件 → Python launch文件- 参数传递方式更新
工具链✅
roscore→ 不再需要rosrun→ros2 runrostopic→ros2 topic
MPL_ROS在SE(3)空间中的椭圆体模型轨迹规划
🚨 常见问题与解决方案
问题1:DDS配置问题
症状:节点无法发现彼此解决方案:设置正确的DDS配置环境变量
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp export FASTRTPS_DEFAULT_PROFILES_FILE=fastdds_config.xml问题2:QoS配置不匹配
症状:消息丢失或延迟解决方案:确保发布者和订阅者使用相同的QoS配置
auto qos = rclcpp::QoS(10) .reliable() .transient_local() .keep_last(10);问题3:参数类型转换
症状:参数获取失败解决方案:使用正确的类型转换方法
// ROS 1 double value; nh.param("param_name", value, 0.0); // ROS 2 this->declare_parameter<double>("param_name", 0.0); double value = this->get_parameter("param_name").as_double();🎯 迁移最佳实践
1. 增量迁移策略
- 从消息包开始迁移
- 逐个迁移功能包
- 保持ROS 1和ROS 2并行运行
2. 测试驱动迁移
- 为每个组件编写单元测试
- 使用ROS 2的测试框架
- 确保功能一致性
3. 性能优化
- 利用ROS 2的实时特性
- 优化QoS配置
- 使用组件化架构
4. 文档更新
- 更新README和文档
- 添加ROS 2示例
- 提供迁移指南
PathArray消息的类结构图
📈 性能对比与优化
通信性能提升
ROS 2的DDS通信机制相比ROS 1的TCPROS/UDPROS提供了更好的实时性和可靠性:
| 指标 | ROS 1 (Kinetic) | ROS 2 (Foxy) | 提升幅度 |
|---|---|---|---|
| 延迟 | 10-50ms | 2-10ms | 5倍 |
| 吞吐量 | 100MB/s | 500MB/s | 5倍 |
| 节点发现 | 秒级 | 毫秒级 | 100倍 |
内存使用优化
ROS 2的内存管理更加精细,通过以下方式优化:
- 零拷贝传输:减少消息复制开销
- 共享内存:节点间高效数据共享
- 内存池:预分配减少动态分配
🔮 未来展望
ROS 2 Humble兼容性
MPL_ROS迁移到ROS 2 Foxy后,可以进一步升级到更新的ROS 2版本:
- Humble Hawksbill:LTS版本,支持到2027年
- Iron Irwini:最新稳定版本
- Jazzy Jalisco:未来版本规划
新特性集成
迁移到ROS 2后,MPL_ROS可以集成更多现代特性:
- 生命周期管理:完善的节点状态机
- 安全特性:DDS安全层支持
- 实时性能:实时Linux支持
- 容器化部署:Docker/Kubernetes集成
🎉 总结
MPL_ROS从ROS Kinetic迁移到ROS 2 Foxy是一个系统性的工程,但通过本文提供的完整迁移方案,您可以:
- 理解架构差异:掌握ROS 1和ROS 2的核心区别
- 逐步迁移组件:从消息到节点,从构建到部署
- 解决常见问题:避免迁移过程中的常见陷阱
- 优化性能:充分利用ROS 2的新特性
迁移到ROS 2不仅能让MPL_ROS获得更好的性能和可靠性,还能为未来的机器人应用开发奠定坚实的基础。现在就开始您的ROS 2迁移之旅吧!✨
核心建议:采用渐进式迁移策略,保持ROS 1和ROS 2的兼容性,确保业务连续性。在迁移过程中,充分利用ROS 2的测试工具和性能分析工具,确保迁移质量。
MPL_ROS在办公室环境中的地图和规划示例
【免费下载链接】mpl_rosA ROS wrapper for trajectory planning based on motion primitives项目地址: https://gitcode.com/gh_mirrors/mp/mpl_ros
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考