ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零跑通NuPlan自动驾驶仿真工具链:环境搭建与规划器调试实战

从零跑通NuPlan自动驾驶仿真工具链:环境搭建与规划器调试实战 写这篇笔记之前我先说个背景我大概花了两周时间才把Nuplan-devkit从零跑通中间重装了三次环境差点因为protobuf版本问题把Conda环境整个删掉。如果你也是第一次接触这套自动驾驶仿真工具链希望我这篇实战笔记能让你把这两周压缩到两天。这篇内容我会先讲清楚NuPlan到底是干什么的然后完整记录环境搭建、mini数据集准备、PyCharm调试配置以及第一次跑通闭环仿真的全过程。适合自动驾驶规划方向的研究生、算法工程师以及准备复现规划类论文但卡在环境这一步的同行。跟着操作下来你应该能拥有一个可以跑baseline、写自定义规划器的仿真环境。1. 为什么是NuPlan它解决的痛点和边界在哪1.1 先用一句话说清楚NuPlan是什么NuPlan是Motional联合MIT等机构推出的自动驾驶运动规划数据集和基准配套的Nuplan-devkit提供了一整套数据读写、仿真、评估工具。和常见的感知类数据集不同NuPlan的重点是规划planning环节——也就是给定自车状态、障碍物轨迹、地图信息后决策模块应该输出什么样的未来轨迹。它和CARLA、SUMO的区别在于CARLA更多是完整的仿真器提供传感器模拟和物理渲染SUMO是微观交通流仿真专注于路网和车辆交互而NuPlan是用真实采集的大规模人类驾驶数据回放场景并在这个基础上做闭环仿真评测。换句话说NuPlan的场景全部来自真实道路采集而不是人工搭建的虚拟路网因此场景的真实性和复杂度都更贴近实际。1.2 Nuplan-devkit的设计思路值得先说透devkit的核心抽象有四个数据库database、场景scenario、仿真器simulation、评估器metrics。数据库负责读取和缓存场景片段每个场景包含自车轨迹、周边车辆/行人轨迹、地图和静态信息仿真器负责把规划器的输出轨迹放到仿真世界里推进并让周边动态物体按照数据回放的方式运动评估器则根据碰撞、可行驶区域、舒适性、效率等维度给规划结果打分。这个设计的好处是解耦。你可以只替换规划器模块而不用动仿真主流程也可以用同一套场景批量跑不同baseline。坏处是理解这套抽象需要时间而官方文档的示例相对简略很多东西要靠读源码才能明白这也是我写下这篇笔记的原因之一。1.3 谁适合用NuPlan谁其实不太适合如果你的目标是验证一个新的运动规划算法或者想找一个能公平对比多种规划方案的benchmarkNuPlan非常合适。它已经内置了IDM、PDM等多个baseline你可以在同一套场景上一键对比。但如果你是初学者还没理清规划、预测、控制三者的边界或者你只是想快速做一个好看的三维仿真视频发演示那CARLA可能更合适。NuPlan的官方仿真器并不强调传感器仿真和物理渲染它给的评估是数值指标和简单的鸟瞰图可视化不是高保真画面。这两点判断清楚能帮你省下不少时间。2. 环境搭建全流程我把版本和依赖一次说清2.1 前置条件Python版本、Conda、显存官方要求的Python版本是3.8到3.10之间我自己用的是3.8.13整体最稳定。推荐用Anaconda或Miniconda创建独立环境不建议直接用系统Python因为NuPlan依赖的torch、protobuf、xgboost等包版本比较敏感直接装到系统环境里很容易污染其他项目。显存方面如果你只是跑IDM、PDM这类baseline并且只加载mini数据集4GB显存完全够用。但如果要加载完整数据集或者训练学习类规划器建议至少12GB以上显存并且要有足够的内存32GB以上保险。我遇到过内存只有16GB的机器在加载长场景时直接OOM的情况后面细说。2.2 创建虚拟环境和安装依赖先创建环境激活conda create -n nuplan python3.8 -y conda activate nuplan然后安装基础依赖建议按顺序装pip install numpy protobuf3.20.3 xgboost torch torchvision pytorch_lightning pip install pandas xarray matplotlib tqdm scikit-learn ipykernel notebook这里我特别提一下protobuf版本。NuPlan对protobuf的版本要求比较严格我当时直接装最新版4.x会导致部分序列化接口报错后来锁定3.20.3才解决。这个坑在官网issue里也出现过多次所以建议先固定版本。2.3 安装nuplan-devkitpip和源码两种方式官方推荐从源码安装这样可以获得最新的功能和完整的示例脚本git clone https://github.com/motional/nuplan-devkit.git cd nuplan-devkit pip install -r requirements.txt pip install -e .如果只是想快速体验Python API也可以直接pip install nuplan-devkit不过源码安装后你可以直接运行仓库里的nuplan/planning/script/run_simulation.py等脚本也方便改源码加自定义log所以我建议还是按源码方式装。安装过程如果网速慢可以把pip源换成国内镜像速度会快很多。注意安装依赖时不要一次性把requirements.txt里所有包都无脑装完先装核心的跑通一个小demo后再回头补。否则你会在无数个版本冲突里迷失方向。3. 数据准备mini数据集是你最好的朋友3.1 下载前必须知道的目录规划NuPlan的原始数据量非常大完整数据集包含波士顿、拉斯维加斯、新加坡多个城市的数百小时驾驶数据下载体积以TB计。对于搭建环境和验证流程来说官方mini数据集就够了它包含挑选出来的典型场景总共约几十GB还算可控。下载之前先在本地规划好目录结构建议这样组织/data/nuplan/ ├── nuplanet-v1.1/ # 完整数据集如果你以后想下载 ├── nuplan-v1.1/ │ ├── mini_set/ # mini数据集 │ ├── map/ # 地图数据 │ └── sensor_blobs/ # 传感器数据缓存部分场景有 └── exp/ # 实验输出根目录3.2 设置环境变量这一步别偷懒NuPlan的运行依赖两个核心环境变量NUPLAN_DATA_ROOT和NUPLAN_EXP_ROOT。另外还有一个NUPLAN_MINI变量在部分脚本中用于指定mini数据集的路径。在Linux下可以写入~/.bashrcexport NUPLAN_DATA_ROOT/data/nuplan export NUPLAN_EXP_ROOT/data/nuplan/exp export NUPLAN_MINI/data/nuplan/nuplan-v1.1/mini_set设置后记得source ~/.bashrc。这一步极其重要如果不设置运行脚本时会报找不到数据集的错误而错误信息往往不够直观容易让人误以为是安装问题。3.3 下载后的校验和常见问题下载完mini数据集后不要急着运行先检查目录完整性。官方压缩包通常自带MD5校验文件建议校验一遍再解压。解压时用tar -xzf nuplan_mini_set.tar.gz -C /data/nuplan/nuplan-v1.1/我当时遇到的第一个诡异问题是解压到一半磁盘空间不足导致后续加载场景时莫名其妙报错。所以解压前一定先用df -h确认剩余空间mini集加上地图数据至少需要40GB空间。4. PyCharm配置技巧把调试效率真正拉满4.1 用Conda环境关联项目解释器PyCharm支持直接识别Conda环境。打开PyCharm进入File - Settings - Project - Python Interpreter点击右侧齿轮图标选择Add Interpreter - Conda Environment然后选择Existing environment在列表中找到你创建的nuplan环境。如果你在终端已经创建好了环境但在PyCharm的下拉列表里找不到可以手动浏览到Conda安装目录下的envs/nuplan/bin/python比如~/miniconda3/envs/nuplan/bin/python关联成功后PyCharm会开始索引所有依赖包这个过程可能持续几分钟耐心等它跑完即可。索引完以后代码补全、跳转到定义这些功能才能正常工作。4.2 配置Run Configuration的环境变量这是PyCharm配置中最关键的一步。虽然你在~/.bashrc里设置了环境变量但PyCharm运行时未必会读取尤其是当你通过GUI启动PyCharm而不是从终端启动时。所以最稳妥的做法是把环境变量直接写进Run Configuration。在PyCharm右上角选择Edit Configurations新建一个Python运行配置然后在Environment variables栏里逐项添加NUPLAN_DATA_ROOT/data/nuplan NUPLAN_EXP_ROOT/data/nuplan/exp NUPLAN_MINI/data/nuplan/nuplan-v1.1/mini_set这样你点击运行按钮时脚本就能正确找到数据。如果你以后要换机器或者改数据目录只需要在这里改一遍不用回终端重新export。4.3 调试模式下的断点技巧NuPlan的仿真主流程run_simulation通常要跑很多个场景如果直接在整个脚本开头打断点你会发现IDE在数据加载阶段就卡了很久。我的建议是先不加断点跑一次确认环境OK之后再在自定义规划器的核心方法里加断点。比如你写了一个继承AbstractPlanner的类重写了compute_planner_trajectory方法那就把断点加在这个方法第一行配合PyCharm的Step Over和Evaluate Expression你可以实时查看当前自车状态、周围障碍物轨迹、地图属性等变量。这个体验比在终端print日志高效太多。4.4 顺手解决PyCharm里CSV文件显示异常的问题NuPlan的实验结果会输出很多CSV文件默认在PyCharm里双击CSV文件它只会以纯文本形式打开不会按表格展示。解决方法是右键CSV文件选择Open In - Editor然后在弹出的标签页右键点击Open as - TablePyCharm就会以表格形式渲染。如果你经常需要看这些结果建议在File - Settings - Editor - File Types里把CSV关联到Text类型再配合插件CSV Plugin使用体验会更好。5. 第一次跑通从最小脚本到IDM基线5.1 用Python脚本验证安装是否成功在你尝试运行官方复杂脚本之前先跑一个最简单的导入测试确认环境安装没问题import nuplan from nuplan.planning.scenario_builder.nuplan_db.nuplan_scenario_builder import NuPlanScenarioBuilder print(nuplan import ok)如果这一步能正常输出说明核心包和依赖已经装好。如果报错ModuleNotFoundError优先检查PyCharm的解释器是否真的选到了nuplan环境而不是Python系统默认环境。5.2 运行官方run_simulation脚本跑IDM基线官方仓库里最核心的脚本是nuplan/planning/script/run_simulation.py。在终端或PyCharm里这样运行python nuplan/planning/script/run_simulation.py \ --grouptest \ --job_nameidm_baseline \ --experiment_namemy_first_run \ --scenario_buildernuplan \ --scenario_filtermueller_training1500 \ --planneridm_planner \ --simulation_callbackserialize_scenario这里的scenario_filter需要在配置文件中预先定义好告诉脚本要加载哪些场景。官方库里预设了一些filter比如mueller_training1500表示从指定数据集切片中挑选1500个训练场景。第一次跑建议用更小的过滤条件比如mueller_train1500中只取前5个场景可以在scenario_filter参数中传入--scenario_filternuplan_mini之类的配置并配合--split_sizes或--num_scenarios限制数量。跑完以后实验结果会输出到NUPLAN_EXP_ROOT下对应的目录包括每个场景的指标JSON文件和可视化结果。如果你看到类似Successfully serialized scenarios的日志说明整个闭环仿真链路已经通了。5.3 看懂运行日志里的关键信息运行过程中会滚动输出很多日志重点看这几个关键信息Loading scenarios...表示正在加载场景数据这里会消耗比较多内存。Running simulation...表示仿真正在推进每一帧会更新自车轨迹。Metric computation...表示评估器正在计算指标。Saving results...表示结果保存路径和保存状态。如果日志在某个阶段卡住超过十几分钟大概率是数据加载或评估器计算过慢。这时候先确认机器内存是否充足再确认你选的场景数量是否过大。mini数据集里有些长场景包含上千帧跑起来确实慢瓶颈通常不在规划器推理而在数据回放和序列化环节。6. 常见报错与排查实录直接抄作业6.1 protobuf版本不一致导致序列化报错这是我在搭建过程中遇到最频繁的问题报错通常长这样TypeError: Descriptors cannot not be created directly...原因是NuPlan内部使用的Google protocol buffers版本与protobuf库不兼容。解决方法是固定protobuf版本pip install protobuf3.20.3如果你用的是Python 3.10以上版本这个固定版本可能会提示不兼容这时候建议降到Python 3.8或者找对应NuPlan版本兼容的protobuf版本比如3.20.x系列。这个问题的根源是不同protobuf版本的API差异较大NuPlan依赖较老的API实现。6.2 内存不足OOM导致进程被杀NuPlan加载场景时会把一段连续时间的场景数据全部放入内存如果机器内存不够进程会被系统直接kill。我碰到过一次加载1500个场景时内存用了90GB直接把服务器干挂了。对策有三个一是优先用mini_set小场景二是减少批处理场景数量三是增加机器的swap空间或者购买更大内存。实际排查时用htop观察内存增长趋势如果接近机器总内存的80%就赶紧缩小场景集。6.3 找不到数据集或路径错误如果你看到类似FileNotFoundError: No such file or directory: /data/nuplan/...九成是环境变量没生效或者PyCharm里没配置Run Configuration的环境变量。在PyCharm里运行时优先检查Run Configuration在终端运行时用echo $NUPLAN_DATA_ROOT确认变量是否真的存在。还有一种情况是数据集解压后的路径多套了一层目录比如解压出来是/data/nuplan/nuplan-v1.1/nuplan-v1.1/mini_set这种多套一层的问题只要调整目录结构即可。6.4 场景串行化卡住和残留进程如果你中断了一次任务然后马上再跑新的实验可能会发现端口被占用或者缓存目录残留。可以用以下命令清理残留的进程pkill -f run_simulation.py另外NuPlan会在实验目录下生成大量中间缓存文件建议定期清理NUPLAN_EXP_ROOT下不再需要的旧实验目录否则占满磁盘后新的实验会莫名失败。7. 在PyCharm里自定义一个最简单的规划器7.1 继承AbstractPlanner写自己的类NuPlan的核心规划器接口是AbstractPlanner。一个最简单的规划器只需要实现两个方法name()和compute_planner_trajectory()。前者返回规划器名称后者接收当前仿真状态和意图返回一个轨迹对象。下面是一个极小示例它只是让自车保持当前速度直线行驶from typing import List import numpy as np from nuplan.planning.simulation.planner.abstract_planner import AbstractPlanner from nuplan.planning.simulation.trajectory.trajectory import Trajectory class SimpleStraightPlanner(AbstractPlanner): def name(self) - str: return simple_straight_planner def compute_planner_trajectory(self, current_input): # 获取当前自车状态 ego_state current_input.history.ego_states[-1] x, y, heading ego_state.rear_axle.x, ego_state.rear_axle.y, ego_state.rear_axle.heading speed ego_state.dynamic_car_state.speed # 生成一条3秒、每秒4个点的匀速直线轨迹 dt 0.25 num_pts 12 waypoints [] for i in range(num_pts): t (i 1) * dt wx x speed * t * np.cos(heading) wy y speed * t * np.sin(heading) waypoints.append((wx, wy, heading, speed)) return Trajectory(waypoints)这段代码虽然简单但它已经把NuPlan轨迹输出的最基本格式跑通了。你再把它注册到run_simulation脚本的planner列表里就可以拿mini数据集做闭环评测然后和IDM的结果对比指标。7.2 在PyCharm里配置调试并单步跟踪把这个新规划器类放到项目里后在PyCharm的Run Configuration里选择run_simulation.py作为入口脚本参数填你之前跑IDM时那套参数然后在这几处打上断点compute_planner_trajectory第一行确认每个仿真帧都调用了你的规划器Trajectory(waypoints)调用前确认轨迹点数量、坐标是否符合预期在score或metric计算代码里断点观察不同指标是如何计算的配合PyCharm的Watches面板你可以把speed、heading、waypoints这几个变量实时加到观察列表里。跑闭环仿真时每一帧都会重新进入断点如果你不想每一帧都停下可以给断点加条件比如当speed 10时再暂停大幅减少调试等待时间。7.3 用NuBoard看你的规划器跑出来的结果NuBoard是NuPlan自带的可视化面板可以加载实验输出目录在浏览器里查看场景回放和规划轨迹。基本用法python nuplan/planning/script/run_nuboard.py \ --experiment_namemy_first_run \ --grouptest启动后访问本地端口默认5006在页面里选择实验和场景你就能看到自车轨迹、目标物体位置变化以及地图背景。这一步非常适合验证自己的规划器是不是在“瞎跑”也能快速定位是算法逻辑问题还是数据加载问题。8. 关于PyCharm的一些零碎心得8.1 推荐用专业版但别折腾激活热词里看到很多人搜PyCharm激活我的建议是如果你是学生或有教育邮箱直接去JetBrains官网申请免费的教育授权这是最稳妥合规的方式。如果是个人学习社区版功能其实够用了NuPlan开发不依赖Pro版的专属能力只是远程开发和数据库工具会受限。我平时主力开发还是在社区版上做的配合几个常用插件完全够用。8.2 善用PyCharm的终端和执行环境PyCharm自带Terminal面板但它默认可能不会加载你的~/.bashrc设置导致每次都要重新export环境变量。解决方案是在PyCharm的Settings - Tools - Terminal里设置Shell路径为/bin/bash --login这样每次打开终端都会加载bash的登录脚本。8.3 大工程目录索引慢怎么办NuPlan源码量不算小第一次索引可能要几分钟。如果你觉得PyCharm卡顿可以在Project Structure里把nuplan目录下你不需要修改的子目录如visualization中的前端资源标记为Excluded减少索引范围。9. 我对NuPlan这套工具链的最终印象把NuPlan从零跑通之后我的最大感受是它不是一个开箱即用的黑盒工具而是一套需要你花时间去理解其设计哲学的框架。但一旦理解了它的场景、仿真、评估三层结构后续做算法实验会非常顺手。如果你打算长期做规划方向的研究建议不要只停留在跑通IDM这一步试着按第7节的方法写一个最简单的自定义规划器然后逐步替换更复杂的决策逻辑。这比一直用现成baseline跑数据能学到更多。最后分享一个我踩过多次的小坑每次跑实验之前先确认实验输出目录是空的或者给新的实验起新的名字否则旧结果和新结果混在一起后面复盘时你会欲哭无泪。我用nuplan-devkit这一个月几乎一半时间花在跑实验、看结果、定位问题这三件事上但把这些前置工作理顺之后后面的效率是真的高。
返回列表