1.2 主飞行回路:感知规划行动的闭环


1.2 主飞行回路:感知规划行动的闭环

本节摘要:主回路是飞行器的心脏。本节拆开闭环的三个阶段,看读数、航线、舵面指令三样数据在接缝上怎么流动;给出频率分层与时间预算的配比算法——回路卡顿的头号病因就在节拍失配;最后对比反应式、分层式、混合式三种布线流派的适用空域与代价,交付一个能空转的主循环骨架。

为什么自动驾驶团队要把感知、决策、控制拆成不同小组,而不是让一个天才模块包打天下?因为这三个阶段的天然节拍差了好几个数量级:摄像头的读数以几十毫秒一帧的速度涌进来,路径规划得出一条能用好几秒的航线,而方向盘的控制量每几毫秒就要刷新一拍。把它们塞进同一个循环里用同一个频率跑,快的等慢的、慢的被快的淹没——飞行器还没离开地面,回路先把自己勒死了。上一节钉好的舱段图纸,在本节要回答的就是"接线"问题:谁以什么频率、把什么数据、交给谁。

回路解剖:读数、航线与舵面

把主回路展开,是三段各司其职的接力。感知段把物理世界的光、声、距离变成结构化读数——读数的契约要求带时间戳与置信度,因为规划舱必须知道这份情报有多新、多可信;规划段把读数加目标变成航线——航线不是单个动作,而是一段带优先级的动作序列,外加"何时重算"的触发条件;行动段把航线当前步拆成执行器指令,并负责回执——指令是否送达、动作是否生效、环境是否如预期改变。

三段接力中最容易被忽视的是回执与再感知的接缝。很多实现里行动执行完就完事了,下一拍感知被动等新读数——这在快速变化的环境里等于闭着眼睛飞。正确的设计是行动段主动触发一次定向感知("我刚动了舵,雷达看我偏了多少"),把回执变成下一拍读数的一部分。闭环由此才算真正闭上:感知喂规划,规划喂行动,行动改变环境,变化回到感知。

节拍与预算:回路的频率学

主循环的第一设计决策不是算法,是频率配比。经验配比按信息变化速度倒排:控制层最快,本地规划次之,全局规划与感知融合再次之。每个舱段在自己的节拍窗口里有时间预算,超预算的处理策略必须预先声明——丢帧、降级还是排队,三种策略对应三种故障后果,混着用是最常见的翻车源。

import time TICK_BUDGET = { "perception": 0.020, # 感知融合:20 毫秒窗口 "planning": 0.100, # 规划:100 毫秒窗口 "action": 0.005, # 行动指令下发:5 毫秒窗口 } class MainLoop: def __init__(self, agent, watchdog): self.agent = agent self.watchdog = watchdog # 超时监控器 def run(self, world, max_ticks=None): tick = 0 while max_ticks is None or tick < max_ticks: t0 = time.monotonic() # 感知拍:读数进状态板 reading = self._run_stage( "perception", self.agent.perception.sense, world) self.agent.board.update_belief(reading) # 规划拍:航线可用就不重算(预算留给触发式重规划) if self.agent.board.route_expired() or \ self.agent.board.goal_changed(): route = self._run_stage( "planning", self.agent.planning.plan, self.agent.board) self.agent.board.load_route(route) # 行动拍:取航线当前步下发,回执写回状态板 receipt = self._run_stage( "action", self.agent.action.execute, self.agent.board.current_action()) self.agent.board.log_receipt(receipt) self._sleep_remaining(t0) # 补齐到节拍点,避免空转挤占 tick += 1 def _run_stage(self, name, fn, *args): t0 = time.monotonic() try: result = fn(*args) except Exception as exc: self.watchdog.report(name, exc) # 单舱段故障不上交主循环 return self.agent.board.last_good(name) # 退回上一帧有效值 spent = time.monotonic() - t0 if spent > TICK_BUDGET[name]: self.watchdog.report_overrun(name, spent) # 超预算留痕 return result

这段骨架有三个刻意的设计值得画重点。其一,规划不必每拍执行——航线没过期、目标没变就跳过,把预算省给感知与行动,这是多数新手实现跑不动的直接原因。其二,单舱段故障不上交:感知一帧失败就退回上一帧有效读数(last-good),主循环照转,飞行器绝不因为一帧雷达噪声而全机熄火。其三,超时必须留痕——watchdog 报告是第 7 章调试的主要线索来源。

三种布线流派:反应式、分层式与混合式

同一套舱段,接线方式决定了飞行器的性格。工程史上沉淀出三种流派,各自的脾气与适用空域差异极大。

反应式把感知近乎直连行动:读数进来,规则表查一下,舵面就动。特点是没有显式规划舱——或者说规划被压缩成了规则查表。 Brooks 的包容架构是这一流派的鼻祖,用一层层简单行为(避障优先于前进)叠加出复杂表象。它赢在响应极快、几乎不会死机,输在没有远见:不会绕开死胡同,因为它不知道"死胡同"这个概念。

分层式把规划舱拆成多层:任务层定"去哪",路径层定"怎么走",动作层定"此刻怎么动舵",上层给下层下子目标,下层给上层报状态。特点是有远见、可解释,但层间延迟叠加,对突发障碍的响应取决于最底层规则是否兜底。

混合式把两种接在一起:规划层慢速出航线,反应层高速兜底,反应层平时服从航线、遇险时越权接管。经典的"三层"( deliberative–sequencing–reactive)架构就是这一路。它两头的好处都要,代价是两套逻辑的仲裁与一致性维护——什么时候允许越权、越权后规划层如何重新对齐,是混合式真正的工程难点。

维度 反应式 分层式 混合式
响应速度 最快(毫秒级查表) 慢(层间传递) 快(反应层兜底)
远见能力
实现复杂度
典型失效 死循环、局部陷阱 层间失配、响应迟钝 仲裁冲突、状态打架
适用空域 动态、局部、无长程目标 静态、结构化、任务长 真实开放环境

选型代码上可以抽象成一个策略接线板,方便在同一批舱段上做布线实验:

class ReactiveWiring: """反应式:读数直连动作,规则表仲裁。""" def next_action(self, board): for rule in self.rules_by_priority: # 避障 > 靠近 > 巡航 if rule.triggered(board.belief): return rule.action(board) return self.default_action class LayeredWiring: """分层式:任务层 -> 路径层 -> 动作层逐级下发。""" def next_action(self, board): subgoal = self.task_layer.refine(board) # 慢拍 path = self.path_layer.refine(subgoal) # 中拍 return self.motor_layer.refine(path) # 快拍 class HybridWiring: """混合式:航线为主,反应层可越权。""" def next_action(self, board): route_cmd = self.layered.next_action(board) if self.reflex.danger(board.belief): # 高速险情检测 return self.reflex.override(board) # 越权接管并上报 return route_cmd

💡 关键直觉:三种流派不是进化关系,是空域适配关系。结构化仓库格路用反应式足够且最可靠;开放道路必须混合式。为静态空域上混合式,是在用复杂度买用不上的能力。

联调测试与故障排查

主回路的联调遵循"先断后通":先把三段接缝逐段断开做开环测试——只跑感知拍看状态板更新,只灌假航线看行动拍执行;确认各段独立健康后再闭环。闭环首跑用慢动作模式:把节拍窗口放大一个数量级,人工盯着状态板走完一圈,确认读数、航线、回执的时序对齐。

闭环特有的故障模式与处置:

  • 节拍失配:感知超预算挤压行动窗口,表现为"动作一顿一顿"。先降感知频率或砍融合耗时,绝不动行动拍。
  • 航线过期:规划赶不上环境变化,飞行器拿着旧航线自信飞行。症状是"明明绕得开却撞上"。处置:给航线加时效戳,过期强制重算。
  • 接缝死锁:行动等回执、规划等行动、感知等调度,互相等待。症状是主循环停摆但进程健在。处置:每段等待都带超时与降级出口,watchdog 强制放行。
  • 越权震荡:混合式里反应层频繁接管又频繁放权,舵面来回抖。处置:越权要带冷却时间与恢复条件。

本节要点回顾

  • 三段接力:感知出读数(带时间戳与置信度)、规划出航线(带过期条件)、行动出指令(带回执),闭环靠"行动触发再感知"真正闭上。
  • 频率配比:控制快于局部规划、局部规划快于全局规划;规划不必每拍执行,省下的预算是回路能转起来的关键。
  • 故障不上交:单舱段失败退回上一帧有效值,主循环照转,watchdog 留痕供事后排障。
  • 三种布线:反应式赢节拍输远见,分层式反之,混合式用仲裁复杂度买两头——按空域选,不按流行度选。
  • 联调次序:先开环分段验证,再闭环慢动作首跑;节拍失配、航线过期、接缝死锁、越权震荡是四类高频病。

回路转起来了,但驾驶舱里的仪表还没定义读法——状态板上该有哪些字段、目标怎么记、行为怎么仲裁,是下一节"飞行状态板"的事。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U