這是一個重大的專案轉移,因為 ROS 2 在底層架構上與 ROS 1 有很大的不同 (例如使用 DDS 作為傳輸層,以及構建系統從 Catkin 轉為 Ament/Colcon)。
以下是將 ROS 1 Noetic 專案轉移到 ROS 2 Humble 的關鍵步驟和注意事項:
🏗️ I. 概念性差異與準備工作
在開始修改程式碼之前,必須理解 ROS 1 和 ROS 2 之間的幾個核心差異:
Build System (建構系統): 從 Catkin 轉為 Ament (使用 Colcon 作為建構工具)。
Client Libraries (客戶端函式庫):
ROS 1 C++:
roscpp$\rightarrow$ ROS 2 C++:rclcppROS 1 Python:
rospy$\rightarrow$ ROS 2 Python:rclpy
Launch Files (啟動檔案): 從 XML/Python 腳本轉為強制使用 ROS 2 Python Launch System。
Parameters (參數系統): 從集中的參數伺服器 (Parameter Server) 轉為分散式的參數服務/客戶端 (Parameter Service/Client)。
Python 版本: ROS 1 Noetic 支援 Python 3,但 ROS 2 Humble 強制使用 Python 3。
資料包頭 (
Header): ROS 2 的std_msgs/msg/Header結構有所改變,不再有seq欄位。
🛠️ II. 實際專案轉移步驟
1. 轉換建構系統 (Catkin $\rightarrow$ Ament/Colcon)
A. package.xml 調整
格式版本: 將
<package format="2">升級為 <package format="3">。Build Tool: 替換 ROS 1 的
buildtool_depend:移除
<buildtool_depend>catkin</buildtool_depend>新增 <buildtool_depend>ament_cmake</buildtool_depend> (適用於 C++ Packages) 或使用
setup.py(適用於 Python Packages)。
依賴項 (Dependencies): 將所有
*_depend替換為 ROS 2 的對應套件名稱 (例如:tf$\rightarrow$tf2_ros,message_runtime$\rightarrow$rosidl_runtime_cpp等)。
B. CMakeLists.txt 調整 (C++ Packages)
這是最需要修改的部分:
替換函式: 替換 Catkin 相關的函式為 Ament 函式,例如:
find_package(catkin ...)$\rightarrow$find_package(rclcpp REQUIRED)和其他 ROS 2 套件。catkin_package(...)$\rightarrow$ament_package()。使用
ament_target_dependencies(...)來連結程式庫。
安裝指令: 使用
install(TARGETS ...)和install(DIRECTORY ...)搭配ament_cmake_index和ament_export_targets進行安裝。
2. 轉換程式碼 (C++ / Python)
A. Node 初始化
將 ROS 1 的 Node 啟動模式替換為 ROS 2 的 Node 類別:
ROS 1 (C++):
C++ros::init(argc, argv, "my_node"); ros::NodeHandle nh; // ... ros::spin();ROS 2 (C++):
C++#include <rclcpp/rclcpp.hpp> int main(int argc, char * argv[]) { rclcpp::init(argc, argv); auto node = std::make_shared<rclcpp::Node>("my_node"); rclcpp::spin(node); rclcpp::shutdown(); return 0; } // 或是建議繼承 rclcpp::Node 類別來自定義 Node
B. Publisher/Subscriber
替換函式庫: 替換
#include <ros/ros.h>等為rclcpp/rclcpp.hpp或rclpy相關。創建物件: ROS 2 的 Publisher 和 Subscriber 必須從 Node 物件創建。
ROS 1:
ros::Publisher pub = nh.advertise<std_msgs::String>("topic", 10);ROS 2:
auto pub = node->create_publisher<std_msgs::msg::String>("topic", 10);(使用std_msgs::msg::String)
Callback 函式: 在 C++ 中,
boost::bind通常被 C++ 標準函式庫的std::bind替換。
C. 參數處理
將參數從 ROS 1 的全域參數伺服器,轉移到 ROS 2 的 Node 專屬參數服務。
ROS 1:
nh.getParam("param_name", value);ROS 2: 需要先在 Node 中宣告參數,然後透過
node->get_parameter("param_name", value)或使用參數客戶端ParameterClient來獲取。
3. 轉換 Launch 檔案
將 ROS 1 的 XML 或舊版 Python Launch 檔案,完全重寫為 ROS 2 Python Launch System 檔案 (.launch.py)。
核心模組: 主要使用
launch和launch_ros.actions.Node。基本結構:
Pythonfrom launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node( package='my_pkg', executable='my_node', name='my_node_name', parameters=[{'param_key': 'param_value'}] ), # ... 其他 Nodes ])
🌉 III. 過渡時期工具:ros1_bridge
如果你無法一次性將所有套件都轉移,可以使用 ros1_bridge 作為一個過渡方案。
功能:
ros1_bridge允許 ROS 1 和 ROS 2 之間的消息進行轉換,讓 ROS 1 節點和 ROS 2 節點能夠互相通訊。使用時機: 在大型專案中,當部分組件已經轉移到 ROS 2,而其他組件仍然在 ROS 1 上執行時,這是非常有用的。
💡 總結
整個轉移過程涉及對 ROS 2 的架構、建構系統和 API 進行深入了解。建議參考
您目前專案中,最主要的程式碼是用 C++ 還是 Python 撰寫的? 我可以提供更具體的程式碼轉換範例。
沒有留言:
張貼留言