tools/car_porting/examples/ford_vin_fingerprint.ipynb
"""In this example, we use the public comma car segments database to check if vin fingerprinting is feasible for ford."""
from openpilot.tools.lib.logreader import LogReader, comma_car_segments_source
from openpilot.tools.lib.comma_car_segments import get_comma_car_segments_database
from opendbc.car.ford.values import CAR
database = get_comma_car_segments_database()
platforms = [c.value for c in CAR]
print(f"Got {len(platforms)} Ford cars from opendbc")
# Adapted from https://github.com/commaai/openpilot/issues/31052#issuecomment-1902690083
MODEL_YEAR_CODES = {'M': 2021, 'N': 2022, 'P': 2023, 'R': 2024, 'S': 2025}
F150_CODES = ['F1C', 'F1E', 'W1C', 'W1E', 'X1C', 'X1E', 'W1R', 'W1P', 'W1S', 'W1T']
LIGHTNING_CODES = ['L', 'V']
MACHE_CODES = ['K1R', 'K1S', 'K2S', 'K3R', 'K3S', 'K4S']
FORD_VIN_START = ['1FT', '3FM', '5LM']
def ford_vin_fingerprint(vin): # Check if it's a Ford vehicle and determine the model
vin_positions_567 = vin[4:7]
if vin.startswith('1FT'):
if vin_positions_567 in F150_CODES:
if vin[7] in LIGHTNING_CODES:
return f"FORD F-150 LIGHTNING 1ST GEN"
else:
return f"FORD F-150 14TH GEN"
elif vin.startswith('3FM'):
if vin_positions_567 in MACHE_CODES:
return f"FORD MUSTANG MACH-E 1ST GEN"
elif vin.startswith('5LM'):
pass
return "mock"
import random
MAX_SEGS_PER_PLATFORM = 5
VINS_TO_CHECK = set()
print("Collecting segments from commaCarSegments dataset:")
for platform in platforms:
if platform not in database:
print(f"Skipping platform: {platform}, no data available")
continue
all_segments = database[platform]
NUM_SEGMENTS = min(len(all_segments), MAX_SEGS_PER_PLATFORM)
print(f"Got {len(all_segments)} segments for platform {platform}, sampling {NUM_SEGMENTS} segments")
segments = random.sample(all_segments, NUM_SEGMENTS)
for segment in segments:
lr = LogReader(segment, sources=[comma_car_segments_source])
CP = lr.first("carParams")
if "FORD" not in CP.carFingerprint:
print(segment, CP.carFingerprint)
VINS_TO_CHECK.add((CP.carVin, CP.carFingerprint))
print("Segment collection finished")
for vin, real_fingerprint in VINS_TO_CHECK:
determined_fingerprint = ford_vin_fingerprint(vin)
print(f"vin: {vin} real platform: {real_fingerprint: <30} determined platform: {determined_fingerprint: <30} correct: {real_fingerprint == determined_fingerprint}")