You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					348 lines
				
				13 KiB
			
		
		
			
		
	
	
					348 lines
				
				13 KiB
			| 
											1 year ago
										 | from dataclasses import dataclass as _dataclass, field, is_dataclass
 | ||
| 
											1 year ago
										 | from enum import Enum, StrEnum as _StrEnum, auto
 | ||
| 
											1 year ago
										 | from typing import dataclass_transform, get_origin
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 | auto_obj = object()
 | ||
|  | 
 | ||
|  | 
 | ||
|  | def auto_field():
 | ||
|  |   return auto_obj
 | ||
|  | 
 | ||
|  | 
 | ||
| 
											1 year ago
										 | @dataclass_transform()
 | ||
|  | def auto_dataclass(cls=None, /, **kwargs):
 | ||
| 
											1 year ago
										 |   cls_annotations = cls.__dict__.get('__annotations__', {})
 | ||
|  |   for name, typ in cls_annotations.items():
 | ||
|  |     current_value = getattr(cls, name, None)
 | ||
|  |     if current_value is auto_obj:
 | ||
|  |       origin_typ = get_origin(typ) or typ
 | ||
|  |       if isinstance(origin_typ, str):
 | ||
|  |         raise TypeError(f"Forward references are not supported for auto_field: '{origin_typ}'. Use a default_factory with lambda instead.")
 | ||
|  |       elif origin_typ in (int, float, str, bytes, list, tuple, set, dict, bool) or is_dataclass(origin_typ):
 | ||
|  |         setattr(cls, name, field(default_factory=origin_typ))
 | ||
|  |       elif origin_typ is None:
 | ||
|  |         setattr(cls, name, field(default=origin_typ))
 | ||
|  |       elif issubclass(origin_typ, Enum):  # first enum is the default
 | ||
|  |         setattr(cls, name, field(default=next(iter(origin_typ))))
 | ||
|  |       else:
 | ||
|  |         raise TypeError(f"Unsupported type for auto_field: {origin_typ}")
 | ||
| 
											1 year ago
										 | 
 | ||
|  |   return _dataclass(cls, **kwargs)
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 | class StrEnum(_StrEnum):
 | ||
| 
											1 year ago
										 |   @staticmethod
 | ||
|  |   def _generate_next_value_(name, *args):
 | ||
|  |     # auto() defaults to name.lower()
 | ||
|  |     return name
 | ||
|  | 
 | ||
|  | 
 | ||
| 
											1 year ago
										 | @auto_dataclass
 | ||
|  | class CarState:
 | ||
|  |   # events: list[CarEvent] = auto_field()
 | ||
|  | 
 | ||
|  |   canValid: bool = auto_field()  # invalid counter/checksums
 | ||
|  |   canTimeout: bool = auto_field()  # CAN bus dropped out
 | ||
|  |   canErrorCounter: int = auto_field()
 | ||
|  | 
 | ||
|  |   vEgo: float = auto_field()  # best estimate of speed
 | ||
|  |   aEgo: float = auto_field()  # best estimate of acceleration
 | ||
|  |   vEgoRaw: float = auto_field()  # unfiltered speed from CAN sensors
 | ||
|  |   vEgoCluster: float = auto_field()  # best estimate of speed shown on car's instrument cluster, used for UI
 | ||
|  | 
 | ||
|  |   yawRate: float = auto_field()  # best estimate of yaw rate
 | ||
|  |   standstill: bool = auto_field()
 | ||
|  |   # wheelSpeeds: WheelSpeeds = auto_field()
 | ||
|  | 
 | ||
|  |   gas: float = auto_field()  # this is user pedal only
 | ||
|  |   gasPressed: bool = auto_field()  # this is user pedal only
 | ||
|  | 
 | ||
|  |   engineRpm: float = auto_field()
 | ||
|  | 
 | ||
|  |   brake: float = auto_field()  # this is user pedal only
 | ||
|  |   brakePressed: bool = auto_field()  # this is user pedal only
 | ||
|  |   regenBraking: bool = auto_field()  # this is user pedal only
 | ||
|  |   parkingBrake: bool = auto_field()
 | ||
|  |   brakeHoldActive: bool = auto_field()
 | ||
|  | 
 | ||
|  |   steeringAngleDeg: float = auto_field()
 | ||
|  |   steeringAngleOffsetDeg: float = auto_field()  # Offset betweens sensors in case there multiple
 | ||
|  |   steeringRateDeg: float = auto_field()
 | ||
|  |   steeringTorque: float = auto_field()  # TODO: standardize units
 | ||
|  |   steeringTorqueEps: float = auto_field()  # TODO: standardize units
 | ||
|  |   steeringPressed: bool = auto_field()  # if the user is using the steering wheel
 | ||
|  |   steerFaultTemporary: bool = auto_field()  # temporary EPS fault
 | ||
|  |   steerFaultPermanent: bool = auto_field()  # permanent EPS fault
 | ||
|  |   stockAeb: bool = auto_field()
 | ||
|  |   stockFcw: bool = auto_field()
 | ||
|  |   espDisabled: bool = auto_field()
 | ||
|  |   accFaulted: bool = auto_field()
 | ||
|  |   carFaultedNonCritical: bool = auto_field()  # some ECU is faulted, but car remains controllable
 | ||
|  |   espActive: bool = auto_field()
 | ||
|  | 
 | ||
|  |   # cruiseState: CruiseState = auto_field()
 | ||
|  | 
 | ||
|  |   # gearShifter: GearShifter = auto_field()
 | ||
|  | 
 | ||
|  |   # buttonEvents: list[ButtonEvent] = auto_field()
 | ||
|  |   leftBlinker: bool = auto_field()
 | ||
|  |   rightBlinker: bool = auto_field()
 | ||
|  |   genericToggle: bool = auto_field()
 | ||
|  | 
 | ||
|  |   doorOpen: bool = auto_field()
 | ||
|  |   seatbeltUnlatched: bool = auto_field()
 | ||
|  | 
 | ||
|  |   clutchPressed: bool = auto_field()
 | ||
|  | 
 | ||
|  |   leftBlindspot: bool = auto_field()  # Is there something blocking the left lane change
 | ||
|  |   rightBlindspot: bool = auto_field()  # Is there something blocking the right lane change
 | ||
|  | 
 | ||
|  |   fuelGauge: float = auto_field()  # battery or fuel tank level from 0.0 to 1.0
 | ||
|  |   charging: bool = auto_field()
 | ||
|  | 
 | ||
|  |   cumLagMs: float = auto_field()
 | ||
|  | 
 | ||
|  | 
 | ||
| 
											1 year ago
										 | @auto_dataclass
 | ||
| 
											1 year ago
										 | class RadarData:
 | ||
| 
											1 year ago
										 |   errors: list['Error'] = auto_field()
 | ||
|  |   points: list['RadarPoint'] = auto_field()
 | ||
| 
											1 year ago
										 | 
 | ||
|  |   class Error(StrEnum):
 | ||
|  |     canError = auto()
 | ||
|  |     fault = auto()
 | ||
|  |     wrongConfig = auto()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class RadarPoint:
 | ||
| 
											1 year ago
										 |     trackId: int = auto_field()  # no trackId reuse
 | ||
| 
											1 year ago
										 | 
 | ||
|  |     # these 3 are the minimum required
 | ||
| 
											1 year ago
										 |     dRel: float = auto_field()  # m from the front bumper of the car
 | ||
|  |     yRel: float = auto_field()  # m
 | ||
|  |     vRel: float = auto_field()  # m/s
 | ||
| 
											1 year ago
										 | 
 | ||
|  |     # these are optional and valid if they are not NaN
 | ||
| 
											1 year ago
										 |     aRel: float = auto_field()  # m/s^2
 | ||
|  |     yvRel: float = auto_field()  # m/s
 | ||
| 
											1 year ago
										 | 
 | ||
|  |     # some radars flag measurements VS estimates
 | ||
| 
											1 year ago
										 |     measured: bool = auto_field()
 | ||
| 
											1 year ago
										 | 
 | ||
|  | 
 | ||
| 
											1 year ago
										 | @auto_dataclass
 | ||
| 
											1 year ago
										 | class CarParams:
 | ||
|  |   carName: str = auto_field()
 | ||
|  |   carFingerprint: str = auto_field()
 | ||
|  |   fuzzyFingerprint: bool = auto_field()
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |   notCar: bool = auto_field()  # flag for non-car robotics platforms
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |   pcmCruise: bool = auto_field()  # is openpilot's state tied to the PCM's cruise state?
 | ||
|  |   enableDsu: bool = auto_field()  # driving support unit
 | ||
|  |   enableBsm: bool = auto_field()  # blind spot monitoring
 | ||
|  |   flags: int = auto_field()  # flags for car specific quirks
 | ||
|  |   experimentalLongitudinalAvailable: bool = auto_field()
 | ||
|  | 
 | ||
|  |   minEnableSpeed: float = auto_field()
 | ||
|  |   minSteerSpeed: float = auto_field()
 | ||
| 
											1 year ago
										 |   safetyConfigs: list['CarParams.SafetyConfig'] = auto_field()
 | ||
| 
											1 year ago
										 |   alternativeExperience: int = auto_field()  # panda flag for features like no disengage on gas
 | ||
|  | 
 | ||
|  |   maxLateralAccel: float = auto_field()
 | ||
|  |   autoResumeSng: bool = auto_field()  # describes whether car can resume from a stop automatically
 | ||
|  | 
 | ||
|  |   mass: float = auto_field()  # [kg] curb weight: all fluids no cargo
 | ||
|  |   wheelbase: float = auto_field()  # [m] distance from rear axle to front axle
 | ||
|  |   centerToFront: float = auto_field()  # [m] distance from center of mass to front axle
 | ||
|  |   steerRatio: float = auto_field()  # [] ratio of steering wheel angle to front wheel angle
 | ||
|  |   steerRatioRear: float = auto_field()  # [] ratio of steering wheel angle to rear wheel angle (usually 0)
 | ||
|  | 
 | ||
|  |   rotationalInertia: float = auto_field()  # [kg*m2] body rotational inertia
 | ||
|  |   tireStiffnessFactor: float = auto_field()  # scaling factor used in calculating tireStiffness[Front,Rear]
 | ||
|  |   tireStiffnessFront: float = auto_field()  # [N/rad] front tire coeff of stiff
 | ||
|  |   tireStiffnessRear: float = auto_field()  # [N/rad] rear tire coeff of stiff
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   longitudinalTuning: 'CarParams.LongitudinalPIDTuning' = field(default_factory=lambda: CarParams.LongitudinalPIDTuning())
 | ||
|  |   lateralParams: 'CarParams.LateralParams' = field(default_factory=lambda: CarParams.LateralParams())
 | ||
| 
											1 year ago
										 |   lateralTuning: 'CarParams.LateralTuning' = field(default_factory=lambda: CarParams.LateralTuning())
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class LateralTuning:
 | ||
| 
											1 year ago
										 |     def init(self, _which: str):
 | ||
|  |       assert _which in ('pid', 'torque'), 'Invalid union type'
 | ||
|  |       self._which = _which
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |     def which(self):
 | ||
|  |       return self._which
 | ||
|  | 
 | ||
|  |     _which: str = 'pid'
 | ||
| 
											1 year ago
										 | 
 | ||
|  |     pid: 'CarParams.LateralPIDTuning' = field(default_factory=lambda: CarParams.LateralPIDTuning())
 | ||
|  |     torque: 'CarParams.LateralTorqueTuning' = field(default_factory=lambda: CarParams.LateralTorqueTuning())
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class SafetyConfig:
 | ||
|  |     safetyModel: 'CarParams.SafetyModel' = field(default_factory=lambda: CarParams.SafetyModel.silent)
 | ||
|  |     safetyParam: int = auto_field()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class LateralParams:
 | ||
|  |     torqueBP: list[int] = auto_field()
 | ||
|  |     torqueV: list[int] = auto_field()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class LateralPIDTuning:
 | ||
|  |     kpBP: list[float] = auto_field()
 | ||
|  |     kpV: list[float] = auto_field()
 | ||
|  |     kiBP: list[float] = auto_field()
 | ||
|  |     kiV: list[float] = auto_field()
 | ||
|  |     kf: float = auto_field()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class LateralTorqueTuning:
 | ||
|  |     useSteeringAngle: bool = auto_field()
 | ||
|  |     kp: float = auto_field()
 | ||
|  |     ki: float = auto_field()
 | ||
|  |     friction: float = auto_field()
 | ||
|  |     kf: float = auto_field()
 | ||
|  |     steeringAngleDeadzoneDeg: float = auto_field()
 | ||
|  |     latAccelFactor: float = auto_field()
 | ||
|  |     latAccelOffset: float = auto_field()
 | ||
|  | 
 | ||
|  |   steerLimitAlert: bool = auto_field()
 | ||
|  |   steerLimitTimer: float = auto_field()  # time before steerLimitAlert is issued
 | ||
|  | 
 | ||
|  |   vEgoStopping: float = auto_field()  # Speed at which the car goes into stopping state
 | ||
|  |   vEgoStarting: float = auto_field()  # Speed at which the car goes into starting state
 | ||
|  |   stoppingControl: bool = auto_field()  # Does the car allow full control even at lows speeds when stopping
 | ||
|  |   steerControlType: 'CarParams.SteerControlType' = field(default_factory=lambda: CarParams.SteerControlType.torque)
 | ||
|  |   radarUnavailable: bool = auto_field()  # True when radar objects aren't visible on CAN or aren't parsed out
 | ||
|  |   stopAccel: float = auto_field()  # Required acceleration to keep vehicle stationary
 | ||
|  |   stoppingDecelRate: float = auto_field()  # m/s^2/s while trying to stop
 | ||
|  |   startAccel: float = auto_field()  # Required acceleration to get car moving
 | ||
|  |   startingState: bool = auto_field()  # Does this car make use of special starting state
 | ||
|  | 
 | ||
|  |   steerActuatorDelay: float = auto_field()  # Steering wheel actuator delay in seconds
 | ||
|  |   longitudinalActuatorDelay: float = auto_field()  # Gas/Brake actuator delay in seconds
 | ||
|  |   openpilotLongitudinalControl: bool = auto_field()  # is openpilot doing the longitudinal control?
 | ||
|  |   carVin: str = auto_field()  # VIN number queried during fingerprinting
 | ||
|  |   dashcamOnly: bool = auto_field()
 | ||
|  |   passive: bool = auto_field()  # is openpilot in control?
 | ||
| 
											1 year ago
										 |   transmissionType: 'CarParams.TransmissionType' = field(default_factory=lambda: CarParams.TransmissionType.unknown)
 | ||
| 
											1 year ago
										 |   carFw: list['CarParams.CarFw'] = auto_field()
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |   radarTimeStep: float = 0.05  # time delta between radar updates, 20Hz is very standard
 | ||
| 
											1 year ago
										 |   fingerprintSource: 'CarParams.FingerprintSource' = field(default_factory=lambda: CarParams.FingerprintSource.can)
 | ||
|  |   # Where Panda/C2 is integrated into the car's CAN network
 | ||
|  |   networkLocation: 'CarParams.NetworkLocation' = field(default_factory=lambda: CarParams.NetworkLocation.fwdCamera)
 | ||
| 
											1 year ago
										 | 
 | ||
|  |   wheelSpeedFactor: float = auto_field()  # Multiplier on wheels speeds to computer actual speeds
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class LongitudinalPIDTuning:
 | ||
|  |     kpBP: list[float] = auto_field()
 | ||
|  |     kpV: list[float] = auto_field()
 | ||
|  |     kiBP: list[float] = auto_field()
 | ||
|  |     kiV: list[float] = auto_field()
 | ||
|  |     kf: float = auto_field()
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |   class SafetyModel(StrEnum):
 | ||
|  |     silent = auto()
 | ||
|  |     hondaNidec = auto()
 | ||
|  |     toyota = auto()
 | ||
|  |     elm327 = auto()
 | ||
|  |     gm = auto()
 | ||
|  |     hondaBoschGiraffe = auto()
 | ||
|  |     ford = auto()
 | ||
|  |     cadillac = auto()
 | ||
|  |     hyundai = auto()
 | ||
|  |     chrysler = auto()
 | ||
|  |     tesla = auto()
 | ||
|  |     subaru = auto()
 | ||
|  |     gmPassive = auto()
 | ||
|  |     mazda = auto()
 | ||
|  |     nissan = auto()
 | ||
|  |     volkswagen = auto()
 | ||
|  |     toyotaIpas = auto()
 | ||
|  |     allOutput = auto()
 | ||
|  |     gmAscm = auto()
 | ||
|  |     noOutput = auto()  # like silent but without silent CAN TXs
 | ||
|  |     hondaBosch = auto()
 | ||
|  |     volkswagenPq = auto()
 | ||
|  |     subaruPreglobal = auto()  # pre-Global platform
 | ||
|  |     hyundaiLegacy = auto()
 | ||
|  |     hyundaiCommunity = auto()
 | ||
|  |     volkswagenMlb = auto()
 | ||
|  |     hongqi = auto()
 | ||
|  |     body = auto()
 | ||
|  |     hyundaiCanfd = auto()
 | ||
|  |     volkswagenMqbEvo = auto()
 | ||
|  |     chryslerCusw = auto()
 | ||
|  |     psa = auto()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   class SteerControlType(StrEnum):
 | ||
|  |     torque = auto()
 | ||
|  |     angle = auto()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   class TransmissionType(StrEnum):
 | ||
|  |     unknown = auto()
 | ||
|  |     automatic = auto()  # Traditional auto, including DSG
 | ||
|  |     manual = auto()  # True "stick shift" only
 | ||
|  |     direct = auto()  # Electric vehicle or other direct drive
 | ||
|  |     cvt = auto()
 | ||
|  | 
 | ||
| 
											1 year ago
										 |   @auto_dataclass
 | ||
| 
											1 year ago
										 |   class CarFw:
 | ||
|  |     ecu: 'CarParams.Ecu' = field(default_factory=lambda: CarParams.Ecu.unknown)
 | ||
|  |     fwVersion: bytes = auto_field()
 | ||
|  |     address: int = auto_field()
 | ||
|  |     subAddress: int = auto_field()
 | ||
|  |     responseAddress: int = auto_field()
 | ||
|  |     request: list[bytes] = auto_field()
 | ||
|  |     brand: str = auto_field()
 | ||
|  |     bus: int = auto_field()
 | ||
|  |     logging: bool = auto_field()
 | ||
|  |     obdMultiplexing: bool = auto_field()
 | ||
| 
											1 year ago
										 | 
 | ||
| 
											1 year ago
										 |   class Ecu(StrEnum):
 | ||
|  |     eps = auto()
 | ||
|  |     abs = auto()
 | ||
|  |     fwdRadar = auto()
 | ||
|  |     fwdCamera = auto()
 | ||
|  |     engine = auto()
 | ||
|  |     unknown = auto()
 | ||
|  |     transmission = auto()  # Transmission Control Module
 | ||
|  |     hybrid = auto()  # hybrid control unit, e.g. Chrysler's HCP, Honda's IMA Control Unit, Toyota's hybrid control computer
 | ||
|  |     srs = auto()  # airbag
 | ||
|  |     gateway = auto()  # can gateway
 | ||
|  |     hud = auto()  # heads up display
 | ||
|  |     combinationMeter = auto()  # instrument cluster
 | ||
|  |     electricBrakeBooster = auto()
 | ||
|  |     shiftByWire = auto()
 | ||
|  |     adas = auto()
 | ||
|  |     cornerRadar = auto()
 | ||
|  |     hvac = auto()
 | ||
|  |     parkingAdas = auto()  # parking assist system ECU, e.g. Toyota's IPAS, Hyundai's RSPA, etc.
 | ||
|  |     epb = auto()  # electronic parking brake
 | ||
|  |     telematics = auto()
 | ||
|  |     body = auto()  # body control module
 | ||
|  | 
 | ||
|  |     # Toyota only
 | ||
|  |     dsu = auto()
 | ||
|  | 
 | ||
|  |     # Honda only
 | ||
|  |     vsa = auto()  # Vehicle Stability Assist
 | ||
|  |     programmedFuelInjection = auto()
 | ||
|  | 
 | ||
|  |     debug = auto()
 | ||
| 
											1 year ago
										 | 
 | ||
|  |   class FingerprintSource(StrEnum):
 | ||
|  |     can = auto()
 | ||
|  |     fw = auto()
 | ||
|  |     fixed = auto()
 | ||
|  | 
 | ||
|  |   class NetworkLocation(StrEnum):
 | ||
|  |     fwdCamera = auto()  # Standard/default integration at LKAS camera
 | ||
|  |     gateway = auto()    # Integration at vehicle's CAN gateway
 |