第三、地图和导航

在讨论了世界及其参与者之后,是时候将所有内容都放在适当的位置并了解地图以及参与者如何导航。


地图

地图包括城镇的三维模型及其道路定义。地图的道路定义基于 OpenDRIVE 文件,这是一种标准化的带注释的道路定义格式。OpenDRIVE 1.4 标准 定义道路、车道、路口等方式决定了 Python API 的功能以及决策背后的推理。

Python API 充当高级查询系统来导航这些道路。它不断发展以提供更广泛的工具集。

改变地图

要改变地图,世界也必须改变。将从头开始重新创建仿真。您可以在新世界中使用相同的地图重新启动,也可以更改地图和世界:

  • reload_world() 使用相同的地图创建世界的新实例。
  • load_world() 改变当前地图并创建一个新世界。
world = client.load_world('Town01')

每个地图都有一个与当前加载的城市名称匹配的name属性,例如 Town01 。要获取可用地图的列表:

print(client.get_available_maps())

地标

OpenDRIVE 文件中定义的交通标志将转换为 Carla,作为可从 API 查询的地标对象。以下方法和类可用于操作和使用地标对象:

  • carla.Landmark 对象代表 OpenDRIVE 信号。该类的属性和方法描述了地标及其影响区域。
  • carla.Waypoint 可以获得位于其前方一定距离的地标。可以指定要获取的地标类型。
  • carla.Map 检索地标集。它可以返回地图中的所有地标,或者具有共同 ID、类型或组的地标。
  • carla.World 充当地标、仿真中代表他们的carla.TrafficSigncarla.TrafficLight 之间的中间。
my_waypoint.get_landmarks(200.0,True)

路径点

carla.Waypoint 是 Carla 世界中的三维有向点,对应于 OpenDRIVE 车道。与路径点相关的所有事情都发生在客户端;只需与服务器通信一次即可获取包含航点信息的地图对象

每个路径点都包含一个 carla.Transform ,它说明其在地图上的位置以及包含该航路点的车道的方向。变量road_id,section_id,lane_ids对应 OpenDRIVE 道路。路径点id的是由这四个值的哈希组合构造的。

笔记

同一道路内距离小于 2 厘米 的路点共享相同的路点 id

路径点保存有关包含该路径点的 车道 的信息。此信息包括车道的左车道和右 车道标记、用于确定其是否位于路口内的布尔值、车道类型、宽度和车道变更权限。

# 从路径点访问车道信息
inside_junction = waypoint.is_junction()
width = waypoint.lane_width
right_lm_color = waypoint.right_lane_marking.color

车道

OpenDRIVE 1.4 标准 定义的通道类型将 carla.LaneType 作为一系列枚举值转换为 API 。

车道周围的车道标记可通过 carla.LaneMarking 访问。车道标记由一系列变量定义:

下面的示例显示了获取有关特定路径点的车道类型、车道标记和车道变更权限的信息:

# 获得路径点车道类型
lane_type = waypoint.lane_type

# 获得左车道标记的类型
left_lanemarking_type = waypoint.left_lane_marking.type()

# 获得该路径点可得的车道改变
lane_change = waypoint.lane_change

路口

carla.Junction 代表 OpenDRIVE 连接点。此类包含带有边界框的交汇处,用于识别其中的车道或车辆。

carla.Junction 类包含 get_waypoints 为交汇处的每个车道返回一对路点的方法。每对位于交界处边界的起点和终点。

waypoints_junc = my_junction.get_waypoints()

环境对象

Carla 地图上的每个对象都有一组关联的变量,可以在 处找到这些变量。这些变量中包含一个 唯一 ID,可用于切换该对象在地图上的可见性。您可以使用 Python API 根据每个环境对象的语义标签 获取 其 ID :

# 获得世界中的建筑
world = client.get_world()
env_objs = world.get_environment_objects(carla.CityObjectLabel.Buildings)

# 访问各个建筑 IDs 并保存在集合当中
building_01 = env_objs[0]
building_02 = env_objs[1]
objects_to_toggle = {building_01.id, building_02.id}

# 切换建筑为不可见
world.enable_environment_objects(objects_to_toggle, False)
# 切换建筑为可见
world.enable_environment_objects(objects_to_toggle, True)

查看切换不同对象的示例:

toggle_objects_gif


在 Carla 中导航

Carla 中的导航是通过 Waypoint API (来自 carla.Waypointcarla.Map 的方法组合)进行管理。

客户端必须首先与服务器通信以检索包含路径点信息的地图对象。这只需要一次,所有后续查询都在客户端执行。

通过路径点导航

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() 返回相邻车道中的等路径点(如果存在)。可以通过找到右/左车道上的下一个路点并移动到该路点来进行变道操作。
# 找到前面 2 米的下一个路径点
waypoint = waypoint.next(2.0)

生成地图导航

客户端需要向服务器发出请求来获取 .xodr 地图文件并将其解析为carla.Map 对象。这只需要做一次。

获取地图对象:

map = world.get_map()

地图对象包含用于创建车辆的 推荐生成点。您可以使用以下方法获取这些生成点的列表,每个生成点都包含 carla.Transform。请记住,生成点可能已被占用,从而导致由于碰撞而导致车辆创建失败。

spawn_points = world.get_map().get_spawn_points()

您可以通过获取距特定位置或特定 road_idlane_ids位置最近的航路点以及地图 OpenDRIVE 定义中的值来开始使用路径点:

# 驾驶车道或人行道中心最近的路径点。
waypoint01 = map.get_waypoint(vehicle.get_location(),project_to_road=True, lane_type=(carla.LaneType.Driving | carla.LaneType.Sidewalk))

# 最近的路径点,同时指定 OpenDRIVE 参数。
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()

Carla 地图

Carla 生态系统中有八个城镇,每个城镇都有两种地图,非分层地图和分层地图。图层是指地图中分组的对象,由以下部分组成:

  • NONE
  • 建筑物
  • 贴标
  • 叶子
  • 地面
  • 停放的车辆
  • 粒子
  • 道具
  • 路灯
  • 墙壁
  • 全部

非分层地图

下表显示了非分层地图(单击城镇名称可查看布局的俯视图)。所有图层始终存在,并且无法在这些地图中打开或关闭。直到 Carla 0.9.11 为止,这些是唯一可用的地图类型。

笔记

用户可以使用 自定义地图 甚至创建要在 Carla 中使用的 新地图

城镇 概括
Town01 由“T 字路口”组成的基本城镇布局。
Town02 Town01 类似,但是更小。
Town03 最复杂的城镇,有 5 车道交叉路口、环岛、凹凸不平、隧道等。
Town04 有高速公路和小镇的无限循环。
Town05 方形网格城镇,有十字路口和一座桥梁。每个方向有多个车道。对于执行变道很有用。
Town06 高速公路长,有许多高速公路入口和出口。它还有一个 密歇根左转
Town07 乡村环境,道路狭窄,谷仓,几乎没有红绿灯。
Town10 具有大道或长廊等不同环境的城市环境,以及更真实的纹理。
Town11 具有大道或长廊等不同环境的城市环境,以及更真实的纹理。
Town12 一张包含许多不同区域的大地图,包括高层建筑、住宅区和乡村环境。
Town13 一张与 12 号镇规模相似的大地图,但具有鲜明的特色。
Town15 基于巴塞罗那自治大学道路布局的地图。
HUTB 基于湖南工商大学道路布局的地图。

分层地图

分层地图的布局与非分层地图相同,但可以关闭和打开地图的图层。有一个无法关闭的最小布局,由道路、人行道、交通灯和交通标志组成。分层地图可以通过后缀 _Opt 来标识,例如Town01_Opt。使用这些地图,可以通过 Python API 加载卸载图层:

# 加载 城镇01 的分层地图,带有最小布局加上建筑物和停放的车辆
world = client.load_world('Town01_Opt', carla.MapLayer.Buildings | carla.MapLayer.ParkedVehicles)

# 关闭所有建筑
world.unload_map_layer(carla.MapLayer.Buildings)

# 打开所有建筑    
world.load_map_layer(carla.MapLayer.Buildings)

查看按顺序加载和卸载所有层的示例:

map-layers


自定义地图

Carla 旨在针对专业应用程序进行可扩展和高度定制。因此,除了 Carla 中现有的许多地图和资产之外,还可以创建和导入新的地图、道路网络和资产,以填充 Carla 仿真中的定制环境。以下文档详细介绍了构建和集成自定义地图所需的步骤: