mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
521 lines
30 KiB
Python
521 lines
30 KiB
Python
"""Optional learner plumbing; never imported by controller realtime loops."""
|
|
from dataclasses import asdict
|
|
import base64
|
|
import math
|
|
|
|
from openpilot.starpilot.flm.source_plant_fit import PROTOCOL, CONTEXT_VERSION, source_binding, experiment_context
|
|
|
|
|
|
def enable(adapter, clock_contract, *, protocol=PROTOCOL):
|
|
from openpilot.starpilot.flm.original_source_capture import OriginalSourceClockContract
|
|
if (not getattr(adapter,'event_collection',False) or adapter.replay_version != 3 or
|
|
clock_contract is not None and not isinstance(clock_contract,OriginalSourceClockContract)):
|
|
raise ValueError('explicit registered event/source clock plant contract')
|
|
if clock_contract is not None:
|
|
clock_contract.validate()
|
|
from openpilot.starpilot.flm.feedback_replay import PROTOCOL as FEEDBACK_PROTOCOL
|
|
if protocol not in (PROTOCOL,FEEDBACK_PROTOCOL):
|
|
raise ValueError('explicit original plant protocol')
|
|
if protocol == FEEDBACK_PROTOCOL:
|
|
from openpilot.starpilot.flm.feedback_archive import OriginalFeedbackArchive
|
|
adapter.original_feedback_archive = OriginalFeedbackArchive()
|
|
adapter.source_plant_protocol = protocol
|
|
adapter.source_plant_clock = clock_contract
|
|
adapter.source_plant_receipt = None
|
|
adapter.source_plant_binding = None
|
|
adapter.source_plant_submitted_epoch = None
|
|
adapter.source_plant_submitted_contexts = {}
|
|
return adapter
|
|
|
|
|
|
def start_original_capture(collector):
|
|
"""Source-pin/clock unavailability denies learning without killing producer."""
|
|
adapter = collector.adapter
|
|
try:
|
|
collector.enable_original_source_capture(clock_contract=adapter.source_plant_clock)
|
|
except (OSError,ValueError) as error:
|
|
adapter.source_plant_capture_error = 'original_source_clock_contract_unavailable'
|
|
from openpilot.starpilot.flm.source_observation_report import record_refusal
|
|
import time
|
|
record_refusal(collector, None, time.monotonic_ns(), adapter.source_plant_capture_error, error=error)
|
|
adapter.current_physical_valid = False
|
|
adapter.last_physical_ns = collector.last_qualified_response = 0
|
|
return False
|
|
adapter.source_plant_capture_error = None
|
|
return True
|
|
|
|
|
|
def observe(sm, cp, collector, now_ns, current_native):
|
|
from openpilot.starpilot.flm.runtime_adapter_registry import original_source_pose_observer
|
|
from openpilot.starpilot.flm.original_source_capture import OriginalSourcePose
|
|
from openpilot.starpilot.flm.torque_eligibility import consumed_sources_current
|
|
from openpilot.starpilot.flm.torque_emission_replay import delivered
|
|
|
|
adapter = collector.adapter
|
|
def revoke():
|
|
adapter.current_physical_valid = False
|
|
adapter.last_physical_ns = collector.last_qualified_response = 0
|
|
if not current_native:
|
|
from openpilot.starpilot.flm.source_observation_report import record_refusal
|
|
record_refusal(collector, sm, now_ns, 'current_native_unavailable')
|
|
revoke()
|
|
return
|
|
row = original_source_pose_observer(sm,cp,collector,now_ns,distinguish_pending=True)
|
|
from openpilot.starpilot.flm.physical_observation import PendingPhysical
|
|
if type(row) is PendingPhysical and row.fresh(now_ns) and not row.context_changed:
|
|
return # Keep the ORIGINAL prior receipt; do not renew its timestamp.
|
|
if not isinstance(row,OriginalSourcePose):
|
|
revoke()
|
|
return
|
|
revoke()
|
|
collector.original_source_pose(row,now_ns)
|
|
live = getattr(collector, 'live_tracking', None)
|
|
live_lag = live.optimizer.lag_ns if live is not None else getattr(collector, 'live_response_lag_ns', None)
|
|
collector.live_response_pair = None
|
|
if type(live_lag) is int and 0 <= live_lag <= 500_000_000:
|
|
if live is not None:
|
|
collector.live_response_pair = None
|
|
pair = live.original_pose_pair(collector.ready, row)
|
|
if pair is not None:
|
|
collector.live_response_pair = (*pair, row)
|
|
else:
|
|
lower = [(c,o) for c,o in collector.ready if o.apply_ns <= row.source_lower_ns-live_lag]
|
|
upper = [(c,o) for c,o in collector.ready if o.apply_ns <= row.source_upper_ns-live_lag]
|
|
if lower and upper and lower[-1][1].apply_ns == upper[-1][1].apply_ns:
|
|
collector.live_response_pair = (*lower[-1], row)
|
|
if live is not None:
|
|
live.observe_original_pose(row, collector, now_ns=now_ns, current_native=current_native)
|
|
model, binding = adapter.model, adapter.source_plant_binding
|
|
if model is None or binding is None or adapter.source_plant_receipt is None:
|
|
return
|
|
from openpilot.starpilot.flm.runtime_adapter_registry import digest
|
|
if (row.identity != binding['identity'] or row.source_epoch != binding['source_epoch'] or
|
|
row.baseline_revision != binding['baseline_revision'] or row.calibration != binding['calibration_generation'] or
|
|
row.native_identity != binding['native_identity'] or digest((row.source_clock_contract,row.context[7])) != binding['source_clock_contract_sha256'] or
|
|
digest(row.controller_revision) != binding['controller_revision'] or
|
|
digest((row.context[2],row.context[10],list(row.context[11:]))) != binding['vehicle_model_generation'] or
|
|
model.context != digest(collector.physical_context) or
|
|
not 0 < row.source_lower_ns <= row.source_upper_ns <= now_ns or now_ns-row.source_lower_ns > 100_000_000):
|
|
return
|
|
lower = tuple((control,output) for control,output in collector.ready if output.apply_ns <= row.source_lower_ns-model.lag_ns)
|
|
upper = tuple((control,output) for control,output in collector.ready if output.apply_ns <= row.source_upper_ns-model.lag_ns)
|
|
if not lower or not upper or lower[-1][1].apply_ns != upper[-1][1].apply_ns:
|
|
return
|
|
control,output = lower[-1]
|
|
if (row.source_upper_ns-model.lag_ns-output.apply_ns > 30_000_000 or
|
|
not consumed_sources_current(control,output) or not adapter.replay.applied_matches(control,output) or
|
|
not output.native_allowed or output.limited or output.override or output.fault or not output.valid or
|
|
control.native_required and not control.native_allowed or control.override or control.fault or not control.valid or control.manual or
|
|
not control.enabled or not control.active or control.saturated or control.model_wobble or control.controller_chatter or
|
|
min(control.control_ns,output.apply_ns,row.mono_ns) <= adapter.model_cutoff_ns):
|
|
return
|
|
command = -delivered(output)
|
|
measured = row.speed_mps*row.yaw_rate-9.81*math.sin(row.roll_rad)
|
|
bounds = adapter.model_speed_bounds
|
|
valid = (bounds is not None and bounds[0] <= row.speed_mps <= bounds[1] and
|
|
model.command_low <= command <= model.command_high and
|
|
abs(model.slope*command+model.intercept-measured) <= max(.01,3*model.heldout_rmse))
|
|
if valid:
|
|
adapter.current_physical_valid = True
|
|
adapter.last_physical_ns = collector.last_qualified_response = row.mono_ns
|
|
|
|
|
|
MIN_NORMAL_JOB_AGE_NS = 60_000_000_000 # Fixed before data/fit outcomes; source epoch is100s.
|
|
NORMAL_JOB_ATTEMPT_SPACING_NS = 80_000_000_000
|
|
|
|
|
|
def _current_fit_pair_reason(collector, now_ns, *, physical_binding=None):
|
|
"""Cheap latest-pair availability only; no history search or fit authority.
|
|
|
|
The child/current validators remain independent. A known-unqualified latest
|
|
endpoint must not consume this fixed experiment's one fitting attempt.
|
|
"""
|
|
from openpilot.starpilot.flm.fullrate_collector import ControlEvidence, AppliedEvidence, MAX_AGE_NS
|
|
from openpilot.starpilot.flm.torque_eligibility import consumed_sources_current, exact_unclipped_pair
|
|
try:
|
|
control, output = collector.ready[-1]
|
|
if (type(control) is not ControlEvidence or type(output) is not AppliedEvidence or
|
|
type(now_ns) is not int or now_ns <= 0):
|
|
return 'invalid_current_pair'
|
|
if not output.apply_ns <= now_ns <= output.apply_ns+MAX_AGE_NS or not consumed_sources_current(control,output) or output.control_ns != control.control_ns:
|
|
return 'current_pair_not_fresh'
|
|
if (control.identity != collector.adapter.identity or control.baseline_revision != collector.adapter.baseline_revision or
|
|
not 0 < control.source_receipt_ns <= control.control_ns <= now_ns <= control.source_receipt_ns+500_000_000):
|
|
return 'current_pair_source_mismatch'
|
|
observed_clip = False
|
|
if physical_binding is not None and output.limited:
|
|
from openpilot.starpilot.flm.live_trial_contract import LiveTrialBinding
|
|
from openpilot.starpilot.flm.live_tracking_response import verified_clipped_input
|
|
if type(physical_binding) is LiveTrialBinding:
|
|
observed_clip = verified_clipped_input(collector.adapter.replay, control, output, physical_binding)
|
|
if (not control.enabled or control.manual or not control.active or not control.valid or control.override or control.fault or
|
|
control.saturated or control.model_wobble or control.controller_chatter or
|
|
control.limited and not exact_unclipped_pair(control,output) and not observed_clip):
|
|
return 'current_control_unqualified'
|
|
if (not output.valid or not output.active or output.override or output.fault or output.limited and not observed_clip or not output.native_allowed):
|
|
return 'current_output_unqualified'
|
|
if control.native_required and (not control.native_allowed or not control.native_identity or
|
|
not 0 < control.native_observed_ns <= control.control_ns <= output.apply_ns <= now_ns <= control.native_expires_ns or
|
|
control.native_expires_ns-control.native_observed_ns > 200_000_000):
|
|
return 'current_native_unqualified'
|
|
if not control.native_required and (control.native_allowed or control.native_identity or
|
|
(control.native_observed_ns,control.native_expires_ns) != (0,0)):
|
|
return 'current_native_unqualified'
|
|
return None
|
|
except (AttributeError,IndexError,KeyError,TypeError,ValueError,OverflowError):
|
|
return 'invalid_current_pair'
|
|
|
|
|
|
def snapshot(collector,now_ns):
|
|
adapter,capture = collector.adapter,collector.original_source_capture
|
|
if capture is None:
|
|
adapter.snapshot_readiness = {'reason':'original_source_capture_unavailable'}
|
|
return None
|
|
if (adapter.envelope is None or not collector.ready or not capture.rows or
|
|
adapter.source_plant_submitted_epoch == capture.epoch or
|
|
collector.last_fit and now_ns-collector.last_fit < NORMAL_JOB_ATTEMPT_SPACING_NS):
|
|
return None
|
|
current_decline = _current_fit_pair_reason(collector,now_ns)
|
|
if current_decline is not None:
|
|
adapter.snapshot_readiness = {'reason':current_decline,'childQualification':'not_yet_evaluated'}
|
|
return None
|
|
checkpoints = tuple(stamp for stamp,_ in adapter.replay.checkpoints if stamp <= capture.rows[0].mono_ns)
|
|
if not checkpoints:
|
|
adapter.snapshot_readiness = {'reason':'plant_original_prefix_checkpoint_unavailable'}
|
|
return None
|
|
start = max(checkpoints)
|
|
if now_ns-start < MIN_NORMAL_JOB_AGE_NS:
|
|
adapter.snapshot_readiness = {'reason':'plant_fixed_cohort_still_collecting',
|
|
'elapsedNs':now_ns-start,'requiredNs':MIN_NORMAL_JOB_AGE_NS}
|
|
return None
|
|
# Full original geometry retains the fixed attempt spacing. Its counts
|
|
# are availability only; the child independently reconstructs every join.
|
|
geometry_context = (capture.epoch,getattr(capture,'epoch_start_ns',0),
|
|
getattr(capture,'epoch_cutoff_ns',0),getattr(collector,'context',None),
|
|
getattr(adapter.envelope,'prior_full_profile_sha256',None))
|
|
if getattr(collector,'source_plant_geometry_context',None) == geometry_context:
|
|
last_check = getattr(collector,'source_plant_geometry_check_ns',0)
|
|
if last_check and now_ns-last_check < 1_000_000_000:
|
|
return None
|
|
collector.source_plant_geometry_context = geometry_context
|
|
collector.source_plant_geometry_check_ns = now_ns
|
|
records = tuple(frame for frame in adapter.replay.records if frame.control_ns >= start)
|
|
if not records or len(records) > 12000:
|
|
adapter.snapshot_readiness = {'reason':'plant_original_prefix_frame_budget'}
|
|
return None
|
|
from openpilot.starpilot.flm.event_storage import source_windows
|
|
from openpilot.starpilot.flm.event_windows import whole_event_windows
|
|
from openpilot.starpilot.flm.source_plant_fit import FIRST_SLOT_NS,BLOCK_NS,PURGE_NS
|
|
from types import SimpleNamespace
|
|
view = SimpleNamespace(records=records,replay_windows=(),_frame_context=adapter.replay._frame_context)
|
|
view.replay_windows = source_windows(view)
|
|
cutoff = start+FIRST_SLOT_NS+7*(BLOCK_NS+PURGE_NS)+BLOCK_NS
|
|
count,pending,last_window = 0,0,None
|
|
complete_goal_windows = 0
|
|
for window,first,last,_ in whole_event_windows(view):
|
|
if first <= cutoff:
|
|
continue
|
|
if window != last_window:
|
|
pending = 0
|
|
last_window = window
|
|
points = sum(first <= row.mono_ns <= last for row in capture.rows)
|
|
if points > 240:
|
|
pending = 0
|
|
continue
|
|
# The child requires nine comparable subtle cycles (or three large
|
|
# maneuvers), independently of eight statistical storage bundles. Wait
|
|
# for enough complete original geometry before consuming this epoch's
|
|
# sole attempt. This is availability only: error/excitation/quality and
|
|
# train/heldout lineage remain fresh child qualifications.
|
|
if points >= 4:
|
|
complete_goal_windows += 1
|
|
if pending+points > 240:
|
|
pending = 0
|
|
pending += points
|
|
if pending >= 40:
|
|
count += 1
|
|
pending = 0
|
|
if count < 8 or complete_goal_windows < 9:
|
|
adapter.snapshot_readiness = {'reason':'plant_later_original_goal_geometry',
|
|
'candidateBundles':count,'requiredBundles':8,'completeGoalWindows':complete_goal_windows,
|
|
'requiredCompleteGoalWindows':9,'childQualification':'not_yet_evaluated'}
|
|
return None
|
|
# Geometry availability is not a submitted/failed experiment. Only a ready
|
|
# export attempt starts the existing fit cooldown; later original geometry
|
|
# in this fixed epoch may complete without waiting beyond its100s cutoff.
|
|
collector.last_fit = now_ns
|
|
collector.snapshot_attempts += 1
|
|
try:
|
|
wire = adapter.original_source_packet(collector,((start,records[-1].control_ns),),now_ns)
|
|
return snapshot_from_packet(collector,wire,now_ns)
|
|
except (AttributeError,KeyError,TypeError,ValueError,OverflowError) as error:
|
|
adapter.snapshot_readiness = {'reason':'plant_snapshot_unavailable','detail':str(error)}
|
|
return None
|
|
|
|
|
|
SCHEDULE_VERSION = 'original-source-experiment-objective-v1'
|
|
|
|
|
|
def fit_schedule(collector):
|
|
"""Fixed original experiment ordinal, independent of readiness/fit outcomes."""
|
|
from openpilot.starpilot.flm.learner_factory import collection_keys
|
|
capture = collector.original_source_capture
|
|
if capture is None or not collector.ready or not capture.rows or not capture.epoch_start_ns:
|
|
return None
|
|
keys = tuple(collection_keys(collector.ready[-1][0]))
|
|
if (type(capture.epoch) is not int or capture.epoch < 0 or
|
|
not 0 < capture.epoch_start_ns < capture.epoch_cutoff_ns or
|
|
capture.epoch_cutoff_ns-capture.epoch_start_ns > 100_000_000_000 or
|
|
not 1 <= len(keys) <= 12 or len(set(keys)) != len(keys)):
|
|
raise ValueError('original source experiment objective registry')
|
|
return {'version':SCHEDULE_VERSION,'epoch':capture.epoch,
|
|
'start_ns':capture.epoch_start_ns,'cutoff_ns':capture.epoch_cutoff_ns,
|
|
'registered_keys':keys,'objective_key':keys[capture.epoch % len(keys)]}
|
|
|
|
|
|
def fit_key(collector):
|
|
schedule = fit_schedule(collector)
|
|
return None if schedule is None else schedule['objective_key']
|
|
|
|
|
|
def submission_key(snapshot,collector,capture_key):
|
|
if getattr(collector.adapter,'source_plant_protocol',None) is None:
|
|
return capture_key
|
|
key = tuple(snapshot.get('objective_key',()))
|
|
if key != fit_key(collector):
|
|
raise ValueError('original source experiment submitted objective registry')
|
|
return key
|
|
|
|
|
|
def snapshot_from_packet(collector,packet_wire,now_ns):
|
|
"""Select the original experiment's key only around the job transport."""
|
|
schedule = fit_schedule(collector)
|
|
if schedule is None:
|
|
return None
|
|
adapter = collector.adapter
|
|
capture_key = adapter.key
|
|
adapter.select_objective(schedule['objective_key'])
|
|
try:
|
|
return _snapshot_from_packet(collector,packet_wire,now_ns,schedule)
|
|
finally:
|
|
adapter.select_objective(capture_key)
|
|
|
|
|
|
def _snapshot_from_packet(collector,packet_wire,now_ns,schedule,*,response_only=False):
|
|
"""Common lossless worker transport for an already exported ORIGINAL packet.
|
|
|
|
This does no fit-readiness or admission declaration. The normal parent calls
|
|
it only after its predeclared readiness/cadence gates.
|
|
"""
|
|
from openpilot.starpilot.flm.controller_replay import pack_primitive_snapshot,MAX_FIT_RAW_BYTES
|
|
from openpilot.starpilot.flm.source_plant_pipeline import replay_data
|
|
import pickle
|
|
adapter,capture = collector.adapter,collector.original_source_capture
|
|
if type(response_only) is not bool:
|
|
raise ValueError('explicit response-only transport purpose')
|
|
try:
|
|
from openpilot.starpilot.flm.original_source_capture import (
|
|
unpack_source_packet, SOURCE_PACKET_VERSION, SOURCE_PACKET_ENCODING, NORMALIZED_SOURCE_VERSION,
|
|
)
|
|
if response_only:
|
|
# This parent owns a freshly encoded, read-only transport graph. Do not
|
|
# expand every shared container just to intern it again. The response
|
|
# worker still makes its independent copy and verifies ALL original data.
|
|
from openpilot.starpilot.flm.controller_replay import unpack_primitive_snapshot
|
|
from openpilot.starpilot.flm.primitive_source_memo import _logical_limits
|
|
from openpilot.starpilot.flm.normalized_trace_archive import reserve_for_packet
|
|
packet = unpack_primitive_snapshot(packet_wire)
|
|
if (type(packet) is not dict or packet.get('version') not in (SOURCE_PACKET_VERSION, NORMALIZED_SOURCE_VERSION) or
|
|
packet.get('encoding') != SOURCE_PACKET_ENCODING or packet.get('qualified') is not False):
|
|
raise ValueError('unsupported original source packet codec/version')
|
|
_logical_limits((packet, bytes(reserve_for_packet(packet))))
|
|
context = None # Computed independently by the worker; never admission.
|
|
else:
|
|
packet = unpack_source_packet(packet_wire)
|
|
# Trial/restore retains its exact pending experiment binding unchanged.
|
|
from openpilot.starpilot.flm.event_controller_replay import EventControllerReplay
|
|
template = EventControllerReplay(adapter.replay,adapter.event_objective,adapter.envelope.replay_anchor())
|
|
binding = source_binding(packet,template)
|
|
context = experiment_context(packet,binding)
|
|
envelope = adapter.envelope
|
|
from openpilot.starpilot.flm.feedback_replay import PROTOCOL as FEEDBACK_PROTOCOL,EVENT_VERSION
|
|
feedback_job = adapter.source_plant_protocol == FEEDBACK_PROTOCOL
|
|
operation,version = 'trial',EVENT_VERSION if feedback_job else 3
|
|
if adapter.restore_envelope is not None and not response_only:
|
|
if feedback_job and adapter.restore_version != 8 or not feedback_job and adapter.restore_version == 8:
|
|
raise ValueError('feedback restore requires explicit version8')
|
|
envelope = adapter.envelope.for_trial(adapter.event_objective.names).restore_from_history(adapter.optimizer_prior)
|
|
operation,version = 'restore',adapter.restore_version
|
|
from openpilot.starpilot.flm.clipping_quality import identification_for_quality,restore_policy,FIXED_MAP_IDENTIFICATION
|
|
payload = {'version':1,'family':adapter.command_family,'identity':adapter.identity,
|
|
'plant_protocol':adapter.source_plant_protocol,'source_packet':packet,'physical_context':context,
|
|
'event_version':version,'event_operation':operation,'event_objective':asdict(adapter.event_objective),
|
|
'effect_envelope':asdict(envelope),'objective':asdict(adapter.objective),
|
|
'event_clipping_quality':adapter.clipping_quality,
|
|
'event_identification_policy':identification_for_quality(adapter.clipping_quality) if operation=='trial' else FIXED_MAP_IDENTIFICATION,
|
|
'now_ns':now_ns,'sequence':collector.sequence+1,
|
|
'prior':tuple(dict(envelope.prior_coordinates)[name] for name in adapter.event_objective.names),
|
|
'objective_key':adapter.key,'fit_schedule':schedule}
|
|
if feedback_job:
|
|
from openpilot.starpilot.flm.event_mean_evidence import VERSION as MEAN_VERSION
|
|
from openpilot.starpilot.flm.feedback_archive import archive_binding
|
|
feedback_wire = packet['feedback_observations']
|
|
from openpilot.starpilot.flm.candidate_feedback import CLOSED_POLICY
|
|
payload['candidate_feedback_policy'] = CLOSED_POLICY
|
|
if operation == 'trial':
|
|
payload['event_mean_version'] = MEAN_VERSION
|
|
feedback_submission = None if response_only else (archive_binding(packet),feedback_wire['digest'].hex(),MEAN_VERSION,CLOSED_POLICY)
|
|
else:
|
|
from openpilot.starpilot.flm.clipping_quality import RESTORE_FEEDBACK_STATISTICS
|
|
payload['event_restore_statistics'] = RESTORE_FEEDBACK_STATISTICS
|
|
feedback_submission = (archive_binding(packet),feedback_wire['digest'].hex(),RESTORE_FEEDBACK_STATISTICS,CLOSED_POLICY)
|
|
else:
|
|
feedback_submission = None
|
|
if operation == 'restore':
|
|
payload['event_restore_policy'] = restore_policy(version)
|
|
from opendbc.car.steering_projection import projection_to_dict
|
|
if not response_only:
|
|
# Trial/restore jobs require their current endpoints. Response-only
|
|
# bootstrap independently verifies its frozen original experiment and
|
|
# never issues a profile or current permission; its worker uses neither.
|
|
control,output = collector.ready[-1]
|
|
from openpilot.starpilot.flm.normalized_trace_archive import normalized_packet,current_record
|
|
payload['control'] = current_record(control,packet['trace_archive']) if normalized_packet(packet) else asdict(control)
|
|
payload['output'] = {**asdict(output),'projection':projection_to_dict(output.projection)}
|
|
replay = replay_data(packet,objective=adapter.objective,identity=adapter.identity,baseline_revision=adapter.baseline_revision)
|
|
payload_raw_bytes = len(pickle.dumps(payload,protocol=5))
|
|
replay_raw_bytes = len(pickle.dumps(replay,protocol=5))
|
|
if payload_raw_bytes+replay_raw_bytes > MAX_FIT_RAW_BYTES:
|
|
raise ValueError('plant aggregate original raw worker byte bound')
|
|
if feedback_job:
|
|
from openpilot.starpilot.flm.primitive_source_memo import intern_primitive_graph
|
|
from openpilot.starpilot.flm.normalized_trace_archive import reserve_for_packet
|
|
reserve = reserve_for_packet(packet)
|
|
if response_only:
|
|
# Source packet sharing is already canonical. Preserve it and validate
|
|
# the SAME logical expansion/depth/reservation caps without rebuilding.
|
|
_logical_limits((payload,bytes(reserve)))
|
|
else:
|
|
payload = intern_primitive_graph((payload,bytes(reserve)))[0] if reserve else intern_primitive_graph(payload)
|
|
packed = pack_primitive_snapshot(payload) # Existing raw/IPC caps unchanged.
|
|
adapter.source_plant_export_cost = {'sourceWireBytes':len(packet_wire),'payloadRawBytes':payload_raw_bytes,
|
|
'derivedReplayRawBytes':replay_raw_bytes,'aggregateRawBytes':payload_raw_bytes+replay_raw_bytes,'workerCompressedBytes':len(packed)}
|
|
wrapper = {'version':1,'family':adapter.command_family,'snapshot_b64':base64.b64encode(packed).decode('ascii'),
|
|
'objective_key':tuple(adapter.key)}
|
|
if len(wrapper['snapshot_b64']) > 6*1024*1024:
|
|
raise ValueError('plant existing fit wrapper bound')
|
|
except (AttributeError,KeyError,TypeError,ValueError,OverflowError) as error:
|
|
adapter.snapshot_readiness = {'reason':'plant_snapshot_unavailable','detail':str(error)}
|
|
return None
|
|
# Pending calibration is not the active model context. A failed/new attempt
|
|
# must not switch off an independently fresh previously accepted correction.
|
|
if response_only:
|
|
collector.sequence += 1
|
|
return wrapper
|
|
import weakref
|
|
adapter.source_plant_collector = weakref.ref(collector)
|
|
adapter.source_plant_pending_context = context
|
|
collector.sequence += 1
|
|
adapter.source_plant_pending_epoch = capture.epoch
|
|
adapter.source_plant_pending_feedback = feedback_submission
|
|
adapter.snapshot_readiness = {'reason':'snapshot_ready','plantProtocol':adapter.source_plant_protocol,'childQualification':'not_yet_evaluated'}
|
|
return wrapper
|
|
|
|
|
|
def submitted(collector):
|
|
adapter = collector.adapter
|
|
adapter.source_plant_submitted_epoch = adapter.source_plant_pending_epoch
|
|
contexts = adapter.source_plant_submitted_contexts
|
|
contexts[adapter.source_plant_pending_context] = adapter.source_plant_pending_feedback or True
|
|
while len(contexts) > 14: # Same bound as the existing cached profile registry.
|
|
contexts.pop(next(iter(contexts)))
|
|
|
|
|
|
def install(adapter, report, physical_context, *, commit=False):
|
|
from openpilot.starpilot.flm.runtime_adapter_registry import digest
|
|
protocol = adapter.source_plant_protocol
|
|
if report.get('plant_protocol') != protocol or tuple(report.get('physical_context',())) != tuple(physical_context):
|
|
return False
|
|
expected_context = ('original-source-feedback-mean-context-v1' if protocol ==
|
|
'chronological-source-feedback-mean-fit-v1' else CONTEXT_VERSION)
|
|
if not physical_context or physical_context[0] != expected_context:
|
|
return False
|
|
if tuple(physical_context) not in adapter.source_plant_submitted_contexts:
|
|
return False
|
|
from openpilot.starpilot.flm.feedback_replay import PROTOCOL as FEEDBACK_PROTOCOL,EVENT_VERSION
|
|
if protocol == FEEDBACK_PROTOCOL:
|
|
from openpilot.starpilot.flm.event_mean_evidence import VERSION as MEAN_VERSION
|
|
offered = report.get('feedback_evidence')
|
|
submitted = adapter.source_plant_submitted_contexts[tuple(physical_context)]
|
|
basis = report.get('event_mean_basis')
|
|
from openpilot.starpilot.flm.clipping_quality import RESTORE_FEEDBACK_STATISTICS
|
|
restoring = report.get('event_version') == 8
|
|
marker = RESTORE_FEEDBACK_STATISTICS if restoring else MEAN_VERSION
|
|
from openpilot.starpilot.flm.candidate_feedback import CLOSED_POLICY,PROOF_VERSION,report_policy_matches
|
|
closed = type(submitted) is tuple and len(submitted) == 4 and submitted[3] == CLOSED_POLICY
|
|
expected_fields = {'protocol','binding_digest','archive_digest','verified_digest','known_rows','context_rows'}
|
|
if closed:
|
|
expected_fields |= {'candidate_feedback_policy','candidate_feedback_proof_version'}
|
|
if (type(submitted) is not tuple or len(submitted) not in (3,4) or len(submitted) == 4 and not closed or
|
|
report.get('event_version') not in (EVENT_VERSION,8) or
|
|
not report_policy_matches(submitted,offered) or type(offered) is not dict or set(offered) != expected_fields or
|
|
((offered['binding_digest'],offered['archive_digest'],marker,CLOSED_POLICY) if closed else
|
|
(offered['binding_digest'],offered['archive_digest'],marker)) != submitted or
|
|
closed and (offered['candidate_feedback_policy'] != CLOSED_POLICY or
|
|
offered['candidate_feedback_proof_version'] != PROOF_VERSION) or
|
|
offered['protocol'] != FEEDBACK_PROTOCOL or type(offered['verified_digest']) is not str or len(offered['verified_digest']) != 64 or
|
|
type(offered['known_rows']) is not int or not 1 <= offered['known_rows'] <= 12000 or
|
|
type(offered['context_rows']) is not int or not 0 <= offered['context_rows'] <= 1 or
|
|
(restoring and (adapter.restore_version != 8 or report.get('event_restore_statistics') != marker or basis is not None) or
|
|
not restoring and (type(basis) is not dict or basis.get('version') != MEAN_VERSION))):
|
|
return False
|
|
elif 'feedback_evidence' in report or 'event_mean_basis' in report:
|
|
return False
|
|
receipt = report.get('plant_identification')
|
|
binding = report.get('plant_binding')
|
|
if (type(receipt) is not dict or type(binding) is not dict or
|
|
receipt.get('receipt_schema') != 'compact-source-plant-receipt-v1' or
|
|
receipt.get('status') != 'physical_affine_test_passed' or not receipt.get('model_receipt_digest') or
|
|
receipt.get('binding_digest') != physical_context[1] or digest(binding) != physical_context[1] or
|
|
receipt.get('cutoff_ns') != report.get('model_cutoff_ns') or
|
|
receipt['decision']['lag_ns'] != report['model']['lag_ns'] or
|
|
report['model']['context'] != digest(physical_context)):
|
|
return False
|
|
from openpilot.starpilot.flm import plant_lag
|
|
decision = receipt['decision']
|
|
declaration = {key:value for key,value in decision.items() if key != 'compact_decision_sha256'}
|
|
expected_receipt = plant_lag.digest({'protocol':plant_lag.PHYSICAL_PROTOCOL,'experiment':receipt['experiment_digest'],
|
|
'decision':decision['digest'],'heldout':receipt['heldout_blocks'],'cutoff_ns':receipt['cutoff_ns'],
|
|
'binding':receipt['binding_digest']})
|
|
if (decision.get('protocol') != plant_lag.PHYSICAL_PROTOCOL or decision.get('compact_decision_sha256') != plant_lag.digest(declaration) or
|
|
receipt['model_receipt_digest'] != expected_receipt or
|
|
tuple(row[0] for row in decision['training_scores']) != plant_lag.LAGS_NS or
|
|
any(not 0 <= error <= .05 or outside != 0 for _,error,outside in receipt['heldout_blocks']) or
|
|
any(report['model'][name] != decision[name] for name in ('slope','intercept','command_low','command_high'))):
|
|
return False
|
|
if commit:
|
|
collector = adapter.source_plant_collector()
|
|
if collector is None:
|
|
return False
|
|
adapter.source_plant_receipt = receipt
|
|
adapter.source_plant_binding = binding
|
|
collector.physical_context = tuple(physical_context)
|
|
return True
|
|
|
|
|
|
def installed_report_context_current(adapter,report,physical_context):
|
|
"""Recognize only the exact report installed while awaiting fresh admission.
|
|
|
|
The original submission token stays immutable. Installation switches active
|
|
model context, so that same pending report may survive to the next ORIGINAL
|
|
pose without pretending its submission used the new context.
|
|
"""
|
|
from openpilot.starpilot.flm.runtime_adapter_registry import canonical_physical_context
|
|
context = tuple(report.get('physical_context',()))
|
|
return (getattr(adapter,'source_plant_protocol',None) in (PROTOCOL,
|
|
'chronological-source-feedback-mean-fit-v1') and
|
|
report.get('plant_protocol') == adapter.source_plant_protocol and context == physical_context and
|
|
adapter.model is not None and adapter.model.context == canonical_physical_context(context) and
|
|
adapter.source_plant_receipt is not None and adapter.source_plant_receipt == report.get('plant_identification') and
|
|
adapter.source_plant_binding == report.get('plant_binding'))
|