4. 异步模式与同步模式对比
做仿真时间同步,说白了就是解决一个问题:仿真器里的时间怎么跟现实世界的时间对齐?
CARLA 给了我们两种选择——异步模式和同步模式。这两种模式我用了好几年,踩过不少坑,今天跟你好好聊聊。
4.1 异步模式(Asynchronous Mode)原理
异步模式是 CARLA 的默认行为。什么意思呢?
服务器自己跑自己的,客户端只管发请求。服务器每完成一帧计算,就立刻推送给客户端。客户端收到多少算多少,不会去等。
打个比方:就像你看视频,服务器是视频源,客户端是播放器。源端一直往外发数据,播放器能播多快取决于它自己的处理能力。
核心特点:
- 服务器不受客户端控制,自主推进仿真时间
- 客户端接收帧的速率取决于网络和计算能力
- 帧率可能波动,不保证每帧都处理
我记得刚开始用 CARLA 时,直接跑异步模式做感知算法测试。结果发现,每次跑出来的结果都不一样。后来才意识到——异步模式下,客户端丢帧是常态。
4.2 同步模式(Synchronous Mode)原理
同步模式就完全不一样了。服务器会乖乖等着,直到客户端说「好了,下一帧」。客户端不发 tick 指令,服务器就卡在那不动。
还是那个视频的比喻:这次服务器变成了一个听话的播放器,你按一下「播放」它才走一帧。你不按,它就暂停。
核心特点:
- 服务器等待客户端的 tick 指令
- 每一帧都精确可控
- 仿真时间与真实时间解耦
我做过一个多传感器融合的项目,需要激光雷达、摄像头、毫米波雷达的数据严格对齐。异步模式根本没法用,必须上同步模式。每次 tick 之后,所有传感器的数据都是同一时刻的,这才靠谱。
4.3 两种模式的对比
直接上表格,一目了然:
| 对比维度 | 异步模式 | 同步模式 |
|---|---|---|
| 时间控制 | 服务器自主推进 | 客户端控制推进 |
| 帧率稳定性 | 可能波动 | 完全可控 |
| 数据对齐 | 难以保证 | 精确对齐 |
| 实现复杂度 | 低,开箱即用 | 高,需要手动 tick |
| 性能开销 | 较低 | 较高(需等待客户端) |
4.4 适用场景与优缺点
异步模式适合的场景
- 可视化展示:比如跑个演示视频,不需要精确控制
- 快速原型验证:算法刚写完,先跑跑看效果
- 性能测试:想看看服务器能跑多快
我的经验:如果你只是看看场景长什么样,异步模式完全够用。我曾经用它做场景编辑器预览,效果很好,代码量还少。
同步模式适合的场景
- 多传感器融合:需要所有传感器数据时间戳一致
- 强化学习训练:每一步都需要精确的状态和奖励
- 确定性仿真:要求每次运行结果完全一致
- 硬件在环测试:需要与真实硬件同步
避坑指南:我曾经在同步模式下忘记加超时处理,结果仿真卡死了一整晚。同步模式一定要设置 tick 超时,否则客户端崩了,服务器就永远等下去了。
4.5 知识结构图
下面这张图帮你理清两种模式的核心逻辑:
4.6 代码示例
给你看看两种模式在代码上的区别:
# 异步模式(默认)
client = carla.Client('localhost', 2000)
world = client.get_world()
# 什么都不用做,直接跑
# 同步模式
client = carla.Client('localhost', 2000)
world = client.get_world()
settings = world.get_settings()
settings.synchronous_mode = True
settings.fixed_delta_seconds = 0.05 # 20 FPS
world.apply_settings(settings)
# 手动推进
for i in range(100):
world.tick()
# 在这里处理传感器数据
# 所有数据都是同一时刻的
小技巧:我习惯在同步模式下把 fixed_delta_seconds 设成 0.05,也就是 20 FPS。这个帧率对大多数算法测试都够用,而且计算压力不大。
嗯,两种模式各有千秋。异步模式省心,同步模式精确。我个人建议:做算法开发用同步模式,做展示用异步模式。别问我怎么知道的,都是血泪教训。