“ 经常有朋友问如何学习仿真测试,于是想着把自己的一些经验和理解分享出来,希望能有所帮助。不过视野和技术有限,所说不一定对,供大家批评和参考。这是第21篇,CARLA的道路环境。”
前面介绍了车辆模型和传感器,本篇介绍CARLA中道路环境的加载方式和如何获取相应信息
道路环境不仅包含道路结构,还包括附着在道路上的交通标志、标线、信号灯和建筑树木等静态元素。道路环境是生成仿真世界的基础,也是复杂多样的测试场景的重要组成部分。
道路环境的加载
CARLA中道路环境的加载方法如下图所示。

1.import carla2.import os3.import time4.5.# 设置道路环境加载方式6.LOAD_MODE = "map" #map or xodr7.8.def main():9. # 创建client,并获取world10. client = carla.Client("localhost", 2000)11.12. # 加载地图13. if LOAD_MODE == "map":14. # 加载Town10HD_Opt15. maps = client.get_available_maps()16. print(f"maps = {maps}")17. world = client.load_world("Town10HD_Opt")18. time.sleep(3)19. world.unload_map_layer(carla.MapLayer.All)20. time.sleep(1)21. world.load_map_layer(carla.MapLayer.Ground)22. time.sleep(1)23. world.load_map_layer(carla.MapLayer.Buildings)24. elif LOAD_MODE == "xodr":25. # 加载OpenDRIVE26. xodr_path_base = "/home/sun/adsim_sun/carla_api_example/OpenDrive"27. xodr_name = "Town10HD_Opt"28. xodr_path = os.path.join(xodr_path_base, f"{xodr_name}.xodr")29. with open(xodr_path, encoding='utf-8') as od_file:30. data = od_file.read()31. print(f"load opendrive map {xodr_path}")32.33. vertex_distance = 2.0 # in meters34. max_road_length = 500.0 # in meters35. wall_height = 1.0 # in meters36. extra_width = 0.6 # in meters37. world = client.generate_opendrive_world(38. data, carla.OpendriveGenerationParameters(39. vertex_distance=vertex_distance,40. max_road_length=max_road_length,41. wall_height=wall_height,42. additional_width=extra_width,43. smooth_junctions=True,44. enable_mesh_visibility=True))45.46.if __name__ == "__main__":47. main()

道路环境信息的获取
1.import carla2.import random3.4.def main():5. # 创建client,并获取world6. client = carla.Client("localhost", 2000)7. world = client.get_world()8.9. # 获取map信息10. map = world.get_map()11.12. # 设置ego的车型13. ego_bp = world.get_blueprint_library().find('vehicle.tesla.model3')14. ego_bp.set_attribute('role_name','ego')15.16. # 随机选择预定义的生成点为ego生成位置17. spawn_points = world.get_map().get_spawn_points()18. spawn_point = random.choice(spawn_points)19.20. # 生成ego车并设置自动驾驶21. ego_vehicle = world.try_spawn_actor(ego_bp, spawn_point)22. ego_vehicle.set_autopilot(True)23.24. snap = world.wait_for_tick()25. init_frame = snap.frame26. run_frame = 027. print(f"spawn ego vehicle at: {spawn_point}")28.29. # 采用默认的异步变步长模式30. while run_frame < 10000:31. snap = world.wait_for_tick()32. run_frame = snap.frame - init_frame33. print(f"----- run_frame = {run_frame} -----")34.35. # 设置spectator跟随ego车36. spectator = world.get_spectator()37. ego_tf = ego_vehicle.get_transform()38. spectator_tf = carla.Transform(ego_tf.location, ego_tf.rotation)39. spectator_tf.location += ego_tf.get_forward_vector() * (-10)40. spectator_tf.location += ego_tf.get_up_vector() * 341. spectator.set_transform(spectator_tf)42.43. # 获取车辆位置44. transform = ego_vehicle.get_transform()45. waypoint = map.get_waypoint(transform.location)46. print(f"-- current waypoint = {waypoint}")47.48. #获取当前位置的车道信息49. road_id = waypoint.road_id50. section_id = waypoint.section_id51. lane_id = waypoint.lane_id52. lane_type = waypoint.lane_type53. s = waypoint.s54. print(f" -road_id = {road_id}, section_id = {section_id}, lane_id = {lane_id}, lane_type = {lane_type}, s = {s}")55.56. right_marking = waypoint.right_lane_marking57. print(f" -right marking color = {right_marking.color}, type = {right_marking.type}, width = {right_marking.width}")58.59. #获取当前位置附近的红绿灯60. landmarks = waypoint.get_landmarks(50)61. for landmark in landmarks:62. tf = landmark.transform63. distance = landmark.distance64. name = landmark.name65. type = landmark.type66. print(f" -landmark tf = {tf}, distance = {distance}, name = {name}, type = {type}")67.68. #获取附近路径点69. next_wp = waypoint.next(10) #获取前进方向10米处的路径点列表,分叉处可能有多个点70. previous_wp = waypoint.previous(5) #获取后退方向5米的路径点列表,合流处可能有多个点71. left_wp = waypoint.get_left_lane() #获取左侧车道的路径点72. right_wp = waypoint.get_right_lane() #获取右侧车道的路径点73. print(f" -next_wp = {next_wp[0]}")74. print(f" -previous_wp = {previous_wp[0]}")75. print(f" -left_wp = {left_wp}")76. print(f" -right_wp = {right_wp}")77.78. # 销毁车辆79. is_destroyed = ego_vehicle.destroy()80. if is_destroyed:81. print(f"ego_vehicle has been destroyed sucessfully")82.83.if __name__ == "__main__":84. main()
若想通过路径点获取当前位置的各种信息,首先要获取当前位置对应的路径点,方法是:①通过world的get_map方法获取当前仿真世界的地图信息,如代码第10行所示,该方法一次会获取所有地图信息,因此耗时较大、获取一次即可反复使用;②获取当前位置,进而通过map的get_waypoint方法获取对应的路径点,如代码第44~45行;③获取当前路径点对应的各种信息。