
手里有一台差速驱动机器人激光雷达扫出来的地图看着也凑合但导航就是跑不起来——要么原地转圈要么一头怼上障碍物要么在走廊里走S形。这种时候问题大概率不在算法本身而在于nav2_params.yaml里的参数根本没有被真正理解过。这篇就从头到尾拆一遍这个文件讲清楚每个关键参数背后到底在干什么。我这两年调试Nav2导航栈最大的感受是绝大多数导航问题都不是代码bug而是参数不合理。nav2_params.yaml是Nav2的参数总入口里面每个数字都直接影响全局规划、局部规划、代价地图、恢复行为等模块的最终表现。如果只是照着默认配置跑一遍十台车有九台跑不顺。这篇文章面向已经能用Nav2做基础导航、但想进一步优化效果的朋友。我会按实际调试顺序从YAML语法基础、文件骨架、核心参数拆解到常见问题和排查手法一层层把参数调优这件事讲透。很多人觉得YAML就是个“缩进格式”不值得专门学。但实际排查导航问题的时候YAML语法错误、类型不匹配、命名空间搞错这三类问题至少占掉我在群里帮人看问题的三分之一。所以第一节先把YAML本身说清楚这绝对是值得的投入。1. 从nav2_params.yaml说起YAML在导航系统里的真实位置1.1 为什么Nav2把所有参数都塞进YAML文件ROS2里每个节点都可以通过参数parameter控制运行行为。Nav2由一堆节点组成planner_server负责全局规划controller_server负责局部规划costmap_2d负责维护代价地图bt_navigator负责行为树调度recoveries_server负责恢复行为。这些节点加起来有上百个参数如果每次启动都在命令行里一个一个传基本不可维护。YAML方案的核心优势在于它天然支持层级结构能直接映射ROS2参数名中的命名空间。比如planner_server节点下的robot_base_frame在YAML里就是planner_server: ros__parameters: robot_base_frame: base_link这个结构直接对应/planner_server/robot_base_frame参数。在你启动导航的时候Nav2通过ros2 run nav2_util lifecycle_bringup或nav2_bringup里的launch文件把这些YAML内容加载进对应节点的参数服务器。整个过程本质上就是一个“批量灌参数”的操作。和TOML、JSON相比YAML的缩进和换行让层级关系一目了然。调试机器人导航的时候频繁改参数是常态YAML可以写注释、可以局部改一个数字而不影响其他结构这两个特性在实战中极其重要。1.2 YAML基础语法能读懂nav2_params.yaml就够了Nav2的YAML并不复杂真正需要掌握的语法点不超过五个键值对、嵌套层级、列表、注释、类型。键值对是最基础的冒号后面必须有空格。robot_radius: 0.20嵌套层级靠缩进表达Nav2统一用两个空格这点没有硬性规定但跟随官方风格最省心。local_costmap: ros__parameters: robot_radius: 0.20列表用短横线加空格开头。在Nav2里最典型的是observation_sources的多传感器配置。observation_sources: laser_scan_sensor laser_scan_sensor: topic: /scan data_type: LaserScan注释用#开头而且Nav2官方参数文件里注释非常丰富——这在调试时是重要参考不要删掉。类型问题是我见过最多的坑。YAML里的0.20是浮点数20是整数0.20是字符串。ROS2参数系统对类型敏感比如inflation_radius期望double你写成整数虽然也能加载但后续计算时的行为会和你预期不完全一致。更关键的是plugins这种参数期望是字符串数组如果格式写错节点直接启动失败。提示Nav2官方推荐用ros2 param dump node_name命令导出当前运行节点的真实参数生成的YAML格式一定是对的。后续你要自己写或改参数以param dump的输出为模板最稳妥。搞清楚这些基础语法再看nav2_params.yaml就不会犯低级错误。下面进入正题。2. nav2_params.yaml的骨架先看懂节点与命名空间2.1 顶层设计一个文件如何同时喂饱所有导航节点nav2_params.yaml的顶层是各个节点的名字每个节点名字下面必须有ros__parameters这一层这是ROS2参数加载的约定。没有这层参数根本不会被节点读取。一个典型的最小化骨架长这样planner_server: ros__parameters: expected_planner_frequency: 1.0 use_sim_time: false planner_plugins: [GridBased] controller_server: ros__parameters: controller_frequency: 20.0 controller_plugins: [FollowPath] local_costmap: local_costmap: ros__parameters: robot_radius: 0.20 inflation_radius: 0.55 global_costmap: global_costmap: ros__parameters: robot_radius: 0.20 inflation_radius: 0.55 bt_navigator: ros__parameters: default_bt_xml_filename: navigate_to_pose_w_replanning_and_recovery.xml recoveries_server: ros__parameters: costmap_topic: local_costmap/costmap_raw注意一个细节local_costmap下面嵌套了一层也叫local_costmap。这是因为costmap_2d节点在启动时ROS2参数会自动加上节点名作为前缀Nav2的launch文件里通常将这个节点的name设置为local_costmap导致在YAML里需要“双层嵌套”。这是Nav2新手最容易懵的地方。经常有人把local_costmap的参数直接写到顶层结果启动后节点报“parameter not found”。记住local_costmap和global_costmap这两个节点参数必须放在二级命名空间下面。如果你用ros2 param list看会发现所有costmap参数的前缀是/local_costmap/local_costmap/。2.2 TF树和坐标系参数导航调优的第一步不是速度是坐标系导航要跑起来坐标系必须先对。nav2_params.yaml里涉及坐标系的关键参数有三个robot_base_frame、global_frame、transform_tolerance。local_costmap: local_costmap: ros__parameters: global_frame: odom robot_base_frame: base_link transform_tolerance: 0.5global_frame在局部代价地图里通常是odom在全局代价地图里通常是map。robot_base_frame是机器人本体坐标系默认是base_link如果你的URDF里把body frame命名成了base_footprint这里一定要同步改否则代价地图就找不到机器人在哪里。transform_tolerance是TF缓存的容忍时间单位秒。它的含义是当TF查询时允许的时间戳最大偏差。数值太小会频繁报TF超时数值太大会让地图上的机器人位置滞后。常规范围0.1到0.5我做过的室内机器人一般设0.2到0.3室外大底盘车因为振动和轮子打滑导致TF跳变频繁会放宽到0.5。改完坐标系参数之后务必第一时间用rviz2打开TF显示确认map→odom→base_link→laser这条树是通的再去动后面的速度参数和规划参数。我见过太多人上来就调max_vel_x结果最后发现是TF没接通白折腾一整天。2.3 代价地图更新频率性能与安全的平衡点另一个容易被忽视的顶层参数是代价地图的更新频率。local_costmap: local_costmap: ros__parameters: update_frequency: 5.0 publish_frequency: 2.0update_frequency控制传感器数据多久被处理并写入代价地图一次publish_frequency控制代价地图的可视化数据多久对外发布一次。这两个参数经常被混淆但作用完全不同。update_frequency决定避障的实时性——激光雷达10Hz出数据你这里如果只有1Hz那机器人看到障碍物的反应就慢半拍。但频率也不是越高越好每次更新都要做raycasting和代价计算工控机性能不够的时候调高频率会导致CPU飙升、主循环卡顿、控制器响应反而变慢。我实测过一个差速机器人代价地图更新频率从2Hz拉到5HzCPU占用涨了大约20%但避障效果没有肉眼可见的提升从5Hz拉到10HzCPU直接顶满控制器开始频繁丢步。所以对于一般的室内机器人激光雷达10Hz的情况下update_frequency设在3~5Hz就很安全publish_frequency设在1~2Hz够用毕竟可视化不追求实时刷新。3. 核心调优参数逐个拆解代价地图、规划器、控制器与恢复行为3.1 代价地图参数膨胀半径和代价缩放如何决定生死线Nav2导航避障的本质是把传感器检测到的障碍物在二维栅格地图上“画”出来再根据机器人尺寸做膨胀处理最后让规划器在膨胀后的地图上寻路。这里最核心的两个参数是inflation_radius和cost_scaling_factor。local_costmap: local_costmap: ros__parameters: inflation_radius: 0.55 cost_scaling_factor: 3.0inflation_radius决定障碍物周围多大范围内会被标记为“危险区域”。它的数值直接决定机器人离墙、离货架能有多近。设得太小机器人路径会贴障碍物边缘走一旦里程计有偏差就撞上设得太大狭窄通道会被整个堵死路径规划直接失败。这里有个关键原理代价地图的膨胀区间是分级的。紧挨障碍物的栅格代价最高255致命往外按距离衰减衰减速度由cost_scaling_factor控制。cost_scaling_factor越大代价随距离衰减就越快膨胀区“外圈”会更稀疏越小危险区向外延伸的范围越广、梯度越平缓。有人问那我把cost_scaling_factor调到很大是不是既保留了安全距离又不至于堵死通道理论上可以但实际不行。膨胀梯度的存在意义是让规划器在做全局规划的时候有“从障碍物旁边平滑绕开”的余地。如果梯度过于陡峭规划器要么硬挤过代价边缘要么直接认为路径代价过高而放弃两种结果都是不稳定的运动。实操建议先量好机器人实际车体半径不是底盘半径是包含外部壳体的最大半径robot_radius设为这个值再加3~5cm余量。然后用一个比车体半径大15~20cm的数值作为inflation_radius初始值再根据实际窄道通行能力逐步缩小或扩大。差速驱动机器人我一般从车体半径的2~3倍开始试全向轮因为运动方向灵活、姿态可控可以适当小一点。obstacle_range和raytrace_range也是值得关注的参数。obstacle_range: 3.0 raytrace_range: 3.5obstacle_range表示传感器读数在多远距离内被当作障碍物写入代价地图raytrace_range表示传感器射线在多大范围内清除“风筝线”。注意这个“清除”的作用对于移动的人或临时出现的障碍物代价地图需要把它们留下的痕迹逐渐擦掉raytrace_range必须大于等于obstacle_range否则传感器检测范围之外的旧障碍永远消不掉导航规划会因为“幽灵障碍”而在空旷区域绕路。3.2 全局规划器参数从GridBased到SMAC的选型与权重Nav2的全局规划器通过planner_plugins参数选择。默认配置是GridBased对应NavFn规划器也就是经典的A*或Dijkstra。更进阶的选择还有SmacPlannerHybrid、SmacPlannerLattice等它们支持曲率约束适合阿克曼底盘的机器人。planner_server: ros__parameters: planner_plugins: [GridBased] GridBased: plugin: nav2_navfn_planner/NavfnPlanner tolerance: 0.5 use_astar: true allow_unknown: trueNavFn参数里use_astar: true表示用A搜索false则退化为Dijkstra。在多数室内场景A效率高得多但如果地图里有大量不可通行的窄缝A可能因为启发式函数不准确而绕远路这时候Dijkstra的“膨胀式”搜索反而能带来更平滑的路径。不过这种情况很少见默认A即可。tolerance这个参数非常实用——它允许终点附近多大半径内算作“到达目标”。如果目标点稍微陷在障碍物边缘里没有tolerance的话规划直接失败机器人停在原地不动。0.5米是一个合理的默认值但在一些需要精确停靠的任务里可以单独把任务层用别的机制处理导航层的tolerance别小于0.2太夸张。如果使用SMAC规划器需要调的核心参数完全不同。SmacPlannerHybrid: plugin: nav2_smac_planner/SmacPlannerHybrid minimum_turning_radius: 0.20 max_planning_time: 2.0 lookup_table_size: 20.0minimum_turning_radius对应机器人的最小转弯半径这个值必须从底盘规格里查差速驱动机器人是0阿克曼车要看转向机构极限。设得比实际偏大规划器会绕不必要的远路设得比实际偏小规划出的路径机器人根本执行不了。SMAC系列规划器比NavFn多了一个“搜索耗时”问题所以max_planning_time设置很关键超过这个时间还没找到路径就放弃。室内环境2秒够用如果你发现经常规划失败可以先看这个时间是不是被卡住了再考虑地图膨胀参数是否合理。3.3 局部控制器参数DWB和TEB谁更配你的底盘局部控制器负责把全局路径转化为实际速度指令。Nav2官方默认是DWBDynamic Window Approach的Nav2版可选的有TEBTimed Elastic Band和RPP。DWB的参数集中在FollowPath插件下。controller_server: ros__parameters: controller_frequency: 20.0 FollowPath: plugin: nav2_dwb_controller::DWBLocalPlanner min_vel_x: 0.0 max_vel_x: 0.26 min_vel_y: 0.0 max_vel_y: 0.0 max_vel_theta: 1.0 min_speed_xy: 0.0 max_speed_xy: 0.26差速机器人的max_vel_y必须设为0全向轮机器人则要按底盘能力设置。max_vel_theta控制最大旋转角速度这个设太大会导致机器人转向时甩尾设太小在需要原地掉头的时候会显得特别磨叽。我自己调试差速底盘常用的是0.8到1.2 rad/s具体看电机性能和车体稳定性。DWB的轨迹评分由Critic权重决定这部分是调优重头戏。FollowPath: critics: [RotateToGoal, Oscillation, BaseObstacle, GoalAlign, PathAlign, PathDist, GoalDist] BaseObstacle: scale: 0.02 PathAlign: scale: 32.0 PathDist: scale: 32.0 GoalAlign: scale: 24.0 GoalDist: scale: 24.0这些critic权重直接影响机器人运动倾向PathDist权重越大机器人越严格沿全局路径走路径偏离惩罚大GoalDist权重越大机器人越倾向直接冲向目标点而不太在意是否偏离路径。BaseObstacle是障碍物代价scale设置太大会导致机器人离障碍物远远的就刹停太小又可能贴着障碍物走。我遇到过最典型的DWB问题是“机器人在障碍物前疯狂抖动但不前进”。排查下来是PathDist权重太大、机器人为了贴合全局路径在路径转弯点附近反复横摆。最后把PathDist从32降到24GoalDist从24提到32抖动立刻消失。TEB是另一个常用局部控制器参数逻辑和DWB差异很大。FollowPath: plugin: nav2_teb_controller/TebController dt_ref: 0.3 max_vel_x: 0.26 max_vel_theta: 1.0 min_obstacle_dist: 0.20 penalty_epsilon: 0.1TEB的核心思路是“时间弹性带”它会把整段路径在时间维度上做优化。dt_ref是轨迹离散化的参考时间间隔值越小轨迹越精细但计算量越大、越容易震荡。min_obstacle_dist是TEB眼中的最小安全距离设太小容易撞设太大又在窄道里无法规划。TEB对非完整约束底盘阿克曼支持更好DWB则对差速底盘更直观。我的建议差速车优先DWB阿克曼车优先TEB全向轮看个人习惯。3.4 恢复行为参数机器人卡住之后怎么办Nav2有一个专门处理“卡住”的模块——recoveries_server行为树navigate_to_pose_w_replanning_and_recovery.xml会在规划失败或控制失败时触发恢复行为。recoveries_server: ros__parameters: costmap_topic: local_costmap/costmap_raw behavior_plugins: [spin, backup, wait] spin: plugin: nav2_recoveries/Spin backup: plugin: nav2_recoveries/BackUp wait: plugin: nav2_recoveries/Waitspin是原地旋转适合机器人被前方障碍物挡住但两侧有空间的情况backup是后退适合卡在通道里、前方障碍物离得太近的情况wait是原地等待适合动态障碍物可能自行离开的场景。这三个插件的执行参数旋转速度、后退距离、等待时间在行为树XML里控制在YAML里主要配置插件类型和关联的costmap话题。这里的一个调优技巧是行为树文件navigate_to_pose_w_replanning_and_recovery.xml可以从nav2_bringup里拷贝出来自己修改恢复行为的次数和顺序。比如默认是spin→backup→spin你可以改成backup→spin→backup因为有些场景后退比旋转更容易脱困。4. 实操调优流程从默认参数到能跑再到跑得稳4.1 调优前的三个前提少一个都白调我见过太多人跳过基础检查直接调参数最后陷入“改参数→症状变一个→再改”的无限循环。在动nav2_params.yaml之前必须确认三件事TF树完整、里程计可靠、静态地图质量合格。TF树的检查方法很简单ros2 run tf2_tools view_frames生成PDF看map→odom→base_link→laser_frame是否全部连通且频率正常。如果TF断链所有代价地图都不会正常工作调什么都白搭。里程计的可靠性可以从/odom话题观察让机器人原地转一圈看odom的角速度累积是否接近2π。如果差得离谱检查轮子编码器方向、轮距参数、是否打滑。里程计是所有局部规划和代价地图配准的基准它不准的话任何速度参数调优都是无根之木。静态地图质量也直接影响参数调优的效果。用SLAM建图时地图存在重影、空洞、多余噪点后面导航参数再优化也是勉力补救。建图时把激光雷达数据检查好、轮式里程计标定好出来的地图是干净的导航调参才谈得上有意义。4.2 从零开始的一套现场调优动作确认三个前提之后我有一套固定的调优流程出差调试都是按这个顺序走能快速定位问题。第一步先让机器人原地旋转看局部代价地图上的障碍物是否稳定显示。执行ros2 topic echo /local_costmap/costmap确认数据有输出同时在rviz里打开Local Costmap图层肉眼确认激光打在障碍物上时代价地图的红色区域能实时出现。第二步给一个近距离目标点做全局规划用rviz的“2D Goal Pose”功能发布目标观察/plan话题是否输出合理路径。如果规划失败查看planner_server的日志多半是目标点在膨胀区域内调大tolerance或者缩小膨胀半径。第三步用ros2 action send_goal方式执行导航而不是直接用rviz点目标。这种方式方便在终端里看控制器的反馈可以实时打印出机器人速度指令和当前位置误差。第四步观察/cmd_vel话题发布的速度值对比机器人实际速度。如果发布速度和实际速度偏差大检查底层电机驱动、PID参数、加速度限制这不是nav2_params.yaml能解决的问题。调参本身建议一次只改一个参数改完跑一次完整导航记录效果。我习惯用一个表格记录修改时间、修改参数、修改前现象、修改后现象、是否保留。不然改多了根本回忆不起来哪个参数发挥了作用。4.3 用ros2命令行工具验证参数是否真正生效每次改完nav2_params.yaml都需要重启导航相关节点才能重新加载参数。很多人在这个环节犯迷糊改了文件但没重启然后发现“改了没用”。重启后第一件事用ros2 param list查看节点下所有参数是否和配置文件一致。ros2 param list /planner_server ros2 param get /planner_server GridBased.toleranceros2 param get只能查运行时参数值它显示的值就是节点实际加载的值。如果和YAML里写的不一致检查YAML路径和命名空间是否写对了。另一个实用工具是ros2 param dump /controller_server它会把节点当前所有参数导出为YAML格式。当你不确定Nav2官方默认参数长什么样、或者想检查节点加载了哪些参数的时候直接dump一份出来对照看比翻源码方便得多我调试时基本随身带着这个命令。提示use_sim_time参数在nav2_params.yaml里有出现这个参数必须和你的运行环境匹配。真机运行时设为false仿真运行时设为true。如果真机上误设成了true整个导航系统的时钟会乱掉TF和时间戳对不上现象很奇怪检查这个参数往往能救命。5. 常见问题与排查技巧实录5.1 YAML格式错误mapping values are not allowed in this context这是我被问得最多的报错之一。完整报错通常是yaml: mapping values are not allowed in this context这个错误的本质是YAML解析器在某个位置期待一个缩进层级但遇到了另一个冒号。最常见原因是参数名或值的冒号后面没加空格比如inflation_radius:0.55 # 错误 inflation_radius: 0.55 # 正确第二个常见原因是键名里有/或:等特殊字符但没有加引号。Nav2的某些插件参数名里包含斜杠比如GridBased: plugin: nav2_navfn_planner/NavfnPlanner这里如果plugin的值漏了引号双冒号或斜杠结构就可能让YAML解析器晕掉。第三个原因是缩进层级错误。YAML对缩进极其敏感同一个层级必须缩进一致不能混用空格和Tab。Nav2官方的参数文件用了大量嵌套我看着有空格的缩进和无空格的缩进混在一起就会报解析错误。遇到这种报错我建议用VS Code的YAML插件或Python的yaml.safe_load()直接加载文件报错信息会精确指出第几行比launch启动日志里的报错好定位得多。5.2 参数加载了但不生效可能是生命周期节点还没激活Nav2的节点都是生命周期节点LifecycleNode启动后要经过未配置unconfigured、未激活inactive、激活active三个阶段参数才能真正参与运行。有时候你改了YAML、重启了节点、ros2 param get查到的参数也确实更新了但导航行为没变化——这种情况要检查节点生命周期状态ros2 lifecycle get /controller_server执行后会输出当前状态如果停留在inactive说明节点没完成激活流程参数虽然加载了但没有真正被主循环使用。正常情况下Nav2的launch文件会自动处理生命周期转换但如果用了自定义launch启动方式容易漏掉这一步。此外ros2 param set可以运行时直接改参数但代价地图相关的参数改了之后代价地图不会自动重新构建需要清空或重启。运行时调参在测试阶段好用但最终交付时一定要把确认好的参数写回nav2_params.yaml避免每次启动都要手动set。5.3 机器人绕远路、原地打转、抖动按现象反查参数这里整理一个我常用的现象-参数映射速查表按出现频率排序现象优先排查的参数常见原因全局路径贴墙太近全局代价地图的inflation_radius膨胀半径偏小路径紧贴障碍物全局规划频繁失败tolerance、inflation_radius目标点在膨胀区内或膨胀过大堵死通道局部路径抖动DWB的PathDist/GoalDist权重路径跟随权重过大转弯时过度修正机器人绕弯时撞到内侧局部代价地图的cost_scaling_factor代价衰减太快内侧危险区没被有效标记机器人走S形max_vel_theta、控制频率转向速度过快控制器回调频率不足原地打转不前进行为树中的恢复行为执行顺序每次前进失败都触发旋转陷入循环到达目标后停不准goal_checker相关参数目标检查半径过大或过小最后一行的goal_checker参数容易被忽略它在controller_server配置里controller_server: ros__parameters: goal_checker_plugins: [general_goal_checker] general_goal_checker: plugin: nav2_controller::SimpleGoalChecker xy_goal_tolerance: 0.25 yaw_goal_tolerance: 0.25xy_goal_tolerance是平面位置到达判定的容差yaw_goal_tolerance是姿态角的容差。机器人到目标点附近就停下来不再调整很多时候不是控制器问题而是goal_checker提前认定“到位了”。5.4 不要忽视CPU占用参数调优也有性能天花板Nav2在树莓派、Jetson Nano这类低性能板子上跑的时候参数调优的约束条件和工控机完全不同。我实测过Jetson Nano上跑Nav2代价地图更新频率3HzSMAC规划器DWB控制器CPU占用已经到75%左右。这时候再调高任何频率参数系统就会开始卡顿控制器响应断断续续导航效果急剧恶化。低性能平台上的调优策略应该是保证基本避障安全减少不必要的计算。具体做法包括update_frequency维持2Hz即可不做高频率可视化。publish_frequency降到0.5Hz甚至0.1Hz可视化信息不参与决策纯粹是给rviz看的。全局规划器优先用NavFn而不是SMAC规划耗时和CPU占用都低很多。关闭不必要的costmap图层比如keepout_filter、prohibition_layer这些图层功能很实用但在低性能平台上要按需开启。我之前调试过一个室内巡检机器人工控机是老款Atom处理器Nav2默认参数跑起来CPU直接75%以上导航路径规划要十来秒。把代价地图更新频率降到2Hz、publish_frequency降到0.2Hzplanner换成NavFn之后CPU占用降到40%左右路径规划时间也压到了两三秒。性能优化和导航效果的权衡没有标准答案只能按实际平台一个一个参数试。这里再次体现YAML适合调试的优势——改一个数字、重启、测试整个闭环只需要两分钟。5.5 现场调试的经验笔记参数调优是个细致活调了两年Nav2我总结出一条核心经验nav2_params.yaml不是配置完就一劳永逸的文件它是机器人导航系统的“性格设定”。同一台机器在走廊很宽的大厅里和货架很密的仓库里参数最优解完全不同。每次到新场地调试我第一件事是看地图通道宽度、障碍物密度、地面平整度。通道宽就用稍大一点的inflation_radius保证安全通道窄就调小inflation_radius确保能通过。这个“先看地图再定参数”的习惯帮我避免了很多无用功。第二个经验是一定要养成“一次只改一个参数”的习惯。人的直觉很容易在多个参数同时变化时误判因果关系特别是机器人的运动表现本身就带随机性。我见过同事一口气改了6个参数出了问题完全不知道回退到哪个版本最后只能重置所有配置从头调。第三个经验是每个调好的参数组合都要做好注释和备份。# 2024-03-12 现场实测调整 # 仓库A通道宽度1.2m需要缩小inflation_radius才能通过 inflation_radius: 0.35 # 仓库B通道宽度2m以上保留inflation_radius 0.55 # inflation_radius: 0.55这样即使过了一个月看到参数文件还能回忆起当时的调参背景。导航调优是门经验活这些记录就是你的经验库。