
最近在调试自动驾驶规划控制算法的时候我又把Lattice Planner从头到尾捋了一遍。这算法虽然不算新但每次回头研究都会有新收获。很多刚入门的朋友找我聊规划模块问得最多的就是“Lattice到底怎么实现”“代价函数怎么定”“为什么生成了一堆轨迹最后却选不出一条能用的”。今天干脆把我自己的理解和工程落地经验整理出来从原理到代码级别怎么实现再到实际调试会遇到什么坑一次性说清楚。老规矩先交代一下背景。Lattice Planner是典型的基于采样的运动规划算法最早因为百度Apollo开源项目大面积使用而被国内做自动驾驶的工程师熟知它主要解决的是在结构化道路下“怎么从当前状态安全、舒适、高效地到达目标状态”的问题。无论你是做乘用车L2辅助驾驶还是做L4级的Robotaxi只要跑在城市公开道路或者高速上这套思路都能适用。适合手里已经有一定规划基础、想系统学习运动规划或者正在被轨迹采样折磨的工程师参考。1. 为什么Lattice能成为运动规划的主流方案之一1.1 先理清它在“感知-决策-规划-控制”链路里的位置要真正搞懂Lattice Planner先要把它放到整个自动驾驶系统里看清楚位置。一辆自动驾驶车的软件链路通常分成感知、决策、规划、控制四层。感知负责告诉我“周围有什么”决策负责回答“我现在应该干什么”规划负责回答“具体怎么干”控制负责把这句“怎么干”翻译成方向盘和电机的指令。Lattice Planner就是规划层里的核心算法之一。它接收来自上游的参考线route 或者 reference line、本车定位状态、高精地图或道路结构信息以及经过决策模块处理后的目标比如跟车目标、停车点、变道目标然后输出一条在时间和空间上连续的轨迹。这条轨迹不是简单的一条线而是包含时间戳的位置序列也就是每一时刻车辆应该在哪个位置附带速度、加速度、航向角等信息。这里有个关键认知规划层输出的轨迹质量直接决定了下游控制能不能跟得住。很多新手在调控制的时候发现车辆左摇右晃查来查去最后发现是规划轨迹本身的jerk太大或者曲率不连续根本不是控制参数的问题。所以规划算法做的不是“画线”而是“画出适合车辆动力学执行的线”这一点理解到位了再回头看Lattice的很多设计就顺理成章了。1.2 采样规划的核心思路把连续问题离散化自动驾驶的运动规划本质上是一个连续优化问题在满足车辆动力学约束、安全约束、交规约束的前提下找一条从起点到终点的最优轨迹。直接对这个连续问题进行求解数学上难度很大计算量也不可控。Lattice采取了一个非常工程化的思路——先把连续空间离散化把问题变成“从一堆有限的候选轨迹里挑一条最好的”。这个过程很像选路线出行。如果让你从家去机场你不会在脑子里把每一条可能的路线都过一遍而是会先选出几个大致方案走高速、走快速路、走地面道路。然后在这几个方案里综合考虑时间、距离、过路费、拥堵情况做出最后选择。Lattice做的是同样的事只不过它把“大致方案”变成了按采样步长生成的一系列精确定义的轨迹把“综合考虑”变成了代价函数里的各项加权。这种离散化采样带来的最大好处是可控性强。候选轨迹的数量是固定的每条轨迹都是能用数学表达式描述的那么轨迹是否安全、是否舒适、是否符合交规都可以在生成之后逐条打分筛选。模块之间逻辑清晰出了问题也好定位。它的代价是理论上不能保证一定找到全局最优解——如果采样分辨率不够真正的最优轨迹可能恰好没被采到。但在工程实践中只要采样策略设计得当这个缺点完全可以接受。2. Lattice Planner的两个支柱坐标系变换和轨迹族生成2.1 从笛卡尔到Frenet坐标系为什么非要“掰直”道路Lattice里最核心的预处理步骤是把车辆和障碍物的坐标从笛卡尔坐标系转换到Frenet坐标系。很多初学者在这一步就开始懵了不理解为什么要绕这么一圈。其实道理很简单在笛卡尔坐标系下道路是弯弯曲曲的如果直接在xy平面上采样生成的轨迹很难处理“道路边界约束”和“沿道路方向的目标”。比如一条S型弯道想在笛卡尔坐标系下表达“沿路往前50米”计算量非常大。Frenet坐标系以参考线为轴重新定义了空间。在这个坐标系里横坐标s表示沿参考线的纵向距离纵坐标l表示偏离参考线的横向距离。经过这个变换道路在数学上被“掰直”了——不管参考线怎么弯车道边界在Frenet坐标系下都是平行线。于是“沿路往前走”就变成了“s方向上往前走”“保持在车道内”就变成了“l方向限制在某个范围内”问题一下就从弯弯曲曲的曲线问题变成了直线问题处理起来简单得多。这个思想很像画地图时用的投影。把一个三维地球表面投影到二维平面地图上虽然会有变形但在局部范围内城市道路、建筑之间的相对关系变得非常直观。Frenet坐标系就是自动驾驶领域的“墨卡托投影”它牺牲了全局的几何直观性换来了局部运动规划的极大便利。实际代码实现时坐标变换没有一个全局闭式解通常采用“找最近匹配点”的方法。每一步都从参考线上的离散点中搜索距离当前车位置最近的点作为投影点然后以这个投影点为基准计算s和l。这个过程在工程上叫“Cartesian to Frenet Transformation”里面有大量细节参考线要平滑、投影点搜索要精确、速度方向与参考线切向的夹角要正确处理。如果投影这一步做不准确后面所有的采样轨迹都会带上系统性误差这是Lattice工程实现里最容易埋雷的地方之一。2.2 轨迹生成横向和纵向解耦多项式怎么选Lattice能高效生成轨迹的另一个关键设计是把横向运动和纵向运动解耦。横向运动指的是车辆在Frenet坐标系下l方向的运动也就是“换道”“避障”这种左右方向的变化纵向运动指的是s方向的运动也就是“加速”“减速”“停车”这种前后方向的变化。这两者解耦之后可以分别生成轨迹再在时间维度上组合起来。横向轨迹一般用五次多项式来描述l a0 a1t a2t^2 a3t^3 a4t^4 a5*t^5。为什么是五次多项式因为它有6个系数刚好可以满足6个边界条件起点l、终点l、起点一阶导横向速度、终点一阶导、起点二阶导横向加速度、终点二阶导。多项式天然是光滑的只要边界条件给得合理得到的轨迹就是连续的而且它的三阶导jerk可以用解析方式算出来方便后续做舒适性评估。纵向轨迹则要看场景分两套做法。定速巡航场景下速度基本不变使用四次多项式就够了因为已知起点s、s一阶导和二阶导以及终点s和终点s一阶导5个条件对应5个系数。停车场景下终点速度和加速度都应为0所以要升级成五次多项式来满足6个边界条件。这套选择背后没有玄学就是“边界条件的数量决定多项式的阶数”这一条朴素的数学规则。轨迹生成之后还要做一步“横向纵向合并”的工作。把一组横向轨迹和一组纵向轨迹按照相同的时间轴进行组合得到一条完整的候选轨迹。合并不是简单拼接坐标而是要在每一个时刻t取横向轨迹给出的l值和纵向轨迹给出的s值通过Frenet到笛卡尔的逆变换还原出车辆在真实世界坐标系下的位置、速度、加速度和航向角。这步逆变换比正向变换细节更多因为需要处理参考线曲率的影响轨迹的中心线曲率越大同样的横向偏移对应的笛卡尔坐标差异就越大处理不当会直接导致规划结果发飘。2.3 采样与拼接不是所有轨迹都值得评估从原理上说只要有横向轨迹和纵向轨迹就可以组合出M×N条候选轨迹。但如果真把M和N都取到30以上组合出来几千条轨迹每次规划都全部评估一遍计算耗时一定会出事。工程上常见的做法是限制采样数量让候选轨迹总数控制在百条量级比如横向取811条纵向取813条组合后100条左右这个量级在实际部署时是可以接受的。横向采样的目标通常围绕当前车道和相邻车道展开。以当前横向位置为中心采样点可以是“保持当前l不变”“向左侧车道中心靠拢”“向右侧车道中心靠拢”等几个离散层级每条目标再配一个或多个期望时间。纵向采样的对象则是前方一段范围内的多个s值比如从当前位置往前10米到80米每隔一定间距取一个目标位置同时为每个目标位置配置期望速度。采样范围不能太小也不能太大太小了看不到长距离的决策意图太大了计算量上涨且远端轨迹大概率用不上是一种典型的性价比权衡。采样结束之后生成的轨迹还要做一次“配时间轴”的处理。由于每条横向轨迹和每条纵向轨迹都有自己的时间参数组合时要确保时间点对齐也就是说同一物理时刻t对应的横向状态和纵向状态必须来自同一时间点。实际工程中这一步通常会在计算每条轨迹的时候就统一用固定的采样时间步长这样后续所有轨迹天然时间轴一致不需要额外插值对齐大幅降低通用实现的复杂度。3. 代价函数设计怎么让规划结果“像人开的”3.1 代价的四个核心维度如果采样生成了一堆安全轨迹但是不知道怎么从里面选出最好的一条那整个算法就白做了。Lattice的筛选机制就是代价函数它把“好”的风格量化为几个维度的加权和分数最低的轨迹胜出。代价函数设计的好坏直接决定了规划结果是像一个老司机还是有路怒症的莽夫。我在工程落地中通常把代价分为四个维度第一是效率代价。这条轨迹要花多久到达目标到达之后速度和期望速度差多少如果前方没有障碍物你规划出一条时速只有20km/h的轨迹那即使再舒适安全车主也不会满意。第二是舒适性代价。通常用jerk也就是加速度的变化率来度量。很多人对jerk没有直观概念举个例子你坐公交车司机起步时一脚油门到底你的身体会猛地往后仰这个过程给你带来的不适感主要就是由jerk造成的。加速度本身会让身体倾斜但jerk会让身体“突然”倾斜感受最差。五次多项式轨迹的jerk可以直接对位置函数求三阶导得到计算简单且物理意义清晰。第三是横向偏移代价。这条轨迹偏离参考线的距离是多少偏向道路哪一侧要让车辆尽量保持在车道中心行驶这个代价就得占足够权重。如果权重太小车辆会总贴着车道边缘走一方面乘坐体验差另一方面也会增加擦碰护栏或旁边车辆的危险概率。第四是终点状态代价。这条轨迹结束时的状态是否落在我们想要的目标附近比如决策模块说“应该在下一个路口停车”那终点位于停车线附近且终点速度接近0的轨迹就应该比终点停在几十米外的轨迹拿到更低的分数。这类代价是引导整个算法达成上层意图的关键不能只靠采样范围硬凑。3.2 约束怎么落到代码里代价函数负责“择优”但“择优”的前提是“候选轨迹本身必须满足基本约束”。我在实践里习惯把约束分成硬约束和软约束两类。硬约束是无论如何都不能违反的包括碰撞约束和动力学约束。碰撞约束不用多说轨迹上任何一个点都不能与障碍物发生重叠这是安全底线。动力学约束包括加速度不能超过车辆物理极限、曲率必须符合最小转弯半径、jerk不能超过车身舒适阈值等。这些约束不满足的轨迹会在评估前直接被丢弃不进入评分阶段。你可以把硬约束理解为“及格线”不及格的直接淘汰不存在补考机会。软约束则是指“尽量满足但不强求”的项通常被折算成代价的一部分。比如规划结果不要频繁变道这个不是绝对的但如果有一条轨迹不变道也能到达目标那就不应该选择连续换两条车道的激进方案。再比如轨迹尽量贴近参考速度但如果因为前车慢行必须减速那减速的轨迹仍然可以使用只是效率代价会略微变高。在代码层面硬约束和软约束的实现方式差别很大。硬约束需要在每个离散时间点或路径点上做判断任何一点不满足就丢弃整条轨迹。软约束则通常表现为代价函数里的一个或多个术语比如通过一个分段函数在偏离约束较小时惩罚很小一旦偏离超过阈值惩罚项指数上升。这种分段函数的写法比简单线性加权更能体现“软”的程度实际调参时也更好控制边界行为。3.3 实际工程中的权重调参经验代价函数的权重怎么定这是Lattice工程落地中最磨人的问题之一。理论上我们可以通过仿真和实车试验反复调但单纯靠感觉调参效率太低。我的经验是先给每个维度的代价做归一化让每个分量的数值量级大致在0到1之间然后再设权重。如果不归一化效率代价动辄几十舒适性代价只有零点几最终权重会完全被量级大的项主导调参完全失准。举个例子归一化之前如果效率代价的平均量级是20舒适性代价的平均量级是0.5那你把舒适性权重调到10看起来已经很重视了实际加总后舒适性贡献只有5还是远小于效率的20。归一化之后两个维度都在0到1之间权重就直接表达了“你愿意用多少舒适性换取多少效率”语义清晰了很多。另外我习惯在调参初期只调整两到三个主要权重把其他维度固定下来等主要问题收敛后再逐个微调。同时要充分使用仿真工具的轨迹可视化能力把每条候选轨迹的代价分量逐项打印出来。这个方法帮我解决过很多次“看起来权重合理但行为诡异”的问题。打个比方如果发现车辆总在不需要变道的时候变道大概率不是变道代价权重太小而是参考线本身有跳变或者横向偏移代价的归一化方式有bug。可视化能帮你快速定位到底问题出在哪个维度而不是盲目地调权重。4. 从轨迹生成到筛选碰撞检测和可行性校验的实操要点4.1 碰撞检测的常见做法碰撞检测是轨迹筛选里计算量最大的环节之一也是整个规划算法安全性的最后一道闸。Lattice生成的是离散时间点上的轨迹因此碰撞检测通常也是离散逐点做的。每到一个轨迹点把车辆的外形轮廓放到这个位置上再与周围障碍物做空间相交判断。车辆轮廓通常有两种表示方式矩形包络和圆形包络。矩形包络更贴近车辆真实外形但两个旋转矩形求交的计算开销稍大。圆形包络是用几个圆来近似车身外形比如用3个半径为1.8米到2.2米的圆覆盖前后轴区域圆的相交判断只需要计算两个圆心之间的距离和半径之和做比较计算量比矩形小很多。实际工程里因为我们要在100条候选轨迹上逐点检测每个轨迹点可能还有几十上百个障碍物用圆形包络可以显著降低计算耗时而精度损失在绝大多数场景下是可以接受的。除了几何表达工程上还很讲究“先粗筛后精检”的策略。在粗筛阶段先用每个轨迹点的粗略矩形或待检测障碍物的粗糙包围盒做快速相交测试把绝大多数明显不碰撞的候选直接排掉只对可能碰撞的少数轨迹做精确的逐点多边形相交检测。这样做的思路和数据库查询时先建索引再扫描是一样的先用成本最低的方法圈定可疑范围再做精细验证整体计算效率可以提高好几个数量级。4.2 可行性校验曲率、加速度、加加速度碰撞检测通过并不代表轨迹一定能执行。车辆是受物理规律约束的非完整约束系统不能横着走不能瞬间转弯也不能一下子从静止加速到100km/h。可行性校验就是检查候选轨迹是否在车辆的物理能力范围之内。第一项是曲率约束。每个轨迹点都要计算曲率曲率不能超过车辆最大转向角对应曲率半径。这里的难点在于规划输出的曲率是一个瞬时几何量但车辆的转向系统有响应延迟实际执行的曲率会比规划值平滑一些。如果规划曲率刚好卡在极限值上实车执行时很可能会超出物理极限所以在工程上一般会留至少10%到20%的余量。我自己通常会设一个安全系数比如把最大曲率限制为物理极限的0.85倍换取之后控制模块的容错空间。第二项是加速度和减速度约束。每一项都要满足车辆动力系统的最大能力但更重要的是规划输出值不能被约束卡得太死。因为前轮转角和油门刹车控制本身就是有延迟和误差的如果一个规划轨迹的加速度经常贴着极限值跑控制器稍微跟偏一点就会触发安全保护。这点在雨天、雪天等低附着路面上尤其重要。如果你在做量产级项目建议在可行性校验里根据路面附着系数动态调整加速度阈值而不是写死一个固定值。第三项是jerk约束。jerk过大除了影响乘坐舒适性还会让执行器疲劳加剧长期下来对转向电机和刹车系统的损耗都很大。Lattice中jerk可以直接对多项式求三阶导得到这个计算开销很小几乎可以忽略不计。比较常见的做法是同时校验整个轨迹的最大jerk和平均jerk最大jerk保证不超过硬件极限平均jerk保证整体风格平稳。4.3 时间一致性问题轨迹筛选结束后我们得到了当前周期的最优轨迹。但自动驾驶系统是周期性运行的规划周期通常为100ms每个周期都会重新做一次采样和评估。这就带来一个非常重要但经常被忽略的问题时间一致性。如果你在当前周期选择了一条耗时8秒的轨迹但每个周期都重新规划那么新的轨迹很可能和上一周期的轨迹不一样。如果两个周期的轨迹差异过大控制端的指令会发生跳变导致车辆出现明显的顿挫或抖动。解决这个问题的方法通常是在代价函数里加入“与上一周期轨迹的接近程度”这一项让新规划的轨迹尽量贴近上一时刻的轨迹只有在安全或者任务要求明确变化时系统才允许产生较大偏离。这种情况很像写文章时做修改。如果每次大改都推翻重写读者会看到前后风格完全不同的文章阅读体验很差。好的编辑器会保留大部分已有内容只在必要处做局部修正。Lattice的时间一致性设计就是为了让每个规划周期之间的改变保持“局部修正”的尺度而不是每次都推倒重来。我在实际调试中遇到过这样一个案例车辆在高速上直线行驶但每个周期方向盘都在轻微抖动。排查到最后发现就是因为相邻周期选出的最优轨迹在s方向上有细微错位错位量虽然不大但通过控制器误差积累后被放大了。最后在代价函数里加了轨迹平滑项让最优轨迹与上一周期结果在采样时间轴上对齐抖动问题就消失了。这个坑非常隐蔽如果没有可视化工具把前后两个周期的轨迹叠在一起看几乎不可能定位到原因。5. 常见问题与坑Lattice Planner工程落地实录5.1 停车场景和高速场景参数要分开很多第一次接触Lattice的工程师会直接把一套采样参数和代价权重用在所有场景里结果就是高速表现还可以但一到城市停车场景就各种翻车。这不是算法错了而是参数适配有问题。高速场景的特点是参考线曲率小、车速高、纵向目标距离远。这时候横向采样范围不宜过大因为高速下横向动作稍大一点对应的侧向加速度就非常惊人会让乘客感觉被甩来甩去。纵向采样距离要拉得足够远给系统留出充足的减速和变道空间。城区停车场景则完全相反。车速低、距离近、障碍物密集横向采样需要更细的粒度来支持精准避障和入库操作纵向采样距离可能只需要前方20米就够了。代价函数也要跟着调整城区场景效率代价的权重应该降低舒适性和精确性的权重应该提高。如果拿一套参数硬跑两种场景结果不是高速上变道像抽风就是停车时路线太过激进或者根本倒不进去。我自己的项目会在规划模块内部维护一套场景参数表根据当前车速、道路类型、上游决策模块的状态自动切换参数集合。这个参数表不是拍脑袋定的每一组数值都需要在仿真和实车上反复验证但一旦建立了这个结构后续扩展新场景的效率会高很多。5.2 重规划频率和设备算力Lattice每周期都需要完成坐标变换、轨迹生成、碰撞检测、代价评估全流程对算力是有一定压力的。在x86工控机上跑自然压力不大但如果要部署到嵌入式平台或者域控制器上就必须对每个环节做细致优化。我踩过的坑之一是碰撞检测环节。未经优化的实现用矩形包络加逐点多边形求交100条候选轨迹每周期能吃掉20毫秒以上这明显不可接受。后来做了三层优化第一层是用车辆简单包围盒快速筛选障碍物候选集第二层把矩形检测换成圆形包络检测第三层是只在曲率突变点和障碍物密集区域做高精度检测其余区域直接采样检测。优化后单周期碰撞检测时间能压到5毫秒以内。另一个优化思路是减少候选轨迹数量但这种方法要谨慎使用。当你把候选轨迹从100条砍到50条计算时间确实减半但系统的鲁棒性也会明显下降偶尔会出现“好轨迹恰好没被采到”的尴尬情况。我对成功项目的直觉是性能优化优先从算法层面下手而不是简单砍采样密度因为采样密度是你最后的“能力边界”砍了采样就是砍了系统上限。5.3 容易被忽视的边界条件Lattice实现里最容易被忽视的其实是各种“边界条件”的处理。这里的边界不是指地图边界而是指状态空间的边界。比如当前车速为零的时候轨迹生成要如何处理如果直接套用多项式拟合三次项系数可能爆炸导致轨迹形态异常。又比如初始横向速度很大但横向加速度受限时该如何调整采样策略这些情况在实车调试时几乎必然遇到但教科书和论文里基本不会写。我的做法是在轨迹生成前增加一个“状态检查器”专门处理异常边界。车速极低或者静止时强制将起点横向速度清零甚至可以直接走纯纵向轨迹生成分支不再做横纵向合并。初始纵向速度与目标纵向速度方向相反时要防止生成“先倒车再前进”的不合理轨迹直接在约束里限制整个轨迹段的s方向速度非负。这些检查逻辑本身不难但要在设计算法一开始就留好位置否则后面补起来很痛苦每一处都像是在既有的流水线上硬塞检查工位。5.4 常见问题速查表问题现象可能原因排查思路与解决办法规划轨迹抖动、频繁左右偏移参考线不平滑或横向采样过密导致相邻轨迹代价相近对参考线做平滑处理查看相邻轨迹的评分差适当增大横向偏移代价车辆总是靠车道边行驶横向偏移代价权重过低或归一化方法有误打印每个维度的代价分量核对纵向与横向代价的量级匹配高速上方向盘细碎抖动相邻周期最优轨迹时间轴错位在代价函数中加入与上周期轨迹的接近程度项检查时间对齐逻辑停车场景轨迹激进或入库失败使用了高速场景参数或采样范围过大切换到城区停车场景参数集缩小横向和纵向采样范围提高终点状态权重碰撞检测耗时过高使用矩形包络且逐点全量检测改为圆形包络粗筛精检两级策略优先优化检测热点区域车辆起步时规划异常起点状态下边界条件处理不当增加状态检查器在低速和静止状态下特殊处理横向速度和多项式拟合6. 扩展与对比它和其他规划算法的关系没你想的那么对立6.1 和A*、RRT这类搜索算法的区别Lattice Planner经常被拿来和A*、RRT这类基于搜索或者采样的算法做比较。初学者容易把它们看成互相竞争的替代关系实际上它们是不同层级、不同用途的工具。A*和RRT更多用于全局路径规划解决的是“从A点到B点怎么走”的问题输出是一条抽象的路径通常没有时间信息和速度信息也基本不直接考虑车辆动力学。Lattice Planner则是在一条相对明确的全局路径参考线上求解局部运动轨迹强调时间、速度、加速度以及跟车避障等动态交互关系。如果说A*和RRT是在一个大的城市规划里决定从家到公司走哪条街Lattice就是在这条街上具体决定什么时候加速、什么时候变道、怎么避让前车。两者解决的是不同尺度的问题可以串联使用而谈不上谁替代谁。这里也要澄清一个常见误解Lattice也会“采样”所以它也是搜索算法的一种。但在Lattice的计算框架里采样不是随机撒点而是沿着精心设计的模式生成一组确定性的候选轨迹然后通过代价函数做评估。它更像是“有限方案集择优”不是传统意义上在连续空间里随机搜索的过程。6.2 和EM Planner、MPC控制的关系在规划算法族谱里Lattice和另一个著名的EM Planner经常被拿来对比。EM Planner采用的是“先横向后纵向”的迭代优化思路通过交替优化横向和纵向运动来逼近最优解应对复杂场景时很强大。Lattice则一次性完成横纵向解耦采样每条轨迹都是独立的候选方案思路更直接结构更简单代码上也更容易维护和调试。实际操作中Lattice在结构化道路、标线清晰、参考线质量高的场景下表现非常稳定工程落地成本相对可控。EM Planner在高度非结构化和复杂交互场景中优势更明显但工程实现难度和调参成本也高不少。我自己在选择算法路线时会先评估项目场景的结构化程度和团队对算法复杂度的掌控能力再决定优先采用哪种方案。另一方面Lattice输出的轨迹会交给下游MPC模型预测控制之类的控制器来执行。这个衔接过程中有一个常见问题Lattice输出的是以参考线为基准的轨迹在弯道处如果参考线本身曲率大轨迹转换到笛卡尔坐标后可能产生畸变给控制器的跟踪带来额外负担。因此在实际项目中我习惯在Lattice输出轨迹之前对生成的笛卡尔轨迹再做一次平滑和曲率限制处理而不是直接把转换结果丢给控制层。这个小步骤往往能大幅降低控制模块的跟踪误差值得大家尝试。6.3 学完Lattice之后可以往哪走Lattice的价值并不仅在于这个算法本身更在于它帮你建立了一套完整的“采样—评估—择优”方法论。这套思路在自动驾驶规划里无处不在后面学EM Planner、学MPC轨迹优化、学强化学习规划策略底层逻辑都是相通的——定义候选、量化评估、择优执行。如果你正在做规划岗位的面试准备Lattice是最高频的技术考察点之一考官通常不会只问“Lattice是什么”而是会追问坐标变换公式、多项式阶数选择原因、代价函数怎么设计、碰撞检测怎么做、如何解决规划抖动。把上面这些问题想透彻面试时能讲出工程上实实在在的细节比背概念机会大得多。如果你的工作重心偏量产落地那么从Lattice开始逐步扩展去理解整个规划控制算法体系的耦合关系是一条很高效的路径。规划不是独立模块它和上游决策、下游控制之间的联动决定了系统整体的驾乘体验。搞明白Lattice你就同时理解了这条链路中“规划”这一环应该怎样为上下游留出设计接口。最后再分享一个实际调试中的小技巧我在用Lattice做项目时最后都会在可视化工具里加一个功能把每条候选轨迹和它对应的代价分量同时显示出来。每一条轨迹旁边标注这一条轨迹的jerk积分、横向偏移量、终点误差等数值。这样在调参时我一眼就能看出来是哪一项代价压过了其他项、哪些轨迹是因为哪一项被淘汰的、哪些“看起来挺好的轨迹”为什么评分反而很高。这个习惯帮我省过无数次排查的力气。有一次车辆在跟车场景中总是刹车过晚看轨迹看不出问题但代价可视化之后发现效率代价的权重被归一化方法坑了导致系统认为“晚一点点刹车、保持高速”的轨迹性价比很高。发现问题后我重新设计了效率代价的归一化方式跟车刹车的提前量很快就正常了。Lattice Planner作为自动驾驶规划控制算法体系里的常青树看起来简单但真正吃透并跑得稳并不容易。希望这篇从原理到工程落地的经验总结能帮你在学习或部署的路上少踩几个坑。