This commit is contained in:
firestar5683
2026-07-16 10:33:59 -05:00
parent 4013a70e9d
commit 8f3f9cf6c7
3 changed files with 43 additions and 11 deletions
@@ -27,6 +27,7 @@ ACCEL_PID_UNWIND = 0.03 * DT_CTRL * 3 # m/s^2 / frame
PRIUS_INTEGRAL_MISMATCH_UNWIND = 8.0
PRIUS_POSITIVE_FEEDFORWARD_SCALE = 0.7
PRIUS_CRUISE_FEEDFORWARD_SCALE = 1.0
CAMRY_HYBRID_POSITIVE_FEEDFORWARD_SCALE = 0.8
MAX_PITCH_COMPENSATION = 1.5 # m/s^2
TOYOTA_COAST_BRAKE_MIN_SPEED = 15.0 # m/s
@@ -52,10 +53,12 @@ LOCK_CMD = b"\x40\x05\x30\x11\x00\x80\x00\x00"
UNLOCK_CMD = b"\x40\x05\x30\x11\x00\x40\x00\x00"
def is_camry_hybrid(CP) -> bool:
return CP.carFingerprint == CAR.TOYOTA_CAMRY and bool(CP.flags & ToyotaFlags.HYBRID.value)
def is_ths_hybrid(CP) -> bool:
return CP.carFingerprint == CAR.TOYOTA_PRIUS or (
CP.carFingerprint == CAR.TOYOTA_CAMRY and bool(CP.flags & ToyotaFlags.HYBRID.value)
)
return CP.carFingerprint == CAR.TOYOTA_PRIUS or is_camry_hybrid(CP)
def get_long_tune(CP, params):
@@ -64,7 +67,7 @@ def get_long_tune(CP, params):
k_f = 1.0
if is_ths_hybrid(CP):
k_f = 0.8
k_f = 0.8 if CP.carFingerprint == CAR.TOYOTA_PRIUS else 1.0
elif CP.carFingerprint not in TSS2_CAR:
kiBP = [0., 5., 35.]
kiV = [3.6, 2.4, 1.5]
@@ -79,6 +82,10 @@ def get_prius_positive_feedforward_scale(v_ego: float) -> float:
[PRIUS_POSITIVE_FEEDFORWARD_SCALE, PRIUS_POSITIVE_FEEDFORWARD_SCALE, PRIUS_CRUISE_FEEDFORWARD_SCALE]))
def get_camry_hybrid_feedforward(accel: float) -> float:
return accel * CAMRY_HYBRID_POSITIVE_FEEDFORWARD_SCALE if accel > 0.0 else accel
def update_permit_braking(current: bool, net_acceleration_request_min: float, stopping: bool,
long_active: bool, v_ego: float, lead_visible: bool) -> bool:
if stopping or not long_active:
@@ -463,6 +470,10 @@ class CarController(CarControllerBase):
if self.CP.carFingerprint == CAR.TOYOTA_PRIUS:
if feedforward > 0.0:
feedforward *= get_prius_positive_feedforward_scale(CS.out.vEgo)
elif is_camry_hybrid(self.CP) and feedforward > 0.0:
# Preserve the established Camry Hybrid acceleration response while
# allowing negative requests to track the planner at full scale.
feedforward = get_camry_hybrid_feedforward(feedforward)
pcm_accel_cmd = self.long_pid.update(error_future,
speed=CS.out.vEgo,
@@ -8,7 +8,8 @@ from opendbc.can import CANPacker, CANParser
from opendbc.car.structs import CarParams
from opendbc.car.fw_versions import build_fw_dict
from opendbc.car.toyota import toyotacan
from opendbc.car.toyota.carcontroller import CarController, get_long_tune, get_prius_positive_feedforward_scale, limit_interceptor_pcm_accel, \
from opendbc.car.toyota.carcontroller import CarController, get_camry_hybrid_feedforward, get_long_tune, get_prius_positive_feedforward_scale, \
limit_interceptor_pcm_accel, \
limit_interceptor_stopping_accel, limit_no_lead_cruise_sign_flip, \
limit_prius_stopping_accel, update_permit_braking
from opendbc.car.toyota.carstate import CarState, LKAS_BUTTON_CAR, calculate_interceptor_gas_pressed, create_lkas_button_events
@@ -164,7 +165,7 @@ class TestToyotaInterfaces:
controller = get_long_tune(car_params, SimpleNamespace(ACCEL_MIN=-3.5, ACCEL_MAX=2.0))
controller.speed = 0.0
assert controller.k_i == pytest.approx(0.5)
assert controller.k_f == pytest.approx(0.8)
assert controller.k_f == pytest.approx(1.0)
radar_interface = RadarInterface(car_params)
assert radar_interface.radar_acc_tssp
@@ -464,6 +465,10 @@ class TestToyotaCarController:
assert get_prius_positive_feedforward_scale(20.0) > get_prius_positive_feedforward_scale(8.0)
assert abs(get_prius_positive_feedforward_scale(20.0) - 1.0) < 1e-6
def test_camry_hybrid_feedforward_only_softens_acceleration(self):
assert get_camry_hybrid_feedforward(1.0) == pytest.approx(0.8)
assert get_camry_hybrid_feedforward(-2.0) == pytest.approx(-2.0)
def test_sng_hack_clears_existing_standstill_latch(self):
controller = self._make_controller(standstill_req=True, last_standstill=True)
@@ -587,20 +587,28 @@ function tuneComparisonRows() {
if (!stock || !current) return []
const trialGeneric = activeTrialProfile()?.genericParams || {}
const rows = [
const angleControl = state.report?.car?.controlPath === "angle"
const genericParams = angleControl ? [
["Auto steer delay", "UseAutoSteerDelay"],
["Steer delay", "SteerDelay"],
["Steer ratio", "SteerRatio"],
] : [
["Lat accel", "SteerLatAccel"],
["Friction", "SteerFriction"],
["Auto steer delay", "UseAutoSteerDelay"],
["Steer delay", "SteerDelay"],
["Steer ratio", "SteerRatio"],
["KP", "SteerKP"],
].map(([label, key]) => ({
]
const rows = genericParams.map(([label, key]) => ({
key,
label,
stock: stock[key],
current: Object.hasOwn(trialGeneric, key) ? trialGeneric[key] : current[key],
}))
if (angleControl) return rows
const overrides = mergedFlmOverrides()
for (const [family, payload] of Object.entries(stock.FLMBaseFrictionThresholds || {})) {
rows.push({
@@ -635,21 +643,29 @@ function renderTuneComparison() {
const rows = tuneComparisonRows()
if (!rows.length) return ""
const profile = activeTrialProfile()
const angleControl = state.report?.car?.controlPath === "angle"
return html`
<div class="flmCardSubsection flmTuneComparison">
<div class="flmCardHeader">
<div>
<h4>Stock vs Current FLM</h4>
<h4>${angleControl ? "Applicable Angle Settings" : "Stock vs Current FLM"}</h4>
<p class="longManeuverMuted">
${profile ? `Includes active trial: ${profile.pathLabel || "FLM"} / ${profile.label}` : "Current values captured when this route was analyzed."}
${angleControl
? "Current applicable values captured when this route was analyzed."
: profile
? `Includes active trial: ${profile.pathLabel || "FLM"} / ${profile.label}`
: "Current values captured when this route was analyzed."}
</p>
${angleControl ? html`
<p class="longManeuverMuted">Torque-only lateral acceleration, friction, and KP values do not apply to this angle-control car.</p>
` : ""}
</div>
</div>
<div class="flmTuneComparisonTable">
<div class="flmTuneComparisonHeader">Parameter</div>
<div class="flmTuneComparisonHeader">Stock</div>
<div class="flmTuneComparisonArrow"></div>
<div class="flmTuneComparisonHeader">FLM</div>
<div class="flmTuneComparisonHeader">${angleControl ? "Current" : "FLM"}</div>
${rows.map((row) => html`
<div class="flmTuneComparisonLabel" title="${row.codeLabel || row.key}">${row.label}</div>
<div>${formatTuneComparisonValue(row.stock)}</div>