1. 地图
地图包括城镇的 3D
模型和道路定义。地图的道路定义基于 OpenDRIVE
文件,这是一种标准化的带注释的道路定义格式。
OpenDRIVE 定义道路、车道、路口等的方式决定了 Python API
的功能以及做出决策背后的原因。
1.1 更换地图
要改变地图,世界也必须改变。仿真将从零开始重新创建。也可以在新的世界中使用相同的地图重新开始,或者同时改变地图和世界。
reload_world()
使用同样的地图创建一个世界的对象load_world()
改变当前地图并创建一个新的世界
# 加载地图
world = client.load_world('Town01')
# world = client.reload_world()
# 获取可用地图列表
print(client.get_available_maps())
每个地图都有一个与当前加载的城市名称相匹配的 name
属性,例如 Town01
。在客户端可以获取可用地图的列表:
print(client.get_available_maps())
1.2 Landmarks
opendrive
文件中定义的交通标志被转换为 CARLA
,作为可以从 API
中查询的地标对象。以下方法和类可用于操作和处理地标对象:
carla.Landmark
:对应OpenDRIVE
的signals
carla.LandmarkOrientation
:根据道路的几何形状定义地标的方向
carla.LandmarkType
:地标类型
carla.Waypoint
:根据距离来获取landmarks
carla.Map
可以查询地图中的所有地标,或者某一类型的地标carla.World
是landmarks
和carla.TrafficSign
、carla.TrafficLight
的中介
# 获取地标
print(world)
map = world.get_map()
print(map)
waypoints = map.generate_waypoints(100000)
print(waypoints)
waypoint = waypoints[4]
print(waypoint)
landmarks = waypoint.get_landmarks(20000.0, True)
print(landmarks)
1.3 Waypoints
carla.Waypoint
是 CARLA
世界中的一个 3D
定向点,对应于 OpenDRIVE
车道。所有与路径点相关的内容都发生在客户端,与服务器的通信只需要一次就可以获得包含路径点信息的映射对象。
同一道路内距离小于 2 厘米的路径点 id 相同。
每一个 waypoint
包含一个 carla.Transform
对象,它表示在地图中的位置以及包含它的车道方向。carla
中的变量 road_id
、section_id
、lane_id
和 s
对应 OpenDRIVER
中的道路。waypoint
中的 id
是由这 4
个值的哈希组合而成。
Waypoint
保存有关包含它的车道的信息。这些信息包括车道的左车道和右车道标记,一个布尔值,用于确定它是否在路口内,车道类型、宽度和车道更改许可。
# Access lane information from a waypoint
inside_junction = waypoint.is_junction()
width = waypoint.lane_width
right_lm_color = waypoint.right_lane_marking.color
1.4 Lanes
OpenDRIVE standard 1.4 定义的车道类型被转换成 Carla 中 carla.LaneType 的一系列枚举值。
车道周围的车道标记通过 carla.LaneMarking
访问。车道标记由一系列变量定义:
color
:carla.LaneMarkingColor
是定义标记颜色的枚举值。lane_change
:carla.LaneChange
说明车道是否允许左转、右转、双转或不允许。type
:carla.LaneMarkingType
是enum
值,根据OpenDRIVE
标准定义标记类型。width
: 定义标记的厚度。
下面的例子显示了获取有关特定航路点的车道类型、车道标记和换道许可的信息:
# Get the lane type of the waypoint
lane_type = waypoint.lane_type
# Get the type of lane marking on the left.
left_lanemarking_type = waypoint.left_lane_marking.type()
# Get available lane changes for this waypoint.
lane_change = waypoint.lane_change
1.5 Junctions
carla.Junction
代表一个 OpenDRIVE
的 junction
。这个类包含一个带有边界框的路口,用于识别其中的车道或车辆。
carla.Junction
类包含一个 get_waypoints
方法, 该方法为路口内的每个车道返回一对路点。每一对位于接合边界的起点和终点。
waypoints_junc = my_junction.get_waypoints()
1.6 Environment Objects
Carla
地图上的每个对象都有一组相关的变量,可以在 carla.EnvironmentObject 找到。这些变量中包含一个 unique ID,可用于 切换 该对象在地图上的可见性。你可以使用 Python API
根据每个环境对象的语义标签获取 semantic tag::
# Get the buildings in the world
world = client.get_world()
env_objs = world.get_environment_objects(carla.CityObjectLabel.Buildings)
# Access individual building IDs and save in a set
building_01 = env_objs[0]
building_02 = env_objs[1]
objects_to_toggle = {building_01.id, building_02.id}
# Toggle buildings off
world.enable_environment_objects(objects_to_toggle, False)
# Toggle buildings on
world.enable_environment_objects(objects_to_toggle, True)
2. 导航
Carla
中的导航是通过 Waypoint API
来管理的,是一些列来自 carla.Waypoint
和 carla.Map
方法的组合。
客户端首先必须与服务端通信来获取地图对象,其中包含路径点信息。这只需要执行一次,所有的后续查询操作都在客户端执行。
2.1 通过路径点导航
Waypoint API
公开了一些方法,这些方法允许路径点相互连接,并沿着道路构建一条道路供车辆导航。
next(d)
创建一个位于车道方向近似距离d
之内的路径点列表,该列表包含每个可能偏差的一个路径点。previous(d)
创建一个位于车道相反方向近似距离d
之内的路径点列表,该列表包含每个可能偏差的一个路径点。next_until_lane_end(d)
和previous_until_lane_start(d)
返回一个以d
为间隔的路径点列表,列表分别从当前路径点到达其路径的起点和终点。get_right_lane()
和get_left_lane()
返回相邻车道中的等效路径点(如果有的话)。换道机动可以通过找到左/右车道上的下一个航路点,并移动到它。
# Find next waypoint 2 meters ahead.
waypoint = waypoint.next(2.0)
2.2 生成地图导航
客户端需要向服务端发送请求以获取 .xodr
地图文件并解析为 carla.Map
对象,这仅仅需要执行一次。
map = world.get_map() # 获取地图对象
地图对象包含用于创建车辆推荐的生成点,可以获得生成点的一个列表,每一个生成点包含一个 carla.Transform
。有些生成点可能已经被占用了,这样会因为碰撞而无法创建车辆。
spawn_points = world.get_map().get_spawn_points()
你可以从路径点开始,通过获得最近的路径点到一个指定的位置或到地图的 OpenDRIVE
定义中的一个特定的 road_id
, lane_id
和 s
值:
# Nearest waypoint in the center of a Driving or Sidewalk lane.
waypoint01 = map.get_waypoint(vehicle.get_location(),project_to_road=True, lane_type=(carla.LaneType.Driving | carla.LaneType.Sidewalk))
#Nearest waypoint but specifying OpenDRIVE parameters.
waypoint02 = map.get_waypoint_xodr(road_id,lane_id,s)
下面的示例演示如何生成一组路径点来可视化城市车道。这将在地图上为每个道路和车道创建路径点。它们之间的距离大约是 2 米:
waypoint_list = map.generate_waypoints(2.0)
要生成道路拓扑的最小图,请使用下面的示例。这将返回一个路径点对(元组)列表。每一对中的第一个元素与第二个元素连接,它们都定义了地图中每个车道的起点和终点。有关此方法的更多信息可以在 PythonAPI 中找到。
waypoint_tuple_list = map.get_topology()
下面的例子将 carla.Transform
转换为 carla.GeoLocation
形式的地理维度和经度坐标。
my_geolocation = map.transform_to_geolocation(vehicle.transform)
将路况信息以 OpenDRIVE
格式保存到磁盘,示例如下:
info_map = map.to_opendrive()
3. 地图分类
carla
生态系统中有 8 个城镇,每个城镇都有两种地图,非分层和分层。图层指的是地图中的分组对象,由以下几个部分组成:
- 空的
- 建筑
- 贴花
- 树叶
- 地面
- 泊车
- 粒子
- 道具
- 路灯
- 墙
- 所有
3.1 不分层地图
非分层地图如下表所示(点击城镇名称可以查看布局的俯视图)。在 carla 0.9.11
之前所有的层在任何时候都存在,并且不能在这些映射中切换打开或关闭,这是唯一一种可用的地图。
用户可以 自定义地图,甚至 创建一个新的地图 来在 CARLA
中使用。
- Town01 由 “T形路口” 组成的基本城镇布局。
- Town02 与 Town01 相似,但是更小
- Town03 最复杂的城镇,有5车道的交叉路口,一个环形,不平,一条隧道,等等。
- Town04 一条有高速公路和一个小镇的无限环线。
- Town05 有十字路口和一座桥的方格城镇。每个方向都有多个车道。对变道很有用。
- Town06 高速公路长,有许多高速公路出入口。它也有密歇根左翼。
- Town07 乡村环境,道路狭窄,有谷仓,几乎没有红绿灯。
- Town10 城市环境与不同的环境,如大道或步道,和更现实的纹理。
3.2 分层地图
分层地图的布局与非分层地图相同,但可以在地图的图层上切换和关闭。有一个不能切换的最小布局,由道路、人行道、交通灯和交通标志组成。可以使用后缀 _Opt
标识分层映射,例如,Town01_Opt
。使用这些地图,可以通过 Python API
加载 和 卸载 层:
# Load layered map for Town 01 with minimum layout plus buildings and parked vehicles
world = client.load_world('Town01_Opt', carla.MapLayer.Buildings | carla.MapLayer.ParkedVehicles)
# Toggle all buildings off
world.unload_map_layer(carla.MapLayer.Buildings)
# Toggle all buildings on
world.load_map_layer(carla.MapLayer.Buildings)
查看所有层按顺序加载和卸载的示例: