Files
StarPilot/openpilot/starpilot/flm/tests/test_selected_effect_owner.py
T
firestar5683 2cd7728be2 FLM Auto-Weave
2026-10-17 18:38:27 -05:00

172 lines
6.6 KiB
Python

"""Actual effect owner lifecycle; profile fixture is not physical fit proof."""
from dataclasses import replace
import pytest
from openpilot.starpilot.flm.adaptive_profile import Profile, ReplayValidation
from openpilot.starpilot.flm.canonical_surface_adapter import (
MANIFEST_SHA256,
NAMES,
full_original_anchor,
full_profile_sha256,
original_anchor,
parameters_for,
)
from openpilot.starpilot.flm.event_objective import EffectObjective
from openpilot.starpilot.flm.full_surface_profile import FullSurfaceEnvelope
from openpilot.starpilot.flm.selected_effects import EffectOwner, EffectTrial
from openpilot.starpilot.flm.torque_adapter import Admission
NOW = 1_000_000_000
BASE = 'b' * 64
SOURCE = 'e' * 64
def fixture(*, accumulated=False):
names = ('ff_gain_left',)
prior = dict.fromkeys(NAMES, 0.0)
if accumulated:
prior['center_taper_max'] = 0.1
proposed = dict(prior, ff_gain_left=0.004)
envelope = FullSurfaceEnvelope(
1,
MANIFEST_SHA256,
full_original_anchor(BASE),
original_anchor(BASE, names),
SOURCE,
'c' * 64,
'selected-controller',
SOURCE,
'0',
BASE,
full_profile_sha256(BASE, prior),
full_profile_sha256(BASE, proposed),
tuple(prior.items()),
tuple(proposed.items()),
names,
'f' * 64,
)
profile = Profile(
'a' * 64,
1,
NOW,
NOW + 500_000_000,
parameters_for(names),
(0.004,),
tuple(f'train{i}' for i in range(4)),
tuple(f'held{i}' for i in range(4)),
1.0,
0.8,
(('held', 0.1),),
policy='event_effect_coordinate_v2',
effect_envelope=envelope,
)
validation = ReplayValidation(profile, BASE, 'physical-model', True, True, 0.1)
objective = EffectObjective('ff.left', names, envelope.trial_anchor, SOURCE)
context = {
'cp_sha256': envelope.cp_sha256,
'controller_revision': envelope.controller_revision,
'source_epoch': SOURCE,
'reset_generation': '0',
'selected_baseline_revision': BASE,
'context_key': SOURCE,
'persistent_source_epoch': 'f' * 64,
'current_full_profile_sha256': envelope.prior_full_profile_sha256,
}
owner = EffectOwner(
profile.identity, objective, selected_baseline_revision=BASE, physical_model_revision='physical-model', original_anchor=envelope.replay_anchor()
)
return owner, profile, validation, context
def test_expired_proof_withdraws_all30_not_just_fitted_group():
owner, p, v, context = fixture(accumulated=True)
owner.prepare(Admission(p, NOW, True, False, True, v), active=True, current_context=context)
assert owner.source is not None
assert 0 < owner.applied_full['center_taper_max'] <= 0.005 * 0.01
owner.prepare(Admission(p, NOW + 500_000_001, True, False, True, v), active=True, current_context=context)
assert owner.source is None
assert all(value == 0 for value in owner.applied_full.values())
@pytest.mark.parametrize('reason', ['manual', 'off', 'inactive', 'unhealthy'])
def test_withdrawal_and_recovery_slew_all30(reason):
owner, p, v, context = fixture(accumulated=True)
owner.prepare(Admission(p, NOW, True, False, True, v), active=True, current_context=context)
owner.prepare(
Admission(p, NOW + 10_000_000, reason != 'off', reason == 'manual', reason != 'unhealthy', v), active=reason != 'inactive', current_context=context
)
assert owner.source is None and not any(owner.applied_full.values())
owner.prepare(Admission(p, NOW + 20_000_000, True, False, True, v), active=True, current_context=context)
assert owner.source is not None
assert max(abs(value) for value in owner.applied_full.values()) <= 0.005 * 0.01 + 1e-12
def test_changed_current_context_never_leaves_previous_source_attached():
owner, p, v, context = fixture()
owner.prepare(Admission(p, NOW, True, False, True, v), active=True, current_context=context)
with pytest.raises(ValueError):
owner.prepare(Admission(p, NOW + 10_000_000, True, False, True, v), active=True, current_context=dict(context, source_epoch='d' * 64))
assert owner.source is None
def test_replay_trial_preserves_nonzero_group_and_outside_group_original_prior():
owner, p, _, _ = fixture(accumulated=True)
prior = dict(p.effect_envelope.prior_coordinates)
prior['ff_gain_left'] = 0.1
envelope = replace(
p.effect_envelope,
prior_coordinates=tuple(prior.items()),
coordinates=tuple(prior.items()),
prior_full_profile_sha256=full_profile_sha256(BASE, prior),
full_profile_sha256=full_profile_sha256(BASE, prior),
)
trial = EffectTrial(owner.objective, (0.104,), BASE, envelope.replay_anchor())
source = trial.source()
assert source.values['ff_gain_left'] == 0.104
assert source.values['center_taper_max'] == 0.1
assert source.values['ff_gain_right'] == 0
def test_trial_group_switch_preserves_full30_state_and_cas_without_step_jump():
owner, p, v, context = fixture()
owner.prepare(Admission(p, NOW, True, False, True, v), active=True, current_context=context)
before = dict(owner.applied_full)
old = p.effect_envelope
names = ('turn_in_threshold_reduction_left',)
prior = dict(old.coordinates)
proposed = dict(prior, turn_in_threshold_reduction_left=0.004)
envelope = replace(
old,
trial_names=names,
trial_anchor=original_anchor(BASE, names),
prior_coordinates=tuple(prior.items()),
coordinates=tuple(proposed.items()),
prior_full_profile_sha256=old.full_profile_sha256,
full_profile_sha256=full_profile_sha256(BASE, proposed),
)
p2 = replace(p, sequence=2, parameters=parameters_for(names), coefficients=(0.004,), effect_envelope=envelope)
v2 = replace(v, profile=p2)
objective = EffectObjective('friction.left', names, envelope.trial_anchor, SOURCE)
next_owner = EffectOwner(
p.identity,
objective,
selected_baseline_revision=BASE,
physical_model_revision='physical-model',
original_anchor=envelope.replay_anchor(),
applied_full=before,
)
context2 = dict(context, current_full_profile_sha256=old.full_profile_sha256)
next_owner.prepare(Admission(p2, NOW + 10_000_000, True, False, True, v2), active=True, current_context=context2)
assert next_owner.trace.before == tuple(before.items())
assert next_owner.applied_full['ff_gain_left'] >= before['ff_gain_left']
assert 0 < next_owner.applied_full['turn_in_threshold_reduction_left'] <= 0.005 * 0.01
assert all(abs(next_owner.applied_full[n] - before[n]) <= 0.005 * 0.01 + 1e-12 for n in NAMES)
stale = EffectOwner(
p.identity, objective, selected_baseline_revision=BASE, physical_model_revision='physical-model', original_anchor=envelope.replay_anchor()
)
with pytest.raises(ValueError):
stale.prepare(Admission(p2, NOW + 10_000_000, True, False, True, v2), active=True, current_context=context)
assert stale.source is None