# Dock Planner Global planner tao duong di cho robot tiep can tram dock (tram sac, tram hang) bang duong cong NURBS. ## Cau truc thu muc ``` dock_planner/ ├── include/dock_planner/ │ ├── dock_planner.h # Lop DockPlanner - plugin interface │ ├── dock_calc.h # Lop DockCalc - logic tinh toan duong di │ └── utils/ │ ├── curve_common.h # Thu vien NURBS curve │ ├── pose.h # Chuyen doi pose/quaternion │ └── common.h # Tien ich chung ├── src/ │ ├── dock_planner.cpp # Khoi tao, load param, goi DockCalc │ ├── dock_calc.cpp # Thuat toan chinh: NURBS path generation │ └── utils/ │ ├── curve_common.cpp │ ├── line_common.cpp │ └── pose.cpp └── config/ └── dock_global_params.yaml # Tham so cau hinh ``` ## Pipeline tong quan ```mermaid flowchart TB subgraph INIT["1. KHOI TAO - DockPlanner::initialize"] I1["Lien ket costmap_robot"] --> I2["Load ROS params:
cost_threshold, calib_safety_distance"] I2 --> I3["Load footprint_dock
tu param server"] end subgraph PLAN["2. LAP KE HOACH - DockPlanner::makePlan"] P1["Lay footprint_robot
tu costmap"] --> P2["Goi DockCalc::makePlanMoveToDock"] P2 --> P3["Chuyen vector Pose
thanh vector PoseStamped"] end subgraph CALC["3. TINH TOAN - DockCalc::makePlanMoveToDock"] C1["Tinh RobotGeometry + safety_distance"] C2["Xac dinh huong tiep can
forward / backward"] C3["Tinh angle_threshold
heuristic"] C4["Tao duong tam NURBS
findPathTMP"] C5["Tim control points
segment 1"] C6["Sinh NURBS segment 1"] C7["Sinh NURBS segment 2"] C8["Ghep path: start + seg1 + seg2 + goal"] C1 --> C2 --> C3 --> C4 --> C5 --> C6 --> C7 --> C8 end INIT --> PLAN --> CALC ``` ## So do giai thuat chi tiet ### 1. Khoi tao (initialize) ```mermaid flowchart LR A["DockPlanner::initialize(name, costmap_robot)"] --> B{Da initialized?} B -- Co --> Z["return true"] B -- Chua --> C["Lien ket costmap_robot_
costmap_
frame_id_"] C --> D["getParam:
check_free_space
cost_threshold
calib_safety_distance"] D --> E["Copy params
sang DockCalc"] E --> F["footprintFromParams
→ footprint_dock_"] F --> G["initialized_ = true"] G --> Z ``` ### 2. Lap ke hoach (makePlan) ```mermaid flowchart TD A["makePlan(start, goal, plan)"] --> B{initialized_?} B -- false --> FAIL["return false"] B -- true --> C["footprint_robot =
costmap_robot_->getRobotFootprint()"] C --> D["makePlanMoveToDock
(start, goal, footprint_robot,
footprint_dock_, degree=2, step=0.02)"] D --> E{Thanh cong?} E -- false --> FAIL E -- true --> F["Chuyen moi Pose thanh PoseStamped
(gan timestamp, frame_id)"] F --> G["return true"] ``` ### 3. Thuat toan chinh (makePlanMoveToDock) ```mermaid flowchart TD START["makePlanMoveToDock(start, goal)"] --> GEOM subgraph GEOM["BUOC 1: Tinh hinh hoc"] G1["computeGeometry(footprint_robot)
→ robot.length, robot.radius"] G2["computeGeometry(footprint_dock)
→ dock.length"] G3["safety_distance =
(robot.radius + calib) * 2"] G1 --> G3 G2 --> G3 end GEOM --> VALID{robot.length > 0
AND safety > 0?} VALID -- false --> ERR["return false"] VALID -- true --> POSE_C subgraph POSE_C["BUOC 2: Tinh diem trung gian C"] PC1["distance_min_C =
(robot.length + dock.length) / 2"] PC2["yaw_goal = normalizeAngle(goal.yaw)"] PC3["Pose_C = offsetPoint(goal, yaw_goal, distance_min_C)"] PC1 --> PC3 PC2 --> PC3 end POSE_C --> DIR subgraph DIR["BUOC 3: Xac dinh huong di"] D1["t = compute_t(start, goal, Pose_C)"] D2{t < 0 ?} D3["Lat yaw_goal 180 do
Tinh lai Pose_C va t
dir = backward"] D4["dir = forward"] D1 --> D2 D2 -- Co --> D3 D2 -- Khong --> D4 end DIR --> T_CHECK{t > 1 ?} T_CHECK -- false --> ERR T_CHECK -- true --> ANGLE subgraph ANGLE["BUOC 4: Tinh angle threshold"] A1["Pose_D = compute_D(goal, Pose_C, t)"] A2["distance_AD =
pointToSegmentDistance(start, goal, Pose_C)"] A3["scale = f(distance_AD)
angle_threshold =
min((alpha+|scale|)*beta*pi, gamma*pi)"] A1 --> A3 A2 --> A3 end ANGLE --> TMP_PATH subgraph TMP_PATH["BUOC 5: Tao duong tam"] T1["Tinh Pose_F = offsetPoint(goal, yaw, dist_F)"] T2["mid = trung diem(C, F)"] T3["findPathTMP({C, mid, F})
→ saved_poses_tmp"] T1 --> T2 --> T3 end TMP_PATH --> TMP_OK{Path tmp ok?} TMP_OK -- false --> ERR TMP_OK -- true --> SEG1 subgraph SEG1["BUOC 6: Sinh segment 1"] S1["findNURBSControlPoints
(start, saved_poses_tmp, angle_threshold)
→ control_points_1, dir"] S2["Xac dinh chieu reverse
cua segment 1"] S3["generateNURBSPath(control_points_1)
→ first_segment"] S1 --> S2 --> S3 end SEG1 --> SEG1_OK{first_segment
khong rong?} SEG1_OK -- false --> ERR SEG1_OK -- true --> SEG2 subgraph SEG2["BUOC 7: Sinh segment 2"] S4["mid_ctrl = trung diem
(first_segment.back, goal)"] S5["generateNURBSPath
({last_of_seg1, mid_ctrl, goal})
→ second_segment"] S4 --> S5 end SEG2 --> ASSEMBLE["BUOC 8: Ghep duong di
start + seg1 + seg2 + goal"] ASSEMBLE --> OK["return true"] ``` ### 4. Sinh duong NURBS (generateNURBSPath) ```mermaid flowchart TD A["generateNURBSPath
(control_points, check_free,
edge_end, reverse)"] --> B["setupSpline(control_points, degree)
Tao knot vector + weights
Nap vao Spline_Inf"] B --> C["Tinh chieu dai NURBS
calculateNURBSLength"] C --> D["step_new = resolution / length
(adaptive step)"] D --> E["Duyet t = 0 → 1
(buoc step_new)"] E --> F["point = CalculateCurvePoint(t)"] F --> G{point hop le?
khong NaN?} G -- false --> E G -- true --> H{Kiem tra
isFreeSpace?} H -- Bi chan --> I["obstacle_flag = true
BREAK"] H -- Thong --> J["Luu pose
Cap nhat orientation"] J --> E I --> K["result.clear()"] E -- t > 1.0 --> L["Gan orientation
cho diem cuoi"] L --> M["return result"] K --> M ``` ### 5. Tim control points (findNURBSControlPoints) ```mermaid flowchart TD A["findNURBSControlPoints
(start, saved_poses, angle_threshold)"] --> B["findNearestPointOnPath
→ idx, dir"] B --> C{idx != -1 ?} C -- idx hop le --> D["control_points = {start, saved[idx]}"] D --> E{dir == 1?} E -- Co --> F["Tim diem lui ve
sao cho dist >= target
→ end_idx"] F --> G["Them saved[end_idx]"] E -- Khong, dir == -1 --> H["Them saved.back()"] C -- idx == -1 --> I["mid = trung diem
(start, nearest)"] I --> J["control_points =
{start, mid, nearest}"] G --> K["return true"] H --> K J --> K ``` ### 6. Tim diem gan nhat tren duong (findNearestPointOnPath) ```mermaid flowchart TD A["findNearestPointOnPath
(pose, saved_poses, angle_threshold)"] --> B["Tim nearest_idx
(khoang cach nho nhat)"] B --> C["Duyet nguoc tu nearest_idx → 1"] C --> D{signedAngle >= threshold?} D -- Co --> E["nearest_idx = i
found_flag_1 = true"] D -- Khong --> C E --> F{Kiem tra khoang cach
distance_2 >= distance_1?} F -- Co --> G["dir = 1
return nearest_idx"] F -- Khong --> H["Duyet xuoi tu nearest_idx → cuoi"] C -- Het vong --> H H --> I{signedAngle >= threshold - 0.05?} I -- Co --> J["dir = -1
return nearest_idx"] I -- Khong, i == cuoi --> K["dir = 0
return -1"] J --> L{dist hop ly?} L -- false --> K L -- true --> J ``` ## Mo ta cac diem hinh hoc ``` F ──────── mid ──────── C ──────── Goal | (duong tam) | | | | | | Pose_D | | | ╲ | | | ╲ distance_AD | | | ╲ | | Start ╲ | | | | ◄── distance_min_F ────►| | ◄── dist_C ──►| ``` - **Goal**: Vi tri dock dich - **Pose_C**: Diem offset tu Goal theo huong yaw_goal, cach `(robot.length + dock.length) / 2` - **Pose_F**: Diem xa hon tren cung huong, cach Goal = `dist_C + dist_CD + dist_DF` - **Pose_D**: Hinh chieu vuong goc tu Start len duong Goal→C keo dai - **distance_AD**: Khoang cach vuong goc tu Start den duong Goal→C - **Duong tam (C → mid → F)**: Duong NURBS tam de tim diem noi segment 1 ## Luong du lieu giua cac lop ```mermaid flowchart LR subgraph Plugin["DockPlanner (Plugin Interface)"] init["initialize()"] make["makePlan()"] end subgraph Core["DockCalc (Core Algorithm)"] calc["makePlanMoveToDock()"] nurbs["generateNURBSPath()"] tmp["findPathTMP()"] ctrl["findNURBSControlPoints()"] near["findNearestPointOnPath()"] setup["setupSpline()"] end subgraph Lib["Utils"] curve["CurveCommon
(NURBS engine)"] spline["Spline_Inf
(knot/ctrl/weight)"] end init -->|"config params"| calc make -->|"start, goal,
footprints"| calc calc --> tmp calc --> ctrl calc --> nurbs ctrl --> near tmp --> setup nurbs --> setup setup --> curve setup --> spline curve -->|"CalculateCurvePoint"| nurbs curve -->|"CalculateCurvePoint"| tmp ``` ## Tham so cau hinh | Tham so | Kieu | Mac dinh | Mo ta | |---------|------|----------|-------| | `cost_threshold` | int | 200 | Nguong chi phi vat can (0-255) | | `calib_safety_distance` | double | 0.0 | Khoang cach an toan bo sung (met) | | `check_free_space` | bool | false | Bat/tat kiem tra vung tu do | | `degree` (hardcode) | int | 2 | Bac cua duong cong NURBS | | `step` (hardcode) | double | 0.02 | Buoc lay mau tham so t | ## Ghi chu - **NURBS (Non-Uniform Rational B-Spline)**: Duong cong bac 2 voi 3 control points, knot vector dang clamped `[0,0,0,1,1,1]`. - **Adaptive step**: Buoc lay mau duoc tinh tu `resolution / curve_length` de dam bao mat do diem dong deu theo do phan giai costmap. - **2-segment path**: Duong di gom 2 doan NURBS noi tiep — segment 1 dua robot tu vi tri hien tai vao duong tiep can, segment 2 dua robot tu diem noi den dock.