编辑 | blame | 历史 | 原始文档

割草机运动控制器状态机

概览

该状态机包含 3 个主阶段(GOTO_START, FOLLOW_PATH, FINISHED),以及多个子状态和模式标志。


完整状态机图(分层结构)

stateDiagram-v2
    [*] --> GOTO_START: 初始化

    state GOTO_START {
        [*] --> Rotate
        Rotate --> Move: abs(heading_err) <= start_turn_first_heading
        Move --> Approach: dist_to_start < start_approach_dist
        Move --> Align: dist_to_start < start_tolerance
        Approach --> Align: dist_to_start < start_tolerance
        Align --> [*]: dist_to_start < start_tolerance AND\nabs(heading_err_final) < start_heading_tolerance
        
        note right of Rotate
            原地转向面向起点
            forward=0, turn=yawrate
            条件:heading_err > start_turn_first_heading
        end note
        
        note right of Move
            面向起点前进
            forward=scaled, turn=correction
            条件:dist_to_start >= start_tolerance
        end note
        
        note right of Approach
            减速接近起点
            speed = slow_speed * dist_ratio
            条件:dist < start_approach_dist
        end note
        
        note right of Align
            原地对齐路径起始航向
            forward=0, turn=yawrate
            条件:到达起点但航向不对
        end note
    }

    GOTO_START --> FOLLOW_PATH: 到达起点且航向对齐

    state FOLLOW_PATH {
        [*] --> NormalFollow
        
        NormalFollow --> WaypointApproach: 检测到未转向拐点\n且 dist < 2.0m
        NormalFollow --> Recovery: abs(xte) > recovery_dist (2.0m)
        
        state WaypointApproach {
            [*] --> ApproachingCorner
            ApproachingCorner --> [*]: dist_to_waypoint < waypoint_turn_tolerance (0.12m)
            
            note right of ApproachingCorner
                直接朝向拐点前进(忽略路径)
                减速:dist<0.5m时逐渐降速
                forward=scaled, turn=to_waypoint
            end note
        }
        
        WaypointApproach --> WaypointTurn: 到达拐点位置
        
        state WaypointTurn {
            [*] --> TurningInPlace
            TurningInPlace --> [*]: abs(heading_err) < waypoint_turn_heading_tol (0.1rad)
            
            note right of TurningInPlace
                原地转向到下一段路径方向
                forward=0, turn=yawrate
                完成后标记拐点已转向
            end note
        }
        
        WaypointTurn --> NormalFollow: 转向完成
        
        state Recovery {
            [*] --> RecoveringToPath
            RecoveringToPath --> [*]: abs(xte) < recovery_exit_dist (0.8m)
            
            note right of RecoveringToPath
                大偏离恢复模式
                朝向路径投影点前进
                speed = recovery_speed (0.55 m/s)
            end note
        }
        
        Recovery --> NormalFollow: 回到路径附近
        
        state NormalFollow {
            [*] --> PurePursuit
            PurePursuit --> SlowZone: final_dist < slow_zone (1.5m)
            SlowZone --> FinalApproach: final_dist < final_approach_dist (0.8m)
            FinalApproach --> PurePursuit: final_dist >= final_approach_dist
            
            note right of PurePursuit
                标准纯追踪控制
                lookahead = f(speed, xte)
                速度 = base_speed * scale(曲率,航向误差,xte)
                转向 = PID(heading_err) + xte_correction
            end note
            
            note right of SlowZone
                接近终点减速区
                speed *= dist_scale
            end note
            
            note right of FinalApproach
                终点精确接近
                speed *= 0.6
                增加航向/xte精度要求
            end note
        }
        
        NormalFollow --> [*]: final_dist < goal_tolerance (0.3m)
    }

    FOLLOW_PATH --> FINISHED: 到达终点

    state FINISHED {
        [*] --> Stopped
        note right of Stopped
            forward=0, turn=0
            任务完成
        end note
    }

    FINISHED --> [*]

主要状态与参数

顶层阶段

状态 说明 进入条件 退出条件
GOTO_START 从任意位置移动到路径起点 初始化 到达起点且航向对齐
FOLLOW_PATH 跟随路径行驶 完成 GOTO_START 到达终点
FINISHED 停止 到达终点

GOTO_START 子状态

子状态 说明 控制输出 进入条件 退出条件
Rotate 原地转向面向起点 forward=0, turn=k*heading_err 初始/航向偏差大 abs(heading_err) <= start_turn_first_heading (~15°)
Move 朝向起点前进 forward>0, turn=correction 完成 Rotate dist_to_start < start_tolerance (0.12m)
Approach 减速接近起点 forward=slow_speed*scale dist < start_approach_dist (1.5m) 到达起点容差内
Align 原地对齐路径起始航向 forward=0, turn=k*heading_err_final 到达位置但航向不对 abs(heading_err_final) < start_heading_tolerance (0.01rad)

关键参数:
- start_tolerance = 0.12m - 位置到达容差
- start_heading_tolerance = 0.01rad (~0.57°) - 航向对齐容差
- start_approach_dist = 1.5m - 开始减速距离
- start_turn_first_heading = pi/50 (~3.6°) - 先转向再前进的航向阈值

FOLLOW_PATH 模式

标准跟踪(Normal Follow)

  • Pure Pursuit 前视点选择
  • 动态 lookahead:lookahead_min + lookahead_time * speed - 0.3 * xte
  • 范围:[0.35m, 1.5m]
  • 速度调度

  • 基础速度:base_speed = 0.5 m/s
  • 缩放因子:
    • 曲率:1 / (1 + abs(curvature) * 2.0)
    • 航向误差:1 / (1 + abs(heading_err) * 1.5)
    • 横向误差:1 / (1 + abs(xte) * 1.0)
  • 最终速度:target_speed = base_speed * 混合缩放
  • 转向控制(PID + 横向修正)

  • P: k_heading * heading_err (k=1.8)
  • D: k_heading_d * heading_err_d (k=0.25)
  • I: k_heading_i * heading_err_sum (k=0.01)
  • XTE修正: -k_xte * xte_normalized (k=1.2)

拐点模式(Waypoint Mode)

模式 说明 触发条件 控制策略 退出条件
WaypointApproach 接近拐点 检测到未转向拐点 & dist<2m 直接朝向拐点前进(忽略路径),dist<0.5m时减速 dist < waypoint_turn_tolerance (0.12m)
WaypointTurn 原地转向 到达拐点位置 forward=0, turn=k*heading_err abs(heading_err) < waypoint_turn_heading_tol (0.1rad ~6°)

拐点检测条件:
- 原始路径点前后方向变化 > 45° (pi/4)
- 未在 waypoint_turned 集合中(避免重复)
- 按路径顺序依次处理(不跳过)

恢复模式(Recovery Mode)

属性 值/说明
触发条件 abs(xte) > recovery_dist (2.0m)
退出条件 abs(xte) < recovery_exit_dist (0.8m)
控制策略 朝向路径投影点前进,固定速度 recovery_speed = 0.55 m/s
优先级 覆盖所有其他速度调度逻辑

终点接近

区域 距离阈值 速度调整 精度要求
Slow Zone < slow_zone (1.5m) speed *= dist_scale (0.3~1.0) 标准
Final Approach < final_approach_dist (0.8m) speed *= 0.6, 再乘 dist_scale 航向<pi/10, xte<0.15m 时再*0.7

| Goal Tolerance | < goal_tolerance (0.3m) | 停止 | - |

扩展完成条件:
- final_dist < goal_tolerance * 1.5 (0.45m)
- current_target_idx >= n - 2
- abs(heading_err) < 0.3rad
- abs(xte) < 0.2m


并发标志与特殊逻辑

状态标志

  • stage: GOTO_START / FOLLOW_PATH / FINISHED
  • goto_substage: rotate / move / align(仅在 GOTO_START 有效)
  • waypoint_approach_mode: bool(拐点接近模式)
  • waypoint_turn_mode: bool(拐点转向模式)
  • in_recovery: bool(恢复模式)
  • finished: bool(任务完成)

优先级(从高到低)

  1. finished → 立即返回 forward=0, turn=0
  2. GOTO_START → 按子状态执行(rotate/move/align)
  3. waypoint_turn_mode → 原地转向(覆盖其他控制)
  4. waypoint_approach_mode → 直接朝向拐点
  5. in_recovery → 恢复模式(覆盖速度调度)
  6. Normal Follow → 标准纯追踪

安全与约束

  • 最小前进速度min_follow_speed = 0.08 m/s(防止静止)
  • 加速度限制accel = 0.2 m/s²(软启动)
  • 倒车条件abs(heading_err) > 2.9rad (~166°)
  • 错误恢复:连续大误差(xte>0.75m 或 heading_err>pi/2.5)超过 10 次 → 重置积分项

控制输出映射

forward_signal = int(round((current_speed / max_forward_mps) * 100))
turn_signal = int(round((yawrate_cmd / max_yawrate) * 100))

范围:[-100, 100]
- forward: -100 → -0.2 m/s (倒车), 0 → 静止, +100 → +0.6 m/s
- turn: -100 → -pi/4 rad/s (右转), 0 → 直行, +100 → +pi/4 rad/s (左转)

典型执行流程示例

场景1:从远处到达起点并开始作业

[*] → GOTO_START(Rotate) 
    → 原地转向面向起点 (heading_err 从 120° 降到 3°)
    → GOTO_START(Move) 
    → 前进接近起点 (dist 从 5m 降到 1.5m)
    → GOTO_START(Approach) 
    → 减速接近 (dist 从 1.5m 降到 0.1m)
    → GOTO_START(Align) 
    → 原地调整航向对齐路径方向 (heading_err_final 从 8° 降到 0.5°)
    → FOLLOW_PATH(NormalFollow/PurePursuit)
    → 标准纯追踪跟随路径

场景2:路径跟随中遇到拐点

FOLLOW_PATH(NormalFollow) 
    → 检测到前方 2m 处有拐点(方向变化 60°)
    → WaypointApproach 
    → 直接朝向拐点前进,逐渐减速 (dist 从 2m 降到 0.1m)
    → WaypointTurn 
    → 原地转向到下一段方向 (heading_err 从 60° 降到 5°)
    → 标记拐点已转向,回到 NormalFollow

场景3:大幅偏离路径

FOLLOW_PATH(NormalFollow) 
    → 横向误差 xte 增大到 2.5m(触发恢复)
    → Recovery 
    → 朝向路径投影点,固定速度 0.55 m/s (xte 从 2.5m 降到 0.7m)
    → 回到 NormalFollow

场景4:接近并到达终点

FOLLOW_PATH(NormalFollow/PurePursuit) 
    → final_dist < 1.5m → SlowZone(速度降到 0.3~0.5 m/s)
    → final_dist < 0.8m → FinalApproach(速度进一步降到 0.2 m/s)
    → final_dist < 0.3m → FINISHED(Stopped)

关键数值速查表

参数 默认值 说明
max_forward_mps 0.6 最大前进速度 (m/s)
max_reverse_mps 0.2 最大倒车速度 (m/s)
max_yawrate pi/4 最大偏航角速度 (rad/s)
base_speed 0.5 基础速度 (m/s)
k_heading 1.8 航向误差比例增益
k_heading_d 0.25 航向误差微分增益
k_xte 1.2 横向误差修正增益
lookahead_min 0.35 最小前视距离 (m)
lookahead_max 1.5 最大前视距离 (m)
lookahead_time 2.0 前视时间系数 (s)
goal_tolerance 0.3 终点到达容差 (m)
start_tolerance 0.12 起点到达容差 (m)
waypoint_turn_tolerance 0.12 拐点到达容差 (m)
recovery_dist 2.0 触发恢复模式距离 (m)
recovery_exit_dist 0.8 退出恢复模式距离 (m)

状态机实现建议(C移植)

// 主状态枚举
typedef enum {
    STAGE_GOTO_START,
    STAGE_FOLLOW_PATH,
    STAGE_FINISHED
} MowerStage;

// GOTO_START 子状态
typedef enum {
    GOTO_SUBSTAGE_ROTATE,
    GOTO_SUBSTAGE_MOVE,
    GOTO_SUBSTAGE_ALIGN
} GotoSubstage;

// FOLLOW_PATH 模式标志
typedef struct {
    bool waypoint_approach_mode;
    bool waypoint_turn_mode;
    bool in_recovery;
} FollowModeFlags;

// 控制器状态
typedef struct {
    MowerStage stage;
    GotoSubstage goto_substage;
    FollowModeFlags follow_flags;
    uint16_t current_target_idx;
    uint16_t waypoint_turn_target_idx;
    float current_speed;
    bool finished;
} MowerControlState;

// 状态转移函数原型
void update_goto_start_state(MowerControlState *state, float dist, float heading_err);
void update_follow_path_state(MowerControlState *state, float xte, float waypoint_dist);
void compute_goto_start_control(const MowerControlState *state, int16_t *forward, int16_t *turn);
void compute_follow_path_control(const MowerControlState *state, int16_t *forward, int16_t *turn);

注意事项与已知问题

  1. 重复定义_find_nearest_original_waypoint 函数出现两次,后者覆盖前者
  2. 日志频繁:74Hz 写文件 + flush,嵌入式需改为缓冲或减少频率
  3. 参数注释不符start_heading_tolerance = 0.01 注释说 ~14°,实际 ~0.57°
  4. 多级速度缩放:难以调参,建议简化为统一公式
  5. 拐点检测无距离过滤:锯齿路径可能频繁触发,建议加入"前后边长 > min_seg_len"
  6. 恢复模式触发可能过晚:lookahead 前视可能使车继续偏离,建议提前触发
  7. 终点完成条件重复:两个分支可能同时满足,建议统一
  8. 倒车逻辑:基于 heading_err > 166° 可能导致不必要倒车,建议结合距离判断

生成时间:2025-11-13
基于:mower_controller.py (约 1200 行)