ARTICLE DETAIL

资讯详情

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

用Python打通Carla与Apollo:自动驾驶联合仿真环境搭建与实操指南

用Python打通Carla与Apollo:自动驾驶联合仿真环境搭建与实操指南 第一次把Carla和Apollo打通的时候我盯着DreamView界面里那辆车的轨迹线看了半天差点忘了它跑在一台纯模拟环境里。如果你正在做自动驾驶相关的开发或测试一定也被同样的问题困扰过真车测试成本高、周期长纯算法仿真又离真实传感器数据太远。Carla提供逼真的场景和传感器仿真Apollo提供从感知到规划的完整算法栈而Python恰好是连接这两者最顺手的那双手。这篇文章我会从环境搭建、数据链路原理、实操步骤到常见坑点完整梳理一套用Python玩转Carla-Apollo联合仿真的方案适合正在入门自动驾驶测试、或者想在实验室里搭一套回归测试平台的工程师参考。1. 联合仿真前必须想清楚的事架构、版本与选型1.1 为什么偏偏是Carla Apollo Python先聊聊这套组合的由来。Apollo本身是一个完整的自动驾驶操作系统感知、定位、预测、规划、控制全都有但它的模拟能力相对有限自带的SimControl更多是逻辑仿真传感器数据不够真实。Carla则反过来它出身于视觉仿真研究基于虚幻引擎能给你高质量的摄像头画面、激光雷达点云、毫米波雷达回波甚至雨天、夜间、光照变化的连续模拟。但Carla本身不自带成熟的自动驾驶决策算法它默认的Autopilot本质上是个简单的控制器。两套框架正好互补Carla负责让车“看见世界”Apollo负责让车“思考并行动”。而Python在这里的价值就很有意思了——Carla提供了一整套Python API可以用来创建车辆、行人、传感器、设置天气、控制交通流等于说整个测试环境的“上帝之手”是Python写的而Apollo的CyberRT框架虽然主要面向C但其模块配置、数据调试、场景管理同样绕不开Python脚本。联合仿真里最关键的桥接层也完全可以用Python作为原型实现。可以说这套技术选型覆盖了环境搭建、数据流转、场景编排、结果分析的全链路。1.2 版本匹配是头号大坑我必须把版本匹配放在最前面因为这真的是我踩过最深的一个坑。Carla和Apollo都有自己的版本节奏而且它们之间没有官方的强绑定关系很多版本组合根本跑不通。根据社区里的常见实践比较稳的组合是Apollo 6.0配Carla 0.9.11或0.9.12Apollo 7.0以上版本可以尝试更新一些的Carla版本但适配工作量和踩坑概率会明显上升。为什么版本会影响这么大关键在桥接层。Carla端的传感器数据和车辆控制指令要通过桥接层转发给Apollo而Apollo各版本的Channel定义、消息格式、坐标系约定都有差异。比如Apollo 6.0的感知模块订阅的是/apollo/sensor/lidar/compensator/PointCloud2这样的Channel7.0和8.0则对消息类型做了调整。桥接层必须和Apollo的消息定义严格匹配否则数据发过去Apollo根本不认。所以我的建议是先确定你想用的Apollo版本再反推选择Carla版本不要先装Carla再选Apollo。这里给一个参考组合表Apollo版本推荐Carla版本桥接层方案备注Apollo 6.0Carla 0.9.11 / 0.9.12Apollo官方carla_bridge或社区二次开发版社区方案最成熟资料最多新手首选Apollo 7.0 / 8.0Carla 0.9.13社区fork版本或自行适配CyberRT需要自己处理消息适配工作量中等更早期Apollo 3.5/5.0Carla 0.9.9左右旧版桥接工具不建议新项目使用生态已经落后如果你在装完环境后发现Apollo模块一直报“No data received”之类的错误先别急着查网络或端口八成就是版本不匹配的问题。1.3 硬件要求与系统准备联合仿真实测下来对机器配置的要求比单跑Carla要高不少。Carla本身要渲染场景Apollo要跑感知规划算法桥接层还要不停转发数据三者叠加对CPU、内存、GPU的压力都不小。个人经验是CPU建议8核心以上内存32GB起步显卡最好NVIDIA系列且显存不低于8GB否则Carla的帧率会低到难以忍受Apollo端感知延迟也会变大。系统方面Carla和Apollo对Linux的兼容性最好。Apollo官方主要支持Ubuntu 18.04和20.046.0对应18.047.0以后对20.04支持更好而且它推荐用Docker方式部署这样会省掉大量依赖冲突的麻烦。Carla则直接在Ubuntu里跑预编译包就行。Windows下虽然Carla也能跑但Apollo基本只能靠虚拟机仿真性能会大打折扣所以我的建议是直接上一台Ubuntu机器或者用双系统别在Windows上折腾。2. 环境搭建实录从零到能启动2.1 Carla的安装与验证Carla的安装相对简单。直接到Carla官方GitHub Release页面下载对应版本的预编译压缩包名称一般是Carla_0.9.xx.tar.gz解压后进入目录就能用。下载时注意选择包含全部地图资源的完整包否则某些测试场景会加载不了地图。解压后启动服务端cd ~/carla ./CarlaUE4.sh -quality-levelLow-quality-levelLow是我建议新手加上去的参数它能明显降低显卡负载在联合仿真初期调试阶段画质根本不是关注重点流畅和稳定才是。启动成功后会弹出一个窗口能看到一个典型的城市环境左下角通常会有一些状态输出。验证Carla服务端是否正常最直接的方式是跑一小段Python脚本import carla client carla.Client(localhost, 2000) client.set_timeout(10.0) world client.get_world() print(world.get_map().name)如果能打印出地图名称就说明Carla服务端和Python API是通的。这里有个很容易忽略的问题Carla的Python API需要单独安装或配置路径。不同版本的Carla会携带对应版本的Python API文件一般在PythonAPI/carla/dist/目录下需要用pip安装对应的.whl文件或者把PythonAPI/carla目录加入Python搜索路径。如果import carla报错找不到模块本质上不是Python问题而是版本对不上或路径没指对。2.2 Apollo的部署与启动Apollo的部署比Carla复杂很多但好在官方提供了Docker化的一键脚本。以Apollo 6.0为例基本流程是git clone https://github.com/ApolloAuto/apollo.git cd apollo bash docker/scripts/dev_start.sh bash docker/scripts/dev_into.sh ./apollo.sh build这几条命令做的事情分别是对应着拉取源码、启动开发容器、进入容器、编译整个项目。Apollo的编译时间取决于机器性能我第一次编译用了接近一个小时如果报错也别慌多数是依赖下载不完整或Docker镜像源问题检查网络后重新执行build即可。进入容器后启动DreamView用命令./scripts/bootstrap.sh start然后浏览器访问http://localhost:8888就能打开DreamView界面。在DreamView中需要先选择模式一般选“Sim_Control”或“RTK”模式然后加载地图。联合仿真场景下通常选用Carla对应的地图如San Francisco或Town01等再启动感知、预测、规划、控制等相关模块。注意这一步要先启动一个最简单的空环境验证Apollo本身能跑通再接入Carla否则联合仿真的问题定位会非常痛苦。2.3 Python环境的坑与建议联合仿真至少涉及两套Python环境一套是Carla的Python API一套是写测试脚本时用的Python解释器。我的建议是统一用Python 3.8或者3.10不要太新也不要太旧。系统自带的Python版本如果是3.6以下很多现代语法和依赖库会装不上如果太新比如3.12Carla的部分旧版本whl包反而不兼容。最省心的方式是用conda建一个独立环境专门用于仿真相关脚本conda create -n sim python3.8 conda activate sim pip install carla0.9.12 # 根据你的Carla版本选择 pip install numpy opencv-python如果你发现pip install carla下载不到对应版本也可以直接从Carla目录下复制whl文件到当前环境安装。这里有个小技巧安装后可以用python -c import carla; print(carla.__version__)确认当前环境连接的Python API版本这个版本必须和Carla服务端一致哪怕差一个小版本都可能在运行时出现莫名其妙的数据异常。3. 数据链路是如何打通的3.1 一张图看清联合仿真数据流联合仿真的本质是数据流转理解了这个模型后面遇到问题才不至于抓瞎。整体数据流大致是这样Carla端不断生成车辆状态、激光雷达点云、摄像头图像等数据通过桥接层做格式转换后写入Apollo的CyberRT通道。Apollo感知模块订阅通道数据处理后输出障碍物列表预测模块推测障碍物轨迹规划模块生成决策路径控制模块输出油门、刹车和转向指令。这些指令再通过桥接层转回CarlaCarla用自带物理引擎驱动车辆模型运动。车辆运动后的新状态再次进入传感器仿真形成闭环。这个环形链路上任何一个环节出问题表现都是“车不动”或“感知空白”。我在排查时习惯先确认数据是断在哪一段是Carla到桥接层还是桥接层到Apollo还是Apollo内部模块之间。CyberRT提供了非常方便的工具可以用cyber_monitor查看Channel里有没有数据流动这是定位问题的最有力抓手。3.2 坐标系与时间戳最容易踩的暗坑如果桥接层能直接转发数据就好了但现实没那么简单。你要面对的第一个难题是坐标系。Carla使用的是Unreal Engine的左手坐标系而Apollo在全局定位和局部规划中使用的是ENU东-北-天坐标两者不仅原点和单位有差异坐标轴方向也不同。桥接层必须先把Carla的坐标转换成Apollo的局部坐标再填充到对应的消息字段里否则Apollo的定位模块会认为车在完全错误的位置。时间戳是另一个暗坑。Apollo传感器消息要求毫秒或微秒级的时间戳Carla每帧数据也有自己的时间戳但由于渲染和转发延迟两个时间戳不可能完全一致。如果时间戳偏差过大Apollo的感知融合模块会直接丢弃数据。我见过最典型的故障就是激光雷达点云在Cyber Monitor里能看到但感知模块就是不出障碍物排查到最后发现是时间戳不是单调递增的导致数据被当成“过期数据”过滤掉了。桥接层在转发时最好统一用消息到达的本地时间作为时间戳并且做一些简单的滤波和同步。3.3 桥接层用现成的还是自己写桥接层的选择直接决定了你前面的工作量。最省事的方案是使用现成桥接工具Apollo早期自带过carla_bridge模块后来迁移到了独立仓库维护社区里也有不少可用的fork版本。如果你用的是Apollo 6.0配Carla 0.9.12大概率能找到一个编译好、开箱即用的版本。这类工具一般会做三件事订阅Carla传感器数据、包装成Apollo消息、发布到CyberRT对应Channel同时订阅控制Channel并转发回Carla。如果你打算自己写一个简化版桥接用Python做原型其实不用怕。Carla的Python API能获取传感器数据CyberRT虽然有Python接口但配置起来稍繁琐可以先做成文件或UDP中转验证思路。当然我强烈不建议在初期自己造桥除非你有极强的调试欲和足够多的时间。联合仿真涉及通信协议、坐标系转换、时间戳同步、模块调度任何一个环节出错都很隐蔽用成熟的桥接层可以帮你砍掉大量调试成本。4. 手把手实操Python驱动联合仿真4.1 正确的启动顺序联合仿真最忌讳的就是“乱序启动”。我自己的固定顺序如下稳定跑了很多次启动Carla服务端等待地图加载完成启动Apollo的Docker环境和DreamView在DreamView中加载Carla对应的地图启动各算法模块启动桥接层等待数据流动运行Python脚本创建车辆和传感器让场景跑起来这个顺序的核心逻辑是数据发送端Carla和接收端Apollo先就绪再启动中间桥接层最后注入车辆和场景。如果先启动Python脚本创建车辆再启动桥接层Carla端可能会丢掉一部分初始化数据甚至在某些版本里出现传感器Actor无法生成的问题。4.2 用Python创建测试车辆与传感器对接桥接层后Carla世界的场景编排就成了Python的天下。下面这段代码是典型的“造车”逻辑把一辆测试车放到指定出生点并让它在默认自动驾驶模式下行驶import carla client carla.Client(localhost, 2000) client.set_timeout(20.0) world client.get_world() bp_lib world.get_blueprint_library() # 选择一辆测试车辆 vehicle_bp bp_lib.filter(vehicle.tesla.model3)[0] spawn_points world.get_map().get_spawn_points() # 为了便于复现固定选第一个出生点 vehicle world.spawn_actor(vehicle_bp, spawn_points[0]) vehicle.set_autopilot(True)关键点是set_autopilot(True)。在纯Carla环境下这会让Carla自带的简单AI驱动车辆但在联合仿真场景中更建议关闭Autopilot由Apollo的控制模块接管。否则会出现两套控制指令打架的问题表现就是车一会按Carla逻辑走一会按Apollo规划走姿态非常诡异。传感器是另一个核心。为了让Apollo感知模块有数据可吃需要在车上挂载激光雷达和摄像头# 添加激光雷达 lidar_bp bp_lib.find(sensor.lidar.ray_cast) lidar_bp.set_attribute(channels, 32) lidar_bp.set_attribute(range, 50.0) lidar_transform carla.Transform(carla.Location(x0.0, z2.5)) lidar world.spawn_actor(lidar_bp, lidar_transform, attach_tovehicle) # 添加前视摄像头 camera_bp bp_lib.filter(sensor.camera.rgb)[0] camera_bp.set_attribute(image_size_x, 1280) camera_bp.set_attribute(image_size_y, 720) camera_bp.set_attribute(fov, 90) camera_transform carla.Transform(carla.Location(x1.5, z1.8)) camera world.spawn_actor(camera_bp, camera_transform, attach_tovehicle)需要特别注意的是传感器的坐标位置。激光雷达最好放在车顶中央摄像头放在前挡风位置转换后的数据才符合Apollo对传感器外参的预期。如果你把传感器位置放得偏差太大即便数据链路是通的Apollo感知模块输出的障碍物位置也会严重偏斜。4.3 在DreamView中验证接管当Python脚本把车“放”进Carla世界后回到Apollo的DreamView界面。正常情况下你应该能看到一辆车出现在地图上对应的位置并且车身上开始显示激光雷达点云、障碍物方框、规划轨迹线等。如果车位置不对先检查坐标系转换是否正常如果能看到障碍物但车辆不按规划走检查控制模块是否正常输出并转发给Carla。这里我有个小经验验证接管是否成功最快的方法是人为在Carla里切换一下目标速度或方向看Apollo规划轨迹有没有反应。或者在场景里加一个静态障碍物看Apollo是否重新规划路径。如果这些响应都正常说明整套链路已经通了。我见过很多新手在这一步会卡很久其实最重要的不是代码写得多漂亮而是把“数据是否在流动”“数据是否正确”这两个基础问题敲实。4.4 跑通第一个自动驾驶测试场景数据链路通了之后就可以开始做真正有价值的事情设计测试场景。第一个场景建议做个最简单的让测试车在一段直路上行驶在车的前方放一个静态障碍物看Apollo能不能在碰撞前完成变道或刹车。用Python控制场景核心是控制障碍物和交通流。Carla允许你直接放置一个静态车辆obstacle_bp bp_lib.filter(vehicle.audi.a2)[0] obstacle_transform carla.Transform(carla.Location(xspawn_points[0].location.x 30, yspawn_points[0].location.y, z0.1)) obstacle world.spawn_actor(obstacle_bp, obstacle_transform) wing_obstacle obstacle.set_autopilot(False)然后通过Apollo端观察测试车行为。这个场景虽然简单但它验证了从传感器感知、到决策规划、再到执行控制的全链路闭环。我做联合仿真测试时第一件事永远是跑通这个最简单场景确认链路没问题后再加复杂度否则出了bug根本没法定位是场景问题、通信问题还是算法问题。5. 进阶玩法把联合仿真变成你的测试平台5.1 将测试场景脚本化跑通了单个场景下一步就是让它变成可复用的能力。我的做法是把场景封装成Python类用参数控制车辆型号、障碍物位置、天气、交通流密度这样就能批量生成不同的测试用例。比如一个最简单的场景函数class TestScenario: def __init__(self, car_modelvehicle.tesla.model3, obstacle_distance30, weatherclear): self.car_model car_model self.obstacle_distance obstacle_distance self.weather weather def setup(self, world): # 创建主角车、障碍物、设置天气封装为完整的场景初始化 pass def run(self, duration30): # 运行指定时长的仿真持续记录数据 pass def check(self): # 根据预设标准判断测试是否通过 pass这种封装的价值是你可以像写单元测试一样写自动驾驶场景把日常测试用例沉淀到代码里。Carla官方还提供了ScenarioRunner工具配合Python API可以定义更复杂的“基于场景”的交互逻辑——比如行人在特定时间点横穿马路、前方车辆在某个位置忽然变道等这些都能通过Python脚本精确触发非常适合做边缘场景测试。5.2 采集、录制与回放数据流一目了然联合仿真最大的优势之一就是可以精确采集每一个环节的数据。用Python脚本你可以把每一帧的车辆状态、传感器原始数据、Apollo输出的感知结果和规划路径保存下来。Carla端传感器回调和车辆状态可以直接保存成numpy数组或CSVApollo端CyberRT提供了录制功能可以把指定Channel的数据录制下来之后可以回放。把这个能力用起来你就能对某一次失败的测试进行“事后退尸”——把车辆状态、传感器数据、算法输出全部对齐定位是哪一步出了问题。一个很实用的经验在做数据分析时时间戳是你把Carla数据和Apollo数据关联起来的唯一钥匙。所以我强烈建议保存数据时每一行都同时记录Carla帧号和Apollo消息时间戳这样在分析时才能精确对应到同一时刻的车辆状态和算法状态。5.3 自动化回归测试的思路当场景脚本化、数据采集能力具备之后就可以搭建自动化回归测试了。最简单的流程包括批量执行一组场景脚本跑完后根据预定判定标准自动给出测试结果比如是否发生碰撞、是否超出车道线、是否在限定时间内到达目的地。把这些判定逻辑写进场景类的check方法里然后写一个shell脚本或Python脚本循环执行场景库里的所有场景最终汇总成一份测试报告。这套流程跑起来之后联合仿真的价值才真正体现出来你对算法做一次小幅改动就能在几十个场景上快速验证是否带来副作用。虽然不像真车测试那样有绝对的说服力但作为日常迭代的“体检工具”性价比非常高。我在实际项目里就是用这套方案在版本迭代中维护基础安全指标的。6. 常见问题与排查技巧实录6.1 启动异常速查表现象可能原因排查方向Carla窗口黑屏或闪退显卡驱动不兼容、显存不足检查NVIDIA驱动尝试-quality-levelLowPython无法import carlaPython API版本不匹配或路径错误确认whl包版本和Carla服务端一致Apollo编译报错网络下载依赖失败、Docker镜像问题检查网络和代理设置重新拉取依赖DreamView打开无显示容器映射端口异常检查Docker端口映射和防火墙桥接层启动后无数据坐标系配置异常、版本不匹配用cyber_monitor确认Channel里是否有数据Apollo模块反复重启Channel数据格式不匹配检查桥接层发布的topic名称和消息格式6.2 数据链路不通怎么排查链路不通是最让人头疼的问题。几个关键思路先说Carla侧用Python脚本确认传感器数据是否在正常回调比如激光雷达每帧有没有新数据、摄像头图像能不能保存到本地这个能排除Carla端的问题。接着看桥接层日志多数开源的桥接层会打印“收到Carla传感器数据”之类的信息如果桥接层就没收到数据问题出在Carla到桥接层如果收到了但报转换错误问题出在格式匹配。最后用CyberRT的cyber_monitor工具订阅对应Channel确认Apollo侧到底有没有数据进来。按这个顺序逐段排查效率会高很多。我自己遇到过一个特别隐蔽的问题Carla端激光雷达能正常出点云桥接层也显示转发了但Apollo感知模块一直不输出障碍物。查了两天最后发现是点云消息里的height和width字段填反了导致点云被当成空数据。这类问题光靠看数据流很难发现最好是把一条消息打开之后检查每个字段的实际数值。6.3 性能优化建议联合仿真性能瓶颈通常出在Carla渲染端。如果你发现整体帧率非常低先尝试降低Carla画面的分辨率和画质将Carla渲染窗口最小化也能释放一些性能。Apollo侧可以关闭不需要的模块比如不测试定位算法时可以用Apollo自带的模拟定位模块替代减少计算耗时。桥接层的转发频率没必要设太高Carla端传感器数据到Apollo端能达到10到15Hz的更新率对大多数测试场景已经完全足够了过高的频率只会白白消耗资源。另一个常被忽视的点是CPU核心分配。用Carla自带的需求参数设置和Docker资源限制把CPU核心和内存按需分配能有效避免Carla和Apollo互相抢占资源导致两边都卡顿。我在自己的测试机上会把Apollo容器限制在8核以内给Carla留下足够多的CPU核心实测下来稳定性和帧率都有明显改善。最后分享一个个人体会这套联合仿真平台刚搭完时你会觉得“终于能跑了”但真正让它发挥价值的是你开始批量跑场景、把测试用例沉淀下来的那一刻。Carla和Apollo都是开源工具Python脚本就是你的“测试脚本语言”只要愿意投入时间把场景库和自动化流程做起来它的回报会远超你的预期。一个小建议从最简单的直线跟车场景开始一步一个脚印扩展别一开始就追求复杂场景那只会让你在排错中耗尽耐心。
返回列表