Files
StarPilot/openpilot/starpilot/flm/live_tracking_bootstrap_cohorts.py
T
2026-10-21 23:28:39 -05:00

582 lines
24 KiB
Python

"""Outcome-blind scheduling of a FIRST complete original calibration cohort.
This is source/command availability, never plant identification or permission.
Every candidate is an actual captured checkpoint, ordered by source clock. All
response yaw/roll/error/residual values are deliberately absent from selection.
"""
from bisect import bisect_left, bisect_right
import math
import pickle
from typing import cast
VERSION = 'first-complete-physical-feedback-cohort-v7'
MAX_CHECKPOINTS = 128
CHECK_INTERVAL_NS = 1_000_000_000
def _decline(diagnostics, reason):
if type(diagnostics) is dict:
diagnostics['reason'] = reason
return None
def _literal(value):
kind = type(value)
if kind in (type(None), bool, int, str, bytes):
return value
if kind is float and math.isfinite(value):
return value
if kind is tuple:
return tuple(_literal(item) for item in value)
raise ValueError('closed source-only cohort scheduling value required')
def source_quality_keys(frames, poses, emissions, checkpoints, controls, *, diagnostics=None):
"""Fresh exact values invalidate scheduling memo; never reads a response.
The memo avoids rescanning every sealed cohort, NOT original source/native
verification. Its keys contain all fields that scheduling reads, with Float64
bits preserved by pickle5. Unknown leaves are rejected before pickle callbacks.
"""
from openpilot.starpilot.flm.controller_replay import ReplayFrame, Snapshot
from openpilot.starpilot.flm.original_source_capture import OriginalSourcePose
from openpilot.starpilot.flm.fullrate_collector import ControlEvidence
from openpilot.starpilot.flm.torque_emission_replay import Emission
from opendbc.car.steering_projection import TorqueProjection
if (
len(frames) > 12000
or len(poses) > 5120
or len(emissions) > 12000
or any(type(row) is not ReplayFrame for row in frames)
or any(type(row) is not OriginalSourcePose for row in poses)
or any(type(row) is not Emission or type(row.witness) is not TorqueProjection for row in emissions)
or len(controls) > 12000
or any(type(row) is not ControlEvidence for row in controls)
):
raise ValueError('exact bounded original cohort source')
if len(checkpoints) > MAX_CHECKPOINTS:
_decline(diagnostics, 'checkpoint_count_exceeds_128_bound')
raise ValueError('genuine bounded checkpoint metadata')
if any(type(row) is not tuple or len(row) != 2 or type(row[1]) is not Snapshot for row in checkpoints):
_decline(diagnostics, 'checkpoint_metadata_type_unavailable')
raise ValueError('genuine bounded checkpoint metadata')
raw = (
tuple((row.control_ns, row.healthy, row.manual, row.frame_sequence) for row in frames),
tuple(
(
row.mono_ns,
row.source_lower_ns,
row.source_upper_ns,
row.completed_ns,
row.speed_mps,
row.valid,
row.native_allowed,
row.native_required,
row.identity,
row.source_epoch,
row.baseline_revision,
row.controller_revision,
row.calibration,
row.native_identity,
row.context,
)
for row in poses
),
tuple(
(
row.control_ns,
row.state_ns,
row.apply_ns,
tuple(row.witness),
row.valid,
row.active,
row.override,
row.fault,
row.limited,
row.native_allowed,
row.native_required,
row.identity,
row.source_epoch,
row.baseline_revision,
row.native_identity,
row.native_observed_ns,
row.native_expires_ns,
)
for row in emissions
),
tuple((stamp, snapshot.revision, snapshot.values) for stamp, snapshot in checkpoints),
tuple(
(
row.control_ns,
row.state_ns,
row.enabled,
row.active,
row.valid,
row.manual,
row.override,
row.fault,
row.identity,
row.source_epoch,
row.baseline_revision,
row.controller_revision,
row.native_identity,
row.native_required,
row.native_allowed,
row.native_observed_ns,
row.native_expires_ns,
row.vehicle_model_anchor,
row.saturated,
row.model_wobble,
row.controller_chatter,
row.limited,
row.source_receipt_ns,
row.domain,
row.stage_schema_revision,
row.replay_inputs,
row.requested,
)
for row in controls
),
)
keys = tuple(tuple(pickle.dumps(_literal(row), protocol=5) for row in group) for group in raw)
for stamps in (
tuple(row.control_ns for row in frames),
tuple(row.mono_ns for row in poses),
tuple(row.apply_ns for row in emissions),
tuple(row.control_ns for row in controls),
):
if any(type(value) is not int or value <= 0 for value in stamps) or any(right <= left for left, right in zip(stamps, stamps[1:], strict=False)):
raise ValueError('ordered original source cohort clocks')
if any(type(row.control_ns) is not int or row.control_ns <= 0 for row in emissions):
raise ValueError('original emitted command clock type')
if any(right.control_ns < left.control_ns for left, right in zip(emissions, emissions[1:], strict=False)):
raise ValueError('original emitted command clock regression')
return keys
def new_schedule_cache(old, token, keys):
"""Only fresh append-only exact-value source can retain examined anchors."""
if (
type(old) is dict
and old.get('token') == token
and type(old.get('keys')) is tuple
and len(old['keys']) == len(keys)
and type(old.get('examined')) is dict
and 'selected' in old
and all(len(new) >= len(before) and new[: len(before)] == before for new, before in zip(keys, old['keys'], strict=True))
):
return dict(old, keys=keys)
return {'token': token, 'keys': keys, 'examined': {}, 'selected': None}
def _directions(rows):
for positive in (True, False):
selected = [(slot, value) for slot, value in rows if (value > 0 if positive else value < 0)]
if len(selected) < 80:
return False
if sum(sum(slot == index for slot, _ in selected) >= 20 for index in range(8)) < 2:
return False
return True
def _command_quality(groups):
from openpilot.starpilot.flm.plant_lag import MIN_EXCITATION
train = tuple((slot, value) for slot, values in enumerate(groups[:4]) for value in values)
heldout = tuple((slot + 4, value) for slot, values in enumerate(groups[4:]) for value in values)
values = tuple(value for _, value in train)
mean = sum(values) / len(values)
variance = sum((value - mean) ** 2 for value in values) / len(values)
if variance < MIN_EXCITATION**2 or not _directions(train) or not _directions(heldout):
return None
low, high = min(values), max(values)
# Scheduling is availability only. Match the response worker's supported
# TRAINING domain instead of requiring every future input to lie inside it.
# Outside inputs neither widen that range nor count as supported evidence;
# the child still validates ALL original heldout errors and native/source data.
supported = tuple((slot, value) for slot, value in heldout if low <= value <= high)
if any(sum(slot == index for slot, _ in supported) < 40 for index in range(4, 8)) or not _directions(supported):
return None
return {'training_command_std': math.sqrt(variance), 'command_low': low, 'command_high': high}
def source_complete_groups(applies, commands, groups):
"""Input-only eligibility shared by parent scheduling and independent child.
Keep the fixed eight slot boundaries. An unavailable command excludes every
pose whose FULL all-lag lookback includes it. No response value is read; no
command is interpolated, restamped or made known by omitting it from a tape.
"""
from openpilot.starpilot.flm.plant_lag import LAGS_NS, JOIN_NS
gap_prefix, invalid_prefix = [0], [0]
for index, stamp in enumerate(applies):
gap_prefix.append(gap_prefix[-1] + int(index > 0 and stamp - applies[index - 1] > JOIN_NS))
invalid_prefix.append(invalid_prefix[-1] + int(commands[index] is None))
previous = [0] * len(LAGS_NS)
accepted = []
for group in groups:
rows = []
for row in group:
first = bisect_right(applies, row.source_lower_ns - LAGS_NS[-1]) - 1
last = bisect_right(applies, row.source_upper_ns) - 1
if (
first < 0
or last < first
or row.source_lower_ns - LAGS_NS[-1] - applies[first] > JOIN_NS
or gap_prefix[last + 1] - gap_prefix[first + 1]
or invalid_prefix[last + 1] - invalid_prefix[first]
):
continue
endpoints = []
for index, lag_ns in enumerate(LAGS_NS):
lower, upper = row.source_lower_ns - lag_ns, row.source_upper_ns - lag_ns
left, right = bisect_right(applies, lower) - 1, bisect_right(applies, upper) - 1
if left < 0 or left != right or upper - applies[left] > JOIN_NS or applies[left] <= previous[index]:
break
endpoints.append(applies[left])
if len(endpoints) == len(LAGS_NS):
rows.append(row)
previous = endpoints
accepted.append(tuple(rows))
return tuple(accepted)
def _common_command_source(applies, commands, groups):
filtered = source_complete_groups(applies, commands, groups)
return all(len(before) == len(after) for before, after in zip(groups, filtered, strict=True))
def quality_for_start(start_ns, *, frames, poses, emissions, controls, binding, now_ns, diagnostics=None, source_complete=False):
"""Fresh literal quality of eight fixed slots; no response values inspected."""
from openpilot.starpilot.flm.controller_replay import ReplayFrame
from openpilot.starpilot.flm.original_source_capture import OriginalSourcePose
from openpilot.starpilot.flm.fullrate_collector import ControlEvidence, AppliedEvidence
from openpilot.starpilot.flm.torque_eligibility import consumed_sources_current
from openpilot.starpilot.flm.runtime_adapter_registry import digest
from openpilot.starpilot.flm.torque_emission_replay import Emission
from openpilot.starpilot.flm.source_plant_fit import FIRST_SLOT_NS, BLOCK_NS, PURGE_NS
from openpilot.starpilot.flm.plant_lag import LAGS_NS, JOIN_NS
from openpilot.starpilot.flm.live_tracking_response import physical_calibration_generation
from opendbc.car.steering_projection import TorqueProjection, normalized_applied_command
end_ns = start_ns + FIRST_SLOT_NS + 7 * (BLOCK_NS + PURGE_NS) + BLOCK_NS
if type(start_ns) is not int or start_ns <= 0 or end_ns > now_ns:
return _decline(diagnostics, 'fixed_cohort_clock_incomplete')
if (
type(frames) is not tuple
or type(poses) is not tuple
or type(emissions) is not tuple
or len(frames) > 12000
or len(poses) > 5120
or len(emissions) > 12000
or any(type(row) is not ReplayFrame for row in frames)
or any(type(row) is not OriginalSourcePose for row in poses)
or any(type(row) is not Emission for row in emissions)
or type(controls) is not tuple
or len(controls) > 12000
or any(type(row) is not ControlEvidence for row in controls)
):
raise ValueError('exact bounded original cohort source required')
stamps = tuple(frame.control_ns for frame in frames)
first, crossing = bisect_left(stamps, start_ns), bisect_left(stamps, end_ns)
if first == len(frames) or stamps[first] != start_ns or crossing == len(frames):
return _decline(diagnostics, 'fixed_cohort_frame_coverage_unavailable')
selected_frames = frames[first : crossing + 1]
if any(frame.healthy is not True or frame.manual is not False for frame in selected_frames) or any(
not 0 < right.control_ns - left.control_ns <= 50_000_000 or right.frame_sequence != left.frame_sequence + 1
for left, right in zip(selected_frames, selected_frames[1:], strict=False)
):
return _decline(diagnostics, 'fixed_cohort_frame_health_or_contiguity_unavailable')
by_stamp = {row.control_ns: row for row in controls}
if len(by_stamp) != len(controls) or any(frame.control_ns not in by_stamp for frame in selected_frames):
return _decline(diagnostics, 'fixed_cohort_original_control_coverage_unavailable')
selected_controls = tuple(by_stamp[frame.control_ns] for frame in selected_frames)
if any(
not row.enabled
or not row.active
or not row.valid
or row.manual
or row.override
or row.fault
or row.native_required is not binding.native_required
or (row.identity, row.source_epoch, row.baseline_revision, row.controller_revision, row.native_identity)
!= (binding.identity, binding.source_epoch, binding.baseline_revision, binding.controller_revision, binding.native_identity)
or row.native_required
and (not row.native_allowed or not 0 < row.native_observed_ns <= row.control_ns <= row.native_expires_ns)
for row in selected_controls
):
return _decline(diagnostics, 'fixed_cohort_control_source_or_native_unqualified')
if not source_complete and any(
row.saturated
or row.model_wobble
or row.controller_chatter
or row.limited
and not (row.stage_schema_revision == 'torque-selected-stage-snapshot-v1' and dict(row.replay_inputs).get('curvature_limited') == 0.0)
for row in selected_controls
):
# Preserve the conservative legacy controller-row selector. Only the
# explicit versioned PHYSICAL input policy below may retain a delivered
# tagged input; its independent native/CAN verifier remains mandatory.
return _decline(diagnostics, 'fixed_cohort_controller_row_quality_unqualified')
anchors = tuple(dict.fromkeys(row.vehicle_model_anchor for row in selected_controls))
if any(type(anchor) is not tuple or len(anchor) != 3 or digest(anchor) != binding.vehicle_model_generation for anchor in anchors):
return _decline(diagnostics, 'fixed_cohort_vehicle_model_anchor_unavailable')
selected = []
calibration = physical_calibration_generation(binding)
context = None
for index in range(8):
lower = start_ns + FIRST_SLOT_NS + index * (BLOCK_NS + PURGE_NS)
upper = lower + BLOCK_NS
raw = tuple(row for row in poses if lower <= row.mono_ns < upper)
if any(
any(type(value) is not int for value in (row.source_lower_ns, row.source_upper_ns, row.completed_ns))
or not 0 < row.source_lower_ns <= row.mono_ns <= row.source_upper_ns <= row.completed_ns
for row in raw
):
return _decline(diagnostics, 'fixed_slot_pose_source_clock_unavailable')
group = tuple(row for row in raw if lower <= row.source_lower_ns <= row.source_upper_ns < upper)
if not 40 <= len(group) <= 240:
return _decline(diagnostics, 'fixed_slot_pose_count_unavailable')
for row in group:
# These are source/context/physical QUALITY conditions, not residuals.
if (
row.valid is not True
or row.native_allowed is not True
or row.native_required is not binding.native_required
or (row.identity, row.source_epoch, row.baseline_revision, row.controller_revision, row.calibration, row.native_identity)
!= (binding.identity, binding.source_epoch, binding.baseline_revision, binding.controller_revision, calibration, binding.native_identity)
or type(row.speed_mps) not in (float, int)
or not math.isfinite(row.speed_mps)
or row.speed_mps <= 0
or not 0 < row.source_lower_ns <= row.mono_ns <= row.source_upper_ns <= row.completed_ns <= now_ns
):
return _decline(diagnostics, 'fixed_slot_pose_source_or_native_unqualified')
if context is None:
context = row.context
if row.context != context:
return _decline(diagnostics, 'fixed_slot_pose_context_changed')
selected.append(group)
events = tuple(event for event in emissions if start_ns <= event.control_ns <= selected_frames[-1].control_ns)
applies = tuple(event.apply_ns for event in events)
if not events or any(right <= left for left, right in zip(applies, applies[1:], strict=False)):
return _decline(diagnostics, 'fixed_cohort_original_emission_order_unavailable')
commands = []
for event in events:
if (
event.valid is not True
or event.active is not True
or event.override is not False
or event.fault is not False
or event.native_allowed is not True
or event.native_required is not binding.native_required
or (event.identity, event.source_epoch, event.baseline_revision, event.native_identity)
!= (binding.identity, binding.source_epoch, binding.baseline_revision, binding.native_identity)
or type(event.witness) is not TorqueProjection
or not 0 < event.state_ns <= event.control_ns <= event.apply_ns <= now_ns
or event.native_required
and not 0 < event.native_observed_ns <= event.control_ns <= event.apply_ns <= event.native_expires_ns
):
commands.append(None)
continue
control = by_stamp.get(event.control_ns)
# This immutable view copies the ACTUAL emitted source/codec fields only;
# it supplies no native permission. The child still decodes actual CAN.
output = AppliedEvidence(
event.control_ns,
event.state_ns,
event.apply_ns,
'normalized_torque',
event.witness.reported_torque,
event.valid,
event.active,
event.override,
event.fault,
event.limited,
event.native_allowed,
projection=event.witness,
)
# This selector schedules PHYSICAL calibration only. Original saturation,
# chatter and limiting remain in the full immutable packet. They do not
# erase a known emitted input. The independent physical-input owner still
# verifies its exact CAN/limiter result, source identity and native leases.
# Current witnesses, trial eligibility and application remain unchanged.
if control is None or not consumed_sources_current(control, output):
commands.append(None)
continue
value = normalized_applied_command(event.witness)
commands.append(-cast(float, value) if type(value) in (float, int) and math.isfinite(cast(float, value)) else None)
source_support = {}
if source_complete:
selected = source_complete_groups(applies, commands, selected)
if any(not 40 <= len(group) <= 240 for group in selected):
return _decline(diagnostics, 'fixed_slots_source_complete_pose_count_unavailable')
source_support = {'source_pose_ns': tuple(tuple(row.mono_ns for row in group) for group in selected)}
if not _common_command_source(applies, commands, selected):
return _decline(diagnostics, 'fixed_cohort_common_command_source_unavailable')
# This is NOT lag identification: only whether ANY declared lag has adequate
# original command support. No response/correlation/error chooses this lag.
for lag_ns in LAGS_NS:
groups = []
for group in selected:
values = []
for row in group:
lower, upper = row.source_lower_ns - lag_ns, row.source_upper_ns - lag_ns
left, right = bisect_right(applies, lower) - 1, bisect_right(applies, upper) - 1
if left < 0 or left != right or upper - applies[left] > JOIN_NS or commands[left] is None:
break
values.append(commands[left])
if len(values) != len(group):
break
groups.append(tuple(values))
if len(groups) != 8:
continue
summary = _command_quality(groups)
if summary is not None:
return dict(
summary, **source_support, start_ns=start_ns, end_ns=end_ns, pose_counts=tuple(len(group) for group in selected), command_support_lag_ns=lag_ns
)
return _decline(diagnostics, 'fixed_slots_command_support_or_excitation_unavailable')
def select_first_cohort(
*,
checkpoints,
frames,
poses,
emissions,
controls,
binding,
epoch,
epoch_start_ns,
cutoff_ns,
now_ns,
cache=None,
diagnostics=None,
unavailable_anchors=(),
source_complete=False,
):
"""Actual checkpoint anchors are declared independently of response outcomes."""
from openpilot.starpilot.flm.controller_replay import Snapshot
if (
type(checkpoints) is not tuple
or len(checkpoints) > MAX_CHECKPOINTS
or not poses
or type(epoch) is not int
or epoch < 0
or not 0 < epoch_start_ns < cutoff_ns
or cutoff_ns - epoch_start_ns > 100_000_000_000
):
raise ValueError('bounded original source epoch required')
binding.validate()
if any(type(row) is not tuple or len(row) != 2 or type(row[0]) is not int or type(row[1]) is not Snapshot for row in checkpoints):
raise ValueError('genuine captured checkpoint anchors required')
anchors = tuple(stamp for stamp, _ in checkpoints)
if any(right <= left for left, right in zip(anchors, anchors[1:], strict=False)):
raise ValueError('original checkpoint order')
preceding = tuple(stamp for stamp in anchors if stamp <= poses[0].mono_ns)
if not preceding:
return _decline(diagnostics, 'original_checkpoint_before_first_pose_unavailable')
origin = preceding[-1]
if cache is None:
cache = {'examined': {}, 'selected': None}
if cache['selected'] is not None:
if type(diagnostics) is dict:
diagnostics['reason'] = 'cached_source_cohort_selected_not_child_qualified'
return dict(cache['selected'])
from openpilot.starpilot.flm.source_plant_fit import FIRST_SLOT_NS, BLOCK_NS, PURGE_NS
duration_ns = FIRST_SLOT_NS + 7 * (BLOCK_NS + PURGE_NS) + BLOCK_NS
if type(diagnostics) is dict:
diagnostics.update(
{
'reason': 'fixed_cohort_still_collecting_or_previously_declined',
'requiredCohortNs': duration_ns,
'originCheckpointNs': origin,
'examinedAnchors': len(cast(dict[int, bool], cache['examined'])),
}
)
for start_ns in anchors:
if start_ns < origin or start_ns + duration_ns >= cutoff_ns:
continue
if (
start_ns + duration_ns > now_ns
or not frames
or not poses
or frames[-1].control_ns < start_ns + duration_ns
or poses[-1].source_lower_ns < start_ns + duration_ns
or not emissions
or emissions[-1].control_ns < start_ns + duration_ns
or not controls
or controls[-1].control_ns < start_ns + duration_ns
or start_ns in cast(dict[int, bool], cache['examined'])
):
continue
if start_ns in unavailable_anchors:
_decline(diagnostics, 'fixed_cohort_feedback_source_incomplete')
continue
if type(diagnostics) is dict:
diagnostics['lastExaminedAnchorNs'] = start_ns
result = quality_for_start(
start_ns,
frames=frames,
poses=poses,
emissions=emissions,
controls=controls,
binding=binding,
now_ns=now_ns,
diagnostics=diagnostics,
source_complete=source_complete,
)
cast(dict[int, bool], cache['examined'])[start_ns] = result is not None
if type(diagnostics) is dict:
diagnostics['examinedAnchors'] = len(cast(dict[int, bool], cache['examined']))
if result is not None and result['end_ns'] < cutoff_ns:
selected = dict(result, version=VERSION, epoch=epoch, epoch_start_ns=epoch_start_ns, cutoff_ns=cutoff_ns, origin_checkpoint_ns=origin)
cache['selected'] = selected
if type(diagnostics) is dict:
diagnostics['reason'] = 'source_cohort_selected_not_child_qualified'
return dict(selected)
return None
def validate_selected_cohort(selection, packet, engine, binding, now_ns, *, source_complete=False):
"""Fresh child recomputation of selected command support; no parent trust."""
from openpilot.starpilot.flm.original_source_capture import OriginalSourcePose
if (
type(selection) is not dict
or selection.get('version') != VERSION
or not engine.records
or selection.get('epoch') != packet['capture_epoch']
or selection.get('epoch_start_ns') != packet['capture_epoch_start_ns']
or selection.get('cutoff_ns') != packet['capture_epoch_cutoff_ns']
or selection.get('start_ns') != engine.records[0].control_ns
or type(selection.get('origin_checkpoint_ns')) is not int
or not 0 < selection['origin_checkpoint_ns'] <= selection['start_ns'] < selection['end_ns'] < selection['cutoff_ns']
or not 0 <= selection['epoch_start_ns'] - selection['origin_checkpoint_ns'] <= 1_100_000_000
or selection['start_ns'] not in dict(engine.checkpoints)
):
raise ValueError('explicit original checkpoint cohort selection provenance')
poses = tuple(OriginalSourcePose(**row) for row in packet['source_poses'])
quality = quality_for_start(
selection['start_ns'],
frames=tuple(engine.records),
poses=poses,
emissions=tuple(engine.emissions.events.values()),
controls=tuple(engine.original_context_controls.values()),
binding=binding,
now_ns=now_ns,
source_complete=source_complete,
)
if (
quality is None
or set(selection) != set(quality) | {'version', 'epoch', 'epoch_start_ns', 'cutoff_ns', 'origin_checkpoint_ns'}
or any(selection[name] != value for name, value in quality.items())
):
raise ValueError('current independently verified cohort command/source quality changed')
return selection