Replay unchanged native limits before judging a learned tune

This commit is contained in:
firestar5683
2026-11-09 02:24:36 +00:00
parent 22308dac24
commit aae3767d89
6 changed files with 273 additions and 18 deletions
@@ -278,16 +278,17 @@ def check_original_native(cp, controls, outputs, commands, *, require_change=Tru
for output in originals.values():
history.verify(by_control[output.control_ns], output)
before = history.rollout(baseline, start, end)
after = history.rollout(candidate, start, end)
if set(before) != set(originals) or any(before[stamp] != delivered(originals[stamp]) for stamp in before):
return {'qualified': False, 'reason': 'original_encoder_reconstruction_mismatch'}
after = history.rollout(candidate, start, end, allow_unclipped_equal_output=True)
except (AttributeError, KeyError, TypeError, ValueError, OverflowError) as error:
return {'qualified': False, 'reason': 'original_encoder_or_candidate_quality_refused', 'detail': str(error)[:160]}
if set(before) != set(originals) or any(before[stamp] != delivered(originals[stamp]) for stamp in before):
return {'qualified': False, 'reason': 'original_encoder_reconstruction_mismatch'}
changed = sum(before[k] != after[k] for k in before)
return {
'qualified': bool(changed or not require_change),
'reason': 'registered_encoder_trial_only' if require_change else 'original_registered_encoder_observed',
'original_decoded_emissions': len(originals),
'limiter_policy': 'same_state_equal_output_unclipped_v1',
'candidate_changed_emissions': changed,
'physical_improvement_proven': False,
'hardware_current_permission': False,
@@ -268,18 +268,35 @@ class StableRouteSelector:
all_ids = ids['training'] + ids['heldout']
if any(key not in rows or rows[key] is None for key in all_ids):
return None, {'reason': 'original_stable_input_fields_missing', 'original_windows': all_ids}
mapped, reports = {}, {}
for role, windows in ids.items():
mapped[role], reports[role] = self.profile(windows, cohort['cohort'])
training, heldout = mapped['training'], mapped['heldout']
training, training_report = self.profile(ids['training'], cohort['cohort'])
selection = 'training_values_only_no_heldout_resizing'
if training is not None:
from openpilot.starpilot.flm.offroad_surface import CURVE_NAMES
if any(training['values'][name] != self.previous[name] for name in CURVE_NAMES):
# Quieting is one trial; unrelated turn changes need their own evidence.
values = dict(self.previous)
for name in CURVE_NAMES:
if training['values'][name] != self.previous[name]:
values[name] = round(self.previous[name] + 0.6 * (training['values'][name] - self.previous[name]), 12)
training = dict(
training,
values=values,
changed_parameters=tuple(name for name in CURVE_NAMES if values[name] != self.previous[name]),
maximum_coordinate_step=max(abs(values[name] - self.previous[name]) for name in CURVE_NAMES),
bounded_profile_scale=training['bounded_profile_scale'] * 0.6,
)
selection = 'training_only_conservative_friction_trial_before_heldout'
heldout, heldout_report = self.profile(ids['heldout'], cohort['cohort'])
agrees = independent_profile_support(training, heldout, self.previous)
proof = {
'source_policy_commit': ORIGINAL_COMMIT,
'source_classifier_commit': CURRENT_CLASSIFIER_SOURCE,
'policy': 'original_stable_recommended_bounded_route_v1',
'reason': 'independent_support_for_frozen_training_profile' if agrees else 'heldout_profile_does_not_support_training_step',
'selection': 'training_values_only_no_heldout_resizing',
'roles': reports,
'selection': selection,
'frozen_training_profile': training,
'roles': {'training': training_report, 'heldout': heldout_report},
'all_original_windows_still_required': True,
'physical_improvement_proven': False,
}
@@ -492,10 +492,6 @@ class OffroadWorker:
independent = None
stable = proposal.get('policy') == 'original_stable_recommended_bounded_route_v1'
provider = self.stable_prior_provider if stable else self.prior_provider
if provider is None and self.assessor is analyze_latest:
from openpilot.starpilot.flm.offroad_prior_inputs import prior_originals, prior_stable_originals
provider = prior_stable_originals if stable else prior_originals
independent = None if provider is None else provider(assessment, group, cohort, self.root, permitted=self.permitted)
if independent is not None and row is not None and independent.receipt.source_sha256 in row['route_sha256s']:
independent = None
@@ -1296,6 +1296,132 @@ class TestOffroadRouteCoverage(unittest.TestCase):
class TestOffroadTrackingPolicy(unittest.TestCase):
def test_current_disjoint_windows_do_not_trigger_an_older_drive_rescan(self):
from types import SimpleNamespace
from openpilot.starpilot.flm import offroad_worker as module
from openpilot.starpilot.flm.offroad_processor import CompletedAssessment
from openpilot.starpilot.flm.offroad_route import RouteReceipt
# Dispatch-only fixture: training refuses, so no accepted tune is fabricated.
roles = trial()['before']
proposal = {'parameter': 'center_taper_max', 'delta': 0.005, 'values': values(0.005)}
cohort = {'cohort': 'declared-current-drive', 'whole_windows': 6, 'qualification_roles': roles,
'training': dict(roles['training'], reference_rms=0.5), 'heldout': dict(roles['heldout'], reference_rms=0.5), 'proposal': proposal}
metadata = {'route_values': tuple(values().items()), 'route_revision': REVISION, 'controller_mode': 'starpilot', 'route_scope': scope().key()}
group = {'original_metadata': metadata, 'original_context_sha256': 'f' * 64, 'cohorts': [cohort]}
cp = SimpleNamespace(carFingerprint='declared-current-drive')
receipt = RouteReceipt('declared-current-drive', 'd' * 64, (), 'a' * 64, 1, 2, 3, ())
inventory = {'routeId': receipt.route_id}
assessment = CompletedAssessment(receipt, (group,), {}, cp, (), inventory)
calls = []
def assessed(params, root, previous, *, permitted):
previous(cp)
return assessment
def refuse_training(actual, original, selected, proposed, previous, root, *, permitted):
self.assertIs(actual, assessment)
self.assertEqual(selected['qualification_roles'], roles)
self.assertEqual(proposed, proposal)
self.assertTrue(permitted())
calls.append('current_drive_training')
return None, {'declared_training_refusal': True}
def refused_check(*args, **kwargs):
self.fail('A refused training step cannot enter validation')
with tempfile.TemporaryDirectory() as directory:
params = Params(directory)
with (
patch.object(module, 'latest_route', return_value=inventory),
patch.object(module, 'analyze_latest', new=assessed),
patch.object(module, 'qualify', new=refused_check),
patch('openpilot.starpilot.flm.offroad_checks.fit_training_step', new=refuse_training),
patch('openpilot.starpilot.flm.offroad_prior_inputs.prior_originals', side_effect=AssertionError('Unexpected older drive rescan')),
patch('openpilot.starpilot.flm.offroad_prior_inputs.prior_stable_originals', side_effect=AssertionError('Unexpected older drive rescan')),
):
worker = module.OffroadWorker(params, directory, Path(directory) / 'cache', permitted=lambda: True,
assessor=assessed, checker=refused_check, scope_for=lambda cp, params: scope())
result = worker.run_once()
self.assertEqual(calls, ['current_drive_training'])
self.assertFalse(result['configuration_changed'])
self.assertEqual(result['reason'], 'no_new_native_feasible_training_step')
self.assertEqual(read_saved(params, KEY, MAX_BYTES), (None, True))
def test_quieting_trial_is_frozen_before_unrelated_heldout_turn_disagreement(self):
import copy
from openpilot.starpilot.flm.offroad_stable_bridge import StableRouteSelector
# Declared proposal-policy regression, using the retained profile's numeric shape.
# Actual controller/native qualification and automatic storage are not mocked.
roles = trial()['before']
cohort = {'cohort': '2:left:steady', **roles}
original = values()
original.update(friction_threshold_mid=0.004625, friction_threshold_fast=0.0061875, friction_threshold_highway=0.0061875, unwind_taper_left=0.01)
training = {
'values': original,
'changed_parameters': tuple(name for name, value in original.items() if value),
'maximum_coordinate_step': 0.01,
'bounded_profile_scale': 0.625,
}
independent = values()
independent.update(friction_threshold_mid=0.0071, friction_threshold_fast=0.0095, friction_threshold_highway=0.0095)
frozen = copy.deepcopy(training)
for unsupported in (None, 0.0, -0.0095, 0.0001):
with self.subTest(unsupported_primary=unsupported):
selector = object.__new__(StableRouteSelector)
selector.previous = values()
selector.rows = dict.fromkeys(roles['training']['windows'] + roles['heldout']['windows'], [])
events = []
heldout_values = dict(independent)
if unsupported is not None:
heldout_values['friction_threshold_fast'] = unsupported
def declared_profile(windows, selected_cohort, events=events, heldout_values=heldout_values):
self.assertEqual(selected_cohort, cohort['cohort'])
if windows == tuple(roles['training']['windows']):
events.append('training')
return copy.deepcopy(frozen), {'declared_role': 'training'}
self.assertEqual(windows, tuple(roles['heldout']['windows']))
events.append('heldout')
return {'values': heldout_values}, {'declared_role': 'heldout'}
with patch.object(selector, 'profile', side_effect=declared_profile):
proposed, proof = selector.propose({}, cohort)
self.assertEqual(events, ['training', 'heldout'])
self.assertEqual(proof['selection'], 'training_only_conservative_friction_trial_before_heldout')
expected = values()
expected.update(friction_threshold_mid=0.002775, friction_threshold_fast=0.0037125, friction_threshold_highway=0.0037125)
self.assertEqual(proof['frozen_training_profile']['values'], expected)
self.assertEqual(training, frozen)
if unsupported is None:
self.assertIsNotNone(proposed)
assert proposed is not None
self.assertEqual(proposed['values'], expected)
self.assertEqual(proposed['values']['unwind_taper_left'], 0.0)
self.assertEqual(set(proof['frozen_training_profile']['changed_parameters']), set(CURVE_NAMES[2:]))
self.assertTrue(proof['all_original_windows_still_required'])
else:
self.assertIsNone(proposed, 'Missing, reversed or weaker primary evidence must still refuse; no resizing or fallback')
def test_turn_only_training_profile_keeps_original_values(self):
from openpilot.starpilot.flm.offroad_stable_bridge import StableRouteSelector
roles = trial()['before']
mapped = values()
mapped['unwind_taper_left'] = 0.005
profile = {'values': mapped, 'changed_parameters': ('unwind_taper_left',), 'maximum_coordinate_step': 0.005, 'bounded_profile_scale': 1.0}
selector = object.__new__(StableRouteSelector)
selector.previous = values()
selector.rows = dict.fromkeys(roles['training']['windows'] + roles['heldout']['windows'], [])
with patch.object(selector, 'profile', return_value=(profile, {'declared_proposal_only': True})):
proposed, proof = selector.propose({}, {'cohort': '2:left:unwind', **roles})
self.assertIsNotNone(proposed)
assert proposed is not None
self.assertEqual(proposed['values'], mapped)
self.assertEqual(proposed['delta'], 0.005)
self.assertEqual(proof['selection'], 'training_values_only_no_heldout_resizing')
def test_heldout_profile_supports_frozen_training_step_without_identical_floats(self):
import copy
from openpilot.starpilot.flm.offroad_stable_bridge import independent_profile_support
@@ -2234,5 +2360,95 @@ class TestOffroadTrackingPolicy(unittest.TestCase):
self.assertEqual(result['improvement_kind'], 'forced_tracking')
class TestOffroadEqualNativeOutput(unittest.TestCase):
@staticmethod
def boundary(platform, *, unwind=False):
from openpilot.starpilot.flm.tests.test_steering_projection import make_interface, control, apply, settle, install_observer, check_packet
from openpilot.starpilot.flm.torque_emission_replay import Emission
ci = make_interface(platform)
assert install_observer(ci)
initial = settle(ci, control(0.0))[-1][2]
limits = dict(initial.limits)
step = limits['STEER_DELTA_DOWN' if unwind else 'STEER_DELTA_UP']
if unwind:
settle(ci, control(4 * step / initial.effective_max))
target = (3 if unwind else 2) * step
for _ in range(24):
_, packets, witness = apply(ci, control(target / initial.effective_max))
if witness is None:
continue
if (witness.unlimited_raw == witness.final_raw == target and
witness.final_raw - witness.previous_torque == (-step if unwind else step)):
check_packet(ci, packets, witness)
stamp = 10_000_000_000 + witness.frame * 10_000_000
return Emission(stamp, stamp, stamp + 1_000_000, witness, 'a' * 64, 'b' * 64, 'c' * 64,
True, True, False, False, False, False, False, 0, 0, '')
raise AssertionError('Actual registered encoder did not provide the unclipped rate boundary')
def test_exact_same_request_uses_candidate_native_prestate(self):
from opendbc.car.gm.values import CAR as GM
from opendbc.car.hyundai.values import CAR as HYUNDAI
from opendbc.car.toyota.values import CAR as TOYOTA
from openpilot.starpilot.flm.torque_emission_replay import EncoderBranch
for platform in (GM.GMC_ACADIA, HYUNDAI.HYUNDAI_IONIQ_6, TOYOTA.TOYOTA_COROLLA_TSS2):
with self.subTest(platform=platform):
event = self.boundary(platform)
w = event.witness
original = EncoderBranch()
self.assertEqual(original.step(event, w.requested_torque, actual=True), w.final_raw / w.effective_max)
strict = EncoderBranch()
strict.previous = w.previous_torque - 1
with self.assertRaisesRegex(ValueError, 'limiter/support'):
strict.step(event, w.requested_torque)
candidate = EncoderBranch(allow_unclipped_equal_output=True)
candidate.previous = w.previous_torque - 1
self.assertEqual(candidate.step(event, w.requested_torque), (w.final_raw - 1) / w.effective_max)
self.assertEqual(candidate.previous, w.final_raw - 1)
self.assertFalse(event.limited)
self.assertEqual(event.witness, w)
def test_native_unwind_cap_is_not_an_unsafe_request(self):
from opendbc.car.hyundai.values import CAR
from openpilot.starpilot.flm.torque_emission_replay import EncoderBranch
event = self.boundary(CAR.HYUNDAI_IONIQ_6, unwind=True)
w = event.witness
request = (w.unlimited_raw - 1) / w.effective_max
with self.assertRaisesRegex(ValueError, 'limiter/support'):
EncoderBranch().step(event, request)
branch = EncoderBranch(allow_unclipped_equal_output=True)
self.assertEqual(branch.step(event, request), w.final_raw / w.effective_max)
self.assertEqual(branch.previous, w.final_raw)
for unsafe in ((w.unlimited_raw + 1) / w.effective_max, -w.requested_torque):
candidate = EncoderBranch(allow_unclipped_equal_output=True)
candidate.previous = w.previous_torque + 100
with self.assertRaises(ValueError):
candidate.step(event, unsafe)
def test_equal_output_does_not_relax_original_or_legacy_quality(self):
from opendbc.car.gm.values import CAR as GM
from opendbc.car.hyundai.values import CAR as HYUNDAI
from opendbc.car.toyota.values import CAR as TOYOTA
from openpilot.starpilot.flm.torque_emission_replay import EncoderBranch
from openpilot.starpilot.flm.tests import test_state_aligned_encoder as legacy
event = self.boundary(HYUNDAI.HYUNDAI_IONIQ_6)
branch = EncoderBranch(allow_unclipped_equal_output=True)
branch.previous = event.witness.previous_torque - 1
with self.assertRaisesRegex(ValueError, 'actual previous'):
branch.step(event, event.witness.requested_torque, actual=True)
clipped = legacy.captured_event(TOYOTA.TOYOTA_COROLLA_TSS2)
with self.assertRaisesRegex(ValueError, 'limiter/support'):
EncoderBranch(allow_unclipped_equal_output=True).step(replace(clipped, limited=False), clipped.witness.requested_torque)
for platform in (TOYOTA.TOYOTA_COROLLA_TSS2, GM.GMC_ACADIA):
legacy.test_registered_measured_driver_same_request_shadow_and_increased_demand(platform)
legacy.test_common_state_unlimited_reference_recorded_opposite_and_original_unlimited_vetoes()
legacy.test_unsupported_paired_projection_fails_without_advancing_candidate_native_state()
legacy.test_honda_normalized_pre_lookup_comparison_and_modified_filter_shadow_is_pure()
legacy.test_honda_nonfinite_reference_and_paired_original_pressed_fail_closed()
if __name__ == '__main__':
unittest.main()
@@ -102,7 +102,8 @@ def exact_local_emission(witness, reference_raw, candidate_raw, recorded_debt, r
class EncoderBranch:
"""Own previous raw/normalized torque and modified-Civic state per branch."""
def __init__(self, *, quality_contract=RECORDED_DEBT, identification_policy=STRICT_IDENTIFICATION):
def __init__(self, *, quality_contract=RECORDED_DEBT, identification_policy=STRICT_IDENTIFICATION, allow_unclipped_equal_output=False):
self.allow_unclipped_equal_output = allow_unclipped_equal_output
self.quality_contract = clipping_quality(quality_contract)
self.identification_policy = validate_identification_policy(identification_policy)
if (self.identification_policy == NATIVE_SHADOW_IDENTIFICATION and
@@ -198,6 +199,28 @@ class EncoderBranch:
admitted = exact_local_emission(witness, reference_raw, raw, original_demand, reference_demand, candidate_demand)
if not shadow and (not original_demand or not actual and not admitted):
raise ValueError('candidate encoder clipping regression')
if (raw is None and self.allow_unclipped_equal_output and not actual and not shadow and not event.limited and
witness.mapping_kind == 'round' and not witness.shape and witness.steer_requested and
witness.unlimited_raw == witness.final_raw and witness.limiter_kind in ('driver', 'measured')):
from opendbc.car.steering_projection import project_request
from opendbc.car.lateral import apply_driver_steer_torque_limits, apply_meas_steer_torque_limits
requested_raw = project_request(witness, request)
reference_raw = project_request(witness, witness.requested_torque)
# Replaying a different history can engage a rate limiter that was idle
# on the original drive. BOTH requests must produce the EXACT same native
# output from this SAME candidate prestate, with no larger request.
if (reference_raw == witness.unlimited_raw and requested_raw is not None and reference_raw is not None and
(requested_raw == reference_raw or requested_raw * reference_raw > 0 and abs(requested_raw) < abs(reference_raw))):
params = SimpleNamespace(STEER_MAX=witness.effective_max, **dict(witness.limits))
if witness.limiter_kind == 'driver':
candidate_output = apply_driver_steer_torque_limits(requested_raw, self.previous, witness.measured_torque, params, int(witness.effective_max))
reference_output = apply_driver_steer_torque_limits(reference_raw, self.previous, witness.measured_torque, params, int(witness.effective_max))
else:
candidate_output = apply_meas_steer_torque_limits(requested_raw, self.previous, witness.measured_torque, params)
reference_output = apply_meas_steer_torque_limits(reference_raw, self.previous, witness.measured_torque, params)
if candidate_output == reference_output:
raw = candidate_output
if raw is None and (event.limited or shadow) and witness.limiter_kind in ('driver', 'measured'):
from opendbc.car.steering_projection import project_request
from opendbc.car.lateral import apply_driver_steer_torque_limits, apply_meas_steer_torque_limits
@@ -454,9 +477,10 @@ class EmissionHistory:
return base, features
def rollout(self, requests, start_ns, end_ns, windows=(), *, quality_contract=RECORDED_DEBT,
identification_policy=STRICT_IDENTIFICATION, feedback_reported=None):
identification_policy=STRICT_IDENTIFICATION, feedback_reported=None, allow_unclipped_equal_output=False):
"""Advance on EVERY actual emission, including unscored warmup emissions."""
branch = EncoderBranch(quality_contract=quality_contract, identification_policy=identification_policy)
branch = EncoderBranch(quality_contract=quality_contract, identification_policy=identification_policy,
allow_unclipped_equal_output=allow_unclipped_equal_output)
if feedback_reported is not None and (type(feedback_reported) is not dict or feedback_reported):
raise ValueError('empty private candidate reported CO sink required')
values = {}
@@ -469,7 +493,8 @@ class EmissionHistory:
raise ValueError('missing consumed controller source')
window = next((i for i, (a, b) in enumerate(windows) if a <= event.control_ns <= b), 0)
if window != last_window:
branch = EncoderBranch(quality_contract=quality_contract, identification_policy=identification_policy)
branch = EncoderBranch(quality_contract=quality_contract, identification_policy=identification_policy,
allow_unclipped_equal_output=allow_unclipped_equal_output)
previous = None
self.decode(event)
value = branch.step(event, requests[event.control_ns])
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "52558c336dd65c0d44d35ffdc87186a7bb059bd3243d2f18b6fe4522809484a9", "schema_version": 1}
{"protected_inventory_sha256": "e94ee72057011ff5d3cd0a0250d65d4ebf13d3f526196d04626c2fec6ddc29db", "schema_version": 1}