mirror of
https://github.com/MoreTore/openpilot.git
synced 2026-07-26 12:22:04 +08:00
teslurrrr
This commit is contained in:
@@ -131,6 +131,13 @@ struct OnroadEvent @0xc4fa6047f024e718 {
|
||||
excessiveActuation @96;
|
||||
audioFeedback @97;
|
||||
lateralManeuver @98;
|
||||
pedalCruiseEnabled @99;
|
||||
pedalCruiseDisabled @100;
|
||||
pedalMaxRegen @101;
|
||||
teslaCCEngaged @102;
|
||||
teslaCCDisengaged @103;
|
||||
teslaCCNotArmed @104;
|
||||
pedalNotCalibrated @105;
|
||||
|
||||
soundsUnavailableDEPRECATED @47;
|
||||
}
|
||||
|
||||
@@ -205,6 +205,11 @@ struct CarState {
|
||||
vehicleSensorsInvalid @52 :Bool; # invalid steering angle readings, etc.
|
||||
lowSpeedAlert @56 :Bool; # lost steering control due to a dynamic min steering speed
|
||||
blockPcmEnable @60 :Bool; # whether to allow PCM to enable this frame
|
||||
pedalMaxRegen @61 :Bool; # pedal at max regen, driver should use brake for more decel
|
||||
pedalLongActive @62 :Bool; # Pre-AP pedal longitudinal mode is active (enableLongControl)
|
||||
teslaCCEngaged @63 :Bool; # rising edge of stock Tesla CC engaging (no-pedal mode)
|
||||
teslaCCDisengaged @64 :Bool; # falling edge of stock Tesla CC
|
||||
teslaCCNotArmed @65 :Bool; # lateral engaged but DI_cruiseState != STANDBY/ENABLED
|
||||
|
||||
# cruise state
|
||||
cruiseState @10 :CruiseState;
|
||||
|
||||
@@ -124,11 +124,14 @@ class CarController(CarControllerBase):
|
||||
can_sends.append(self.tesla_can.create_steering_control(cntr, self.apply_angle_last, lat_active))
|
||||
can_sends.append(self.tesla_can.create_epas_control(cntr, 1))
|
||||
|
||||
CS.pccEvent = None
|
||||
if self.CP.openpilotLongitudinalControl and self.preap_long is not None:
|
||||
can_sends.extend(self.preap_long.update(CC, CS, self.frame, self.tesla_can, CANBUS.party))
|
||||
|
||||
if self.stock_cc is not None:
|
||||
can_sends.extend(self.stock_cc.update(CS, self.frame, self.tesla_can, CANBUS.party))
|
||||
if self.stock_cc.pcc_event:
|
||||
CS.pccEvent = self.stock_cc.pcc_event
|
||||
|
||||
new_actuators = actuators.as_builder()
|
||||
new_actuators.steeringAngleDeg = self.apply_angle_last
|
||||
|
||||
@@ -37,6 +37,8 @@ class CarState(CarStateBase):
|
||||
self.enableLongControl = False
|
||||
self.enableJustCC = False
|
||||
self.pedal_speed_kph = 0.0
|
||||
self.prev_stalk_follow = 0
|
||||
self.pccEvent = None
|
||||
self.preap_cc_cancel_needed = False
|
||||
self.preap_cc_engage_needed = False
|
||||
self.di_cruise_state = "OFF"
|
||||
@@ -53,6 +55,11 @@ class CarState(CarStateBase):
|
||||
self.autopark_prev = autopark_now
|
||||
self.cruise_enabled_prev = cruise_enabled
|
||||
|
||||
def update_button_enable(self, buttonEvents: list[structs.CarState.ButtonEvent]):
|
||||
if self.CP.carFingerprint == CAR.TESLA_MODEL_S_PREAP:
|
||||
return False
|
||||
return super().update_button_enable(buttonEvents)
|
||||
|
||||
def update(self, can_parsers, starpilot_toggles) -> structs.CarState:
|
||||
if self.CP.carFingerprint == CAR.TESLA_MODEL_S_PREAP:
|
||||
return update_preap(self, can_parsers)
|
||||
|
||||
@@ -69,6 +69,8 @@ class PreAPLongController:
|
||||
freeze_integrator=in_engage_grace, orientation_ned=list(CC.orientationNED),
|
||||
)
|
||||
can_sends.append(tesla_can.create_pedal_command(nap_conf.di_to_pedal(self.prev_pedal_di), enable=1))
|
||||
if self.prev_pedal_di <= 0.95 * PEDAL_DI_MIN and not in_engage_grace:
|
||||
CS.pccEvent = "pedalMaxRegen"
|
||||
else:
|
||||
zero_torque_di = get_zero_torque().get(CS.out.vEgo)
|
||||
self.prev_pedal_di = zero_torque_di
|
||||
@@ -87,4 +89,3 @@ class PreAPLongController:
|
||||
@staticmethod
|
||||
def _pedal_ready() -> bool:
|
||||
return nap_conf.pedal_calibrated and abs(nap_conf.pedal_factor) > 1e-6
|
||||
|
||||
|
||||
@@ -6,11 +6,18 @@ from cereal import custom
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.car import Bus, structs
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.tesla.preap.nap_params import NAPParamKeys
|
||||
from opendbc.car.tesla.preap.engagement import PreAPEngagement
|
||||
from opendbc.car.tesla.preap.nap_conf import PEDAL_DI_PRESSED, nap_conf
|
||||
from opendbc.car.tesla.preap.pedal_feedback import PedalFeedback
|
||||
from opendbc.car.tesla.values import CANBUS, DBC, GEAR_MAP, STEER_THRESHOLD
|
||||
|
||||
try:
|
||||
from openpilot.common.params import Params as _NAPParams
|
||||
_nap_params = _NAPParams()
|
||||
except ImportError:
|
||||
_nap_params = None
|
||||
|
||||
_DOORS = ("DOOR_STATE_FL", "DOOR_STATE_FR", "DOOR_STATE_RL", "DOOR_STATE_RR", "DOOR_STATE_FrontTrunk", "BOOT_STATE")
|
||||
|
||||
|
||||
@@ -83,6 +90,14 @@ def update_preap(cs, can_parsers):
|
||||
cs.cruise_buttons = int(cp_chassis.vl["STW_ACTN_RQ"]["SpdCtrlLvr_Stat"])
|
||||
cs.msg_stw_actn_req = copy.copy(cp_chassis.vl["STW_ACTN_RQ"])
|
||||
|
||||
if _nap_params is not None:
|
||||
dtr_dist = int(cp_chassis.vl["STW_ACTN_RQ"]["DTR_Dist_Rq"])
|
||||
if dtr_dist != 255:
|
||||
stalk_follow = min((dtr_dist // 33) + 1, 7)
|
||||
if stalk_follow != cs.prev_stalk_follow:
|
||||
_nap_params.put(NAPParamKeys.FOLLOW_DISTANCE, str(stalk_follow))
|
||||
cs.prev_stalk_follow = stalk_follow
|
||||
|
||||
curr_time_ms = _current_time_millis()
|
||||
ret.buttonEvents = cs.engagement.process_buttons(
|
||||
cs.cruise_buttons, cs.prev_cruise_buttons, curr_time_ms, ret.vEgo, cs.speed_units,
|
||||
@@ -109,7 +124,18 @@ def update_preap(cs, can_parsers):
|
||||
if use_pedal:
|
||||
ret.gasPressed = cs.pedal.gas_pressed
|
||||
|
||||
cs.das_control = None
|
||||
cs.cruise_enabled_prev = ret.cruiseState.enabled
|
||||
ret.pedalMaxRegen = cs.pccEvent == "pedalMaxRegen"
|
||||
ret.teslaCCEngaged = cs.pccEvent == "teslaCCEngaged"
|
||||
ret.teslaCCDisengaged = cs.pccEvent == "teslaCCDisengaged"
|
||||
ret.teslaCCNotArmed = (
|
||||
not nap_conf.use_pedal and
|
||||
cs.cruiseEnabled and
|
||||
cs.enableLongControl and
|
||||
cs.di_cruise_state not in ("STANDBY", "ENABLED")
|
||||
)
|
||||
ret.pedalLongActive = cs.enableLongControl and nap_conf.use_pedal
|
||||
return ret, fp_ret
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ class StockCCSpoofer:
|
||||
self.cc_engage_start_frame = 0
|
||||
self.cancel_pending = False
|
||||
self.cancel_frame = -1_000_000
|
||||
self.prev_di_cc_engaged = False
|
||||
self.pcc_event = None
|
||||
|
||||
def update(self, CS, frame: int, tesla_can, can_bus_party: int):
|
||||
can_sends = []
|
||||
@@ -40,6 +42,15 @@ class StockCCSpoofer:
|
||||
if sent is not None:
|
||||
can_sends.append(sent)
|
||||
|
||||
di_cc_engaged = getattr(CS, "di_cruise_state", "OFF") == "ENABLED"
|
||||
if di_cc_engaged and not self.prev_di_cc_engaged:
|
||||
self.pcc_event = "teslaCCEngaged"
|
||||
elif not di_cc_engaged and self.prev_di_cc_engaged:
|
||||
self.pcc_event = "teslaCCDisengaged"
|
||||
else:
|
||||
self.pcc_event = None
|
||||
self.prev_di_cc_engaged = di_cc_engaged
|
||||
|
||||
return can_sends
|
||||
|
||||
@staticmethod
|
||||
@@ -49,4 +60,3 @@ class StockCCSpoofer:
|
||||
return None
|
||||
counter = (int(msg_stw.get("MC_STW_ACTN_RQ", 0)) + 1) % 16
|
||||
return tesla_can.create_action_request(button, can_bus_party, counter, msg_stw)
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ static bool tesla_preap_tx_hook(const CANPacket_t *msg) {
|
||||
static bool tesla_preap_fwd_hook(int bus_num, int addr) {
|
||||
(void)bus_num;
|
||||
(void)addr;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static safety_config tesla_preap_init(uint16_t param) {
|
||||
|
||||
@@ -173,6 +173,22 @@ class CarSpecificEvents:
|
||||
# if CC.eps_timer_soft_disable_alert: # type: ignore[attr-defined]
|
||||
# events.add(EventName.steerTimeLimit)
|
||||
|
||||
elif self.CP.brand == 'tesla':
|
||||
events = self.create_common_events(CS, CS_prev, extra_gears=extra_gears)
|
||||
|
||||
if self.CP.carFingerprint == "TESLA_MODEL_S_PREAP":
|
||||
if self.CP.pcmCruise:
|
||||
if getattr(CS, 'teslaCCEngaged', False):
|
||||
events.add(EventName.teslaCCEngaged)
|
||||
if getattr(CS, 'teslaCCDisengaged', False):
|
||||
events.add(EventName.teslaCCDisengaged)
|
||||
if getattr(CS, 'teslaCCNotArmed', False):
|
||||
events.add(EventName.teslaCCNotArmed)
|
||||
else:
|
||||
from opendbc.car.tesla.preap.nap_conf import nap_conf
|
||||
if not nap_conf.pedal_calibrated:
|
||||
events.add(EventName.pedalNotCalibrated)
|
||||
|
||||
elif self.CP.brand == 'hyundai':
|
||||
events = self.create_common_events(CS, CS_prev, extra_gears=extra_gears, pcm_enable=self.CP.pcmCruise, allow_button_cancel=False)
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
from unittest.mock import PropertyMock, patch # noqa: TID251
|
||||
|
||||
from cereal import car, log
|
||||
|
||||
from openpilot.selfdrive.car.car_specific import CarSpecificEvents
|
||||
|
||||
|
||||
EventName = log.OnroadEvent.EventName
|
||||
NAP_CONF_PATH = "opendbc.car.tesla.preap.nap_conf.NAPConf.pedal_calibrated"
|
||||
|
||||
|
||||
def _make_cp(*, fingerprint="TESLA_MODEL_S_PREAP", brand="tesla", pcm_cruise=False, op_long=True):
|
||||
cp = car.CarParams.new_message()
|
||||
cp.carFingerprint = fingerprint
|
||||
cp.brand = brand
|
||||
cp.pcmCruise = pcm_cruise
|
||||
cp.openpilotLongitudinalControl = op_long
|
||||
return cp
|
||||
|
||||
|
||||
def _make_cs():
|
||||
cs = car.CarState.new_message()
|
||||
cs.cruiseState.available = True
|
||||
cs.gearShifter = "drive"
|
||||
return cs
|
||||
|
||||
|
||||
def _run(cp, calibrated):
|
||||
with patch(NAP_CONF_PATH, new_callable=PropertyMock, return_value=calibrated):
|
||||
ce = CarSpecificEvents(cp)
|
||||
events = ce.update(_make_cs(), _make_cs(), car.CarControl.new_message())
|
||||
return events.names
|
||||
|
||||
|
||||
def test_fires_in_preap_pedal_mode_when_uncalibrated():
|
||||
cp = _make_cp(pcm_cruise=False, op_long=True)
|
||||
assert EventName.pedalNotCalibrated in _run(cp, calibrated=False)
|
||||
|
||||
|
||||
def test_silent_in_preap_pedal_mode_when_calibrated():
|
||||
cp = _make_cp(pcm_cruise=False, op_long=True)
|
||||
assert EventName.pedalNotCalibrated not in _run(cp, calibrated=True)
|
||||
|
||||
|
||||
def test_silent_in_preap_nopedal_mode_even_when_uncalibrated():
|
||||
cp = _make_cp(pcm_cruise=True, op_long=False)
|
||||
assert EventName.pedalNotCalibrated not in _run(cp, calibrated=False)
|
||||
|
||||
|
||||
def test_silent_on_non_preap_tesla():
|
||||
cp = _make_cp(fingerprint="TESLA_MODEL_S", pcm_cruise=False, op_long=True)
|
||||
assert EventName.pedalNotCalibrated not in _run(cp, calibrated=False)
|
||||
|
||||
|
||||
def test_silent_on_non_tesla_brand():
|
||||
cp = _make_cp(fingerprint="HONDA_CIVIC_2022", brand="honda", pcm_cruise=True, op_long=False)
|
||||
assert EventName.pedalNotCalibrated not in _run(cp, calibrated=False)
|
||||
@@ -49,9 +49,9 @@ MIN_LATERAL_CONTROL_SPEED = 0.3
|
||||
CIVIC_BOSCH_MODIFIED_B_FIXED_FRICTION_THRESHOLD = 0.30
|
||||
CIVIC_BOSCH_MODIFIED_B_LAT_ACCEL_FACTOR_MULT = 1.20
|
||||
CIVIC_BOSCH_MODIFIED_A_VARIANT_LAT_ACCEL_FACTOR_MULT = 1.00
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_LAT_ACCEL_FACTOR_MULT = 1.26
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_LAT_ACCEL_FACTOR_MULT = 1.32
|
||||
CIVIC_BOSCH_MODIFIED_B_TRANSITION_SPEED = 12.0
|
||||
CIVIC_BOSCH_MODIFIED_B_PHASE_SCALE = 0.10
|
||||
CIVIC_BOSCH_MODIFIED_B_PHASE_SCALE = 0.08
|
||||
CIVIC_BOSCH_MODIFIED_B_FF_ONSET = 0.18
|
||||
CIVIC_BOSCH_MODIFIED_B_FF_ONSET_WIDTH = 0.07
|
||||
CIVIC_BOSCH_MODIFIED_B_FF_CUTOFF = 1.00
|
||||
@@ -76,16 +76,16 @@ CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_FRICTION_BOOST_LEFT = 0.00
|
||||
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_FRICTION_BOOST_RIGHT = 0.00
|
||||
CIVIC_BOSCH_MODIFIED_A_VARIANT_UNWIND_FRICTION_REDUCTION_LEFT = 0.03
|
||||
CIVIC_BOSCH_MODIFIED_A_VARIANT_UNWIND_FRICTION_REDUCTION_RIGHT = 0.07
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_LEFT = 0.24
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_RIGHT = 0.34
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_LEFT = 0.26
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_RIGHT = 0.38
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_BOOST_LEFT = 0.06
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_BOOST_RIGHT = 0.06
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_LEFT = 1.18
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_RIGHT = 1.48
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_LEFT = 1.55
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_RIGHT = 1.95
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_FRICTION_BOOST_LEFT = 0.03
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_FRICTION_BOOST_RIGHT = 0.03
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_LEFT = 0.88
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_RIGHT = 1.20
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_LEFT = 1.05
|
||||
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_RIGHT = 1.40
|
||||
|
||||
BOLT_2022_2023_CARS = (
|
||||
GM_CAR.CHEVROLET_BOLT_ACC_2022_2023,
|
||||
|
||||
@@ -441,7 +441,7 @@ class TestLatControl:
|
||||
monkeypatch.setattr(latcontrol_torque, "civic_bosch_modified_lateral_testing_ground_active", lambda: True)
|
||||
variant_controller = LatControlTorque(CP.as_reader(), CI, DT_CTRL)
|
||||
|
||||
assert variant_controller.torque_params.latAccelFactor == pytest.approx(3.0 * 1.20 * 1.26)
|
||||
assert variant_controller.torque_params.latAccelFactor == pytest.approx(3.0 * 1.20 * 1.32)
|
||||
|
||||
def test_modified_civic_b_torque_ff_scale_curve(self):
|
||||
steady_left = get_civic_bosch_modified_b_ff_scale(0.5, 0.0, 12.0)
|
||||
|
||||
@@ -920,6 +920,11 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"),
|
||||
},
|
||||
|
||||
EventName.pedalNotCalibrated: {
|
||||
ET.PERMANENT: NormalPermanentAlert("Pedal Not Calibrated", "Check Calibration"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Pedal Not Calibrated: Check Calibration"),
|
||||
},
|
||||
|
||||
EventName.calibrationRecalibrating: {
|
||||
ET.PERMANENT: calibration_incomplete_alert,
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Device Remount Detected: Recalibrating"),
|
||||
@@ -1120,6 +1125,50 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
ET.WARNING: personality_changed_alert,
|
||||
},
|
||||
|
||||
EventName.pedalCruiseEnabled: {
|
||||
ET.WARNING: Alert(
|
||||
"Pedal Cruise Engaged",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.engage, 0.8),
|
||||
},
|
||||
|
||||
EventName.pedalCruiseDisabled: {
|
||||
ET.WARNING: Alert(
|
||||
"Pedal Cruise Disengaged",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.disengage, 0.8),
|
||||
},
|
||||
|
||||
EventName.pedalMaxRegen: {
|
||||
ET.WARNING: Alert(
|
||||
"Max Regen Being Used",
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.prompt, 2.),
|
||||
},
|
||||
|
||||
EventName.teslaCCEngaged: {
|
||||
ET.WARNING: Alert(
|
||||
"Tesla Cruise Engaged",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.engage, 0.8),
|
||||
},
|
||||
|
||||
EventName.teslaCCDisengaged: {
|
||||
ET.WARNING: Alert(
|
||||
"Tesla Cruise Disengaged",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.disengage, 0.8),
|
||||
},
|
||||
|
||||
EventName.teslaCCNotArmed: {
|
||||
ET.PERMANENT: NormalPermanentAlert("Arm Stock Cruise to Enable Speed Control"),
|
||||
},
|
||||
|
||||
EventName.userBookmark: {
|
||||
ET.PERMANENT: NormalPermanentAlert("Bookmark Saved", duration=1.5),
|
||||
},
|
||||
|
||||
@@ -133,6 +133,7 @@ class SelfdriveD:
|
||||
self.recalibrating_seen = False
|
||||
self.state_machine = StateMachine()
|
||||
self.rk = Ratekeeper(100, print_delay_threshold=None)
|
||||
self.prev_pedal_long_active = False
|
||||
|
||||
# Determine startup event
|
||||
self.startup_event = StarPilotEventName.customStartupAlert
|
||||
@@ -241,6 +242,22 @@ class SelfdriveD:
|
||||
self.last_below_steer_speed_alert_time = now
|
||||
self.events.add_from_msg(car_events)
|
||||
|
||||
if (self.CP.brand == "tesla"
|
||||
and self.CP.carFingerprint == "TESLA_MODEL_S_PREAP"
|
||||
and self.CP.openpilotLongitudinalControl
|
||||
and not self.CP.pcmCruise):
|
||||
pedal_long_active = bool(CS.cruiseState.enabled and getattr(CS, 'pedalLongActive', False))
|
||||
if pedal_long_active and not self.prev_pedal_long_active:
|
||||
self.events.add(EventName.pedalCruiseEnabled)
|
||||
elif self.prev_pedal_long_active and not pedal_long_active:
|
||||
self.events.add(EventName.pedalCruiseDisabled)
|
||||
self.prev_pedal_long_active = pedal_long_active
|
||||
|
||||
if getattr(CS, 'pedalMaxRegen', False):
|
||||
self.events.add(EventName.pedalMaxRegen)
|
||||
else:
|
||||
self.prev_pedal_long_active = False
|
||||
|
||||
if (getattr(self.starpilot_toggles, "nostalgia_mode", False) and
|
||||
self.CP.openpilotLongitudinalControl and
|
||||
self.enabled and
|
||||
|
||||
Reference in New Issue
Block a user