Source code for commonroad.scenario.traffic_sign

import enum
import warnings
from typing import List, Set, Union

import numpy as np

import commonroad.geometry.transform
from commonroad.common.validity import (
    is_real_number,
    is_real_number_vector,
    is_valid_orientation,
)
from commonroad.visualization.draw_params import (
    OptionalSpecificOrAllDrawParams,
    TrafficSignParams,
)
from commonroad.visualization.drawable import IDrawable
from commonroad.visualization.renderer import IRenderer

TRAFFIC_SIGN_VALIDITY_START = {
    "WARNING_DANGER_SPOT",
    "WARNING_RIGHT_BEFORE_LEFT",
    "WARNING_STEEP_HILL_DOWNWARDS",
    "WARNING_SLIPPERY_ROAD",
    "WARNING_CONSTRUCTION_SITE",
    "WARNING_CROSSING_CYCLIST",
    "WARNING_ANIMAL_CROSSING_RIGHT",
    "RAILWAY",
    "PRIORITY_OPPOSITE_DIRECTION",
    "TURN_RIGHT_AHEAD",
    "TURN_LEFT_AHEAD",
    "ONEWAY_RIGHT",
    "ONEWAY_LEFT",
    "PRESCRIBED_PASSING_LEFT",
    "PRESCRIBED_PASSING_RIGHT",
    "BIKEWAY",
    "PEDESTRIAN_SIDEWALK",
    "PEDESTRIAN_ZONE_START",
    "BICYCLE_ROAD_START",
    "BUS_LANE",
    "BAN_ALL_VEHICLES",
    "BAN_CARS",
    "BAN_TRUCKS",
    "BAN_BICYCLE",
    "BAN_MOTORCYCLE",
    "BAN_BUS",
    "BAN_PEDESTRIAN",
    "BAN_CAR_TRUCK_BUS_MOTORCYCLE",
    "BAN_VEHICLES_CARRYING_DANGEROUS_GOODS",
    "NO_ENTRY",
    "MAX_WEIGHT",
    "MAX_WIDTH",
    "MAX_HEIGHT",
    "MAX_LENGTH",
    "MAX_SPEED",
    "MAX_SPEED_ZONE_START",
    "MIN_SPEED",
    "NO_OVERTAKING_START",
    "NO_OVERTAKING_TRUCKS_START",
    "TRAFFIC_CALMED_AREA_START",
    "PRIORITY_OVER_ONCOMING",
    "TOWN_SIGN",
    "TUNNEL",
    "INTERSTATE_START",
    "HIGHWAY_START",
    "PEDESTRIANS_CROSSING",
}

TRAFFIC_SIGN_WITH_ADDITIONAL_VALUE = {
    "MAX_WEIGHT",
    "MAX_WIDTH",
    "MAX_HEIGHT",
    "MAX_LENGTH",
    "MAX_SPEED",
    "MAX_SPEED_ZONE_START",
    "MIN_SPEED",
    "ADDITION_VALID_FOR_X_METERS",
    "ADDITION_VALID_IN_X_KILOMETERS",
    "ADDITION_TIME_PERIOD_PERMITTED",
}

LEFT_HAND_TRAFFIC = {
    "AUS",
    "JPN",
    "HKG",
    "IND",
    "JEY",
    "IMN",
    "IRL",
    "JAM",
    "KEN",
    "MLT",
    "MYS",
    "NPL",
    "NZL",
    "ZAF",
    "SGP",
    "THA",
    "GBR",
    "IDN",
    "MAC",
    "PAK",
    "CYP",
}


@enum.unique
class TrafficSignID(enum.Enum):
    # German
    WARNING_DANGER_SPOT = 0
    WARNING_RIGHT_BEFORE_LEFT = 1
    WARNING_LEFT_CURVE = 2
    WARNING_RIGHT_CURVE = 3
    WARNING_STEEP_HILL_DOWNWARDS = 4
    WARNING_SLIPPERY_ROAD = 5
    WARNING_CONSTRUCTION_SITE = 6
    WARNING_TRAFFIC_QUEUES_LIKELY = 7
    WARNING_ONCOMING_TRAFFIC = 8
    WARNING_TRAFFIC_LIGHTS_AHEAD = 9
    WARNING_PEDESTRIANS_RIGHT = 10
    WARNING_PEDESTRIANS_LEFT = 11
    WARNING_CROSSING_CYCLIST = 12
    WARNING_ANIMAL_CROSSING_RIGHT = 13
    WARNING_LOOSE_GRAVEL = 14
    RAILWAY = 15
    YIELD = 16
    STOP = 17
    PRIORITY_OPPOSITE_DIRECTION = 18
    TURN_RIGHT_AHEAD = 19
    TURN_LEFT_AHEAD = 20
    KEEP_STRAIGHT_AHEAD = 21
    PRESCRIBED_DIRECTION_RIGHT = 22
    ROUNDABOUT = 23
    ONEWAY_RIGHT = 24
    ONEWAY_LEFT = 25
    PRESCRIBED_PASSING_LEFT = 26
    PRESCRIBED_PASSING_RIGHT = 27
    DO_NOT_DRIVE_ON_SHOULDER_LANE = 28
    DO_NOT_DRIVE_ON_SHOULDER_LANE_2_LANE = 29
    DO_NOT_DRIVE_ON_SHOULDER_LANE_3_LANE = 30
    BUS_STOP = 31
    BIKEWAY = 32
    PEDESTRIAN_SIDEWALK = 33
    PEDESTRIAN_AND_BICYCLE_ROAD = 34
    PEDESTRIAN_ZONE_START = 35
    PEDESTRIAN_ZONE_END = 36
    BICYCLE_ROAD_START = 37
    BICYCLE_ROAD_END = 38
    BUS_LANE = 39
    BAN_ALL_VEHICLES = 40
    BAN_CARS = 41
    BAN_TRUCKS = 42
    BAN_BICYCLE = 43
    BAN_MOTORCYCLE = 44
    BAN_BUS = 45
    BAN_PEDESTRIAN = 46
    BAN_CAR_TRUCK_BUS_MOTORCYCLE = 47
    BAN_VEHICLES_CARRYING_DANGEROUS_GOODS = 48
    MAX_WEIGHT = 49
    MAX_WIDTH = 50
    MAX_HEIGHT = 51
    MAX_LENGTH = 52
    NO_ENTRY = 53
    ENVIRONMENTAL_ZONE_START = 54
    ENVIRONMENTAL_ZONE_END = 55
    U_TURN = 56
    MAX_SPEED = 57
    MAX_SPEED_ZONE_START = 58
    MAX_SPEED_ZONE_END = 59
    MIN_SPEED = 60
    NO_OVERTAKING_START = 61
    NO_OVERTAKING_TRUCKS_START = 62
    MAX_SPEED_END = 63
    NO_OVERTAKING_END = 64
    NO_OVERTAKING_TRUCKS_END = 65
    ALL_MAX_SPEED_AND_OVERTAKING_END = 66
    NO_STOP_START_RIGHT = 67
    NO_STOP_CENTER_RIGHT = 68
    RESTRICTED_STOP_CENTER_RIGHT = 69
    RIGHT_OF_WAY = 70
    PRIORITY = 71
    PRIORITY_OVER_ONCOMING = 72
    TOWN_SIGN = 73
    TOWN_SIGN_BACK = 74
    PARKING_AREA = 75
    PARKING_AREA_LEFT = 76
    PARKING_AREA_RIGHT = 77
    PARKING_AREA_RIGHT_LEFT = 78
    TRAFFIC_CALMED_AREA_START = 79
    TRAFFIC_CALMED_AREA_END = 80
    TUNNEL = 81
    EMERGENCY_STOP = 82
    INTERSTATE_START = 83
    INTERSTATE_END = 84
    HIGHWAY_START = 85
    HIGHWAY_END = 86
    HIGHWAY_EXIT_WITH_PLACE_NAME = 87
    EXIT_ROUTE = 88
    HIGHWAY_EXIT = 89
    EXIT_BUILT_UP = 90
    EXIT_GENERAL = 91
    PEDESTRIANS_CROSSING = 92
    WATER_PROTECTION_ZONE = 93
    TRAFFIC_ASSISTANTS = 94
    DEAD_END = 95
    POLICE = 96
    EMERGENCY_CALL_STATION = 97
    GAS_STATION = 98
    CAMP_AND_CARAVAN_SITE = 99
    ATTRACTION_POINT = 100
    TOURISTIC_ROUTE = 101
    NEARBY_ATTRACTION_POINT = 102
    HIGHWAY_INTERSECTION = 103
    DIRECTION_ARROW_SIGN_MULTI = 104
    DIRECTION_ARROW_SIGN_SINGLE = 105
    DIRECTION_SIGN_CONSOLIDATED = 106
    EXPRESSWAY_ARROW_DIRECTION = 107
    ARROW_SIGN_POST_POINT_OF_INTEREST_LEFT = 108
    STATION = 109
    GUIDE_SIGN_TABLE = 110
    ADVANCE_DIRECTION = 111
    DIRECTIONS_SIGN = 112
    EXPRESSWAY_ENTRANCE_DIRECTIONS = 113
    INTERSTATE_ANNOUNCEMENT = 114
    INTERSTATE_ADVANCE_DIRECTION = 115
    HIGHWAY_EXIT_AHEAD_100_METER = 116
    HIGHWAY_EXIT_AHEAD_200_METER = 117
    HIGHWAY_EXIT_AHEAD_300_METER = 118
    EXPRESSWAY_EXIT_100_METRES = 119
    EXPRESSWAY_EXIT_200_METRES = 120
    EXPRESSWAY_EXIT_300_METRES = 121
    INTERSTATE_DISTANCE = 122
    DETOUR_SKETCH = 123
    DETOUR_STRAIGHT = 124
    DETOUR_ON_DEMAND_LEFT = 125
    DETOUR_ON_DEMAND_GET_IN_LEFT_LANE = 126
    DETOUR_ON_DEMAND_ANNOUNCEMENT_RIGHT = 127
    DETOUR_ON_DEMAND_RIGHT = 128
    DETOUR_ON_DEMAND_GET_IN_RIGHT_LANE = 129
    DETOUR_ON_DEMAND_STRAIGHTFORWARD = 130
    TRANSITION_3_LEFT_2_TRANSITIONED = 131
    TRANSITION_1_LEFT_1_STRAIGHT = 132
    TRANSITION_3_RIGHT = 133
    LANE_BOARD_NO_OPPOSITE_TWO_LANES = 134
    THREE_LANES_NO_ONCOMING_LANES = 135
    FOUR_LANES_NO_ONCOMING_LANES = 136
    FIVE_LANES_NO_ONCOMING_LANES = 137
    LANE_BOARD_3_LANES_NO_OPPOSITE_WITH_SIGNS = 138
    NARROWING_LANES_1_LANE_FROM_RIGHT = 139
    NARROWING_LANES_1_LANE_FROM_LEFT = 140
    NARROWING_LANES_2_LANES_PLUS_1_LEFT = 141
    FOUR_LANES_NO_ONCOMING_TRAFFIC_TWO_RIGHT_LANES_TURN_RIGHT = 142
    MERGING_LANES_1_LANE_PLUS_1_LANE_RIGHT = 143
    BARRIER = 144
    BARRIER_GATE_100_800 = 145
    BARRIER_GATE_100_1200 = 146
    BARRIER_GATE_100_1600 = 147
    BARRIER_GATE_250_1600 = 148
    BARRIER_GATE = 149
    ROAD_WARNING_POST_SCRAPER_BEACON_RIGHT = 150
    ROAD_WARNING_POST_ARROW_BEACON_RIGHT = 151
    ROAD_WARNING_POST_SCRAPER_BEACON_LEFT = 152
    ROAD_WARNING_POST_SCRAPER_BEACON_ARROW_RIGHT = 153
    ROAD_WARNING_POST_GUIDE_UP_THREE_ARROWS = 154
    DIRECTION_SIGN_LEFT_SINGLE = 155
    DIRECTION_SIGN_LEFT_SMALL = 156
    DIRECTION_SIGN_LEFT_MEDIUM = 157
    DIRECTION_SIGN_LEFT_LARGE = 158
    DIRECTION_SIGN_RIGHT_SINGLE = 159
    DIRECTION_SIGN_RIGHT_SMALL = 160
    DIRECTION_SIGN_RIGHT_MEDIUM = 161
    DIRECTION_SIGN_RIGHT_LARGE = 162
    WARNING_PANEL_RIGHT = 163
    WARNING_PANEL_LEFT = 164
    WARNING_PANEL_STRAIGHT_BROAD = 165
    WARNING_PANEL_STRAIGHT_HIGH = 166
    GUIDE_SILL_WITH_GUIDE_BEACON_RIGHT = 167
    GUIDE_RAIL_WITH_GUIDE_BEACON_RIGHT = 168
    GUIDE_PANEL_WITH_GUIDE_BEACON_RIGHT = 169
    GREEN_ARROW = 170
    ADDITION_LEFT_DIRECTION = 171
    ADDITION_LEFT_DIRECTION_1 = 172
    ADDITION_LEFT_DIRECTION_DANGER_POINT = 173
    ADDITION_RIGHT_DIRECTION_1 = 174
    ADDITION_RIGHT_DIRECTION_DANGER_POINT = 175
    ADDITION_BOTH_DIRECTIONS_HORIZONTAL = 176
    ADDITION_BOTH_DIRECTIONS_VERTICAL = 177
    ADDITION_VALID_FOR_X_METERS = 178
    ADDITION_VALID_FOR_X_KILOMETERS = 179
    ADDITION_LEFT_TURNING_PRIORITY_WITH_OPPOSITE_RIGHT_YIELD = 180
    ADDITION_LEFT_TRAFFIC_PRIORITY_WITH_STRAIGHT_RIGHT_YIELD = 181
    ADDITION_LEFT_TURNING_PRIORITY_WITH_OPPOSITE_YIELD = 182
    ADDITION_LEFT_TURNING_PRIORITY_WITH_RIGHT_YIELD = 183
    ADDITION_LEFT_TRAFFIC_PRIORITY_WITH_STRAIGHT_YIELD = 184
    ADDITION_RIGHT_TURNING_PRIORITY_WITH_OPPOSITE_LEFT_YIELD = 185
    ADDITION_RIGHT_TRAFFIC_PRIORITY_WITH_STRAIGHT_LEFT_YIELD = 186
    ADDITION_RIGHT_TURNING_PRIORITY_WITH_OPPOSITE_YIELD = 187
    ADDITION_RIGHT_TURNING_PRIORITY_WITH_LEFT_YIELD = 188
    ADDITION_RIGHT_TRAFFIC_PRIORITY_WITH_STRAIGHT_YIELD = 189
    ADDITION_VALID_IN_X_METERS = 190
    ADDITION_VALID_IN_X_KILOMETERS = 191
    ADDITION_VALID_IN_200_KILOMETERS = 192
    ADDITION_VALID_IN_400_METRES = 193
    ADDITION_VALID_IN_600_METRES = 194
    ADDITION_VALID_IN_2_KILOMETERS = 195
    ADDITION_OIL_ON_ROAD = 196
    ADDITION_SMOKE = 197
    ADDITION_LOOSE_GRAVEL = 198
    ADDITION_BUILDING_SITE_EXIT = 199
    ADDITION_DAMAGED_ROAD = 201
    ADDITION_DIRTY_ROAD = 202
    ADDITION_DANGER_OF_COLLISION = 203
    ADDITION_TOAD_MIGRATION = 204
    ADDITION_DANGER_OF_CONGESTION = 205
    ADDITION_RESTRICTED_VIEW_DUE_TO_TREES = 206
    DANGER_INDICATION_SMOKE = 207
    ADDITION_CHILDREN_PLAYING_ON_ROAD = 208
    ADDITION_WINTER_SPORTS_ALLOWED = 209
    ADDITION_TRAILERS_ALLOWED_TO_PARK_MORE_THAN_14_DAYS = 210
    ADDITION_CARAVANS_ALLOWED_TO_PARK_MORE_THAN_14_DAYS = 211
    ADDITION_ROLLING_HIGHWAY = 212
    ADDITION_LOADING_AREA = 213
    ADDITION_END = 214
    ADDITION_GET_OFF_BICYCLES = 215
    ADDITION_NO_MOPEDS = 216
    ADDITION_GREEN_WAVE_AT_KM_H = 217
    ADDITION_STOP_HERE_AT_RED = 218
    ADDITION_NOISE_CONTROL = 219
    ADDITION_INFLOW_REGULATION = 220
    ADDITION_SECONDARY_LANE = 221
    ADDITION_SCHOOL = 222
    ADDITION_KINDERGARTEN = 223
    ADDITION_RETIREMENT_HOME = 224
    ADDITION_HOSPITAL = 225
    ADDITION_RESIDENTS_PERMITTED = 226
    ADDITION_BICYCLES_PERMITTED = 227
    ADDITION_CARS_PERMITTED = 228
    ADDITION_AGRICULTURE_PERMITTED = 229
    ADDITION_FOREST_PERMITTED = 230
    ADDITION_AGRICULTURE_FOREST_PERMITTED = 231
    ADDITION_GREEN_STICKER_PERMITTED = 232
    ADDITION_TIME_PERIOD_PERMITTED = 233
    ADDITION_MOTOR_VEHICLES_ALLOWED_MASS_3_5_TONS = 234
    ADDITION_MIN_MASS_3_5_TONS = 235
    ADDITION_NO_WATER_POLLUTANTS_LOADED = 236
    ALLOWED_MASS_7_5_TONS = 237
    ADDITION_VALID_ON_SHOULDER = 238
    ADDITION_VALID_WHEN_WET = 239
    LINE_MARKING_MISSING = 240
    UNKNOWN = 241
    # US
    ROAD_WORK_AHEAD = 242
    NO_PARKING_ANY_TIME = 243
    NO_STANDING = 244
    TOW_AWAY_ZONE = 245
    ONE_WAY_LEFT = 246
    ONE_WAY_RIGHT = 247
    DO_NOT_ENTER = 248
    NO_LEFT_TURN = 249
    RIGHT_TURN_ONLY = 250
    TURN_ONLY_LANES = 251
    NO_RIGHT_TURN = 252
    KEEP_RIGHT = 253
    SIGNAL_AHEAD = 254
    LOADING_ZONE = 255
    NO_PARKING = 256
    LEFT_TURN_ONLY = 257
    NO_STRAIGHT_THROUGH = 258
    LEFT_REVERSE_TURN = 259
    PEDESTRIAN_WARNING = 260
    DIAGONAL_DOWNWARD_LEFT_ARROW = 261
    RIGHT_LANE_ENDS = 262
    RESERVED_HANDICAP_PARKING = 263
    NO_PARKING_BUS_STOP = 264
    ON_PAVEMENT = 265
    DO_NOT_BLOCK_INTERSECTION = 266
    WARNING_ARROW_LEFT = 267
    # Spain
    NO_STOPPING = 268
    NO_WAITING = 269


[docs]@enum.unique class SupportedTrafficSignCountry(enum.Enum): GERMANY = "DEU" USA = "USA" CHINA = "CHN" SPAIN = "ESP" RUSSIA = "RUS" ARGENTINA = "ARG" BELGIUM = "BEL" FRANCE = "FRA" GREECE = "GRC" CROATIA = "HRV" ITALY = "ITA" PUERTO_RICO = "PRI" ZAMUNDA = "ZAM" # default
[docs]@enum.unique class TrafficSignIDGermany(enum.Enum): # default traffic sign IDs (similar to German IDs) WARNING_DANGER_SPOT = "101" WARNING_RIGHT_BEFORE_LEFT = "102" WARNING_LEFT_CURVE = "103-10" WARNING_RIGHT_CURVE = "103-20" WARNING_STEEP_HILL_DOWNWARDS = "108" WARNING_SLIPPERY_ROAD = "114" WARNING_CONSTRUCTION_SITE = "123" WARNING_TRAFFIC_QUEUES_LIKELY = "124" WARNING_ONCOMING_TRAFFIC = "125" WARNING_TRAFFIC_LIGHTS_AHEAD = "131" WARNING_PEDESTRIANS_RIGHT = "133-10" WARNING_PEDESTRIANS_LEFT = "133-20" WARNING_CROSSING_CYCLIST = "138" WARNING_ANIMAL_CROSSING_RIGHT = "142-10" WARNING_LOOSE_GRAVEL = "145-50" RAILWAY = "201" YIELD = "205" STOP = "206" PRIORITY_OPPOSITE_DIRECTION = "208" TURN_RIGHT_AHEAD = "209-10" TURN_LEFT_AHEAD = "209-20" KEEP_STRAIGHT_AHEAD = "209-30" PRESCRIBED_DIRECTION_RIGHT = "211-20" ROUNDABOUT = "215" ONEWAY_RIGHT = "220-10" ONEWAY_LEFT = "220-20" PRESCRIBED_PASSING_LEFT = "222-10" PRESCRIBED_PASSING_RIGHT = "222-20" DO_NOT_DRIVE_ON_SHOULDER_LANE = "223.2" DO_NOT_DRIVE_ON_SHOULDER_LANE_2_LANE = "223.2-50" DO_NOT_DRIVE_ON_SHOULDER_LANE_3_LANE = "223.2-51" BUS_STOP = "224-50" BIKEWAY = "237" PEDESTRIAN_SIDEWALK = "239" PEDESTRIAN_AND_BICYCLE_ROAD = "240" PEDESTRIAN_ZONE_START = "242.1" PEDESTRIAN_ZONE_END = "242.2" BICYCLE_ROAD_START = "244.1" BICYCLE_ROAD_END = "244.2" BUS_LANE = "245" BAN_ALL_VEHICLES = "250" BAN_CARS = "251" BAN_TRUCKS = "253" BAN_BICYCLE = "254" BAN_MOTORCYCLE = "255" BAN_BUS = "257-54" BAN_PEDESTRIAN = "259" BAN_CAR_TRUCK_BUS_MOTORCYCLE = "260" BAN_VEHICLES_CARRYING_DANGEROUS_GOODS = "261" MAX_WEIGHT = "262" MAX_WIDTH = "264" MAX_HEIGHT = "265" MAX_LENGTH = "266" NO_ENTRY = "267" ENVIRONMENTAL_ZONE_START = "270.1" ENVIRONMENTAL_ZONE_END = "270.2" U_TURN = "272" MAX_SPEED = "274" MAX_SPEED_ZONE_START = "274.1" MAX_SPEED_ZONE_END = "274.2" MIN_SPEED = "275" NO_OVERTAKING_START = "276" NO_OVERTAKING_TRUCKS_START = "277" MAX_SPEED_END = "278" NO_OVERTAKING_END = "280" NO_OVERTAKING_TRUCKS_END = "281" ALL_MAX_SPEED_AND_OVERTAKING_END = "282" NO_STOP_START_RIGHT = "283-10" NO_STOP_CENTER_RIGHT = "283-30" RESTRICTED_STOP_CENTER_RIGHT = "286-30" RIGHT_OF_WAY = "301" PRIORITY = "306" PRIORITY_OVER_ONCOMING = "308" TOWN_SIGN = "310" TOWN_SIGN_BACK = "311" PARKING_AREA = "314" PARKING_AREA_LEFT = "314-10" PARKING_AREA_RIGHT = "314-20" PARKING_AREA_RIGHT_LEFT = "314-30" TRAFFIC_CALMED_AREA_START = "325.1" TRAFFIC_CALMED_AREA_END = "325.2" TUNNEL = "327" EMERGENCY_STOP = "328" INTERSTATE_START = "330.1" INTERSTATE_END = "330.2" HIGHWAY_START = "331.1" HIGHWAY_END = "331.2" HIGHWAY_EXIT_WITH_PLACE_NAME = "332" EXIT_ROUTE = "332.1" HIGHWAY_EXIT = "333" EXIT_BUILT_UP = "333-21" EXIT_GENERAL = "333-22" PEDESTRIANS_CROSSING = "350" WATER_PROTECTION_ZONE = "354" TRAFFIC_ASSISTANTS = "356" DEAD_END = "357" POLICE = "363" EMERGENCY_CALL_STATION = "365-51" GAS_STATION = "365-52" CAMP_AND_CARAVAN_SITE = "365-60" ATTRACTION_POINT = "386.1" TOURISTIC_ROUTE = "386.2" NEARBY_ATTRACTION_POINT = "386.3" HIGHWAY_INTERSECTION = "406-50" DIRECTION_ARROW_SIGN_MULTI = "418-20" DIRECTION_ARROW_SIGN_SINGLE = "419-20" DIRECTION_SIGN_CONSOLIDATED = "434-50" EXPRESSWAY_ARROW_DIRECTION = "430-20" ARROW_SIGN_POST_POINT_OF_INTEREST_LEFT = "432-10" STATION = "432-20" GUIDE_SIGN_TABLE = "434" ADVANCE_DIRECTION = "438" DIRECTIONS_SIGN = "439" EXPRESSWAY_ENTRANCE_DIRECTIONS = "440" INTERSTATE_ANNOUNCEMENT = "448" INTERSTATE_ADVANCE_DIRECTION = "449" HIGHWAY_EXIT_AHEAD_100_METER = "450-50" HIGHWAY_EXIT_AHEAD_200_METER = "450-51" HIGHWAY_EXIT_AHEAD_300_METER = "450-52" EXPRESSWAY_EXIT_100_METRES = "450-53" EXPRESSWAY_EXIT_200_METRES = "450-54" EXPRESSWAY_EXIT_300_METRES = "450-55" INTERSTATE_DISTANCE = "453" DETOUR_SKETCH = "458" DETOUR_STRAIGHT = "455.1-30" DETOUR_ON_DEMAND_LEFT = "460-10" DETOUR_ON_DEMAND_GET_IN_LEFT_LANE = "460-12" DETOUR_ON_DEMAND_ANNOUNCEMENT_RIGHT = "460-20" DETOUR_ON_DEMAND_RIGHT = "460-21" DETOUR_ON_DEMAND_GET_IN_RIGHT_LANE = "460-22" DETOUR_ON_DEMAND_STRAIGHTFORWARD = "460-30" TRANSITION_3_LEFT_2_TRANSITIONED = "501-15" TRANSITION_1_LEFT_1_STRAIGHT = "501-16" TRANSITION_3_RIGHT = "511-22" LANE_BOARD_NO_OPPOSITE_TWO_LANES = "521-30" THREE_LANES_NO_ONCOMING_LANES = "521-31" FOUR_LANES_NO_ONCOMING_LANES = "521-32" FIVE_LANES_NO_ONCOMING_LANES = "521-33" LANE_BOARD_3_LANES_NO_OPPOSITE_WITH_SIGNS = "525" NARROWING_LANES_1_LANE_FROM_RIGHT = "531-10" NARROWING_LANES_1_LANE_FROM_LEFT = "531-20" NARROWING_LANES_2_LANES_PLUS_1_LEFT = "531-21" FOUR_LANES_NO_ONCOMING_TRAFFIC_TWO_RIGHT_LANES_TURN_RIGHT = "533-22" MERGING_LANES_1_LANE_PLUS_1_LANE_RIGHT = "550-20" BARRIER = "600-35" BARRIER_GATE_100_800 = "600-30" BARRIER_GATE_100_1200 = "600-31" BARRIER_GATE_100_1600 = "600-32" BARRIER_GATE_250_1600 = "600-34" BARRIER_GATE = "600-38" ROAD_WARNING_POST_SCRAPER_BEACON_RIGHT = "605-10" ROAD_WARNING_POST_ARROW_BEACON_RIGHT = "605-11" ROAD_WARNING_POST_SCRAPER_BEACON_LEFT = "605-20" ROAD_WARNING_POST_SCRAPER_BEACON_ARROW_RIGHT = "605-21" ROAD_WARNING_POST_GUIDE_UP_THREE_ARROWS = "605-31" DIRECTION_SIGN_LEFT_SINGLE = "625-10" DIRECTION_SIGN_LEFT_SMALL = "625-11" DIRECTION_SIGN_LEFT_MEDIUM = "625-12" DIRECTION_SIGN_LEFT_LARGE = "625-13" DIRECTION_SIGN_RIGHT_SINGLE = "625-20" DIRECTION_SIGN_RIGHT_SMALL = "625-21" DIRECTION_SIGN_RIGHT_MEDIUM = "625-22" DIRECTION_SIGN_RIGHT_LARGE = "625-23" WARNING_PANEL_RIGHT = "626-10" WARNING_PANEL_LEFT = "626-20" WARNING_PANEL_STRAIGHT_BROAD = "626-30" WARNING_PANEL_STRAIGHT_HIGH = "626-31" GUIDE_SILL_WITH_GUIDE_BEACON_RIGHT = "628-10" GUIDE_RAIL_WITH_GUIDE_BEACON_RIGHT = "629-10" GUIDE_PANEL_WITH_GUIDE_BEACON_RIGHT = "629-20" GREEN_ARROW = "720" ADDITION_LEFT_DIRECTION = "1000" ADDITION_LEFT_DIRECTION_1 = "1000-10" ADDITION_LEFT_DIRECTION_DANGER_POINT = "1000-11" ADDITION_RIGHT_DIRECTION_1 = "1000-20" ADDITION_RIGHT_DIRECTION_DANGER_POINT = "1000-21" ADDITION_BOTH_DIRECTIONS_HORIZONTAL = "1000-30" ADDITION_BOTH_DIRECTIONS_VERTICAL = "1000-31" ADDITION_VALID_FOR_X_METERS = "1001-30" ADDITION_VALID_FOR_X_KILOMETERS = "1001-31" ADDITION_LEFT_TURNING_PRIORITY_WITH_OPPOSITE_RIGHT_YIELD = "1002-10" ADDITION_LEFT_TRAFFIC_PRIORITY_WITH_STRAIGHT_RIGHT_YIELD = "1002-11" ADDITION_LEFT_TURNING_PRIORITY_WITH_OPPOSITE_YIELD = "1002-12" ADDITION_LEFT_TURNING_PRIORITY_WITH_RIGHT_YIELD = "1002-13" ADDITION_LEFT_TRAFFIC_PRIORITY_WITH_STRAIGHT_YIELD = "1002-14" ADDITION_RIGHT_TURNING_PRIORITY_WITH_OPPOSITE_LEFT_YIELD = "1002-20" ADDITION_RIGHT_TRAFFIC_PRIORITY_WITH_STRAIGHT_LEFT_YIELD = "1002-21" ADDITION_RIGHT_TURNING_PRIORITY_WITH_OPPOSITE_YIELD = "1002-22" ADDITION_RIGHT_TURNING_PRIORITY_WITH_LEFT_YIELD = "1002-23" ADDITION_RIGHT_TRAFFIC_PRIORITY_WITH_STRAIGHT_YIELD = "1002-24" ADDITION_VALID_IN_X_METERS = "1004-30" ADDITION_VALID_IN_X_KILOMETERS = "1004-31" ADDITION_VALID_IN_200_KILOMETERS = "1004-32" ADDITION_VALID_IN_400_METRES = "1004-33" ADDITION_VALID_IN_600_METRES = "1004-34" ADDITION_VALID_IN_2_KILOMETERS = "1004-35" ADDITION_OIL_ON_ROAD = "1006-30" ADDITION_SMOKE = "1006-31" ADDITION_LOOSE_GRAVEL = "1006-32" ADDITION_BUILDING_SITE_EXIT = "1006-33" ADDITION_DAMAGED_ROAD = "1006-34" ADDITION_DIRTY_ROAD = "1006-35" ADDITION_DANGER_OF_COLLISION = "1006-36" ADDITION_TOAD_MIGRATION = "1006-37" ADDITION_DANGER_OF_CONGESTION = "1006-38" ADDITION_RESTRICTED_VIEW_DUE_TO_TREES = "1006-39" DANGER_INDICATION_SMOKE = "1007-31" ADDITION_CHILDREN_PLAYING_ON_ROAD = "1010-10" ADDITION_WINTER_SPORTS_ALLOWED = "1010-11" ADDITION_TRAILERS_ALLOWED_TO_PARK_MORE_THAN_14_DAYS = "1010-12" ADDITION_CARAVANS_ALLOWED_TO_PARK_MORE_THAN_14_DAYS = "1010-13" ADDITION_ROLLING_HIGHWAY = "1010-14" ADDITION_LOADING_AREA = "1012-30" ADDITION_END = "1012-31" ADDITION_GET_OFF_BICYCLES = "1012-32" ADDITION_NO_MOPEDS = "1012-33" ADDITION_GREEN_WAVE_AT_KM_H = "1012-34" ADDITION_STOP_HERE_AT_RED = "1012-35" ADDITION_NOISE_CONTROL = "1012-36" ADDITION_INFLOW_REGULATION = "1012-37" ADDITION_SECONDARY_LANE = "1012-38" ADDITION_SCHOOL = "1012-50" ADDITION_KINDERGARTEN = "1012-51" ADDITION_RETIREMENT_HOME = "1012-52" ADDITION_HOSPITAL = "1012-53" ADDITION_RESIDENTS_PERMITTED = "1020-30" ADDITION_BICYCLES_PERMITTED = "1022-10" ADDITION_CARS_PERMITTED = "1024-10" ADDITION_AGRICULTURE_PERMITTED = "1026-36" ADDITION_FOREST_PERMITTED = "1026-37" ADDITION_AGRICULTURE_FOREST_PERMITTED = "1026-38" ADDITION_GREEN_STICKER_PERMITTED = "1031-52" ADDITION_TIME_PERIOD_PERMITTED = "1040-30" ADDITION_MOTOR_VEHICLES_ALLOWED_MASS_3_5_TONS = "1048-12" ADDITION_MIN_MASS_3_5_TONS = "1049-13" ADDITION_NO_WATER_POLLUTANTS_LOADED = "1052-31" ALLOWED_MASS_7_5_TONS = "1053-33" ADDITION_VALID_ON_SHOULDER = "1053-34" ADDITION_VALID_WHEN_WET = "1053-35" LINE_MARKING_MISSING = "2113" UNKNOWN = ""
TrafficSignIDZamunda = TrafficSignIDGermany # default traffic sign IDs (similar to German IDs)
[docs]@enum.unique class TrafficSignIDUsa(enum.Enum): MAX_SPEED = "R2-1" U_TURN = "R3-4" ROAD_WORK_AHEAD = "CW20-1" NO_PARKING_ANY_TIME = "R7-1" NO_STANDING = "R7-4" TOW_AWAY_ZONE = "R7-201a" ONE_WAY_LEFT = "R6-1L" ONE_WAY_RIGHT = "R6-1R" DO_NOT_ENTER = "R5-1" NO_LEFT_TURN = "R3-2" RIGHT_TURN_ONLY = "R3-5R" TURN_ONLY_LANES = "R3-8b" NO_RIGHT_TURN = "R3-1" KEEP_RIGHT = "R4-7" SIGNAL_AHEAD = "W3-3" LOADING_ZONE = "R8-3gP" NO_PARKING = "R8-3" LEFT_TURN_ONLY = "R3-5L" NO_STRAIGHT_THROUGH = "R3-27" LEFT_REVERSE_TURN = "W1-3L" PEDESTRIAN_WARNING = "W11-2" DIAGONAL_DOWNWARD_LEFT_ARROW = "M6-2aL" RIGHT_LANE_ENDS = "W4-2R" RESERVED_HANDICAP_PARKING = "R7-8" NO_PARKING_BUS_STOP = "R7-107" ON_PAVEMENT = "R8-3C" DO_NOT_BLOCK_INTERSECTION = "R10-7" WARNING_ARROW_LEFT = "W1-6L" UNKNOWN = ""
[docs]@enum.unique class TrafficSignIDChina(enum.Enum): MAX_SPEED = "274" # TODO: change to actual ID UNKNOWN = ""
[docs]@enum.unique class TrafficSignIDSpain(enum.Enum): YIELD = "r1" STOP = "r2" BAN_ALL_VEHICLES = "r100" NO_ENTRY = "r101" BAN_TRUCKS = "r106" MAX_WEIGHT = "r107" MAX_HEIGHT = "r205" MAX_SPEED = "r301" NO_OVERTAKING_START = "r305" NO_STOPPING = "r307" NO_WAITING = "r308" PEDESTRIANS_CROSSING = "s13" UNKNOWN = ""
[docs]@enum.unique class TrafficSignIDRussia(enum.Enum): MAX_SPEED = "3.24" UNKNOWN = ""
@enum.unique class TrafficSignIDArgentina(enum.Enum): MAX_SPEED = "R15" UNKNOWN = "" @enum.unique class TrafficSignIDBelgium(enum.Enum): MAX_SPEED = "C43" UNKNOWN = "" @enum.unique class TrafficSignIDFrance(enum.Enum): MAX_SPEED = "B14" UNKNOWN = "" @enum.unique class TrafficSignIDGreece(enum.Enum): MAX_SPEED = "Ρ-32" UNKNOWN = "" @enum.unique class TrafficSignIDCroatia(enum.Enum): MAX_SPEED = "B31" UNKNOWN = "" @enum.unique class TrafficSignIDItaly(enum.Enum): MAX_SPEED = "274" # TODO: change to actual ID UNKNOWN = "" @enum.unique class TrafficSignIDPuertoRico(enum.Enum): MAX_SPEED = "R2-1" UNKNOWN = "" TrafficSignIDCountries = { ele.value: globals()[ "TrafficSignID" + SupportedTrafficSignCountry(ele.value).name.replace("_", " ").title().replace(" ", "") ] for ele in SupportedTrafficSignCountry }
[docs]class TrafficSignElement: """Class which represents a collection of traffic signs at one position""" def __init__( self, traffic_sign_element_id: Union[ TrafficSignIDZamunda, TrafficSignIDUsa, TrafficSignIDSpain, TrafficSignIDGermany, TrafficSignIDChina, TrafficSignIDRussia, ], additional_values: List[str] = [], ): """ :param traffic_sign_element_id: ID of traffic sign element (must be element of a traffic sign element enum) :param additional_values: list of additional values of a traffic sign element, e.g. velocity, time, city name """ self._traffic_sign_element_id = traffic_sign_element_id self._additional_values = additional_values def __eq__(self, other): if not isinstance(other, TrafficSignElement): warnings.warn(f"Inequality between TrafficSignElement {repr(self)} and different type {type(other)}") return False return self.traffic_sign_element_id == other.traffic_sign_element_id and set(self.additional_values) == set( other.additional_values ) def __ne__(self, other): return not self.__eq__(other) def __hash__(self): return hash((self._traffic_sign_element_id, frozenset(self.additional_values))) def __str__(self): return f"TrafficSignElement with id {self._traffic_sign_element_id} and values {self._additional_values}" def __repr__(self): return ( f"TrafficSignElement(traffic_sign_element_id={self._traffic_sign_element_id}, " f"additional_values={self._additional_values})" ) @property def traffic_sign_element_id(self) -> enum: return self._traffic_sign_element_id @traffic_sign_element_id.setter def traffic_sign_element_id(self, traffic_sign_element_id: enum): self._traffic_sign_element_id = traffic_sign_element_id @property def additional_values(self) -> List[str]: return self._additional_values @additional_values.setter def additional_values(self, additional_values: List[str]): self._additional_values = additional_values
[docs]class TrafficSign(IDrawable): """Class to represent a traffic sign""" def __init__( self, traffic_sign_id: int, traffic_sign_elements: List[TrafficSignElement], first_occurrence: Set[int], position: np.ndarray, virtual: bool = False, ): """ :param traffic_sign_id: ID of traffic sign :param traffic_sign_elements: list of traffic sign elements :param first_occurrence: lanelet ID where traffic sign first appears :param position: position of traffic sign :param virtual: boolean indicating if this traffic sign is also placed there in the real environment, or it is added for other reasons (e.g., completeness of scenario) """ self._traffic_sign_id = traffic_sign_id self._position = position self._traffic_sign_elements = traffic_sign_elements self._virtual = virtual self._first_occurrence = first_occurrence if self._first_occurrence is None: self._first_occurrence = set() def __eq__(self, other): if not isinstance(other, TrafficSign): warnings.warn(f"Inequality between TrafficSign {repr(self)} and different type {type(other)}") return False list_elements_eq = True traffic_sign_elements = { traffic_sign_element.traffic_sign_element_id: traffic_sign_element for traffic_sign_element in self._traffic_sign_elements } traffic_sign_elements_other = { traffic_sign_element.traffic_sign_element_id: traffic_sign_element for traffic_sign_element in other._traffic_sign_elements } traffic_sign_eq = len(traffic_sign_elements) == len(traffic_sign_elements_other) for k in traffic_sign_elements.keys(): if k not in traffic_sign_elements_other: traffic_sign_eq = False continue if traffic_sign_elements.get(k) != traffic_sign_elements_other.get(k): list_elements_eq = False position_string = np.array2string(np.around(self._position.astype(float), 10), precision=10) position_other_string = np.array2string(np.around(other.position.astype(float), 10), precision=10) return ( list_elements_eq and traffic_sign_eq and self._traffic_sign_id == other.traffic_sign_id and position_string == position_other_string and self._virtual == other.virtual and self._first_occurrence == other.first_occurrence ) def __hash__(self): position_string = np.array2string(np.around(self._position.astype(float), 10), precision=10) return hash( ( self._traffic_sign_id, position_string, frozenset(self._traffic_sign_elements), self._virtual, frozenset(self._first_occurrence), ) ) def __str__(self): return f"TrafficSign with id {self._traffic_sign_id} placed at {self._position}" def __repr__(self): return ( f"TrafficSign(traffic_sign_id={self._traffic_sign_id}, " f"traffic_sign_elements={repr(self._traffic_sign_elements)}, " f"first_occurrence={self._first_occurrence}, " f"position={self._position.tolist()}, virtual={self._virtual})" ) @property def traffic_sign_id(self) -> int: return self._traffic_sign_id @traffic_sign_id.setter def traffic_sign_id(self, traffic_sign_id: int): self._traffic_sign_id = traffic_sign_id @property def position(self) -> np.ndarray: return self._position @position.setter def position(self, position: np.ndarray): self._position = position @property def traffic_sign_elements(self) -> List[TrafficSignElement]: return self._traffic_sign_elements @traffic_sign_elements.setter def traffic_sign_elements(self, traffic_sign_elements: List[TrafficSignElement]): self._traffic_sign_elements = traffic_sign_elements @property def virtual(self) -> bool: return self._virtual @virtual.setter def virtual(self, virtual: bool): self._virtual = virtual @property def first_occurrence(self) -> Set[int]: return self._first_occurrence @first_occurrence.setter def first_occurrence(self, first_occurrence: Set[int]): self._first_occurrence = first_occurrence
[docs] def translate_rotate(self, translation: np.ndarray, angle: float): """ This method translates and rotates a traffic sign :param translation: The translation given as [x_off,y_off] for the x and y translation :param angle: The rotation angle in radian (counter-clockwise defined) """ assert is_real_number_vector(translation, 2), ( "<TrafficSign/translate_rotate>: argument translation is " "not a vector of real " "numbers of length 2." ) assert is_real_number(angle), ( "<TrafficSign/translate_rotate>: argument angle must be a " "scalar. " "angle = %s" % angle ) assert is_valid_orientation(angle), ( "<TrafficSign/translate_rotate>: argument angle must " "be " "within the " "interval [-2pi, 2pi]. angle = %s" % angle ) self._position = commonroad.geometry.transform.translate_rotate(np.array([self._position]), translation, angle)[ 0 ]
[docs] def convert_to_2d(self) -> None: """ Convert the traffic sign to 2D by removing the z-coordinate from its position. This has no effect if the traffic sign is already 2D. """ self._position = self._position[:2]
[docs] def draw(self, renderer: IRenderer, draw_params: OptionalSpecificOrAllDrawParams[TrafficSignParams] = None): renderer.draw_traffic_light_sign(self, draw_params)