mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-06-28 01:52:06 +08:00
i6
This commit is contained in:
@@ -54,9 +54,8 @@ IONIQ_6_STOP_RELEASE_JERK_V = [3.6 * IONIQ_6_RESPONSE_MULTIPLIER,
|
||||
4.2 * IONIQ_6_RESPONSE_MULTIPLIER,
|
||||
4.8 * IONIQ_6_RESPONSE_MULTIPLIER]
|
||||
IONIQ_6_IPEDAL_PRESS_SEND_COUNT = 6
|
||||
IONIQ_6_IPEDAL_LATCH_PRESS_SEND_COUNT = 10
|
||||
IONIQ_6_IPEDAL_LATCH_PRESS_SEND_COUNT = 6
|
||||
IONIQ_6_IPEDAL_PADDLE_BURST_COUNT = 3
|
||||
IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT = 1
|
||||
IONIQ_6_MAX_REGEN_STATE = 0x3C
|
||||
IONIQ_6_MAX_REGEN_STATE_2 = 0x01
|
||||
IONIQ_6_IPEDAL_REGEN_STATE = 0x50
|
||||
@@ -246,6 +245,7 @@ class CarController(CarControllerBase):
|
||||
self._ioniq_6_last_buttons_counter = 0
|
||||
self._ioniq_6_last_regen_control_counter = -1
|
||||
self._ioniq_6_regen_request_sent = False
|
||||
self._ioniq_6_ipedal_latch_counter = -1
|
||||
self._ioniq_6_last_gear = structs.CarState.GearShifter.unknown
|
||||
self._genesis_g90_long_tuning = GenesisG90LongitudinalTuningState()
|
||||
|
||||
@@ -254,12 +254,14 @@ class CarController(CarControllerBase):
|
||||
self._ioniq_6_always_ipedal_press_remaining = 0
|
||||
self._ioniq_6_always_ipedal_retry_frame = 0
|
||||
self._ioniq_6_regen_request_sent = False
|
||||
self._ioniq_6_ipedal_latch_counter = -1
|
||||
|
||||
def _arm_ioniq_6_always_ipedal(self) -> None:
|
||||
self._ioniq_6_always_ipedal_pending = True
|
||||
self._ioniq_6_always_ipedal_press_remaining = 0
|
||||
self._ioniq_6_always_ipedal_retry_frame = self.frame
|
||||
self._ioniq_6_regen_request_sent = False
|
||||
self._ioniq_6_ipedal_latch_counter = -1
|
||||
|
||||
def _update_ioniq_6_always_ipedal(self, CC, CS, starpilot_toggles):
|
||||
can_sends = []
|
||||
@@ -286,6 +288,12 @@ class CarController(CarControllerBase):
|
||||
regen_control_counter_changed = regen_control_counter != self._ioniq_6_last_regen_control_counter
|
||||
max_regen_state = regen_state == IONIQ_6_MAX_REGEN_STATE and regen_state_2 == IONIQ_6_MAX_REGEN_STATE_2
|
||||
ipedal_latch_pending = regen_state == IONIQ_6_IPEDAL_REGEN_STATE and regen_state_2 == IONIQ_6_IPEDAL_REGEN_STATE_2_PENDING
|
||||
was_max_regen_state = self._ioniq_6_last_ipedal_regen_state == IONIQ_6_MAX_REGEN_STATE and \
|
||||
self._ioniq_6_last_ipedal_regen_state_2 == IONIQ_6_MAX_REGEN_STATE_2
|
||||
was_ipedal_latch_pending = self._ioniq_6_last_ipedal_regen_state == IONIQ_6_IPEDAL_REGEN_STATE and \
|
||||
self._ioniq_6_last_ipedal_regen_state_2 == IONIQ_6_IPEDAL_REGEN_STATE_2_PENDING
|
||||
entered_latch_stage = (max_regen_state and not was_max_regen_state) or \
|
||||
(ipedal_latch_pending and not was_ipedal_latch_pending)
|
||||
drive = gear == structs.CarState.GearShifter.drive
|
||||
park = gear == structs.CarState.GearShifter.park
|
||||
drive_edge = drive and self._ioniq_6_last_gear != structs.CarState.GearShifter.drive
|
||||
@@ -306,29 +314,46 @@ class CarController(CarControllerBase):
|
||||
self._ioniq_6_always_ipedal_pending = False
|
||||
self._ioniq_6_always_ipedal_press_remaining = 0
|
||||
|
||||
if entered_latch_stage:
|
||||
self._ioniq_6_always_ipedal_press_remaining = 0
|
||||
self._ioniq_6_always_ipedal_retry_frame = self.frame
|
||||
self._ioniq_6_regen_request_sent = False
|
||||
self._ioniq_6_ipedal_latch_counter = -1
|
||||
|
||||
if target_gear and self._ioniq_6_always_ipedal_pending and not CS.ipedal_active and not CC.enabled:
|
||||
if self._ioniq_6_always_ipedal_press_remaining == 0 and self.frame >= self._ioniq_6_always_ipedal_retry_frame:
|
||||
self._ioniq_6_always_ipedal_press_remaining = IONIQ_6_IPEDAL_LATCH_PRESS_SEND_COUNT if (max_regen_state or ipedal_latch_pending) \
|
||||
else IONIQ_6_IPEDAL_PRESS_SEND_COUNT
|
||||
self._ioniq_6_regen_request_sent = False
|
||||
|
||||
# Mirror the current stock counter after seeing the real CRUISE_BUTTONS frame land on the bus.
|
||||
# A single duplicate was enough to move the cluster-facing state, but not enough to reliably beat
|
||||
# the stock no-paddle frame for the actual drivetrain latch path.
|
||||
if self._ioniq_6_always_ipedal_press_remaining > 0 and buttons_counter_changed and \
|
||||
0 <= buttons_counter < hyundaicanfd.IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX:
|
||||
paddle_msg = hyundaicanfd.create_ioniq_6_paddle_buttons(self.packer, self.CP, self.CAN,
|
||||
buttons_counter, left_paddle=True)
|
||||
can_sends.extend([paddle_msg] * IONIQ_6_IPEDAL_PADDLE_BURST_COUNT)
|
||||
if max_regen_state or ipedal_latch_pending:
|
||||
next_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(buttons_counter)
|
||||
next_paddle_msg = hyundaicanfd.create_ioniq_6_paddle_buttons(self.packer, self.CP, self.CAN,
|
||||
next_counter, left_paddle=True)
|
||||
can_sends.extend([next_paddle_msg] * IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT)
|
||||
self._ioniq_6_always_ipedal_press_remaining -= 1
|
||||
self._ioniq_6_ipedal_latch_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(buttons_counter) \
|
||||
if 0 <= buttons_counter < hyundaicanfd.IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX else -1
|
||||
else:
|
||||
self._ioniq_6_ipedal_latch_counter = -1
|
||||
|
||||
if self._ioniq_6_always_ipedal_press_remaining > 0:
|
||||
if max_regen_state or ipedal_latch_pending:
|
||||
if self._ioniq_6_ipedal_latch_counter < 0 and 0 <= buttons_counter < hyundaicanfd.IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX:
|
||||
self._ioniq_6_ipedal_latch_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(buttons_counter)
|
||||
|
||||
if 0 <= self._ioniq_6_ipedal_latch_counter < hyundaicanfd.IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX:
|
||||
# A real successful i-Pedal pull is a short held press followed by release, not a continuous hold.
|
||||
# Mirror that with a stock-like six-counter sequence, then stop transmitting to give the car a release window.
|
||||
paddle_msg = hyundaicanfd.create_ioniq_6_paddle_buttons(self.packer, self.CP, self.CAN,
|
||||
self._ioniq_6_ipedal_latch_counter, left_paddle=True)
|
||||
can_sends.append(paddle_msg)
|
||||
self._ioniq_6_ipedal_latch_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(self._ioniq_6_ipedal_latch_counter)
|
||||
self._ioniq_6_always_ipedal_press_remaining -= 1
|
||||
elif buttons_counter_changed and 0 <= buttons_counter < hyundaicanfd.IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX:
|
||||
paddle_msg = hyundaicanfd.create_ioniq_6_paddle_buttons(self.packer, self.CP, self.CAN,
|
||||
buttons_counter, left_paddle=True)
|
||||
can_sends.extend([paddle_msg] * IONIQ_6_IPEDAL_PADDLE_BURST_COUNT)
|
||||
self._ioniq_6_always_ipedal_press_remaining -= 1
|
||||
|
||||
if self._ioniq_6_always_ipedal_press_remaining == 0:
|
||||
retry_wait_frames = IONIQ_6_IPEDAL_PROGRESS_RETRY_WAIT_FRAMES if regen_state_changed else IONIQ_6_IPEDAL_RETRY_WAIT_FRAMES
|
||||
self._ioniq_6_always_ipedal_retry_frame = self.frame + retry_wait_frames
|
||||
self._ioniq_6_ipedal_latch_counter = -1
|
||||
|
||||
# The drivetrain latch uses a second HKG CAN-FD request path in addition to the left paddle bit.
|
||||
# Mirror the next stock 0x25A frame once per retry burst instead of spamming it continuously.
|
||||
|
||||
@@ -8,7 +8,7 @@ from opendbc.car import Bus, ButtonType, gen_empty_fingerprint, structs
|
||||
from opendbc.car.structs import CarControl, CarParams
|
||||
from opendbc.car.fw_versions import build_fw_dict, match_fw_to_car
|
||||
from opendbc.car.hyundai.carcontroller import CarController, Ioniq6LongitudinalTuningState, GenesisG90LongitudinalTuningState, \
|
||||
IONIQ_6_IPEDAL_PADDLE_BURST_COUNT, IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT, \
|
||||
IONIQ_6_IPEDAL_PADDLE_BURST_COUNT, \
|
||||
update_ioniq_6_longitudinal_tuning, \
|
||||
update_genesis_g90_longitudinal_tuning
|
||||
from opendbc.car.hyundai.carstate import CarState, decode_ioniq_6_blindspot_radar_state, decode_ioniq_6_ipedal_intermediate_state, \
|
||||
@@ -484,7 +484,8 @@ class TestHyundaiFingerprint:
|
||||
sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles)
|
||||
|
||||
assert sends
|
||||
assert controller._ioniq_6_always_ipedal_press_remaining == 9
|
||||
assert [msg[1].hex() for msg in sends if msg[0] == 0x1CF] == ["9060002800000000"]
|
||||
assert controller._ioniq_6_always_ipedal_press_remaining == 5
|
||||
|
||||
def test_ioniq_6_always_ipedal_sends_regen_control_companion_once_max_regen_is_shown(self):
|
||||
toggles = get_test_toggles()
|
||||
@@ -550,13 +551,12 @@ class TestHyundaiFingerprint:
|
||||
sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles)
|
||||
|
||||
paddle_msgs = [msg for msg in sends if msg[0] == 0x1CF]
|
||||
assert len(paddle_msgs) == IONIQ_6_IPEDAL_PADDLE_BURST_COUNT + IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT
|
||||
assert [msg[1].hex() for msg in paddle_msgs[:IONIQ_6_IPEDAL_PADDLE_BURST_COUNT]] == ["4650002800000000"] * IONIQ_6_IPEDAL_PADDLE_BURST_COUNT
|
||||
assert [msg[1].hex() for msg in paddle_msgs[IONIQ_6_IPEDAL_PADDLE_BURST_COUNT:]] == ["9060002800000000"] * IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT
|
||||
assert [msg[1].hex() for msg in paddle_msgs] == ["9060002800000000"]
|
||||
regen_cmd = next(msg for msg in sends if msg[0] == 0x25A)
|
||||
assert regen_cmd[1][24:28] == bytes.fromhex("c00c1200")
|
||||
checksum = hyundaicanfd.hkg_can_fd_checksum(regen_cmd[0], None, bytearray(regen_cmd[1]))
|
||||
assert regen_cmd[1][0] | (regen_cmd[1][1] << 8) == checksum
|
||||
assert controller._ioniq_6_always_ipedal_press_remaining == 5
|
||||
|
||||
controller.frame = 1
|
||||
cs.buttons_counter = 6
|
||||
@@ -564,9 +564,7 @@ class TestHyundaiFingerprint:
|
||||
sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles)
|
||||
|
||||
paddle_msgs = [msg for msg in sends if msg[0] == 0x1CF]
|
||||
assert len(paddle_msgs) == IONIQ_6_IPEDAL_PADDLE_BURST_COUNT + IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT
|
||||
assert [msg[1].hex() for msg in paddle_msgs[:IONIQ_6_IPEDAL_PADDLE_BURST_COUNT]] == ["9060002800000000"] * IONIQ_6_IPEDAL_PADDLE_BURST_COUNT
|
||||
assert [msg[1].hex() for msg in paddle_msgs[IONIQ_6_IPEDAL_PADDLE_BURST_COUNT:]] == ["2970002800000000"] * IONIQ_6_IPEDAL_NEXT_COUNTER_BURST_COUNT
|
||||
assert [msg[1].hex() for msg in paddle_msgs] == ["2970002800000000"]
|
||||
assert not any(msg[0] == 0x25A for msg in sends)
|
||||
|
||||
def test_ioniq_6_longitudinal_params_match_canfd_tune(self):
|
||||
|
||||
@@ -284,18 +284,18 @@ IONIQ_6_TRANSITION_SPEED = 10.0
|
||||
IONIQ_6_PHASE_SCALE = 0.10
|
||||
IONIQ_6_TURN_IN_BOOST_LEFT = 1.58
|
||||
IONIQ_6_TURN_IN_BOOST_RIGHT = 1.82
|
||||
IONIQ_6_UNWIND_TAPER_LEFT = 2.84
|
||||
IONIQ_6_UNWIND_TAPER_LEFT = 3.05
|
||||
IONIQ_6_UNWIND_TAPER_RIGHT = 6.35
|
||||
IONIQ_6_FRICTION_MULT = 0.928
|
||||
IONIQ_6_FRICTION_LAT_RISE = 0.20
|
||||
IONIQ_6_FRICTION_JERK_RISE = 0.24
|
||||
IONIQ_6_TURN_IN_THRESHOLD_REDUCTION_LEFT = 0.74
|
||||
IONIQ_6_TURN_IN_THRESHOLD_REDUCTION_RIGHT = 1.18
|
||||
IONIQ_6_UNWIND_THRESHOLD_INCREASE_LEFT = 3.35
|
||||
IONIQ_6_UNWIND_THRESHOLD_INCREASE_LEFT = 3.70
|
||||
IONIQ_6_UNWIND_THRESHOLD_INCREASE_RIGHT = 7.85
|
||||
IONIQ_6_TURN_IN_FRICTION_BOOST_LEFT = 0.40
|
||||
IONIQ_6_TURN_IN_FRICTION_BOOST_RIGHT = 0.72
|
||||
IONIQ_6_UNWIND_FRICTION_REDUCTION_LEFT = 3.10
|
||||
IONIQ_6_UNWIND_FRICTION_REDUCTION_LEFT = 3.35
|
||||
IONIQ_6_UNWIND_FRICTION_REDUCTION_RIGHT = 7.30
|
||||
IONIQ_6_CENTER_TAPER_MAX = 0.082
|
||||
IONIQ_6_CENTER_TAPER_LAT = 0.24
|
||||
@@ -311,9 +311,9 @@ IONIQ_6_LOW_MID_CENTER_TAPER_SPEED_WIDTH = 1.5
|
||||
IONIQ_6_DIRECTIONAL_TAPER_LAT_START = 0.19
|
||||
IONIQ_6_DIRECTIONAL_TAPER_LAT_END = 0.90
|
||||
IONIQ_6_DIRECTIONAL_TAPER_LAT_WIDTH = 0.06
|
||||
IONIQ_6_DIRECTIONAL_TAPER_BASE_LEFT = 0.14
|
||||
IONIQ_6_DIRECTIONAL_TAPER_BASE_RIGHT = 0.48
|
||||
IONIQ_6_DIRECTIONAL_TAPER_UNWIND_LEFT = 1.64
|
||||
IONIQ_6_DIRECTIONAL_TAPER_BASE_LEFT = 0.13
|
||||
IONIQ_6_DIRECTIONAL_TAPER_BASE_RIGHT = 0.45
|
||||
IONIQ_6_DIRECTIONAL_TAPER_UNWIND_LEFT = 1.82
|
||||
IONIQ_6_DIRECTIONAL_TAPER_UNWIND_RIGHT = 3.28
|
||||
IONIQ_6_DIRECTIONAL_TAPER_FLOOR_LEFT = 0.48
|
||||
IONIQ_6_DIRECTIONAL_TAPER_FLOOR_RIGHT = 0.52
|
||||
@@ -325,7 +325,7 @@ IONIQ_6_HEAVY_DIRECTIONAL_TAPER_LAT_START = 0.82
|
||||
IONIQ_6_HEAVY_DIRECTIONAL_TAPER_LAT_WIDTH = 0.12
|
||||
IONIQ_6_HEAVY_DIRECTIONAL_TAPER_BASE_LEFT = 0.10
|
||||
IONIQ_6_HEAVY_DIRECTIONAL_TAPER_BASE_RIGHT = 0.17
|
||||
IONIQ_6_HEAVY_DIRECTIONAL_TAPER_UNWIND_LEFT = 0.56
|
||||
IONIQ_6_HEAVY_DIRECTIONAL_TAPER_UNWIND_LEFT = 0.62
|
||||
IONIQ_6_HEAVY_DIRECTIONAL_TAPER_UNWIND_RIGHT = 0.94
|
||||
IONIQ_6_OUTPUT_TAPER_SPEED = 8.5
|
||||
IONIQ_6_OUTPUT_TAPER_SPEED_WIDTH = 2.5
|
||||
|
||||
Reference in New Issue
Block a user