diff --git a/selfdrive/car/ford/tests/ford_fuzzy_fingerprint.ipynb b/selfdrive/car/ford/tests/ford_fuzzy_fingerprint.ipynb new file mode 100644 index 0000000000..4ef7a752da --- /dev/null +++ b/selfdrive/car/ford/tests/ford_fuzzy_fingerprint.ipynb @@ -0,0 +1,378 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "kj/filesystem-disk-unix.c++:1703: warning: PWD environment variable doesn't match current directory; pwd = /mnt/c/Users/camer/AppData/Local/Programs/Microsoft VS Code\n" + ] + } + ], + "source": [ + "from openpilot.tools.lib.comma_car_segments import get_comma_car_segments_database\n", + "from openpilot.selfdrive.car.ford.values import CAR\n", + "\n", + "database = get_comma_car_segments_database()\n", + "\n", + "platforms = [c.value for c in CAR]" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9ddb0675cd4a4f46a23b608252324ed4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/261 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sourceexpectedfuzzycorrect
0fwFORD BRONCO SPORT 1ST GENFORD BRONCO SPORT 1ST GENTrue
1fwFORD ESCAPE 4TH GENFORD ESCAPE 4TH GENTrue
5fixedFORD EXPLORER 6TH GENFORD EXPLORER 6TH GENTrue
8fwFORD EXPLORER 6TH GENFORD EXPLORER 6TH GENTrue
11fwFORD MAVERICK 1ST GENFORD MAVERICK 1ST GENTrue
12fwFORD MAVERICK 1ST GENmockFalse
17fwFORD FOCUS 4TH GENFORD FOCUS 4TH GENTrue
103fixedFORD MAVERICK 1ST GENFORD MAVERICK 1ST GENTrue
119fwFORD F-150 LIGHTNING 1ST GENFORD F-150 LIGHTNING 1ST GENTrue
149fwFORD MUSTANG MACH-E 1ST GENFORD MUSTANG MACH-E 1ST GENTrue
\n", + "" + ], + "text/plain": [ + " source expected fuzzy \\\n", + "0 fw FORD BRONCO SPORT 1ST GEN FORD BRONCO SPORT 1ST GEN \n", + "1 fw FORD ESCAPE 4TH GEN FORD ESCAPE 4TH GEN \n", + "5 fixed FORD EXPLORER 6TH GEN FORD EXPLORER 6TH GEN \n", + "8 fw FORD EXPLORER 6TH GEN FORD EXPLORER 6TH GEN \n", + "11 fw FORD MAVERICK 1ST GEN FORD MAVERICK 1ST GEN \n", + "12 fw FORD MAVERICK 1ST GEN mock \n", + "17 fw FORD FOCUS 4TH GEN FORD FOCUS 4TH GEN \n", + "103 fixed FORD MAVERICK 1ST GEN FORD MAVERICK 1ST GEN \n", + "119 fw FORD F-150 LIGHTNING 1ST GEN FORD F-150 LIGHTNING 1ST GEN \n", + "149 fw FORD MUSTANG MACH-E 1ST GEN FORD MUSTANG MACH-E 1ST GEN \n", + "\n", + " correct \n", + "0 True \n", + "1 True \n", + "5 True \n", + "8 True \n", + "11 True \n", + "12 False \n", + "17 True \n", + "103 True \n", + "119 True \n", + "149 True " + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "from openpilot.selfdrive.car.fw_versions import build_fw_dict\n", + "from openpilot.selfdrive.car.ford.fingerprints import FW_VERSIONS\n", + "from openpilot.selfdrive.car.ford.values import match_fw_to_car_fuzzy\n", + "\n", + "rows = []\n", + "success, count = 0, 0\n", + "for vin, car_fw, expected_platform, fuzzy, source in FW_TO_CHECK:\n", + " car_fw = list(filter(lambda fw: fw.brand == \"ford\" and not fw.logging, car_fw))\n", + " if len(car_fw) == 0:\n", + " print(f\"Skipping vin: {vin} platform: {expected_platform}, no car fw\")\n", + " continue\n", + "\n", + " fuzzy_fingerprint = match_fw_to_car_fuzzy(build_fw_dict(car_fw), FW_VERSIONS)\n", + " if len(fuzzy_fingerprint) == 0:\n", + " fuzzy_fingerprint = \"mock\"\n", + " elif len(fuzzy_fingerprint) > 1:\n", + " fuzzy_fingerprint = \"multiple\"\n", + " else:\n", + " fuzzy_fingerprint = list(fuzzy_fingerprint)[0]\n", + "\n", + " correct = fuzzy_fingerprint == expected_platform\n", + " rows.append((source, expected_platform, fuzzy_fingerprint, correct))\n", + " if not correct:\n", + " print(f\"vin: {vin} expected: {expected_platform: <30} fuzzy: {fuzzy_fingerprint: <30} correct: {correct}\")\n", + " print(f\" source: {source}\")\n", + " print(f\" fuzzy: {fuzzy}\")\n", + " print(\" car_fw:\")\n", + " fws = set()\n", + " for fw in car_fw:\n", + " fw_version = fw.fwVersion.rstrip(b\"\\0\")\n", + " fws.add(f\"{fw.ecu} {fw_version}\")\n", + " for fw in sorted(fws):\n", + " print(f\" {fw}\")\n", + " success += correct\n", + " count += 1\n", + "\n", + "print(f\"Success rate: {success / count * 100:.2f}%\")\n", + "\n", + "pd.set_option(\"display.max_rows\", None)\n", + "\n", + "df = pd.DataFrame(rows, columns=[\"source\", \"expected\", \"fuzzy\", \"correct\"]).drop_duplicates()\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}