more car info -> car docs (#31885)

This commit is contained in:
Justin Newberry 2024-03-17 19:53:57 -04:00 committed by GitHub
parent 3e816e7df8
commit 0b92f4e9ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 69 additions and 69 deletions

View File

@ -340,7 +340,7 @@ jobs:
- uses: ./.github/workflows/setup-with-retry
- name: Get base car info
run: |
${{ env.RUN }} "scons -j$(nproc) && python selfdrive/debug/dump_car_info.py --path /tmp/openpilot_cache/base_car_info"
${{ env.RUN }} "scons -j$(nproc) && python selfdrive/debug/dump_car_docs.py --path /tmp/openpilot_cache/base_car_docs"
sudo chown -R $USER:$USER ${{ github.workspace }}
- uses: actions/checkout@v4
with:
@ -352,7 +352,7 @@ jobs:
run: |
cd current
${{ env.RUN }} "scons -j$(nproc)"
output=$(${{ env.RUN }} "python selfdrive/debug/print_docs_diff.py --path /tmp/openpilot_cache/base_car_info")
output=$(${{ env.RUN }} "python selfdrive/debug/print_docs_diff.py --path /tmp/openpilot_cache/base_car_docs")
output="${output//$'\n'/'%0A'}"
echo "::set-output name=diff::$output"
- name: Find comment

View File

@ -2,10 +2,10 @@
from collections import Counter
from pprint import pprint
from openpilot.selfdrive.car.docs import get_all_car_info
from openpilot.selfdrive.car.docs import get_all_car_docs
if __name__ == "__main__":
cars = get_all_car_info()
cars = get_all_car_docs()
make_count = Counter(l.make for l in cars)
print("\n", "*" * 20, len(cars), "total", "*" * 20, "\n")
pprint(make_count)

View File

@ -12,12 +12,12 @@
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
# {{all_car_info | length}} Supported Cars
# {{all_car_docs | length}} Supported Cars
|{{Column | map(attribute='value') | join('|') | replace(hardware_col_name, wide_hardware_col_name)}}|
|---|---|---|{% for _ in range((Column | length) - 3) %}{{':---:|'}}{% endfor +%}
{% for car_info in all_car_info %}
|{% for column in Column %}{{car_info.get_column(column, star_icon, video_icon, footnote_tag)}}|{% endfor %}
{% for car_docs in all_car_docs %}
|{% for column in Column %}{{car_docs.get_column(column, star_icon, video_icon, footnote_tag)}}|{% endfor %}
{% endfor %}

View File

@ -262,7 +262,7 @@ class CarSpecs:
@dataclass(order=True)
class PlatformConfig(Freezable):
platform_str: str
car_info: list[CarDocs]
car_docs: list[CarDocs]
specs: CarSpecs
dbc_dict: DbcDict

View File

@ -25,43 +25,43 @@ CARS_MD_OUT = os.path.join(BASEDIR, "docs", "CARS.md")
CARS_MD_TEMPLATE = os.path.join(BASEDIR, "selfdrive", "car", "CARS_template.md")
def get_all_car_info() -> list[CarDocs]:
all_car_info: list[CarDocs] = []
def get_all_car_docs() -> list[CarDocs]:
all_car_docs: list[CarDocs] = []
footnotes = get_all_footnotes()
for model, platform in PLATFORMS.items():
car_info = platform.config.car_info
car_docs = platform.config.car_docs
# If available, uses experimental longitudinal limits for the docs
CP = interfaces[model][0].get_params(platform, fingerprint=gen_empty_fingerprint(),
car_fw=[car.CarParams.CarFw(ecu="unknown")], experimental_long=True, docs=True)
if CP.dashcamOnly or not len(car_info):
if CP.dashcamOnly or not len(car_docs):
continue
# A platform can include multiple car models
for _car_info in car_info:
if not hasattr(_car_info, "row"):
_car_info.init_make(CP)
_car_info.init(CP, footnotes)
all_car_info.append(_car_info)
for _car_docs in car_docs:
if not hasattr(_car_docs, "row"):
_car_docs.init_make(CP)
_car_docs.init(CP, footnotes)
all_car_docs.append(_car_docs)
# Sort cars by make and model + year
sorted_cars: list[CarDocs] = natsorted(all_car_info, key=lambda car: car.name.lower())
sorted_cars: list[CarDocs] = natsorted(all_car_docs, key=lambda car: car.name.lower())
return sorted_cars
def group_by_make(all_car_info: list[CarDocs]) -> dict[str, list[CarDocs]]:
sorted_car_info = defaultdict(list)
for car_info in all_car_info:
sorted_car_info[car_info.make].append(car_info)
return dict(sorted_car_info)
def group_by_make(all_car_docs: list[CarDocs]) -> dict[str, list[CarDocs]]:
sorted_car_docs = defaultdict(list)
for car_docs in all_car_docs:
sorted_car_docs[car_docs.make].append(car_docs)
return dict(sorted_car_docs)
def generate_cars_md(all_car_info: list[CarDocs], template_fn: str) -> str:
def generate_cars_md(all_car_docs: list[CarDocs], template_fn: str) -> str:
with open(template_fn) as f:
template = jinja2.Template(f.read(), trim_blocks=True, lstrip_blocks=True)
footnotes = [fn.value.text for fn in get_all_footnotes()]
cars_md: str = template.render(all_car_info=all_car_info, PartType=PartType,
cars_md: str = template.render(all_car_docs=all_car_docs, PartType=PartType,
group_by_make=group_by_make, footnotes=footnotes,
Column=Column)
return cars_md
@ -76,5 +76,5 @@ if __name__ == "__main__":
args = parser.parse_args()
with open(args.out, 'w') as f:
f.write(generate_cars_md(get_all_car_info(), args.template))
f.write(generate_cars_md(get_all_car_docs(), args.template))
print(f"Generated and written to {args.out}")

View File

@ -77,13 +77,13 @@ class FordPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', RADAR.DELPHI_MRR))
def init(self):
for car_info in list(self.car_info):
if car_info.hybrid:
name = f"{car_info.make} {car_info.model} Hybrid {car_info.years}"
self.car_info.append(replace(copy.deepcopy(car_info), name=name))
if car_info.plug_in_hybrid:
name = f"{car_info.make} {car_info.model} Plug-in Hybrid {car_info.years}"
self.car_info.append(replace(copy.deepcopy(car_info), name=name))
for car_docs in list(self.car_docs):
if car_docs.hybrid:
name = f"{car_docs.make} {car_docs.model} Hybrid {car_docs.years}"
self.car_docs.append(replace(copy.deepcopy(car_docs), name=name))
if car_docs.plug_in_hybrid:
name = f"{car_docs.make} {car_docs.model} Plug-in Hybrid {car_docs.years}"
self.car_docs.append(replace(copy.deepcopy(car_docs), name=name))
@dataclass

View File

@ -50,7 +50,7 @@ class CAR(Platforms):
)
# Leaf with ADAS ECU found behind instrument cluster instead of glovebox
# Currently the only known difference between them is the inverted seatbelt signal.
LEAF_IC = LEAF.override(platform_str="NISSAN LEAF 2018 Instrument Cluster", car_info=[])
LEAF_IC = LEAF.override(platform_str="NISSAN LEAF 2018 Instrument Cluster", car_docs=[])
ROGUE = NissanPlaformConfig(
"NISSAN ROGUE 2019",
[NissanCarDocs("Nissan Rogue 2018-20")],

View File

@ -6,18 +6,18 @@ import unittest
from openpilot.common.basedir import BASEDIR
from openpilot.selfdrive.car.car_helpers import interfaces
from openpilot.selfdrive.car.docs import CARS_MD_OUT, CARS_MD_TEMPLATE, generate_cars_md, get_all_car_info
from openpilot.selfdrive.car.docs import CARS_MD_OUT, CARS_MD_TEMPLATE, generate_cars_md, get_all_car_docs
from openpilot.selfdrive.car.docs_definitions import Cable, Column, PartType, Star
from openpilot.selfdrive.car.honda.values import CAR as HONDA
from openpilot.selfdrive.car.values import PLATFORMS
from openpilot.selfdrive.debug.dump_car_info import dump_car_info
from openpilot.selfdrive.debug.print_docs_diff import print_car_info_diff
from openpilot.selfdrive.debug.dump_car_docs import dump_car_docs
from openpilot.selfdrive.debug.print_docs_diff import print_car_docs_diff
class TestCarDocs(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.all_cars = get_all_car_info()
cls.all_cars = get_all_car_docs()
def test_generator(self):
generated_cars_md = generate_cars_md(self.all_cars, CARS_MD_TEMPLATE)
@ -29,24 +29,24 @@ class TestCarDocs(unittest.TestCase):
def test_docs_diff(self):
dump_path = os.path.join(BASEDIR, "selfdrive", "car", "tests", "cars_dump")
dump_car_info(dump_path)
print_car_info_diff(dump_path)
dump_car_docs(dump_path)
print_car_docs_diff(dump_path)
os.remove(dump_path)
def test_duplicate_years(self):
make_model_years = defaultdict(list)
for car in self.all_cars:
with self.subTest(car_info_name=car.name):
with self.subTest(car_docs_name=car.name):
make_model = (car.make, car.model)
for year in car.year_list:
self.assertNotIn(year, make_model_years[make_model], f"{car.name}: Duplicate model year")
make_model_years[make_model].append(year)
def test_missing_car_info(self):
all_car_info_platforms = [name for name, config in PLATFORMS.items()]
def test_missing_car_docs(self):
all_car_docs_platforms = [name for name, config in PLATFORMS.items()]
for platform in sorted(interfaces.keys()):
with self.subTest(platform=platform):
self.assertTrue(platform in all_car_info_platforms, f"Platform: {platform} doesn't have a CarDocs entry")
self.assertTrue(platform in all_car_docs_platforms, f"Platform: {platform} doesn't have a CarDocs entry")
def test_naming_conventions(self):
# Asserts market-standard car naming conventions by brand

View File

@ -2,12 +2,12 @@
import argparse
import pickle
from openpilot.selfdrive.car.docs import get_all_car_info
from openpilot.selfdrive.car.docs import get_all_car_docs
def dump_car_info(path):
def dump_car_docs(path):
with open(path, 'wb') as f:
pickle.dump(get_all_car_info(), f)
pickle.dump(get_all_car_docs(), f)
print(f'Dumping car info to {path}')
@ -15,4 +15,4 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--path", required=True)
args = parser.parse_args()
dump_car_info(args.path)
dump_car_docs(args.path)

View File

@ -4,7 +4,7 @@ from collections import defaultdict
import difflib
import pickle
from openpilot.selfdrive.car.docs import get_all_car_info
from openpilot.selfdrive.car.docs import get_all_car_docs
from openpilot.selfdrive.car.docs_definitions import Column
FOOTNOTE_TAG = "<sup>{}</sup>"
@ -17,7 +17,7 @@ COLUMN_HEADER = "|---|---|---|{}|".format("|".join([":---:"] * (len(Column) - 3)
ARROW_SYMBOL = "➡️"
def load_base_car_info(path):
def load_base_car_docs(path):
with open(path, "rb") as f:
return pickle.load(f)
@ -57,31 +57,31 @@ def format_row(builder):
return "|" + "|".join(builder) + "|"
def print_car_info_diff(path):
base_car_info = defaultdict(list)
new_car_info = defaultdict(list)
def print_car_docs_diff(path):
base_car_docs = defaultdict(list)
new_car_docs = defaultdict(list)
for car in load_base_car_info(path):
base_car_info[car.car_fingerprint].append(car)
for car in get_all_car_info():
new_car_info[car.car_fingerprint].append(car)
for car in load_base_car_docs(path):
base_car_docs[car.car_fingerprint].append(car)
for car in get_all_car_docs():
new_car_docs[car.car_fingerprint].append(car)
# Add new platforms to base cars so we can detect additions and removals in one pass
base_car_info.update({car: [] for car in new_car_info if car not in base_car_info})
base_car_docs.update({car: [] for car in new_car_docs if car not in base_car_docs})
changes = defaultdict(list)
for base_car_model, base_cars in base_car_info.items():
for base_car_model, base_cars in base_car_docs.items():
# Match car info changes, and get additions and removals
new_cars = new_car_info[base_car_model]
new_cars = new_car_docs[base_car_model]
car_changes, car_additions, car_removals = match_cars(base_cars, new_cars)
# Removals
for car_info in car_removals:
changes["removals"].append(format_row([car_info.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) for column in Column]))
for car_docs in car_removals:
changes["removals"].append(format_row([car_docs.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) for column in Column]))
# Additions
for car_info in car_additions:
changes["additions"].append(format_row([car_info.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) for column in Column]))
for car_docs in car_additions:
changes["additions"].append(format_row([car_docs.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) for column in Column]))
for new_car, base_car in car_changes:
# Column changes
@ -117,4 +117,4 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--path", required=True)
args = parser.parse_args()
print_car_info_diff(args.path)
print_car_docs_diff(args.path)

View File

@ -146,10 +146,10 @@
],
"source": [
"def test_year_code(platform, year):\n",
" car_info = CAR(platform).config.car_info\n",
" if isinstance(car_info, list):\n",
" car_info = car_info[0]\n",
" years = [int(y) for y in car_info.year_list]\n",
" car_docs = CAR(platform).config.car_docs\n",
" if isinstance(car_docs, list):\n",
" car_docs = car_docs[0]\n",
" years = [int(y) for y in car_docs.year_list]\n",
" correct_year = year in years\n",
" print(f\"{correct_year=!s: <6} {platform=: <32} {year=: <5} {years=}\")\n",
"\n",