# Thảo luận về Kiến trúc Navigation cho AMR ## Mục tiêu dự án Nghiên cứu và phát triển hệ thống navigation (di chuyển bám quỹ đạo) cho robot AMR dạng hai bánh vi sai, **không sử dụng ROS**, viết thuần C++ với CMake trên Linux. ## Yêu cầu chức năng Từ `readme.md`: - Có khả năng thay đổi mô hình kinematics (dạng hai bánh vi sai, dạng steering bicycle, ...) - Có chức năng di chuyển từ điểm khởi đầu đến điểm đích - Có chức năng xoay tròn - Có chức năng đi thẳng - Có chức năng thay đổi vận tốc ## Sơ đồ kiến trúc hệ thống Kiến trúc được thiết kế theo mô hình layered, tách biệt các concerns và cho phép mở rộng dễ dàng: ```mermaid flowchart TB %% ========== API LAYER ========== subgraph API["🌐 API Layer"] direction TB CAPI["📦 C API
━━━━━━━━━━━━━━━━
🔌 nav_c_api
💻 P/Invoke cho .NET/C#
📝 Wrapper Functions
🔗 Interop Layer"] style API fill:#E3F2FD,stroke:#1976D2,stroke-width:4px,color:#000 style CAPI fill:#BBDEFB,stroke:#1976D2,stroke-width:3px,font-size:14px end %% ========== USER CONTROLLER LAYER ========== subgraph UserController["🎮 User Controller Layer"] direction TB UserCtrl["🔌 User Controller Plugin
━━━━━━━━━━━━━━━━
📚 Dynamic Loader
⚙️ boost::dll
🎯 Custom Behavior
🔄 Runtime Loading"] style UserController fill:#F3E5F5,stroke:#7B1FA2,stroke-width:4px,color:#000 style UserCtrl fill:#E1BEE7,stroke:#7B1FA2,stroke-width:3px,font-size:14px end %% ========== INTERFACE LAYER ========== subgraph Interface["🔌 Interface Layer"] direction TB BaseNav["📋 BaseNavigation
━━━━━━━━━━━━━━━━
🏗️ move_base_core::BaseNavigation
🎯 Abstract Interface
━━━━━━━━━━━━━━━━
📍 moveTo, dockTo
🔄 rotateTo, moveStraightTo
⏸️ pause, resume, cancel
📊 getRobotPose"] style Interface fill:#FFF3E0,stroke:#E65100,stroke-width:4px,color:#000 style BaseNav fill:#FFE0B2,stroke:#E65100,stroke-width:3px,font-size:14px end %% ========== MOVE BASE CORE ========== subgraph MoveBaseCore["⚙️ Move Base Core"] direction TB MoveBase["🚀 MoveBase
━━━━━━━━━━━━━━━━
📦 move_base::MoveBase
🔄 State Machine
━━━━━━━━━━━━━━━━
📊 PLANNING
🎮 CONTROLLING
🧹 CLEARING
━━━━━━━━━━━━━━━━
🎛️ Control Loop
🔄 executeCycle"] style MoveBaseCore fill:#E8F5E9,stroke:#2E7D32,stroke-width:4px,color:#000 style MoveBase fill:#C8E6C9,stroke:#2E7D32,stroke-width:3px,font-size:14px end %% ========== PLANNING LAYER ========== subgraph Planning["🗺️ Planning Layer - Plugin System"] direction LR GP["🌍 Global Planner
━━━━━━━━━━━━━━━━
📋 nav_core::BaseGlobalPlanner
🔌 Dynamic Plugin
━━━━━━━━━━━━━━━━
🎯 A*, D*, Hybrid A*
📐 Long-range Planning
🗺️ Global Path"] LP["📍 Local Planner
━━━━━━━━━━━━━━━━
📋 nav_core::BaseLocalPlanner
🔌 Dynamic Plugin
━━━━━━━━━━━━━━━━
🎯 DWA, TEB, MKT
🚗 Velocity Commands
🛡️ Obstacle Avoidance"] RB["🔄 Recovery Behaviors
━━━━━━━━━━━━━━━━
📋 nav_core::RecoveryBehavior
🔌 Dynamic Plugin
━━━━━━━━━━━━━━━━
🧹 Clear Costmap
🔄 Rotate Recovery
🚨 Emergency Stop"] style Planning fill:#E1F5FE,stroke:#0277BD,stroke-width:4px,color:#000 style GP fill:#B3E5FC,stroke:#0277BD,stroke-width:3px,font-size:13px style LP fill:#B3E5FC,stroke:#0277BD,stroke-width:3px,font-size:13px style RB fill:#B3E5FC,stroke:#0277BD,stroke-width:3px,font-size:13px end %% ========== COSTMAP LAYER ========== subgraph Costmap["🗺️ Costmap Layer"] direction LR GC["🌍 Global Costmap
━━━━━━━━━━━━━━━━
📦 costmap_2d::Costmap2DROBOT
🌍 frame: map
━━━━━━━━━━━━━━━━
🗺️ Static Map
🚫 Obstacles
💰 Inflation Layer"] LC["📍 Local Costmap
━━━━━━━━━━━━━━━━
📦 costmap_2d::Costmap2DROBOT
📍 frame: odom
━━━━━━━━━━━━━━━━
🔍 Dynamic Obstacles
📡 Sensor Fusion
⚡ Real-time Updates"] style Costmap fill:#F1F8E9,stroke:#558B2F,stroke-width:4px,color:#000 style GC fill:#DCEDC8,stroke:#558B2F,stroke-width:3px,font-size:13px style LC fill:#DCEDC8,stroke:#558B2F,stroke-width:3px,font-size:13px end %% ========== ALGORITHMS LAYER ========== subgraph Algorithms["🧮 Algorithms Layer"] direction LR MKTAlgo["🚗 MKT Algorithm
━━━━━━━━━━━━━━━━
⚙️ Diff Drive Kinematics
🚲 Bicycle Kinematics
📐 Trajectory Generation"] ScoreAlgo["📊 Score Algorithm
━━━━━━━━━━━━━━━━
📈 Trajectory Scoring
✅ Goal Checking
🎯 Path Evaluation"] KalmanAlgo["🔍 Kalman Filter
━━━━━━━━━━━━━━━━
📊 State Estimation
🔮 Sensor Fusion
📉 Noise Filtering"] style Algorithms fill:#FCE4EC,stroke:#C2185B,stroke-width:4px,color:#000 style MKTAlgo fill:#F8BBD0,stroke:#C2185B,stroke-width:3px,font-size:13px style ScoreAlgo fill:#F8BBD0,stroke:#C2185B,stroke-width:3px,font-size:13px style KalmanAlgo fill:#F8BBD0,stroke:#C2185B,stroke-width:3px,font-size:13px end %% ========== DATA SOURCES ========== subgraph DataSources["📡 Data Sources"] direction TB Goal["🎯 Goal Input
━━━━━━━━━━━━━━━━
📍 geometry_msgs::PoseStamped
📨 move_base_simple/goal"] Loc["🌍 Localization
━━━━━━━━━━━━━━━━
📍 Pnkx Loc
🗺️ Global Pose
🔄 Pose Updates"] TF["🔄 Transform System
━━━━━━━━━━━━━━━━
📐 tf3::BufferCore
🌐 Coordinate Frames
⏱️ Time Synchronization"] Odom["🚗 Odometry
━━━━━━━━━━━━━━━━
📍 geometry_msgs::Odometry
⚡ Robot Velocity
📊 Position Tracking"] Laser["📡 Laser Sensors
━━━━━━━━━━━━━━━━
🔍 sensor_msgs::LaserScan
🚫 Obstacle Detection
📏 Distance Measurement"] Map["🗺️ Map Server
━━━━━━━━━━━━━━━━
📋 nav_msgs::OccupancyGrid
🏗️ Static Map
📐 Map Metadata"] style DataSources fill:#FFF9C4,stroke:#F57F17,stroke-width:4px,color:#000 style Goal fill:#FFF59D,stroke:#F57F17,stroke-width:3px,font-size:12px style Loc fill:#FFF59D,stroke:#F57F17,stroke-width:3px,font-size:12px style TF fill:#FFF59D,stroke:#F57F17,stroke-width:3px,font-size:12px style Odom fill:#FFF59D,stroke:#F57F17,stroke-width:3px,font-size:12px style Laser fill:#FFF59D,stroke:#F57F17,stroke-width:3px,font-size:12px style Map fill:#FFF59D,stroke:#F57F17,stroke-width:3px,font-size:12px end %% ========== CONTROL LOOP ========== subgraph ControlLoop["🔄 Control Loop"] direction LR CmdVel["⚡ Velocity Command
━━━━━━━━━━━━━━━━
📤 geometry_msgs::Twist
📨 cmd_vel
━━━━━━━━━━━━━━━━
➡️ Linear Velocity
🔄 Angular Velocity"] BaseCtrl["🎮 Base Controller
━━━━━━━━━━━━━━━━
🚗 diff_driver_controller
🚲 steer_drive_controller
━━━━━━━━━━━━━━━━
⚙️ Kinematics
🔧 Hardware Interface"] style ControlLoop fill:#FFEBEE,stroke:#C62828,stroke-width:4px,color:#000 style CmdVel fill:#FFCDD2,stroke:#C62828,stroke-width:3px,font-size:13px style BaseCtrl fill:#FFCDD2,stroke:#C62828,stroke-width:3px,font-size:13px end %% ========== CONNECTIONS ========== %% API to User Controller CAPI -->|"🔗 P/Invoke"| UserCtrl %% User Controller to Interface UserCtrl -->|"🎯 Uses"| BaseNav %% Interface to MoveBase BaseNav -->|"⚙️ Implements"| MoveBase %% MoveBase to Planning MoveBase -->|"🎛️ Manages"| GP MoveBase -->|"🎛️ Manages"| LP MoveBase -->|"🎛️ Manages"| RB %% MoveBase to Costmap MoveBase -->|"🎛️ Manages"| GC MoveBase -->|"🎛️ Manages"| LC %% Data Sources to Components Goal -->|"📥 Input"| UserCtrl Goal -->|"📥 Input"| BaseNav Loc -->|"📍 Pose"| MoveBase TF -->|"🔄 Transforms"| MoveBase Laser -->|"📡 Scan Data"| LC Map -->|"🗺️ Static Map"| GC Odom -->|"⚡ Velocity"| LP Odom -->|"📍 Pose"| MoveBase %% Planning Flow GC -->|"🗺️ Costmap"| GP GP -->|"🛤️ Global Path"| LP LC -->|"🗺️ Costmap"| LP LC -->|"🗺️ Costmap"| RB GC -->|"🗺️ Costmap"| RB %% Algorithm Integration MKTAlgo -->|"🚗 Kinematics"| LP ScoreAlgo -->|"📊 Scoring"| LP KalmanAlgo -.->|"🔍 Filtering"| Loc %% Control Flow LP -->|"⚡ Velocity Cmd"| CmdVel CmdVel -->|"▶️ Execute"| BaseCtrl BaseCtrl -->|"📊 Feedback"| Odom %% Styling Classes classDef implemented fill:#C8E6C9,stroke:#2E7D32,stroke-width:4px,color:#000 classDef partial fill:#FFF9C4,stroke:#F57F17,stroke-width:3px,color:#000 classDef todo fill:#FFCDD2,stroke:#C62828,stroke-width:3px,color:#000 class BaseNav,MoveBase,GP,LP,RB,GC,LC,CAPI,MKTAlgo,ScoreAlgo,KalmanAlgo,UserCtrl implemented class BaseCtrl,Loc,Odom,Map,Laser,TF partial ``` ## Đề xuất giải pháp kiến trúc ### 1. Xác định phạm vi & yêu cầu vận hành Cần làm rõ: - **Kịch bản sử dụng chính**: go-to-goal trong môi trường indoor/outdoor? Tốc độ di chuyển? Độ chính xác yêu cầu? - **Cảm biến có sẵn**: encoder, IMU, lidar, camera? Dữ liệu nào đã có? - **Yêu cầu real-time**: chu kỳ điều khiển (control loop frequency), độ trễ tối đa cho phép? ### 2. Kiến trúc tổng thể **Các layer chính:** 1. **API Layer** ✅ - C API (`nav_c_api`) cho P/Invoke với .NET/C# - Wrapper functions cho tất cả BaseNavigation methods 2. **User Controller Layer** ✅ - **User Controller Plugin**: Dynamically allocated từ loader controller plugin - Sử dụng `boost::dll` để load plugins động - Cho phép user định nghĩa controller riêng để điều khiển navigation behavior - Kết nối với `BaseNavigation` interface 3. **Interface Layer** ✅ - `move_base_core::BaseNavigation`: Abstract interface cho navigation - Định nghĩa các operations: moveTo, dockTo, rotateTo, moveStraightTo, pause, resume, cancel - Là lớp trung gian định nghĩa các phương thức và thuộc tính liên quan đến navigation 4. **Move Base Core** ✅ - `move_base::MoveBase`: Core implementation của BaseNavigation - Quản lý state machine (PLANNING, CONTROLLING, CLEARING) - Điều phối global/local planner và recovery behaviors - Quản lý costmaps (global và local) - Thực thi control loop (executeCycle) 4. **Planning Layer** ✅ - `nav_core::BaseGlobalPlanner`: Interface cho global planners (A*, D*, etc.) - `nav_core::BaseLocalPlanner`: Interface cho local planners (DWA, TEB, MKT, etc.) - `nav_core::RecoveryBehavior`: Interface cho recovery behaviors - Plugin system sử dụng `boost::dll` để dynamic loading 5. **Costmap Layer** ✅ - `costmap_2d::Costmap2DROBOT`: Global và local costmap - Costmap layers: static map, obstacles, inflation - Frame management: map (global), odom (local) 6. **Algorithms Layer** ✅ - `mkt_algorithm`: Diff drive và bicycle kinematics algorithms - `score_algorithm`: Trajectory scoring và goal checking - `kalman`: Filtering algorithms 7. **Data Sources** ⚠️ (Interface cần định nghĩa) - Localization source (Pnkx Loc) - Odometry source - Sensor transforms (tf3) - Map server - Laser sensors 8. **Control Layer** ⚠️ (Cần implementation) - Base Controller interface (Diff/Steer drive) - Velocity command execution **Định dạng dữ liệu:** - `geometry_msgs::Pose2D` / `geometry_msgs::PoseStamped` (vị trí + hướng) - `geometry_msgs::Twist` (vận tốc linear/angular) - `std::vector` (đường đi) - `costmap_2d::Costmap2D` (bản đồ chi phí) ### 3. Thiết kế từng module (interface level) **Các interface đã có:** ✅ - `move_base_core::BaseNavigation` ✅ - `initialize(TFListenerPtr)` - Khởi tạo với TF listener - `moveTo(goal, xy_tol, yaw_tol)` - Di chuyển đến goal - `dockTo(marker, goal, ...)` - Docking đến marker - `rotateTo(goal, yaw_tol)` - Xoay tại chỗ - `moveStraightTo(goal, xy_tol)` - Đi thẳng - `pause()`, `resume()`, `cancel()` - Điều khiển trạng thái - `getRobotPose(...)` - Lấy vị trí robot - `nav_core::BaseGlobalPlanner` ✅ - `makePlan(start, goal, plan)` - Tạo global path - `initialize(name, costmap_robot)` - Khởi tạo với costmap - `nav_core::BaseLocalPlanner` ✅ - `computeVelocityCommands(cmd_vel)` - Tính toán velocity command - `setPlan(plan)` - Set global path để follow - `isGoalReached()` - Kiểm tra đã đến goal chưa - `swapPlanner(name)` - Thay đổi planner động - `setTwistLinear/Angular(...)` - Set velocity limits - `nav_core::RecoveryBehavior` ✅ - `runBehavior()` - Thực thi recovery behavior - `costmap_2d::Costmap2DROBOT` ✅ - Wrapper cho costmap với robot footprint - Thread-safe access với mutex **Các interface cần bổ sung:** ⚠️ - `ILocalizationSource` ⚠️ - `getCurrentPose()` - Lấy vị trí hiện tại từ localization - `isAvailable()` - Kiểm tra localization có sẵn không - `IOdometrySource` ⚠️ - `getCurrentPose()` - Lấy vị trí từ odometry - `getCurrentVelocity()` - Lấy vận tốc hiện tại - `isAvailable()` - Kiểm tra odometry có sẵn không - `IBaseController` ⚠️ - `executeVelocity(cmd_vel)` - Thực thi velocity command - `stop()` - Dừng robot ngay lập tức - `getCurrentVelocity()` - Lấy vận tốc thực tế - `IMapProvider` ⚠️ - `getMap()` - Lấy static map - `isMapAvailable()` - Kiểm tra map có sẵn không **Plugin mechanism:** ✅ - Sử dụng `boost::dll` để dynamic loading plugins - Factory pattern với `boost::function` và `boost::dll::import` - Config file YAML để specify plugin names - Plugin interfaces: `BaseGlobalPlanner`, `BaseLocalPlanner`, `RecoveryBehavior` ### 4. Cơ chế giao tiếp & đồng bộ **Lựa chọn transport:** - Shared memory + mutex (cho real-time nhẹ) - Message queue (ZeroMQ, nanomsg) - Event loop với callback thread-safe **Time synchronization:** - Sử dụng `std::chrono` cho timestamp - Buffer dữ liệu để xử lý dữ liệu không đồng bộ **Threading strategy:** - Mỗi module một thread riêng, hoặc - Scheduler chung quản lý tất cả ### 5. Chiến lược an toàn & recovery **Monitoring:** - Heartbeat mechanism - Watchdog timer **Recovery behaviors:** - Không tìm được đường đi - Mất localization - Obstacle chặn đường - Emergency stop mechanism - Giới hạn vận tốc theo trạng thái ### 6. Config & Logging/Diagnostics **Configuration:** - File YAML/JSON cho: - Kinematics parameters - Velocity limits - Planner parameters - Sensor configurations **Logging & Debugging:** - Logging framework (spdlog?) - Telemetry interface - Visualizer tool (SDL/ImGui) để debug map/path ### 7. Trạng thái triển khai & lộ trình **Đã hoàn thành:** ✅ 1. ✅ **Interface Layer**: `BaseNavigation` interface 2. ✅ **Implementation Layer**: `MoveBase` core logic 3. ✅ **Planning Layer**: Plugin system cho global/local planners và recovery 4. ✅ **Costmap Layer**: Global và local costmap với layers 5. ✅ **Algorithms Layer**: MKT algorithms, score algorithm, kalman 6. ✅ **API Layer**: C API wrapper cho .NET integration 7. ✅ **Supporting Libraries**: tf3, robot_time, geometry_msgs, nav_2d_utils **Đang triển khai / Cần bổ sung:** ⚠️ 1. ⚠️ **Data Sources Interfaces**: - `ILocalizationSource` interface - `IOdometrySource` interface - `IMapProvider` interface - Integration với Pnkx Loc, odometry sources 2. ⚠️ **Base Controller**: - `IBaseController` interface - Diff drive controller implementation - Steer drive controller implementation - Velocity command execution 3. ⚠️ **Control Loop**: - Control loop trong MoveBase (executeCycle) - State machine management hoàn chỉnh - Threading và synchronization 4. ⚠️ **User Controller Plugin System**: - Factory để load user controller plugins - Integration với BaseNavigation **Lộ trình tiếp theo:** **Phase 1: Data Sources & Base Controller** (Ưu tiên cao) - Định nghĩa interfaces cho data sources - Implement Base Controller interface và diff drive controller - Integration với MoveBase **Phase 2: Control Loop & State Management** (Ưu tiên cao) - Hoàn thiện executeCycle trong MoveBase - State machine management - Threading strategy **Phase 3: User Controller Plugin System** (Ưu tiên trung bình) - Factory pattern cho user controllers - Plugin loading mechanism - Integration testing **Phase 4: Testing & Optimization** (Ưu tiên trung bình) - Unit tests cho các module - Integration tests - Performance optimization **Testing strategy:** - Unit tests cho các module độc lập (gtest?) - Integration tests cho full navigation stack - Simulation environment (2D simulator) - TODO - Hardware-in-the-loop testing - TODO ## Cấu trúc thư mục ``` pnkx_nav_core/ ├── src/ │ ├── Navigations/ │ │ ├── Cores/ │ │ │ ├── move_base_core/ # BaseNavigation interface │ │ │ ├── nav_core/ # Planner interfaces │ │ │ ├── nav_core_adapter/ # Adapter utilities │ │ │ └── nav_core2/ # Additional nav utilities │ │ ├── Libraries/ │ │ │ ├── costmap_2d/ # Costmap system │ │ │ ├── tf3/ # Transform system │ │ │ ├── robot_time/ # Time management │ │ │ ├── geometry2/ # Geometry utilities │ │ │ └── ... # Other supporting libraries │ │ └── Packages/ │ │ └── move_base/ # MoveBase implementation │ ├── Algorithms/ │ │ ├── Cores/ │ │ │ └── score_algorithm/ # Trajectory scoring │ │ └── Libraries/ │ │ ├── mkt_algorithm/ # MKT kinematics algorithms │ │ ├── kalman/ # Kalman filtering │ │ └── angles/ # Angle utilities │ └── APIs/ │ └── c_api/ # C API wrapper ├── build/ # Build artifacts └── doc/ # Documentation ``` ## Ghi chú - ✅ Kiến trúc cốt lõi đã được triển khai với plugin system linh hoạt - ⚠️ Cần bổ sung data sources interfaces và base controller - 🔄 Kiến trúc được thiết kế để dễ dàng thay đổi thuật toán và mô hình kinematics thông qua plugin system - 📦 Tất cả components được build bằng CMake, không phụ thuộc ROS - 🔌 Plugin system sử dụng `boost::dll` cho dynamic loading