Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PYDANTIC_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ class RoadSegment(TransportationSegment):
speed_limits: SpeedLimits | None = None

def get_speed_limit(self) -> float:
return self.speed_limits.max_speed if self.speed_limits else 50.0
return self.speed_limits.speed if self.speed_limits else 50.0

# Now only concrete classes can be instantiated
# base_segment = TransportationSegment(...) # TypeError: Can't instantiate abstract class
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
id: road segment where road.restrictions.speed_limits contains a rule with an invalid type
type: Feature
geometry:
type: LineString
coordinates: [[0, 0], [1, 1]]
properties:
ext_expected_errors:
- "[S#/$defs/propertyDefinitions/speedLimitType/enum]: value must be one of"
theme: transportation
type: segment
version: 1
subtype: road
class: secondary
speed_limits:
- type: recommended
speed:
value: 110
unit: mph
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
{}
],
"ext_expected_errors": [
"anyOf/0/required]: missing property 'min_speed'",
"anyOf/1/required]: missing property 'max_speed'"
"required]: missing properties 'type', 'speed'"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ properties:
- connector_id: barConnector
at: 1
speed_limits:
- max_speed:
- type: maximum
speed:
value: 110
unit: mph
when: {mode: [foo]}
17 changes: 14 additions & 3 deletions docs/schema/concepts/by-theme/transportation/roads.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ExampleAccessRestrictionAxleLimit from '!!raw-loader!@site/docs/_examples
import ExampleSpeedLimitsSimple from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/speed-limits-01-simple.yaml';
import ExampleSpeedLimitsDirectional from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/speed-limits-02-directional.yaml';
import ExampleSpeedLimitsVariableMax from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/speed-limits-03-variable-max.yaml';
import ExampleSpeedLimitsAdvisory from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/speed-limits-04-advisory.yaml';
import ExampleTurnRestriction1Source from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/turn-restriction-01-source.yaml';
import ExampleTurnRestriction1Target from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/turn-restriction-01-target.yaml';
import ExampleTurnRestriction1Exit from '!!raw-loader!@site/docs/_examples/transportation/docusaurus/turn-restriction-01-exit.yaml';
Expand Down Expand Up @@ -272,9 +273,13 @@ real-world context to the example.*
### Speed limits

Speed limits restrict the speed at which travel is permitted on a road.
Typically speed limits specify maximum allowed speeds, but the
Overture also allows minimum speed limits to be set and variable speed
corridors to be indicated.
Each speed limit rule has a `type` indicating the kind of speed rule,
and a `speed` holding the speed value. Typically speed limits specify
`maximum` allowed speeds, but Overture also supports `minimum` speed
limits and `advisory` speeds, which are recommended but not regulatory.
Variable speed corridors and roads without a regulatory maximum speed
are indicated with the `road_flags` property, using the
`dynamic_speed` and `unlimited_speed` flags.

Every road segment has an implied speed limit or set of speed limits
defined by its [road class](#road-class) and local rules, norms, and
Expand Down Expand Up @@ -306,4 +311,10 @@ As with access restrictions and turn restrictions, speed limits can be specified
<CodeBlock language="yaml">{ ExampleSpeedLimitsVariableMax }</CodeBlock>

</TabItem>

<TabItem value="speedLimitAdvisory" label="Advisory speed" default>

<CodeBlock language="yaml">{ ExampleSpeedLimitsAdvisory }</CodeBlock>

</TabItem>
</Tabs>
2 changes: 1 addition & 1 deletion docs/schema/concepts/by-theme/transportation/segments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ case, it is similar to, but not the same as, OSM's `highway=*` and `railway=*` t

## Flags

A segment's flags (`road_flags` for roads, `rail_flags` for rails) are a set of named flag values indicating the presence or absence of simple physical characteristics.
A segment's flags (`road_flags` for roads, `rail_flags` for rails) are a set of named flag values indicating the presence or absence of simple physical characteristics and other properties of the segment.

For example, a road segment with `road_flags = [is_link, is_under_construction]` is a link segment that is physically under construction.

Expand Down
6 changes: 4 additions & 2 deletions examples/transportation/docusaurus/geometric-scoping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ properties:
class: primary
speed_limits:
- between: [0, 0.15]
max_speed:
type: maximum
speed:
value: 100
unit: km/h
- between: [0.15, 1]
max_speed:
type: maximum
speed:
value: 60
unit: km/h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ properties:
subtype: road
class: residential
speed_limits:
- max_speed:
- type: maximum
speed:
value: 30
unit: km/h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: speed-limits-variable-max
id: speed-limits-directional
type: Feature
geometry:
type: LineString
Expand All @@ -13,8 +13,10 @@ properties:
subtype: road
class: secondary
speed_limits:
- max_speed: {value: 70, unit: "mph"}
- type: maximum
speed: {value: 70, unit: "mph"}
- when:
mode: [hgv]
heading: forward
max_speed: {value: 65, unit: "mph"}
type: maximum
speed: {value: 65, unit: "mph"}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ properties:
version: 1
subtype: road
class: motorway
road_flags:
- values: [dynamic_speed]
speed_limits:
- max_speed:
- type: maximum
speed:
value: 100
unit: km/h
is_max_speed_variable: true
25 changes: 25 additions & 0 deletions examples/transportation/docusaurus/speed-limits-04-advisory.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
id: speed-limits-advisory
type: Feature
geometry:
type: LineString
coordinates:
- [-123.36051977110497, 48.42945540586221]
- [-123.36053780784551, 48.42906755412086]
- [-123.36034842206483, 48.42868269843091]
properties:
theme: transportation
type: segment
version: 1
subtype: road
class: secondary
speed_limits:
- type: maximum
speed:
value: 60
unit: km/h
- between: [0.4, 1]
type: advisory
speed:
value: 40
unit: km/h
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,46 @@ properties:
subtype: road
class: tertiary
version: 3
road_flags:
- values: [dynamic_speed]
when: {heading: forward}
- values: [dynamic_speed]
between: [0.25, 0.5]
when: {heading: forward}
speed_limits:
- max_speed: {value: 20, unit: 'km/h'}
- type: maximum
speed: {value: 20, unit: 'km/h'}
between: [ 0, 0.5 ]
- min_speed: {value: 25, unit: 'mph'}
- type: minimum
speed: {value: 25, unit: 'mph'}
when:
during: PH
- max_speed: {value: 100, unit: 'km/h'}
min_speed: {value: 75, unit: 'km/h'}
- type: maximum
speed: {value: 100, unit: 'km/h'}
when: {heading: forward}
- type: minimum
speed: {value: 75, unit: 'km/h'}
when: {heading: forward}
- min_speed: {value: 25, unit: 'mph'}
- type: minimum
speed: {value: 25, unit: 'mph'}
when:
heading: forward
mode: [car, hgv]
- max_speed: {value: 60, unit: 'mph'}
is_max_speed_variable: true
- type: maximum
speed: {value: 60, unit: 'mph'}
when:
heading: forward
using: [at_destination]
- min_speed: {value: 25, unit: 'mph'}
- type: advisory
speed: {value: 45, unit: 'mph'}
between: [ 0.5, 1 ]
- type: minimum
speed: {value: 25, unit: 'mph'}
when:
heading: forward
recognized: [as_employee]
- min_speed: {value: 40, unit: 'mph'}
- type: minimum
speed: {value: 40, unit: 'mph'}
when:
heading: forward
vehicle:
Expand All @@ -47,9 +64,8 @@ properties:
comparison: less_than
value: 12
unit: 'ft'
- max_speed: {value: 30, unit: 'km/h'}
min_speed: {value: 20, unit: 'mph'}
is_max_speed_variable: true
- type: maximum
speed: {value: 30, unit: 'km/h'}
between: [0.25, 0.5]
when:
heading: forward
Expand Down
15 changes: 9 additions & 6 deletions examples/transportation/segment/road/road.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,27 @@ properties:
road_surface:
- value: gravel
road_flags:
- values: [is_link, is_tunnel] # Note: `is_link` is deprecated and will be removed in a future release in favor of the link subclass
- values: [is_link, is_tunnel, dynamic_speed] # Note: `is_link` is deprecated and will be removed in a future release in favor of the link subclass
level_rules:
- value: -1
width_rules:
- value: 10
speed_limits:
- min_speed:
- type: minimum
speed:
value: 90
unit: km/h
max_speed:
- type: maximum
speed:
value: 110
unit: mph
is_max_speed_variable: true
- max_speed:
- type: maximum
speed:
value: 55
unit: mph
when: {mode: [ "truck" ]}
- max_speed:
- type: maximum
speed:
value: 30
unit: km/h
between: [0.25, 0.50]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1605,16 +1605,6 @@ def test_shared_fields_have_no_variant_values(
for node in subtype_nodes:
assert node.guards == ()

def test_speed_limits_require_any_of_in_model_nodes(
self, model_nodes: list[ModelCheck]
) -> None:
speed_limit_nodes = [
n
for n in _filter_nodes(model_nodes, "check_require_any_of")
if n.target == _path("speed_limits[]")
]
assert len(speed_limit_nodes) >= 1

def test_destinations_require_any_of_in_model_nodes(
self, model_nodes: list[ModelCheck]
) -> None:
Expand Down
2 changes: 1 addition & 1 deletion packages/overture-schema-common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ from overture.schema.system.numeric import float32

@scoped(Scope.GEOMETRIC_RANGE, Scope.TEMPORAL)
class SpeedLimit(BaseModel):
max_speed: float32
speed: float32
```

This produces a model with `between` (geometric range) and `when.during` (temporal) fields, both optional. The full set of scopes and the fields they inject:
Expand Down
3 changes: 2 additions & 1 deletion packages/overture-schema-theme-transportation/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ unit = "m"
value = 5.2

[[examples.Segment.speed_limits]]
type = "maximum"

[examples.Segment.speed_limits.max_speed]
[examples.Segment.speed_limits.speed]
unit = "km/h"
value = 60

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
SegmentSubtype,
Speed,
SpeedLimitRule,
SpeedLimitType,
TransportationSegment,
WaterSegment,
WidthRule,
Expand Down Expand Up @@ -69,6 +70,7 @@
"SegmentSubtype",
"Speed",
"SpeedLimitRule",
"SpeedLimitType",
"TransportationSegment",
"WaterSegment",
"WidthRule",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
SegmentSubtype,
Speed,
SpeedLimitRule,
SpeedLimitType,
TransportationSegment,
WidthRule,
)
Expand Down Expand Up @@ -91,6 +92,7 @@
"SegmentSubtype",
"Speed",
"SpeedLimitRule",
"SpeedLimitType",
"TransportationSegment",
"WaterSegment",
"WidthRule",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
GeometryType,
GeometryTypeConstraint,
)
from overture.schema.system.model_constraint import no_extra_fields, require_any_of
from overture.schema.system.model_constraint import no_extra_fields
from overture.schema.system.numeric import float64, int32
from overture.schema.system.ref import Id, Reference, Relationship

Expand Down Expand Up @@ -297,8 +297,18 @@ class Speed(BaseModel):
unit: SpeedUnit


class SpeedLimitType(str, DocumentedEnum):
"""The kind of speed limit."""

ADVISORY = (
"advisory",
"A recommended safe speed (e.g. before sharp curves or on ramps)",
)
MAXIMUM = "maximum"
MINIMUM = "minimum"


@no_extra_fields
@require_any_of("max_speed", "min_speed")
@scoped(
Scope.GEOMETRIC_RANGE,
Scope.HEADING,
Expand All @@ -311,17 +321,10 @@ class Speed(BaseModel):
class SpeedLimitRule(BaseModel):
"""An individual speed limit rule."""

# Optional
# Required

max_speed: Speed | None = None
min_speed: Speed | None = None
is_max_speed_variable: Annotated[
bool | None,
Field(
description="Indicates a variable speed corridor",
strict=True,
),
] = False
type: SpeedLimitType
speed: Speed


SpeedLimits = NewType(
Expand Down
Loading
Loading