ARTICLE DETAIL

资讯详情

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

Apollo与Carla联合仿真环境搭建与调试实战指南

Apollo与Carla联合仿真环境搭建与调试实战指南 从最早的纯几何仿真工具到后来折腾过Carsim和Simulink的联合仿真再到如今在Apollo跟Carla这条链路上做各种算法实测我最大的感受是真正让人崩溃的地方往往不是“单个软件用不熟”而是“两套系统怎么在数据层对齐”。这篇东西就是围绕“ApolloCarla联合仿真环境搭建与实战调试”展开的把从环境准备、版本选型、桥接链路到实际调试过程中踩过的坑和排查思路一次性说透。内容框架直接按下述几个主题展开。1. 联合仿真的整体思路与方案选型1.1 为什么是Apollo加Carla而不是其他组合先说明我的选型结论。Carla提供的是“虚拟世界”和“传感器数据”Apollo提供的是“自动驾驶大脑”也就是感知、预测、规划、控制这一整套模块。这种组合最大的优势是两者都是各自领域的开源主力资料多、生态成熟而且模块解耦得比较干净。Carla用C/Python实现基于UE4渲染传感器仿真能力很强尤其是点云和图像Apollo则是自带CyberRT通信框架和DreamView可视化工具链基本上把真车上跑的软件栈照搬到仿真环境里这也是其他纯仿真方案很难比的。相比Carsim与Simulink联合仿真这种更多偏向控制逻辑验证的方案ApolloCarla的覆盖面明显更广从感知决策到控制闭环都能练适合完整跑通“感知—预测—规划—控制”全链路。它的问题也很明显集成的中间层很薄官方和社区提供的桥接工具版本匹配要求极高一个版本不对整个链路就静默失败。多数人安装时习惯“哪个新装哪个”结果经常是Apollo 7.0配了Carla 0.9.13但桥接脚本还是按0.9.8的接口写的最后所有传感器都订阅不到消息。所以版本组合最好参考官方Release说明或社区成熟配置而不是盲追新版。具体来说如果要跑Apollo 5.0配Carla 0.9.8比较稳跑Apollo 6.0配Carla 0.9.10就够用跑Apollo 7.0甚至更高的版本目前社区踩得比较多的是Carla 0.9.13前向兼容性好很多。如果你的主要目标是联合调试控制、规划模块不必非上最新版稳定压倒一切。1.2 整个仿真链路的数据流向理解联合仿真最重要的不是安装步骤而是数据流。整体逻辑可以分成三段你在排查问题的时候也按这个顺序去查就行。第一段是Carla作为环境端它负责加载地图、生成交通流、布置传感器并且用高精度渲染计算每个传感器的观测数据。这些观测通过Python API输出给客户端也就是桥接层。第二段是桥接层它用Carla提供的Python SDK拉取图像、点云、GNSS/IMU和车辆状态然后做两件事一是把数据从CARLA坐标系转换到Apollo传感器坐标系二是通过CyberRT Writer接口把数据发布成Apollo各模块能订阅的消息。第三段是Apollo决策端订阅感知、定位消息后感知模块输出目标级障碍物预测模块做轨迹预测规划模块生成轨迹控制模块计算油门刹车主转命令。控制命令最后重新通过桥接层写入Carla的VehicleControl形成闭环。所以你在配置Bridge的时候脑子里一定要有这张消息流地图。出了任何“模块不工作”的问题先看它前面的消息有没有进来别一上来就怀疑规划算法写错了。1.3 版本匹配与硬件需求先给一张我实测过、相对稳妥的版本组合表方便直接照着选组件推荐版本说明操作系统Ubuntu 18.04 / 20.04Apollo 5.0要求18.047.0建议20.04Apollo6.0或7.06.0资料最全7.0接口更现代Carla0.9.10配Apollo 6.0或0.9.13配7.0不建议0.9.11之后直接换Apollo5Docker19.03Apollo必须跑在Docker容器里NVIDIA驱动455Carla和Apollo感知都重度依赖GPUCARLA-ROS-Bridge / carla-apollo-bridge对应Carla版本的分支别用master分支硬套硬件上我的建议是显卡显存至少8GB模型用RTX 2070/3060以上级别。内存16GB打底32GB更稳妥。CPU方面6核以上不会太难受Carla场景里车辆一多CPU也会成为瓶颈。硬盘建议固态Carla地图加载和Docker镜像体积都很大机械盘会让你等到怀疑人生。2. 环境搭建从零开始把两个大件装起来2.1 Apollo Docker环境准备Apollo官方推荐用Docker方式部署这也是最省心的方式。首先安装Docker CE然后把当前用户加入docker组避免每次执行命令都加sudosudo apt-get update sudo apt-get install -y docker.io sudo systemctl enable docker sudo usermod -aG docker $USER newgrp docker接着克隆Apollo仓库进入目录后调用官方脚本拉取镜像并进入容器git clone https://github.com/ApolloAuto/apollo.git cd apollo bash docker/scripts/dev_start.sh bash docker/scripts/dev_into.sh这里有个关键点dev_start.sh默认会拉取较大的开发镜像国内网络环境下经常超时。实测可以配置Docker镜像加速器或者用脚本里的-C参数走国内镜像源速度会明显更快。如果你所在内网环境有代理或专用镜像仓库也可以直接在Docker daemon配置里指定registry-mirrors。启动容器后先跑一遍自带Demo验证环境是否正常bash scripts/bootstrap.sh start启动完打开浏览器的DreamView页面如果能正常显示说明Apollo容器环境基本没有问题。注意这里启动DreamView只是一个前端实际模块还要在界面里启动。最后强烈建议在容器里手动确认CyberRT的编译状态bash apollo.sh buildCarla版本对Apollo的依赖主要集中在CyberRT消息定义过早跳过编译后面会在桥接阶段踩一堆接口不匹配的坑。2.2 Carla仿真器安装与启动Carla安装相对简单直接下载对应版本压缩包解压即可。这里有几个注意点。下载后先确认解压目录里包含CarlaUE4.sh然后启动时不要直接用默认模式给显卡和渲染模式指定参数cd ~/carla ./CarlaUE4.sh -prefer-gl -quality-levelLow-prefer-gl会强制走OpenGL渲染兼容性更好-quality-levelLow可以降低GPU负载在联合仿真调试阶段足够用。如果机器上有多块显卡还要注意设置CUDA_VISIBLE_DEVICES不然Carla可能选了错误的GPU。启动之后Carla会默认监听2000端口这是RPC端口桥接客户端连的就是它。传感器数据流的端口则从2000往后递增比如2001、2002这些在防火墙和Docker端口映射时要同时考虑。为了后续方便我一般会用Python脚本读取服务器状态确认Carla完全加载完成再进入下一步import carla client carla.Client(127.0.0.1, 2000) world client.get_world() print(world.get_map().name)如果脚本能打印出地图名称说明Carla服务端已经正常就绪。这一步看起来简单但能省掉后面不少“桥接连不上”的排查时间。2.3 网络互通与端口规划如果Apollo和Carla跑在同一台机器上端口配置会简单很多。但实际开发中经常有这样的情况Carla跑在高性能渲染机器上Apollo跑在另一台大内存机器上这时候网络互通就是你必须面对的问题。Carla服务端RPC端口是2000流数据端口是2001到2010左右桥接层一般还会用到8000等自定义端口。你需要在Carla所在机器上确保这些端口对Apollo所在机器可达同时在Apollo容器的启动配置里做好端口映射。如果你直接用官方dev_start.sh启动容器它默认映射了8888DreamView、8887CyberMonitor等端口。桥接层如果在容器外运行则不需要额外映射如果桥接层要跑在容器内就需要把Carla端口映射进容器。一个常见的坑是Carla服务端和桥接客户端都通了但Apollo模块订阅不到数据原因往往是CyberRT的网络模式。CyberRT默认使用共享内存通信跨机器传输需要开启相应的传输配置否则Docker内外的CyberRT节点根本不在一个通信域里。3. 联合仿真桥接与核心模块调试3.1 数据桥接方案CARLA-ROS-Bridge与Apollo CyberRT的衔接Apollo自6.0以后已经全面使用CyberRT不再直接兼容ROS1消息。而Carla官方提供的桥接大多是CARLA-ROS-Bridge面向的是ROS2。所以联合仿真必须经过一次消息转换。最省事的方式是用社区维护的carla_apollo_bridge。这个桥接库通常作为Carla Python客户端的扩展运行它会创建CyberRT Writer节点将Carla传感器数据直接封装成Apollo感知消息。如果你的Apollo版本较旧也可以先把Carla数据转成ROS消息再用Apollo的ROS兼容层转发。但实测下来后者链路长时间戳容易乱排查问题很痛苦。启动桥接前需要确认几个环境变量。Carla服务端地址、端口以及Apollo CyberRT的domain ID必须一致。如果Apollo容器和Carla桥接层宿主机共享网络domain ID默认即可如果分处不同机器建议统一设置export CYBER_DOMAIN_ID1 export CARLA_HOST127.0.0.1 export CARLA_PORT2000启动桥接的命令各家脚本不一样但核心动作是一致的连接Carla服务端加载地图和演员车辆然后创建传感器并关联到CyberRT Writer。桥接脚本启动后会打印每一类消息的送达频率例如[publisher] publishing perception/obstacles 10 Hz [publisher] publishing localization/pose 20 Hz这两行输出是整个调试过程中最直接的“心跳信号”如果频率为0说明桥接层和Carla通信就有问题根本不涉及Apollo模块。3.2 坐标对齐与时间同步这节是很多新手最容易懵的部分。Carla使用的坐标系是Unreal引擎的Z-up右手系X轴向前Y轴向右而Apollo感知模块默认以车体为原点采用前X、左Y、上Z的FLU坐标系局部定位模块通常又用ENU或UTM系。两边坐标定义不同必须做旋转和平移补偿。一个简单的方法是只考虑偏航角对齐。假设Carla车体的朝向角为yaw需要转换到Apollo车体坐标时参照右手系绕Z轴旋转-90度同时把单位从厘米转成米。具体公式如下P_apollo R_z(-90°) * (P_carla / 100.0)其中旋转矩阵为R_z(-90°) | 0 1 0 | |-1 0 0 | | 0 0 1 |别看这个公式简单真在桥接脚本里做的时候很多人就忘了单位换算导致障碍物定位偏出几十米。我排查过一次连续三小时的问题最后发现是Carla输出的坐标单位是厘米而桥接层没有除以100。时间同步同样关键。Carla默认是非同步模式服务器机帧率不稳定传感器时间戳就会抖。为了保证感知和定位数据时间戳一致必须在Carla客户端设置同步模式settings world.get_settings() settings.synchronous_mode True settings.fixed_delta_seconds 0.05 world.apply_settings(settings)固定步长0.05秒表示仿真时间每步推进50毫秒这也直接决定了控制周期。同步模式下客户端每次调用world.tick()时所有传感器才会输出一帧数据这样可以确保Apollo拿到的点云、图像、定位数据属于同一仿真时刻。3.3 场景配置车辆、传感器、地图与交通流地图选择方面Carla官方自带Town01到Town10等多个地图。Apollo默认自带的演示地图是Greeley或San Mateo跟Carla地图并没有一一对应关系。联合仿真时最常用的做法是在桥接脚本里指定一个Carla地图然后用Apollo的寻路模块在给定地图上做路径规划但这个阶段Apollo需要一份匹配该地图的高精地图文件。社区通常的做法是先用Carla生成真值数据离线转换地图或者直接用Apollo官方提供的一个起始点做Rigid路测。我的经验是刚搭环境时不要在地图匹配上花太多时间先把Carla的Town03搭配一个Apollo可用的简单道路结构跑通整条链路等模块都正常了再回头处理高精地图细节。传感器配置是联合仿真里最灵活的部分。Carla用蓝图类型区分传感器常用的是彩色相机sensor.camera.rgb64线激光雷达sensor.lidar.ray_castGNSSsensor.other.gnssIMUsensor.other.imu我用过一段比较稳的配置激光雷达设64线、每秒64万点、探测距离85米。注意Carla的Lidar默认带某些噪声模型如果只做感知算法验证可以把点云噪声调低一点。车辆控制方面Carla的角色分为自动驾驶控制通过Traffic Manager和直接控制两种。在联合仿真时主角车辆一定不能交给Traffic Manager接管否则桥接层写进去的车辆控制命令会被覆盖车会在原地打转或不停加速。正确的做法是将主角车辆设置成固定车型然后在每帧tick后从Apollo控制模块读取输出通过apply_vehicle_control写入。3.4 从DreamView发起一次仿真任务环境统统就绪以后真正发起一次联合仿真任务完整流程我总结为以下六步。第一步启动Carla服务端确认RPC端口正常。第二步进入Apollo容器启动DreamView和所有的核心模块通过DreamView右下角“Module Startup”按钮至少开启Routing、Planning、Control、以及Prediction和Perception。第三步启动桥接脚本并且确认打印输出的消息频率不为0。第四步在DreamView里设置车辆起点和终点下发Routing请求。第五步观察车辆是否按照规划路径移动Control是否输出非零的油门、刹车和方向盘指令。第六步打开CyberMonitor或者DreamView的调试面板实时检查障碍物感知结果和控制消息延迟。其中最容易出现问题的是第四步和第五步的连接。Routing请求下发成功后Planning模块会开始规划轨迹但如果Control模块没有正确输出控制指令车辆就会静止。这时候先看Control的频道有没有输出再看是否有底盘反馈也就是Apollo框架下的chassis消息。没有底盘反馈时控制模块会认为车辆还没执行完上次指令从而一直输出很保守的控制量。4. 常见问题与排查技巧实录4.1 启动阶段问题这个阶段最常见的报错是Carla启动黑屏、CarlaUE4进程崩溃以及Apollo容器里GPU不可见。Carla黑屏首先排查显卡驱动用nvidia-smi确认驱动正常后再看UE4是否指定了正确的渲染API。部分显卡用Vulkan渲染兼容性差加-prefer-gl就能解决。Apollo容器里nvidia-smi命令不存在通常说明NVIDIA Container Toolkit没装好重新安装nvidia-docker相关组件即可。Carla启动后端口被占也是高频问题特别是在多实例调试场景里。用lsof -i:2000看看端口被哪个进程占用必要时加-carla-rpc-port3000指定其他端口并在桥接脚本里同步修改。另一个隐患是服务器和客户端Carla版本不一致。比如服务端是0.9.13客户端脚本却引用了低版本的Python API调用某些接口时直接报AttributeError。解决办法就是统一版本不能盲目pip install最新版。4.2 数据链路阶段问题这一阶段的问题基本集中在桥接层和CyberRT的衔接上。最典型的是“桥接打印消息频率为0”。遇到这个问题先确认桥接层的客户端是否连上了Carla端口用Python脚本carla.Client(...)测试连接。另一个典型问题是“点云有数据但Apollo感知模块看不到障碍物”。很多时候不是算法问题而是点云话题的坐标系和Apollo感知模块期望的坐标系不一致。感知模块收到点云后会做ROI滤波如果坐标偏移导致所有点都在ROI之外输出自然为空。解决办法是检查桥接脚本里雷达安装的坐标和朝向确认雷达中心位置和旋转外参匹配。我还遇到过桥接层不打印任何日志但CyberMonitor里能看见部分话题消息的情况。这种问题通常是CyberRT DDS域隔离导致的环境变量CYBER_DOMAIN_ID不一致会让节点间互相发现不了。在容器内外都执行一下cyber_launch相关的环境变量查看命令确认ID一致再试。4.3 控制闭环阶段问题过了数据链路调试重点就变成“车能不能动起来”。常见的表现有三种。第一种是车辆在DreamView里一动不动控制消息输出为0。这是底盘反馈缺失Carla桥接层没有正确发布/apollo/canbus/chassis控制模块不会进入闭环模式。第二种是车辆原地转圈或横向漂移。这种情况通常是控制命令的符号或单位不匹配。Carla的VehicleControl里steer范围是-1到1、油门范围是0到1而Apollo控制模块输出的刹车、油门是百分比单位如果你直接把Apollo输出的油门值塞给Carla会超出范围或者单位错误。一定要在桥接层做缩放和限幅。第三种是车辆可以动但轨迹严重抖动。这往往是同步模式设置不正确。Carla有渲染线程和物理线程如果你没有在同步模式下手动tick各传感器的时间戳会错开Apollo感知结果和控制指令交错执行画面看起来就是车在“抽搐”。确保world.tick()每帧只调用一次并且只在一个线程里调用。4.4 性能优化与踩坑笔记联合仿真对机器配置要求高特别是GPU显存和CPU主频。优化性能时我建议按优先级操作。首先把Carla渲染画质调到最低-quality-levelLow能立竿见影。其次减少不必要的传感器数量和点云点数。64线雷达够用就别上128线。Carla里每颗雷达每秒要生成几十万点CPU频率不够时直接拖垮仿真器。接下来优化Apollo模块的开销。感知、预测、控制这几个模块不是每次都要启动。只验证规划控制时可以把感知模块关闭直接用Carla真值转换成感知消息。这样不仅省GPU还能减少一个潜在故障点。最后使用性能监控工具。Carla自带/carla/status消息能看服务器帧率Apollo的CyberMonitor可以看每个话题的发布频率。两者结合能快速判断瓶颈是渲染、桥接还是Apollo模块本身。我自己的经验是先不管真实传感器噪声直接用Carla真值的BBox数据代替摄像头和点云感知结果把规划控制链路调通再逐步替换成感知模块输出。这样的“降级调试”能显著缩短问题排查范围。5. 从一次实战复盘谈起上个月我在调试一个变道场景时Carla里车辆总是到了变道点就减速刹停不执行变道。打开DreamView看Routing结果正常但Planning模块的轨迹里始终没有换道轨迹。排查到最后发现是感知模块把旁边车道的车误检为同车道障碍物导致规划器始终认为换道不满足安全距离。这个问题的根子不在规划算法而是激光雷达点云的ROI判断。Carla里车道线是一条线型边缘Apollo感知模块ROI过滤后对边缘判断不准旁边车道的车辆有一部分点云落进了当前车道于是感知目标被视为“同车道”。最后我把Carla里的车道宽度和Apollo的ROI扩了一圈问题就消失了。这种问题单看任何一方都不会发现只有把两边数据放在一起对比才能定位。所以在整个联合仿真调试过程中我一直建议多花时间看原始消息和真值数据别迷信可视化面板上的显示。最后说一点个人体会Apollo和Carla联合仿真最耗时间的往往不是“装环境”本身而是“两套系统对世界定义不同”的隐性问题。坐标系、单位、时间戳、通信域、模块启动顺序每个看起来都不是大问题但叠加起来会让整个系统处于一种“看起来活了实际就是不动”的状态。把前面的数据流和版本匹配记牢再动手排查就会顺畅很多。这次的实战记录就分享到这里。如果后续有时间我打算再整理一份Carla地图转Apollo高精地图的完整过程那个环节的坑也不少到时候再展开聊。
返回列表