如何在Carla自动驾驶模拟器中实现可重复的确定性运行?
在Carla中实现可重复的实时仿真运行
问题描述
我希望在自动驾驶模拟器Carla中,未修改任何仿真参数的情况下实现完全相同的运行。目前已做操作:为所有随机操作设置特定种子、为Traffic Manager设置特定种子,开启synchronous_mode=True避免电脑延迟干扰。但记录ego vehicle的x、y、z位置后,两次运行结果相近但不完全一致,请问如何实现可重复的实时运行(非录制模式)?
环境信息
- Carla 0.9.14
- Ubuntu 20.04
- Python 3.8
相关代码
import random import numpy as np import sys import os try: sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/carla') except IndexError: pass import carla from agents.navigation.behavior_agent import BehaviorAgent # pylint: disable=import-error seed = 123 N_vehicles = 50 camera = None telemetry = [] random.seed(seed) try: # Connect the client and set up bp library and spawn points client = carla.Client('localhost', 2000) client.set_timeout(60.0) world = client.get_world() bp_lib = world.get_blueprint_library() spawn_points = world.get_map().get_spawn_points() settings = world.get_settings() settings.synchronous_mode = True settings.fixed_delta_seconds = 0.10 world.apply_settings(settings) traffic_manager = client.get_trafficmanager() traffic_manager.set_random_device_seed(seed) traffic_manager.set_synchronous_mode(True) # Spawn ego vehicle vehicle_bp = bp_lib.find('vehicle.audi.a2') vehicle = world.try_spawn_actor(vehicle_bp, random.choice(spawn_points)) # Move spectator behind vehicle to motion spectator = world.get_spectator() transform = carla.Transform(vehicle.get_transform().transform(carla.Location(x=-6,z=2.5)),vehicle.get_transform().rotation) spectator.set_transform(transform) world.tick() # set the car's controls agent = BehaviorAgent(vehicle, behavior="normal") destination = random.choice(spawn_points).location agent.set_destination(destination) print('destination:') print(destination) print('current location:') print(vehicle.get_location()) #Iterate this cell to find desired camera location camera_bp = bp_lib.find('sensor.camera.rgb') # Spawn camera camera_init_trans = carla.Transform(carla.Location(z=2)) camera = world.spawn_actor(camera_bp, camera_init_trans, attach_to=vehicle) # Callback stores sensor data in a dictionary for use outside callback def camera_callback(image, data_dict): data_dict['image'] = np.reshape(np.copy(image.raw_data), (image.height, image.width, 4)) # Get camera dimensions and initialise dictionary image_w = camera_bp.get_attribute("image_size_x").as_int() image_h = camera_bp.get_attribute("image_size_y").as_int() camera_data = {'image': np.zeros((image_h, image_w, 4))} # Start camera recording camera.listen(lambda image: camera_callback(image, camera_data)) # Add traffic to the simulation SpawnActor = carla.command.SpawnActor SetAutopilot = carla.command.SetAutopilot FutureActor = carla.command.FutureActor vehicles_list, batch = [], [] for i in range(N_vehicles): ovehicle_bp = random.choice(bp_lib.filter('vehicle')) npc = world.try_spawn_actor(ovehicle_bp, random.choice(spawn_points)) # add it if it was successful if(npc): vehicles_list.append(npc) print(f'only {len(vehicles_list)} cars were spawned') world.tick() # Set the all vehicles in motion using the Traffic Manager for idx, v in enumerate(vehicles_list): try: v.set_autopilot(True) except: pass # Game loop while True: world.tick() pose = vehicle.get_location() telemetry.append([pose.x, pose.y, pose.z]) # keep following the car transform = carla.Transform(vehicle.get_transform().transform(carla.Location(x=-6,z=2.5)),vehicle.get_transform().rotation) spectator.set_transform(transform) if agent.done(): print("The target has been reached, stopping the simulation") break control = agent.run_step() control.manual_gear_shift = False vehicle.apply_control(control) finally: # Stop the camera when we've recorded enough data if(camera): camera.stop() camera.destroy() settings = world.get_settings() settings.synchronous_mode = False settings.fixed_delta_seconds = None world.apply_settings(settings) traffic_manager.set_synchronous_mode(True) if(vehicles_list): client.apply_batch([carla.command.DestroyActor(v) for v in vehicles_list]) vehicle.destroy() np.savetxt('telemetry.txt', np.array(telemetry), delimiter=',')
运行误差情况

图中y轴为两次运行的误差,x轴为运行时间索引。
解决方案
要实现完全可重复的Carla仿真,除已做操作外,需补充以下关键步骤:
1. 固定Carla世界的全局种子
除random和Traffic Manager的种子外,设置Carla世界的各类随机种子,确保物理模拟、NPC初始行为等内部随机行为一致:
world.set_random_seed(seed) world.set_pedestrians_seed(seed) world.set_weather_seed(seed)
2. 确保NPC生成完全可控
当前try_spawn_actor可能因生成失败导致两次运行的NPC数量/类型不一致,改为预定义固定的蓝图和 spawn 点:
# 替换原NPC生成代码,预定义固定索引确保一致性 predefined_bp_indices = [0, 5, 3, 12, 7] # 固定蓝图索引 predefined_spawn_indices = [10, 20, 5, 30, 15] # 固定 spawn 点索引 for bp_idx, spawn_idx in zip(predefined_bp_indices, predefined_spawn_indices): ovehicle_bp = bp_lib.filter('vehicle')[bp_idx] spawn_point = spawn_points[spawn_idx] npc = world.spawn_actor(ovehicle_bp, spawn_point) if npc: vehicles_list.append(npc)
3. 固定BehaviorAgent和numpy的随机种子
BehaviorAgent内部可能使用独立随机生成器,需同时固定numpy种子:
# 在代码开头添加 np.random.seed(seed) # 初始化BehaviorAgent后设置其内部种子 agent = BehaviorAgent(vehicle, behavior="normal") agent._random.seed(seed) # 适配BehaviorAgent内部随机属性
4. 固定Traffic Manager的行为参数
禁用或固定Traffic Manager的随机行为参数,避免默认随机性导致差异:
traffic_manager.set_vehicle_lane_change_probability(0.0) # 禁用随机变道 traffic_manager.set_global_distance_to_leading_vehicle(2.0) # 固定跟车距离 traffic_manager.set_desired_speed(10.0) # 固定全局期望速度
5. 每次运行前重置世界状态
确保每次仿真开始前世界处于干净初始状态:
# 在连接客户端后添加 client.reload_world() world = client.get_world()
完成上述修改后,重新运行两次仿真,对比telemetry.txt数据即可实现完全一致的ego车辆轨迹。
内容的提问来源于stack exchange,提问作者GuyS
相关产品推荐
相关产品推荐

