mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 22:23:56 +08:00
CarInfo: parse out model years (#25208)
* add function
* split model and years
* typing and clean uop
* one function to split into make, model, years
* add test for bad years
* simpler re
* don't match only numbers
* clean up
* we can just use name
* clean up
old-commit-hash: b30871daad
This commit is contained in:
@@ -117,7 +117,7 @@ How We Rate The Cars
|
||||
|Lexus|NX 2020-21|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|NX Hybrid 2018-19|All|<a href="##"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#footnotes)|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|NX Hybrid 2020-21|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RC 2017-2020|All|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RC 2017-20|All|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX 2016-18|All|<a href="##"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#footnotes)|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX 2020-22|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX Hybrid 2016-19|All|<a href="##"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#footnotes)|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
@@ -162,8 +162,8 @@ How We Rate The Cars
|
||||
|Toyota|Camry Hybrid 2021-22|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla 2017-19|All|<a href="##"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#footnotes)|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla 2020-22|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Cross 2020-21 (Non-US only)|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Cross Hybrid 2020-22 (Non-US only)|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Cross (Non-US only) 2020-21|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Hatchback 2019-22|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Hybrid 2020-22|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Highlander 2017-19|All|<a href="##"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#footnotes)|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|
||||
@@ -10,7 +10,6 @@ from common.basedir import BASEDIR
|
||||
from selfdrive.car.docs_definitions import STAR_DESCRIPTIONS, StarColumns, TierColumns, CarInfo, Column, Star
|
||||
from selfdrive.car.car_helpers import interfaces, get_interface_attr
|
||||
from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR as HKG_RADAR_START_ADDR
|
||||
from selfdrive.car.tests.routes import non_tested_cars
|
||||
|
||||
|
||||
def get_all_footnotes() -> Dict[Enum, int]:
|
||||
@@ -40,10 +39,10 @@ def get_all_car_info() -> List[CarInfo]:
|
||||
car_info = (car_info,)
|
||||
|
||||
for _car_info in car_info:
|
||||
all_car_info.append(_car_info.init(CP, non_tested_cars, ALL_FOOTNOTES))
|
||||
all_car_info.append(_car_info.init(CP, ALL_FOOTNOTES))
|
||||
|
||||
# Sort cars by make and model + year
|
||||
sorted_cars: List[CarInfo] = natsorted(all_car_info, key=lambda car: (car.make + car.model).lower())
|
||||
sorted_cars: List[CarInfo] = natsorted(all_car_info, key=lambda car: car.name.lower())
|
||||
return sorted_cars
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import re
|
||||
|
||||
from cereal import car
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Optional, Union, no_type_check
|
||||
from typing import Dict, List, Optional, Tuple, Union, no_type_check
|
||||
|
||||
TACO_TORQUE_THRESHOLD = 2.5 # m/s^2
|
||||
GREAT_TORQUE_THRESHOLD = 1.4 # m/s^2
|
||||
GOOD_TORQUE_THRESHOLD = 1.0 # m/s^2
|
||||
MODEL_YEARS_RE = r"(?<= )((\d{4}-\d{2})|(\d{4}))(,|$)"
|
||||
|
||||
|
||||
class Tier(Enum):
|
||||
@@ -45,6 +46,16 @@ def get_footnote(footnotes: Optional[List[Enum]], column: Column) -> Optional[En
|
||||
return None
|
||||
|
||||
|
||||
def split_name(name: str) -> Tuple[str, str, str]:
|
||||
make, model = name.split(" ", 1)
|
||||
years = ""
|
||||
match = re.search(MODEL_YEARS_RE, model)
|
||||
if match is not None:
|
||||
years = model[match.start():]
|
||||
model = model[:match.start() - 1]
|
||||
return make, model, years
|
||||
|
||||
|
||||
@dataclass
|
||||
class CarInfo:
|
||||
name: str
|
||||
@@ -55,7 +66,7 @@ class CarInfo:
|
||||
min_enable_speed: Optional[float] = None
|
||||
harness: Optional[Enum] = None
|
||||
|
||||
def init(self, CP: car.CarParams, non_tested_cars: List[str], all_footnotes: Dict[Enum, int]):
|
||||
def init(self, CP: car.CarParams, 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:
|
||||
@@ -71,7 +82,7 @@ class CarInfo:
|
||||
|
||||
self.car_name = CP.carName
|
||||
self.car_fingerprint = CP.carFingerprint
|
||||
self.make, self.model = self.name.split(' ', 1)
|
||||
self.make, self.model, self.years = split_name(self.name)
|
||||
self.row = {
|
||||
Column.MAKE: self.make,
|
||||
Column.MODEL: self.model,
|
||||
@@ -80,15 +91,13 @@ class CarInfo:
|
||||
Column.LONGITUDINAL: Star.FULL if CP.openpilotLongitudinalControl and not CP.radarOffCan else Star.EMPTY,
|
||||
Column.FSR_LONGITUDINAL: Star.FULL if min_enable_speed <= 0. else Star.EMPTY,
|
||||
Column.FSR_STEERING: Star.FULL if min_steer_speed <= 0. else Star.EMPTY,
|
||||
# Column.STEERING_TORQUE set below
|
||||
Column.STEERING_TORQUE: Star.EMPTY,
|
||||
}
|
||||
|
||||
# Set steering torque star from max lateral acceleration
|
||||
assert CP.maxLateralAccel > 0.1
|
||||
if CP.maxLateralAccel >= GOOD_TORQUE_THRESHOLD:
|
||||
self.row[Column.STEERING_TORQUE] = Star.FULL
|
||||
else:
|
||||
self.row[Column.STEERING_TORQUE] = Star.EMPTY
|
||||
|
||||
if CP.notCar:
|
||||
for col in StarColumns:
|
||||
@@ -105,7 +114,7 @@ class CarInfo:
|
||||
full_stars = [s for col, s in self.row.items() if col in TierColumns].count(Star.FULL)
|
||||
if full_stars == len(TierColumns):
|
||||
self.tier = Tier.GOLD
|
||||
elif full_stars == (len(TierColumns)-1):
|
||||
elif full_stars == len(TierColumns) - 1:
|
||||
self.tier = Tier.SILVER
|
||||
else:
|
||||
self.tier = Tier.BRONZE
|
||||
@@ -117,6 +126,8 @@ class CarInfo:
|
||||
item: Union[str, Star] = self.row[column]
|
||||
if column in StarColumns:
|
||||
item = star_icon.format(item.value)
|
||||
elif column == Column.MODEL and len(self.years):
|
||||
item += f" {self.years}"
|
||||
|
||||
footnote = get_footnote(self.footnotes, column)
|
||||
if footnote is not None:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from selfdrive.car.car_helpers import interfaces, get_interface_attr
|
||||
@@ -50,6 +51,11 @@ class TestCarDocs(unittest.TestCase):
|
||||
elif car.car_name in ("toyota", "hyundai"):
|
||||
self.assertNotEqual(car.row[Column.STEERING_TORQUE], Star.EMPTY, f"{car.name} has no torque star")
|
||||
|
||||
def test_year_format(self):
|
||||
for car in self.all_cars:
|
||||
with self.subTest(car=car):
|
||||
self.assertIsNone(re.search(r"\d{4}-\d{4}", car.name), f"Format years correctly: {car.name}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -119,12 +119,12 @@ CAR_INFO: Dict[str, Union[ToyotaCarInfo, List[ToyotaCarInfo]]] = {
|
||||
CAR.COROLLA: ToyotaCarInfo("Toyota Corolla 2017-19", footnotes=[Footnote.DSU]),
|
||||
CAR.COROLLA_TSS2: [
|
||||
ToyotaCarInfo("Toyota Corolla 2020-22", video_link="https://www.youtube.com/watch?v=_66pXk0CBYA"),
|
||||
ToyotaCarInfo("Toyota Corolla Cross 2020-21 (Non-US only)", min_enable_speed=7.5),
|
||||
ToyotaCarInfo("Toyota Corolla Cross (Non-US only) 2020-21", min_enable_speed=7.5),
|
||||
ToyotaCarInfo("Toyota Corolla Hatchback 2019-22", video_link="https://www.youtube.com/watch?v=_66pXk0CBYA"),
|
||||
],
|
||||
CAR.COROLLAH_TSS2: [
|
||||
ToyotaCarInfo("Toyota Corolla Hybrid 2020-22"),
|
||||
ToyotaCarInfo("Toyota Corolla Cross Hybrid 2020-22 (Non-US only)", min_enable_speed=7.5),
|
||||
ToyotaCarInfo("Toyota Corolla Cross Hybrid (Non-US only) 2020-22", min_enable_speed=7.5),
|
||||
ToyotaCarInfo("Lexus UX Hybrid 2019-22"),
|
||||
],
|
||||
CAR.HIGHLANDER: ToyotaCarInfo("Toyota Highlander 2017-19", video_link="https://www.youtube.com/watch?v=0wS0wXSLzoo", footnotes=[Footnote.DSU]),
|
||||
@@ -159,7 +159,7 @@ CAR_INFO: Dict[str, Union[ToyotaCarInfo, List[ToyotaCarInfo]]] = {
|
||||
CAR.LEXUS_NXH: ToyotaCarInfo("Lexus NX Hybrid 2018-19", footnotes=[Footnote.DSU]),
|
||||
CAR.LEXUS_NX_TSS2: ToyotaCarInfo("Lexus NX 2020-21"),
|
||||
CAR.LEXUS_NXH_TSS2: ToyotaCarInfo("Lexus NX Hybrid 2020-21"),
|
||||
CAR.LEXUS_RC: ToyotaCarInfo("Lexus RC 2017-2020"),
|
||||
CAR.LEXUS_RC: ToyotaCarInfo("Lexus RC 2017-20"),
|
||||
CAR.LEXUS_RX: ToyotaCarInfo("Lexus RX 2016-18", footnotes=[Footnote.DSU]),
|
||||
CAR.LEXUS_RXH: ToyotaCarInfo("Lexus RX Hybrid 2016-19", footnotes=[Footnote.DSU]),
|
||||
CAR.LEXUS_RX_TSS2: ToyotaCarInfo("Lexus RX 2020-22"),
|
||||
|
||||
Reference in New Issue
Block a user