4. 单车道直行场景:编写第一个脚本,让一辆车在单车道直行道路上行驶
好,咱们正式开始动手写脚本了。
说实话,我刚开始学仿真的时候,也以为一上来就要搞什么复杂路口、多车博弈。其实没必要。你想想看,再复杂的场景,也是从一条直路、一辆车开始的。今天我们就来搞定这个最基础、也最核心的单元——单车道直行。
4.1 场景分析:我们要模拟什么?
先别急着敲代码。我个人的习惯是,先想清楚场景的要素。
一个单车道直行场景,说白了就三样东西:
- 一条路:单车道,直的,长度够用就行。
- 一辆车:初始位置在路的一端。
- 一个动作:车沿着车道往前开,直到终点。
嗯,就这么简单。但简单归简单,这里面其实藏着仿真脚本的骨架——初始化、实体、行为、终止条件。这四个要素,以后你写任何复杂场景都跑不掉。
核心知识点:任何仿真脚本都可以抽象为四个部分:
- 初始化环境:加载地图、设置天气、时间等。
- 创建实体:生成车辆、行人、交通设施。
- 定义行为:控制实体如何运动、交互。
- 设置终止条件:什么时候结束仿真。
4.2 知识体系:单车道直行场景的核心逻辑
为了让你更直观地理解,我画了一张流程图。它展示了从脚本启动到仿真结束的完整脉络。
你看,整个流程就是一个闭环。车辆没到终点,就继续走;到了,就停。这个逻辑虽然简单,但它是所有行为规划的基础。
4.3 手写第一个脚本:Python + 伪代码实现
好,理论说完了,咱们来真的。下面这个脚本,是我用伪代码风格写的,目的是让你看清逻辑,不被具体API干扰。
# 单车道直行场景脚本 (v1.0)
# 作者:你的名字
# 描述:一辆车在单车道直行道路上行驶
# 步骤1:初始化仿真环境
load_map("single_lane_straight.xodr") # 加载OpenDRIVE地图
# 步骤2:创建车辆实体
my_car = create_vehicle(
model="sedan", # 车型:轿车
position=(0, 0, 0), # 初始位置 (x, y, z)
speed=0.0 # 初始速度:静止
)
# 步骤3:控制车辆直行
target_speed = 10.0 # 目标速度:10 m/s (约36 km/h)
while True:
# 获取当前车辆位置
current_x = my_car.get_position().x
# 判断是否到达终点 (假设终点在 x=200 米处)
if current_x >= 200.0:
print("车辆已到达终点")
break
# 控制车辆以目标速度行驶
my_car.set_target_speed(target_speed)
# 等待下一帧 (仿真步进)
step_simulation(0.05) # 步长50ms
# 步骤4:结束仿真
terminate_simulation()
小提示:这段代码里,load_map、create_vehicle、set_target_speed 这些函数,在不同仿真平台(比如CARLA、VTD、SUMO)里名字不一样,但逻辑是通用的。你只要找到对应的API替换就行。
4.4 避坑指南:我踩过的三个坑
写这个脚本的时候,我估计你一次就能跑通。但有些细节不注意,后面复杂场景会出大问题。我跟你分享三个我亲身经历过的坑。
坑一:坐标系的坑
我曾经在某个项目里,把车辆的初始位置设成了 (0, 0, 0),结果车直接掉到地底下去了。为什么?因为那个地图的路面高度是 0.3 米,不是 0 米。所以,一定要确认地图的路面高度。我的习惯是,先在地图编辑器里点一下路面,看看坐标。
坑二:速度单位的坑
有的平台用 m/s,有的用 km/h。我见过一个同事,把目标速度设成 10,以为是 10 km/h,结果是 10 m/s(36 km/h),在小区场景里直接飞出去了。所以,写脚本前,先查清楚API文档里的单位。不确定的话,先设一个很小的值试试。
坑三:终止条件的坑
你想想看,如果终点判断条件写的是 current_x == 200.0,会发生什么?车很可能永远到不了,因为仿真步进是离散的,车可能从 199.9 直接跳到 200.1,永远不等于 200.0。所以,一定要用 >= 或者 >,不要用 ==。这个错误,我刚开始学的时候犯了不下五次。
4.5 进阶思考:从一辆车到多辆车
嗯,单车道直行搞定了。你可能会想,这太简单了,有什么意思?
其实,这个脚本稍微改一改,就能变成多车跟驰场景。比如:
- 再创建一辆车,放在第一辆车后面 20 米处。
- 第二辆车的目标速度设为 12 m/s,比第一辆快。
- 然后,第二辆车就会追上第一辆车,这时候就需要加入碰撞检测和跟车模型了。
你看,从一辆车到两辆车,复杂度就上来了。但核心骨架,还是我们今天写的这几十行代码。
总结一下今天的内容:
- 单车道直行场景是仿真脚本的“Hello World”。
- 任何脚本都包含:初始化、创建实体、定义行为、终止条件。
- 注意坐标系、速度单位、终止条件判断这三个细节。
- 这个骨架可以扩展到更复杂的场景。
好了,今天的课就到这儿。脚本虽然短,但它是你构建复杂交通场景的第一块砖。把这砖砌实了,后面盖楼才稳当。