2 Commits

Author SHA1 Message Date
IQ.Lvbs CI [bot]
b49032f0c3 IQ.Pilot Release Commit @ 5394182 2026-09-04 12:28:32 -05:00
IQ.Lvbs CI [bot]
bbd84a134f IQ.Pilot Release Commit @ 0b267b5 2026-09-03 11:24:15 -05:00
2 changed files with 28 additions and 9 deletions

View File

@@ -3,10 +3,16 @@
# 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
# Must stay at the OEM value. Tried at 300 (other BYD angle-mode ports ship the equivalent field at
# 200-300) to see whether it was an authority ceiling worth lowering: the car did not steer at all.
# Stock sends 500 in every one of 47625+ captured frames, idle and engaged alike, so the EPS treats
# any other value as no authority rather than as a softer limit.
ANGLE_RATE_LIMIT_UPPER = OEM_ANGLE_RATE_LIMIT
ANGLE_RATE_LIMIT_LOWER = -OEM_ANGLE_RATE_LIMIT
# 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,8 +88,17 @@ 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
# 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")
@@ -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")
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)