Source code for mimic_data_api.radar

"""
Radar Module
============

This module provides data structures for representing radar sensors,
including intrinsic parameters, point cloud data, and calibration information.

Supports automotive radar sensors with configurable resolution, field of view,
and velocity measurement capabilities.

Classes
-------
RadarIntrinsics
    Internal radar sensor parameters.
RadarPointCloudData
    Metadata and optional point cloud data for a single radar scan.
Radar
    Complete radar sensor representation.

Example
-------
Creating a radar sensor::

    import numpy as np
    from mimic_data_api.radar import Radar, RadarIntrinsics, RadarPointCloudData
    from mimic_data_api.trajectory_numpy import WorldTrajectory

    radar = Radar(
        id=1,
        name="front_radar",
        extrinsics=np.eye(4),
        intrinsics=RadarIntrinsics(
            range=200.0,
            azimuth_fov=2.0,  # ~115 degrees
            elevation_fov=0.35,  # ~20 degrees
            azimuth_resolution=[(0.0, 0.03), (1.0, 0.05)],
            elevation_resolution=None,
            min_speed_resolution=-50.0,
            max_speed_resolution=50.0
        ),
        trajectory=trajectory,
        radar_pcds_data=[...]
    )
"""

from pydantic import BaseModel, Field
import numpy as np

from mimic_data_api.extrinsic import SensorExtrinsic
from mimic_data_api.trajectory_numpy import WorldTrajectory
from mimic_data_api import RadarPointCloud


[docs] class RadarIntrinsics(BaseModel): """Internal parameters for a radar sensor. Defines the sensing characteristics of a radar including field of view, angular resolution, range, and velocity measurement capabilities. Attributes ---------- range : float Maximum detection range in meters. Must be >= 0. azimuth_fov : float Horizontal field of view in radians. Must be >= 0. elevation_fov : float Vertical field of view in radians. Must be >= 0. azimuth_resolution : list of tuple[float, float] Azimuth (horizontal) angular resolution as a function of angle. Each tuple contains (angle_in_radians, resolution_in_radians). Resolution may vary across the field of view, hence the list format. elevation_resolution : list of tuple[float, float] or None Elevation (vertical) angular resolution for imaging radars. Same format as ``azimuth_resolution``. ``None`` for non-imaging radars. min_speed_resolution : float Minimum measurable radial (Doppler) velocity in m/s. Typically negative, representing approaching targets. max_speed_resolution : float Maximum measurable radial (Doppler) velocity in m/s. Typically positive, representing receding targets. Note ---- Resolution parameters are specified as (angle, resolution) pairs because many radar sensors have angle-dependent resolution - typically better resolution near boresight and degraded resolution at the edges of FOV. Example ------- >>> intrinsics = RadarIntrinsics( ... range=200.0, # 200m max range ... azimuth_fov=2.09, # 120 degrees ... elevation_fov=0.35, # 20 degrees ... azimuth_resolution=[ ... (0.0, 0.017), # 1 degree at boresight ... (0.5, 0.026), # 1.5 degrees at 30 degrees off-axis ... (1.0, 0.035) # 2 degrees at edge of FOV ... ], ... elevation_resolution=None, # Non-imaging radar ... min_speed_resolution=-70.0, ... max_speed_resolution=70.0 ... ) """ range: float = Field(ge=0, description="Maximum range of the radar in meters") azimuth_fov: float = Field(ge=0, description="Horizontal field of view in rads") elevation_fov: float = Field(ge=0, description="Vertical field of view in rads") azimuth_resolution: list[tuple[float, float]] = Field( description="Azimuth resolution (in rads) at specific angles (in rads). Typically azimuth resolution is given for different range of azimuth." ) elevation_resolution: list[tuple[float, float]] | None = Field( description="Elevation resolution (in rads) at specific angles (in rads), for imaging radars." ) min_speed_resolution: float = Field( description="Minimum measurable radial speed in m/s." ) max_speed_resolution: float = Field( description="Maximum measurable radial speed in m/s." )
[docs] class RadarPointCloudData(BaseModel): """Metadata and optional point cloud data for a single radar scan. This class stores information about individual radar detections, including file location and timestamp. Attributes ---------- filepath : str Path to the point cloud file (PLY format). radar_pcd : RadarPointCloud or None Optional in-memory point cloud data. Not serialized to JSON. timestamp : float Timestamp in seconds corresponding to the middle of the scan. Note ---- Radar point clouds typically include additional per-point attributes such as radial velocity (Doppler), radar cross-section (RCS), and signal-to-noise ratio (SNR). Example ------- >>> pcd_data = RadarPointCloudData( ... filepath="data/radar/scan_000.ply", ... timestamp=0.0 ... ) """ filepath: str = Field(description="Filepath to the point cloud data plyfile.") radar_pcd: RadarPointCloud | None = Field( default=None, exclude=True, description="Radar point-cloud to be used when loading a scene, will not be serialized in json file.", ) timestamp: float = Field( description="Timestamp of the radar point cloud in seconds that corresponds to the middle of the scan." )
[docs] class Radar(BaseModel): """Complete radar sensor representation. This class encapsulates all information about a radar sensor including its calibration, intrinsic parameters, trajectory, and captured point cloud data. Attributes ---------- id : int Unique identifier for the radar within the sensor suite. name : str Human-readable name for the radar (e.g., "front_radar", "corner_radar"). extrinsics : SensorExtrinsic 4x4 transformation matrix from sensor frame to vehicle frame. intrinsics : RadarIntrinsics Internal radar parameters (FOV, resolution, range, velocity limits). trajectory : WorldTrajectory Time-series of radar poses in world coordinates. radar_pcds_data : list of RadarPointCloudData List of captured radar point clouds with their metadata. Note ---- Radar sensors provide unique capabilities compared to LiDAR and cameras: - Direct velocity measurement via Doppler effect - Better performance in adverse weather (rain, fog, dust) - Longer detection range for some targets - Lower angular resolution compared to LiDAR Example ------- >>> radar = Radar( ... id=0, ... name="front_long_range_radar", ... extrinsics=np.eye(4), ... intrinsics=intrinsics, ... trajectory=trajectory, ... radar_pcds_data=[pcd_data] ... ) """ id: int name: str extrinsics: SensorExtrinsic = Field( description="Extrinsic calibration from sensor to vehicle frame" ) intrinsics: RadarIntrinsics trajectory: WorldTrajectory radar_pcds_data: list[RadarPointCloudData] = Field( description="List of point clouds captured by the radar sensor." )
[docs] def __eq__(self, other: object) -> bool: """Check equality with another Radar. Performs deep comparison of all radar attributes including calibration parameters, trajectory, and point cloud data. Parameters ---------- other : object The object to compare against. Returns ------- bool ``True`` if radars are equal, ``False`` otherwise. """ if not isinstance(other, Radar): return False if self.id != other.id: return False if self.name != other.name: return False if not np.allclose(self.extrinsics, other.extrinsics): return False if self.intrinsics != other.intrinsics: return False if self.trajectory != other.trajectory: return False if self.radar_pcds_data != other.radar_pcds_data: return False return True