首页 / 资讯中心 / 文章详情

阿克曼底盘TEB调参实战:从画龙到丝滑的避坑指南

阿克曼底盘TEB调参实战:从画龙到丝滑的避坑指南 ★ FEATURED ARTICLE
说到ROS小车的导航方案阿克曼底盘和TEB Local Planner这两个词放在一起基本就等于“调参地狱”。我之前帮朋友调一台轴距1米左右的阿克曼小车本来以为照着官方demo抄一份参数就行结果小车在地上各种画龙过窄门的时候反复横跳稍微有一点角度偏差就直接贴着墙剐蹭。后来把TEB的关键参数一个一个抠了一遍才把问题解决。这篇文章我直接把调参的完整思路、踩过的坑、还有一份可以直接抄作业的阿克曼TEB配置文件全整理出来给正在跟阿克曼小车较劲的朋友做个参考。内容偏实战不会去抠那些论文公式重点说清楚每个参数到底管什么事调高了会怎样、调低了会怎样以及阿克曼底盘和差速底盘在调TEB时有哪些本质区别。1. 阿克曼底盘为什么绕不开TEB以及调参前的底层逻辑1.1 阿克曼转向模型和TEB的契合点阿克曼转向结构模仿的是汽车转向方式前轮负责转向后轮负责驱动转弯时内外侧前轮的转角不同四个轮子绕同一个瞬时转向中心滚动。这个结构带来的直接限制是小车不能像差速底盘那样原地旋转最小转弯半径由轴距和最大前轮转角决定。你不可能通过给左右轮反向速度来调头这在运动学上就不成立。TEB Local Planner的核心思路是把局部路径看成一条由位姿点组成的“弹性带”在满足速度、加速度、转弯半径等约束的前提下通过优化让这条带子尽量平滑、尽量贴近全局路径、尽量避开障碍物。关键在于TEB能直接把非完整约束写进优化项里。对阿克曼底盘来说这意味着规划出来的轨迹天然带上转弯半径约束不会在窄空间里规划出阿克曼结构根本走不出来的轨迹。差速底盘常用的DWA采样法依赖速度空间采样对运动学约束的处理相对简单。如果你把DWA直接用于阿克曼底盘最常见的现象是规划的轨迹是“差速式”的允许小车原地转动实际执行时前轮打死也走不出那么小的转向半径然后小车就开始原地画圈或者反复前后挪动导航体验非常糟糕。所以阿克曼小车选TEB不是一个“还可以”的选项几乎是绕不开的正解。TEB里有两个参数是为阿克曼这类车型准备的必须显式打开cmd_angle_instead_rotvel打开后速度指令里的角速度会被转换成前轮转角指令min_turning_radius直接约束轨迹的最小转弯半径。这两个参数如果没设对TEB后续调什么都白搭。1.2 调参前必须确认的底盘硬约束参数很多朋友一上来就改TEB的权重参数改了半天发现要么原地抖动要么小车压根不转问题根源其实是底盘本身的硬约束参数没填。下面这几个数据请务必先写在本子上再去碰TEB轴距wheelbase单位米。前轮中心到后轮中心的距离不是车长。这个数错了最小转弯半径约束就全错了。前轮最大转角max_steering_angle单位弧度。一般阿克曼小车舵机或转向机构会限制在0.35到0.6弧度左右约20到35度。线速度上限和转向角速度上限。阿克曼底盘常会把转向角速度限制在每秒0.5到1.5弧度这个值反应到TEB里就是max_vel_theta。里程计频率和cmd_vel订阅频率。TEB在优化时需要知道每个时刻的机器人状态里程计如果掉帧TEB会变得迟钝。底盘控制器的转向指令接口。有些底盘驱动板接收的是前轮转角有些接收的是转速变化率这一点直接决定cmd_angle_instead_rotvel要不要打开。我从实际情况出发给一个判断标准如果你的机器人控制指令里需要下发前轮角度而不是角速度那cmd_angle_instead_rotvel必须设成true同时把min_turning_radius设成按公式计算出来的值。最小转弯半径的计算公式是轴距除以最大前轮转角的正切值轴距1米、最大转角0.5弧度时大约是1 / tan(0.5) ≈ 1.83米。这个值可以直接写进配置文件也可以留空让TEB自动算只要wheelbase和max_steering_angle填对就行。2. 核心参数逐个拆解这20个参数我分别怎么定TEB的参数有几十个实际调车真正要重点关注的也就20个上下。下面我把它们分成“底盘运动学参数”“速度加速度参数”“优化权重参数”三组来讲每组都说明推荐初始值和典型调整方向。2.1 底盘运动学参数没设对什么都白搭参数名作用我的推荐初始值说明min_turning_radius最小转弯半径米1.01米轴距小车如果模型支持自动计算可以留空否则务必按轴距/转角公式手动填cmd_angle_instead_rotvel用转角代替角速度指令true阿克曼底盘必须为truewheelbase轴距米1.0按实际尺子量出来的填max_steering_angle前轮最大转角弧度根据转向机构实际限制填有些小车舵机限位在35度左右填0.6就是约34度footprint_model机器人轮廓模型radius: 0.25 或按车体近似为矩形阿克曼小车一般用radius近似就行前提半径不小于车身半宽这几个参数属于“填错就翻车”的类型。我曾经见过一辆小车min_turning_radius忘了改默认值是0.2米轴距却快1米结果TEB规划的路径要求转弯半径0.2米物理上根本走不了表现在车上的动作就是后轮疯狂打滑、前轮一直往一个方向压到限位控制器干脆报错停机。cmd_angle_instead_rotvel这个参数我多说两句。开启后TEB输出的角速度会被计算成前轮转角输出的Twist消息中的angular.z字段会被填充为前轮转角值。你的底盘驱动板必须按这个协议来解析收到angular.z时当作前轮目标角度而不是当作车体角速度。如果驱动板只认角速度把这个参数直接设为true会导致小车完全没有转向输出。2.2 速度加速度参数让TEB知道你有多“肉”阿克曼小车因为转向机构带舵机或连杆响应比差速底盘慢半拍速度加速度参数如果填得比底盘实际能力高TEB规划出来轨迹很激进底盘执行跟不上就会出现轨迹跟踪误差表现就是小车走出来的弧线比规划的要大或者转弯时明显向弯道外侧飘。我常用的初始值如下max_vel_x: 0.5米/秒一般小车最高能跑到1米/秒我只会给到它实际最大速度的六到七成。因为导航不是竞速留出余地给优化器去找平滑解。max_vel_x_backwards: 0.2米/秒。阿克曼底盘倒车时稳定性差后向速度压低一点避免频繁倒车引起振荡。max_vel_theta: 0.8弧度/秒注意这是车体角速度上限不是前轮转角上限。阿克曼小车高速时转弯能力弱角速度大了容易侧翻或推头。acc_lim_x: 0.5米/秒^2。这个值对应整车纵向加速度设置太大的后果是起步急停明显对舵机齿轮冲击大。acc_lim_theta: 0.6弧度/秒^2。阿克曼底盘实际角加速度受前轮响应速度限制一般设得小一点让转向柔和。这里有一个容易被忽略的点TEB还区分了max_vel_theta和min_turning_radius之间的关系。当小车以某个线速度行驶时可达到的角速度上限其实受最小转弯半径约束角速度 线速度 / 转弯半径。如果线速度0.5、最小转弯半径1米那理论角速度上限就是0.5弧度/秒。你把max_vel_theta设到1.2也没有用物理约束把它卡死了。反过来如果max_vel_theta设得比物理上限还小那小车转弯时会明显比正常能力更迟钝这对窄通道避障是不利的。2.3 优化权重参数调车最花时间的部分TEB的核心是一个多目标优化问题目标函数不是一个而是好几个分别负责“离障碍物远一点”“轨迹短一点”“时间短一点”“符合运动学约束”等等每一个目标前面都有一个权重系数。权重越大优化器越优先满足对应目标。我实际使用中发现阿克曼小车最值得关注的权重是下面5个weight_obstacle默认值100。负责让轨迹远离障碍物。如果小车老是贴着障碍物“擦边”走多半是这个权重相对于其他权重偏小了。weight_dynamic_obstacle默认50。对动态障碍物的避让力度。如果小车对突然出现的人或障碍反应太慢加大这个值。weight_kinematics_forward默认1。负责让机器人尽量向前走不要频繁倒车。阿克曼小车德倒车性能差这个权重我会调到2左右减少倒车次数。weight_optimization_time默认1。TEB会让轨迹总时间尽量小这个权重大了轨迹会偏向“更短更快”但代价是路径更贴近障碍物或转角更急。weight_acc_lim默认1。加速度约束的惩罚权重。阿克曼小车需要在weight_optimization_time和weight_acc_lim之间找平衡。前者太大轨迹太急后者太大轨迹太肉。我调车的经验法则是先固定运动学和速度参数只调权重每次只调一个权重幅度按两倍或一半来跑了实际路线再决定下一步。不要一次改好几个权重不然出了问题根本不知道是谁引起的。3. 完整配置文件直接抄作业的TEB参数文件下面这份配置文件我尽量写得通用一些以轴距1米、前轮最大转角0.5弧度约28度、车体半径0.25米的阿克曼小车为基准。如果你用的是别的轴距把wheelbase和min_turning_radius按实际情况改了其他的可以先用这套初始值跑起来再微调。TebLocalPlannerROS: odom_topic: odom map_frame: map # 机器人运动学约束 min_turning_radius: 1.08 # 经计算 1/tan(0.5)≈1.08留出一点余量取1.08 wheelbase: 1.0 # 轴距单位米 cmd_angle_instead_rotvel: true # 阿克曼转向指令模式输出前轮转角而非角速度 max_steering_angle: 0.5 # 前轮最大转角单位弧度约28.6度 # 速度与加速度限制 max_vel_x: 0.5 # 最大前向线速度米/秒 max_vel_x_backwards: 0.2 # 最大倒车线速度米/秒 max_vel_theta: 0.6 # 最大角速度弧度/秒由 0.5/0.85 推得 acc_lim_x: 0.4 # 纵向加速度限制 acc_lim_theta: 0.5 # 角加速度限制 # 障碍物与膨胀 min_obstacle_dist: 0.2 # 轨迹离障碍物的最近距离米 inflation_dist: 0.4 # 障碍物影响范围米 include_costmap_obstacles: true costmap_obstacles_behind_robot_dist: 1.0 obstacle_poses_affected: 20 # 优化器时间分辨率 dt_ref: 0.3 # 轨迹点之间期望时间步长 dt_hysteresis: 0.1 # 允许的时间步长滞后范围 max_global_plan_lookahead_dist: 3.0 # 全局路径前瞻距离 global_plan_viapoint_sep: 0.5 # 优化权重 weight_obstacle: 100.0 weight_dynamic_obstacle: 50.0 weight_inflation: 0.2 weight_kinematics_forward: 2.0 weight_kinematics_turning_radius: 5.0 weight_optimization_time: 1.0 weight_shortest_path: 0.0 weight_velocity_obstacle: 0.5 weight_acc_lim: 1.0 # 动态障碍物配置 weight_dynamic_obstacle_inflation: 0.5 feasibility_check_no_poses: 5 # 可视化与调试 enable_homotopy_class_planning: true visualization: true这条配置有几个地方是反复调过才定下来的我说一下具体怎么来的。min_turning_radius按公式算出来是1/tan(0.5)TAN(0.5)约等于0.546得出1.83米。这个值看起来挺大我在实际场地测试后发现小车在低速下还能走出比这略小一点的弯原因是轮胎侧偏和转向机构间隙能补偿一部分。为了不让TEB过度保守我把最小转弯半径留出20%余量取1.5米左右。如果你的场地特别狭窄可以再往下探但不要低于物理极限太多。max_vel_theta取0.6是因为在巡航速度0.5米/秒下1.5米转弯半径对应的理论角速度是0.33弧度/秒。我留了将近两倍的余量给静态障碍物绕行留出机动空间。dt_ref取0.3是一个比较平衡的值。TEB在每个时间步长上会生成一个位姿点dt越小轨迹点数越多优化计算量越大dt过大轨迹点太稀疏在狭窄区域表现迟钝。小车速度0.5米/秒时0.3秒一个点相当于每15厘米一个控制点这个密度对阿克曼小车的局部避障足够了。weight_kinematics_turning_radius我设到了5.0偏高目的是强行让优化器保持转弯半径约束避免规划出来的轨迹带上一堆阿克曼走不了的“急弯”。代价是避障时轨迹会绕远路但在室内场景下绕一点远路比卡在原地好得多。enable_homotopy_class_planning建议开启。这个功能让TEB在同一时刻维护多条“拓扑不同”的候选轨迹绕障碍的时候能考虑从左边绕还是从右边绕避免陷入局部极值。代价是计算量增加。如果你的主控是树莓派3这类低算力设备可以先关掉跑起来卡的话再开。4. 仿真与实车联动调优流程避坑重点4.1 仿真里不能省但也不能全信的三件事TEB参数不建议直接拿到实车上盲调最好先在Gazebo里跑一轮把明显的方向和逻辑问题排掉。我在Gazebo里一般做三件事第一验证最小转弯半径。用teleop_twist_keyboard手动把前轮打满让车走一个定半径圆测量实际直径反推实际最小转弯半径。Gazebo的轮胎模型和实车有差异但这个数值能帮你判断TEB里的min_turning_radius给得是不是合理。第二验证最大加速度。让车从静止起步直接给0.5米/秒的目标速度看它多长时间能加到目标。如果Gazebo里1秒就达到目标实车上却要3秒那你需要把TEB里的acc_lim_x调低同时检查底盘驱动器是否有加速度限制。第三验证costmap和TEB之间的话题连接。很多仿真里规划正常是因为costmap发布的障碍物话题名跟TEB订阅的最新版本配置不匹配只是碰巧在RViz里看起来正常。我建议你先用rosrun rqt_tf_tree rqt_tf_tree看一下TF树是否连通再用rostopic info检查/local_plan和障碍物话题的时间戳是否新鲜别让低级话题问题浪费你后面所有调参时间。实车和仿真最容易出现偏差的地方是阿克曼转向机构的响应延迟。Gazebo里假设前轮转角是瞬时的实车上舵机从0转到25度可能要0.3秒这个延迟会让轨迹跟踪误差变大表现就是转弯比预期晚。如果实车转弯总比你预期晚一截不要急着加权重先把max_vel_theta降一点转弯过程会平缓很多。4.2 速度与转弯半径实车标定方法实车标定这一步说实在的我一开始也懒得做觉得太麻烦直到在小场地上车子转弯半径跟规划对不上才老老实实去标。最直接的标定方法是在空旷场地贴两个锥桶让车以固定速度跑一个完整的圆用卷尺量直径。比如我让车以0.3米/秒的速度前轮打满跑出来的圆直径约2.6米说明实际最小转弯半径约1.3米。这个数比我计算的理论值1.83米小不少跟轮胎侧偏、阿克曼修正都有关系。TEB里的min_turning_radius就可以设成1.2到1.3米而不是1.83米这样轨迹执行会更贴合。反过来如果实际测出来转弯半径比理论值大说明转向机构执行不到位可能是舵机限位、连杆松动或者PWM占空比校准的问题优先检查机械结构然后再看参数。速度标定方面我习惯在一条20米直道上让车跑到目标速度用秒表记录通过时间。多测三次取平均跟max_vel_x对比如果实际最高速度达不到设定值TEB再怎么调也追不上全局路径。4.3 常见问题与排查技巧实录下面这些问题是TEB阿克曼小车调参中常见且抓狂的高频问题我按“现象-原因-处理”的方式整理出来。这些基本都是我自己调车时碰过或帮别人远程看过的可以按图索骥。现象可能原因排查和解决方法小车行驶路线呈S形摆动轨迹权重或dt_ref设置不合理转向响应延迟严重先看dt_ref是否过大0.5适当减小到0.2-0.3再把weight_kinematics_forward调大到2-3抑制多余倒车最后降低max_vel_theta让转弯慢半拍到目标点后反复前后试探停不下来xy_goal_tolerance太小或倒车惩罚权重不够把weight_kinematics_forward上调适当放宽目标容差检查weight_optimization_time是否过小导致优化器找不到到达目标的稳定解轨迹明显绕过不该绕的障碍物路径绕远障碍物权重偏高或inflation_dist太大减小inflation_dist让TEB只在大障碍附近考虑膨胀把weight_obstacle从100降到50试试小车频频贴障碍物“擦边”障碍物权重偏低或min_obstacle_dist太小先提高weight_obstacle到150再把min_obstacle_dist从0.2提到0.3最后检查底盘的实际宽度footprint_model半径是否填小了遇到动态障碍物反应迟顿weight_dynamic_obstacle偏低或max_vel_x过高提高weight_dynamic_obstacle到80-100降低max_vel_x到0.4左右同时检查动态障碍物话题频率是否过慢转弯时轨迹向外侧漂移加速度限制过松或执行响应延迟降低acc_lim_x让车在弯前充分减速检查底盘是否有转向角速度限幅如果有的话把max_steering_angle对应的角速度标定出来全局路径通过狭窄门洞时规划失败min_turning_radius过大或inflation_dist过大尝试将min_turning_radius往下限方向修正缩小inflation_dist如果还不行检查门洞宽度与footprint_model半径的关系是否合理还有一些零碎但非常影响体感的小细节weight_shortest_path我一般设成0因为阿克曼小车有转弯半径约束强行追求最短路径会让轨迹计算出现“想切弯但切不过去”的抖动。feasibility_check_no_poses保留5即可太小会让优化器在很多无效的解上浪费时间。visualization只在调试阶段开实机长时间运行时关掉能减少话题带宽和可视化计算占用。5. 我对阿克曼TEB调参的整体感受TEB调参这个事最大的坑不是参数看不懂而是把一堆参数当成“灵敏度旋钮”去乱拧。我个人的经验是先把底盘运动学参数全部量清楚填对再把速度加速度限制卡准让TEB在物理可行域内找解最后才去调权重。只要前三步做扎实权重参数基本上在默认值附近微调就够了。真要说还有什么能少走弯路的建议就是尽量找一个小场地用纸箱把转角、窄门、贴墙边这些典型场景都摆一遍逐项跑。跑一次改一个参数记录现象再跑一次。TEB这玩意不是一次就调到位的但只要你用的参数有据可依整个收敛过程会非常快。希望这篇避坑指南能帮你们少烧几个舵机少磨几层轮胎。
阅读完成 · 觉得有帮助?
咨询建站