Skip to content

Commit 328448a

Browse files
committed
Add road lines to argoverse map. Change road line types to argoverse convention
1 parent 2ee7bcf commit 328448a

File tree

8 files changed

+106
-70
lines changed

8 files changed

+106
-70
lines changed

d123/dataset/conversion/map/opendrive/opendrive_map_conversion.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,19 +358,19 @@ def _extract_road_line_df(
358358
if str(lane_row.right_lane_id) in ["nan", "None"]:
359359
# This is a boundary lane, e.g. a border or sidewalk
360360
ids.append(running_id)
361-
road_line_types.append(int(RoadLineType.SOLID_SINGLE_WHITE))
361+
road_line_types.append(int(RoadLineType.SOLID_WHITE))
362362
geometries.append(lane_row.right_boundary)
363363
running_id += 1
364364
else:
365365
# This is a regular lane
366366
ids.append(running_id)
367-
road_line_types.append(int(RoadLineType.BROKEN_SINGLE_WHITE))
367+
road_line_types.append(int(RoadLineType.DASHED_WHITE))
368368
geometries.append(lane_row.right_boundary)
369369
running_id += 1
370370
if str(lane_row.left_lane_id) in ["nan", "None"]:
371371
# This is a boundary lane, e.g. a border or sidewalk
372372
ids.append(running_id)
373-
road_line_types.append(int(RoadLineType.SOLID_SINGLE_WHITE))
373+
road_line_types.append(int(RoadLineType.DASHED_WHITE))
374374
geometries.append(lane_row.left_boundary)
375375
running_id += 1
376376

d123/dataset/dataset_specific/av2/av2_constants.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from d123.common.datatypes.detection.detection_types import DetectionType
22
from d123.common.datatypes.sensor.camera import CameraType
33
from d123.common.utils.enums import SerialIntEnum
4+
from d123.dataset.maps.map_datatypes import RoadLineType
45

56

67
class AV2SensorBoxDetectionType(SerialIntEnum):
@@ -85,3 +86,22 @@ class AV2SensorBoxDetectionType(SerialIntEnum):
8586
"stereo_front_left": CameraType.CAM_STEREO_L,
8687
"stereo_front_right": CameraType.CAM_STEREO_R,
8788
}
89+
90+
91+
AV2_ROAD_LINE_TYPE_MAPPING = {
92+
"NONE": RoadLineType.NONE,
93+
"UNKNOWN": RoadLineType.UNKNOWN,
94+
"DASH_SOLID_YELLOW": RoadLineType.DASH_SOLID_YELLOW,
95+
"DASH_SOLID_WHITE": RoadLineType.DASH_SOLID_WHITE,
96+
"DASHED_WHITE": RoadLineType.DASHED_WHITE,
97+
"DASHED_YELLOW": RoadLineType.DASHED_YELLOW,
98+
"DOUBLE_SOLID_YELLOW": RoadLineType.DOUBLE_SOLID_YELLOW,
99+
"DOUBLE_SOLID_WHITE": RoadLineType.DOUBLE_SOLID_WHITE,
100+
"DOUBLE_DASH_YELLOW": RoadLineType.DOUBLE_DASH_YELLOW,
101+
"DOUBLE_DASH_WHITE": RoadLineType.DOUBLE_DASH_WHITE,
102+
"SOLID_YELLOW": RoadLineType.SOLID_YELLOW,
103+
"SOLID_WHITE": RoadLineType.SOLID_WHITE,
104+
"SOLID_DASH_WHITE": RoadLineType.SOLID_DASH_WHITE,
105+
"SOLID_DASH_YELLOW": RoadLineType.SOLID_DASH_YELLOW,
106+
"SOLID_BLUE": RoadLineType.SOLID_BLUE,
107+
}

d123/dataset/dataset_specific/av2/av2_map_conversion.py

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warnings
12
from pathlib import Path
23
from typing import Any, Dict, Final, List
34

@@ -16,11 +17,16 @@
1617
from d123.dataset.conversion.map.road_edge.road_edge_3d_utils import (
1718
get_road_edges_3d_from_generic_drivable_area_df,
1819
)
19-
from d123.dataset.maps.map_datatypes import MapLayer, RoadEdgeType, RoadLineType
20-
21-
# TODO:
22-
# - TODO
23-
LANE_GROUP_MARK_TYPES = ["DASHED_WHITE", "DOUBLE_DASH_WHITE", "DASH_SOLID_WHITE", "SOLID_DASH_WHITE", "SOLID_WHITE"]
20+
from d123.dataset.dataset_specific.av2.av2_constants import AV2_ROAD_LINE_TYPE_MAPPING
21+
from d123.dataset.maps.map_datatypes import MapLayer, RoadEdgeType
22+
23+
LANE_GROUP_MARK_TYPES: List[str] = [
24+
"DASHED_WHITE",
25+
"DOUBLE_DASH_WHITE",
26+
"DASH_SOLID_WHITE",
27+
"SOLID_DASH_WHITE",
28+
"SOLID_WHITE",
29+
]
2430
MAX_ROAD_EDGE_LENGTH: Final[float] = 100.0 # TODO: Add to config
2531

2632

@@ -73,29 +79,27 @@ def _extract_polyline(data: List[Dict[str, float]], close: bool = False) -> Poly
7379
lane_group_dict = _extract_lane_group_dict(log_map_archive["lane_segments"])
7480
intersection_dict = _extract_intersection_dict(log_map_archive["lane_segments"], lane_group_dict)
7581

76-
lane_df = get_lane_df(log_map_archive["lane_segments"])
77-
lane_group_df = get_lane_group_df(lane_group_dict)
78-
intersection_df = get_intersections_df(intersection_dict)
79-
crosswalk_df = get_crosswalk_df(log_map_archive["pedestrian_crossings"])
80-
walkway_df = get_empty_gdf() # NOTE: AV2 does not provide walkways, so we create an empty DataFrame.
81-
carpark_df = get_empty_gdf() # NOTE: AV2 does not provide carparks, so we create an empty DataFrame.
82-
generic_drivable_df = get_generic_drivable_df(drivable_areas)
83-
road_edge_df = get_road_edge_df(generic_drivable_df)
84-
# road_line_df = get_empty_gdf()
82+
dataframes: Dict[MapLayer, gpd.GeoDataFrame] = {}
83+
84+
dataframes[MapLayer.LANE] = get_lane_df(log_map_archive["lane_segments"])
85+
dataframes[MapLayer.LANE_GROUP] = get_lane_group_df(lane_group_dict)
86+
dataframes[MapLayer.INTERSECTION] = get_intersections_df(intersection_dict)
87+
dataframes[MapLayer.CROSSWALK] = get_crosswalk_df(log_map_archive["pedestrian_crossings"])
88+
dataframes[MapLayer.GENERIC_DRIVABLE] = get_generic_drivable_df(drivable_areas)
89+
dataframes[MapLayer.ROAD_EDGE] = get_road_edge_df(dataframes[MapLayer.GENERIC_DRIVABLE])
90+
dataframes[MapLayer.ROAD_LINE] = get_road_line_df(log_map_archive["lane_segments"])
91+
# NOTE: AV2 does not provide walkways or carparks, so we create an empty DataFrame.
92+
dataframes[MapLayer.WALKWAY] = get_empty_gdf()
93+
dataframes[MapLayer.CARPARK] = get_empty_gdf()
8594

8695
map_file_path.unlink(missing_ok=True)
8796
if not map_file_path.parent.exists():
8897
map_file_path.parent.mkdir(parents=True, exist_ok=True)
8998

90-
lane_df.to_file(map_file_path, layer=MapLayer.LANE.serialize(), driver="GPKG")
91-
lane_group_df.to_file(map_file_path, layer=MapLayer.LANE_GROUP.serialize(), driver="GPKG", mode="a")
92-
intersection_df.to_file(map_file_path, layer=MapLayer.INTERSECTION.serialize(), driver="GPKG", mode="a")
93-
crosswalk_df.to_file(map_file_path, layer=MapLayer.CROSSWALK.serialize(), driver="GPKG", mode="a")
94-
walkway_df.to_file(map_file_path, layer=MapLayer.WALKWAY.serialize(), driver="GPKG", mode="a")
95-
carpark_df.to_file(map_file_path, layer=MapLayer.CARPARK.serialize(), driver="GPKG", mode="a")
96-
generic_drivable_df.to_file(map_file_path, layer=MapLayer.GENERIC_DRIVABLE.serialize(), driver="GPKG", mode="a")
97-
road_edge_df.to_file(map_file_path, layer=MapLayer.ROAD_EDGE.serialize(), driver="GPKG", mode="a")
98-
# road_line_df.to_file(map_file_path, layer=MapLayer.ROAD_LINE.serialize(), driver="GPKG", mode="a")
99+
with warnings.catch_warnings():
100+
warnings.filterwarnings("ignore", message="'crs' was not provided")
101+
for layer, gdf in dataframes.items():
102+
gdf.to_file(map_file_path, layer=layer.serialize(), driver="GPKG", mode="a")
99103

100104

101105
def get_empty_gdf() -> gpd.GeoDataFrame:
@@ -151,10 +155,7 @@ def _get_centerline_from_boundaries(
151155
left_boundary=lane_dict["left_lane_boundary"],
152156
right_boundary=lane_dict["right_lane_boundary"],
153157
)
154-
lane_speed_limit_mps = None
155-
156-
# ids.append(lane_id)
157-
# lane_types.append(lanes_type[lane_id])
158+
lane_speed_limit_mps = None # TODO: Consider using geo reference to retrieve speed limits.
158159
lane_group_ids.append(lane_id)
159160
speed_limits_mps.append(lane_speed_limit_mps)
160161
predecessor_ids.append(lane_dict["predecessors"])
@@ -313,18 +314,28 @@ def get_road_edge_df(generic_drivable_area_df: gpd.GeoDataFrame) -> gpd.GeoDataF
313314
return gpd.GeoDataFrame(pd.DataFrame({"id": ids, "road_edge_type": road_edge_types}), geometry=geometries)
314315

315316

316-
def get_road_line_df(
317-
road_lines: Dict[int, npt.NDArray[np.float64]], road_lines_type: Dict[int, RoadLineType]
318-
) -> gpd.GeoDataFrame:
319-
ids = list(road_lines.keys())
320-
geometries = [Polyline3D.from_array(road_edge).linestring for road_edge in road_lines.values()]
317+
def get_road_line_df(lanes: Dict[int, Any]) -> gpd.GeoDataFrame:
321318

322-
data = pd.DataFrame(
323-
{
324-
"id": ids,
325-
"road_line_type": [int(road_line_type) for road_line_type in road_lines_type.values()],
326-
}
327-
)
319+
# TODO @DanielDauner: Allow lanes to reference road line dataframe.
320+
321+
ids = []
322+
road_lines_type = []
323+
geometries = []
324+
325+
running_id = 0
326+
for lane in lanes.values():
327+
for side in ["left", "right"]:
328+
# NOTE: We currently ignore lane markings that are NONE in the AV2 dataset.
329+
# TODO: Review if the road line system should be changed in the future.
330+
if lane[f"{side}_lane_mark_type"] == "NONE":
331+
continue
332+
333+
ids.append(running_id)
334+
road_lines_type.append(AV2_ROAD_LINE_TYPE_MAPPING[lane[f"{side}_lane_mark_type"]])
335+
geometries.append(lane[f"{side}_lane_boundary"].linestring)
336+
running_id += 1
337+
338+
data = pd.DataFrame({"id": ids, "road_line_type": road_lines_type})
328339
gdf = gpd.GeoDataFrame(data, geometry=geometries)
329340
return gdf
330341

d123/dataset/dataset_specific/nuplan/nuplan_map_conversion.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@
5353
MAX_ROAD_EDGE_LENGTH = 100.0 # meters, used to filter out very long road edges
5454

5555
NUPLAN_ROAD_LINE_CONVERSION = {
56-
0: RoadLineType.BROKEN_SINGLE_WHITE,
57-
2: RoadLineType.SOLID_SINGLE_WHITE,
56+
0: RoadLineType.DASHED_WHITE,
57+
2: RoadLineType.SOLID_WHITE,
58+
3: RoadLineType.UNKNOWN,
5859
}
5960

6061

@@ -443,9 +444,6 @@ def _extract_road_line_dataframe(self) -> gpd.GeoDataFrame:
443444
geometries = []
444445

445446
for idx in range(len(boundary_types)):
446-
# NOTE @DanielDauner: We ignore boundaries of nuPlan-type, which are on intersections.
447-
if boundary_types[idx] not in NUPLAN_ROAD_LINE_CONVERSION.keys():
448-
continue
449447
ids.append(fids[idx])
450448
road_line_types.append(int(NUPLAN_ROAD_LINE_CONVERSION[boundary_types[idx]]))
451449
geometries.append(boundaries[idx])

d123/dataset/dataset_specific/wopd/waymo_map_utils/wopd_map_utils.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,17 @@
2020
# - Implement speed bumps
2121
# - Implement driveways with a different semantic type if needed
2222
# - Implement intersections and lane group logic
23-
# - Handle lane type, e.g. TYPE_UNDEFINED = 0; TYPE_FREEWAY = 1; TYPE_SURFACE_STREET = 2; TYPE_BIKE_LANE = 3;
2423

2524
WAYMO_ROAD_LINE_CONVERSION = {
26-
0: RoadLineType.UNKNOWN,
27-
1: RoadLineType.BROKEN_SINGLE_WHITE,
28-
2: RoadLineType.SOLID_SINGLE_WHITE,
29-
3: RoadLineType.SOLID_DOUBLE_WHITE,
30-
4: RoadLineType.BROKEN_SINGLE_YELLOW,
31-
5: RoadLineType.BROKEN_DOUBLE_YELLOW,
32-
6: RoadLineType.SOLID_SINGLE_YELLOW,
33-
7: RoadLineType.SOLID_DOUBLE_YELLOW,
34-
8: RoadLineType.PASSING_DOUBLE_YELLOW,
25+
0: RoadLineType.UNKNOWN, # aka. UNKNOWN
26+
1: RoadLineType.DASHED_WHITE, # aka. BROKEN_SINGLE_WHITE
27+
2: RoadLineType.SOLID_WHITE, # aka. SOLID_SINGLE_WHITE
28+
3: RoadLineType.DOUBLE_SOLID_WHITE, # aka. SOLID_DOUBLE_WHITE
29+
4: RoadLineType.DASHED_YELLOW, # aka. BROKEN_SINGLE_YELLOW
30+
5: RoadLineType.DOUBLE_DASH_YELLOW, # aka. BROKEN_DOUBLE_YELLOW
31+
6: RoadLineType.SOLID_YELLOW, # aka. SOLID_SINGLE_YELLOW
32+
7: RoadLineType.DOUBLE_SOLID_YELLOW, # aka. SOLID_DOUBLE_YELLOW
33+
8: RoadLineType.DOUBLE_DASH_YELLOW, # aka. PASSING_DOUBLE_YELLOW
3534
}
3635

3736
WAYMO_ROAD_EDGE_CONVERSION = {

d123/dataset/maps/map_datatypes.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class MapLayer(SerialIntEnum):
2525
class LaneType(SerialIntEnum):
2626
"""
2727
Enum for LaneType.
28-
NOTE: We use the lane types from Waymo.
2928
https://github.com/waymo-research/waymo-open-dataset/blob/99a4cb3ff07e2fe06c2ce73da001f850f628e45a/src/waymo_open_dataset/protos/map.proto#L147
3029
"""
3130

@@ -55,12 +54,18 @@ class RoadLineType(SerialIntEnum):
5554
https://github.com/waymo-research/waymo-open-dataset/blob/master/src/waymo_open_dataset/protos/map.proto#L208
5655
"""
5756

58-
UNKNOWN = 0
59-
BROKEN_SINGLE_WHITE = 1
60-
SOLID_SINGLE_WHITE = 2
61-
SOLID_DOUBLE_WHITE = 3
62-
BROKEN_SINGLE_YELLOW = 4
63-
BROKEN_DOUBLE_YELLOW = 5
64-
SOLID_SINGLE_YELLOW = 6
65-
SOLID_DOUBLE_YELLOW = 7
66-
PASSING_DOUBLE_YELLOW = 8
57+
NONE = 0
58+
UNKNOWN = 1
59+
DASH_SOLID_YELLOW = 2
60+
DASH_SOLID_WHITE = 3
61+
DASHED_WHITE = 4
62+
DASHED_YELLOW = 5
63+
DOUBLE_SOLID_YELLOW = 6
64+
DOUBLE_SOLID_WHITE = 7
65+
DOUBLE_DASH_YELLOW = 8
66+
DOUBLE_DASH_WHITE = 9
67+
SOLID_YELLOW = 10
68+
SOLID_WHITE = 11
69+
SOLID_DASH_WHITE = 12
70+
SOLID_DASH_YELLOW = 13
71+
SOLID_BLUE = 14

notebooks/av2/delete_me_map.ipynb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@
4343
"id": "2",
4444
"metadata": {},
4545
"outputs": [],
46-
"source": []
46+
"source": [
47+
"for lane_segment_id, lane_segment_dict in log_map_archive[\"lane_segments\"].items():\n",
48+
" print(f\"Lane Segment ID: {lane_segment_id}\")"
49+
]
4750
},
4851
{
4952
"cell_type": "code",

notebooks/viz/bev_matplotlib.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@
210210
" box_detections = scene.get_box_detections_at_iteration(iteration)\n",
211211
"\n",
212212
" point_2d = ego_vehicle_state.bounding_box.center.state_se2.point_2d\n",
213-
" add_debug_map_on_ax(ax, scene.map_api, point_2d, radius=radius, route_lane_group_ids=None)\n",
214-
" # add_default_map_on_ax(ax, scene.map_api, point_2d, radius=radius, route_lane_group_ids=None)\n",
213+
" # add_debug_map_on_ax(ax, scene.map_api, point_2d, radius=radius, route_lane_group_ids=None)\n",
214+
" add_default_map_on_ax(ax, scene.map_api, point_2d, radius=radius, route_lane_group_ids=None)\n",
215215
" # add_traffic_lights_to_ax(ax, traffic_light_detections, scene.map_api)\n",
216216
"\n",
217217
" add_box_detections_to_ax(ax, box_detections)\n",
@@ -238,7 +238,7 @@
238238
"\n",
239239
"scene_index = 9\n",
240240
"iteration = 99\n",
241-
"fig, ax = plot_scene_at_iteration(scenes[scene_index], iteration=iteration, radius=100)\n",
241+
"fig, ax = plot_scene_at_iteration(scenes[scene_index], iteration=iteration, radius=30)\n",
242242
"plt.show()\n",
243243
"\n",
244244
"# camera = scenes[scene_index].get_camera_at_iteration(\n",

0 commit comments

Comments
 (0)