optimal & fix file cmake
This commit is contained in:
@@ -1,46 +1,106 @@
|
||||
# Kiến Trúc recovery_core
|
||||
# Kiến trúc recovery_core
|
||||
|
||||
## Vị trí trong stack
|
||||
## Vị trí
|
||||
|
||||
`recovery_core` nằm ở tầng `Navigations/Libraries`, cạnh `robot_clear_costmap_recovery`. Nó
|
||||
giữ vai trò interface tương tự `robot_nav_core::RecoveryBehavior` cho các recovery cần **trả
|
||||
về output** (path/vận tốc), đồng thời vẫn dùng global path/costmap/tf như bản gốc.
|
||||
Gói nằm ở `Test/recovery_core`. Nó định nghĩa interface recovery **duy nhất** của workspace
|
||||
(`CLAUDE.md`); bản legacy `robot_nav_core::RecoveryBehavior` đã dừng phát triển và không được port
|
||||
sang.
|
||||
|
||||
## Các thành phần
|
||||
Consumer đầu tiên là `RecoveryRunner` của `move_base2` — nó include thẳng
|
||||
`recovery_core/recovery_behavior.h`, nên contract được compiler kiểm đầy đủ ở một nơi.
|
||||
|
||||
- `RecoveryBehavior` (interface, template-method): API non-virtual `configure`/`start`/`update`/
|
||||
`cancel`; plugin chỉ triển khai hook `onConfigure`/`onStart(goal)`/`onUpdate()`.
|
||||
- `RecoveryContext`: gói con trỏ ngữ cảnh (tf/costmap/global_path) truyền một lần qua `configure`.
|
||||
- `RecoveryGoal`: mục tiêu RUNTIME mỗi lượt (angle/distance/target_pose/params).
|
||||
- `RecoveryResult` / `RecoveryStatus` / `RecoveryOutputType`: hợp đồng output hợp nhất 3 họ +
|
||||
rich feedback (`progress`/`remaining`/`elapsed`/`message`), thêm trạng thái `kCancelled`.
|
||||
- Plugin mẫu:
|
||||
- `ClearCostmapRecovery`: clear layer costmap theo tên, one-shot no-output.
|
||||
- `RotateRecovery`: quay tới `goal.angle` (rad); sinh `Twist.angular.z` mỗi cycle.
|
||||
- `BackUpRecovery`: lùi tới `goal.distance` (m); sinh `Twist.linear.x < 0` mỗi cycle.
|
||||
- `RegenPathRecovery`: trả lại `robot_nav_msgs::Path` từ `global_path` hiện tại.
|
||||
## Vì sao tick-based
|
||||
|
||||
Recovery thế hệ trước chạy blocking bên trong một lời gọi và không trả gì. Hệ quả: không cancel
|
||||
được giữa chừng, không báo tiến độ, và **không phát được vận tốc** — nên mọi behavior cần robot cử
|
||||
động phải tự quay vòng lặp bên trong, tranh quyền phát `cmd_vel` với controller.
|
||||
|
||||
Bản này trả kết quả từng cycle. Ràng buộc kéo theo: recovery phải được tick từ **đúng thread đang
|
||||
sở hữu cmd_vel**, không được có thread riêng.
|
||||
|
||||
## Thành phần
|
||||
|
||||
| Thành phần | Vai trò |
|
||||
|---|---|
|
||||
| `RecoveryBehavior` | Base template-method. Giữ toàn bộ bất biến; plugin chỉ triển khai hook |
|
||||
| `RecoveryContext` | Các **cổng** môi trường: `PoseProvider`, `CollisionChecker`, `PlanProvider`, con trỏ costmap |
|
||||
| `RecoveryGoal` | Mục tiêu runtime mỗi lượt: `trigger`, `angle`, `distance`, `target_pose`, `params` |
|
||||
| `RecoveryResult` | Kết quả một tick: status, output theo họ, progress/remaining/elapsed/message |
|
||||
| `RecoveryRegistry` | Danh sách behavior **có thứ tự**, nạp từ YAML qua Boost.DLL |
|
||||
| `adapters/` | `CostmapPoseProvider`, `CostmapCollisionChecker` — nối cổng vào costmap thật |
|
||||
| `plugins/` | Bộ mặc định: wait, clear costmap, rotate, back up |
|
||||
|
||||
## Ai giữ bất biến gì
|
||||
|
||||
Đây là điểm khác quan trọng nhất so với bản trước, nơi state là `protected` và plugin ghi thẳng
|
||||
được vào `status_`.
|
||||
|
||||
**Base giữ:**
|
||||
|
||||
- guard vòng đời: `start` sau `configure`, `update` sau `start`, `configure` chỉ một lần;
|
||||
- cổng bắt buộc theo `outputKind()` — họ velocity không có `PoseProvider`/`CollisionChecker` thì
|
||||
`configure()` trả `false` ngay, chứ không để plugin phát hiện lúc đang lái;
|
||||
- validate goal (NaN/Inf, `distance > 0`) trước khi plugin nhìn thấy;
|
||||
- đo `dt` và `elapsed` bằng đồng hồ **thật**, ép `timeout`;
|
||||
- cưỡng chế `output_type ∈ {outputKind(), kNone}`;
|
||||
- chặn NaN/Inf trong lệnh vận tốc;
|
||||
- sinh **stop output đúng họ** ở mọi nhánh guard/cancel/timeout.
|
||||
|
||||
**Plugin giữ:** đọc param riêng, chốt mục tiêu lượt này, và sinh một tick an toàn. Toàn bộ state của
|
||||
base là `private`; plugin truy cập qua accessor `const`.
|
||||
|
||||
## Luồng runtime
|
||||
|
||||
```
|
||||
configure(name, ctx) // 1 lần: cache ctx, đọc config chung, onConfigure()
|
||||
configure(name, ctx, nh) # 1 lần. Kiểm cổng bắt buộc, đọc timeout, gọi onConfigure(nh).
|
||||
│
|
||||
start(goal) // mỗi lượt: chốt mục tiêu runtime, onStart()
|
||||
start(goal, now) # mỗi lượt. Validate goal, mốc thời gian, gọi onStart(goal) -> bool.
|
||||
│
|
||||
├── one-shot (họ A/B): update() 1 lần ───────────► RecoveryResult{status, path|none, msg}
|
||||
├── kNone : update() -> làm việc / đếm giờ ─────► {status, elapsed, message}
|
||||
├── kVelocity : loop { update(now) } ───────────────► {status, Twist, progress, remaining}
|
||||
└── kPath : update() -> sinh path ──────────────► {status, Path}
|
||||
│
|
||||
└── per-cycle (họ C): loop { update() } ────────► RecoveryResult{status, velocity,
|
||||
(tới khi status != kRunning) progress, remaining}
|
||||
cancel() # tick kế tiếp gọi onCancel() -> stop output + kCancelled.
|
||||
```
|
||||
|
||||
## Ghi chú thiết kế
|
||||
## Quyết định thiết kế
|
||||
|
||||
- Template-method: base xử lý guard vòng đời (configure→start→update) và `cancel` một chỗ;
|
||||
plugin không lặp lại các guard này.
|
||||
- Mục tiêu là RUNTIME qua `RecoveryGoal` (không cố định trong config): cùng plugin phục vụ nhiều
|
||||
yêu cầu góc/khoảng khác nhau. Field = 0 → dùng default plugin đọc ở `onConfigure()`.
|
||||
- `onUpdate()` lấy pose robot từ costmap/tf bên trong; không truyền pose qua tham số.
|
||||
- Sau `cancel()`, base tự trả stop output (Twist 0) + `kCancelled`.
|
||||
- Param RIÊNG của plugin đọc trong `onConfigure()`.
|
||||
- Interface KHÔNG include Boost.DLL; export/import là việc của plugin/loader.
|
||||
- Plugin mẫu có dùng Boost.DLL alias, nhưng core contract vẫn không biết loader/adaptor.
|
||||
**Cổng, không phải dữ liệu, nằm trong context.** `PlanProvider` là accessor chứ không phải con trỏ
|
||||
tới `std::vector` vì runtime dùng triple-buffer plan và **xoay con trỏ** giữa ba bộ đệm — một con
|
||||
trỏ cache lúc `configure()` sẽ trỏ vào bộ đệm scratch sau vài chu kỳ planner. Cùng lý do đó, con trỏ
|
||||
costmap phải được caller làm mới trước mỗi lượt và plugin không được cache `Costmap2D*` bên trong.
|
||||
|
||||
**`std::optional` thay cho sentinel 0.** `goal.angle = 0` là yêu cầu hợp lệ ("đừng quay") và phải
|
||||
phân biệt được với "caller không đặt". Quy ước cũ "0 nghĩa là dùng default" khiến một góc tính từ
|
||||
hình học ra ~0 bị âm thầm thay bằng π/2.
|
||||
|
||||
**Họ output nằm trong kiểu.** `outputKind()` khai một lần và base cưỡng chế. Trước kia mỗi kết quả
|
||||
tự mang `output_type` nên nó không dùng để route được: một behavior họ path báo `kVelocity` ở tick
|
||||
đầu, còn base thì sinh `Velocity(zero)` cho mọi họ ở nhánh terminal.
|
||||
|
||||
**Param do caller cấp namespace.** `configure()` nhận `robot::NodeHandle&` đã scope sẵn; plugin
|
||||
không tự dựng `NodeHandle("~/" + name)` và tự nạp YAML từ disk. Nhờ vậy test chỉ cần trỏ vào cây
|
||||
config của mình, không phải dựng cây config production.
|
||||
|
||||
**Không có `RecoveryDirective`.** Từng cân nhắc thêm kênh "xin lập plan lại", nhưng state machine
|
||||
của `move_base2` đã chuyển `RECOVERING → PLANNING` với `start_planner = true` trên **cả**
|
||||
`kSucceeded` lẫn `kFailed` — replan sau recovery đã là hành vi mặc định, thêm kênh riêng là thêm thứ
|
||||
không ai đọc.
|
||||
|
||||
**`kCancelled` không qua ranh giới port.** `move_base2` không tick recovery sau khi cancel (state
|
||||
chuyển sang `CANCELLING`, nơi mọi nguồn vận tốc bị khoá). Đường `onCancel()` vẫn phải đúng vì nó là
|
||||
hàng rào cho host khác, nhưng `RecoveryTick` của `move_base2` không cần giá trị tương ứng.
|
||||
|
||||
## Điều kiện đóng lại phần legacy
|
||||
|
||||
`robot_nav_core::RecoveryBehavior` và `robot_clear_costmap_recovery` chỉ còn được tham chiếu ở hai
|
||||
nơi, và cả hai biến mất cùng lúc khi `move_base2` thay xong `move_base` cũ:
|
||||
|
||||
| Nơi | Xử lý |
|
||||
|---|---|
|
||||
| `move_base/src/move_base.cpp` (loader gen-1) | Bị `move_base2` thay, không sửa |
|
||||
| `robot_clear_costmap_recovery` | Bị `ClearCostmapRecovery` gen-2 thay, không port |
|
||||
|
||||
Khoá `recovery_behaviors:` trong `move_base_common_params.yaml` đã được gỡ: các entry cũ trỏ tên
|
||||
alias vào `.so` gen-2 trong khi loader ở đó import theo chữ ký gen-1, và Boost.DLL không kiểm kiểu
|
||||
qua ranh giới `.so`.
|
||||
|
||||
Reference in New Issue
Block a user