"""Road elements are simple individual components of the road that have a frame.
Examples are traffic signs, obstacles or surface markings (e.g. turn arrow on the ground.
"""
from dataclasses import dataclass
from typing import Union
from kitcar_utils.geometry import Line, Point, Polygon, Transform
from simulation.utils.road.sections.transformable import Transformable
[docs]@dataclass
class RoadElement(Transformable):
normalize_x: bool = True
"""If true, all x-values are substracted by the lowest x-value."""
_frame: Polygon = Polygon(
[Point(-0.1, -0.2), Point(0.1, -0.2), Point(0.1, 0.2), Point(-0.1, 0.2)]
)
"""Polygon: Frame of the element in local coordinates."""
@property
def frame(self) -> Polygon:
"""Polygon: Frame of the element in global coordinates."""
tf = (
Transform([-self._center.x, 0], 0) if self.normalize_x else Transform([0, 0], 0)
)
return self.transform * (tf * self._frame)
@property
def center(self) -> Point:
"""Point: Center point of the element in global coordinates."""
return Point(self.frame.centroid)
@property
def _center(self) -> Point:
"""Point: Center point of the element in local coordinates."""
return Point(self._frame.centroid)
[docs]@dataclass
class RoadElementRect(RoadElement):
"""Generic element of the road that has a frame.
Examples of road elements are obstacles and traffic signs.
Args:
arc_length: x coordinate of the element along the road.
y: y coordinate of the element. (Perpendicular to the road.)
width: Width of the element.
depth: Depth of the element. Component of the size in the direction of the road.
angle: Angle [radian] between the middle line and the element
(measured at the center).
"""
width: float = 0.2
"""Width of the element."""
depth: float = 0.2
"""Depth (length) of the element."""
angle: float = 0
"""Angle [radian] between the middle line and the element (measured at the center)."""
def __init__(
self,
arc_length: float = 0.4,
y: float = -0.2,
width: float = width,
depth: float = depth,
angle: float = angle,
normalize_x: bool = True,
z: float = 0,
height: float = 0,
):
"""Initialize a retangular road element."""
for obj in arc_length, y, width, depth, angle:
assert isinstance(obj, float) or isinstance(
obj, int
), f"Should be a number but is {obj}"
self.width = width
self.depth = depth
self.angle = angle
self.height = height
super().__init__(
normalize_x=normalize_x,
_frame=Transform(Point(arc_length, y, z), self.angle)
* Polygon(
[
[-self.depth / 2, self.width / 2],
[self.depth / 2, self.width / 2],
[self.depth / 2, -self.width / 2],
[-self.depth / 2, -self.width / 2],
]
),
)
@property
def orientation(self) -> float:
"""float: Orientation of the element in global coordinates in radians."""
return self.transform.get_angle() + self.angle