IQ.Pilot Release Commit @ 0b267b5

This commit is contained in:
IQ.Lvbs CI [bot]
2026-09-03 11:24:15 -05:00
parent e8748fd704
commit bbd84a134f
2 changed files with 30 additions and 9 deletions

View File

@@ -3,10 +3,18 @@
# Measured off the stock camera while it was actively steering (route 0000007b--88dd577c32):
# every engaged 0x1E2 carries +500/-500 and byte5 = 0x64. 251/-252/0xFF came from Atto 3 notes.
ANGLE_RATE_LIMIT_UPPER = 500
ANGLE_RATE_LIMIT_LOWER = -500
OEM_ANGLE_RATE_LIMIT = 500
SET_ME_FF_VALUE = 0x64
# This symmetric pair is the EPS authority ceiling, not a demand: the stock camera can hold it wide
# open because its own angle command never asks for much torque, but openpilot's does, and the EPS
# was measured saturating at +-470 against the +-500 ceiling while the wheel jittered. Other BYD
# angle-mode ports ship the equivalent field at 200-300. Lowered to 300 so the EPS runs out of
# authority before it can fight the driver or slam the wheel; raise back to OEM_ANGLE_RATE_LIMIT to
# restore byte-exact stock frames.
ANGLE_RATE_LIMIT_UPPER = 300
ANGLE_RATE_LIMIT_LOWER = -300
# 0x316 LKAS_STATE, in the order the stock camera walks them on an engage
LKAS_STATE_IDLE = 1
LKAS_STATE_SUSPENDED = 2

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import unittest
import unittest.mock
import numpy as np
@@ -87,9 +88,18 @@ class TestBydSteeringControl(unittest.TestCase):
self.assertEqual(vals["ANGLE_RATE_LIMIT_UPPER"], bydcan.ANGLE_RATE_LIMIT_UPPER)
self.assertEqual(vals["ANGLE_RATE_LIMIT_LOWER"], bydcan.ANGLE_RATE_LIMIT_LOWER)
def _oem_ceiling(self):
return unittest.mock.patch.multiple(
bydcan,
ANGLE_RATE_LIMIT_UPPER=bydcan.OEM_ANGLE_RATE_LIMIT,
ANGLE_RATE_LIMIT_LOWER=-bydcan.OEM_ANGLE_RATE_LIMIT,
)
def test_matches_stock_camera_idle_frame(self):
# stock idle: f4 31 c8 .. .. 64 (47625 samples); only the angle bytes differ
_, dat, _ = bydcan.create_steering_control(self.packer, 0.0, False)
# stock idle: f4 31 c8 .. .. 64 (47625 samples); only the angle bytes differ. Checked with the
# OEM ceiling so the frame stays provably stock-shaped independent of the shipped ceiling.
with self._oem_ceiling():
_, dat, _ = bydcan.create_steering_control(self.packer, 0.0, False)
self.assertEqual(bytes(dat[:3]), bytes.fromhex("f431c8"),
f"idle 0x1E2 diverges from stock: {bytes(dat[:3]).hex(' ')} != f4 31 c8")
self.assertEqual(dat[5], 0x64)
@@ -99,15 +109,18 @@ class TestBydSteeringControl(unittest.TestCase):
# dashcam mode (route 0000007b--88dd577c32): f4 31 e8 01 00 64 9f ee at +0.1 deg.
# Only COUNTER/CHECKSUM (byte 6 high nibble, byte 7) may differ.
OEM = bytes.fromhex("f431e8010064")
_, dat, _ = bydcan.create_steering_control(self.packer, 0.1, True)
with self._oem_ceiling():
_, dat, _ = bydcan.create_steering_control(self.packer, 0.1, True)
self.assertEqual(bytes(dat[:6]), OEM,
f"0x1E2 diverges from stock: {bytes(dat[:6]).hex(' ')} != {OEM.hex(' ')}")
self.assertEqual(dat[6] & 0x0F, 0x0F)
def test_rate_limits_and_set_me_match_stock(self):
# 251/-252/0xFF came from the Atto 3 notes; this car's camera sends 500/-500/0x64
self.assertEqual(bydcan.ANGLE_RATE_LIMIT_UPPER, 500)
self.assertEqual(bydcan.ANGLE_RATE_LIMIT_LOWER, -500)
def test_authority_ceiling_is_symmetric_and_within_stock(self):
# The ceiling caps how hard the EPS may push, so it must never exceed what stock authorises,
# and it must stay symmetric or the EPS gets more authority one way than the other.
self.assertEqual(bydcan.ANGLE_RATE_LIMIT_LOWER, -bydcan.ANGLE_RATE_LIMIT_UPPER)
self.assertLessEqual(bydcan.ANGLE_RATE_LIMIT_UPPER, bydcan.OEM_ANGLE_RATE_LIMIT)
self.assertGreater(bydcan.ANGLE_RATE_LIMIT_UPPER, 0)
self.assertEqual(bydcan.SET_ME_FF_VALUE, 0x64)
_, dat, _ = bydcan.create_steering_control(self.packer, 0.0, True)
self.assertEqual(_unpack(DBC_NAME, "STEERING_MODULE_ADAS", dat)["SET_ME_FF"], 0x64)