Creating an OpenPilot Car Port for Hyundai Elantra Hybrid 2021

3 minute read

I got a Comma Two sometime late 2020, during one of their rare sales. Even though I didn’t have a car with LKAS or SCC at the time, knowing that the price of COTS devices that can provide self driving can only go up with time I had to get in on the deal.

It wasn’t up until now, during openpilot 0.8.6 development cycle, when I got a supported car. 👌

OpenPilot

I heard during one of geohot’s live stream that Hyundai Hybrid cars aren’t quite supported yet, mainly because the gas signal differed a bit from Hyundai’s gas car variants. What that means?–I was going to attempt to find out, but someone already figured it out, saving me quite some time!

A DIY Connector

The only thing left was fingerprinting the car and then driving! And surprisingly, it was really that easy. Except for the connector that I needed to replace the LKAS camera.

The connector was keyed a bit differently from the harness I bought from Comma. However, judging from the connector guide from the OpenPilot wiki, the wiring hasn’t changed, so all I needed to do was shave down some plastic on the harness’s Male plug.

Once I plugged it in, the Comma Two powered on, didn’t recognize the device, and I was ready to go.

Fingerprinting (2.0)

OpenPilot’s codebase really is something else: easy to comprehend and minimal bloat. Their Wiki guide is fairly straight-forward:

  1. drive around in dashcam mode
  2. upload the results
  3. go to my.comma.ai useradmin site
  4. extract the firmware, and Copy & Paste it into selfdive/car/<car_make>/values.py
  5. “Rebuild” the codebase on-device and see if the car gets recognized

After some snooping around the car’s upload logs and toggling the Enable Community Features on the device I was good to go!

Adding this small snippet of code into OpenPilot’s openpilot/selfdrive/car/hyundai/values.py is all it needed to get it to work.

 1CAR.ELANTRA_HEV_2021: {
 2   (Ecu.fwdCamera, 0x7c4, None) : [
 3      b'\xf1\000CN7HMFC  AT USA LHD 1.00 1.03 99210-AA000 200819'
 4   ],
 5   (Ecu.fwdRadar, 0x7d0, None) : [
 6     b'\xf1\000CNhe SCC FHCUP      1.00 1.01 99110-BY000         '
 7   ],
 8   (Ecu.eps, 0x7d4, None) :[
 9     b'\xf1\x8756310/BY050\xf1\000CN7 MDPS C 1.00 1.02 56310/BY050 4CNHC102\xf1\xa01.02'
10   ],
11   (Ecu.transmission, 0x7e1, None) :[
12     b'\xf1\x816U3K3051\000\000\xf1\0006U3L0_C2\000\0006U3K3051\000\000HCN0G16NS0\xb9?A\xaa'
13   ],
14   (Ecu.engine, 0x7e0, None) : [
15     b'\xf1\x816H6G5051\000\000\000\000\000\000\000\000'
16   ]
17}

This, and mirroring the similar parameters of other Hyundai cars.

In values.py:

 1...
 2ELANTRA_HEV_2021 = "HYUNDAI ELANTRA HYBRID 2021"
 3...
 4HYBRID_CAR = set([CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.KIA_NIRO_HEV, CAR.KIA_NIRO_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV])  # these cars use a different gas signal
 5...
 6  "use_fca": set([CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.ELANTRA_GT_I30, CAR.KIA_STINGER, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021]),
 7...
 8  "use_elect_gears": set([CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021,CAR.SONATA_HYBRID, CAR.KONA_HEV]),
 9
10...
11CAR.ELANTRA_HEV_2021: dbc_dict('hyundai_kia_generic', None),

In interface.py

 1...
 2    elif candidate == CAR.ELANTRA_HEV_2021:
 3      ret.lateralTuning.pid.kf = 0.00005
 4      ret.mass = (3017. * CV.LB_TO_KG) + STD_CARGO_KG
 5      ret.wheelbase = 2.72
 6      ret.steerRatio = 12.9
 7      tire_stiffness_factor = 0.65
 8      ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
 9      ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
10...

Results

I submited a PR to be upstream for other Elantra Hybrid 2021 owners to try out, and it was quickly merged and acccepted. The people at comma.ai work fast.

The near out-of-the-box experience is something else–absolutely blows the stock system out of the water. Unfortunately all Hyundais currently use latitudinal-only control (left-right); the longitudinal control said to come soon, so the experience I’m having is only a small part of what OpenPilot is capable of.

Definitely looking forward to using this day-to-day. 😄


EDIT (9/30/2021): Sometimes I would get CAR UNRECOGNIZED even if I’ve already added the fingerprints into values.py. The solution is to see what fingerprint I may have missed that the Comma 2 detected. Viewing the https://useradmin.comma.ai/ database (under device > route_name > segment 0 > log > carParams) shows that the Comma 2 detected a different Transmission fingerprint.

Add in the new fingerprint with the detected one and solves the issue. ✅

 1  CAR.ELANTRA_HEV_2021: {
 2    (Ecu.fwdCamera, 0x7c4, None) : [
 3      b'\xf1\000CN7HMFC  AT USA LHD 1.00 1.03 99210-AA000 200819'
 4    ],
 5    (Ecu.fwdRadar, 0x7d0, None) : [
 6      b'\xf1\000CNhe SCC FHCUP      1.00 1.01 99110-BY000         '
 7    ],
 8    (Ecu.eps, 0x7d4, None) :[
 9      b'\xf1\x8756310/BY050\xf1\000CN7 MDPS C 1.00 1.02 56310/BY050 4CNHC102'
10    ],
11    (Ecu.transmission, 0x7e1, None) :[
12      b'\xf1\0006U3L0_C2\000\0006U3K3051\000\000HCN0G16NS0\xb9?A\xaa',
13      b'\xf1\0006U3L0_C2\000\0006U3K3051\000\000HCN0G16NS0\000\000\000\000',
14      b'\xf1\x816U3K3051\000\000\xf1\0006U3L0_C2\000\0006U3K3051\000\000HCN0G16NS0\xb9?A\xaa',
15      b'\xf1\x816U3K3051\000\000\xf1\0006U3L0_C2\000\0006U3K3051\000\000HCN0G16NS0\000\000\000\000'
16    ],
17    (Ecu.engine, 0x7e0, None) : [
18      b'\xf1\x816H6G5051\000\000\000\000\000\000\000\000'
19    ]
20  },