nopenpilot/selfdrive/car/docs_definitions.py

105 lines
3.5 KiB
Python

from cereal import car
from collections import namedtuple
from dataclasses import dataclass
from enum import Enum
from typing import Dict, List, Optional, Union
import typing
class Tier(Enum):
GOLD = "The best openpilot experience. Great highway driving and beyond."
SILVER = "A solid highway driving experience, but is limited by stock longitudinal. May be upgraded in the future."
BRONZE = "A good highway experience, but may have limited performance in traffic and on sharp turns."
class Column(Enum):
MAKE = "Make"
MODEL = "Model"
PACKAGE = "Supported Package"
LONGITUDINAL = "openpilot ACC"
FSR_LONGITUDINAL = "Stop and Go"
FSR_STEERING = "Steer to 0"
STEERING_TORQUE = "Steering Torque"
MAINTAINED = "Actively Maintained"
class Star(Enum):
FULL = "full"
HALF = "half"
EMPTY = "empty"
StarColumns = list(Column)[3:]
CarFootnote = namedtuple("CarFootnote", ["text", "column", "star"], defaults=[None])
def get_footnote(footnotes: Optional[List[Enum]], column: Column) -> Optional[Enum]:
# Returns applicable footnote given current column
if footnotes is not None:
for fn in footnotes:
if fn.value.column == column:
return fn
return None
@dataclass
class CarInfo:
name: str
package: str
video_link: Optional[str] = None
footnotes: Optional[List[Enum]] = None
min_steer_speed: Optional[float] = None
min_enable_speed: Optional[float] = None
good_torque: bool = False
def init(self, CP: car.CarParams, non_tested_cars: List[str], all_footnotes: Dict[Enum, int]):
# TODO: set all the min steer speeds in carParams and remove this
min_steer_speed = CP.minSteerSpeed
if self.min_steer_speed is not None:
min_steer_speed = self.min_steer_speed
assert CP.minSteerSpeed == 0, f"Minimum steer speed set in both CarInfo and CarParams for {CP.carFingerprint}"
# TODO: set all the min enable speeds in carParams correctly and remove this
min_enable_speed = CP.minEnableSpeed
if self.min_enable_speed is not None:
min_enable_speed = self.min_enable_speed
self.make, self.model = self.name.split(' ', 1)
self.row = {
Column.MAKE: self.make,
Column.MODEL: self.model,
Column.PACKAGE: self.package,
# StarColumns
Column.LONGITUDINAL: CP.openpilotLongitudinalControl and not CP.radarOffCan,
Column.FSR_LONGITUDINAL: min_enable_speed <= 0.,
Column.FSR_STEERING: min_steer_speed <= 0.,
Column.STEERING_TORQUE: self.good_torque,
Column.MAINTAINED: CP.carFingerprint not in non_tested_cars,
}
self.all_footnotes = all_footnotes
for column in StarColumns:
self.row[column] = Star.FULL if self.row[column] else Star.EMPTY
# Demote if footnote specifies a star
footnote = get_footnote(self.footnotes, column)
if footnote is not None and footnote.value.star is not None:
self.row[column] = footnote.value.star
self.tier = {5: Tier.GOLD, 4: Tier.SILVER}.get(list(self.row.values()).count(Star.FULL), Tier.BRONZE)
@typing.no_type_check
def get_column(self, column: Column, star_icon: str, footnote_tag: str, video_link_tag: Optional[str] = None) -> str:
item: Union[str, Star] = self.row[column]
if column in StarColumns:
item = star_icon.format(item.value)
footnote = get_footnote(self.footnotes, column)
if footnote is not None:
item += footnote_tag.format(self.all_footnotes[footnote])
if column == Column.MODEL and self.video_link is not None and video_link_tag is not None:
item += video_link_tag.format(self.video_link)
return item