4. Carla地图与车辆控制:地图加载与切换、车辆生成与操控、行人及交通流管理

好,咱们今天来聊聊Carla里最核心的几个操作——地图、车辆、行人、交通流。说实话,这部分内容我刚开始接触的时候也觉得挺乱的,但后来发现,只要理清了几个关键点,其实就那么回事。

4.1 地图加载与切换

Carla自带了好几个地图,比如Town01到Town10。每个地图的布局、路况、复杂度都不一样。我个人习惯在调试感知算法时,先用Town01这种简单地图,等模型跑稳了再换到Town05这种带环岛和复杂路口的。

加载地图其实就一行代码:

client.load_world('Town01')

但这里有个坑——切换地图时,之前生成的所有actor(车辆、行人等)都会被自动销毁。嗯,这个设计其实挺合理的,因为地图变了,路网都不同了,之前的actor位置信息全废了。

注意: 切换地图后,需要重新获取world对象。我遇到过有人直接复用旧的world引用,结果报错半天找不到原因。

如果你想看看当前有哪些地图可用,可以这样:

available_maps = client.get_available_maps()
for map_name in available_maps:
    print(map_name)

返回的是一串路径,比如/Game/Carla/Maps/Town01。你只需要取最后那个名字就行。

4.2 车辆生成与操控

生成车辆,说白了就是三步:选车型、选位置、spawn。但每一步都有讲究。

4.2.1 选择车型

Carla提供了几十种车辆蓝图。你可以按类型筛选:

blueprint_library = world.get_blueprint_library()
vehicle_bps = blueprint_library.filter('vehicle.*')

我个人建议,做感知测试时尽量用轿车或SUV,别用卡车——视野遮挡太严重,容易把算法搞崩。

4.2.2 设置生成位置

Carla地图里预置了很多spawn point,你可以直接拿来用:

spawn_points = world.get_map().get_spawn_points()
transform = spawn_points[0]  # 取第一个

但要注意,不是每个spawn point都能成功生成车辆。如果位置被占了或者地形有问题,spawn会返回None。我曾经在调试时没做这个检查,结果后面代码全崩了。

小技巧: 建议写个循环,尝试多个spawn point,直到成功为止。我一般会试10个,总有一个能用的。

4.2.3 生成并控制车辆

vehicle = world.spawn_actor(blueprint, transform)
vehicle.set_autopilot(True)  # 开启自动驾驶

开启autopilot后,车辆会按照交通规则行驶。但如果你想手动控制,可以设置速度或转向:

vehicle.apply_control(carla.VehicleControl(
    throttle=0.5,   # 油门 0~1
    steer=0.0,      # 转向 -1~1
    brake=0.0       # 刹车 0~1
))

嗯,这里要注意,apply_control和set_autopilot是互斥的。你开了autopilot再手动控制,车辆会跟你抢方向盘,结果就是车在原地抽搐。别问我怎么知道的...

4.3 行人及交通流管理

做感知算法,光有车不行,还得有行人、自行车、红绿灯这些。不然你的模型一上路就懵了。

4.3.1 生成行人

行人的生成逻辑和车辆类似,但有个区别——行人需要走路,所以得设置行走目标:

walker_bp = blueprint_library.filter('walker.pedestrian.*')[0]
walker = world.spawn_actor(walker_bp, transform)

# 让行人自动行走
walker_controller_bp = blueprint_library.find('controller.ai.walker')
walker_controller = world.spawn_actor(walker_controller_bp, carla.Transform(), walker)
walker_controller.start()
walker_controller.go_to_location(target_location)

这里有个容易忽略的点:行人控制器必须单独生成,不能直接让行人自己走。我刚开始做的时候以为spawn完就完事了,结果行人站在原地一动不动,像个雕塑。

4.3.2 交通流管理

交通流说白了就是让一堆车和行人按照规则跑起来。Carla提供了TrafficManager来管理:

traffic_manager = client.get_trafficmanager()
traffic_manager.set_global_distance_to_leading_vehicle(2.0)  # 跟车距离

你可以调整几个关键参数:

参数 说明 推荐值
跟车距离 前车距离(米) 1.0 ~ 3.0
速度百分比 相对于限速的比例 80% ~ 120%
是否忽略红绿灯 调试时可能用到 False
核心思路: 交通流管理的本质是让每个actor都按照规则运动,同时避免碰撞。TrafficManager帮你做了这件事,你只需要告诉它「车多密」「跑多快」就行。

4.3.3 批量生成交通流

如果你想要一个热闹的街道,可以批量生成车辆和行人。我一般会写个函数:

def spawn_traffic(world, num_vehicles=50, num_walkers=30):
    # 生成车辆
    for _ in range(num_vehicles):
        bp = random.choice(vehicle_bps)
        spawn_point = random.choice(spawn_points)
        vehicle = world.try_spawn_actor(bp, spawn_point)
        if vehicle:
            vehicle.set_autopilot(True)
    
    # 生成行人
    for _ in range(num_walkers):
        bp = random.choice(walker_bps)
        spawn_point = random.choice(walker_spawn_points)
        walker = world.try_spawn_actor(bp, spawn_point)
        if walker:
            # 设置控制器...
            pass

这里用try_spawn_actor而不是spawn_actor,是因为前者在失败时返回None而不是抛异常。嗯,做批量生成时,这个函数能省不少事。

4.4 避坑指南

最后,分享几个我踩过的坑:

  • 地图切换后一定要重新获取world,否则你操作的还是旧地图,会报错。
  • 不要同时开autopilot和手动控制,车辆会精神分裂。
  • 行人控制器必须单独生成,别指望spawn完就能走。
  • 批量生成时用try_spawn_actor,别让一个失败搞崩整个流程。

好了,这一章的内容就这些。说白了就是三件事:地图、车辆、交通流。你把这些搞明白了,后面的感知算法部署就有了一个稳定的测试环境。下一章咱们聊聊传感器配置,那才是真正有意思的部分。