“ 经常有朋友问如何学习仿真测试,于是想着把自己的一些经验和理解分享出来,希望能有所帮助。不过视野和技术有限,所说不一定对,供大家批评和参考。这是第21篇,CARLA的道路环境。”
前面介绍了车辆模型和传感器,本篇介绍CARLA中道路环境的加载方式和如何获取相应信息
道路环境不仅包含道路结构,还包括附着在道路上的交通标志、标线、信号灯和建筑树木等静态元素。道路环境是生成仿真世界的基础,也是复杂多样的测试场景的重要组成部分。
道路环境的加载
CARLA中道路环境的加载方法如下图所示。
1.import carla
2.import os
3.import time
4.
5.# 设置道路环境加载方式
6.LOAD_MODE = "map" #map or xodr
7.
8.def main():
9. # 创建client,并获取world
10. client = carla.Client("localhost", 2000)
11.
12. # 加载地图
13. if LOAD_MODE == "map":
14. # 加载Town10HD_Opt
15. 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. # 加载OpenDRIVE
26. 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 meters
34. max_road_length = 500.0 # in meters
35. wall_height = 1.0 # in meters
36. extra_width = 0.6 # in meters
37. 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 carla
2.import random
3.
4.def main():
5. # 创建client,并获取world
6. 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.frame
26. run_frame = 0
27. 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_frame
33. 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() * 3
41. 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_id
50. section_id = waypoint.section_id
51. lane_id = waypoint.lane_id
52. lane_type = waypoint.lane_type
53. s = waypoint.s
54. 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_marking
57. 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.transform
63. distance = landmark.distance
64. name = landmark.name
65. type = landmark.type
66. 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行;③获取当前路径点对应的各种信息。