Files
recovery_core/docs/SAFETY.md
2026-08-03 22:32:40 +07:00

4.5 KiB

An toàn — recovery_core

Đọc trước khi viết plugin họ vận tốc. Recovery chạy đúng lúc robot đã ở tình huống xấu, nên default ở đây phải fail-safe chứ không fail-open.

Base bảo đảm

Những điều dưới đây đúng kể cả khi plugin viết ẩu — base cưỡng chế, không phụ thuộc plugin nhớ.

Bất biến Cơ chế
Họ velocity không chạy được nếu thiếu pose hoặc collision checker configure() trả false khi ctx.pose/ctx.collision null
dt là thời gian thật, không phải chu kỳ cấu hình update(now) tính now - lần trước; đồng hồ đi lùi → dt = 0
elapsed luôn có mặt trên mọi kết quả Base ghi, plugin không phải đặt
Recovery không treo vô hạn Param timeout [s]; quá hạn → kFailed + stop output
output_type luôn thuộc {outputKind(), kNone} Sai họ → hạ về kNone, xoá dữ liệu, log lỗi
NaN/Inf không ra được cmd_vel Lệnh không hữu hạn → Twist 0 + kFailed
Guard vòng đời không cần plugin tự làm start trước configure, update trước startkFailed + stop output
Stop output đúng họ Họ velocity nhận Twist 0 tường minh; họ khác nhận kNone

Base KHÔNG bảo đảm

  • Không thay caller quyết định có nên recovery hay không. Ngữ cảnh cho phép recovery (đã dừng planner, không đang ở chế độ thủ công, không đang estop) là việc của caller.
  • Không quản lý nhịp gọi. Caller phải tick đúng chu kỳ control và publish lệnh.
  • Không là hàng rào vận tốc cuối cùng. Plugin clamp theo giới hạn của mình; VelocityArbiter phía ngoài vẫn phải clamp lần cuối. Hai tầng, không chồng nhau: plugin lập kế hoạch dừng/ramp, arbiter chặn giá trị vượt ngưỡng.

Quy tắc cho plugin họ vận tốc

  1. Không tích phân vận tốc lệnh để đo tiến độ. Dùng PoseProvider và hình chiếu delta pose (recovery_core::projectOntoHeading). Tích phân lệnh thì bánh trượt hay robot bị chặn vẫn báo đi đủ quãng — và đó là lúc nguy hiểm nhất để nói dối.
  2. Kiểm va chạm trên pose dự đoán, trước khi phát lệnh. Không phải sau. BackUpRecovery dò pose ở cuối chu kỳ tới; RotateRecovery quét toàn bộ cung ngay tại onStart() và refuse khởi động nếu có bất kỳ góc nào bị chặn.
  3. Mất pose là dừng. getRobotPose() trả false → trả kFailed + Twist 0. Không dùng pose cũ.
  4. Ramp theo acc_lim_*. Tick đầu không được nhảy thẳng lên tốc độ tối đa; onCancel() cũng nên giảm tốc thay vì nhảy bậc.
  5. Clamp mọi param có dải. angle ∈ [-2π, 2π], distance ∈ (0, *_max], tốc độ ≤ trần. Param sai thì log cảnh báo kèm giá trị rồi dùng default — không im lặng.
  6. Ghi rõ dấu. linear.x < 0 là lùi; angular.z > 0 là ngược chiều kim đồng hồ. Param cấu hình là độ lớn, dấu do plugin đặt theo ngữ cảnh.

Quy tắc chung cho mọi plugin

  • onUpdate() chạy trên thread phát cmd_vel. Không block quá một phần nhỏ chu kỳ control: không parse file, không cấp phát lớn, không gọi việc nặng của costmap (ClearCostmapRecovery cố ý không gọi updateMap() vì lý do này).
  • Không cache Costmap2D* qua các tick. Con trỏ có thể bị thay giữa hai cycle; lấy lại mỗi lần dùng.
  • Kiểm mã trả về của CollisionChecker bằng < 0, không so với một giá trị âm cụ thể — các hiện thực trong workspace không thống nhất mã lỗi.
  • configure() trả false khi cấu hình không chạy được, thay vì log warning rồi chạy tiếp bằng default. Registry sẽ bỏ behavior đó và log đích danh.

Trách nhiệm của caller

  • Làm mới con trỏ costmap trong RecoveryContext trước mỗi start()/update().
  • Tick recovery từ đúng một thread — thread sở hữu cmd_vel. Thread riêng cho recovery nghĩa là hai bộ điều khiển cùng phát vận tốc.
  • Chỉ gọi update() sau khi start() trả true.
  • Sau cancel(), hoặc tick tiếp để nhận stop output, hoặc tự khoá nguồn vận tốc về 0.