move_base2: kiến trúc, C API và tương thích

Phân tích theo mã nguồn và log chạy của T800 · 03/08/2026

Kết luận ngắn. Khung chương trình T800 đang nạp move_base qua interface robot::move_base_core::BaseNavigation và factory alias "MoveBase" có thể chạy move_base2 mà không phải sửa host, nếu đổi đúng thư viện và cây cấu hình runtime. Điều này đúng cho khung T800 hiện tại; không phải quy tắc tự động đúng cho mọi ứng dụng ROS dùng package move_base.

1. Khung đang khởi tạo những gì?

Log cho thấy chỉ có một node ROS là /amr_node cho phần điều khiển. Bên trong process đó, amr_control nạp động navigation runtime và các plugin. Global planner, local planner, action, recovery và mission adapter không là node ROS riêng.

roslaunch → /amr_node (amr_control) → BaseNavigation factory → NavigationServer (move_base2)
→ costmap global/local + runners + mission/action/recovery plugins
Thành phầnThời điểm / cách tạoVai trò quan sát được
amr_controlNode /amr_node; tạo TF, localization, sensor converter, publisher/subscriber rồi nạp navigation.Cầu nối ROS/MQTT/OPC-UA với lõi navigation.
NavigationServerFactory của libmove_base2.so trả về BaseNavigation::Ptr.Vỏ tương thích BaseNavigation; quản lý runtime và control thread 30 Hz.
Global/local costmapTạo khi NavigationRuntime::buildCostmaps() chạy.Global dùng frame map; local dùng odom; nhận laser, cloud, depth qua SensorGateway.
PlannerRunnerNạp CustomPlanner lúc boot; nạp SBPLLatticePlanner, DockPlanner khi profile cần.Lập global plan, cache instance theo tên planner.
ControllerRunnerNạp HybridLocalPlanner lúc boot; có thể đổi theo profile.Biến plan thành lệnh vận tốc.
RecoveryRunnerNạp lúc boot từ namespace recovery.Trong log: wait, clear-costmap (2 mức), rotate, back-up.
ActionRunnerNạp lúc boot từ namespace actions.Trong log: detect, wait, report, sim_noop.
Mission layerNạp source adapter lúc boot từ mission_adapters.GoalSourceAdapter nhận goal; VDA5050SourceAdapter tách order thành các leg/nav/action.

Luồng một VDA5050 order

  1. MQTT nhận topic order.
  2. VDA5050SourceAdapter đổi order thành các mission leg: navigation hoặc action-only.
  3. MissionManager đưa leg vào hàng đợi; MissionExecutor chạy tuần tự.
  4. Control loop chọn profile: position, docking, go_straight hoặc rotate; runner lấy planner/local planner phù hợp.
  5. Kết quả nav/action trả về mission layer, rồi trạng thái VDA5050.

2. C API đang dùng gì và có dùng được move_base2 không?

C API nằm tại pnkx_nav_core/src/APIs/c_api. Nó không tạo trực tiếp lớp C++ move_base::MoveBase hay move_base2::NavigationServer. Hàm navigation_create() làm đúng chuỗi sau:

PluginLoaderHelper::findLibraryPath("MoveBase")
boost::dll::import_alias<BaseNavigation::Ptr()>(path, "MoveBase")
factory()  -> NavigationHandle

libmove_base2.so export cả hai alias MoveBase2MoveBase, C API sẽ nhận được một NavigationServer của move_base2 khi cấu hình MoveBase trỏ đến libmove_base2. C API phía gọi không cần đổi tên hàm.

Nhóm C APIVí dụKhi dùng move_base2
Vòng đờinavigation_create, navigation_initialize, navigation_destroyDùng được qua interface chung. Nên bảo đảm host gọi shutdown() ở đường C++ trước khi dỡ process/plugin.
Lệnh điều hướngnavigation_move_to, navigation_move_to_order, navigation_dock_to, pause/resume/cancelDùng được. Order/docking được move_base2 đưa vào mission/profile tương ứng.
Sensor và mapnavigation_add_static_map, navigation_add_laser_scan, navigation_add_point_cloud2, odometryDùng được; tên nguồn phải khớp source trong costmap YAML, ví dụ pc_r_marking.
Quan sátnavigation_get_feedback, pose/twist, global/local planner dataDùng được cho trạng thái BaseNavigation. Không tự lộ API chi tiết của MissionManager hay ActionRunner.
Lưu ý kỹ thuật C API: đây là ABI C-linkage (hàm dùng extern "C"), nhưng header hiện có một số tham số tham chiếu C++ như PoseStamped &out_posesize_t &out_count. Vì vậy nó chưa là header ISO C thuần để biên dịch trực tiếp bằng C compiler. Điều này không cản trở việc chọn move_base2, nhưng nếu caller là C thuần thì cần đổi các output reference thành pointer trước khi coi API là C API hoàn chỉnh.

3. move_base2 khác move_base ở đâu?

Chủ đềmove_base cũ trong T800move_base2
Ranh giới với hostBaseNavigation, plugin được nạp qua alias MoveBase.Giữ cùng interface và xuất alias tương thích MoveBase; thêm alias rõ ràng MoveBase2.
Tổ chức runtimeĐiều phối kiểu đơn khối hơn.Tách NavigationRuntime, ControlLoop, PlannerRunner, ControllerRunner, RecoveryRunner, ActionRunner và MissionLayer.
Nhiệm vụ / orderHost hoặc lớp ngoài thường phải tự điều phối nhiều bước.Mission layer có adapter nguồn và executor; VDA5050 order được tách thành leg, action-only leg chạy qua ActionRunner.
ProfileThường chỉ một bộ planner/controller cho một kiểu goal.Profile position, docking, go_straight, rotate; docking có marker profile. Planner/local planner có thể chuyển theo mission.
FallbackPhụ thuộc implementation cũ.Log chứng minh: khi CustomPlanner không hỗ trợ request đơn giản, runtime chuyển một lần sang SBPLLatticePlanner.
SafetyTùy implementation.Có điều kiện require_current_costmap; sensor stale sẽ chặn wheel command để không điều khiển theo thế giới cũ.
Local planner pluginKhông nên giả định plugin cũ có cùng ABI.Dùng contract robot_nav_core2::LocalPlanner; local planner cũ chỉ dùng lại khi đã xác nhận cùng interface/ABI hoặc có adapter.
Đừng nhầm hai mức tương thích. Host/API BaseNavigation tương thích là một việc. Plugin local planner, YAML, và hành vi mission/profile tương thích là các việc khác. Việc đổi thư viện thành công không chứng minh tất cả planner cũ sẽ chạy được trong move_base2.

4. Một khung đang dùng move_base có chạy move_base2 luôn không?

Câu trả lời: có điều kiện. Với amr_control của T800 thì câu trả lời là có, theo đúng cơ chế đã được thiết kế. Với một khung ROS bất kỳ đang dùng package ROS1 move_base, câu trả lời là không thể kết luận là có nếu chưa kiểm tra interface.

Loại khung hiện cóKhả năng chuyểnLý do / việc cần làm
T800 host nạp BaseNavigation::Ptr từ alias MoveBaseCaomove_base2 export alias tương thích. Đặt đúng library/config, rồi kiểm thử runtime.
Ứng dụng gọi C API navigation_create()CaoC API cũng tìm MoveBase; config quyết định .so được nạp. Cần cùng ABI của move_base_core.
Ứng dụng liên kết trực tiếp class/private header của move_base cũThấpPhải sửa và build lại theo interface công khai hoặc làm adapter; không nên thay .so mù quáng.
ROS1 chuẩn dùng action move_base_msgs/MoveBaseAction và pluginlib/nav_coreChưa khẳng địnhĐây không phải tự động là contract T800 BaseNavigation; cần kiểm tra node/action/topic/plugin ABI cụ thể.

Điều kiện bắt buộc để chuyển khung T800

  1. Chung ABI: host, libmove_base2.somove_base_core phải được build từ cùng workspace/devel hoặc ABI tương thích.
  2. Đúng alias: library phải export factory BaseNavigation::Ptr() dưới tên MoveBase. move_base2 hiện đã có alias này.
  3. Đúng config: PNKX_NAV_CORE_CONFIG_DIR phải trỏ đến move_base2/config/runtime; file move_base_common_params.yaml cần có MoveBase: library_path: libmove_base2.
  4. Đủ plugin: global planner/local planner/recovery/action/mission adapter được khai trong YAML phải có .so, alias factory và dependency đúng.
  5. Đúng sensor contract: map, TF, odom, laser/cloud/depth được bơm bằng đúng topic-key và tần số. Với require_current_costmap: true, sensor stale sẽ chặn lệnh bánh xe.
  6. Shutdown rõ ràng: dừng navigation trước khi destroy loader/process để tránh race thread/plugin.

Cách chuyển an toàn trong launch của T800

<!-- move_base2_control.launch đã làm hai việc quan trọng -->
<env name="PNKX_NAV_CORE_CONFIG_DIR"
     value="$(find move_base2)/config/runtime" />

# config/runtime/move_base_common_params.yaml
MoveBase:
  library_path: libmove_base2

Không đổi trực tiếp link library trong amr_control. Nó tiếp tục nạp factory "MoveBase"; file cấu hình chọn implementation là move_base2.

5. Checklist test trước khi thay cho hệ chạy dài

  1. Build: xác nhận có devel/lib/libmove_base2.so và các plugin runtime.
  2. Boot: log phải có Found library ... libmove_base2.so, NavigationRuntime built, costmap và sensor source tạo thành công.
  3. Goal đơn: position, cancel/preempt, pause/resume; xác nhận cmd_vel và feedback.
  4. Order: VDA5050 order có nhiều node/edge, action wait/detect/charge và docking marker.
  5. Fallback/recovery: tạo tình huống CustomPlanner fail, obstacle/stale sensor có kiểm soát; xác nhận fallback/recovery và robot dừng an toàn.
  6. Soak test: chạy 8 giờ, theo dõi CPU/RAM, tần số camera/cloud, message queue Gazebo, reconnect MQTT và tần suất sensor stale.

6. Liên hệ với cảnh báo qua đêm trong log

Cảnh báo /gazebo/default/pose/local/info là hàng đợi của Gazebo Transport đầy ở publisher đó; Gazebo bỏ một message để queue không tăng vô hạn. Nó không chứng minh C API hay move_base2 bị lỗi. Tuy vậy, nó là dấu hiệu nên theo dõi tải mô phỏng/consumer. Cảnh báo ảnh hưởng an toàn hơn trong log là:

/camera_right/depth/points_proc observation buffer has not been updated ...
[move_base2] Sensor data is stale — wheel commands blocked

move_base2 đang dừng lệnh bánh xe đúng chủ đích vì local/global costmap không còn mô tả thế giới hiện tại. Cần chẩn đoán đường camera phải/DepthCameraData, callback SensorConverter và tần số thực tế; không quy kết ngay cho nghẽn mạng.

7. Dấu vết mã nguồn dùng để kết luận