深入nuScenes数据集(5/6)
in Tutorial with 0 comment
深入nuScenes数据集(5/6)
in Tutorial with 0 comment

这是一篇跟着官方教程走的深入文章,官方教程有6篇。现在这篇是 map_expansion_tutorial.ipynb,也就是第五篇,链接:here

6篇教程分别如下:

背景

在2019年7月,nuScenes 发布了包含11个语义层(人行横道、人行道、红绿灯、停车线、车道等)的地图扩展包。语义地图以矢量格式提供,并在所有数据集分割(mini、trainval、test)中使用。此外,还提供了用于语义先验(可行驶表面+人行道)和激光雷达底图的附加位图。

准备工作

下载数据集:需要先注册,邮箱注册即可,然后进入下载页:https://www.nuscenes.org/download,找到 Map expansion,md5: fa34801f375e3d645d944f73bb6a2fd5,点击 Asia,即可下载,因为是官方是使用了 aws s3 进行存储,如果遇到下载不畅,请自备魔法。

下载记得选择 v1.3,如果使用旧数据集,nuscenes-devkit 工具会报错。

将下载好的数据集解压到~/data_sets/nuscenes/maps/expansion,完整的目录是/Users/lau/data_sets/nuscenes,这个目录后面会用到。

目录结构如下:

tree -L 2
.
├── basemap
│   ├── boston-seaport.png
│   ├── singapore-hollandvillage.png
│   ├── singapore-onenorth.png
│   └── singapore-queenstown.png
├── expansion
│   ├── boston-seaport.json
│   ├── singapore-hollandvillage.json
│   ├── singapore-onenorth.json
│   └── singapore-queenstown.json
└── prediction
    └── prediction_scenes.json

初始化

打开 jupyter, 创建map-extention.ipynb文件

pip install nuscenes-devkit
import matplotlib.pyplot as plt
import tqdm
import numpy as np

from nuscenes.map_expansion.map_api import NuScenesMap
from nuscenes.map_expansion import arcline_path_utils
from nuscenes.map_expansion.bitmap import BitMap

nusc_map = NuScenesMap(dataroot='/Users/lau/data_sets/nuscenes', map_name='singapore-onenorth')

渲染

多层渲染

NuScenesMap类可以在matplotlib图中渲染多个地图层。

fig, ax = nusc_map.render_layers(nusc_map.non_geometric_layers, figsize=1)

2023-05-26T17:16:36.png

渲染激光雷达基础地图

我们可以渲染用于定位的高清激光雷达基础地图。该基础地图是一个位图图像,可以用于大多数功能(如渲染中心线、渲染车辆姿态在精美地图上、渲染图层、渲染地图区块、渲染下一条道路、渲染记录)。相同的BitMap类也可用于渲染原始nuScenes发布的语义先验(可行驶表面+人行道)。请注意,在此可视化中,我们仅显示车道标注以提高可见性。

bitmap = BitMap(nusc_map.dataroot, nusc_map.map_name, 'basemap')
fig, ax = nusc_map.render_layers(['lane'], figsize=1, bitmap=bitmap)

2023-05-26T17:20:19.png

渲染地图层的特定记录

我们可以渲染一条记录,显示其全局和局部视图。

fig, ax = nusc_map.render_record('stop_line', nusc_map.stop_line[14]['token'], other_layers=[], bitmap=bitmap)

2023-05-26T17:22:15.png

渲染二进制地图掩码层

NuScenesMap类可以将多个地图层转换为二进制掩码,并在Matplotlib图上进行渲染。首先,让我们调用get_map_mask来查看两个层的原始数据:

patch_box = (300, 1700, 100, 100)
patch_angle = 0  # Default orientation where North is up
layer_names = ['drivable_area', 'walkway']
canvas_size = (1000, 1000)
map_mask = nusc_map.get_map_mask(patch_box, patch_angle, layer_names, canvas_size)
map_mask[0]

# 输出结果
array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 1, 1, 1],
       [0, 0, 0, ..., 1, 1, 1],
       [0, 0, 0, ..., 1, 1, 1]], dtype=uint8)

现在我们使用render_map_mask直接可视化上面获取的地图掩码:

figsize = (12, 4)
fig, ax = nusc_map.render_map_mask(patch_box, patch_angle, layer_names, canvas_size, figsize=figsize, n_row=1)

2023-05-26T17:24:27.png

我们还可以将同一地图逆时针旋转45度后进行渲染:

fig, ax = nusc_map.render_map_mask(patch_box, 45, layer_names, canvas_size, figsize=figsize, n_row=1)

2023-05-26T17:24:58.png

在图像上渲染地图层

让我们获取一张nuScenes相机图像,并将相关的地图层叠加在上面。请注意,由于定位是2D的,如果地面不平坦,投影可能不完美。

# Init nuScenes. Requires the dataset to be stored on disk.
from nuscenes.nuscenes import NuScenes
nusc = NuScenes(dataroot='/Users/lau/data_sets/nuscenes', version='v1.0-mini', verbose=False)

# Pick a sample and render the front camera image.
sample_token = nusc.sample[9]['token']
layer_names = ['road_segment', 'lane', 'ped_crossing', 'walkway', 'stop_line', 'carpark_area']
camera_channel = 'CAM_FRONT'
nusc_map.render_map_in_image(nusc, sample_token, layer_names=layer_names, camera_channel=camera_channel)

2023-05-26T17:31:23.png

选择车姿在地图上

我们还可以将自车姿态绘制在地图上。这需要加载NuScenes类,这可能需要一些时间。

# Init NuScenes. Requires the dataset to be stored on disk.
from nuscenes.nuscenes import NuScenes
nusc = NuScenes(dataroot='/Users/lau/data_sets/nuscenes', version='v1.0-mini', verbose=False)

# Render ego poses.
nusc_map_bos = NuScenesMap(dataroot='/Users/lau/data_sets/nuscenes', map_name='boston-seaport')
ego_poses = nusc_map_bos.render_egoposes_on_fancy_map(nusc, scene_tokens=[nusc.scene[1]['token']], verbose=False)

2023-05-26T17:33:34.png

导航

数据集还提供了用于在道路网络中导航的功能。为此,道路层的车道(lane)、道路阻塞(road_block)和道路段(road_segment)尤为有用(参见下面的定义)。get_next_roads(x, y)函数用于查找特定点处的道路层。然后,在车道或道路阻塞的方向上检索下一个道路对象。由于道路段没有方向(例如交叉口),我们返回所有可能的下一个道路。

x = 873
y = 1286
print('Road objects on selected point:', nusc_map.layers_on_point(x, y), '\n')
print('Next road objects:', nusc_map.get_next_roads(x, y))

# 输出结果
Road objects on selected point: {'drivable_area': 'c3e28556-b711-4581-9970-b66166fb907d', 'road_segment': '57416e99-8919-4a28-985b-033a16938243', 'road_block': '', 'lane': '', 'ped_crossing': '', 'walkway': '', 'stop_line': '', 'carpark_area': ''} 

Next road objects: {'road_segment': ['3493d68c-5217-4d21-ae1b-3cbf4467dd77', '4b0e50c0-c549-49a2-9077-57a8cba8ab55', '5428b143-6343-4045-ac81-466df3dcc510'], 'road_block': ['5c286ee8-7b4d-4cd8-84bb-7486e77ba827', '8b33213a-692e-4c5f-a69a-efa6836f5316', '9aa7a714-30ba-4892-a276-c033928a8ae2', '9c506cc4-7d14-475d-8063-22a5b9bc257f', 'b7cc94f4-3882-4df2-a9ae-9349925809a1', 'e0c4f027-ea81-40f2-bafc-3fb8e8ab78c3'], 'lane': ['525b6716-a12e-4dd0-8541-91ef672ce39b', '5fdd162d-477d-4bc4-ada3-535d79a9f4b1', '8658217b-87d6-4f8b-96be-35d53100247d', 'b7378bda-dedf-4f97-9d87-b0dd602fdab5', 'bce7caf7-5e33-48d6-b0aa-8b5b641c8ce5', 'f747ce8a-2396-4da3-a8e6-45201ed470d6']}

我们还可以使用render_next_roads(x, y)函数可视化下一个道路。我们可以看到与坐标(x, y)指定的交叉口相邻的3条道路。

nusc_map.render_next_roads(x, y, figsize=1, bitmap=bitmap)

2023-05-26T17:36:28.png

处理车道

地图扩展(v1.2)中添加了连接性信息,以便高效查询哪些车道与其他车道相连。下面我们渲染车道(lanes)和车道连接器(lane_connectors)对象。车道和车道连接器由参数化曲线定义。参数resolution_meters指定曲线的离散化分辨率。如果将其设置为较高的值(例如100),曲线将显示为直线。我们建议将此值设置为1米或更小。

nusc_map.render_centerlines(resolution_meters=0.5, figsize=1, bitmap=bitmap)

2023-05-26T17:38:40.png

要获取最接近某个位置的车道,请使用get_closest_lane方法。要查看车道的内部数据表示,请使用get_lane_record方法。还可以通过get_outgoing_lanesget_incoming_lane方法来探索车道之间的连接性。

x, y, yaw = 395, 1095, 0
closest_lane = nusc_map.get_closest_lane(x, y, radius=2)
closest_lane

# 输出结果
'5933500a-f0f2-4d69-9bbc-83b875e4a73e'
lane_record = nusc_map.get_arcline_path(closest_lane)
lane_record

# 输出结果
[{'start_pose': [421.2419602954602, 1087.9127960414617, 2.739593514975998],
  'end_pose': [391.7142849867393, 1100.464077182952, 2.7365754617298705],
  'shape': 'LSR',
  'radius': 999.999,
  'segment_length': [0.23651121617864976,
   28.593481378991886,
   3.254561444252876]}]
nusc_map.get_incoming_lane_ids(closest_lane)

# 输出结果
['f24a067b-d650-47d0-8664-039d648d7c0d']
nusc_map.get_outgoing_lane_ids(closest_lane)

['0282d0e3-b6bf-4bcd-be24-35c9ce4c6591',
 '28d15254-0ef9-48c3-9e06-dc5a25b31127']

为了帮助操作车道,需要一个arcline_path_utils模块。例如,我们可能想要的一项操作是将车道离散化为一系列姿态。

poses = arcline_path_utils.discretize_lane(lane_record, resolution_meters=1)
poses

# 输出结果
[(421.2419602954602, 1087.9127960414617, 2.739593514975998),
 (420.34712994585345, 1088.2930152148274, 2.739830026428688),
 (419.45228865726136, 1088.6732086473173, 2.739830026428688),
 (418.5574473686693, 1089.0534020798073, 2.739830026428688),
 (417.66260608007724, 1089.433595512297, 2.739830026428688),
 (416.76776479148515, 1089.813788944787, 2.739830026428688),
 (415.87292350289306, 1090.1939823772768, 2.739830026428688),
 (414.97808221430097, 1090.5741758097668, 2.739830026428688),
 (414.0832409257089, 1090.9543692422567, 2.739830026428688),
 (413.1883996371168, 1091.3345626747464, 2.739830026428688),
 (412.29355834852475, 1091.7147561072363, 2.739830026428688),
 (411.39871705993266, 1092.0949495397263, 2.739830026428688),
 (410.5038757713406, 1092.4751429722162, 2.739830026428688),
 (409.6090344827485, 1092.8553364047061, 2.739830026428688),
 (408.7141931941564, 1093.2355298371958, 2.739830026428688),
 (407.81935190556436, 1093.6157232696858, 2.739830026428688),
 (406.92451061697227, 1093.9959167021757, 2.739830026428688),
 (406.0296693283802, 1094.3761101346656, 2.739830026428688),
 (405.1348280397881, 1094.7563035671556, 2.739830026428688),
 (404.239986751196, 1095.1364969996453, 2.739830026428688),
 (403.3451454626039, 1095.5166904321352, 2.739830026428688),
 (402.4503041740119, 1095.8968838646251, 2.739830026428688),
 (401.5554628854198, 1096.277077297115, 2.739830026428688),
 (400.6606215968277, 1096.657270729605, 2.739830026428688),
 (399.7657803082356, 1097.0374641620947, 2.739830026428688),
 (398.8709390196435, 1097.4176575945846, 2.739830026428688),
 (397.9760977310515, 1097.7978510270746, 2.739830026428688),
 (397.0812564424594, 1098.1780444595645, 2.739830026428688),
 (396.1864151538673, 1098.5582378920544, 2.739830026428688),
 (395.2915738652752, 1098.9384313245444, 2.739830026428688),
 (394.3967548911081, 1099.318677260896, 2.739492242286598),
 (393.5022271882191, 1099.69960782173, 2.738519982101022),
 (392.60807027168346, 1100.0814079160527, 2.737547721915446),
 (391.71428498673856, 1100.4640771829522, 2.7365754617298705)]

给定一个查询姿态,也可以找到车道上最近的姿态。

closest_pose_on_lane, distance_along_lane = arcline_path_utils.project_pose_to_lane((x, y, yaw), lane_record)

print(x, y, yaw)
closest_pose_on_lane

# 输出结果
395 1095 0
(396.25524909914367, 1098.5289922434013, 2.739830026428688)
# Meters
distance_along_lane

# 输出结果
27.5

要找到整个车道的长度,可以使用length_of_lane函数。

arcline_path_utils.length_of_lane(lane_record)

# 输出结果
32.08455403942341

还可以计算车道在车道上给定长度处的曲率。

# 0 表示这是一条直线车道。
arcline_path_utils.get_curvature_at_distance_along_lane(distance_along_lane, lane_record)

# 输出结果
0

探索数据

让我们在地图上渲染一个特定区块:

my_patch = (300, 1000, 500, 1200)
fig, ax = nusc_map.render_map_patch(my_patch, nusc_map.non_geometric_layers, figsize=(10, 10), bitmap=bitmap)

2023-05-27T02:16:31.png

在这个区块中可以看到很多图层。让我们获取所有在这个区块中的地图记录。

records_within_patch = nusc_map.get_records_in_patch(my_patch, nusc_map.non_geometric_layers, mode='within')
records_intersect_patch = nusc_map.get_records_in_patch(my_patch, nusc_map.non_geometric_layers, mode='intersect')

由于有很多记录,我们只关注道路段(road_segment)图层:

layer = 'road_segment'
print('Found %d records of %s (within).' % (len(records_within_patch[layer]), layer))
print('Found %d records of %s (intersect).' % (len(records_intersect_patch[layer]), layer))

# 输出结果
Found 25 records of road_segment (within).
Found 36 records of road_segment (intersect).

我们可以看到,使用 intersect 选项通常返回比 within 选项更多的记录。

根据上面的绘图,点(390,1100)似乎位于一个停车线上。让我们验证一下。

my_point = (390, 1100)
layers = nusc_map.layers_on_point(my_point[0], my_point[1])
assert len(layers['stop_line']) > 0, 'Error: No stop line found!'

确实,我们看到一个停车线记录。

要直接检查停车线记录,我们运行以下代码:

nusc_map.record_on_point(my_point[0], my_point[1], 'stop_line')

# 输出结果
'942dc2b1-345c-4fe7-83d0-9eeed8202709'

让我们看一下该记录的边界/端点。

nusc_map.get_bounds('stop_line', 'ac0a935f-99af-4dd4-95e3-71c92a5e58b1')

# 输出结果
(751.928131680929, 920.9848298895206, 762.8608345788314, 929.439260149884)

图层

让我们更详细地了解不同的地图图层:

nusc_map.layer_names

# 输出结果
['polygon',
 'line',
 'node',
 'drivable_area',
 'road_segment',
 'road_block',
 'lane',
 'ped_crossing',
 'walkway',
 'stop_line',
 'carpark_area',
 'lane_connector',
 'road_divider',
 'lane_divider',
 'traffic_light']

地图数据库由多个图层组成。每个图层由记录组成,每个记录都有一个令牌标识符。

我们可以看到地图图层分为两种类型的图层。一组图层属于geometric_layers组,另一组图层属于non_geometric_layers组。

  1. geometric_layers定义地图中的几何实体:

    • 节点(2D点)是所有几何图层的基础。
    • 线由两个或多个节点组成。形式上,一个Line记录可以由多个线段组成。
    • 多边形由三个或多个节点组成。多边形可以有孔,从而扭曲了其形式定义。孔被定义为形成多边形孔的节点序列。
  2. non_geometric_layers表示地图中的物理实体。它们可以具有多个几何表示(例如可行驶区域),但必须严格属于一种类型(例如road_segmentlane_divider)。

地图图层

nusc_map.geometric_layers

# 输出结果
['polygon', 'line', 'node']

Node

我们地图数据库中最原始的几何记录。这是唯一一个明确包含空间坐标的图层。

sample_node = nusc_map.node[0]
sample_node

# 输出结果
{'token': '2163fdc8-77fc-4c1c-a099-70bc5be9f9b7',
 'x': 994.6139837360693,
 'y': 1054.5199816348131}

Line

定义一个由一个或多个线段组成的线序列,因此由两个或更多节点组成。

sample_line = nusc_map.line[2]
sample_line

# 输出结果
{'token': '19f89773-f466-4d21-a583-4a963e6fe042',
 'node_tokens': ['ee2752d0-5fc9-495c-aa4b-fc24f703db1b',
  '48b2f4ea-9781-4cf2-82ff-624267be98d6',
  '9995a31d-089b-45f1-81ec-11925d17dbda']}

Polygon

定义一个可能包含孔的多边形。

每个多边形记录由外部节点列表和零个或多个节点列表(构成零个或多个孔)组成。

让我们来看一个多边形记录:

sample_polygon = nusc_map.polygon[3]
sample_polygon.keys()

# 输出结果
dict_keys(['token', 'exterior_node_tokens', 'holes'])
sample_polygon['exterior_node_tokens'][:10]

# 输出结果
['de837055-7009-42f2-80c7-cb224a9ce750',
 '86ee21c3-4a35-4f0e-9286-57b4cde9a2df',
 'ac4be197-c315-4233-98e0-d52007091090',
 '3ae2328f-cf1d-4597-8cc6-c9ac9f28f3b5',
 '3bb30867-05e0-4687-bd67-613ad5ad6476',
 '507d041c-5a0a-439e-9fbe-e57556e02d93',
 '19b5ae73-163a-47a7-b6f6-deea88d8d72f',
 'c0eedac8-f7d0-44d1-becc-535183fbf496',
 '9fe84337-f37d-4873-bd7b-be3922203a36',
 'cb8ee715-d481-49d6-a6c7-c765afccdfd5']
sample_holes = sample_polygon['holes'][0]
sample_holes

# 输出结果
{'node_tokens': ['13e0ec9d-e592-4d15-a30f-e61c5a04546f',
  'ed06f702-2a3f-4c7e-b200-6c41d20f04c7',
  '8e7b8e2f-7218-4e00-bce3-1f79245f5946',
  '542f7094-634e-4972-9108-602184f81ec8',
  '45dd272a-cda0-4de5-89b3-28ff539881e7',
  'c8952a38-8199-4580-b27c-ce7631f598cd',
  'f3def455-f19a-4379-9903-71628c0f9303',
  '16083beb-d393-4045-b903-bbd9a126d0bc',
  '80879705-d6ec-4f52-b54a-859a13c2670c',
  '1980fcec-6ba3-4fb4-b3c1-0126886cc29f',
  '1c01e9ae-2974-4863-856d-56f6a472355a',
  '85feaeae-1802-44f2-90af-9e04ca5934ff',
  'af88a07c-4aa6-479d-bc1e-7b9a824fc750',
  'f9a9097e-e844-486f-a497-f3521dd6bf2c',
  '86f21780-6f2a-4cbe-8aac-f13a0b5adf3f',
  '35e8c5f7-b89d-494b-9840-725cd4fa6010',
  'da77624e-765e-44f8-8374-c7513684f015',
  '28aa464f-93db-4ef1-a907-9abf07b5a380',
  '0e3ba3fd-3e85-4c26-bf20-d9144e5864cc',
  'ab924ff2-c6fe-41c0-b8f4-dc9db5fc1a48']}

非地图图层

每个非几何图层都与至少一个几何对象相关联。

nusc_map.non_geometric_layers

# 输出结果
['drivable_area',
 'road_segment',
 'road_block',
 'lane',
 'ped_crossing',
 'walkway',
 'stop_line',
 'carpark_area',
 'road_divider',
 'lane_divider',
 'traffic_light']

可行驶区域

可行驶区域被定义为汽车可以行驶的区域,不考虑行驶方向或法律限制。这是唯一一个记录可以由多个几何实体表示的图层。注意:在某些机器上,该多边形可能会错误地渲染为一个填充的黑色矩形。

sample_drivable_area = nusc_map.drivable_area[0]
sample_drivable_area

# 输出结果
{'token': 'c3e28556-b711-4581-9970-b66166fb907d',
 'polygon_tokens': ['fff7b0c9-1eaf-4988-afe3-e4e4607f85e3',
  'd235013d-2a07-4181-9862-c666b49a79b4',
  '0bbf311c-405d-433b-a097-7d9c292a9b87',
  'b4dfb634-2721-42d9-aa5d-0f8ec9a2fa31',
  'c4b4c925-6ddb-4e4b-a4ca-609e1ca626c2',
  'a60970c7-86cd-4169-ae9a-b9b51e4ec950',
  '1209379e-bc10-4d65-9fb1-0ee938032130']}
fig, ax = nusc_map.render_record('drivable_area', sample_drivable_area['token'], other_layers=[])

2023-05-27T02:52:00.png

道路段

可行驶区域上的一段道路。它具有一个is_intersection标志,用于表示特定道路段是否为交叉口。

它可能与其drivable_area_token字段中的可行驶区域记录相关联,也可能没有关联。

sample_road_segment = nusc_map.road_segment[600]
sample_road_segment

# 输出结果
{'token': 'c366bb7b-1f3b-4840-b7d3-9d3362b02589',
 'polygon_token': '254a099d-d884-4c5f-a444-d3703163f173',
 'is_intersection': True,
 'drivable_area_token': 'c3e28556-b711-4581-9970-b66166fb907d',
 'exterior_node_tokens': ['15d4c84c-a459-492d-8fae-619c6eccb60c',
  '4e336b1e-b67c-4452-bad5-fedfb970fac4',
  '6060b6c9-26c8-4887-8b7d-0aa67404cd1a',
  '54305c13-60f8-4976-a555-8d915eb9ae4f',
  '6a2e3ae8-72c8-4605-a644-8c74b8454c98',
  'f9190d61-9d7a-46cb-9f6d-909f51f7565a',
  'eef9c998-204a-40f6-ad27-a600849e1b68',
  'bfa79595-ab08-46b5-ae1a-c66c57ebbe9f',
  '439fc8a3-c175-4511-99bf-e993a016c280',
  'bd2ca111-5da9-4e2d-b4c1-13cedb1f96ef',
  'a95821b5-a97e-401c-b96c-938037a8fbb0',
  '10d9a934-338a-413b-8835-f8ae1d9abb87',
  '61372da3-bed1-4524-bca4-26cb2f4d0f8e',
  '4f639960-ad63-40e2-a58f-2e7387a5c846'],
 'holes': []}

正如观察到的那样,对于除了可行驶区域以外的所有非几何对象,我们都提供了一种访问其节点的快捷方式。

让我们来看一个is_intersection==Trueroad_segment记录。

sample_intersection_road_segment = nusc_map.road_segment[3]
sample_intersection_road_segment

# 输出结果
{'token': '00cbbc19-252e-4eef-a9e9-3158446bd794',
 'polygon_token': 'c6df6bdd-698c-40b2-b2a0-728eb5172efa',
 'is_intersection': True,
 'drivable_area_token': 'c3e28556-b711-4581-9970-b66166fb907d',
 'exterior_node_tokens': ['a29ee8f6-53a5-44c3-878f-5137e06b343d',
  '4d518646-6a49-4bad-96c8-e37af381a189',
  '6958b257-2443-4366-afb2-cfb9585e756b',
  'debfdfe0-d701-4833-ada6-ec8dd1d612b4',
  'c92b7476-10ac-4222-b5c0-f0512aca89b9',
  'd261ca11-b827-4cc2-ab34-092970b7d6fa',
  '3df5c6fc-92e5-40f2-bacf-6322f4896495',
  '8007e1bd-3ed6-4fab-8530-5717cfb93fc9',
  'cc8cf624-d4e1-4fed-a35a-d27ff7b3e4e9',
  '067e77f2-7443-46b1-a7e4-3ce0af7501a5',
  'a918f42d-5f99-477a-ad8f-027e1af656d8',
  '6063aace-dbc6-4761-a40d-e593d34ae8e6'],
 'holes': []}

如果我们渲染这个道路段,我们可以看到它确实是一个交叉口。

fig, ax = nusc_map.render_record('road_segment', sample_intersection_road_segment['token'], other_layers=[])

2023-05-27T02:54:40.png

道路阻塞

道路阻塞是具有相同交通方向的道路块。多个道路阻塞被分组在一个道路段中。

在道路阻塞中,车道数是一致的。

sample_road_block = nusc_map.road_block[0]
sample_road_block

# 输出结果
{'token': '002d8233-c9bf-4a9b-9d53-be86cd6cf73f',
 'polygon_token': '29fc4c78-75ae-4777-adab-f33d93591661',
 'from_edge_line_token': 'b0d2163e-732b-4be6-b6f7-2add8b4c7e8f',
 'to_edge_line_token': '7ce97362-1133-4c19-a73c-5cfa8f0d64f0',
 'road_segment_token': '85a06614-958c-461f-bc11-6cadd68efa7d',
 'exterior_node_tokens': ['46cf43f6-30ea-437e-83b3-42af3ce2783b',
  'aca16135-79a1-4acd-a68f-3918c38d54be',
  'ce31539b-d8c8-45a0-94df-3ac3a585225b',
  '26704699-79a6-4d4c-8ca2-d65ffb3ac11b',
  '2d0168af-7952-416d-8aff-7512130fb73d',
  'e3fa777d-d87a-45f9-bd41-5364e3bb9dd2',
  'bedec7db-1f55-4639-9826-ab8639ee250b',
  '05243627-6e25-472d-af1f-aca0ff30b00c'],
 'holes': []}

每个道路阻塞都有一个from_edge_line_tokento_edge_line_token,表示它的交通方向。

fig, ax = nusc_map.render_record('road_block', sample_road_block['token'], other_layers=[])

2023-05-27T02:56:32.png

车道

车道是道路的一部分,车辆在其中单向行驶。

sample_lane_record = nusc_map.lane[600]
sample_lane_record

# 输出结果
{'token': 'a6f12a5c-f6fa-4e99-993f-4cbd6f982c65',
 'polygon_token': 'd50a64b4-021c-4f73-8496-f6491eb0d3fa',
 'lane_type': 'CAR',
 'from_edge_line_token': '32f811fd-a2d8-4dc8-9785-8c43d0ea947c',
 'to_edge_line_token': 'ca27a4ad-37ca-44b7-8703-85aa39119a47',
 'left_lane_divider_segments': [],
 'right_lane_divider_segments': [],
 'exterior_node_tokens': ['124f5c61-f391-43f0-a245-32a325243a73',
  '55ad1d37-fe95-4e5c-a43e-1148ad4a13f6',
  'e3df7273-cb2e-4fef-8849-72141d549a1c',
  '9b5764b9-ca40-4622-afec-494d979b716a',
  '1066e47d-486e-45cf-affe-59c4e4e93fa9',
  '741bede3-d6c2-44c0-966f-fdce30f57817',
  'f5f4e292-056a-499b-b097-2e70e07435a7',
  'bbdf380c-9aed-4082-88e5-834eb39bca9e',
  'a040018c-3f38-4779-8876-6741b4aa4f81',
  '0d110059-c96f-413d-afd9-65963d4823fd',
  '1d0feda2-ee54-4ebd-aaa1-7c669089b4ef',
  '445a42dc-dbac-4fea-b03d-ece94729d0e8',
  'd8f8d28e-8be1-4c8a-a008-6c852b86363b'],
 'holes': [],
 'left_lane_divider_segment_nodes': [],
 'right_lane_divider_segment_nodes': []}

除了令牌和几何表示之外,车道还有几个字段:

fig, ax = nusc_map.render_record('lane', sample_lane_record['token'], other_layers=[])

2023-05-27T02:58:57.png

人行横道

人行横道是行人可以合法横穿道路的区域,通常由白色标线标识。每个人行横道记录必须位于一个道路段上。它具有road_segment_token字段,用于表示与其相关联的道路段记录。

sample_ped_crossing_record = nusc_map.ped_crossing[0]
sample_ped_crossing_record

# 输出结果
{'token': '027c4ccd-56c9-4980-9949-1d42bb36f23c',
 'polygon_token': '62138b18-6dd1-4c1e-8f11-7a2c8d5783c8',
 'road_segment_token': 'af7744d2-6dfe-4b9f-ab9a-58cc155f3f08',
 'exterior_node_tokens': ['58cf4a19-d28e-44b1-b4c0-bc217e50da1e',
  '0e3fda05-0936-4cbb-acbd-fc582750b3d3',
  '6a0f7286-8e6d-4fb5-b874-c830f090a05a',
  '0f45b051-0f14-469d-bde3-e8975b4d67cb'],
 'holes': []}
fig, ax = nusc_map.render_record('ped_crossing', sample_ped_crossing_record['token'])

2023-05-27T03:00:22.png

人行道

人行道或人行便道是通常位于道路旁的高出区域,用于保护行人免受道路上的车辆影响。

sample_walkway_record = nusc_map.walkway[0]
sample_walkway_record

# 输出结果
{'token': '00a01743-8d10-41ca-849e-ef6a32bee77d',
 'polygon_token': '17ff2a4b-a5c2-41d2-abf5-4a8aa07cb30f',
 'exterior_node_tokens': ['e7aa76d5-8368-4749-900d-dd2cbb4971e6',
  'c7187b86-fdb8-4eec-ba71-0f2c6ee0b57b',
  '8bd36561-55ef-4ff6-ab55-583dc59f2b73',
  '47db713d-fc9f-49bd-b5ba-6d89123f6357',
  '442e2766-733f-4147-b1cf-4238de3b93e1',
  '5a831f39-0352-4fcf-ab76-e696c9d5e651',
  'ac7839a1-73ef-4f39-80f0-e32ee2d816ae',
  '4434e104-1317-4bcd-bddf-ac0abb4e158c',
  '1cc537c7-1b78-443a-8513-8894cb807c8a',
  '85cff4b3-a56b-45e5-8e6b-880a73860696',
  '9344380b-375f-480f-9877-aa75e21b7acd',
  '6c5a6416-ab0c-4221-842a-bc5aa97da61b',
  '60e66d85-c5c1-4d27-8d67-d5ce28c2dac1',
  '68c442df-c38f-482e-b863-10afae9c69ce',
  '519240d4-5c8c-45e6-8d85-5ec78eac43bf',
  'f12f278c-e0ca-4c18-ab14-d6b259885687',
  '95e6e737-310d-4a9a-99aa-02dc4365ff19',
  'f69e2a9d-f43b-4a3d-834b-bc0de489caf5'],
 'holes': []}
fig, ax = nusc_map.render_record('walkway', sample_walkway_record['token'])

2023-05-27T03:05:10.png

停车线

停车线是物理世界中的停车线,尽管名称暗示它应该具有线段的几何表示,但实际上它的物理表示是一个区域,在该区域内自动驾驶车辆必须停车。

sample_stop_line_record = nusc_map.stop_line[1]
sample_stop_line_record

# 输出结果
{'token': '00904b8f-3166-47b8-9cbb-30062caec0eb',
 'polygon_token': '90102f73-9921-4d2a-8e07-148503868957',
 'stop_line_type': 'TURN_STOP',
 'ped_crossing_tokens': ['96748923-eabf-4142-8458-92ff580e997f'],
 'traffic_light_tokens': [],
 'road_block_token': '',
 'exterior_node_tokens': ['a3e110de-2443-406f-bf54-ef9b4dc46939',
  'e5d038c8-f964-4ae2-b498-9952496c801f',
  'bbec1377-0e20-4888-9f79-2a1aa50b3b88',
  '37a078fa-2804-412e-b8b9-682fe21ad8be',
  '50597561-e04f-4ea1-894a-cfd2c212aef0',
  'b05b2d23-3a12-493d-9d8d-e57f4f8ddc60'],
 'holes': [],
 'cue': [{'token': '96748923-eabf-4142-8458-92ff580e997f',
   'polygon_token': 'f8a39c38-1d04-4dc0-9e35-f63966e56250',
   'road_segment_token': '6ea9d0a6-65e7-4038-ae50-4fb89a4c296d',
   'exterior_node_tokens': ['7931be00-b6a7-437d-9335-e4314dbe47b4',
    '1f6f7c4a-27a2-4a18-96bd-fe597546440f',
    'a28f6633-a23e-44f6-8355-0c06df42005e',
    '235431b5-9f71-452d-a3b2-bdeaaa44aa41'],
   'holes': []}]}

它具有以下几个属性:

fig, ax = nusc_map.render_record('stop_line', sample_stop_line_record['token'])

2023-05-27T03:06:15.png

停车场区域

停车场或停车场区域。

sample_carpark_area_record = nusc_map.carpark_area[1]
sample_carpark_area_record

# 输出结果
{'token': '0a711883-2477-4eb5-aef8-cc9ad3e3158a',
 'polygon_token': 'eca315c8-cfb7-4759-a91a-d148d08ef2eb',
 'orientation': 2.5073506567369885,
 'road_block_token': '2b60cc1b-0882-4ef3-8207-f7cb3561aff9',
 'exterior_node_tokens': ['0043375d-b853-4149-94a5-3ca6c984e3d8',
  '5aa572e1-1848-4739-bbd8-f5934fb3e1ea',
  '5419cf3e-9e02-4683-adae-fe0dcd948644',
  'ba9efc27-c461-402f-a172-e451e92ef7c8'],
 'holes': []}

它具有以下几个属性:

fig, ax = nusc_map.render_record('carpark_area', sample_carpark_area_record['token'])

2023-05-27T03:10:05.png

道路隔离带

用于将一个道路阻塞与另一个道路阻塞分隔开的隔离带。

sample_road_divider_record = nusc_map.road_divider[0]
sample_road_divider_record

# 输出结果
{'token': '00bbfc65-0b44-4b4c-b517-6d87dc02529c',
 'line_token': '98c91318-5854-41ac-9210-001b57b8185f',
 'road_segment_token': 'b1ed2f76-bfcd-4b0c-b367-7a20cf707b95',
 'node_tokens': ['4e2605d4-b9f4-41f9-a03c-032c8d4a3c24',
  '1cbbdda6-5ee6-4b4d-8bcc-30af18094978']}

road_segment_token保存了与road_segment的关联信息。

fig, ax = nusc_map.render_record('road_divider', sample_road_divider_record['token'])

2023-05-27T03:11:35.png

车道分隔带

车道分隔带位于指向相同交通方向的车道之间。

sample_lane_divider_record = nusc_map.lane_divider[0]
sample_lane_divider_record

# 输出结果
{'token': '00569b72-a7dc-4cdf-9bf3-7f3583c6dbae',
 'line_token': '9ac741dc-20b5-44f3-9f0a-41e371a722ee',
 'lane_divider_segments': [{'node_token': '57d546eb-682c-4540-871c-2e8d6a67f2de',
   'segment_type': 'DOUBLE_DASHED_WHITE'},
  {'node_token': 'fef2c634-7096-4b48-bf87-6575d2a67b56',
   'segment_type': 'DOUBLE_DASHED_WHITE'},
  {'node_token': '153990f1-b0da-4243-a065-e4a99d29e180',
   'segment_type': 'DOUBLE_DASHED_WHITE'},
  {'node_token': '8ad3000f-c1e9-4eda-8bf1-c5f64a879c54',
   'segment_type': 'NIL'}],
 'node_tokens': ['57d546eb-682c-4540-871c-2e8d6a67f2de',
  'fef2c634-7096-4b48-bf87-6575d2a67b56',
  '153990f1-b0da-4243-a065-e4a99d29e180',
  '8ad3000f-c1e9-4eda-8bf1-c5f64a879c54']}

lane_divider_segments字段由不同的node和它们各自的segment_type组成,这些segment_type表示它们的物理外观。

fig, ax = nusc_map.render_record('lane_divider', sample_lane_divider_record['token'])

2023-05-27T03:13:38.png

红绿灯

现实世界中的交通信号灯。

sample_traffic_light_record = nusc_map.traffic_light[0]
sample_traffic_light_record

# 输出结果
{'token': '00590fed-3542-4c20-9927-f822134be5fc',
 'line_token': '5bffb006-bce8-44a4-a466-5580f1d748fd',
 'traffic_light_type': 'VERTICAL',
 'from_road_block_token': '71c79c48-819c-4b17-ad28-2a9e82ba1596',
 'items': [{'color': 'RED',
   'shape': 'CIRCLE',
   'rel_pos': {'tx': 0.0,
    'ty': 0.0,
    'tz': 0.632,
    'rx': 0.0,
    'ry': 0.0,
    'rz': 0.0},
   'to_road_block_tokens': []},
  {'color': 'YELLOW',
   'shape': 'CIRCLE',
   'rel_pos': {'tx': 0.0,
    'ty': 0.0,
    'tz': 0.381,
    'rx': 0.0,
    'ry': 0.0,
    'rz': 0.0},
   'to_road_block_tokens': []},
  {'color': 'GREEN',
   'shape': 'CIRCLE',
   'rel_pos': {'tx': 0.0,
    'ty': 0.0,
    'tz': 0.13,
    'rx': 0.0,
    'ry': 0.0,
    'rz': 0.0},
   'to_road_block_tokens': []},
  {'color': 'GREEN',
   'shape': 'RIGHT',
   'rel_pos': {'tx': 0.0,
    'ty': -0.26,
    'tz': 0.13,
    'rx': 0.0,
    'ry': 0.0,
    'rz': 0.0},
   'to_road_block_tokens': ['bd26d490-8822-469b-ae60-74f6c0c9e1cb']}],
 'pose': {'tx': 369.2207339994191,
  'ty': 1129.3945093980494,
  'tz': 2.4,
  'rx': 0.0,
  'ry': 0.0,
  'rz': -0.6004778487509836},
 'node_tokens': ['8e483ef5-75e5-417a-bc78-fa7750297fb1',
  '78a4b686-3207-48fa-ae2a-d5f875e0ee37']}

它具有以下几个属性:

让我们来检查一下items字段。

sample_traffic_light_record['items']

# 输出结果
[{'color': 'RED',
  'shape': 'CIRCLE',
  'rel_pos': {'tx': 0.0,
   'ty': 0.0,
   'tz': 0.632,
   'rx': 0.0,
   'ry': 0.0,
   'rz': 0.0},
  'to_road_block_tokens': []},
 {'color': 'YELLOW',
  'shape': 'CIRCLE',
  'rel_pos': {'tx': 0.0,
   'ty': 0.0,
   'tz': 0.381,
   'rx': 0.0,
   'ry': 0.0,
   'rz': 0.0},
  'to_road_block_tokens': []},
 {'color': 'GREEN',
  'shape': 'CIRCLE',
  'rel_pos': {'tx': 0.0,
   'ty': 0.0,
   'tz': 0.13,
   'rx': 0.0,
   'ry': 0.0,
   'rz': 0.0},
  'to_road_block_tokens': []},
 {'color': 'GREEN',
  'shape': 'RIGHT',
  'rel_pos': {'tx': 0.0,
   'ty': -0.26,
   'tz': 0.13,
   'rx': 0.0,
   'ry': 0.0,
   'rz': 0.0},
  'to_road_block_tokens': ['bd26d490-8822-469b-ae60-74f6c0c9e1cb']}]

如前所述,items字段中的每个条目都是一个交通信号灯的灯泡。它包含颜色信息、形状信息、相对位置(rel_pos)以及指示该交通信号灯灯泡引导到哪些道路障碍物(to_road_block_tokens)。

参考

Responses