3. 第一台自动驾驶车
好,我们正式开始动手了。
上一章我们把CARLA环境搭好,也跑通了那个小栗子。说实话,看到那辆蓝色小车在屏幕上动起来的时候,我自己当年第一次跑通也是挺激动的。但那个demo太简单了,说白了就是让车自己瞎跑。
这一章,我们要亲手造出第一台属于我们的自动驾驶车。我会用特斯拉Model3作为原型,带你把油门、刹车、转向都控制起来,再实时读取它的速度、位置、加速度。最后,我们还要调一调它的物理属性,让它开起来更真实。
3.1 生成一辆特斯拉Model3
CARLA自带的车辆模型里,刚好有特斯拉Model3。我个人习惯是每次启动仿真前,先清空一下世界里的老演员,免得上一轮的车还停在路上。
import carla
# 连接客户端
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
# 获取世界对象
world = client.get_world()
# 清空所有老演员(车辆、行人等)
for actor in world.get_actors().filter('vehicle.*'):
actor.destroy()
嗯,这里要注意:destroy() 操作会直接删除演员,如果你后面还要用它的数据,记得先存一下。
接下来,我们生成一辆特斯拉Model3:
# 获取蓝图库
blueprint_library = world.get_blueprint_library()
# 筛选出特斯拉Model3的蓝图
tesla_bp = blueprint_library.find('vehicle.tesla.model3')
# 设置生成点(我习惯用地图上的随机生成点)
spawn_points = world.get_map().get_spawn_points()
spawn_point = spawn_points[0] # 选第一个生成点
# 生成车辆
vehicle = world.spawn_actor(tesla_bp, spawn_point)
print(f"特斯拉已生成,ID: {vehicle.id}")
为什么选第一个生成点?其实无所谓,你完全可以随机选一个。我在项目里遇到过一个问题:有些生成点被其他车辆占了,导致 spawn_actor 报错。所以稳妥的做法是加个 try-except,或者先检查一下这个点有没有障碍物。
carla.Transform,手动指定 x、y、z 坐标和朝向。
3.2 控制车辆运动:油门、刹车、转向
车生出来了,怎么让它动?CARLA 里控制车辆运动的核心是 VehicleControl 这个类。它包含几个关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| throttle | float (0.0 ~ 1.0) | 油门,0 是松油,1 是地板油 |
| brake | float (0.0 ~ 1.0) | 刹车,0 不刹,1 刹死 |
| steer | float (-1.0 ~ 1.0) | 转向,-1 左满舵,1 右满舵 |
| hand_brake | bool | 手刹,一般不用 |
| reverse | bool | 倒车档 |
举个例子,让车直线加速:
# 创建一个控制指令
control = carla.VehicleControl()
control.throttle = 0.5 # 50% 油门
control.brake = 0.0 # 不刹车
control.steer = 0.0 # 方向盘回正
# 应用控制
vehicle.apply_control(control)
你想想看,如果只给一次控制,车只会动一帧然后就停了。所以我们需要在循环里持续发送控制指令。我一般用 while True 配合 time.sleep 来控制频率:
import time
# 持续加速 3 秒
for i in range(30): # 假设每 0.1 秒发一次,共 3 秒
control.throttle = 0.6
vehicle.apply_control(control)
time.sleep(0.1)
# 然后刹车
control.throttle = 0.0
control.brake = 0.8
vehicle.apply_control(control)
time.sleep(1)
3.3 获取车辆状态信息
光让车跑还不够,我们得知道它跑得怎么样。CARLA 提供了 VehiclePhysicsControl 和 VehicleControl 的实时数据,但最常用的是通过 get_velocity()、get_location()、get_acceleration() 这三个方法。
来,我们写个函数,把状态打印出来:
def print_vehicle_state(vehicle):
# 速度(返回的是三维向量,单位 m/s)
velocity = vehicle.get_velocity()
speed = (velocity.x**2 + velocity.y**2 + velocity.z**2) ** 0.5
speed_kmh = speed * 3.6 # 转成 km/h
# 位置(返回 carla.Location)
location = vehicle.get_location()
# 加速度(返回三维向量)
acceleration = vehicle.get_acceleration()
acc_magnitude = (acceleration.x**2 + acceleration.y**2 + acceleration.z**2) ** 0.5
print(f"速度: {speed_kmh:.2f} km/h")
print(f"位置: ({location.x:.2f}, {location.y:.2f}, {location.z:.2f})")
print(f"加速度: {acc_magnitude:.2f} m/s²")
把这个函数放到控制循环里,每帧调用一次,你就能实时看到车辆状态了。我个人习惯把速度转成 km/h,因为平时看仪表盘习惯了,m/s 总觉得不直观。
3.4 设置车辆物理属性
默认的车辆物理参数是 CARLA 根据真实车型粗略设定的。但有时候我们需要调一调,比如让车更飘一点(模拟雨天),或者更稳一点(模拟满载)。
物理属性通过 VehiclePhysicsControl 来设置。常用的参数有:
| 参数 | 说明 | 典型值 |
|---|---|---|
| mass | 车辆质量(kg) | 1800(Model3 约 1800kg) |
| drag_coefficient | 空气阻力系数 | 0.23(Model3 很低) |
| max_steering_angle | 最大转向角(度) | 40 |
| tire_friction | 轮胎摩擦系数 | 1.0(干地),0.5(湿地) |
举个例子,把车改成「雨天模式」:
# 获取当前物理控制
physics_control = vehicle.get_physics_control()
# 修改参数
physics_control.mass = 1900 # 稍微重点,模拟积水
physics_control.tire_friction = 0.6 # 降低摩擦,模拟湿滑路面
physics_control.drag_coefficient = 0.3 # 风阻大一点
# 应用修改
vehicle.apply_physics_control(physics_control)
print("物理属性已更新:雨天模式")
嗯,这里有个坑:apply_physics_control 之后,车辆不会立刻改变状态,它需要等下一个物理步长才会生效。我建议你在设置完后,等个 0.1 秒再开始控制,否则第一帧的数据可能还是旧的。
3.5 本章知识体系
下面这张图帮你梳理了本章的核心逻辑:从生成车辆,到控制运动,再到获取状态和调物理属性,环环相扣。
3.6 完整示例代码
最后,我把上面所有步骤整合成一个完整的脚本。你直接复制到 CARLA 的 Python 环境下运行就行:
import carla
import time
def main():
# 连接
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
world = client.get_world()
# 清空旧车
for actor in world.get_actors().filter('vehicle.*'):
actor.destroy()
# 生成特斯拉
blueprint_library = world.get_blueprint_library()
tesla_bp = blueprint_library.find('vehicle.tesla.model3')
spawn_points = world.get_map().get_spawn_points()
spawn_point = spawn_points[0]
vehicle = world.spawn_actor(tesla_bp, spawn_point)
print("特斯拉已生成")
# 设置物理属性(雨天模式)
physics_control = vehicle.get_physics_control()
physics_control.tire_friction = 0.6
physics_control.mass = 1900
vehicle.apply_physics_control(physics_control)
time.sleep(0.1)
# 控制循环
control = carla.VehicleControl()
for i in range(50): # 约5秒
# 前3秒加速,后2秒刹车
if i < 30:
control.throttle = 0.5
control.brake = 0.0
else:
control.throttle = 0.0
control.brake = 0.7
control.steer = 0.0
vehicle.apply_control(control)
# 获取状态
velocity = vehicle.get_velocity()
speed = (velocity.x**2 + velocity.y**2 + velocity.z**2) ** 0.5 * 3.6
location = vehicle.get_location()
acc = vehicle.get_acceleration()
acc_mag = (acc.x**2 + acc.y**2 + acc.z**2) ** 0.5
print(f"帧{i:2d} | 速度:{speed:5.1f} km/h | 位置:({location.x:6.1f},{location.y:6.1f}) | 加速度:{acc_mag:4.2f} m/s²")
time.sleep(0.1)
# 清理
vehicle.destroy()
print("测试完成,车辆已销毁")
if __name__ == '__main__':
main()
运行这个脚本,你会看到特斯拉从静止加速到大概 50 km/h,然后刹车停下。同时终端会实时打印每一帧的状态数据。
嗯,到这里,你已经亲手造出了第一台自动驾驶车。虽然它现在只会直行和刹车,但你已经掌握了最核心的三个能力:生成、控制、感知。下一章我们会让这辆车学会转弯和跟车,敬请期待。
- 用
spawn_actor生成特斯拉Model3 - 用
VehicleControl控制油门、刹车、转向 - 用
get_velocity()、get_location()、get_acceleration()获取状态 - 用
VehiclePhysicsControl调整物理属性