diff --git a/openpilot/starpilot/flm/analyze.py b/openpilot/starpilot/flm/analyze.py new file mode 100644 index 0000000000..3d721e36b9 --- /dev/null +++ b/openpilot/starpilot/flm/analyze.py @@ -0,0 +1,61 @@ +"""Desktop-only FLM diagnostic report from explicitly selected closed rlogs.""" + +import argparse +from collections.abc import Callable, Sequence +from dataclasses import asdict +import json +from pathlib import Path +import sys + +from openpilot.common.hardware import PC +from openpilot.starpilot.galaxy.drive_history import SEGMENT_NAME +from openpilot.starpilot.flm.local_logs import LocalLogUnavailable, read_closed_rlog +from openpilot.starpilot.flm.log_decode import LogDecodeError, decode_segment +from openpilot.starpilot.flm.offline import MAX_SEGMENTS, SegmentInput, analyze_segments + + +def analyze_local(root: Path, names: Sequence[str], *, cancelled: Callable[[], bool] = lambda: False) -> dict: + """Process one bounded segment at a time; never return a partial report.""" + if not PC: + raise ValueError("Use a desktop: device analysis needs a separate parked operation owner") + if not 1 <= len(names) <= MAX_SEGMENTS or len(set(names)) != len(names): + raise ValueError("Select one to five distinct closed segments") + reports = [] + for name in names: + source = read_closed_rlog(root, name, permitted=lambda: not cancelled()) + match = SEGMENT_NAME.fullmatch(name) + assert match is not None + events = decode_segment(source.compressed, source.codec, cancelled=cancelled) + report = analyze_segments((SegmentInput(match.group("route"), int(match.group("number")), events),), cancelled=cancelled) + reports.append({"source": {"segmentName": source.segment_name, "sha256": source.sha256, + "compressedBytes": source.size, "codec": source.codec}, + "analysis": asdict(report.segments[0])}) + del events, source + if cancelled(): + raise ValueError("Analysis cancelled") + return {"schemaVersion": 1, "purpose": "offline_tracking_diagnostics", "segments": reports, + "tuneRecommendation": None, "vehicleQualification": False} + + +def main(argv: Sequence[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--log-root", required=True, type=Path, help="Absolute local recording directory; no remote routes") + parser.add_argument("--output", type=Path, help="Create a new JSON report file; never overwrite an existing file") + parser.add_argument("segments", nargs="+", help="Closed segment directory names under --log-root (at most five)") + args = parser.parse_args(argv) + try: + result = analyze_local(args.log_root, args.segments) + payload = json.dumps(result, allow_nan=False, indent=2) + if args.output is not None: + with args.output.open("x", encoding="utf-8") as destination: + destination.write(payload + "\n") + else: + print(payload) + except (LocalLogUnavailable, LogDecodeError, OSError, ValueError, RuntimeError) as error: + print(f"FLM analysis unavailable: {error}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/openpilot/starpilot/flm/local_logs.py b/openpilot/starpilot/flm/local_logs.py new file mode 100644 index 0000000000..5afc4cf753 --- /dev/null +++ b/openpilot/starpilot/flm/local_logs.py @@ -0,0 +1,112 @@ +"""Admit one immutable, closed local rlog for offline analysis; never download.""" + +from collections.abc import Callable +from dataclasses import dataclass, field +import hashlib +import os +from pathlib import Path +import stat + +from openpilot.starpilot.galaxy.drive_history import MAX_SEGMENT_ENTRIES, SEGMENT_NAME + + +MAX_COMPRESSED_BYTES = 32 * 1024 * 1024 +DIR_FLAGS = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW | os.O_NONBLOCK +FILE_FLAGS = os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK +RLOGS = {"rlog.zst": "zst", "rlog.bz2": "bz2"} + + +class LocalLogUnavailable(Exception): + pass + + +@dataclass(frozen=True) +class ClosedLog: + segment_name: str + codec: str + compressed: bytes = field(repr=False) + sha256: str + size: int + + +def _identity(info: os.stat_result) -> tuple[int, int]: + return info.st_dev, info.st_ino + + +def _revision(info: os.stat_result) -> tuple[int, ...]: + return (*_identity(info), info.st_size, info.st_mtime_ns, info.st_ctime_ns) + + +def _allowed(permitted: Callable[[], bool]) -> None: + if not permitted(): + raise LocalLogUnavailable("Analysis is no longer allowed") + + +def _closed_rlog(fd: int) -> str: + found = [] + with os.scandir(fd) as entries: + for count, entry in enumerate(entries, 1): + if count > MAX_SEGMENT_ENTRIES or entry.name.endswith(".lock"): + raise LocalLogUnavailable("Segment is open or unavailable") + if entry.name in RLOGS: + found.append(entry.name) + if len(found) != 1: + raise LocalLogUnavailable("Select a segment with exactly one closed full rlog") + return found[0] + + +def read_closed_rlog(root: Path, segment_name: str, *, permitted: Callable[[], bool]) -> ClosedLog: + """Revalidate an inventory choice, then bind its receipt to the bytes read. + + The inventory is not authority: locks, file type, bounds and inode revisions + are checked again at admission and after the complete read. The supplied + root is the locally configured recording directory, never an HTTP input. + No decoded events or successful receipt escape a partial/cancelled read. + """ + matched = SEGMENT_NAME.fullmatch(segment_name) if type(segment_name) is str and len(segment_name) <= 180 else None + if matched is None or len(matched.group("number")) > 6 or not root.is_absolute() or ".." in root.parts: + raise LocalLogUnavailable("Invalid local segment selection") + fds = [] + try: + _allowed(permitted) + root_fd = os.open(root, DIR_FLAGS) + fds.append(root_fd) + root_info = os.fstat(root_fd) + segment_fd = os.open(segment_name, DIR_FLAGS, dir_fd=root_fd) + fds.append(segment_fd) + segment_info = os.fstat(segment_fd) + filename = _closed_rlog(segment_fd) + source_fd = os.open(filename, FILE_FLAGS, dir_fd=segment_fd) + fds.append(source_fd) + before = os.fstat(source_fd) + if not stat.S_ISREG(before.st_mode) or not 0 < before.st_size <= MAX_COMPRESSED_BYTES: + raise LocalLogUnavailable("Full rlog is empty, oversized or not a regular file") + chunks = [] + remaining = before.st_size + while remaining: + _allowed(permitted) + chunk = os.read(source_fd, min(1024 * 1024, remaining)) + if not chunk: + raise LocalLogUnavailable("Full rlog changed while reading") + chunks.append(chunk) + remaining -= len(chunk) + if os.read(source_fd, 1): + raise LocalLogUnavailable("Full rlog grew while reading") + _allowed(permitted) + after = os.fstat(source_fd) + current = os.stat(filename, dir_fd=segment_fd, follow_symlinks=False) + segment_now = os.stat(segment_name, dir_fd=root_fd, follow_symlinks=False) + root_now = os.stat(root, follow_symlinks=False) + if (_revision(before) != _revision(after) or _revision(after) != _revision(current) or + not stat.S_ISREG(current.st_mode) or not stat.S_ISDIR(segment_now.st_mode) or + not stat.S_ISDIR(root_now.st_mode) or _identity(segment_now) != _identity(segment_info) or + _identity(root_now) != _identity(root_info) or _closed_rlog(segment_fd) != filename): + raise LocalLogUnavailable("Local recording identity changed") + raw = b"".join(chunks) + _allowed(permitted) + return ClosedLog(segment_name, RLOGS[filename], raw, hashlib.sha256(raw).hexdigest(), len(raw)) + except (OSError, ValueError) as error: + raise LocalLogUnavailable("Local recording is unavailable") from error + finally: + for fd in reversed(fds): + os.close(fd) diff --git a/openpilot/starpilot/flm/operation_owner.py b/openpilot/starpilot/flm/operation_owner.py new file mode 100644 index 0000000000..753085bad0 --- /dev/null +++ b/openpilot/starpilot/flm/operation_owner.py @@ -0,0 +1,556 @@ +"""One parked, read-only FLM operation with an isolated local-log worker.""" + +from collections.abc import Callable, Sequence +from contextlib import contextmanager +import json +import logging +import os +from pathlib import Path +import selectors +import subprocess +import sys +import threading +import time +import uuid + +from openpilot.common.hardware.hw import Paths +from openpilot.starpilot.galaxy.drive_history import SEGMENT_NAME + + +MAX_REPORT_BYTES = 1024 * 1024 +MAX_PIPE_BYTES = MAX_REPORT_BYTES + 4096 +WALL_DEADLINE_SECONDS = 5 * 60 +POLL_SECONDS = 0.05 +ACTIVE_STATE = 'running' +ERROR_CODES = frozenset(('invalid_request', 'busy', 'not_parked', 'operation_changed', 'unavailable', + 'canceled', 'process_failed', 'deadline', 'recording_unavailable', 'decode_failed', 'resource_limit')) + + +class FlmOperationError(RuntimeError): + def __init__(self, code: str): + self.code = code if code in ERROR_CODES else 'unavailable' + super().__init__(self.code) + + +def _stop_child(child: subprocess.Popen) -> None: + if child.poll() is not None: + child.wait() + return + try: + child.terminate() + except ProcessLookupError: + pass + try: + child.wait(timeout=0.5) + except subprocess.TimeoutExpired: + try: + child.kill() + except ProcessLookupError: + pass + try: + child.wait(timeout=0.5) + except subprocess.TimeoutExpired as error: + raise FlmOperationError('unavailable') from error + + +class FlmAnalysisOwner: + """Parent alone owns fresh parked authority, operation identity and report visibility.""" + + def __init__(self, *, parked: Callable[[], bool], root: Path | None = None, + worker_argv: Sequence[str] | None = None, completed: Callable[[dict], bool] | None = None): + self.root = Path(Paths.log_root()) if root is None else root + self._parked = parked + self._completed = completed + self._worker_argv = tuple(worker_argv) if worker_argv is not None else ( + sys.executable, '-m', 'openpilot.starpilot.flm.operation_worker') + self._lock = threading.RLock() + self._session = uuid.uuid4().hex + self._sequence = 0 + self._closed = False + self._cancel = threading.Event() + self._child: subprocess.Popen | None = None + self._monitor_thread: threading.Thread | None = None + self._report: dict | None = None + self._status = self._fresh_status('idle', None, 0) + + @staticmethod + def _fresh_status(state: str, operation_id: str | None, selected: int, processed: int = 0, + error_code: str | None = None) -> dict: + return {'version': 1, 'operationId': operation_id, 'state': state, 'selected': selected, + 'processed': processed, 'errorCode': error_code} + + def _allowed(self) -> bool: + try: + return self._parked() is True + except Exception: + return False + + def _revoke_if_unparked(self) -> None: + if self._allowed(): + return + with self._lock: + if self._status['state'] != 'idle': + self._status = self._fresh_status('unavailable', self._status['operationId'], + self._status['selected'], self._status['processed'], 'not_parked') + self._report = None + self._cancel.set() + + def snapshot(self) -> dict: + self._revoke_if_unparked() + with self._lock: + return dict(self._status) + + def start(self, segment_names: Sequence[str], *, gm_context: dict | None = None) -> dict: + if (type(segment_names) not in (tuple, list) or not 1 <= len(segment_names) <= 5 or + any(type(name) is not str or len(name) > 180 or SEGMENT_NAME.fullmatch(name) is None + for name in segment_names) or len(set(segment_names)) != len(segment_names)): + raise FlmOperationError('invalid_request') + if gm_context is not None: + from openpilot.starpilot.flm.gm_recommend import validate_context + gm_context = json.loads(json.dumps(validate_context(gm_context), allow_nan=False)) + if not self._allowed(): + raise FlmOperationError('not_parked') + with self._lock: + if self._closed: + raise FlmOperationError('unavailable') + if self._status['state'] == ACTIVE_STATE or self._child is not None or \ + (self._monitor_thread is not None and self._monitor_thread.is_alive()): + raise FlmOperationError('busy') + self._sequence += 1 + token = f'{self._session}:{self._sequence}' + self._cancel = threading.Event() + self._report = None + self._status = self._fresh_status(ACTIVE_STATE, token, len(segment_names)) + request_value = {'root': str(self.root), 'segments': list(segment_names), 'parentPid': os.getpid()} + if gm_context is not None: + request_value['gmContext'] = gm_context + request = json.dumps(request_value, sort_keys=True, allow_nan=False, separators=(',', ':')).encode() + if len(request) > (32768 if gm_context is not None else 2048): + self._status = self._fresh_status('failed', token, len(segment_names), error_code='invalid_request') + raise FlmOperationError('invalid_request') + # The monitor must create the child: Linux PR_SET_PDEATHSIG follows the + # creating thread, and an HTTP request thread ends after this response. + self._monitor_thread = threading.Thread(target=self._monitor, args=(token, self._cancel, + tuple(segment_names), request, gm_context), daemon=True) + try: + self._monitor_thread.start() + except RuntimeError as error: + self._monitor_thread = None + self._status = self._fresh_status('failed', token, len(segment_names), error_code='unavailable') + raise FlmOperationError('unavailable') from error + self._revoke_if_unparked() + return self.snapshot() + + def _monitor(self, token: str, canceled: threading.Event, names: tuple[str, ...], request: bytes, + gm_context: dict | None = None) -> None: + result: dict | None = None + error: str | None = 'process_failed' + child: subprocess.Popen | None = None + reaped = False + try: + if canceled.is_set(): + error = 'canceled' + return + if not self._allowed(): + error = 'not_parked' + return + child = subprocess.Popen(self._worker_argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, bufsize=0, close_fds=True) + with self._lock: + if self._status['operationId'] == token: + self._child = child + if child.stdin is None: + raise OSError('worker input unavailable') + child.stdin.write(request) + child.stdin.close() + result, error = self._read_worker(token, child, canceled, names) + if error is None: + if result is None: + raise ValueError('missing report') + sources = result['segments'] + if (result.get('schemaVersion') != 1 or + result.get('purpose') != ('offline_tracking_diagnostics' if gm_context is None else 'gm_flm_evidence_profiles') or + result.get('tuneRecommendation', 1) is not None or result.get('vehicleQualification') is not False or + type(sources) is not list or [row['source']['segmentName'] for row in sources] != list(names)): + raise ValueError('report shape') + if gm_context is not None: + from openpilot.starpilot.flm.gm_recommend import validate_context + evidence = result.get('gmEvidence') + if (type(evidence) is not dict or validate_context(evidence['context']) != gm_context or + evidence.get('fit') is not False or evidence.get('vehicleQualification') is not False): + raise ValueError('GM report source') + result = {**result, 'operationId': token} + if len(json.dumps(result, allow_nan=False).encode()) > MAX_REPORT_BYTES: + raise ValueError('report limit') + except Exception: + logging.exception('FLM operation failed') + error = 'process_failed' + finally: + if child is not None: + try: + _stop_child(child) + reaped = True + except (OSError, FlmOperationError): + error = 'unavailable' + for pipe in (child.stdin, child.stdout): + if pipe is None: + continue + try: + pipe.close() + except OSError: + error = 'unavailable' + else: + reaped = True + if not self._allowed(): + error = 'not_parked' + # Completion effects acquire the HTTP effect guard before this owner's + # lock. Never invoke a callback while holding the owner lock. + if error is None and result is not None and not canceled.is_set() and reaped and gm_context is not None and self._completed is not None: + try: + result['gmEvidence']['progressRecorded'] = self._completed(result) is True + except Exception: + logging.exception('FLM cleanup progress was not recorded') + result['gmEvidence']['progressRecorded'] = False + with self._lock: + if self._status['operationId'] == token: + if self._closed or self._status['state'] == 'unavailable' or not self._allowed(): + error = 'not_parked' if not self._closed else 'unavailable' + if error is None and not canceled.is_set() and reaped: + self._report = result + self._status = self._fresh_status('completed', token, len(names), len(names)) + else: + code = 'unavailable' if self._closed else \ + 'canceled' if canceled.is_set() and error != 'not_parked' else error or 'canceled' + unavailable = code in ('not_parked', 'unavailable', 'recording_unavailable', 'decode_failed', 'resource_limit') + state = 'canceled' if code == 'canceled' else 'unavailable' if unavailable else 'failed' + self._status = self._fresh_status(state, token, len(names), self._status['processed'], code) + self._report = None + if child is not None and self._child is child and reaped: + self._child = None + + def _read_worker(self, token: str, child: subprocess.Popen, canceled: threading.Event, + names: tuple[str, ...]) -> tuple[dict | None, str | None]: + if child.stdout is None: + return None, 'process_failed' + deadline = time.monotonic() + WALL_DEADLINE_SECONDS + buffer = bytearray() + consumed = 0 + result = None + error = None + with selectors.DefaultSelector() as selector: + selector.register(child.stdout, selectors.EVENT_READ) + while error is None: + if canceled.is_set(): + return None, 'canceled' + if not self._allowed(): + return None, 'not_parked' + if time.monotonic() >= deadline: + return None, 'deadline' + if not selector.select(POLL_SECONDS): + continue + chunk = os.read(child.stdout.fileno(), 64 * 1024) + if not chunk: + break # Pipe EOF; wait only a bounded time for the child to exit. + consumed += len(chunk) + if consumed > MAX_PIPE_BYTES: + return None, 'process_failed' + buffer.extend(chunk) + while b'\n' in buffer: + line, _, remainder = buffer.partition(b'\n') + buffer = bytearray(remainder) + message = json.loads(line) + if type(message) is not dict: + return None, 'process_failed' + if message.get('kind') == 'progress' and type(message.get('processed')) is int and \ + 0 < message['processed'] <= len(names): + with self._lock: + if self._status['operationId'] == token and self._status['state'] == ACTIVE_STATE: + self._status['processed'] = max(self._status['processed'], message['processed']) + elif message.get('kind') == 'result' and type(message.get('report')) is dict: + result = message['report'] + elif message.get('kind') == 'error' and message.get('code') in ( + 'unavailable', 'process_failed', 'recording_unavailable', 'decode_failed', 'resource_limit', + ): + error = message['code'] + else: + return None, 'process_failed' + if error is not None: + break + if error is not None: + return None, error + if buffer or child.wait(timeout=0.5) != 0 or result is None: + return None, 'process_failed' + return result, None + + def report(self, operation_id: str) -> dict: + self._revoke_if_unparked() + with self._lock: + if self._closed: + raise FlmOperationError('unavailable') + if self._status['operationId'] != operation_id: + raise FlmOperationError('operation_changed') + if self._status['state'] != 'completed' or self._report is None: + raise FlmOperationError(self._status['errorCode'] or 'unavailable') + return json.loads(json.dumps(self._report, allow_nan=False)) + + @contextmanager + def completion_guard(self, operation_id: str): + # Called only after the shared HTTP effect guard, and retained through the + # optional metadata commit so cancel/close cannot retire this operation + # between its final authority check and document replacement. + with self._lock: + yield (self._status['operationId'] == operation_id and self._status['state'] == ACTIVE_STATE and + not self._closed and not self._cancel.is_set() and self._allowed()) + + def cancel(self, operation_id: str) -> dict: + self._revoke_if_unparked() + with self._lock: + if self._status['operationId'] != operation_id: + raise FlmOperationError('operation_changed') + if self._status['state'] != ACTIVE_STATE: + return dict(self._status) + self._cancel.set() + thread = self._monitor_thread + if thread is not None: + thread.join(timeout=1.5) + if thread.is_alive(): + with self._lock: + child = self._child + if child is not None: + _stop_child(child) + thread.join(timeout=0.5) + return self.snapshot() + + def close(self) -> None: + with self._lock: + self._closed = True + self._cancel.set() + thread = self._monitor_thread + if thread is not None: + thread.join(timeout=1.5) + with self._lock: + child = self._child + if child is not None: + _stop_child(child) + with self._lock: + self._report = None + if self._status['state'] != 'idle': + self._status = self._fresh_status('unavailable', self._status['operationId'], + self._status['selected'], self._status['processed'], 'unavailable') + +class FlmTrialOwner: + """Existing FLM namespace's parked exact-source atomic surface editor.""" + def __init__(self, params, context): + self.params, self.context = params, context + + def _sources(self): + import hashlib + from openpilot.starpilot.flm.live import gm_capability + from openpilot.starpilot.lateral.controller_selection import DOCUMENT_KEY as SELECTION_KEY, selection_from_bytes + from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY, MAX_DOCUMENT_BYTES, parse_document + from openpilot.starpilot.saved_source import read_saved + ctx = self.context.sample() + raw, readable = read_saved(self.params, DOCUMENT_KEY, MAX_DOCUMENT_BYTES) + selection_raw, selection_readable = read_saved(self.params, SELECTION_KEY, 4096) + selection = None if ctx.cp is None or not selection_readable else selection_from_bytes(ctx.cp, selection_raw) + cap = (None if selection is None or selection.source == 'invalid' else gm_capability(ctx.cp, selection.mode)) + if not readable or cap is None or ctx.cp_raw is None: + raise FlmOperationError('unavailable') + try: + profiles = {} if raw is None else parse_document(raw) + except (ValueError, TypeError, UnicodeError, OverflowError): + raise FlmOperationError('unavailable') from None + guards = [] + for key, limit in (('AdvancedLateralTune', 64), ('ForceAutoTuneOff', 1)): + value, valid = read_saved(self.params, key, limit) + guards.append((key, valid, None if value is None else value.hex())) + token = hashlib.sha256( + json.dumps(cap,sort_keys=True).encode()+b'\0'+ctx.cp_raw+b'\0'+(raw or b'')+ + b'\0'+(selection_raw or b'')+b'\0'+json.dumps(guards).encode()).hexdigest() + return ctx, raw, selection_raw, cap, profiles, token + + def snapshot(self): + from opendbc.car.lateral import FRICTION_THRESHOLD + from openpilot.starpilot.flm.live import binding_matches + from openpilot.starpilot.flm.torque_surface import GmFlmBinding, GmSurface, _GM_BOUNDS, _GM_RICH_BOUNDS + try: + ctx, _, _, cap, profiles, token = self._sources() + except FlmOperationError: + return {'version': 1, 'available': False, 'editable': False} + profile = profiles.get(cap['fingerprint']) + state = GmFlmBinding(cap['controller'],cap['policy'],cap['basis']) if profile is None or profile.flm is None else profile.flm + matched = profile is None or (profile.basis == cap['basis'] and + (profile.flm is None or binding_matches(profile,cap))) + from openpilot.starpilot.flm.manual_trial import manual_snapshot, manual_profile, manual_preconditions + from openpilot.starpilot.lateral.torque_settings import PlatformProfile, FieldChoice + current = profile or PlatformProfile(cap['basis'], FieldChoice(), FieldChoice()) + current_manual = manual_snapshot(current, cap['fingerprint']) + manual_conflict = state.applied_manual is not None and current_manual != state.applied_manual + preconditions = {} + for key, raw in state.manual: + try: + preconditions[key] = manual_preconditions(self.params, ctx.cp, cap['controller'], + manual_profile(raw, cap['fingerprint'], cap['basis'])) + except ValueError: + preconditions[key] = ['The saved manual controller or geometry basis changed. Review those choices in settings and save again.'] + limits = dict(_GM_BOUNDS) + limits.update(_GM_RICH_BOUNDS if cap['profile'] == 'gm_bolt_2022_2023' else {'ff_gain_left':(-.4,.6),'ff_gain_right':(-.4,.6)}) + return {'version': 1, 'available': matched, 'editable': bool(ctx.parked and matched), + 'reason': None if matched else ('The selected controller or vehicle basis changed. Reset this surface binding to retain ' + + 'manual choices and edit the current controller.'), + 'manualConflict': manual_conflict, 'manual': current_manual, 'preconditions': preconditions, + 'resettable': bool(ctx.parked and profile is not None and profile.flm is not None), 'token': token, + 'vehicle': cap['fingerprint'], 'controller': cap['controller'], 'profile': cap['profile'], + 'curveDefaults': [FRICTION_THRESHOLD if cap['controller'] == 'standard' else GmSurface(cap['profile'],{}).base_threshold(speed) + for speed in (0.,5.,10.,15.,25.)], + 'inactiveKnobs': {'low_speed_angle_assist_max_torque': ('The selected custom Bolt output law excludes universal angle assist. STANDARD consumes ' + + 'this choice.')} + if cap['controller'] == 'starpilot' and cap['policy'] == 'bolt' else {}, + 'state': state.document(), 'defaults': GmSurface(cap['profile'],{}).document(), + 'knobs': {key:{'min':low,'max':high} for key,(low,high) in limits.items()}} + + def action(self, payload, *, session_valid=lambda: True, generated_manual=None): + from dataclasses import replace + import re + import secrets + from openpilot.starpilot.flm.live import binding_matches + from openpilot.starpilot.flm.torque_surface import GmFlmBinding, GmSurface + from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY, MAX_DOCUMENT_BYTES, PlatformProfile, FieldChoice, serialize_document + from openpilot.starpilot.saved_document import commit_exact + if type(payload) is not dict or payload.get('action') not in ('save','delete','trial','apply','restore','accept','disable','reset','record-progress'): + raise ValueError('Invalid GM FLM action') + action=payload['action'] + if generated_manual is not None and action != 'save': + raise ValueError('Wrong generated manual action') + expected_fields={'action','token'} | ( + {'id','label','surface'} if action=='save' else {'id'} if action in ('delete','trial','apply') + else {'trial'} if action in ('restore','accept') else set()) + if set(payload)!=expected_fields or type(payload['token']) is not str or re.fullmatch(r'[a-f0-9]{64}',payload['token']) is None: + raise ValueError('Invalid GM FLM source') + ctx, raw, selection_raw, cap, profiles, token = self._sources() + if not ctx.parked or not session_valid(): + raise FlmOperationError('not_parked') + if payload['token']!=token: + raise FlmOperationError('operation_changed') + profile=profiles.get(cap['fingerprint'],PlatformProfile(cap['basis'],FieldChoice(),FieldChoice())) + if action != 'reset' and (profile.basis != cap['basis'] or + profile.flm is not None and not binding_matches(profile,cap)): + raise FlmOperationError('operation_changed') + state=profile.flm or GmFlmBinding(cap['controller'],cap['policy'],cap['basis']) + saved={key:(label,surface) for key,label,surface in state.saved} + manual = dict(state.manual) + from openpilot.starpilot.flm.manual_trial import manual_snapshot, manual_profile, manual_preconditions + current_manual = manual_snapshot(profile, cap['fingerprint']) + key=payload.get('id') + if action in ('save','delete','trial','apply') and (type(key) is not str or re.fullmatch(r'[a-zA-Z0-9_-]{1,48}',key) is None): + raise ValueError('Invalid saved surface identity') + if action=='save': + if state.trial is not None and key in (state.active,state.baseline_active): + raise FlmOperationError('busy') + surface=GmSurface.from_document(payload['surface']) + if surface.profile!=cap['profile']: + raise ValueError('Surface does not match selected controller') + saved[key]=(payload['label'],surface) + captured = current_manual if generated_manual is None else generated_manual + manual_profile(captured, cap['fingerprint'], cap['basis']) + manual[key] = captured + state=replace(state,saved=tuple((name,label,surface) for name,(label,surface) in saved.items()), manual=tuple(manual.items())) + elif action=='delete': + if key in (state.active,state.baseline_active): + raise FlmOperationError('busy') + if key not in saved: + raise ValueError('Unknown saved surface') + del saved[key] + manual.pop(key, None) + state=replace(state,saved=tuple((name,label,surface) for name,(label,surface) in saved.items()), manual=tuple(manual.items())) + elif action in ('trial','apply'): + if key not in saved: + raise ValueError('Unknown saved surface') + if state.applied_manual is not None and current_manual != state.applied_manual: + raise FlmOperationError('operation_changed') + target_manual = manual.get(key, state.baseline_manual or current_manual) + target = manual_profile(target_manual, cap['fingerprint'], cap['basis']) + if manual_preconditions(self.params, ctx.cp, cap['controller'], target): + raise FlmOperationError('unavailable') + # Every switch starts from the original owned manual baseline; the saved + # full canonical snapshot explicitly includes source/default choices. + baseline_manual = state.baseline_manual if state.trial else current_manual + old_flm = profile.flm + profile = replace(target, flm=old_flm) + state=replace(state,active=key,applied=True,trial=state.trial or secrets.token_hex(16), + baseline_active=state.baseline_active if state.trial else state.active, + baseline_applied=state.baseline_applied if state.trial else state.applied, + baseline_manual=baseline_manual, applied_manual=manual_snapshot(profile,cap['fingerprint'])) + elif action in ('restore','accept'): + if state.trial is None or payload['trial']!=state.trial: + raise FlmOperationError('operation_changed') + if action == 'restore' and state.baseline_manual is not None: + if current_manual != state.applied_manual: + # A later explicit manual edit is never silently overwritten. Keep + # as baseline resolves this conflict without rewriting preferences. + raise FlmOperationError('operation_changed') + profile = replace(manual_profile(state.baseline_manual, cap['fingerprint'], cap['basis']), flm=profile.flm) + state=replace(state,active=state.baseline_active if action=='restore' else state.active, + applied=state.baseline_applied if action=='restore' else state.applied, + trial=None,baseline_active=None,baseline_applied=False,baseline_manual=None,applied_manual=None) + elif action=='record-progress': + state=replace(state, cleanup_progress=True) + elif action=='disable': + state=replace(state,active=None,applied=False,trial=None,baseline_active=None,baseline_applied=False,baseline_manual=None,applied_manual=None) + # One atomic canonical document commit owns only this selected vehicle + # manual+surface trial; other vehicle preferences are retained unchanged. + profiles[cap['fingerprint']]=replace(profile,flm=None if action=='reset' else state) + encoded=serialize_document(profiles) + def authorized(): + try: + fresh, fresh_raw, fresh_selection, fresh_cap, _, fresh_token=self._sources() + return (session_valid() and fresh.parked and fresh.cp_raw==ctx.cp_raw and fresh_raw==raw and + fresh_selection==selection_raw and fresh_cap==cap and fresh_token==token) + except FlmOperationError: + return False + result=commit_exact(self.params,key=DOCUMENT_KEY,max_bytes=MAX_DOCUMENT_BYTES,raw=encoded,expected=raw, + authorized=authorized,temp_prefix='.flm-') + if not result.committed or not result.verified: + raise FlmOperationError('operation_changed') + return self.snapshot() + + + def training_context(self, token): + from openpilot.starpilot.flm.gm_recommend import source_context + from openpilot.starpilot.lateral.torque_settings import PlatformProfile, FieldChoice + ctx, _, _, cap, profiles, current = self._sources() + if not ctx.parked: + raise FlmOperationError('not_parked') + if token != current: + raise FlmOperationError('operation_changed') + profile = profiles.get(cap['fingerprint'], PlatformProfile(cap['basis'], FieldChoice(), FieldChoice())) + return source_context(ctx.cp, cap['controller'], self.params, current, profile) + + def save_generated(self, report, generated_id, key, label, token, *, session_valid=lambda: True): + context = self.training_context(token) + from openpilot.starpilot.flm.gm_recommend import same_numerical_context + if not same_numerical_context(context, report['context']): + raise FlmOperationError('operation_changed') + matches = [profile for path in report['paths'] for profile in path['profiles'] if profile['id'] == generated_id] + if len(matches) != 1 or matches[0].get('canonical') is None: + raise ValueError('Unavailable generated trial') + selected = matches[0]['canonical'] + return self.action({'action': 'save', 'token': token, 'id': key, 'label': label, 'surface': selected['surface']}, + generated_manual=selected['manual'], session_valid=session_valid) + + + def record_cleanup(self, report, *, session_valid=lambda: False): + evidence = report.get('gmEvidence') + if evidence is None or evidence['decision']['primaryPathKey'] != 'cleanup_pass' or evidence['stats']['sampleCount'] <= 0: + return False + try: + source = evidence['context'] + # This callback belongs only to an explicit Generate GM Trials operation. + # It records original cleanup progression, never applies a tune or writes + # any global flag. Changed source/unparked authority simply declines it. + if self.training_context(source['sourceToken']) != source: + return False + self.action({'action': 'record-progress', 'token': source['sourceToken']}, session_valid=session_valid) + return True + except (ValueError, FlmOperationError): + return False diff --git a/openpilot/starpilot/flm/operation_worker.py b/openpilot/starpilot/flm/operation_worker.py new file mode 100644 index 0000000000..19a0e32be6 --- /dev/null +++ b/openpilot/starpilot/flm/operation_worker.py @@ -0,0 +1,131 @@ +"""Isolated, bounded local FLM analysis worker; never started by the desktop CLI.""" + +from dataclasses import asdict +import ctypes +import json +import logging +import os +from pathlib import Path +import resource +import signal +import sys +import threading +import time + +from openpilot.starpilot.flm.local_logs import LocalLogUnavailable, read_closed_rlog +from openpilot.starpilot.flm.log_decode import LogDecodeError, decode_segment +from openpilot.starpilot.flm.offline import SegmentInput, analyze_segments +from openpilot.starpilot.galaxy.drive_history import SEGMENT_NAME + + +MAX_REQUEST_BYTES = 32768 +MAX_REPORT_BYTES = 1024 * 1024 +LINUX_ADDRESS_SPACE_BYTES = 2 * 1024**3 +LINUX_CPU_SECONDS = 240 + + +def _emit(value: dict) -> None: + payload = json.dumps(value, sort_keys=True, separators=(',', ':'), allow_nan=False).encode() + if len(payload) > MAX_REPORT_BYTES: + raise ValueError('report_limit') + sys.stdout.buffer.write(payload + b'\n') + sys.stdout.buffer.flush() + + +def _limits() -> None: + try: + os.nice(10) + except OSError: + pass + if sys.platform.startswith('linux'): + for limit, ceiling in ((resource.RLIMIT_AS, LINUX_ADDRESS_SPACE_BYTES), + (resource.RLIMIT_CPU, LINUX_CPU_SECONDS)): + soft, hard = resource.getrlimit(limit) + bounded = min([ceiling, *(value for value in (soft, hard) if value >= 0)]) + resource.setrlimit(limit, (bounded, hard)) + + +def _parent_lifeline(expected_pid: int) -> None: + if type(expected_pid) is not int or expected_pid <= 1: + raise ValueError('invalid parent') + if sys.platform.startswith('linux'): + # Set in the child, never in preexec_fn of a threaded parent. The PID + # recheck closes the race where the parent exits before prctl completes. + if ctypes.CDLL(None).prctl(1, signal.SIGKILL, 0, 0, 0) != 0: + raise OSError('parent-death signal unavailable') + if os.getppid() != expected_pid: + raise ValueError('parent changed') + if not sys.platform.startswith('linux'): + def watch_parent() -> None: + while True: + time.sleep(0.1) + if os.getppid() != expected_pid: + os._exit(125) + threading.Thread(target=watch_parent, daemon=True).start() + + +def main() -> int: + try: + _limits() + request = json.loads(sys.stdin.buffer.read(MAX_REQUEST_BYTES + 1)) + root, names = request['root'], request['segments'] + gm_context = request.get('gmContext') + if gm_context is not None: + from openpilot.starpilot.flm.gm_recommend import validate_context + gm_context = validate_context(gm_context) + elif len(json.dumps(request).encode()) > 2048: + raise ValueError('invalid_request') + if set(request) != {'root', 'segments', 'parentPid'} | ({'gmContext'} if gm_context is not None else set()): + raise ValueError('invalid_request') + _parent_lifeline(request['parentPid']) + if (type(root) is not str or not Path(root).is_absolute() or type(names) is not list or + not 1 <= len(names) <= 5 or any(type(name) is not str or len(name) > 180 or + SEGMENT_NAME.fullmatch(name) is None for name in names) or + len(set(names)) != len(names)): + raise ValueError('invalid_request') + selected_names = [name for name in names if type(name) is str] + segments = [] + gm_groups = [] + for index, name in enumerate(selected_names, 1): + source = read_closed_rlog(Path(root), name, permitted=lambda: True) + match = SEGMENT_NAME.fullmatch(name) + if match is None: + raise ValueError('invalid_request') + events = decode_segment(source.compressed, source.codec) + analysis = analyze_segments((SegmentInput(match.group('route'), int(match.group('number')), events),), + gm_context=gm_context, evidence=gm_groups if gm_context is not None else None) + segments.append({'source': {'segmentName': name, 'sha256': source.sha256, + 'compressedBytes': source.size, 'codec': source.codec}, + 'analysis': asdict(analysis.segments[0])}) + del source, events, analysis + _emit({'kind': 'progress', 'processed': index}) + report = {'schemaVersion': 1, 'purpose': 'offline_tracking_diagnostics', 'segments': segments, + 'tuneRecommendation': None, 'vehicleQualification': False} + if gm_context is not None: + from openpilot.starpilot.flm.gm_recommend import classify_groups, build_report + summaries, stats = classify_groups(gm_groups) + report['purpose'] = 'gm_flm_evidence_profiles' + report['gmEvidence'] = build_report(gm_context, summaries, stats) + _emit({'kind': 'result', 'report': report}) + return 0 + except LocalLogUnavailable: + logging.exception('FLM recording admission failed') + code = 'recording_unavailable' + except LogDecodeError: + logging.exception('FLM recording decode failed') + code = 'decode_failed' + except MemoryError: + logging.exception('FLM worker memory limit exceeded') + code = 'resource_limit' + except Exception: + logging.exception('FLM worker failed') + code = 'process_failed' + try: + _emit({'kind': 'error', 'code': code}) + except Exception: + pass + return 1 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/openpilot/starpilot/flm/test_log_decode.py b/openpilot/starpilot/flm/test_log_decode.py new file mode 100644 index 0000000000..34c8809dca --- /dev/null +++ b/openpilot/starpilot/flm/test_log_decode.py @@ -0,0 +1,97 @@ +"""No partial FLM segment success after corrupt compression or Cereal data.""" + +import bz2 +from unittest import mock + +import pytest +import zstandard as zstd + +from openpilot.cereal import messaging +from openpilot.starpilot.flm import log_decode + + +def _events() -> bytes: + first = messaging.new_message("deviceState", valid=True) + first.logMonoTime = 101 + first.deviceState.started = True + second = messaging.new_message("carState", valid=False) + second.logMonoTime = 202 + return first.to_bytes() + second.to_bytes() + + +def _compressed(raw: bytes, codec: str) -> bytes: + return zstd.ZstdCompressor().compress(raw) if codec == "zst" else bz2.compress(raw) + + +@pytest.mark.parametrize("codec", ["zst", "bz2"]) +def test_complete_segment_retains_all_event_envelopes_and_timestamps(codec): + decoded = log_decode.decode_segment(_compressed(_events(), codec), codec) + assert len(decoded) == 2 + assert [(event.which(), event.logMonoTime, event.valid) for event in decoded] == [ + ("deviceState", 101, True), ("carState", 202, False), + ] + assert decoded[0].deviceState.started + + +@pytest.mark.parametrize("codec", ["zst", "bz2"]) +def test_truncated_trailing_and_wrong_codec_reject_entire_segment(codec): + source = _compressed(_events(), codec) + for candidate in (source[:-1], source + _compressed(_events(), codec), source + b"trailing"): + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(candidate, codec) + other = "bz2" if codec == "zst" else "zst" + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(source, other) + + +def test_expansion_compressed_count_and_cereal_corruption_caps(monkeypatch): + raw = _events() + encoded = _compressed(raw, "zst") + monkeypatch.setattr(log_decode, "MAX_COMPRESSED_BYTES", len(encoded) - 1) + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(encoded, "zst") + monkeypatch.setattr(log_decode, "MAX_COMPRESSED_BYTES", 32 * 1024 * 1024) + monkeypatch.setattr(log_decode, "MAX_EXPANDED_BYTES", len(raw) - 1) + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(encoded, "zst") + monkeypatch.setattr(log_decode, "MAX_EXPANDED_BYTES", 64 * 1024 * 1024) + monkeypatch.setattr(log_decode, "MAX_MESSAGES", 1) + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(encoded, "zst") + monkeypatch.setattr(log_decode, "MAX_MESSAGES", 250_000) + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(_compressed(raw + b"not an Event", "zst"), "zst") + + +def test_cancelled_and_wrong_input_never_return_prefix(monkeypatch): + encoded = _compressed(_events(), "zst") + monkeypatch.setattr(log_decode, "CHUNK_BYTES", 8) + calls = 0 + def cancel(): + nonlocal calls + calls += 1 + return calls > 3 + with pytest.raises(log_decode.LogDecodeError, match="cancelled"): + log_decode.decode_segment(encoded, "zst", cancelled=cancel) + decode = mock.Mock(wraps=log_decode.decode_segment) + with pytest.raises(log_decode.LogDecodeError): + decode(bytearray(encoded), "zst") + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(encoded, "raw") + + +def test_event_traversal_limit_rejects_whole_segment(monkeypatch): + monkeypatch.setattr(log_decode, "EVENT_TRAVERSAL_WORDS", 1) + with pytest.raises(log_decode.LogDecodeError, match="Cereal"): + log_decode.decode_segment(_compressed(_events(), "zst"), "zst") + + +@pytest.mark.parametrize("codec", ["zst", "bz2"]) +def test_filtered_retention_still_validates_entire_segment(codec): + encoded = _compressed(_events(), codec) + selected = log_decode.decode_segment(encoded, codec, retain=frozenset(("carState",))) + assert [(event.which(), event.logMonoTime) for event in selected] == [("carState", 202)] + with mock.patch.object(log_decode, "MAX_MESSAGES", 1), pytest.raises(log_decode.LogDecodeError, match="message count"): + log_decode.decode_segment(encoded, codec, retain=frozenset()) + with pytest.raises(log_decode.LogDecodeError): + log_decode.decode_segment(_compressed(_events() + b"not an Event", codec), codec, retain=frozenset()) diff --git a/openpilot/starpilot/flm/tests/__init__.py b/openpilot/starpilot/flm/tests/__init__.py new file mode 100644 index 0000000000..4f1be0bf16 --- /dev/null +++ b/openpilot/starpilot/flm/tests/__init__.py @@ -0,0 +1 @@ +"""Offline FLM tests.""" diff --git a/openpilot/starpilot/flm/tests/test_analyze.py b/openpilot/starpilot/flm/tests/test_analyze.py new file mode 100644 index 0000000000..9b70e5277c --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_analyze.py @@ -0,0 +1,55 @@ +"""The desktop report joins real local-file admission, decompression and events.""" + +import json + +import pytest +import zstandard as zstd + +from openpilot.cereal import messaging +from openpilot.starpilot.flm import analyze +from openpilot.starpilot.flm.local_logs import LocalLogUnavailable + + +SEGMENT = "1234abcd--0123456789--0" + + +def test_desktop_report_for_missing_controller_is_honest_and_source_bound(tmp_path, monkeypatch, capsys): + monkeypatch.setattr(analyze, "PC", True) + folder = tmp_path / SEGMENT + folder.mkdir() + event = messaging.new_message("carState", valid=True) + event.logMonoTime = 100 + (folder / "rlog.zst").write_bytes(zstd.compress(event.to_bytes())) + assert analyze.main(["--log-root", str(tmp_path.resolve()), SEGMENT]) == 0 + report = json.loads(capsys.readouterr().out) + assert report["purpose"] == "offline_tracking_diagnostics" + assert report["vehicleQualification"] is False and report["tuneRecommendation"] is None + segment = report["segments"][0] + assert segment["analysis"]["status"] == "missing_car_params" + assert segment["analysis"]["mean_abs_error"] is None + assert len(segment["source"]["sha256"]) == 64 + assert segment["source"]["segmentName"] == SEGMENT + output = tmp_path / "report.json" + args = ["--log-root", str(tmp_path.resolve()), "--output", str(output), SEGMENT] + assert analyze.main(args) == 0 + assert json.loads(output.read_text()) == report + original = output.read_bytes() + assert analyze.main(args) == 1 + assert output.read_bytes() == original + + +def test_device_duplicate_and_failed_second_segment_never_emit_partial_report(tmp_path, monkeypatch, capsys): + monkeypatch.setattr(analyze, "PC", False) + with pytest.raises(ValueError, match="desktop"): + analyze.analyze_local(tmp_path.resolve(), [SEGMENT]) + monkeypatch.setattr(analyze, "PC", True) + with pytest.raises(ValueError, match="distinct"): + analyze.analyze_local(tmp_path.resolve(), [SEGMENT, SEGMENT]) + folder = tmp_path / SEGMENT + folder.mkdir() + event = messaging.new_message("carState", valid=True) + (folder / "rlog.zst").write_bytes(zstd.compress(event.to_bytes())) + assert analyze.main(["--log-root", str(tmp_path.resolve()), SEGMENT, "1234abcd--0123456789--1"]) == 1 + assert capsys.readouterr().out == "" + with pytest.raises(LocalLogUnavailable): + analyze.analyze_local(tmp_path.resolve(), [SEGMENT], cancelled=lambda: True) diff --git a/openpilot/starpilot/flm/tests/test_automatic_integration.py b/openpilot/starpilot/flm/tests/test_automatic_integration.py new file mode 100644 index 0000000000..06eaa5cef5 --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_automatic_integration.py @@ -0,0 +1,225 @@ +"""Composed automatic fit application; synthetic evidence, actual owners and wire.""" + +from contextlib import contextmanager +from dataclasses import replace +import json +import math +import os +from pathlib import Path +import struct +import unittest +from unittest import mock + +from opendbc.car.car_helpers import interfaces +from opendbc.car.gm.values import CAR as GM +from opendbc.car.hyundai.values import CAR as HKG +from openpilot.cereal import messaging +from openpilot.common.params import Params +from openpilot.common.prefix import OpenpilotPrefix +from openpilot.selfdrive.controls.controlsd import Controls +from openpilot.starpilot.flm.automatic import identity_digest +from openpilot.starpilot.flm.learning_producer import AutomaticLearningProducer +from openpilot.starpilot.flm.learning_source import ( + AutomaticLearningConsumer, MAX_AGE_NS, RESET_KEY, SERVICE, learning_payload, +) +from openpilot.starpilot.flm.tests import test_automatic as evidence +from openpilot.starpilot.lateral.controller_selection import ControllerMode, DOCUMENT_KEY as CONTROLLER_KEY, policy_for, replace_mode +from openpilot.starpilot.lateral.learning_preferences import KEY as PREFERENCE_KEY, replace_preference +from openpilot.starpilot.lateral.tests.test_lane_runtime import feed, publish_corolla_params +from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY as TORQUE_KEY, replace_field, serialize_document + +NOW = 400_000_000_000 + + +def float32(value): + """The controller's CarParams torque fields are Float32, not Python doubles.""" + return struct.unpack(' 1e-7 for row, base in zip(tuned, baseline, strict=True))) + self.assertEqual(tuned[0][0], 0.0) + self.assertEqual(tuned[-5][0], 0.0) # inactive reset frame + + def test_invalid_surface_rejected_before_parent_mutation(self): + cp = _params() + parent = _controller(cp) + original = (parent.pid, parent.torque_params.latAccelFactor, selected_policy(parent)) + with self.assertRaises(ValueError): + Ioniq6TorquePolicy(parent, cp.as_reader(), surface=Ioniq6Surface.validated("firmware_2025", {})) + self.assertIs(parent.pid, original[0]) + self.assertEqual(parent.torque_params.latAccelFactor, original[1]) + self.assertIs(selected_policy(parent), original[2]) + with self.assertRaises(ValueError): + Ioniq6TorquePolicy(parent, cp.as_reader(), surface=object()) + other = interfaces[TOYOTA.TOYOTA_COROLLA_TSS2].get_non_essential_params(TOYOTA.TOYOTA_COROLLA_TSS2) + with self.assertRaises(ValueError): + Ioniq6TorquePolicy(parent, other.as_reader(), surface=Ioniq6Surface.validated("standard", {})) + self.assertIs(parent.pid, original[0]) + + +if __name__ == "__main__": + unittest.main() diff --git a/openpilot/starpilot/flm/tests/test_local_logs.py b/openpilot/starpilot/flm/tests/test_local_logs.py new file mode 100644 index 0000000000..1c6dd66b89 --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_local_logs.py @@ -0,0 +1,101 @@ +"""Local FLM input admission uses disposable recordings and never remote routes.""" + +import hashlib +import os +from unittest.mock import patch + +import pytest + +from openpilot.starpilot.flm.local_logs import LocalLogUnavailable, read_closed_rlog + + +SEGMENT = "1234abcd--0123456789--0" + + +def recording(tmp_path, name="rlog.zst"): + root = tmp_path.resolve() + folder = root / SEGMENT + folder.mkdir() + path = folder / name + path.write_bytes(b"immutable compressed fixture") + return root, path + + +def test_receipt_binds_exact_bytes_and_requires_full_log(tmp_path): + root, path = recording(tmp_path) + result = read_closed_rlog(root, SEGMENT, permitted=lambda: True) + assert result.compressed == path.read_bytes() + assert result.sha256 == hashlib.sha256(result.compressed).hexdigest() + assert result.codec == "zst" and result.size == len(result.compressed) + path.rename(path.with_name("qlog.zst")) + with pytest.raises(LocalLogUnavailable, match="full rlog"): + read_closed_rlog(root, SEGMENT, permitted=lambda: True) + + +@pytest.mark.parametrize("name", ("rlog.lock", "writer.lock")) +def test_open_segment_is_not_analyzed(tmp_path, name): + root, path = recording(tmp_path) + path.with_name(name).touch() + with pytest.raises(LocalLogUnavailable, match="open"): + read_closed_rlog(root, SEGMENT, permitted=lambda: True) + + +def test_symlink_fifo_ambiguous_and_outside_selection_refused(tmp_path): + root, path = recording(tmp_path) + for selection in ("../" + SEGMENT, "/" + SEGMENT, SEGMENT + "/rlog.zst", "https://example.com/log"): + with pytest.raises(LocalLogUnavailable): + read_closed_rlog(root, selection, permitted=lambda: True) + path.with_name("rlog.bz2").write_bytes(b"ambiguous") + with pytest.raises(LocalLogUnavailable): + read_closed_rlog(root, SEGMENT, permitted=lambda: True) + path.with_name("rlog.bz2").unlink() + path.unlink() + external = root / "external" + external.write_bytes(b"not a selected recording") + path.symlink_to(external) + with pytest.raises(LocalLogUnavailable): + read_closed_rlog(root, SEGMENT, permitted=lambda: True) + path.unlink() + os.mkfifo(path) + with pytest.raises(LocalLogUnavailable): + read_closed_rlog(root, SEGMENT, permitted=lambda: True) + + +@pytest.mark.parametrize("change", ("replace", "mutate", "lock", "segment", "cancel")) +def test_changes_during_read_never_return_a_receipt(tmp_path, change): + root, path = recording(tmp_path) + allowed = [True] + native_read = os.read + changed = False + def interrupted(fd, size): + nonlocal changed + result = native_read(fd, size) + if result and not changed: + changed = True + if change == "replace": + other = path.with_name("replacement") + other.write_bytes(result) + other.replace(path) + elif change == "mutate": + path.write_bytes(b"X" * len(result)) + os.utime(path, ns=(0, 0)) + elif change == "lock": + path.with_name("rlog.lock").touch() + elif change == "segment": + path.parent.rename(root / (SEGMENT + "-moved")) + path.parent.mkdir() + else: + allowed[0] = False + return result + with patch("openpilot.starpilot.flm.local_logs.os.read", side_effect=interrupted), pytest.raises(LocalLogUnavailable): + read_closed_rlog(root, SEGMENT, permitted=lambda: allowed[0]) + + +def test_size_limit_and_cancel_before_any_open(tmp_path): + root, path = recording(tmp_path) + with patch("openpilot.starpilot.flm.local_logs.MAX_COMPRESSED_BYTES", len(path.read_bytes()) - 1), \ + pytest.raises(LocalLogUnavailable, match="oversized"): + read_closed_rlog(root, SEGMENT, permitted=lambda: True) + with patch("openpilot.starpilot.flm.local_logs.os.open") as opened, pytest.raises(LocalLogUnavailable): + read_closed_rlog(root, SEGMENT, permitted=lambda: False) + opened.assert_not_called() diff --git a/openpilot/starpilot/flm/tests/test_offline.py b/openpilot/starpilot/flm/tests/test_offline.py new file mode 100644 index 0000000000..a3fc98a7fa --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_offline.py @@ -0,0 +1,272 @@ +"""Serialized current Cereal traces and frozen override-mask differential.""" + +import math +from contextlib import ExitStack +import unittest + +from openpilot.cereal import log +from openpilot.starpilot.flm.offline import SegmentInput, TrackingSample, _eligible, analyze_segments +from opendbc.car.hyundai.values import CAR + + +def event(kind, ns, *, valid=True, **fields): + builder = log.Event.new_message(logMonoTime=ns, valid=valid) + payload = builder.init(kind) + if kind == 'carParams': + payload.carFingerprint = fields.get('fingerprint', CAR.HYUNDAI_IONIQ_6) + payload.lateralTuning.init(fields.get('tuning', 'torque')) + payload.steerControlType = fields.get('steering_type', 'torque') + payload.dashcamOnly = fields.get('dashcam', False) + elif kind == 'carState': + payload.vEgo = fields.get('speed', 12.0) + payload.steeringPressed = fields.get('pressed', False) + payload.canValid = fields.get('can_valid', True) + elif kind == 'carControl': + payload.latActive = fields.get('lat_active', True) + elif kind == 'controlsState': + state = payload.lateralControlState + state.init(fields.get('controller', 'torqueState')) + if fields.get('controller', 'torqueState') == 'torqueState': + state.torqueState.desiredLateralAccel = fields.get('desired', 0.4) + state.torqueState.actualLateralAccel = fields.get('actual', 0.3) + state.torqueState.active = fields.get('active', True) + return builder + + +def serialized(builders): + with ExitStack() as stack: + for builder in builders: + yield stack.enter_context(log.Event.from_bytes(builder.as_reader().as_builder().to_bytes())) + + +def segment(*, number=0, count=25, pressed=(), fingerprint=CAR.HYUNDAI_IONIQ_6, gap_at=None, + invalid_first=False, other_last=False, bad_numeric_at=None, invalid_control_at=None): + base = 1_000_000_000 + events = [event('carParams', base, fingerprint=fingerprint)] + for i in range(count): + ns = base + (i + 1) * 100_000_000 + (1_000_000_000 if gap_at is not None and i >= gap_at else 0) + events += [event('carState', ns, pressed=i in pressed, valid=not (invalid_first and i == 0)), + event('carControl', ns, valid=i != invalid_control_at), + event('controlsState', ns, controller='pidState' if other_last and i == count - 1 else 'torqueState', + desired=float('nan') if i == bad_numeric_at else 0.4)] + return SegmentInput('synthetic', number, serialized(events)) + + +def frozen_mask(samples): + """Independent translation of frozen flm_workspace._analysis_eligibility_mask.""" + eligible = [True for _ in samples] + last_override = -math.inf + for index, sample in enumerate(samples): + t = sample.mono_ns / 1e9 + if sample.steering_pressed: + last_override = t + if sample.steering_pressed or t - last_override <= 1.0: + eligible[index] = False + next_override = math.inf + for index in range(len(samples) - 1, -1, -1): + sample = samples[index] + t = sample.mono_ns / 1e9 + if sample.steering_pressed: + next_override = t + if sample.steering_pressed or next_override - t <= 0.35: + eligible[index] = False + eligible[0] = eligible[-1] = False + return eligible + + +class OfflineTest(unittest.TestCase): + def test_serialized_current_ioniq_torque_tracking(self): + result = analyze_segments((segment(),)).segments[0] + self.assertEqual(result.status, 'measured') + self.assertEqual(result.eligible_samples, 23) + assert result.mean_abs_error is not None + assert result.root_mean_square_error is not None + self.assertAlmostEqual(result.mean_abs_error, 0.1, places=6) + self.assertAlmostEqual(result.root_mean_square_error, 0.1, places=6) + self.assertEqual((result.series[0].desired_lat_accel, result.series[0].actual_lat_accel), (0.4000000059604645, 0.30000001192092896)) + self.assertEqual(len(result.windows), 1) + self.assertEqual(result.windows[0].sample_count, 23) + self.assertEqual(result.windows[0].direction, 'left') + + def test_late_consistent_car_params_has_same_complete_segment_report(self): + base = 1_000_000_000 + samples = [] + for i in range(25): + ns = base + (i + 1) * 100_000_000 + samples.extend((event('carState', ns), event('carControl', ns), event('controlsState', ns))) + def analyze(events): + return analyze_segments((SegmentInput('same', 0, serialized(events)),)).segments[0] + early = analyze([event('carParams', base), *samples]) + late = analyze([*samples, event('carParams', base + 4_000_000_000)]) + repeated = analyze([*samples, event('carParams', base + 4_000_000_000), event('carParams', base)]) + self.assertEqual(early, late) + self.assertEqual(late.eligible_samples, 23) + self.assertEqual(repeated.eligible_samples, early.eligible_samples) + self.assertNotIn('missing_or_unsupported_car_params', dict(late.exclusions)) + + def test_late_invalid_or_changed_car_params_rejects_entire_segment(self): + base = 1_000_000_000 + samples = [] + for i in range(25): + ns = base + (i + 1) * 100_000_000 + samples.extend((event('carState', ns), event('carControl', ns), event('controlsState', ns))) + changed = event('carParams', base + 4_000_000_000) + changed.carParams.lateralTuning.torque.friction = .2 + for cp, reason in ((changed, 'inconsistent_car_params'), + (event('carParams', base + 4_000_000_000, valid=False), 'invalid_car_params'), + (event('carParams', 0), 'invalid_car_params')): + with self.subTest(reason=reason), self.assertRaisesRegex(ValueError, reason): + analyze_segments((SegmentInput('same', 0, serialized([event('carParams', base), *samples, cp])),)) + + def test_frozen_override_mask_and_gap_boundary(self): + samples = [TrackingSample(1_000_000_000 + i * 100_000_000, 12.0, .4, .3, False, i in (5, 17)) for i in range(25)] + self.assertEqual(_eligible(samples), frozen_mask(samples)) + result = analyze_segments((segment(pressed=(5, 17), gap_at=12),)).segments[0] + self.assertGreater(dict(result.exclusions)['driver_override_or_boundary'], 0) + self.assertLess(result.eligible_samples, 23) + + def test_wrong_car_and_non_torque_are_not_measured(self): + wrong = analyze_segments((segment(fingerprint='NOT_IONIQ'),)).segments[0] + self.assertEqual(wrong.status, 'unsupported_car') + self.assertEqual(wrong.eligible_samples, 0) + result = analyze_segments((segment(count=3, other_last=True),)).segments[0] + self.assertEqual(dict(result.exclusions)['other_controller'], 1) + + def test_missing_invalid_stale_sources_and_segment_independence(self): + report = analyze_segments((segment(count=5, invalid_first=True, invalid_control_at=1, bad_numeric_at=2), + segment(number=1, count=5))).segments + self.assertEqual(dict(report[0].exclusions)['missing_or_stale_source'], 2) + self.assertEqual(dict(report[0].exclusions)['invalid_numeric'], 1) + self.assertEqual(report[1].status, 'measured') + + def test_series_and_message_bounds(self): + report = analyze_segments((segment(count=300),)).segments[0] + self.assertEqual(len(report.series), 160) + self.assertLess(report.series[0].mono_ns, report.series[-1].mono_ns) + + def test_bounds_cancel_and_inconsistent_cp(self): + with self.assertRaisesRegex(ValueError, 'segment_count'): + analyze_segments(()) + with self.assertRaisesRegex(RuntimeError, 'cancelled'): + analyze_segments((segment(),), cancelled=lambda: True) + events = [event('carParams', 1_000_000_000), event('carParams', 1_000_000_001, fingerprint='OTHER')] + with self.assertRaisesRegex(ValueError, 'inconsistent_car_params'): + analyze_segments((SegmentInput('a', 0, serialized(events)),)) + + repeated = event('carParams', 1_000_000_002) + repeated.carParams.lateralTuning.torque.friction = .2 + with self.assertRaisesRegex(ValueError, 'inconsistent_car_params'): + analyze_segments((SegmentInput('a', 0, serialized([event('carParams', 1_000_000_000), repeated])),)) + + def test_inactive_press_masks_neighbors_and_breaks_window(self): + base = 1_000_000_000 + events = [event('carParams', base)] + for i in range(30): + ns = base + (i + 1) * 100_000_000 + events.extend((event('carState', ns, pressed=i == 8), event('carControl', ns, lat_active=i != 8), + event('controlsState', ns))) + report = analyze_segments((SegmentInput('a', 0, serialized(events)),)).segments[0] + press_ns = base + 900_000_000 + self.assertTrue(all(not -350_000_000 <= point.mono_ns - press_ns <= 1_000_000_000 for point in report.series)) + self.assertEqual(len(report.windows), 1) + self.assertGreater(report.windows[0].start_mono_ns, press_ns + 1_000_000_000) + + def test_short_invalid_gap_does_not_bridge_and_unrelated_interleaving_is_ignored(self): + base = 1_000_000_000 + events = [event('carParams', base)] + for i in range(25): + ns = base + (i + 1) * 100_000_000 + events.append(event('carState', ns)) + if i == 10: + events.append(event('initData', ns - 50_000_000)) # cross-service chronology is not global + events.append(event('carControl', ns, valid=i != 12)) + events.append(event('controlsState', ns)) + report = analyze_segments((SegmentInput('a', 0, serialized(events)),)).segments[0] + self.assertEqual(len(report.windows), 2) + self.assertEqual(dict(report.exclusions)['missing_or_stale_source'], 1) + self.assertNotIn('invalid_or_reordered_timestamp', dict(report.exclusions)) + before = {point.continuity_id for point in report.series if point.mono_ns < base + 1_300_000_000} + after = {point.continuity_id for point in report.series if point.mono_ns > base + 1_300_000_000} + self.assertTrue(before and after) + self.assertTrue(before.isdisjoint(after)) + + def test_future_publisher_arrives_before_earlier_controls_frame(self): + base = 1_000_000_000 + events = [event('carParams', base)] + for i in range(12): + ns = base + (i + 1) * 100_000_000 + if i != 4: + events.extend((event('carState', ns), event('carControl', ns))) + if i == 3: + future = ns + 100_000_000 + events.extend((event('carState', future), event('carControl', future))) + events.append(event('controlsState', ns)) + report = analyze_segments((SegmentInput('a', 0, serialized(events)),)).segments[0] + self.assertEqual(report.status, 'measured') + self.assertEqual(report.eligible_samples, 10) + self.assertNotIn('missing_or_stale_source', dict(report.exclusions)) + + def test_invalid_vehicle_source_and_extreme_values(self): + events = [event('carParams', 1_000_000_000)] + for i in range(6): + ns = 1_100_000_000 + i * 100_000_000 + events.extend((event('carState', ns, can_valid=i != 0), event('carControl', ns), + event('controlsState', ns, desired=3.4e38 if i == 2 else .4, active=i != 3))) + report = analyze_segments((SegmentInput('a', 0, serialized(events)),)).segments[0] + self.assertEqual(dict(report.exclusions)['invalid_car_state'], 1) + self.assertEqual(dict(report.exclusions)['invalid_numeric'], 1) + self.assertEqual(dict(report.exclusions)['lateral_inactive'], 1) + self.assertIsNone(report.mean_abs_error) + + +if __name__ == '__main__': + unittest.main() + + +class GmEvidenceJoinTest(unittest.TestCase): + def test_actual_factory_context_serialized_epochs_original_profiles_and_mismatch_rejection(self): + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_ascm_intercept import params as ordinary_params + from opendbc.car.gm.values import CAR as GM_CAR + from openpilot.starpilot.flm.gm_recommend import source_context, classify_groups, build_report + from openpilot.starpilot.lateral.torque_settings import PlatformProfile, FieldChoice + cp_builder = ordinary_params(GM_CAR.CHEVROLET_MALIBU_ASCM) + cp_builder.init('carFw', 1)[0].fwVersion = b'\x00\xfffirmware' + cp = cp_builder.as_reader() + tune = cp.lateralTuning.torque + with OpenpilotPrefix(): + context = source_context(cp, 'starpilot', Params(), 'a'*64, + PlatformProfile((tune.latAccelFactor, tune.latAccelOffset, tune.friction), FieldChoice(), FieldChoice())) + events = [] + params_event = log.Event.new_message(logMonoTime=1_000_000_000, valid=True) + params_event.init('carParams').from_dict(cp.to_dict()) + events.append(params_event) + for index in range(500): + ns = 1_000_000_000 + (index+1)*20_000_000 + (1_000_000_000 if index >= 250 else 0) + state = event('carState', ns, pressed=index == 100) + state.carState.steeringAngleDeg = 3. + command = event('carControl', ns) + control = event('controlsState', ns, desired=.8, actual=.1) + control.controlsState.lateralControlState.torqueState.output = .2 + events.extend((state, command, control)) + groups = [] + result = analyze_segments((SegmentInput('synthetic-gm-recording', 0, serialized(events)),), gm_context=context, evidence=groups) + self.assertEqual(result.segments[0].status, 'measured') + self.assertGreaterEqual(len(groups), 3) + self.assertTrue(all(all(0 < b.t-a.t <= .251 for a,b in zip(group,group[1:], strict=False)) for group in groups)) + self.assertTrue(all(not sample.steering_pressed for group in groups for sample in group)) + summaries, stats = classify_groups(groups) + self.assertGreater(stats['sampleCount'], 0) + report = build_report(context, summaries, stats) + self.assertEqual({path['key'] for path in report['paths']}, {'baseline_fix', 'cleanup_pass'}) + self.assertTrue(any(path['profiles'] for path in report['paths'])) + self.assertFalse(report['fit']) + self.assertFalse(report['vehicleQualification']) + with self.assertRaises(ValueError): + build_report(context, summaries, stats, feedback={'acceptedDimensions':['invented-dimension']}) + wrong = {**context, 'cpSignature': 'b'*64} + rejected = [] + result = analyze_segments((SegmentInput('synthetic-gm-recording', 0, serialized(events)),), gm_context=wrong, evidence=rejected) + self.assertEqual(result.segments[0].status, 'unsupported_car') + self.assertEqual(rejected, []) diff --git a/openpilot/starpilot/flm/tests/test_operation_owner.py b/openpilot/starpilot/flm/tests/test_operation_owner.py new file mode 100644 index 0000000000..01f394b41f --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_operation_owner.py @@ -0,0 +1,574 @@ +"""One isolated FLM operation never publishes a partial or unparked report.""" + +from pathlib import Path +import json +import subprocess +import sys +import threading +import time +from unittest import mock + +import pytest +import zstandard as zstd + +from openpilot.cereal import messaging +from openpilot.starpilot.flm.operation_owner import FlmAnalysisOwner, FlmOperationError + + +SEGMENT = '1234abcd--0123456789--0' + + +def recording(tmp_path: Path, *, valid: bool = True) -> Path: + root = tmp_path.resolve() + folder = root / SEGMENT + folder.mkdir() + event = messaging.new_message('deviceState', valid=True) + event.logMonoTime = 1234 + (folder / 'rlog.zst').write_bytes(zstd.ZstdCompressor().compress(event.to_bytes()) if valid else b'bad zstd') + return root + + +def terminal(owner: FlmAnalysisOwner) -> dict: + deadline = time.monotonic() + 5 + while time.monotonic() < deadline: + state = owner.snapshot() + if state['state'] != 'running': + return state + time.sleep(0.01) + raise AssertionError('operation did not terminate') + + +def test_real_local_worker_report_source_identity_and_stale_id(tmp_path): + owner = FlmAnalysisOwner(root=recording(tmp_path), parked=lambda: True) + try: + started = owner.start((SEGMENT,)) + assert started['operationId'].count(':') == 1 and started['selected'] == 1 + assert terminal(owner)['state'] == 'completed' + report = owner.report(started['operationId']) + assert report['schemaVersion'] == 1 and report['vehicleQualification'] is False + assert report['segments'][0]['source']['segmentName'] == SEGMENT + assert report['segments'][0]['analysis']['status'] == 'missing_car_params' + report['segments'].clear() + assert len(owner.report(started['operationId'])['segments']) == 1 + next_run = owner.start((SEGMENT,)) + with pytest.raises(FlmOperationError, match='operation_changed'): + owner.report(started['operationId']) + assert terminal(owner)['state'] == 'completed' + assert owner.report(next_run['operationId'])['operationId'] == next_run['operationId'] + finally: + owner.close() + + +def test_request_thread_can_exit_while_monitor_owned_child_completes(tmp_path): + owner = FlmAnalysisOwner(root=recording(tmp_path), parked=lambda: True) + replies = [] + request_thread = threading.Thread(target=lambda: replies.append(owner.start((SEGMENT,)))) + try: + request_thread.start() + request_thread.join(timeout=2) + assert not request_thread.is_alive() and len(replies) == 1 + assert terminal(owner)['state'] == 'completed' + assert owner.report(replies[0]['operationId'])['segments'][0]['analysis']['status'] == 'missing_car_params' + finally: + owner.close() + + +def test_failed_monitor_start_is_unavailable_and_does_not_wedge_future_analysis(tmp_path): + owner = FlmAnalysisOwner(root=recording(tmp_path), parked=lambda: True) + try: + with mock.patch.object(threading.Thread, 'start', side_effect=RuntimeError('thread unavailable')): + with pytest.raises(FlmOperationError, match='unavailable'): + owner.start((SEGMENT,)) + assert owner.snapshot()['state'] == 'failed' + token = owner.start((SEGMENT,))['operationId'] + assert terminal(owner)['state'] == 'completed' + assert owner.report(token)['operationId'] == token + finally: + owner.close() + + +def test_corrupt_and_symlinked_local_sources_publish_no_report(tmp_path): + root = recording(tmp_path, valid=False) + owner = FlmAnalysisOwner(root=root, parked=lambda: True) + try: + token = owner.start((SEGMENT,))['operationId'] + assert terminal(owner)['state'] == 'unavailable' + with pytest.raises(FlmOperationError): + owner.report(token) + path = root / SEGMENT / 'rlog.zst' + path.unlink() + path.symlink_to(root / 'outside') + token = owner.start((SEGMENT,))['operationId'] + assert terminal(owner)['state'] == 'unavailable' + with pytest.raises(FlmOperationError): + owner.report(token) + finally: + owner.close() + + +def test_cancel_busy_and_onroad_kill_isolated_slow_child(tmp_path): + root = recording(tmp_path) + parked = [True] + slow_worker = (sys.executable, '-c', 'import sys,time;sys.stdin.buffer.read();time.sleep(30)') + owner = FlmAnalysisOwner(root=root, parked=lambda: parked[0], worker_argv=slow_worker) + try: + token = owner.start((SEGMENT,))['operationId'] + with pytest.raises(FlmOperationError, match='busy'): + owner.start((SEGMENT,)) + assert owner.cancel(token)['state'] == 'canceled' + token = owner.start((SEGMENT,))['operationId'] + with owner._lock: + parked[0] = False + assert owner.snapshot()['state'] == 'unavailable' + parked[0] = True + with pytest.raises(FlmOperationError, match='busy'): + owner.start((SEGMENT,)) + parked[0] = False + assert terminal(owner)['state'] == 'unavailable' + with pytest.raises(FlmOperationError): + owner.report(token) + finally: + owner.close() + + +def test_worker_pipe_eof_while_alive_and_selector_failure_reap(tmp_path): + root = recording(tmp_path) + eof_worker = (sys.executable, '-c', 'import os,sys,time;sys.stdin.buffer.read();os.close(1);time.sleep(30)') + owner = FlmAnalysisOwner(root=root, parked=lambda: True, worker_argv=eof_worker) + try: + owner.start((SEGMENT,)) + assert terminal(owner)['state'] == 'failed' + assert owner._child is None + finally: + owner.close() + + class BrokenSelector: + def __enter__(self): + return self + def __exit__(self, *args): + return False + def register(self, *_args): + raise OSError('injected selector failure') + + with mock.patch('openpilot.starpilot.flm.operation_owner.selectors.DefaultSelector', BrokenSelector): + owner = FlmAnalysisOwner(root=root, parked=lambda: True, worker_argv=eof_worker) + try: + owner.start((SEGMENT,)) + assert terminal(owner)['state'] == 'failed' + assert owner._child is None + finally: + owner.close() + + +def test_close_stops_child_and_revokes_report(tmp_path): + owner = FlmAnalysisOwner(root=recording(tmp_path), parked=lambda: True) + token = owner.start((SEGMENT,))['operationId'] + assert terminal(owner)['state'] == 'completed' + owner.close() + with pytest.raises(FlmOperationError, match='unavailable'): + owner.report(token) + + +def test_worker_rejects_stale_parent_identity_before_any_log_read(tmp_path): + root = recording(tmp_path) + child = subprocess.run((sys.executable, '-m', 'openpilot.starpilot.flm.operation_worker'), + input=json.dumps({'root': str(root), 'segments': [SEGMENT], 'parentPid': 1}).encode(), + capture_output=True, timeout=5, check=False) + assert child.returncode != 0 + assert b'"kind":"result"' not in child.stdout + assert b'"code":"process_failed"' in child.stdout + + +def test_wall_deadline_stops_and_reaps_child(tmp_path): + worker = (sys.executable, '-c', 'import sys,time;sys.stdin.buffer.read();time.sleep(30)') + with mock.patch('openpilot.starpilot.flm.operation_owner.WALL_DEADLINE_SECONDS', 0.05): + owner = FlmAnalysisOwner(root=recording(tmp_path), parked=lambda: True, worker_argv=worker) + try: + owner.start((SEGMENT,)) + status = terminal(owner) + assert status['state'] == 'failed' and status['errorCode'] == 'deadline' + assert owner._child is None + finally: + owner.close() + + +def test_invalid_selection_and_unparked_start_do_not_spawn(tmp_path): + owner = FlmAnalysisOwner(root=tmp_path.resolve(), parked=lambda: False) + try: + for names in ((), (SEGMENT, SEGMENT), ('../outside',)): + with pytest.raises(FlmOperationError, match='invalid_request'): + owner.start(names) + with pytest.raises(FlmOperationError, match='not_parked'): + owner.start((SEGMENT,)) + assert owner.snapshot()['state'] == 'idle' + finally: + owner.close() + + +def test_gm_live_trial_atomic_restore_preserves_other_choices_and_rejects_changed_source(): + from dataclasses import replace + from types import SimpleNamespace + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_ascm_intercept import params as ordinary_params + from opendbc.car.gm.values import CAR + from openpilot.starpilot.flm.operation_owner import FlmTrialOwner + from openpilot.starpilot.flm.live import GmLiveSource, gm_capability + from openpilot.starpilot.flm.torque_surface import GmSurface + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import (DOCUMENT_KEY, FieldChoice, parse_document, replace_field, + replace_geometry, serialize_document) + cp = ordinary_params(CAR.CHEVROLET_MALIBU_ASCM).as_reader() + with OpenpilotPrefix(): + saved = Params() + mode = ControllerMode.STARPILOT + saved.put('LateralControllerSelection', json.loads(replace_mode(None, cp, mode)), block=True) + cap = gm_capability(cp, mode) + identity = cap['fingerprint'] + profiles = replace_field({}, identity, cap['basis'], 'friction', 'custom', cap['basis'][2] * 1.1) + profiles = replace_geometry(profiles, identity, cap['basis'], (cp.steerRatio, cp.steerActuatorDelay+.2), + 'ratio', FieldChoice('custom', cp.steerRatio * 1.1)) + saved.put(DOCUMENT_KEY, json.loads(serialize_document(profiles)), block=True) + context = SimpleNamespace(cp=cp, cp_raw=cp.as_builder().to_bytes(), parked=True) + owner = FlmTrialOwner(saved, SimpleNamespace(sample=lambda: context)) + + def action(operation, **fields): + return owner.action({'action': operation, 'token': owner.snapshot()['token'], **fields}) + + for key, gain in (('baseline', .1), ('trial', .3)): + action('save', id=key, label=key, surface=GmSurface(cap['profile'], {'ff_gain_left': gain}).document()) + first = action('apply', id='baseline') + action('accept', trial=first['state']['trial']) + trial = action('trial', id='trial') + token = trial['state']['trial'] + self_profile = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes())[identity] + assert self_profile.flm.active == 'trial' and self_profile.flm.baseline_active == 'baseline' + source = GmLiveSource(cp, mode, saved) + assert source.sample(active=True, speed=20., now_ns=1_000_000_000).knobs['ff_gain_left'] == .3 + before = Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() + with pytest.raises(FlmOperationError, match='busy'): + action('save', id='baseline', label='changed', surface=GmSurface(cap['profile'], {}).document()) + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == before + restored = action('restore', trial=token) + assert restored['state']['active'] == 'baseline' + trial = action('trial', id='trial') + token = trial['state']['trial'] + before = Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() + # A concurrent explicit manual edit rejects even refreshed restore. Accept + # keeps that user edit and clears the old baseline without overwriting it. + latest = parse_document(before) + latest = replace_field(latest, identity, cap['basis'], 'friction', 'custom', cap['basis'][2] * 1.2) + saved.put(DOCUMENT_KEY, json.loads(serialize_document(latest)), block=True) + with pytest.raises(FlmOperationError, match='operation_changed'): + owner.action({'action': 'restore', 'token': trial['token'], 'trial': token}) + with pytest.raises(FlmOperationError, match='operation_changed'): + action('restore', trial=token) + assert owner.snapshot()['manualConflict'] + restored = action('accept', trial=token) + after = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) + assert after[identity].friction == latest[identity].friction + assert after[identity].geometry == profiles[identity].geometry + assert after[identity].flm.active == 'trial' and after[identity].flm.trial is None + assert restored['state']['applied'] + assert source.sample(active=True, speed=20., now_ns=2_000_000_000).knobs['ff_gain_left'] == .3 + action('disable') + assert source.sample(active=True, speed=20., now_ns=3_000_000_000) is None + assert len(parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes())[identity].flm.saved) == 2 + frozen = Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() + valid = iter((True, False)) + with pytest.raises(FlmOperationError, match='operation_changed'): + owner.action({'action': 'trial', 'token': owner.snapshot()['token'], 'id': 'trial'}, + session_valid=lambda: next(valid, False)) + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == frozen, 'authority is rechecked before atomic write' + context.parked = False + with pytest.raises(FlmOperationError, match='not_parked'): + action('trial', id='trial') + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == frozen + context.parked = True + bad = cp.as_builder() + bad.lateralTuning.torque.latAccelFactor *= 1.01 + context.cp, context.cp_raw = bad.as_reader(), bad.to_bytes() + snapshot = owner.snapshot() + assert not snapshot['available'] and snapshot['resettable'] + with pytest.raises(FlmOperationError, match='operation_changed'): + action('trial', id='trial') + action('reset') + result = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) + assert result[identity] == replace(after[identity], flm=None), 'changed-basis reset is FLM-only' + assert not Path(saved.get_param_path('FLMTrialApplied')).exists() + + +def test_gm_live_exact_controller_vehicle_basis_absence_and_malformed_never_rewrite(): + from types import SimpleNamespace + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_ascm_intercept import params as ordinary_params + from opendbc.car.gm.values import CAR + from openpilot.starpilot.flm.live import GmLiveSource, gm_capability + from openpilot.starpilot.flm.operation_owner import FlmTrialOwner + from openpilot.starpilot.flm.torque_surface import GmSurface, GmFlmBinding + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY, PlatformProfile, FieldChoice, parse_document, serialize_document + cp = ordinary_params(CAR.CHEVROLET_MALIBU_ASCM).as_reader() + with OpenpilotPrefix(): + saved = Params() + saved.put('LateralControllerSelection', json.loads(replace_mode(None, cp, ControllerMode.STARPILOT)), block=True) + cap = gm_capability(cp, ControllerMode.STARPILOT) + source = GmLiveSource(cp, ControllerMode.STARPILOT, saved) + assert source.sample(active=True, speed=20., now_ns=1_000_000_000) is None + assert not Path(saved.get_param_path(DOCUMENT_KEY)).exists() + binding = GmFlmBinding('starpilot', cap['policy'], cap['basis'], + (('one', 'One', GmSurface(cap['profile'], {'ff_gain_left': .3})),), 'one', True) + for controller, basis, identity in (('standard', cap['basis'], cap['fingerprint']), + ('starpilot', (cap['basis'][0]*1.01, *cap['basis'][1:]), cap['fingerprint']), + ('starpilot', cap['basis'], str(CAR.CADILLAC_XT4))): + from dataclasses import replace + rejected = replace(binding, controller=controller, basis=basis) + raw = serialize_document({identity: PlatformProfile(cap['basis'], FieldChoice(), FieldChoice(), flm=rejected)}) + saved.put(DOCUMENT_KEY, json.loads(raw), block=True) + source.last_ns = None + assert source.sample(active=True, speed=20., now_ns=2_000_000_000) is None + assert parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) == parse_document(raw) + stale_basis = (cap['basis'][0]*1.01, *cap['basis'][1:]) + saved.put(DOCUMENT_KEY, json.loads(serialize_document({cap['fingerprint']: PlatformProfile(stale_basis, FieldChoice(), FieldChoice())})), block=True) + ctx = SimpleNamespace(cp=cp, cp_raw=cp.as_builder().to_bytes(), parked=True) + stale_owner = FlmTrialOwner(saved, SimpleNamespace(sample=lambda: ctx)) + assert not stale_owner.snapshot()['available'], 'outer manual profile basis is also part of live admission' + frozen = Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() + with pytest.raises(FlmOperationError, match='operation_changed'): + stale_owner.action({'action': 'save', 'token': stale_owner.snapshot()['token'], 'id': 'one', 'label': 'One', + 'surface': GmSurface(cap['profile'], {}).document()}) + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == frozen + Path(saved.get_param_path(DOCUMENT_KEY)).write_bytes(b'{') + source.last_ns = None + assert source.sample(active=True, speed=20., now_ns=3_000_000_000) is None + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == b'{' + ctx = SimpleNamespace(cp=cp, cp_raw=cp.as_builder().to_bytes(), parked=True) + assert not FlmTrialOwner(saved, SimpleNamespace(sample=lambda: ctx)).snapshot()['available'] + + +def test_gm_bundle_full_manual_switch_restore_guard_precedence_and_other_vehicle_preserved(): + from dataclasses import replace + from types import SimpleNamespace + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_bolt_cc import params as bolt_params + from opendbc.car.gm.values import CAR + from openpilot.starpilot.flm.operation_owner import FlmTrialOwner + from openpilot.starpilot.flm.live import gm_capability + from openpilot.starpilot.flm.manual_trial import manual_snapshot + from openpilot.starpilot.flm.torque_surface import GmSurface + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import (DOCUMENT_KEY, FieldChoice, GainBasis, GeometryProfile, + PlatformProfile, parse_document, serialize_document) + cp = bolt_params(CAR.CHEVROLET_BOLT_CC_2022_2023, alpha=True).as_reader() + with OpenpilotPrefix(): + saved = Params() + saved.put('LateralControllerSelection', json.loads(replace_mode(None, cp, ControllerMode.STARPILOT)), block=True) + saved.put('AdvancedLateralTune', False, block=True) + saved.put('ForceAutoTuneOff', True, block=True) + cap = gm_capability(cp, ControllerMode.STARPILOT) + identity = cap['fingerprint'] + baseline = PlatformProfile(cap['basis'], FieldChoice(), FieldChoice()) + other = str(CAR.CHEVROLET_MALIBU_ASCM) + profiles = {identity: baseline, other: PlatformProfile((2., 0., .1), FieldChoice('custom', 2.2), FieldChoice())} + saved.put(DOCUMENT_KEY, json.loads(serialize_document(profiles)), block=True) + ctx = SimpleNamespace(cp=cp, cp_raw=cp.as_builder().to_bytes(), parked=True) + owner = FlmTrialOwner(saved, SimpleNamespace(sample=lambda: ctx)) + gain = GainBasis('starpilot', ((0,), (.6,)), cap['basis']) + geometry = GeometryProfile((cp.steerRatio, cp.steerActuatorDelay + .2), FieldChoice('custom', cp.steerRatio * 1.1), + FieldChoice('custom', .7), False, 'force_auto') + one = replace(baseline, factor=FieldChoice('custom', cap['basis'][0] * 1.1), + friction=FieldChoice('custom', min(.1, cap['basis'][2]*1.1)), + proportional_gain=FieldChoice('custom', .7), gain_basis=gain, geometry=geometry) + two = replace(baseline, geometry=replace(geometry, ratio=FieldChoice(), full_delay=FieldChoice(), + automatic_delay=True, learning='source')) + def save(key, profile): + owner.action({'action': 'save', 'token': owner.snapshot()['token'], 'id': key, 'label': key, + 'surface': GmSurface(cap['profile'], {}).document()}, generated_manual=manual_snapshot(profile, identity)) + save('one', one) + save('two', two) + reasons = owner.snapshot()['preconditions']['one'] + assert any('Advanced' in reason for reason in reasons) and any('Off remains' in reason for reason in reasons) + frozen = Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() + with pytest.raises(FlmOperationError, match='unavailable'): + owner.action({'action': 'trial', 'token': owner.snapshot()['token'], 'id': 'one'}) + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == frozen + assert saved.get_bool('ForceAutoTuneOff') and not saved.get_bool('AdvancedLateralTune') + # Only the user explicitly changes prerequisites; FLM never writes them. + saved.put('ForceAutoTuneOff', False, block=True) + saved.put('AdvancedLateralTune', True, block=True) + preferences = {key: saved.get(key) for key in ('ForceAutoTuneOff', 'AdvancedLateralTune', 'LateralControllerSelection')} + def apply(key): + return owner.action({'action': 'trial', 'token': owner.snapshot()['token'], 'id': key}) + trial = apply('one') + current = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) + assert replace(current[identity], flm=None) == one + switched = apply('two') + current = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) + assert replace(current[identity], flm=None) == two, 'source choices replace every earlier custom field' + assert switched['state']['trial'] == trial['state']['trial'] + owner.action({'action': 'restore', 'token': owner.snapshot()['token'], 'trial': trial['state']['trial']}) + current = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) + assert replace(current[identity], flm=None) == baseline + assert current[other] == profiles[other] + assert preferences == {key: saved.get(key) for key in preferences} + from openpilot.starpilot.flm.gm_recommend import build_report, same_numerical_context + source = owner.training_context(owner.snapshot()['token']) + evidence = build_report(source, [], {'sampleCount': 32, 'meanErrorAbs': .03}) + before_progress = Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() + assert not owner.record_cleanup({'gmEvidence': evidence}, session_valid=lambda: False) + assert Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes() == before_progress + assert owner.record_cleanup({'gmEvidence': evidence}, session_valid=lambda: True) + recorded = parse_document(Path(saved.get_param_path(DOCUMENT_KEY)).read_bytes()) + assert recorded[identity].flm.cleanup_progress and not recorded[identity].flm.applied + assert replace(recorded[identity], flm=None) == baseline + assert recorded[other] == profiles[other] + assert preferences == {key: saved.get(key) for key in preferences} + fresh = owner.training_context(owner.snapshot()['token']) + assert fresh['cleanupProgress'] and same_numerical_context(fresh, source) + assert not same_numerical_context({**fresh, 'geometryBasis': [cp.steerRatio*1.01, cp.steerActuatorDelay+.2]}, source) + assert build_report(fresh, [], {'sampleCount': 32, 'meanErrorAbs': .03})['decision']['cleanupProgressLocked'] + + + +def test_gm_stale_rich_controller_binding_exposes_reset_only_and_preserves_manual(): + from types import SimpleNamespace + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_bolt_cc import params as bolt_params + from opendbc.car.gm.values import CAR + from openpilot.starpilot.flm.operation_owner import FlmTrialOwner + from openpilot.starpilot.flm.live import gm_capability + from openpilot.starpilot.flm.torque_surface import GmSurface + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY, FieldChoice, PlatformProfile, parse_document, serialize_document + cp = bolt_params(CAR.CHEVROLET_BOLT_CC_2022_2023, alpha=True).as_reader() + with OpenpilotPrefix(): + params = Params() + params.put('LateralControllerSelection', json.loads(replace_mode(None, cp, ControllerMode.STARPILOT)), block=True) + cap = gm_capability(cp, ControllerMode.STARPILOT) + profile = PlatformProfile(cap['basis'], FieldChoice('custom', cap['basis'][0]*1.1), FieldChoice()) + params.put(DOCUMENT_KEY, json.loads(serialize_document({cap['fingerprint']: profile})), block=True) + context = SimpleNamespace(sample=lambda: SimpleNamespace(cp=cp, cp_raw=cp.as_builder().to_bytes(), parked=True)) + owner = FlmTrialOwner(params, context) + owner.action({'action': 'save', 'token': owner.snapshot()['token'], 'id': 'rich', 'label': 'Rich', + 'surface': GmSurface(cap['profile'], {}).document()}) + params.put('LateralControllerSelection', json.loads(replace_mode( + Path(params.get_param_path('LateralControllerSelection')).read_bytes(), cp, ControllerMode.STANDARD)), block=True) + stale = owner.snapshot() + assert not stale['available'] and not stale['editable'] and stale['resettable'] + assert stale['profile'] == 'torque_universal' and stale['state']['saved']['rich']['surface']['profile'] == 'gm_bolt_2022_2023' + owner.action({'action': 'reset', 'token': stale['token']}) + assert owner.snapshot()['available'] + from opendbc.car.lateral import FRICTION_THRESHOLD + assert owner.snapshot()['curveDefaults'] == [FRICTION_THRESHOLD] * 5 + assert parse_document(Path(params.get_param_path(DOCUMENT_KEY)).read_bytes())[cap['fingerprint']] == profile + + + +def test_real_gm_worker_frozen_source_report_cannot_grant_or_mutate_preferences(tmp_path): + from openpilot.cereal import log + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_ascm_intercept import params as ordinary_params + from opendbc.car.gm.values import CAR + from openpilot.starpilot.flm.gm_recommend import source_context + from openpilot.starpilot.lateral.torque_settings import PlatformProfile, FieldChoice + from openpilot.starpilot.flm.tests.test_offline import event + cp = ordinary_params(CAR.CHEVROLET_MALIBU_ASCM).as_reader() + tune = cp.lateralTuning.torque + with OpenpilotPrefix(): + params = Params() + context = source_context(cp, 'starpilot', params, 'a'*64, + PlatformProfile((tune.latAccelFactor, tune.latAccelOffset, tune.friction), FieldChoice(), FieldChoice())) + folder = tmp_path/SEGMENT + folder.mkdir() + cp_event = log.Event.new_message(logMonoTime=1_000_000_000, valid=True) + cp_event.init('carParams').from_dict(cp.to_dict()) + rows = [cp_event] + for index in range(250): + ns = 1_000_000_000 + (index+1)*20_000_000 + state = event('carState', ns) + state.carState.steeringAngleDeg = 3. + controls = event('controlsState', ns, desired=.8, actual=.1) + controls.controlsState.lateralControlState.torqueState.output = .2 + rows.extend((state, event('carControl', ns), controls)) + raw = b''.join(row.to_bytes() for row in rows) + (folder/'rlog.zst').write_bytes(zstd.ZstdCompressor().compress(raw)) + owner = FlmAnalysisOwner(root=tmp_path, parked=lambda: True) + before = {key: params.get(key) for key in ('TorqueOverrideDocument', 'LateralControllerSelection', 'ForceAutoTuneOff', 'AdvancedLateralTune')} + try: + started = owner.start((SEGMENT,), gm_context=context) + assert terminal(owner)['state'] == 'completed' + report = owner.report(started['operationId']) + assert report['purpose'] == 'gm_flm_evidence_profiles' + assert report['gmEvidence']['context'] == context + assert report['gmEvidence']['stats']['sampleCount'] > 0 + assert report['gmEvidence']['fit'] is False and report['vehicleQualification'] is False + assert report['tuneRecommendation'] is None, 'original symptom trials never become an autonomous tuning grant' + assert report['segments'][0]['source']['sha256'] == __import__('hashlib').sha256((folder/'rlog.zst').read_bytes()).hexdigest() + assert before == {key: params.get(key) for key in before}, 'isolated worker has no Params writer' + finally: + owner.close() + + +def test_gm_bundle_preserves_inactive_finite_choices_but_rejects_consumed_bounds(): + from dataclasses import replace + from types import SimpleNamespace + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from opendbc.car.gm.tests.test_ascm_intercept import params as ordinary_params + from opendbc.car.gm.values import CAR + from openpilot.starpilot.flm.live import gm_capability + from openpilot.starpilot.flm.manual_trial import manual_profile, manual_snapshot + from openpilot.starpilot.flm.operation_owner import FlmTrialOwner + from openpilot.starpilot.flm.torque_surface import GmSurface + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import (DOCUMENT_KEY, MAX_DOCUMENT_BYTES, FieldChoice, GainBasis, + PlatformProfile, parse_document, serialize_document) + cp = ordinary_params(CAR.CHEVROLET_MALIBU_ASCM).as_reader() + with OpenpilotPrefix(): + params = Params() + params.put('LateralControllerSelection', json.loads(replace_mode(None, cp, ControllerMode.STARPILOT)), block=True) + cap = gm_capability(cp, ControllerMode.STARPILOT) + identity = cap['fingerprint'] + # Source selections retain previously entered finite numbers, even when + # those inactive numbers are outside the current consumption bounds. + baseline = PlatformProfile(cap['basis'], FieldChoice('source', 10000.), FieldChoice('source', 10000.), + FieldChoice('source', 10000.), GainBasis('starpilot', ((0,), (.6,)), cap['basis'])) + raw = serialize_document({identity: baseline}) + params.put(DOCUMENT_KEY, json.loads(raw), block=True) + owner = FlmTrialOwner(params, SimpleNamespace(sample=lambda: SimpleNamespace(cp=cp, cp_raw=cp.as_builder().to_bytes(), parked=True))) + snapshot = manual_snapshot(baseline, identity) + assert manual_profile(snapshot, identity, cap['basis']) == baseline + assert len(snapshot.encode()) < 4096 and MAX_DOCUMENT_BYTES == 16384 + owner.action({'action': 'save', 'token': owner.snapshot()['token'], 'id': 'latent', 'label': 'Latent', + 'surface': GmSurface(cap['profile'], {}).document()}) + frozen = Path(params.get_param_path(DOCUMENT_KEY)).read_bytes() + for name in ('factor', 'friction', 'proportional_gain'): + invalid = replace(baseline, **{name: FieldChoice('custom', 10000.)}) + with pytest.raises(ValueError): + owner.action({'action': 'save', 'token': owner.snapshot()['token'], 'id': 'invalid', 'label': 'Invalid', + 'surface': GmSurface(cap['profile'], {}).document()}, + generated_manual=manual_snapshot(invalid, identity)) + assert Path(params.get_param_path(DOCUMENT_KEY)).read_bytes() == frozen + # An ordinary Save also validates the currently captured consumed fields, + # rather than depending on a later full-document parse to reject them. + params.put(DOCUMENT_KEY, json.loads(serialize_document({identity: replace(baseline, factor=FieldChoice('custom', 10000.))})), block=True) + invalid_raw = Path(params.get_param_path(DOCUMENT_KEY)).read_bytes() + with pytest.raises(ValueError): + owner.action({'action': 'save', 'token': owner.snapshot()['token'], 'id': 'invalid', 'label': 'Invalid', + 'surface': GmSurface(cap['profile'], {}).document()}) + assert Path(params.get_param_path(DOCUMENT_KEY)).read_bytes() == invalid_raw + params.put(DOCUMENT_KEY, json.loads(frozen), block=True) + changed = replace(baseline, factor=FieldChoice('custom', cap['basis'][0]*1.05)) + owner.action({'action': 'save', 'token': owner.snapshot()['token'], 'id': 'custom', 'label': 'Custom', + 'surface': GmSurface(cap['profile'], {}).document()}, generated_manual=manual_snapshot(changed, identity)) + trial = owner.action({'action': 'trial', 'token': owner.snapshot()['token'], 'id': 'custom'}) + owner.action({'action': 'trial', 'token': owner.snapshot()['token'], 'id': 'latent'}) + assert replace(parse_document(Path(params.get_param_path(DOCUMENT_KEY)).read_bytes())[identity], flm=None) == baseline + owner.action({'action': 'restore', 'token': owner.snapshot()['token'], 'trial': trial['state']['trial']}) + restored = parse_document(Path(params.get_param_path(DOCUMENT_KEY)).read_bytes())[identity] + assert replace(restored, flm=None) == baseline + assert len(Path(params.get_param_path(DOCUMENT_KEY)).read_bytes()) <= MAX_DOCUMENT_BYTES diff --git a/openpilot/starpilot/flm/tests/test_torque_surface.py b/openpilot/starpilot/flm/tests/test_torque_surface.py new file mode 100644 index 0000000000..494d8b4e19 --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_torque_surface.py @@ -0,0 +1,281 @@ +import math +from operator import setitem +import unittest +from unittest import mock + +from openpilot.starpilot.flm.torque_surface import Ioniq6Surface, SurfaceInput, _BOUNDS, directional_taper_target, evaluate +from openpilot.starpilot.lateral import ioniq6_policy as baseline + + +class TestIoniq6Surface(unittest.TestCase): + def test_profile_validation_and_immutability(self): + surface = Ioniq6Surface.validated("standard", {"ff_gain_left": 0.217}) + self.assertEqual(surface.value("ff_gain_left"), 0.217) + with self.assertRaises(TypeError): + mock.Mock(wraps=setitem)(surface.knobs, "ff_gain_left", 0.3) + source = {"ff_gain_left": 0.24} + direct = Ioniq6Surface("standard", source) + source["ff_gain_left"] = 0.50 + self.assertEqual(direct.value("ff_gain_left"), 0.24) + for variant, knobs in (("2023", {}), ("standard", {"unknown": 1.0}), + ("standard", {"ff_gain_left": True}), + ("standard", {"ff_gain_left": math.nan}), + ("standard", {"ff_gain_left": 10 ** 1000}), + ("standard", {"turn_in_boost_left": 0.2}), + ("standard", {"ff_gain_left": 0.601}), + ("standard", {"curvy_speed_min": 25.0})): + with self.subTest(variant=variant, knobs=knobs), self.assertRaises(ValueError): + Ioniq6Surface.validated(variant, knobs) + + def test_neutral_matches_existing_ioniq_stages(self): + for variant in ("standard", "firmware_2025"): + surface = Ioniq6Surface.validated(variant, {}) + for speed, setpoint, jerk, desired, actual in ((3.0, 0.7, 1.1, 11.0, 1.0), + (14.0, -0.9, -1.5, -12.0, -3.0), + (27.0, -0.8, 1.7, -3.0, -12.0), + (26.0, 0.0, 0.0, 0.0, 0.0)): + with self.subTest(variant=variant, speed=speed, setpoint=setpoint, jerk=jerk): + taper = baseline.get_ioniq_6_directional_taper_scale(setpoint, jerk, speed) + i = SurfaceInput(speed, setpoint, jerk, desired, actual, 0.2, False, taper) + shape = evaluate(surface, i) + center = baseline.get_ioniq_6_center_taper_scale(setpoint, speed) + self.assertAlmostEqual(shape.directional_taper_target, taper, places=12) + self.assertAlmostEqual(shape.center_taper, center, places=12) + self.assertAlmostEqual(shape.feedforward_scale, + baseline.get_ioniq_6_ff_scale(setpoint, jerk, speed, directional_taper_scale=taper), places=12) + self.assertAlmostEqual(shape.friction_threshold, + baseline.get_ioniq_6_friction_threshold(speed, setpoint, jerk) / max(center, 1e-3), places=12) + self.assertAlmostEqual(shape.output_after_angle_assist, + baseline.get_ioniq_6_low_speed_angle_assist_torque(desired, actual, 0.2, speed), places=12) + self.assertEqual(shape.center_deadband_deg, 0.0) + + def test_nondefault_direction_center_unwind_and_pose(self): + surface = Ioniq6Surface.validated("standard", { + "ff_gain_left": 0.30, "ff_gain_right": 0.12, + "turn_in_boost_left": 1.2, "unwind_taper_right": 2.5, + "center_taper_max": 0.16, "highway_center_taper_max": 0.15, + "unwind_threshold_increase_right": 3.0, + "curvy_turn_in_trim_left": 0.15, "curvy_unwind_extra_reduction_right": 0.25, + "curvy_unwind_floor_relief_right": 0.40, + "center_deadband_low_deg": 0.1, "center_deadband_mid_deg": 0.15, + "low_speed_angle_assist_max_torque": 0.7, + }) + neutral = Ioniq6Surface.validated("standard", {}) + turn = SurfaceInput(3.0, 0.8, 1.2, 12.0, 1.0, 0.0, False, 0.9) + unwind = SurfaceInput(14.0, -0.8, 1.2, -2.0, -10.0, 0.3, False, 0.8) + shaped_turn = evaluate(surface, turn) + shaped_unwind = evaluate(surface, unwind) + self.assertNotEqual(shaped_turn.feedforward_scale, evaluate(neutral, turn).feedforward_scale) + self.assertNotEqual(shaped_turn.center_taper, evaluate(neutral, turn).center_taper) + self.assertNotEqual(shaped_turn.output_after_angle_assist, evaluate(neutral, turn).output_after_angle_assist) + self.assertNotEqual(shaped_unwind.directional_taper_target, evaluate(neutral, unwind).directional_taper_target) + self.assertNotEqual(shaped_unwind.friction_threshold, evaluate(neutral, unwind).friction_threshold) + self.assertGreater(shaped_turn.center_deadband_deg, 0.0) + pressed = SurfaceInput(3.0, 0.8, 1.2, 12.0, 1.0, 0.2, True, 0.9) + self.assertEqual(evaluate(surface, pressed).output_after_angle_assist, 0.2) + + def test_filtered_taper_is_separate_controller_owned_state(self): + surface = Ioniq6Surface.validated("standard", {}) + i = SurfaceInput(14.0, -0.8, 1.2, -6.0, -2.0, 0.2, False, filtered_directional_taper=0.91) + shape = evaluate(surface, i) + self.assertAlmostEqual(shape.feedforward_scale, + baseline.get_ioniq_6_ff_scale(i.setpoint, i.jerk, i.speed, directional_taper_scale=0.91)) + self.assertNotEqual(shape.directional_taper_target, 0.91) + for bad in (math.nan, math.inf, -2.1): + with self.assertRaises(ValueError): + SurfaceInput(i.speed, i.setpoint, i.jerk, i.desired_angle_deg, i.actual_angle_deg, i.output_torque, False, bad) + for bad in (True, 10 ** 1000): + with self.assertRaises(ValueError): + SurfaceInput(bad, i.setpoint, i.jerk, i.desired_angle_deg, i.actual_angle_deg, i.output_torque, False, 0.9) + unchecked_input = mock.Mock(wraps=SurfaceInput) + with self.assertRaises(ValueError): + unchecked_input(i.speed, i.setpoint, i.jerk, i.desired_angle_deg, i.actual_angle_deg, i.output_torque, "false", 0.9) + with self.assertRaises(ValueError): + unchecked_input(i.speed, i.setpoint, i.jerk, i.desired_angle_deg, i.actual_angle_deg, i.output_torque, False, None) + + def test_frozen_ioniq_stage_vectors(self): + # Compact values from frozen 678af783 latcontrol_vehicle_tunes.py SHA256 + # 2a7793c6ee4b53b45070d3267a01e8c7105dfd8df9d38cdfc96cfe4b672a125b. + # Generated with private AST oracle, not by importing the frozen checkout. + surface = Ioniq6Surface.validated("standard", { + "ff_gain_left": 0.11, "ff_gain_right": 0.09, + "turn_in_boost_left": 2.2, "turn_in_boost_right": 2.4, + "unwind_taper_left": 5.0, "unwind_taper_right": 10.0, + "center_taper_max": 0.13, "highway_center_taper_max": 0.08, + "turn_in_threshold_reduction_left": 1.1, "turn_in_threshold_reduction_right": 1.6, + "unwind_threshold_increase_left": 5.0, "unwind_threshold_increase_right": 11.0, + "crawl_turn_in_ff_boost_left": 0.33, "crawl_turn_in_ff_boost_right": 0.38, + "low_speed_angle_assist_max_torque": 0.60, + }) + # speed, accel, jerk, desired angle, actual angle; then frozen direction, + # center, combined pre-2023 FF, threshold and pose output from 0.2 torque. + vectors = ( + (3.0, 0.18, 0.42, 11.0, 2.0, 0.988394829429103, 0.9978605797219613, + 1.4749555335910585, 0.32048565350593106, -0.13901469137077216), + (14.0, -0.32, 0.55, -9.0, -15.0, 0.49398782437927313, 0.9746594981685954, + 0.4814699250108986, 0.40460794823460716, 0.2), + (27.0, 0.19, 0.50, 9.0, 4.0, 0.9444309506239349, 0.8839299279089594, + 0.9260528746519242, 0.4179582730864161, 0.2), + ) + for speed, accel, jerk, desired, actual, direction, center, ff, threshold, pose in vectors: + with self.subTest(speed=speed, accel=accel, jerk=jerk): + shape = evaluate(surface, SurfaceInput(speed, accel, jerk, desired, actual, 0.2, False, direction)) + self.assertAlmostEqual(shape.directional_taper_target, direction, places=11) + self.assertAlmostEqual(shape.center_taper, center, places=11) + self.assertAlmostEqual(shape.feedforward_scale * shape.center_taper, ff, places=11) + self.assertAlmostEqual(shape.friction_threshold, threshold, places=11) + self.assertAlmostEqual(shape.output_after_angle_assist, pose, places=11) + + def test_historical_combined_extreme_is_preserved_but_unqualified(self): + # Every individual value is inside frozen metadata, yet the combination + # reverses the directional multiplier. Pure math must expose it, not clip it. + surface = Ioniq6Surface.validated("standard", {name: high for name, (_, high) in _BOUNDS.items()}) + target = directional_taper_target(surface, 18.0, 0.9, -3.0) + self.assertAlmostEqual(target, -0.13824656992744921, places=11) + shape = evaluate(surface, SurfaceInput(18.0, 0.9, -3.0, 8.0, 4.0, 0.2, False, target)) + self.assertEqual(shape.directional_taper_target, target) + self.assertLess(shape.feedforward_scale, 0.0) + + +if __name__ == "__main__": + unittest.main() + +class TestGmSurface(unittest.TestCase): + def test_selected_neutral_and_rich_default_laws(self): + from openpilot.starpilot.flm.torque_surface import GmSurface + from openpilot.starpilot.lateral import bolt_shaping as gm + neutral = GmSurface('torque_universal', {}) + rich = GmSurface('gm_bolt_2022_2023', {}) + for speed, setpoint, jerk in ((3., .8, 1.2), (14., -.8, 1.2), (27., .8, -1.2), (26., 0., 0.)): + sample = SurfaceInput(speed, setpoint, jerk, 0., 0., 0., False, 1.) + ff, threshold = neutral.stages(sample, setpoint, gm.get_gm_base_friction_threshold(speed)) + self.assertEqual(ff, setpoint) + self.assertEqual(threshold, gm.get_gm_base_friction_threshold(speed)) + self.assertEqual(neutral.deadband(speed), 0.) + rich_ff, rich_threshold = rich.stages(sample, setpoint, threshold, rich=True) + self.assertAlmostEqual(rich_ff, setpoint * gm.get_bolt_2022_2023_ff_scale(setpoint, jerk, speed), places=12) + self.assertAlmostEqual(rich_threshold, gm.get_bolt_2022_2023_friction_threshold(speed, setpoint, jerk), places=12) + self.assertEqual(rich.angle_assist(sample), 0.) + + def test_explicit_surface_bounds_composition_and_immutable_document(self): + from openpilot.starpilot.flm.torque_surface import GmSurface, GmFlmBinding + knobs = {'ff_gain_left': .3, 'ff_gain_right': -.1, 'center_deadband_low_deg': .1} + surface = GmSurface('torque_universal', knobs, [.16, .18, .20, .23, .27]) + knobs['ff_gain_left'] = .6 + self.assertEqual(surface.knobs['ff_gain_left'], .3) + with self.assertRaises(TypeError): + mock.Mock(wraps=setitem)(surface.knobs, 'ff_gain_left', .5) + self.assertEqual(GmSurface.from_document(surface.document()).document(), surface.document()) + self.assertGreater(surface.deadband(5.), 0.) + self.assertAlmostEqual(surface.base_threshold(10.), .20) + for speed in (3., 14., 27.): + for sign in (-1., 1.): + sample = SurfaceInput(speed, sign*.8, sign*1.2, 0., 0., 0., False, 1.) + ff, threshold = surface.stages(sample, sign*.8, .2) + self.assertGreater(ff * sign, 0.) + if speed == 3.: + self.assertGreater(ff, .8) if sign > 0 else self.assertLess(abs(ff), .8) + self.assertTrue(math.isfinite(threshold) and threshold > 0.) + for knobs, curve in (({'ff_gain_left': -.4, 'turn_in_boost_left': 2.8}, None), + ({'ff_gain_left': math.nan}, None), ({'ff_gain_left': 10**1000}, None), + ({'ff_gain_left': True}, None), ({'curvy_speed_min': 25.}, None), + ({}, [.2]*4), ({}, [.2, .2, math.inf, .2, .2]), ({}, [10**1000]*5)): + with self.assertRaises(ValueError): + GmSurface('torque_universal', knobs, curve) + binding = GmFlmBinding('starpilot', 'ordinary_ascm', (2., 0., .1), (('one', 'Surface', surface),), 'one', True) + self.assertEqual(GmFlmBinding.from_document(binding.document()), binding) + for value in ({**binding.document(), 'active': 'missing'}, {**binding.document(), 'baselineActive': 'one', 'baselineApplied': True}): + with self.assertRaises(ValueError): + GmFlmBinding.from_document(value) + + def test_actual_selected_controller_neutral_surface_has_no_double_application(self): + from types import SimpleNamespace + from opendbc.car.gm.interface import CarInterface + from opendbc.car.gm.tests.test_ascm_intercept import params as ordinary_params + from opendbc.car.gm.tests.test_bolt_cc import params as bolt_params + from opendbc.car.gm.values import CAR + from opendbc.car.vehicle_model import VehicleModel + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque + from openpilot.starpilot.flm.live import gm_capability + from openpilot.starpilot.flm import live as flm + from openpilot.starpilot.flm.torque_surface import GmFlmBinding, GmSurface + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY, PlatformProfile, FieldChoice, serialize_document + import json + cases = (ordinary_params(CAR.CHEVROLET_MALIBU_ASCM), bolt_params(CAR.CHEVROLET_BOLT_CC_2022_2023, alpha=True)) + for cp_builder in cases: + cp = cp_builder.as_reader() + for mode in ControllerMode: + with OpenpilotPrefix(): + saved = Params() + saved.put('LateralControllerSelection', json.loads(replace_mode(None, cp, mode)), block=True) + baseline = LatControlTorque(cp, CarInterface(cp), .01, controller_mode=mode) + overlay = LatControlTorque(cp, CarInterface(cp), .01, controller_mode=mode) + cap = gm_capability(cp, mode) + surface = GmSurface(cap['profile'], {}) + cs = SimpleNamespace(vEgo=20., steeringAngleDeg=0., steeringPressed=False, steeringRateDeg=0., standstill=False) + params = SimpleNamespace(angleOffsetDeg=0., roll=0.) + vm = VehicleModel(cp) + with mock.patch('openpilot.starpilot.flm.live.time.monotonic_ns', return_value=1_000_000_000): + baseline.flm_source.sample(active=True, speed=cs.vEgo) + binding = GmFlmBinding(str(mode), cap['policy'], cap['basis'], (('neutral', 'Neutral', surface),), 'neutral', True) + saved.put(DOCUMENT_KEY, json.loads(serialize_document({str(cp.carFingerprint): PlatformProfile(cap['basis'], FieldChoice(), + FieldChoice(), flm=binding)})), block=True) + with mock.patch('openpilot.starpilot.flm.live.stages', wraps=flm.stages) as stages: + for tick in range(100): + curvature = .001 if tick < 50 else -.001 + before = baseline.update(True, cs, vm, params, False, curvature, False, .2) + after = overlay.update(True, cs, vm, params, False, curvature, False, .2) + self.assertEqual(before[:2], after[:2], (cp.carFingerprint, mode, tick)) + self.assertEqual(before[2].to_dict(), after[2].to_dict(), (cp.carFingerprint, mode, tick)) + self.assertEqual(stages.call_count, 200, 'exactly one generic stage call per actual controller update') + self.assertIsNotNone(overlay.flm_surface) + self.assertIsNone(baseline.flm_surface) + self.assertEqual(overlay.update(False, cs, vm, params, False, .001, False, .2)[0], 0.) + self.assertIsNone(overlay.flm_surface) + + + def test_standard_bolt_explicit_universal_angle_assist_reaches_actual_generic_controller(self): + import json + from types import SimpleNamespace + from opendbc.car.gm.interface import CarInterface + from opendbc.car.gm.tests.test_bolt_cc import params as bolt_params + from opendbc.car.gm.values import CAR + from opendbc.car.vehicle_model import VehicleModel + from openpilot.common.params import Params + from openpilot.common.prefix import OpenpilotPrefix + from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque + from openpilot.starpilot.flm import live as flm + from openpilot.starpilot.flm.live import gm_capability + from openpilot.starpilot.flm.torque_surface import GmFlmBinding, GmSurface + from openpilot.starpilot.lateral.controller_selection import ControllerMode, replace_mode + from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY, PlatformProfile, FieldChoice, serialize_document + cp = bolt_params(CAR.CHEVROLET_BOLT_CC_2022_2023, alpha=True).as_reader() + mode = ControllerMode.STANDARD + with OpenpilotPrefix(): + params = Params() + params.put('LateralControllerSelection', json.loads(replace_mode(None, cp, mode)), block=True) + controller = LatControlTorque(cp, CarInterface(cp), .01, controller_mode=mode) + self.assertIsNone(controller.starpilot_extension) + cap = gm_capability(cp, mode) + surface = GmSurface(cap['profile'], {'low_speed_angle_assist_max_torque': .1}) + binding = GmFlmBinding(str(mode), cap['policy'], cap['basis'], (('assist', 'Assist', surface),), 'assist', True) + params.put(DOCUMENT_KEY, json.loads(serialize_document({cap['fingerprint']: PlatformProfile(cap['basis'], + FieldChoice(), FieldChoice(), flm=binding)})), block=True) + cs = SimpleNamespace(vEgo=3., steeringAngleDeg=0., steeringPressed=False, steeringRateDeg=0., standstill=False) + learned = SimpleNamespace(angleOffsetDeg=0., roll=0.) + observed = [] + original_angle = flm.angle_assist + def actual_angle(*args): + output = original_angle(*args) + observed.append((args[-1], output)) + return output + with mock.patch('openpilot.starpilot.flm.live.time.monotonic_ns', return_value=1_000_000_000), \ + mock.patch('openpilot.starpilot.flm.live.angle_assist', side_effect=actual_angle): + result = controller.update(True, cs, VehicleModel(cp), learned, False, .003, False, .2) + self.assertTrue(result[2].active) + self.assertEqual(len(observed), 1) + self.assertGreater(abs(observed[0][1] - observed[0][0]), 1e-6) + self.assertTrue(math.isfinite(result[0]) and abs(result[0]) <= 1.) diff --git a/openpilot/starpilot/flm/tests/test_worker_limits.py b/openpilot/starpilot/flm/tests/test_worker_limits.py new file mode 100644 index 0000000000..8443d725ac --- /dev/null +++ b/openpilot/starpilot/flm/tests/test_worker_limits.py @@ -0,0 +1,21 @@ +from unittest.mock import patch + +from openpilot.starpilot.flm import operation_worker as worker + + +def test_unlimited_linux_limits_get_finite_ceiling(): + with patch.object(worker.sys, "platform", "linux"), patch.object(worker.os, "nice"), \ + patch.object(worker.resource, "getrlimit", return_value=(-1, -1)), \ + patch.object(worker.resource, "setrlimit") as set_limit: + worker._limits() + assert set_limit.call_args_list[0].args == (worker.resource.RLIMIT_AS, (worker.LINUX_ADDRESS_SPACE_BYTES, -1)) + assert set_limit.call_args_list[1].args == (worker.resource.RLIMIT_CPU, (worker.LINUX_CPU_SECONDS, -1)) + + +def test_existing_tighter_linux_limits_are_preserved(): + with patch.object(worker.sys, "platform", "linux"), patch.object(worker.os, "nice"), \ + patch.object(worker.resource, "getrlimit", side_effect=[(1000000, 2000000), (-1, 60)]), \ + patch.object(worker.resource, "setrlimit") as set_limit: + worker._limits() + assert set_limit.call_args_list[0].args == (worker.resource.RLIMIT_AS, (1000000, 2000000)) + assert set_limit.call_args_list[1].args == (worker.resource.RLIMIT_CPU, (60, 60)) diff --git a/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_extended.json b/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_extended.json new file mode 100644 index 0000000000..ddc9ae3a44 --- /dev/null +++ b/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_extended.json @@ -0,0 +1,791 @@ +{ + "sourceCommit": "678af783", + "controllerSha256": "3561d5ac43a72f9b68bc9e44042b8f5cbdca406dec940e7648c64607862a60f7", + "inputFields": ["active", "speed", "angle", "curvature", "pressed", "limited"], + "outputFields": ["output", "desiredLateralAccel", "desiredLateralJerk", "p", "i", "f", "directionalFilter"], + "sequence": [ + [false, 0.3, 10.0, -0.001, false, false], + [false, 0.3, 10.0, -0.001, false, false], + [false, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 0.3, 10.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 2.0, 5.0, -0.001, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -2.0, 0.0007, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 14.0, -8.0, -0.00025, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 2.0, -0.0009, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 27.0, 8.0, 0.00025, false, false], + [true, 20.0, 2.0, -0.0005, true, false], + [true, 20.0, 2.0, -0.0005, true, false], + [true, 20.0, 2.0, -0.0005, true, false], + [true, 20.0, 2.0, -0.0005, true, false], + [true, 20.0, 2.0, -0.0005, true, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, -0.0005, false, false], + [true, 20.0, 2.0, 0.008, false, true], + [true, 20.0, 2.0, 0.008, false, true], + [true, 20.0, 2.0, 0.008, false, true], + [true, 20.0, 2.0, 0.008, false, true], + [true, 20.0, 2.0, 0.008, false, true], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, -3.0, 0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [true, 30.0, 3.0, -0.009, false, false], + [false, 0.0, 8.0, -0.001, false, false], + [false, 0.0, 8.0, -0.001, false, false], + [false, 0.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false], + [true, 3.0, 8.0, -0.001, false, false] + ], + "cases": { + "2023_default": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10946385067439653, -6.3100724219111726e-06, -6.310072058113292e-05, 0.1341981738805771, 1.8787743556458736e-06, 0.00032710772939026356, 0.9996100118902765], + [-0.10883246512145582, -1.2177733879070729e-05, -0.00012177733879070729, 0.1318926364183426, 3.725271199073177e-06, 0.00031992016010917723, 0.9992295059317203], + [-0.10824537411387734, -1.7634001778787933e-05, -0.00017634002142585814, 0.12974874675273895, 5.541753580473596e-06, 0.00031323812436312437, 0.9988582529369309], + [-0.10769947128273318, -2.2707719836034812e-05, -0.00022707720927428454, 0.12775516510009766, 7.330325843213359e-06, 0.00030702617368660867, 0.9984960291624968], + [-0.10719187355088806, -2.7425710868556052e-05, -0.00027425712323747575, 0.12590137124061584, 9.09294521989068e-06, 0.0003012513043358922, 0.998142616186421], + [-0.10671988928055773, -3.181291322107427e-05, -0.0003181291394867003, 0.12417753040790558, 1.0831430699909106e-05, 0.00029588284087367356, 0.9977978007878223], + [-0.10628102618360663, -3.589252446545288e-05, -0.00035892523010261357, 0.1225745677947998, 1.2547474398161285e-05, 0.0002908922324422747, 0.9974613748289103], + [-0.09686010100009308, -0.00012337604130152613, -0.00033376028295606375, 0.08820036798715591, 1.378227989334846e-05, 0.00018323057156521827, 0.9971327104622644], + [-0.09711245617035859, -0.00012103597691748291, -0.00031035972642712295, 0.08911982923746109, 1.5029957467049826e-05, 0.00018614112923387438, 0.9968120741787946], + [-0.09734714586614258, -0.00011885998537763953, -0.00028859981102868915, 0.08997482806444168, 1.6289604900521226e-05, 0.0001888489641714841, 0.9964992693384843], + [-0.09756540626975398, -0.00011683656339300796, -0.0002683655184227973, 0.09076987206935883, 1.7560383639647625e-05, 0.00019136829359922558, 0.9961941041558584], + [-0.09776839378969632, -0.00011495500075398013, -0.00024954992113634944, 0.09150917828083038, 1.88415124284802e-05, 0.00019371230155229568, 0.9958963915774781], + [-0.04090147625093484, -0.004023205488920212, -0.00023205348406918347, 0.31463244557380676, 3.578325777198188e-05, -0.22863617539405823, 0.9955856059993178], + [-0.04097017598155184, -0.0040215784683823586, -0.00021578377345576882, 0.3147938847541809, 5.273369970382191e-05, -0.2285631000995636, 0.9952824091350698], + [-0.0410352771200895, -0.004020065534859896, -0.0002006547583732754, 0.31494399905204773, 6.96922215865925e-05, -0.2284919172525406, 0.9949866152926238], + [-0.041097000895768086, -0.004018658772110939, -0.00018658647604752332, 0.3150835931301117, 8.665826317155734e-05, -0.22842256724834442, 0.9946980433511353], + [-0.04115555977774558, -0.004017350263893604, -0.00017350453708786517, 0.3152133822441101, 0.0001036312896758318, -0.22835500538349152, 0.9944165166465714], + [-0.04121116576736435, -0.0040161339566111565, -0.000161339805345051, 0.3153340816497803, 0.00012061082088621333, -0.2282891720533371, 0.9941418628602553], + [-0.04126399733776618, -0.004015002865344286, -0.0001500279613537714, 0.31544631719589233, 0.00013759639114141464, -0.22822502255439758, 0.9938739139103233], + [-0.04131423253346301, -0.004013950936496258, -0.000139509211294353, 0.31555068492889404, 0.00015458758571185172, -0.22816252708435059, 0.9936125058460087], + [-0.041362040718768846, -0.004012972582131624, -0.00012972795229870826, 0.31564775109291077, 0.00017158400441985577, -0.22810161113739014, 0.99335747874467], + [-0.04140755778402792, -0.004012063145637512, -0.00012063248141203076, 0.3157379925251007, 0.00018858526891563088, -0.22804224491119385, 0.9931086766114875], + [-0.04145094405318292, -0.004011217504739761, -0.00011217471183044836, 0.31582191586494446, 0.00020559107360895723, -0.22798439860343933, 0.9928659472817497], + [-0.04149231813809619, -0.004010431002825499, -0.0001043099255184643, 0.31589996814727783, 0.00022260106925386935, -0.22792799770832062, 0.9926291423256576], + [-0.04153181484392212, -0.004009699448943138, -9.699655493022874e-05, 0.31597253680229187, 0.0002396149793639779, -0.2278730422258377, 0.9923981169555751], + [-0.041569535562070485, -0.004009019583463669, -9.019594290293753e-05, 0.3160400092601776, 0.0002566325129009783, -0.22781947255134583, 0.9921727299356587], + [-0.04160559790412195, -0.004008387215435505, -8.387213165406138e-05, 0.3161027431488037, 0.0002736534224823117, -0.2277672439813614, 0.991952843493798], + [0.39149452693873815, -0.17847982048988342, 0.17520178854465485, -0.9919443130493164, -0.0012358271051198244, -0.4408690929412842, 0.9875400426961929], + [0.37430655796667994, -0.16218021512031555, 0.33819782733917236, -0.9469498991966248, -0.0012358271051198244, -0.4235963821411133, 0.9836890276104427], + [0.3521089741311741, -0.14702340960502625, 0.4897659122943878, -0.9051101207733154, -0.0012358271051198244, -0.38455620408058167, 0.9802772670978159], + [0.33180054687547955, -0.13292928040027618, 0.6307072639465332, -0.8662038445472717, -0.0012358271051198244, -0.34926027059555054, 0.9772155204395125], + [0.3131357750502409, -0.11982330679893494, 0.7617669701576233, -0.830025315284729, -0.0012358271051198244, -0.3171355724334717, 0.9744541209523172], + [0.2959267284560149, -0.1076362207531929, 0.8836377859115601, -0.7963834404945374, -0.0012358271051198244, -0.287752240896225, 0.9719767824781306], + [0.2800275202058069, -0.09630359709262848, 0.9969640374183655, -0.7651001811027527, -0.0012358271051198244, -0.26078182458877563, 0.9697871497690216], + [0.26531816675540615, -0.0857655256986618, 1.1023447513580322, -0.7360102534294128, -0.0012358271051198244, -0.23596204817295074, 0.9678939521880274], + [0.25198985745877733, -0.07596629858016968, 1.2003370523452759, -0.7089598774909973, -0.002314679091796279, -0.2130759358406067, 0.9663002834303565], + [0.2396477597851904, -0.06685411185026169, 1.2914588451385498, -0.6838060617446899, -0.0033552534878253937, -0.1919393688440323, 0.9649991785284114], + [-0.09422456384566856, 0.2572912275791168, 1.2009122371673584, 0.21098390221595764, -0.003034190973266959, 0.13744576275348663, 0.9640429283994295], + [-0.07978759632768234, 0.24887140095233917, 1.1167140007019043, 0.18774132430553436, -0.002748497761785984, 0.10748443752527237, 0.9631736928535165], + [-0.0664175214480964, 0.241041898727417, 1.0384190082550049, 0.16612830758094788, -0.002495693741366267, 0.07983637601137161, 0.9623884128742163], + [-0.053728477209861736, 0.23376135528087616, 0.9656134843826294, 0.14603063464164734, -0.0022734731901437044, 0.05319900065660477, 0.9616834933561276], + [-0.04201910414965606, 0.22699125111103058, 0.8979125022888184, 0.12734206020832062, -0.0020796917378902435, 0.028771236538887024, 0.9610549332646039], + [-0.031218250517506735, 0.22069580852985382, 0.8349581360816956, 0.10996375977993011, -0.0019123556558042765, 0.006389177404344082, 0.9604984525950518], + [-0.021263405719875502, 0.21484176814556122, 0.77641761302948, 0.09380389004945755, -0.0017696106806397438, -0.014086096547544003, 0.960009608840235], + [-0.012098686887233694, 0.20939815044403076, 0.7219814658164978, 0.078777015209198, -0.0016497325850650668, -0.03277546167373657, 0.9595838985390357], + [-0.003672592715702306, 0.20433619618415833, 0.6713619828224182, 0.06480371952056885, -0.0015511182136833668, -0.04978952929377556, 0.9592168418991078], + [0.00406393343230147, 0.19962915778160095, 0.6242915391921997, 0.05181010439991951, -0.001472276751883328, -0.06523533910512924, 0.9589040503149374], + [0.48410737514213165, 0.18219728767871857, 0.44997286796569824, -1.1394410133361816, -0.001472276751883328, -0.6335095763206482, 0.9587681111885773], + [0.49315757002758503, 0.16598761081695557, 0.28787603974342346, -1.1841872930526733, -0.001472276751883328, -0.6214309334754944, 0.9587904679721979], + [0.5019417267515031, 0.15091441571712494, 0.13714411854743958, -1.225796103477478, -0.001472276751883328, -0.6114248037338257, 0.9589498270423709], + [0.5066429697011797, 0.13689802587032318, -0.003019690979272127, -1.2644877433776855, -0.001472276751883328, -0.5896181464195251, 0.9592242556540338], + [0.5101462535718515, 0.12386436760425568, -0.13335634768009186, -1.3004666566848755, -0.001472276751883328, -0.5670620203018188, 0.9595791248723795], + [0.5142910196551662, 0.11174451559782028, -0.2545548677444458, -1.333923101425171, -0.001472276751883328, -0.5495010018348694, 0.9599940969615668], + [0.5201145837768681, 0.10047440975904465, -0.36725589632987976, -1.365033745765686, -0.001472276751883328, -0.5403749346733093, 0.9604526447819721], + [0.5266811298830298, 0.08999447524547577, -0.4720552861690521, -1.393963098526001, -0.001472276751883328, -0.535976767539978, 0.960942258826627], + [0.5338802248892695, 0.08024930208921432, -0.5695069432258606, -1.4208643436431885, -0.0036344616673886776, -0.5336002111434937, 0.9614542357182847], + [0.5408488076228934, 0.07118739187717438, -0.6601260900497437, -1.4458792209625244, -0.0058347126469016075, -0.5321179628372192, 0.9619831418920445], + [0.7028698686034933, -0.11038433760404587, -0.6138433814048767, -1.9471006393432617, -0.008797692134976387, -0.6217712163925171, 0.9607405300190316], + [0.6994011993598761, -0.1060805693268776, -0.5708056688308716, -1.9352203607559204, -0.01174259278923273, -0.6179541945457458, 0.9596426684609639], + [0.23312593818015387, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011739371344447136, -0.9908731579780579, 0.952430201176377], + [0.2434041360989544, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.01178255956619978, -1.025451421737671, 0.9449690078640667], + [0.253317730894443, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011868905276060104, -1.0575085878372192, 0.9373360301855578], + [0.26255685417824387, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.01199538167566061, -1.086762547492981, 0.9295956164929802], + [0.2710665935147652, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012159174308180809, -1.1133455038070679, 0.9218004861200195], + [0.27887848906778195, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.01235766801983118, -1.1375019550323486, 0.9139932139127096], + [0.2860453251332994, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012588429264724255, -1.1594711542129517, 0.9062078294862433], + [0.29262013944878107, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012849196791648865, -1.1794589757919312, 0.8984713202557664], + [0.2965762375070544, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013137864880263805, -1.1887227296829224, 0.890804948172658], + [0.29673017429383713, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013452478684484959, -1.1821510791778564, 0.8832253574194441], + [0.41061267535808227, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.015475008636713028, -1.1757267713546753, 0.875901053699282], + [0.40652346184609994, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01745983213186264, -1.1687333583831787, 0.8685500023249335], + [0.40265765780722296, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.01940959133207798, -1.1617332696914673, 0.8612116165161448], + [0.3990088976545998, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.021326744928956032, -1.1547510623931885, 0.8539169219698891], + [0.3955735707575926, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02321358025074005, -1.1478044986724854, 0.8466900757753881], + [0.3923516701322979, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.025072220712900162, -1.1409056186676025, 0.8395496933996105], + [0.3893475132440573, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026904644444584846, -1.13406240940094, 0.8325099606152043], + [0.3865700034207256, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028712689876556396, -1.1272797584533691, 0.8255815419106031], + [0.3840324206232294, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030498066917061806, -1.1205604076385498, 0.818772311184273], + [0.38175135472175165, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03226236253976822, -1.1139053106307983, 0.8120879340440293], + [0.3797449488321292, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.034007057547569275, -1.1073145866394043, 0.8055323294502604], + [0.3780300673806064, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.03573352470993996, -1.1007879972457886, 0.7991080348309247], + [0.37661911222198174, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.03744304180145264, -1.0943243503570557, 0.7928164947139084], + [0.375516623653327, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.039136793464422226, -1.0879226922988892, 0.7866582890856323], + [0.3747164794461302, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.040815893560647964, -1.0815815925598145, 0.7806333143686989], + [-0.20772754196718846, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.038344670087099075, 0.2443287968635559, 0.7746891641094066], + [-0.21866468578859813, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03580063208937645, 0.22835691273212433, 0.768857914097388], + [-0.21585936135228045, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03318887948989868, 0.19066141545772552, 0.7629371203539954], + [-0.21170539564628826, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030514167621731758, 0.18755827844142914, 0.7569298493810652], + [-0.20825468733893712, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027780907228589058, 0.1886463463306427, 0.7509517971922638], + [-0.20765131927666683, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.024993203580379486, 0.189396932721138, 0.7449545261546827], + [-0.20931310703436964, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022154873237013817, 0.1900661140680313, 0.7388997712783383], + [-0.2119479932436941, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019269464537501335, 0.19072134792804718, 0.7327627342863612], + [-0.214879791806119, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016340281814336777, 0.19137808680534363, 0.726534773886686], + [-0.21783949300901684, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013370390981435776, 0.1920388787984848, 0.72022400558647], + [-0.4000595975484858, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013370390981435776, 0.21871788799762726, 0.724840854185572], + [-0.3994851887388485, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007358826231211424, 0.21651430428028107, 0.7293932460262814], + [-0.12559398326384016, 0.16584111750125885, 0.6584112048149109, 0.5665791034698486, -0.007358826231211424, -0.08538465946912766, 0.7349058161108437], + [-0.10789803604675546, 0.1436968892812729, 0.43696895241737366, 0.5290815234184265, -0.007358826231211424, -0.11545012146234512, 0.7405128616799562], + [-0.0862580050786427, 0.1231052428483963, 0.2310524582862854, 0.4942130148410797, -0.007358826231211424, -0.16420002281665802, 0.7461701549526497], + [-0.07228152550883607, 0.10395731776952744, 0.039573147892951965, 0.46178919076919556, -0.007358826231211424, -0.18570244312286377, 0.7518367441941683], + [-0.059641074877463084, 0.08615188300609589, -0.13848116993904114, 0.4316386580467224, -0.007358826231211424, -0.2014855146408081, 0.7574720838700055], + [-0.048077934326112653, 0.06959482282400131, -0.3040517568588257, 0.40360206365585327, -0.005887060891836882, -0.2165762484073639, 0.7630477127348814], + [-0.032830461086908264, 0.05419861152768135, -0.4580138921737671, 0.37753111124038696, -0.005887060891836882, -0.24716003239154816, 0.768545673778488], + [-0.019114990494410455, 0.03988185524940491, -0.6011814475059509, 0.35328808426856995, -0.005887060891836882, -0.2746863067150116, 0.7739557730076617], + [-0.006568739275635086, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.005887060891836882, -0.29983335733413696, 0.7792738195520029], + [0.005020647807338746, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.005887060891836882, -0.32303452491760254, 0.7844993819957966], + [0.22014447128082382, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.006316260434687138, -0.632738471031189, 0.7807180815256229], + [0.2115738977363323, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006723836064338684, -0.6094859838485718, 0.777189561263008], + [0.20363067710926294, -0.26899752020835876, -0.6899752616882324, -0.16974768042564392, -0.007111303508281708, -0.5878965258598328, 0.7739044654886423], + [-0.5364496390516296, -0.24663199484348297, -0.4663200080394745, -0.13187538087368011, -0.007111303508281708, 2.147817850112915, 0.7714640447550488], + [-0.5626995659039997, -0.22583456337451935, -0.25834566354751587, -0.09665840119123459, -0.007111303508281708, 2.1954567432403564, 0.7699120400719075], + [-0.5788702079428418, -0.2064952701330185, -0.06495276838541031, -0.06391053646802902, -0.007111303508281708, 2.2071051597595215, 0.7692452258750052], + [-0.5566819383639362, -0.1885119080543518, 0.11488097161054611, -0.033458687365055084, -0.007111303508281708, 2.100590705871582, 0.7693473090415099], + [-0.5595099396933427, -0.17178937792778015, 0.2821062207221985, -0.005141880363225937, -0.007111303508281708, 2.100940704345703, 0.7700537236118319], + [-0.7111987419920223, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.01135850790888071, 5.69326639175415, 0.7638278009790337], + [-0.6951031781564898, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015552760101854801, 5.644999980926514, 0.7576461193038383], + [-0.6882315389308565, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.019697772338986397, 5.596573829650879, 0.7514720746944674], + [-0.6852953059998048, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.02379699796438217, 5.547639846801758, 0.7452774336652609], + [-0.6838971368725925, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027853645384311676, 5.497928619384766, 0.7390478495218085], + [-0.8196721119253407, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027853645384311676, 6.132761478424072, 0.7446808313863519], + [-0.8196721119253435, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027853645384311676, 6.175716876983643, 0.7501764234493237], + [-0.8196721119253461, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027853645384311676, 6.21760368347168, 0.7555379766814936], + [-0.8196721119253482, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027853645384311676, 6.258456707000732, 0.7607687603226371], + [-0.8196721119253502, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027853645384311676, 6.298305988311768, 0.765871963874974], + [-0.819672111925403, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027853645384311676, 6.337148666381836, 0.7708506990480516], + [-0.8196721119254029, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027853645384311676, 6.375036239624023, 0.775708001655932], + [0.21049512553768698, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.003978789318352938, -6.231379508972168, 0.780446833468498], + [0.2167229865238455, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03572205454111099, -6.270630836486816, 0.7850700840173425], + [0.22259849652426045, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06738241016864777, -6.309582233428955, 0.7895805723576782], + [0.22835713541223146, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09896565973758698, -6.349024772644043, 0.7939810487872736], + [0.23442855370863105, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.13047721982002258, -6.390467166900635, 0.7982741965234642], + [0.248353420679028, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16192211210727692, -6.4614481925964355, 0.8020599373232822], + [0.25067633677385975, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19330500066280365, -6.4907050132751465, 0.8054052405018639], + [0.25126092480715734, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.22463025152683258, -6.514287948608398, 0.808214631238123], + [0.250099985295841, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25590190291404724, -6.532121181488037, 0.8103390489042367], + [0.24689576802597524, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2871236801147461, -6.543070316314697, 0.8116433931864653], + [0.8196721119254027, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2871236801147461, -7.163768768310547, 0.8135545394151179], + [0.8196721119254027, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2871236801147461, -7.178984642028809, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.6282397257481224, -0.0759519413113594, 0.05048057436943054, -2.187089681625366, -0.0002551604702603072, -0.3603832423686981, 0.9991124139302132], + [0.5691325038955412, -0.0712578147649765, 0.09742186218500137, -1.9766871929168701, -0.00048577398410998285, -0.35422271490097046, 0.9982771386678583], + [0.5141920378419026, -0.06689280271530151, 0.14107200503349304, -1.781036376953125, -0.0006935615674592555, -0.3485835790634155, 0.9974910563680077], + [0.4631199568724304, -0.06283382326364517, 0.18166175484657288, -1.5991029739379883, -0.0008801235817372799, -0.34340646862983704, 0.9967511103297959], + [0.4156403360710332, -0.05905943363904953, 0.21940568089485168, -1.4299253225326538, -0.0010469482513144612, -0.33864158391952515, 0.996054354716816], + [0.37152292685438515, -0.05554967001080513, 0.2545033097267151, -1.272608995437622, -0.0011954192304983735, -0.3343393802642822, 0.9953979847183112], + [0.33049756880200193, -0.05228598415851593, 0.2871401607990265, -1.1263223886489868, -0.0013268234906718135, -0.3303412199020386, 0.9947793526160259], + [-0.5128558334344437, 0.01770082116127014, 0.2670082151889801, 2.0106611251831055, -0.0013268234906718135, -0.26141688227653503, 0.9947870032699171], + [-0.489527715216843, 0.015828775241971016, 0.24828776717185974, 1.9267513751983643, -0.001102035865187645, -0.26311376690864563, 0.9947971654884007], + [-0.46783530644871996, 0.014087983407080173, 0.23087982833385468, 1.8487247228622437, -0.0008863512775860727, -0.2646978199481964, 0.9948095529007845] + ], + "2023_tuned": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10946365319690253, -6.3100724219111726e-06, -6.310072058113292e-05, 0.1341981738805771, 1.8787743556458736e-06, 0.00032638496486470103, 0.9996100118902765], + [-0.10883226781007806, -1.2177733879070729e-05, -0.00012177733879070729, 0.1318926364183426, 3.725271199073177e-06, 0.0003191980067640543, 0.9992295059317203], + [-0.10824517696030346, -1.7634001778787933e-05, -0.00017634002142585814, 0.12974874675273895, 5.541753580473596e-06, 0.00031251655309461057, 0.9988582529369309], + [-0.10769927427915203, -2.2707719836034812e-05, -0.00022707720927428454, 0.12775516510009766, 7.330325843213359e-06, 0.00030630515539087355, 0.9984960291624968], + [-0.10719167668995669, -2.7425710868556052e-05, -0.00027425712323747575, 0.12590137124061584, 9.09294521989068e-06, 0.0003005308099091053, 0.998142616186421], + [-0.10671969255537025, -3.181291322107427e-05, -0.0003181291394867003, 0.12417753040790558, 1.0831430699909106e-05, 0.0002951628412120044, 0.9977978007878223], + [-0.10628082958766569, -3.589252446545288e-05, -0.00035892523010261357, 0.1225745677947998, 1.2547474398161285e-05, 0.00029017269844189286, 0.9974613748289103], + [-0.0968599058624398, -0.00012337604130152613, -0.00033376028295606375, 0.08820036798715591, 1.378227989334846e-05, 0.00018251637811772525, 0.9971327104622644], + [-0.09711226105667088, -0.00012103597691748291, -0.00031035972642712295, 0.08911982923746109, 1.5029957467049826e-05, 0.0001854270085459575, 0.9968120741787946], + [-0.09734695077753276, -0.00011885998537763953, -0.00028859981102868915, 0.08997482806444168, 1.6289604900521226e-05, 0.00018813494534697384, 0.9964992693384843], + [-0.09756521120718856, -0.00011683656339300796, -0.0002683655184227973, 0.09076987206935883, 1.7560383639647625e-05, 0.0001906543766381219, 0.9961941041558584], + [-0.09776819875400798, -0.00011495500075398013, -0.00024954992113634944, 0.09150917828083038, 1.88415124284802e-05, 0.00019299845735076815, 0.9958963915774781], + [-0.04038609594503885, -0.004023205488920212, -0.00023205348406918347, 0.31463244557380676, 3.578325777198188e-05, -0.23052246868610382, 0.9955856059993178], + [-0.04045497259462703, -0.0040215784683823586, -0.00021578377345576882, 0.3147938847541809, 5.273369970382191e-05, -0.23044875264167786, 0.9952824091350698], + [-0.04052024540574341, -0.004020065534859896, -0.0002006547583732754, 0.31494399905204773, 6.96922215865925e-05, -0.2303769439458847, 0.9949866152926238], + [-0.04058213580150532, -0.004018658772110939, -0.00018658647604752332, 0.3150835931301117, 8.665826317155734e-05, -0.2303069829940796, 0.9946980433511353], + [-0.04064085643555087, -0.004017350263893604, -0.00017350453708786517, 0.3152133822441101, 0.0001036312896758318, -0.23023882508277893, 0.9944165166465714], + [-0.04069661948485031, -0.0040161339566111565, -0.000161339805345051, 0.3153340816497803, 0.00012061082088621333, -0.23017242550849915, 0.9941418628602553], + [-0.04074960358984859, -0.004015002865344286, -0.0001500279613537714, 0.31544631719589233, 0.00013759639114141464, -0.23010770976543427, 0.9938739139103233], + [-0.040799986954527745, -0.004013950936496258, -0.000139509211294353, 0.31555068492889404, 0.00015458758571185172, -0.2300446629524231, 0.9936125058460087], + [-0.04084793909529766, -0.004012972582131624, -0.00012972795229870826, 0.31564775109291077, 0.00017158400441985577, -0.22998322546482086, 0.99335747874467], + [-0.040893596047652886, -0.004012063145637512, -0.00012063248141203076, 0.3157379925251007, 0.00018858526891563088, -0.22992335259914398, 0.9931086766114875], + [-0.040937118274140864, -0.004011217504739761, -0.00011217471183044836, 0.31582191586494446, 0.00020559107360895723, -0.22986499965190887, 0.9928659472817497], + [-0.0409786245190571, -0.004010431002825499, -0.0001043099255184643, 0.31589996814727783, 0.00022260106925386935, -0.22980812191963196, 0.9926291423256576], + [-0.041018249714166545, -0.004009699448943138, -9.699655493022874e-05, 0.31597253680229187, 0.0002396149793639779, -0.22975268959999084, 0.9923981169555751], + [-0.041056095371993916, -0.004009019583463669, -9.019594290293753e-05, 0.3160400092601776, 0.0002566325129009783, -0.22969865798950195, 0.9921727299356587], + [-0.041092279220044096, -0.004008387215435505, -8.387213165406138e-05, 0.3161027431488037, 0.0002736534224823117, -0.2296459972858429, 0.991952843493798], + [0.3910602049801107, -0.17847982048988342, 0.17520178854465485, -0.9919443130493164, -0.0012358271051198244, -0.43927818536758423, 0.9875400426961929], + [0.3728127754776832, -0.16218021512031555, 0.33819782733917236, -0.9469498991966248, -0.0012358271051198244, -0.418121874332428, 0.9836890276104427], + [0.3507208261109926, -0.14702340960502625, 0.4897659122943878, -0.9051101207733154, -0.0012358271051198244, -0.3794669806957245, 0.9802772670978159], + [0.33052168875038607, -0.13292928040027618, 0.6307072639465332, -0.8662038445472717, -0.0012358271051198244, -0.34457075595855713, 0.9772155204395125], + [0.31196315588541873, -0.11982330679893494, 0.7617669701576233, -0.830025315284729, -0.0012358271051198244, -0.31283509731292725, 0.9744541209523172], + [0.2948547458290457, -0.1076362207531929, 0.8836377859115601, -0.7963834404945374, -0.0012358271051198244, -0.2838205397129059, 0.9719767824781306], + [0.27904976480994237, -0.09630359709262848, 0.9969640374183655, -0.7651001811027527, -0.0012358271051198244, -0.25719547271728516, 0.9697871497690216], + [0.2644281689694541, -0.0857655256986618, 1.1023447513580322, -0.7360102534294128, -0.0012358271051198244, -0.23269745707511902, 0.9678939521880274], + [0.25118140077284884, -0.07596629858016968, 1.2003370523452759, -0.7089598774909973, -0.002314679091796279, -0.2101103514432907, 0.9663002834303565], + [0.2389150006695386, -0.06685411185026169, 1.2914588451385498, -0.6838060617446899, -0.0033552534878253937, -0.1892513930797577, 0.9649991785284114], + [-0.07901424315348991, 0.2572912275791168, 1.2009122371673584, 0.21098390221595764, -0.003034190973266959, 0.08168985694646835, 0.9640429283994295], + [-0.06462022053982568, 0.24887140095233917, 1.1167140007019043, 0.18774132430553436, -0.002748497761785984, 0.051885414868593216, 0.9631736928535165], + [-0.051341863217181795, 0.241041898727417, 1.0384190082550049, 0.16612830758094788, -0.002495693741366267, 0.024573015049099922, 0.9623884128742163], + [-0.038794570414420915, 0.23376135528087616, 0.9656134843826294, 0.14603063464164734, -0.0022734731901437044, -0.0015452472725883126, 0.9616834933561276], + [-0.02727243474777478, 0.22699125111103058, 0.8979125022888184, 0.12734206020832062, -0.0020796917378902435, -0.025287091732025146, 0.9610549332646039], + [-0.016701299459840592, 0.22069580852985382, 0.8349581360816956, 0.10996375977993011, -0.0019123556558042765, -0.046827398240566254, 0.9604984525950518], + [-0.007015004831310648, 0.21484176814556122, 0.77641761302948, 0.09380389004945755, -0.0017696106806397438, -0.06631841510534286, 0.960009608840235], + [0.0018467047985609802, 0.20939815044403076, 0.7219814658164978, 0.078777015209198, -0.0016497325850650668, -0.08389700949192047, 0.9595838985390357], + [0.00994047632837133, 0.20433619618415833, 0.6713619828224182, 0.06480371952056885, -0.0015511182136833668, -0.09969261288642883, 0.9592168418991078], + [0.01732120216671505, 0.19962915778160095, 0.6242915391921997, 0.05181010439991951, -0.001472276751883328, -0.11383365094661713, 0.9589040503149374], + [0.5091351260568596, 0.18219728767871857, 0.44997286796569824, -1.1394410133361816, -0.001472276751883328, -0.7252450585365295, 0.9587681111885773], + [0.5139989779286086, 0.16598761081695557, 0.28787603974342346, -1.1841872930526733, -0.001472276751883328, -0.6978006362915039, 0.9587904679721979], + [0.5185418167319423, 0.15091441571712494, 0.13714411854743958, -1.225796103477478, -0.001472276751883328, -0.6722335815429688, 0.9589498270423709], + [0.51885924037396, 0.13689802587032318, -0.003019690979272127, -1.2644877433776855, -0.001472276751883328, -0.6343601942062378, 0.9592242556540338], + [0.5173505210709428, 0.12386436760425568, -0.13335634768009186, -1.3004666566848755, -0.001472276751883328, -0.593455970287323, 0.9595791248723795], + [0.5184302249753999, 0.11174451559782028, -0.2545548677444458, -1.333923101425171, -0.001472276751883328, -0.5646713376045227, 0.9599940969615668], + [0.5224928584304824, 0.10047440975904465, -0.36725589632987976, -1.365033745765686, -0.001472276751883328, -0.5490943193435669, 0.9604526447819721], + [0.5280438958049607, 0.08999447524547577, -0.4720552861690521, -1.393963098526001, -0.001472276751883328, -0.5409742593765259, 0.960942258826627], + [0.5346631335970315, 0.08024930208921432, -0.5695069432258606, -1.4208643436431885, -0.0036344616673886776, -0.5364716649055481, 0.9614542357182847], + [0.5413127450841172, 0.07118739187717438, -0.6601260900497437, -1.4458792209625244, -0.0058347126469016075, -0.5338196754455566, 0.9619831418920445], + [0.7082116168003382, -0.11038433760404587, -0.6138433814048767, -1.9471006393432617, -0.008797692134976387, -0.6413612365722656, 0.9607405300190316], + [0.7042939608425406, -0.1060805693268776, -0.5708056688308716, -1.9352203607559204, -0.01174259278923273, -0.6358973979949951, 0.9596426684609639], + [0.24831279792116212, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011739371344447136, -1.0561350584030151, 0.952430201176377], + [0.2605646218326958, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.01178255956619978, -1.09934401512146, 0.9449690078640667], + [0.2718220379521747, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011868905276060104, -1.1372101306915283, 0.9373360301855578], + [0.28187099517007774, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.01199538167566061, -1.1699283123016357, 0.9295956164929802], + [0.2907922906315725, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012159174308180809, -1.1982460021972656, 0.9218004861200195], + [0.29874013254349824, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.01235766801983118, -1.2229489088058472, 0.9139932139127096], + [0.30586049504387924, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012588429264724255, -1.2446823120117188, 0.9062078294862433], + [0.31227171779225527, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012849196791648865, -1.2639342546463013, 0.8984713202557664], + [0.31613837939627004, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013137864880263805, -1.2727845907211304, 0.890804948172658], + [0.31598466647005247, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013452478684484959, -1.2648652791976929, 0.8832253574194441], + [0.412307398886842, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.015475008636713028, -1.1827421188354492, 0.875901053699282], + [0.40834035227403603, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01745983213186264, -1.1762652397155762, 0.8685500023249335], + [0.40459407470573316, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.01940959133207798, -1.1697709560394287, 0.8612116165161448], + [0.4010615788878822, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.021326744928956032, -1.1632810831069946, 0.8539169219698891], + [0.39773876014683174, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02321358025074005, -1.1568107604980469, 0.8466900757753881], + [0.3946252502771808, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.025072220712900162, -1.1503701210021973, 0.8395496933996105], + [0.3917251408411536, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026904644444584846, -1.1439656019210815, 0.8325099606152043], + [0.38904724328331075, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028712689876556396, -1.1376007795333862, 0.8255815419106031], + [0.3866048728576752, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030498066917061806, -1.1312776803970337, 0.818772311184273], + [0.3844147674325609, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03226236253976822, -1.1249967813491821, 0.8120879340440293], + [0.38249530688908656, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.034007057547569275, -1.118757963180542, 0.8055323294502604], + [0.3808636470380862, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.03573352470993996, -1.1125606298446655, 0.7991080348309247], + [0.3795324926695101, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.03744304180145264, -1.106404185295105, 0.7928164947139084], + [0.37850665054287286, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.039136793464422226, -1.100287675857544, 0.7866582890856323], + [0.3777801819633453, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.040815893560647964, -1.094210147857666, 0.7806333143686989], + [-0.20729777909370484, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.038344670087099075, 0.2426171749830246, 0.7746891641094066], + [-0.21818560264028714, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03580063208937645, 0.22653359174728394, 0.768857914097388], + [-0.21585936156737215, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03318887948989868, 0.19066141545772552, 0.7629371203539954], + [-0.21170539606511912, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030514167621731758, 0.18755827844142914, 0.7569298493810652], + [-0.2082546880932433, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027780907228589058, 0.1886463463306427, 0.7509517971922638], + [-0.20765132059944635, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.024993203580379486, 0.1893969476222992, 0.7449545261546827], + [-0.20931310928896568, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022154873237013817, 0.1900661289691925, 0.7388997712783383], + [-0.21194799696328787, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019269464537501335, 0.19072136282920837, 0.7327627342863612], + [-0.21487979774071636, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016340281814336777, 0.19137810170650482, 0.726534773886686], + [-0.217839502176056, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013370390981435776, 0.19203892350196838, 0.72022400558647], + [-0.3953891079754344, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013370390981435776, 0.1986016035079956, 0.724840854185572], + [-0.39486614266660935, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007358826231211424, 0.19661948084831238, 0.7293932460262814], + [-0.10759649751357757, 0.16584111750125885, 0.6584112048149109, 0.5665791034698486, -0.007358826231211424, -0.15328480303287506, 0.7349058161108437], + [-0.09036072132795119, 0.1436968892812729, 0.43696895241737366, 0.5290815234184265, -0.007358826231211424, -0.18148404359817505, 0.7405128616799562], + [-0.07369937041296183, 0.1231052428483963, 0.2310524582862854, 0.4942130148410797, -0.007358826231211424, -0.21117648482322693, 0.7461701549526497], + [-0.06381701228028135, 0.10395731776952744, 0.039573147892951965, 0.46178919076919556, -0.007358826231211424, -0.217171773314476, 0.7518367441941683], + [-0.055415743881643206, 0.08615188300609589, -0.13848116993904114, 0.4316386580467224, -0.007358826231211424, -0.21726959943771362, 0.7574720838700055], + [-0.0466145040604287, 0.06959482282400131, -0.3040517568588257, 0.40360206365585327, -0.005887060891836882, -0.22208988666534424, 0.7630477127348814], + [-0.03318032454594341, 0.05419861152768135, -0.4580138921737671, 0.37753111124038696, -0.005887060891836882, -0.24583345651626587, 0.768545673778488], + [-0.020609027396592147, 0.03988185524940491, -0.6011814475059509, 0.35328808426856995, -0.005887060891836882, -0.26900291442871094, 0.7739557730076617], + [-0.00884738160424083, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.005887060891836882, -0.29115262627601624, 0.7792738195520029], + [0.0021526107575593704, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.005887060891836882, -0.3121010661125183, 0.7844993819957966], + [0.23092860055943876, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.006316260434687138, -0.6732545495033264, 0.7807180815256229], + [0.22203645253943774, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006723836064338684, -0.6487880349159241, 0.777189561263008], + [0.21375181990764777, -0.26899752020835876, -0.6899752616882324, -0.16974768042564392, -0.007111303508281708, -0.6259075403213501, 0.7739044654886423], + [-0.5908803176998131, -0.24663199484348297, -0.4663200080394745, -0.13187538087368011, -0.007111303508281708, 2.3516433238983154, 0.7714640447550488], + [-0.6025141066934809, -0.22583456337451935, -0.25834566354751587, -0.09665840119123459, -0.007111303508281708, 2.343456745147705, 0.7699120400719075], + [-0.6035832997589058, -0.2064952701330185, -0.06495276838541031, -0.06391053646802902, -0.007111303508281708, 2.2982985973358154, 0.7692452258750052], + [-0.5297092393754228, -0.1885119080543518, 0.11488097161054611, -0.033458687365055084, -0.007111303508281708, 2.00077748298645, 0.7693473090415099], + [-0.5292549307682339, -0.17178937792778015, 0.2821062207221985, -0.005141880363225937, -0.007111303508281708, 1.9879966974258423, 0.7700537236118319], + [-0.7111987419920223, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.01135850790888071, 5.69266414642334, 0.7638278009790337], + [-0.6951031781564898, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015552760101854801, 5.643935680389404, 0.7576461193038383], + [-0.6882315389308565, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.019697772338986397, 5.59476900100708, 0.7514720746944674], + [-0.6852953059998048, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.02379699796438217, 5.54469633102417, 0.7452774336652609], + [-0.6838971368725925, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027853645384311676, 5.493298530578613, 0.7390478495218085], + [-0.8196721119253407, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027853645384311676, 6.132761478424072, 0.7446808313863519], + [-0.8196721119253435, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027853645384311676, 6.175716876983643, 0.7501764234493237], + [-0.8196721119253461, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027853645384311676, 6.21760368347168, 0.7555379766814936], + [-0.8196721119253482, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027853645384311676, 6.258456707000732, 0.7607687603226371], + [-0.8196721119253502, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027853645384311676, 6.298305988311768, 0.765871963874974], + [-0.819672111925403, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027853645384311676, 6.337148666381836, 0.7708506990480516], + [-0.8196721119254029, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027853645384311676, 6.375036239624023, 0.775708001655932], + [0.21049512553768698, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.003978789318352938, -6.231379508972168, 0.780446833468498], + [0.2167229865238455, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03572205454111099, -6.270630836486816, 0.7850700840173425], + [0.22259849652426045, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06738241016864777, -6.309582233428955, 0.7895805723576782], + [0.22835713541223146, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09896565973758698, -6.349024772644043, 0.7939810487872736], + [0.23442855370863105, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.13047721982002258, -6.390467166900635, 0.7982741965234642], + [0.248353420679028, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16192211210727692, -6.4614481925964355, 0.8020599373232822], + [0.25067633677385975, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19330500066280365, -6.4907050132751465, 0.8054052405018639], + [0.25126092480715734, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.22463025152683258, -6.514287948608398, 0.808214631238123], + [0.250099985295841, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25590190291404724, -6.532121181488037, 0.8103390489042367], + [0.24689576802597524, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2871236801147461, -6.543070316314697, 0.8116433931864653], + [0.8196721119254027, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2871236801147461, -7.163768768310547, 0.8135545394151179], + [0.8196721119254027, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2871236801147461, -7.178984642028809, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.6300897116143003, -0.0759519413113594, 0.05048057436943054, -2.187089681625366, -0.0002551604702603072, -0.36715421080589294, 0.9991124139302132], + [0.570021419692685, -0.0712578147649765, 0.09742186218500137, -1.9766871929168701, -0.00048577398410998285, -0.357476145029068, 0.9982771386678583], + [0.5144052650105083, -0.06689280271530151, 0.14107200503349304, -1.781036376953125, -0.0006935615674592555, -0.3493639826774597, 0.9974910563680077], + [0.4630606278577127, -0.06283382326364517, 0.18166175484657288, -1.5991029739379883, -0.0008801235817372799, -0.3431893289089203, 0.9967511103297959], + [0.4156212116391389, -0.05905943363904953, 0.21940568089485168, -1.4299253225326538, -0.0010469482513144612, -0.33857160806655884, 0.996054354716816], + [0.37150541385694374, -0.05554967001080513, 0.2545033097267151, -1.272608995437622, -0.0011954192304983735, -0.3342752754688263, 0.9953979847183112], + [0.3304802499251104, -0.05228598415851593, 0.2871401607990265, -1.1263223886489868, -0.0013268234906718135, -0.33027783036231995, 0.9947793526160259], + [-0.5103119485721853, 0.01770082116127014, 0.2670082151889801, 2.0106611251831055, -0.0013268234906718135, -0.27072757482528687, 0.9947870032699171], + [-0.4871247531139276, 0.015828775241971016, 0.24828776717185974, 1.9267513751983643, -0.001102035865187645, -0.27190864086151123, 0.9947971654884007], + [-0.4655545265752654, 0.014087983407080173, 0.23087982833385468, 1.8487247228622437, -0.0008863512775860727, -0.27304553985595703, 0.9948095529007845] + ], + "2025_default": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.1000419596173212, -6.3100724219111726e-06, -6.310072058113292e-05, 0.09995962679386139, 1.399434836457658e-06, 0.00010129198199138045, 0.9996100118902765], + [-0.09957267603318784, -1.2177733879070729e-05, -0.00012177733879070729, 0.09824388474225998, 2.774849235720467e-06, 9.798955579753965e-05, 0.9992295059317203], + [-0.09913630335274988, -1.7634001778787933e-05, -0.00017634002142585814, 0.09664839506149292, 4.127926786168246e-06, 9.492012031842023e-05, 0.9988582529369309], + [-0.0987305336073542, -2.2707719836034812e-05, -0.00022707720927428454, 0.0951647162437439, 5.460232841869583e-06, 9.206731920130551e-05, 0.9984960291624968], + [-0.0983532241033397, -2.7425710868556052e-05, -0.00027425712323747575, 0.09378502517938614, 6.773223049094668e-06, 8.941596024669707e-05, 0.998142616186421], + [-0.09800238149944195, -3.181291322107427e-05, -0.0003181291394867003, 0.09250204265117645, 8.06825210020179e-06, 8.695188444107771e-05, 0.9977978007878223], + [-0.09767614986126376, -3.589252446545288e-05, -0.00035892523010261357, 0.09130898118019104, 9.3465778263635e-06, 8.46619441290386e-05, 0.9974613748289103], + [-0.0906673555152992, -0.00012337604130152613, -0.00033376028295606375, 0.06570431590080261, 1.0266438039252535e-05, 3.4840086300391704e-05, 0.9971327104622644], + [-0.0908549993923562, -0.00012103597691748291, -0.00031035972642712295, 0.06638883799314499, 1.119588159781415e-05, 3.6202189221512526e-05, 0.9968120741787946], + [-0.09102950607063971, -0.00011885998537763953, -0.00028859981102868915, 0.06702535599470139, 1.2134236385463737e-05, 3.74701339751482e-05, 0.9964992693384843], + [-0.09119179556600669, -0.00011683656339300796, -0.0002683655184227973, 0.06761724501848221, 1.3080877579341177e-05, 3.865048711304553e-05, 0.9961941041558584], + [-0.09134272615685958, -0.00011495500075398013, -0.00024954992113634944, 0.06816762685775757, 1.4035224921826739e-05, 3.974936407757923e-05, 0.9958963915774781], + [-0.01996371573553552, -0.004023205488920212, -0.00023205348406918347, 0.23997238278388977, 2.695681541808881e-05, -0.23059208691120148, 0.9955856059993178], + [-0.020020306586320584, -0.0040215784683823586, -0.00021578377345576882, 0.24009454250335693, 3.9884980651549995e-05, -0.23052002489566803, 0.9952824091350698], + [-0.020074058243435496, -0.004020065534859896, -0.0002006547583732754, 0.24020811915397644, 5.281926496536471e-05, -0.23044979572296143, 0.9949866152926238], + [-0.02012515337474716, -0.004018658772110939, -0.00018658647604752332, 0.24031373858451843, 6.575923907803372e-05, -0.2303813248872757, 0.9946980433511353], + [-0.020173757713139062, -0.004017350263893604, -0.00017350453708786517, 0.24041196703910828, 7.870449917390943e-05, -0.23031458258628845, 0.9944165166465714], + [-0.020220024205998142, -0.0040161339566111565, -0.000161339805345051, 0.24050329625606537, 9.165467781713232e-05, -0.23024950921535492, 0.9941418628602553], + [-0.020264097164136057, -0.004015002865344286, -0.0001500279613537714, 0.2405882328748703, 0.00010460942576173693, -0.2301860749721527, 0.9938739139103233], + [-0.020306108140690598, -0.004013950936496258, -0.000139509211294353, 0.2406671941280365, 0.00011756843014154583, -0.23012422025203705, 0.9936125058460087], + [-0.02034618421336529, -0.004012972582131624, -0.00012972795229870826, 0.24074062705039978, 0.00013053139264229685, -0.23006391525268555, 0.99335747874467], + [-0.020384443862206083, -0.004012063145637512, -0.00012063248141203076, 0.24080891907215118, 0.00014349802222568542, -0.23000513017177582, 0.9931086766114875], + [-0.020420996981293797, -0.004011217504739761, -0.00011217471183044836, 0.24087241291999817, 0.00015646807150915265, -0.22994780540466309, 0.9928659472817497], + [-0.020455940755107285, -0.004010431002825499, -0.0001043099255184643, 0.2409314513206482, 0.0001694413076620549, -0.22989189624786377, 0.9926291423256576], + [-0.02048937620788005, -0.004009699448943138, -9.699655493022874e-05, 0.24098636209964752, 0.0001824174978537485, -0.22983740270137787, 0.9923981169555751], + [-0.02052139167532128, -0.004009019583463669, -9.019594290293753e-05, 0.24103742837905884, 0.00019539643835742027, -0.22978425025939941, 0.9921727299356587], + [-0.02055206694872401, -0.004008387215435505, -8.387213165406138e-05, 0.24108490347862244, 0.000208377925446257, -0.2297324240207672, 0.991952843493798], + [0.37125703585399955, -0.17847982048988342, 0.17520178854465485, -0.9918082356452942, -0.0013008954701945186, -0.3814098834991455, 0.9875400426961929], + [0.3563249116250143, -0.16218021512031555, 0.33819782733917236, -0.946868360042572, -0.0013008954701945186, -0.37206515669822693, 0.9836890276104427], + [0.3400332838792249, -0.14702340960502625, 0.4897659122943878, -0.9050739407539368, -0.0013008954701945186, -0.35422003269195557, 0.9802772670978159], + [0.3217350521682795, -0.13292928040027618, 0.6307072639465332, -0.8661898374557495, -0.0013008954701945186, -0.32572245597839355, 0.9772155204395125], + [0.30491287464790134, -0.11982330679893494, 0.7617669701576233, -0.8300200700759888, -0.0013008954701945186, -0.29980576038360596, 0.9744541209523172], + [0.2894013817616517, -0.1076362207531929, 0.8836377859115601, -0.7963812947273254, -0.0013008954701945186, -0.2761189341545105, 0.9719767824781306], + [0.2750710937464448, -0.09630359709262848, 0.9969640374183655, -0.7650993466377258, -0.0013008954701945186, -0.2543935775756836, 0.9697871497690216], + [0.26181467125900454, -0.0857655256986618, 1.1023447513580322, -0.7360098361968994, -0.0013008954701945186, -0.23441553115844727, 0.9678939521880274], + [0.24983044597727005, -0.07596629858016968, 1.2003370523452759, -0.7089597582817078, -0.0023797473404556513, -0.21600757539272308, 0.9663002834303565], + [0.23873606444946352, -0.06685411185026169, 1.2914588451385498, -0.6838060021400452, -0.0034203215036541224, -0.19901923835277557, 0.9649991785284114], + [-0.0705208363838269, 0.2572912275791168, 1.2009122371673584, 0.21098388731479645, -0.0030992592219263315, 0.052963316440582275, 0.9640429283994295], + [-0.05791127976724981, 0.24887140095233917, 1.1167140007019043, 0.1877412647008896, -0.0028135660104453564, 0.029326602816581726, 0.9631736928535165], + [-0.04623994586562036, 0.241041898727417, 1.0384190082550049, 0.1661282330751419, -0.002560762222856283, 0.007540617138147354, 0.9623884128742163], + [-0.03523192766033561, 0.23376135528087616, 0.9656134843826294, 0.1460305154323578, -0.0023385416716337204, -0.013294951058924198, 0.9616834933561276], + [-0.025079714113015437, 0.22699125111103058, 0.8979125022888184, 0.1273418664932251, -0.002144760685041547, -0.0323595255613327, 0.9610549332646039], + [-0.01572118218989378, 0.22069580852985382, 0.8349581360816956, 0.10996348410844803, -0.0019774248357862234, -0.049782607704401016, 0.9604984525950518], + [-0.007101273280377882, 0.21484176814556122, 0.77641761302948, 0.0938035100698471, -0.0018346804426982999, -0.06567493826150894, 0.960009608840235], + [0.0008297808296861664, 0.20939815044403076, 0.7219814658164978, 0.0787765309214592, -0.0017148031620308757, -0.08013449609279633, 0.9595838985390357], + [0.008118299997240544, 0.20433619618415833, 0.6713619828224182, 0.0648031160235405, -0.0016161897219717503, -0.0932527706027031, 0.9592168418991078], + [0.014808633638411376, 0.19962915778160095, 0.6242915391921997, 0.05180941894650459, -0.0015373493079096079, -0.1051197424530983, 0.9589040503149374], + [0.4621020573416811, 0.18219728767871857, 0.44997286796569824, -1.139389991760254, -0.0015373493079096079, -0.5709168910980225, 0.9587681111885773], + [0.4713936456137784, 0.16598761081695557, 0.28787603974342346, -1.1840639114379883, -0.0015373493079096079, -0.5606254935264587, 0.9587904679721979], + [0.4803378636321708, 0.15091441571712494, 0.13714411854743958, -1.2255961894989014, -0.0015373493079096079, -0.5520401000976562, 0.9589498270423709], + [0.48935347370831944, 0.13689802587032318, -0.003019690979272127, -1.2642362117767334, -0.0015373493079096079, -0.5467880964279175, 0.9592242556540338], + [0.49761720293209916, 0.12386436760425568, -0.13335634768009186, -1.3002347946166992, -0.0015373493079096079, -0.542256772518158, 0.9595791248723795], + [0.5055234657170684, 0.11174451559782028, -0.2545548677444458, -1.3337390422821045, -0.0015373493079096079, -0.5389915108680725, 0.9599940969615668], + [0.5130901657853517, 0.10047440975904465, -0.36725589632987976, -1.3649104833602905, -0.0015373493079096079, -0.5367147326469421, 0.9604526447819721], + [0.5203109047218069, 0.08999447524547577, -0.4720552861690521, -1.393890619277954, -0.0015373493079096079, -0.5351468920707703, 0.960942258826627], + [0.5277450384735141, 0.08024930208921432, -0.5695069432258606, -1.4208241701126099, -0.0036994728725403547, -0.5340712070465088, 0.9614542357182847], + [0.5348026953298156, 0.07118739187717438, -0.6601260900497437, -1.4458574056625366, -0.0058996910229325294, -0.5333346724510193, 0.9619831418920445], + [0.6780078736348712, -0.11038433760404587, -0.6138433814048767, -1.9470629692077637, -0.008862612769007683, -0.559460461139679, 0.9607405300190316], + [0.6747115695706011, -0.1060805693268776, -0.5708056688308716, -1.9351692199707031, -0.011807435192167759, -0.5562520027160645, 0.9596426684609639], + [0.17851530759705644, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011804213747382164, -0.9532887935638428, 0.952430201176377], + [0.18678538061932282, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.011847402900457382, -0.9791561961174011, 0.9449690078640667], + [0.1949221573654882, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011933748610317707, -1.0030080080032349, 0.9373360301855578], + [0.2026603194855928, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.012060224078595638, -1.024595022201538, 0.9295956164929802], + [0.2099276450828452, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012224017642438412, -1.0440384149551392, 0.9218004861200195], + [0.21672051159074684, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.012422511354088783, -1.0615546703338623, 0.9139932139127096], + [0.22305534883649292, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012653272598981857, -1.077350378036499, 0.9062078294862433], + [0.22895277393356475, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012914039194583893, -1.0915987491607666, 0.8984713202557664], + [0.23443345341931823, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013202708214521408, -1.1044427156448364, 0.890804948172658], + [0.23951749819606138, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013517322018742561, -1.1160025596618652, 0.8832253574194441], + [0.39289334290020206, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.01553985197097063, -1.1072732210159302, 0.875901053699282], + [0.388718206914192, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01752467453479767, -1.100295901298523, 0.8685500023249335], + [0.3847635472904388, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.019474433735013008, -1.0933153629302979, 0.8612116165161448], + [0.3810239175048684, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.02139158733189106, -1.0863571166992188, 0.8539169219698891], + [0.3774964362735405, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02327842265367508, -1.0794397592544556, 0.8466900757753881], + [0.3741815825976844, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.02513706311583519, -1.0725765228271484, 0.8395496933996105], + [0.3710838694605647, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026969488710165024, -1.0657763481140137, 0.8325099606152043], + [0.3682120755403503, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028777534142136574, -1.0590451955795288, 0.8255815419106031], + [0.36557903498433153, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030562909319996834, -1.05238676071167, 0.818772311184273], + [0.36320061149412136, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03232720494270325, -1.0458028316497803, 0.8120879340440293], + [0.3610940314528291, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.0340718999505043, -1.0392942428588867, 0.8055323294502604], + [0.35927519417236253, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.035798367112874985, -1.0328611135482788, 0.7991080348309247], + [0.35775566889097404, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.037507884204387665, -1.0265032052993774, 0.7928164947139084], + [0.35653949259157774, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.03920163959264755, -1.0202194452285767, 0.7866582890856323], + [0.3556205446497881, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.04088073596358299, -1.01400887966156, 0.7806333143686989], + [-0.18928970090431746, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.0384095124900341, 0.1780533492565155, 0.7746891641094066], + [-0.1998281345720566, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03586547449231148, 0.1654033213853836, 0.768857914097388], + [-0.19824261810433141, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03325372561812401, 0.13446398079395294, 0.7629371203539954], + [-0.19419930945511207, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030579011887311935, 0.13123857975006104, 0.7569298493810652], + [-0.19074162262832509, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027845751494169235, 0.1318981796503067, 0.7509517971922638], + [-0.1899161965066632, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.025058045983314514, 0.13255788385868073, 0.7449545261546827], + [-0.1911287448852193, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022219715639948845, 0.1332218497991562, 0.7388997712783383], + [-0.19318406105815286, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019334308803081512, 0.1338927447795868, 0.7327627342863612], + [-0.19546555151826855, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016405124217271805, 0.13457146286964417, 0.726534773886686], + [-0.19773300519680453, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013435234315693378, 0.1352570652961731, 0.72022400558647], + [-0.3129858658797515, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013435234315693378, 0.15824465453624725, 0.724840854185572], + [-0.31099166787599797, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007423669099807739, 0.1564316302537918, 0.7293932460262814], + [-0.1016954787246937, 0.16584111750125885, 0.6584112048149109, 0.5665790438652039, -0.007423669099807739, -0.1395522952079773, 0.7349058161108437], + [-0.08300327240505596, 0.1436968892812729, 0.43696895241737366, 0.5290812253952026, -0.007423669099807739, -0.1789565533399582, 0.7405128616799562], + [-0.06918421965186021, 0.1231052428483963, 0.2310524582862854, 0.4942123293876648, -0.007423669099807739, -0.2024339735507965, 0.7461701549526497], + [-0.05736861692440621, 0.10395731776952744, 0.039573147892951965, 0.46178823709487915, -0.007423669099807739, -0.2196238934993744, 0.7518367441941683], + [-0.046647800181232595, 0.08615188300609589, -0.13848116993904114, 0.43163782358169556, -0.007423669099807739, -0.23217642307281494, 0.7574720838700055], + [-0.03697180534157927, 0.06959482282400131, -0.3040517568588257, 0.4036014974117279, -0.0059389350935816765, -0.2439926415681839, 0.7630477127348814], + [-0.027750959294197044, 0.05419861152768135, -0.4580138921737671, 0.37753087282180786, -0.0059389350935816765, -0.2554107904434204, 0.768545673778488], + [-0.01650420513479283, 0.03988185524940491, -0.6011814475059509, 0.3532879948616028, -0.0059389350935816765, -0.27798032760620117, 0.7739557730076617], + [-0.006215064317218847, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.0059389350935816765, -0.29863041639328003, 0.7792738195520029], + [0.0032896441892095135, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.0059389350935816765, -0.31771352887153625, 0.7844993819957966], + [0.1867415263504139, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.00636813510209322, -0.5570378303527832, 0.7807180815256229], + [0.17962014109123528, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006775710266083479, -0.5382837653160095, 0.777189561263008], + [0.17304498228624188, -0.26899752020835876, -0.6899752616882324, -0.16974766552448273, -0.007163177710026503, -0.520890474319458, 0.7739044654886423], + [-0.5087494300864623, -0.24663199484348297, -0.4663200080394745, -0.13187535107135773, -0.007163177710026503, 2.1945619583129883, 0.7714640447550488], + [-0.5218161964776654, -0.22583456337451935, -0.25834566354751587, -0.09665831178426743, -0.007163177710026503, 2.205286979675293, 0.7699120400719075], + [-0.5338882181449203, -0.2064952701330185, -0.06495276838541031, -0.06391043961048126, -0.007163177710026503, 2.212782382965088, 0.7692452258750052], + [-0.5112945374698926, -0.1885119080543518, 0.11488097161054611, -0.033458638936281204, -0.007163177710026503, 2.1033742427825928, 0.7693473090415099], + [-0.5120801247826361, -0.17178937792778015, 0.2821062207221985, -0.0051418752409517765, -0.007163177710026503, 2.1013295650482178, 0.7700537236118319], + [-0.6318228120428708, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.011410382576286793, 5.746920108795166, 0.7638278009790337], + [-0.6102463073064712, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015604634769260883, 5.698555946350098, 0.7576461193038383], + [-0.5973168223220888, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.01974964700639248, 5.6500163078308105, 0.7514720746944674], + [-0.5882638545461184, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.023848872631788254, 5.600953578948975, 0.7452774336652609], + [-0.5809686456967957, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027905520051717758, 5.551097869873047, 0.7390478495218085], + [-0.8196721119253407, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027905520051717758, 6.068759918212891, 0.7446808313863519], + [-0.8196721119253435, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027905520051717758, 6.111703872680664, 0.7501764234493237], + [-0.8196721119253461, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027905520051717758, 6.153583526611328, 0.7555379766814936], + [-0.8196721119253482, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027905520051717758, 6.194431781768799, 0.7607687603226371], + [-0.8196721119253502, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027905520051717758, 6.234278202056885, 0.765871963874974], + [-0.819672111925403, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027905520051717758, 6.273124694824219, 0.7708506990480516], + [-0.8196721119254029, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027905520051717758, 6.311017990112305, 0.775708001655932], + [0.22799154825718387, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.0039269146509468555, -6.295364856719971, 0.780446833468498], + [0.23419523367937423, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03567017987370491, -6.334527492523193, 0.7850700840173425], + [0.24001124821910183, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06733053922653198, -6.373260974884033, 0.7895805723576782], + [0.24563307844267657, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09891378879547119, -6.412202835083008, 0.7939810487872736], + [0.2514091635182312, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.1304253488779068, -6.452564239501953, 0.7982741965234642], + [0.26319184231767545, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16187024116516113, -6.51570463180542, 0.8020599373232822], + [0.265450510692521, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19325312972068787, -6.544726848602295, 0.8054052405018639], + [0.26603509872581854, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.2245783805847168, -6.568309783935547, 0.808214631238123], + [0.2648741592145022, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25585001707077026, -6.586142539978027, 0.8103390489042367], + [0.26166994194463644, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2870718240737915, -6.5970916748046875, 0.8116433931864653], + [0.8196721119254027, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2870718240737915, -7.096859455108643, 0.8135545394151179], + [0.8196721119254027, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2870718240737915, -7.112162113189697, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.38513324930148474, -0.0759519413113594, 0.05048057436943054, -1.7808427810668945, -0.00020776498422492296, -0.33449462056159973, 0.9991124139302132], + [0.40075537473288914, -0.0712578147649765, 0.09742186218500137, -1.6257919073104858, -0.00039744071546010673, -0.33135300874710083, 0.9982771386678583], + [0.4201164532492807, -0.06689280271530151, 0.14107200503349304, -1.483040452003479, -0.0005704620853066444, -0.32857346534729004, 0.9974910563680077], + [0.3903238460794766, -0.06283382326364517, 0.18166175484657288, -1.3503772020339966, -0.0007280061254277825, -0.3260654807090759, 0.9967511103297959], + [0.35570301596556403, -0.05905943363904953, 0.21940568089485168, -1.2258175611495972, -0.0008710181573405862, -0.32375097274780273, 0.996054354716816], + [0.3229205375893875, -0.05554967001080513, 0.2545033097267151, -1.1077765226364136, -0.0010002587223425508, -0.32166072726249695, 0.9953979847183112], + [0.2916296151630097, -0.05228598415851593, 0.2871401607990265, -0.995150089263916, -0.001116359606385231, -0.31962889432907104, 0.9947793526160259], + [-0.4353541850257815, 0.01770082116127014, 0.2670082151889801, 1.7472336292266846, -0.001116359606385231, -0.28161153197288513, 0.9947870032699171], + [-0.410655696054713, 0.015828775241971016, 0.24828776717185974, 1.658023476600647, -0.0009229235001839697, -0.28300604224205017, 0.9947971654884007], + [-0.38813969742745874, 0.014087983407080173, 0.23087982833385468, 1.5766654014587402, -0.0007389792008325458, -0.284253865480423, 0.9948095529007845] + ], + "2025_tuned": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10004176588515235, -6.3100724219111726e-06, -6.310072058113292e-05, 0.09995962679386139, 1.399434836457658e-06, 0.00010058288171421736, 0.9996100118902765], + [-0.0995724824028674, -1.2177733879070729e-05, -0.00012177733879070729, 0.09824388474225998, 2.774849235720467e-06, 9.72808338701725e-05, 0.9992295059317203], + [-0.09913610982047417, -1.7634001778787933e-05, -0.00017634002142585814, 0.09664839506149292, 4.127926786168246e-06, 9.421175491297618e-05, 0.9988582529369309], + [-0.09873034016950431, -2.2707719836034812e-05, -0.00022707720927428454, 0.0951647162437439, 5.460232841869583e-06, 9.135930304182693e-05, 0.9984960291624968], + [-0.09835303075647045, -2.7425710868556052e-05, -0.00027425712323747575, 0.09378502517938614, 6.773223049094668e-06, 8.870827150531113e-05, 0.998142616186421], + [-0.09800218824027186, -3.181291322107427e-05, -0.0003181291394867003, 0.09250204265117645, 8.06825210020179e-06, 8.62445158418268e-05, 0.9977978007878223], + [-0.09767595668666544, -3.589252446545288e-05, -0.00035892523010261357, 0.09130898118019104, 9.3465778263635e-06, 8.39548883959651e-05, 0.9974613748289103], + [-0.09066716284226353, -0.00012337604130152613, -0.00033376028295606375, 0.06570431590080261, 1.0266438039252535e-05, 3.4134864108636975e-05, 0.9971327104622644], + [-0.0908548067688955, -0.00012103597691748291, -0.00031035972642712295, 0.06638883799314499, 1.119588159781415e-05, 3.549714892869815e-05, 0.9968120741787946], + [-0.09102931349607103, -0.00011885998537763953, -0.00028859981102868915, 0.06702535599470139, 1.2134236385463737e-05, 3.6765271943295375e-05, 0.9964992693384843], + [-0.09119160303962716, -0.00011683656339300796, -0.0002683655184227973, 0.06761724501848221, 1.3080877579341177e-05, 3.794580334215425e-05, 0.9961941041558584], + [-0.09134253367794945, -0.00011495500075398013, -0.00024954992113634944, 0.06816762685775757, 1.4035224921826739e-05, 3.904485492967069e-05, 0.9958963915774781], + [-0.01944845290711774, -0.004023205488920212, -0.00023205348406918347, 0.23997238278388977, 2.695681541808881e-05, -0.23247814178466797, 0.9955856059993178], + [-0.019505220691704045, -0.0040215784683823586, -0.00021578377345576882, 0.24009454250335693, 3.9884980651549995e-05, -0.23240543901920319, 0.9952824091350698], + [-0.019559144034443626, -0.004020065534859896, -0.0002006547583732754, 0.24020811915397644, 5.281926496536471e-05, -0.23233458399772644, 0.9949866152926238], + [-0.01961040579724358, -0.004018658772110939, -0.00018658647604752332, 0.24031373858451843, 6.575923907803372e-05, -0.23226550221443176, 0.9946980433511353], + [-0.019659171897600212, -0.004017350263893604, -0.00017350453708786517, 0.24041196703910828, 7.870449917390943e-05, -0.23219816386699677, 0.9944165166465714], + [-0.019705595458651293, -0.0040161339566111565, -0.000161339805345051, 0.24050329625606537, 9.165467781713232e-05, -0.23213252425193787, 0.9941418628602553], + [-0.01974982095862555, -0.004015002865344286, -0.0001500279613537714, 0.2405882328748703, 0.00010460942576173693, -0.2320685237646103, 0.9938739139103233], + [-0.019791980110236407, -0.004013950936496258, -0.000139509211294353, 0.2406671941280365, 0.00011756843014154583, -0.23200613260269165, 0.9936125058460087], + [-0.01983220014338104, -0.004012972582131624, -0.00012972795229870826, 0.24074062705039978, 0.00013053139264229685, -0.23194530606269836, 0.99335747874467], + [-0.01987059968334614, -0.004012063145637512, -0.00012063248141203076, 0.24080891907215118, 0.00014349802222568542, -0.23188599944114685, 0.9931086766114875], + [-0.019907288762901165, -0.004011217504739761, -0.00011217471183044836, 0.24087241291999817, 0.00015646807150915265, -0.23182816803455353, 0.9928659472817497], + [-0.01994236469903559, -0.004010431002825499, -0.0001043099255184643, 0.2409314513206482, 0.0001694413076620549, -0.2317717969417572, 0.9926291423256576], + [-0.019975928642665286, -0.004009699448943138, -9.699655493022874e-05, 0.24098636209964752, 0.0001824174978537485, -0.2317168116569519, 0.9923981169555751], + [-0.020008069050680716, -0.004009019583463669, -9.019594290293753e-05, 0.24103742837905884, 0.00019539643835742027, -0.23166321218013763, 0.9921727299356587], + [-0.020038865830360516, -0.004008387215435505, -8.387213165406138e-05, 0.24108490347862244, 0.000208377925446257, -0.23161093890666962, 0.991952843493798], + [0.370812088545753, -0.17847982048988342, 0.17520178854465485, -0.9918082356452942, -0.0013008954701945186, -0.37976253032684326, 0.9875400426961929], + [0.3550224507624517, -0.16218021512031555, 0.33819782733917236, -0.946868360042572, -0.0013008954701945186, -0.3672393560409546, 0.9836890276104427], + [0.3387657012828988, -0.14702340960502625, 0.4897659122943878, -0.9050739407539368, -0.0013008954701945186, -0.349520742893219, 0.9802772670978159], + [0.320553117201625, -0.13292928040027618, 0.6307072639465332, -0.8661898374557495, -0.0013008954701945186, -0.32133904099464417, 0.9772155204395125], + [0.3038147853950517, -0.11982330679893494, 0.7617669701576233, -0.8300200700759888, -0.0013008954701945186, -0.29573220014572144, 0.9744541209523172], + [0.28838297435341453, -0.1076362207531929, 0.8836377859115601, -0.7963812947273254, -0.0013008954701945186, -0.27234020829200745, 0.9719767824781306], + [0.27412739976950157, -0.09630359709262848, 0.9969640374183655, -0.7650993466377258, -0.0013008954701945186, -0.2508915066719055, 0.9697871497690216], + [0.2609405940688192, -0.0857655256986618, 1.1023447513580322, -0.7360098361968994, -0.0013008954701945186, -0.2311713993549347, 0.9678939521880274], + [0.24902105124313956, -0.07596629858016968, 1.2003370523452759, -0.7089597582817078, -0.0023797473404556513, -0.21300318837165833, 0.9663002834303565], + [0.2379866968422148, -0.06685411185026169, 1.2914588451385498, -0.6838060021400452, -0.0034203215036541224, -0.19623741507530212, 0.9649991785284114], + [-0.05555523899531584, 0.2572912275791168, 1.2009122371673584, 0.21098388731479645, -0.0030992592219263315, -0.0023925956338644028, 0.9640429283994295], + [-0.04300703739640971, 0.24887140095233917, 1.1167140007019043, 0.1877412647008896, -0.0028135660104453564, -0.025814607739448547, 0.9631736928535165], + [-0.03144173312508024, 0.241041898727417, 1.0384190082550049, 0.1661282330751419, -0.002560762222856283, -0.04721926525235176, 0.9623884128742163], + [-0.020584306498731966, 0.23376135528087616, 0.9656134843826294, 0.1460305154323578, -0.0023385416716337204, -0.0675073191523552, 0.9616834933561276], + [-0.010623455738642828, 0.22699125111103058, 0.8979125022888184, 0.1273418664932251, -0.002144760685041547, -0.08587225526571274, 0.9610549332646039], + [-0.001494547853067832, 0.22069580852985382, 0.8349581360816956, 0.10996348410844803, -0.0019774248357862234, -0.10245289653539658, 0.9604984525950518], + [0.0068604057005683195, 0.21484176814556122, 0.77641761302948, 0.0938035100698471, -0.0018346804426982999, -0.11737086623907089, 0.960009608840235], + [0.014494764465175735, 0.20939815044403076, 0.7219814658164978, 0.0787765309214592, -0.0017148031620308757, -0.13073746860027313, 0.9595838985390357], + [0.02145925383556136, 0.20433619618415833, 0.6713619828224182, 0.0648031160235405, -0.0016161897219717503, -0.14266054332256317, 0.9592168418991078], + [0.027803413077598614, 0.19962915778160095, 0.6242915391921997, 0.05180941894650459, -0.0015373493079096079, -0.1532493233680725, 0.9589040503149374], + [0.4868611346439523, 0.18219728767871857, 0.44997286796569824, -1.139389991760254, -0.0015373493079096079, -0.6626362204551697, 0.9587681111885773], + [0.491999825957422, 0.16598761081695557, 0.28787603974342346, -1.1840639114379883, -0.0015373493079096079, -0.6369588971138, 0.9587904679721979], + [0.49674077912054715, 0.15091441571712494, 0.13714411854743958, -1.2255961894989014, -0.0015373493079096079, -0.6127965450286865, 0.9589498270423709], + [0.5020593921318688, 0.13689802587032318, -0.003019690979272127, -1.2642362117767334, -0.0015373493079096079, -0.5938507318496704, 0.9592242556540338], + [0.5055839611899835, 0.12386436760425568, -0.13335634768009186, -1.3002347946166992, -0.0015373493079096079, -0.5717793107032776, 0.9595791248723795], + [0.5103376594592743, 0.11174451559782028, -0.2545548677444458, -1.3337390422821045, -0.0015373493079096079, -0.5568405389785767, 0.9599940969615668], + [0.5159163517262825, 0.10047440975904465, -0.36725589632987976, -1.3649104833602905, -0.0015373493079096079, -0.5471976399421692, 0.9604526447819721], + [0.5219334806488688, 0.08999447524547577, -0.4720552861690521, -1.393890619277954, -0.0015373493079096079, -0.5411673784255981, 0.960942258826627], + [0.5286669727750853, 0.08024930208921432, -0.5695069432258606, -1.4208241701126099, -0.0036994728725403547, -0.5374927520751953, 0.9614542357182847], + [0.5353362743544783, 0.07118739187717438, -0.6601260900497437, -1.4458574056625366, -0.0058996910229325294, -0.535315215587616, 0.9619831418920445], + [0.6832885473599156, -0.11038433760404587, -0.6138433814048767, -1.9470629692077637, -0.008862612769007683, -0.5790515542030334, 0.9607405300190316], + [0.6795462170511046, -0.1060805693268776, -0.5708056688308716, -1.9351692199707031, -0.011807435192167759, -0.5741888880729675, 0.9596426684609639], + [0.1908011113905084, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011804213747382164, -1.0196528434753418, 0.952430201176377], + [0.20074079294495029, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.011847402900457382, -1.054008960723877, 0.9449690078640667], + [0.21005581328971235, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011933748610317707, -1.0834929943084717, 0.9373360301855578], + [0.2185519968501357, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.012060224078595638, -1.108378291130066, 0.9295956164929802], + [0.22625973138345304, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012224017642438412, -1.129418134689331, 0.9218004861200195], + [0.2332688587860026, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.012422511354088783, -1.1473722457885742, 0.9139932139127096], + [0.23966734021868588, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012653272598981857, -1.1628490686416626, 0.9062078294862433], + [0.245526388718592, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012914039194583893, -1.1762992143630981, 0.8984713202557664], + [0.250901259515652, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013202708214521408, -1.1880501508712769, 0.890804948172658], + [0.2558354548718358, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013517322018742561, -1.198344111442566, 0.8832253574194441], + [0.3945829136566075, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.01553985197097063, -1.1142884492874146, 0.875901053699282], + [0.39052898584298695, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01752467453479767, -1.1078277826309204, 0.8685500023249335], + [0.3866928098321055, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.019474433735013008, -1.1013531684875488, 0.8612116165161448], + [0.3830683242096016, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.02139158733189106, -1.094887137413025, 0.8539169219698891], + [0.37965216174232946, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02327842265367508, -1.088446021080017, 0.8466900757753881], + [0.3764444491749428, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.02513706311583519, -1.0820410251617432, 0.8395496933996105], + [0.37344948299404424, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026969488710165024, -1.0756795406341553, 0.8325099606152043], + [0.3706759594198795, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028777534142136574, -1.0693663358688354, 0.8255815419106031], + [0.36813675695663267, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030562909319996834, -1.0631040334701538, 0.818772311184273], + [0.36584789570646514, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03232720494270325, -1.056894302368164, 0.8120879340440293], + [0.3638268463778931, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.0340718999505043, -1.0507375001907349, 0.8055323294502604], + [0.36208980635370175, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.035798367112874985, -1.0446338653564453, 0.7991080348309247], + [0.36064865374996596, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.037507884204387665, -1.0385830402374268, 0.7928164947139084], + [0.35950769748704137, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.03920163959264755, -1.0325844287872314, 0.7866582890856323], + [0.35866100585350397, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.04088073596358299, -1.0266374349594116, 0.7806333143686989], + [-0.18886394348797958, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.0384095124900341, 0.1763417273759842, 0.7746891641094066], + [-0.19935445167851054, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03586547449231148, 0.1635800153017044, 0.768857914097388], + [-0.19824261830173168, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03325372561812401, 0.13446398079395294, 0.7629371203539954], + [-0.19419930983956415, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030579011887311935, 0.13123857975006104, 0.7569298493810652], + [-0.19074162332080974, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027845751494169235, 0.1318981796503067, 0.7509517971922638], + [-0.18991619771810794, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.025058045983314514, 0.13255789875984192, 0.7449545261546827], + [-0.19112874694352874, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022219715639948845, 0.13322186470031738, 0.7388997712783383], + [-0.19318406444226807, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019334308803081512, 0.13389275968074799, 0.7327627342863612], + [-0.19546555689832368, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016405124217271805, 0.13457147777080536, 0.726534773886686], + [-0.19773301347682157, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013435234315693378, 0.13525710999965668, 0.72022400558647], + [-0.30919366177723145, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013435234315693378, 0.138100728392601, 0.724840854185572], + [-0.30725900353129726, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007423669099807739, 0.13650169968605042, 0.7293932460262814], + [-0.08521481290160546, 0.16584111750125885, 0.6584112048149109, 0.5665790438652039, -0.007423669099807739, -0.2075527459383011, 0.7349058161108437], + [-0.06783400791318979, 0.1436968892812729, 0.43696895241737366, 0.5290812253952026, -0.007423669099807739, -0.24158689379692078, 0.7405128616799562], + [-0.05825252475310051, 0.1231052428483963, 0.2310524582862854, 0.4942123293876648, -0.007423669099807739, -0.24736443161964417, 0.7461701549526497], + [-0.05012086249249722, 0.10395731776952744, 0.039573147892951965, 0.46178823709487915, -0.007423669099807739, -0.24928022921085358, 0.7518367441941683], + [-0.04321249616872257, 0.08615188300609589, -0.13848116993904114, 0.43163782358169556, -0.007423669099807739, -0.2463187426328659, 0.7574720838700055], + [-0.035995895467763134, 0.06959482282400131, -0.3040517568588257, 0.4036014974117279, -0.0059389350935816765, -0.24804891645908356, 0.7630477127348814], + [-0.02817185116153802, 0.05419861152768135, -0.4580138921737671, 0.37753087282180786, -0.0059389350935816765, -0.25364869832992554, 0.768545673778488], + [-0.017897620847901936, 0.03988185524940491, -0.6011814475059509, 0.3532879948616028, -0.0059389350935816765, -0.27212369441986084, 0.7739557730076617], + [-0.008261216107912184, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.0059389350935816765, -0.2900128662586212, 0.7792738195520029], + [0.0007627783865820081, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.0059389350935816765, -0.30705922842025757, 0.7844993819957966], + [0.1969936943180487, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.00636813510209322, -0.5982919335365295, 0.7807180815256229], + [0.18958238737076302, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006775710266083479, -0.5784175992012024, 0.777189561263008], + [0.1826990815770707, -0.26899752020835876, -0.6899752616882324, -0.16974766552448273, -0.007163177710026503, -0.5598204731941223, 0.7739044654886423], + [-0.5589129262720587, -0.24663199484348297, -0.4663200080394745, -0.13187535107135773, -0.007163177710026503, 2.397239923477173, 0.7714640447550488], + [-0.5584810415223166, -0.22583456337451935, -0.25834566354751587, -0.09665831178426743, -0.007163177710026503, 2.3529441356658936, 0.7699120400719075], + [-0.5565616659645832, -0.2064952701330185, -0.06495276838541031, -0.06391043961048126, -0.007163177710026503, 2.3037376403808594, 0.7692452258750052], + [-0.4865217168598598, -0.1885119080543518, 0.11488097161054611, -0.033458638936281204, -0.007163177710026503, 2.003431558609009, 0.7693473090415099], + [-0.4843897726047696, -0.17178937792778015, 0.2821062207221985, -0.0051418752409517765, -0.007163177710026503, 1.9883670806884766, 0.7700537236118319], + [-0.6318228120428708, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.011410382576286793, 5.746318817138672, 0.7638278009790337], + [-0.6102463073064712, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015604634769260883, 5.697494029998779, 0.7576461193038383], + [-0.5973168223220888, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.01974964700639248, 5.648215293884277, 0.7514720746944674], + [-0.5882638545461184, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.023848872631788254, 5.598015308380127, 0.7452774336652609], + [-0.5809686456967957, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027905520051717758, 5.546477317810059, 0.7390478495218085], + [-0.8196721119253407, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027905520051717758, 6.068759918212891, 0.7446808313863519], + [-0.8196721119253435, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027905520051717758, 6.111703872680664, 0.7501764234493237], + [-0.8196721119253461, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027905520051717758, 6.153583526611328, 0.7555379766814936], + [-0.8196721119253482, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027905520051717758, 6.194431781768799, 0.7607687603226371], + [-0.8196721119253502, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027905520051717758, 6.234278202056885, 0.765871963874974], + [-0.819672111925403, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027905520051717758, 6.273124694824219, 0.7708506990480516], + [-0.8196721119254029, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027905520051717758, 6.311017990112305, 0.775708001655932], + [0.22799154825718387, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.0039269146509468555, -6.295364856719971, 0.780446833468498], + [0.23419523367937423, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03567017987370491, -6.334527492523193, 0.7850700840173425], + [0.24001124821910183, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06733053922653198, -6.373260974884033, 0.7895805723576782], + [0.24563307844267657, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09891378879547119, -6.412202835083008, 0.7939810487872736], + [0.2514091635182312, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.1304253488779068, -6.452564239501953, 0.7982741965234642], + [0.26319184231767545, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16187024116516113, -6.51570463180542, 0.8020599373232822], + [0.265450510692521, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19325312972068787, -6.544726848602295, 0.8054052405018639], + [0.26603509872581854, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.2245783805847168, -6.568309783935547, 0.808214631238123], + [0.2648741592145022, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25585001707077026, -6.586142539978027, 0.8103390489042367], + [0.26166994194463644, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2870718240737915, -6.5970916748046875, 0.8116433931864653], + [0.8196721119254027, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2870718240737915, -7.096859455108643, 0.8135545394151179], + [0.8196721119254027, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2870718240737915, -7.112162113189697, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.38513324930148474, -0.0759519413113594, 0.05048057436943054, -1.7808427810668945, -0.00020776498422492296, -0.34127020835876465, 0.9991124139302132], + [0.40075537473288914, -0.0712578147649765, 0.09742186218500137, -1.6257919073104858, -0.00039744071546010673, -0.33461055159568787, 0.9982771386678583], + [0.4201164532492807, -0.06689280271530151, 0.14107200503349304, -1.483040452003479, -0.0005704620853066444, -0.32935744524002075, 0.9974910563680077], + [0.3902653702713881, -0.06283382326364517, 0.18166175484657288, -1.3503772020339966, -0.0007280061254277825, -0.3258514404296875, 0.9967511103297959], + [0.3556846194505165, -0.05905943363904953, 0.21940568089485168, -1.2258175611495972, -0.0008710181573405862, -0.32368361949920654, 0.996054354716816], + [0.3229036446280457, -0.05554967001080513, 0.2545033097267151, -1.1077765226364136, -0.0010002587223425508, -0.3215988874435425, 0.9953979847183112], + [0.29161282059042204, -0.05228598415851593, 0.2871401607990265, -0.995150089263916, -0.001116359606385231, -0.31956741213798523, 0.9947793526160259], + [-0.43281167838121426, 0.01770082116127014, 0.2670082151889801, 1.7472336292266846, -0.001116359606385231, -0.29091861844062805, 0.9947870032699171], + [-0.40825407552453624, 0.015828775241971016, 0.24828776717185974, 1.658023476600647, -0.0009229235001839697, -0.29179736971855164, 0.9947971654884007], + [-0.38586022378762674, 0.014087983407080173, 0.23087982833385468, 1.5766654014587402, -0.0007389792008325458, -0.29259806871414185, 0.9948095529007845] + ] + }, + "corrections": { + "2746116c4f1040ff28312cd481ed59a43ace3fc1": "Unwind freezes the integrator when steering magnitude decreases in either direction." + } +} diff --git a/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_live_update.json b/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_live_update.json new file mode 100644 index 0000000000..bb236e1e1e --- /dev/null +++ b/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_live_update.json @@ -0,0 +1,681 @@ +{ + "sourceControllerSha256": "3561d5ac43a72f9b68bc9e44042b8f5cbdca406dec940e7648c64607862a60f7", + "fields": ["output", "desiredLateralAccel", "desiredLateralJerk", "p", "i", "f", "directionalFilter"], + "cases": { + "2023_default": { + "before": { + "factor": 3.6600000858306885, + "negLimit": -3.0, + "posLimit": 3.0 + }, + "after": { + "factor": 3.6600000858306885, + "negLimit": -3.6600000858306885, + "posLimit": 3.6600000858306885 + }, + "rows": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10946385067439653, -6.3100724219111726e-06, -6.310072058113292e-05, 0.1341981738805771, 1.8787743556458736e-06, 0.00032710772939026356, 0.9996100118902765], + [-0.10883246512145582, -1.2177733879070729e-05, -0.00012177733879070729, 0.1318926364183426, 3.725271199073177e-06, 0.00031992016010917723, 0.9992295059317203], + [-0.10824537411387734, -1.7634001778787933e-05, -0.00017634002142585814, 0.12974874675273895, 5.541753580473596e-06, 0.00031323812436312437, 0.9988582529369309], + [-0.10769947128273318, -2.2707719836034812e-05, -0.00022707720927428454, 0.12775516510009766, 7.330325843213359e-06, 0.00030702617368660867, 0.9984960291624968], + [-0.10719187355088806, -2.7425710868556052e-05, -0.00027425712323747575, 0.12590137124061584, 9.09294521989068e-06, 0.0003012513043358922, 0.998142616186421], + [-0.10671988928055773, -3.181291322107427e-05, -0.0003181291394867003, 0.12417753040790558, 1.0831430699909106e-05, 0.00029588284087367356, 0.9977978007878223], + [-0.10628102618360663, -3.589252446545288e-05, -0.00035892523010261357, 0.1225745677947998, 1.2547474398161285e-05, 0.0002908922324422747, 0.9974613748289103], + [-0.09686010100009308, -0.00012337604130152613, -0.00033376028295606375, 0.08820036798715591, 1.378227989334846e-05, 0.00018323057156521827, 0.9971327104622644], + [-0.09711245617035859, -0.00012103597691748291, -0.00031035972642712295, 0.08911982923746109, 1.5029957467049826e-05, 0.00018614112923387438, 0.9968120741787946], + [-0.09734714586614258, -0.00011885998537763953, -0.00028859981102868915, 0.08997482806444168, 1.6289604900521226e-05, 0.0001888489641714841, 0.9964992693384843], + [-0.09756540626975398, -0.00011683656339300796, -0.0002683655184227973, 0.09076987206935883, 1.7560383639647625e-05, 0.00019136829359922558, 0.9961941041558584], + [-0.09776839378969632, -0.00011495500075398013, -0.00024954992113634944, 0.09150917828083038, 1.88415124284802e-05, 0.00019371230155229568, 0.9958963915774781], + [-0.04090147625093484, -0.004023205488920212, -0.00023205348406918347, 0.31463244557380676, 3.578325777198188e-05, -0.22863617539405823, 0.9955856059993178], + [-0.04097017598155184, -0.0040215784683823586, -0.00021578377345576882, 0.3147938847541809, 5.273369970382191e-05, -0.2285631000995636, 0.9952824091350698], + [-0.0410352771200895, -0.004020065534859896, -0.0002006547583732754, 0.31494399905204773, 6.96922215865925e-05, -0.2284919172525406, 0.9949866152926238], + [-0.041097000895768086, -0.004018658772110939, -0.00018658647604752332, 0.3150835931301117, 8.665826317155734e-05, -0.22842256724834442, 0.9946980433511353], + [-0.04115555977774558, -0.004017350263893604, -0.00017350453708786517, 0.3152133822441101, 0.0001036312896758318, -0.22835500538349152, 0.9944165166465714], + [-0.04121116576736435, -0.0040161339566111565, -0.000161339805345051, 0.3153340816497803, 0.00012061082088621333, -0.2282891720533371, 0.9941418628602553], + [-0.04126399733776618, -0.004015002865344286, -0.0001500279613537714, 0.31544631719589233, 0.00013759639114141464, -0.22822502255439758, 0.9938739139103233], + [-0.04131423253346301, -0.004013950936496258, -0.000139509211294353, 0.31555068492889404, 0.00015458758571185172, -0.22816252708435059, 0.9936125058460087], + [-0.041362040718768846, -0.004012972582131624, -0.00012972795229870826, 0.31564775109291077, 0.00017158400441985577, -0.22810161113739014, 0.99335747874467], + [-0.04140755778402792, -0.004012063145637512, -0.00012063248141203076, 0.3157379925251007, 0.00018858526891563088, -0.22804224491119385, 0.9931086766114875], + [-0.04145094405318292, -0.004011217504739761, -0.00011217471183044836, 0.31582191586494446, 0.00020559107360895723, -0.22798439860343933, 0.9928659472817497], + [-0.04149231813809619, -0.004010431002825499, -0.0001043099255184643, 0.31589996814727783, 0.00022260106925386935, -0.22792799770832062, 0.9926291423256576], + [-0.04153181484392212, -0.004009699448943138, -9.699655493022874e-05, 0.31597253680229187, 0.0002396149793639779, -0.2278730422258377, 0.9923981169555751], + [-0.041569535562070485, -0.004009019583463669, -9.019594290293753e-05, 0.3160400092601776, 0.0002566325129009783, -0.22781947255134583, 0.9921727299356587], + [-0.04160559790412195, -0.004008387215435505, -8.387213165406138e-05, 0.3161027431488037, 0.0002736534224823117, -0.2277672439813614, 0.991952843493798], + [0.39149452693873815, -0.17847982048988342, 0.17520178854465485, -0.9919443130493164, -0.0012358271051198244, -0.4408690929412842, 0.9875400426961929], + [0.37430655796667994, -0.16218021512031555, 0.33819782733917236, -0.9469498991966248, -0.0012358271051198244, -0.4235963821411133, 0.9836890276104427], + [0.3521089741311741, -0.14702340960502625, 0.4897659122943878, -0.9051101207733154, -0.0012358271051198244, -0.38455620408058167, 0.9802772670978159], + [0.33180054687547955, -0.13292928040027618, 0.6307072639465332, -0.8662038445472717, -0.0012358271051198244, -0.34926027059555054, 0.9772155204395125], + [0.3131357750502409, -0.11982330679893494, 0.7617669701576233, -0.830025315284729, -0.0012358271051198244, -0.3171355724334717, 0.9744541209523172], + [0.2959267284560149, -0.1076362207531929, 0.8836377859115601, -0.7963834404945374, -0.0012358271051198244, -0.287752240896225, 0.9719767824781306], + [0.2800275202058069, -0.09630359709262848, 0.9969640374183655, -0.7651001811027527, -0.0012358271051198244, -0.26078182458877563, 0.9697871497690216], + [0.26531816675540615, -0.0857655256986618, 1.1023447513580322, -0.7360102534294128, -0.0012358271051198244, -0.23596204817295074, 0.9678939521880274], + [0.25198985745877733, -0.07596629858016968, 1.2003370523452759, -0.7089598774909973, -0.002314679091796279, -0.2130759358406067, 0.9663002834303565], + [0.2396477597851904, -0.06685411185026169, 1.2914588451385498, -0.6838060617446899, -0.0033552534878253937, -0.1919393688440323, 0.9649991785284114], + [-0.09422456384566856, 0.2572912275791168, 1.2009122371673584, 0.21098390221595764, -0.003034190973266959, 0.13744576275348663, 0.9640429283994295], + [-0.07978759632768234, 0.24887140095233917, 1.1167140007019043, 0.18774132430553436, -0.002748497761785984, 0.10748443752527237, 0.9631736928535165], + [-0.0664175214480964, 0.241041898727417, 1.0384190082550049, 0.16612830758094788, -0.002495693741366267, 0.07983637601137161, 0.9623884128742163], + [-0.053728477209861736, 0.23376135528087616, 0.9656134843826294, 0.14603063464164734, -0.0022734731901437044, 0.05319900065660477, 0.9616834933561276], + [-0.04201910414965606, 0.22699125111103058, 0.8979125022888184, 0.12734206020832062, -0.0020796917378902435, 0.028771236538887024, 0.9610549332646039], + [-0.031218250517506735, 0.22069580852985382, 0.8349581360816956, 0.10996375977993011, -0.0019123556558042765, 0.006389177404344082, 0.9604984525950518], + [-0.021263405719875502, 0.21484176814556122, 0.77641761302948, 0.09380389004945755, -0.0017696106806397438, -0.014086096547544003, 0.960009608840235], + [-0.012098686887233694, 0.20939815044403076, 0.7219814658164978, 0.078777015209198, -0.0016497325850650668, -0.03277546167373657, 0.9595838985390357], + [-0.003672592715702306, 0.20433619618415833, 0.6713619828224182, 0.06480371952056885, -0.0015511182136833668, -0.04978952929377556, 0.9592168418991078], + [0.00406393343230147, 0.19962915778160095, 0.6242915391921997, 0.05181010439991951, -0.001472276751883328, -0.06523533910512924, 0.9589040503149374], + [0.48410737514213165, 0.18219728767871857, 0.44997286796569824, -1.1394410133361816, -0.001472276751883328, -0.6335095763206482, 0.9587681111885773], + [0.49315757002758503, 0.16598761081695557, 0.28787603974342346, -1.1841872930526733, -0.001472276751883328, -0.6214309334754944, 0.9587904679721979], + [0.5019417267515031, 0.15091441571712494, 0.13714411854743958, -1.225796103477478, -0.001472276751883328, -0.6114248037338257, 0.9589498270423709], + [0.5066429697011797, 0.13689802587032318, -0.003019690979272127, -1.2644877433776855, -0.001472276751883328, -0.5896181464195251, 0.9592242556540338], + [0.5101462535718515, 0.12386436760425568, -0.13335634768009186, -1.3004666566848755, -0.001472276751883328, -0.5670620203018188, 0.9595791248723795], + [0.5142910196551662, 0.11174451559782028, -0.2545548677444458, -1.333923101425171, -0.001472276751883328, -0.5495010018348694, 0.9599940969615668], + [0.5201145837768681, 0.10047440975904465, -0.36725589632987976, -1.365033745765686, -0.001472276751883328, -0.5403749346733093, 0.9604526447819721], + [0.5266811298830298, 0.08999447524547577, -0.4720552861690521, -1.393963098526001, -0.001472276751883328, -0.535976767539978, 0.960942258826627], + [0.5338802248892695, 0.08024930208921432, -0.5695069432258606, -1.4208643436431885, -0.0036344616673886776, -0.5336002111434937, 0.9614542357182847], + [0.5408488076228934, 0.07118739187717438, -0.6601260900497437, -1.4458792209625244, -0.0058347126469016075, -0.5321179628372192, 0.9619831418920445], + [0.7028698686034933, -0.11038433760404587, -0.6138433814048767, -1.9471006393432617, -0.008797692134976387, -0.6217712163925171, 0.9607405300190316], + [0.6994011993598761, -0.1060805693268776, -0.5708056688308716, -1.9352203607559204, -0.01174259278923273, -0.6179541945457458, 0.9596426684609639], + [0.23312593818015387, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011739371344447136, -0.9908731579780579, 0.952430201176377], + [0.2434041360989544, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.01178255956619978, -1.025451421737671, 0.9449690078640667], + [0.253317730894443, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011868905276060104, -1.0575085878372192, 0.9373360301855578], + [0.26255685417824387, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.01199538167566061, -1.086762547492981, 0.9295956164929802], + [0.2710665935147652, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012159174308180809, -1.1133455038070679, 0.9218004861200195], + [0.27887848906778195, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.01235766801983118, -1.1375019550323486, 0.9139932139127096], + [0.2860453251332994, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012588429264724255, -1.1594711542129517, 0.9062078294862433], + [0.29262013944878107, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012849196791648865, -1.1794589757919312, 0.8984713202557664], + [0.2965762375070544, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013137864880263805, -1.1887227296829224, 0.890804948172658], + [0.29673017429383713, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013452478684484959, -1.1821510791778564, 0.8832253574194441], + [0.41061267535808227, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.015475008636713028, -1.1757267713546753, 0.875901053699282], + [0.40652346184609994, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01745983213186264, -1.1687333583831787, 0.8685500023249335], + [0.40265765780722296, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.01940959133207798, -1.1617332696914673, 0.8612116165161448], + [0.3990088976545998, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.021326744928956032, -1.1547510623931885, 0.8539169219698891], + [0.3955735707575926, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02321358025074005, -1.1478044986724854, 0.8466900757753881], + [0.3923516701322979, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.025072220712900162, -1.1409056186676025, 0.8395496933996105], + [0.3893475132440573, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026904644444584846, -1.13406240940094, 0.8325099606152043], + [0.3865700034207256, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028712689876556396, -1.1272797584533691, 0.8255815419106031], + [0.3840324206232294, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030498066917061806, -1.1205604076385498, 0.818772311184273], + [0.38175135472175165, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03226236253976822, -1.1139053106307983, 0.8120879340440293], + [0.3797449488321292, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.034007057547569275, -1.1073145866394043, 0.8055323294502604], + [0.3780300673806064, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.03573352470993996, -1.1007879972457886, 0.7991080348309247], + [0.37661911222198174, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.03744304180145264, -1.0943243503570557, 0.7928164947139084], + [0.375516623653327, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.039136793464422226, -1.0879226922988892, 0.7866582890856323], + [0.3747164794461302, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.040815893560647964, -1.0815815925598145, 0.7806333143686989], + [-0.20772754196718846, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.038344670087099075, 0.2443287968635559, 0.7746891641094066], + [-0.21866468578859813, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03580063208937645, 0.22835691273212433, 0.768857914097388], + [-0.21585936135228045, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03318887948989868, 0.19066141545772552, 0.7629371203539954], + [-0.21170539564628826, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030514167621731758, 0.18755827844142914, 0.7569298493810652], + [-0.20825468733893712, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027780907228589058, 0.1886463463306427, 0.7509517971922638], + [-0.20765131927666683, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.024993203580379486, 0.189396932721138, 0.7449545261546827], + [-0.20931310703436964, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022154873237013817, 0.1900661140680313, 0.7388997712783383], + [-0.2119479932436941, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019269464537501335, 0.19072134792804718, 0.7327627342863612], + [-0.214879791806119, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016340281814336777, 0.19137808680534363, 0.726534773886686], + [-0.21783949300901684, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013370390981435776, 0.1920388787984848, 0.72022400558647], + [-0.4000595975484858, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013370390981435776, 0.21871788799762726, 0.724840854185572], + [-0.3994851887388485, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007358826231211424, 0.21651430428028107, 0.7293932460262814], + [-0.12559398326384016, 0.16584111750125885, 0.6584112048149109, 0.5665791034698486, -0.007358826231211424, -0.08538465946912766, 0.7349058161108437], + [-0.10789803604675546, 0.1436968892812729, 0.43696895241737366, 0.5290815234184265, -0.007358826231211424, -0.11545012146234512, 0.7405128616799562], + [-0.0862580050786427, 0.1231052428483963, 0.2310524582862854, 0.4942130148410797, -0.007358826231211424, -0.16420002281665802, 0.7461701549526497], + [-0.07228152550883607, 0.10395731776952744, 0.039573147892951965, 0.46178919076919556, -0.007358826231211424, -0.18570244312286377, 0.7518367441941683], + [-0.059641074877463084, 0.08615188300609589, -0.13848116993904114, 0.4316386580467224, -0.007358826231211424, -0.2014855146408081, 0.7574720838700055], + [-0.048077934326112653, 0.06959482282400131, -0.3040517568588257, 0.40360206365585327, -0.005887060891836882, -0.2165762484073639, 0.7630477127348814], + [-0.032830461086908264, 0.05419861152768135, -0.4580138921737671, 0.37753111124038696, -0.005887060891836882, -0.24716003239154816, 0.768545673778488], + [-0.019114990494410455, 0.03988185524940491, -0.6011814475059509, 0.35328808426856995, -0.005887060891836882, -0.2746863067150116, 0.7739557730076617], + [-0.006568739275635086, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.005887060891836882, -0.29983335733413696, 0.7792738195520029], + [0.005020647807338746, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.005887060891836882, -0.32303452491760254, 0.7844993819957966], + [0.22014447128082382, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.006316260434687138, -0.632738471031189, 0.7807180815256229], + [0.2115738977363323, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006723836064338684, -0.6094859838485718, 0.777189561263008], + [0.20363067710926294, -0.26899752020835876, -0.6899752616882324, -0.16974768042564392, -0.007111303508281708, -0.5878965258598328, 0.7739044654886423], + [-0.5364496390516296, -0.24663199484348297, -0.4663200080394745, -0.13187538087368011, -0.007111303508281708, 2.147817850112915, 0.7714640447550488], + [-0.5626995659039997, -0.22583456337451935, -0.25834566354751587, -0.09665840119123459, -0.007111303508281708, 2.1954567432403564, 0.7699120400719075], + [-0.5788702079428418, -0.2064952701330185, -0.06495276838541031, -0.06391053646802902, -0.007111303508281708, 2.2071051597595215, 0.7692452258750052], + [-0.5566819383639362, -0.1885119080543518, 0.11488097161054611, -0.033458687365055084, -0.007111303508281708, 2.100590705871582, 0.7693473090415099], + [-0.5595099396933427, -0.17178937792778015, 0.2821062207221985, -0.005141880363225937, -0.007111303508281708, 2.100940704345703, 0.7700537236118319], + [-0.8676624855778264, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.01135850790888071, 5.69326639175415, 0.7638278009790337], + [-0.8480258972379789, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015552760101854801, 5.644999980926514, 0.7576461193038383], + [-0.8396424971861073, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.019697772338986397, 5.596573829650879, 0.7514720746944674], + [-0.836060292926218, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.02379699796438217, 5.547639846801758, 0.7452774336652609], + [-0.8343545265510168, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027853645384311676, 5.497928619384766, 0.7390478495218085], + [-0.999999999999923, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027853645384311676, 6.132761478424072, 0.7446808313863519], + [-0.9999999999999263, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027853645384311676, 6.175716876983643, 0.7501764234493237], + [-0.9999999999999294, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027853645384311676, 6.21760368347168, 0.7555379766814936], + [-0.999999999999932, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027853645384311676, 6.258456707000732, 0.7607687603226371], + [-0.9999999999999345, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027853645384311676, 6.298305988311768, 0.765871963874974], + [-0.9999999999999989, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027853645384311676, 6.337148666381836, 0.7708506990480516], + [-0.9999999999999988, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027853645384311676, 6.375036239624023, 0.775708001655932], + [0.21049512553768698, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.003978789318352938, -6.231379508972168, 0.780446833468498], + [0.2167229865238455, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03572205454111099, -6.270630836486816, 0.7850700840173425], + [0.22259849652426045, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06738241016864777, -6.309582233428955, 0.7895805723576782], + [0.22835713541223146, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09896565973758698, -6.349024772644043, 0.7939810487872736], + [0.23442855370863105, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.13047721982002258, -6.390467166900635, 0.7982741965234642], + [0.248353420679028, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16192211210727692, -6.4614481925964355, 0.8020599373232822], + [0.25067633677385975, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19330500066280365, -6.4907050132751465, 0.8054052405018639], + [0.25126092480715734, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.22463025152683258, -6.514287948608398, 0.808214631238123], + [0.250099985295841, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25590190291404724, -6.532121181488037, 0.8103390489042367], + [0.24689576802597524, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2871236801147461, -6.543070316314697, 0.8116433931864653], + [0.9999999999999986, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2871236801147461, -7.163768768310547, 0.8135545394151179], + [0.9999999999999986, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2871236801147461, -7.178984642028809, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.6282397257481224, -0.0759519413113594, 0.05048057436943054, -2.187089681625366, -0.0002551604702603072, -0.3603832423686981, 0.9991124139302132], + [0.5691325038955412, -0.0712578147649765, 0.09742186218500137, -1.9766871929168701, -0.00048577398410998285, -0.35422271490097046, 0.9982771386678583], + [0.5141920378419026, -0.06689280271530151, 0.14107200503349304, -1.781036376953125, -0.0006935615674592555, -0.3485835790634155, 0.9974910563680077], + [0.4631199568724304, -0.06283382326364517, 0.18166175484657288, -1.5991029739379883, -0.0008801235817372799, -0.34340646862983704, 0.9967511103297959], + [0.4156403360710332, -0.05905943363904953, 0.21940568089485168, -1.4299253225326538, -0.0010469482513144612, -0.33864158391952515, 0.996054354716816], + [0.37152292685438515, -0.05554967001080513, 0.2545033097267151, -1.272608995437622, -0.0011954192304983735, -0.3343393802642822, 0.9953979847183112], + [0.33049756880200193, -0.05228598415851593, 0.2871401607990265, -1.1263223886489868, -0.0013268234906718135, -0.3303412199020386, 0.9947793526160259], + [-0.5128558334344437, 0.01770082116127014, 0.2670082151889801, 2.0106611251831055, -0.0013268234906718135, -0.26141688227653503, 0.9947870032699171], + [-0.489527715216843, 0.015828775241971016, 0.24828776717185974, 1.9267513751983643, -0.001102035865187645, -0.26311376690864563, 0.9947971654884007], + [-0.46783530644871996, 0.014087983407080173, 0.23087982833385468, 1.8487247228622437, -0.0008863512775860727, -0.2646978199481964, 0.9948095529007845] + ] + }, + "2023_tuned": { + "before": { + "factor": 3.6600000858306885, + "negLimit": -3.0, + "posLimit": 3.0 + }, + "after": { + "factor": 3.6600000858306885, + "negLimit": -3.6600000858306885, + "posLimit": 3.6600000858306885 + }, + "rows": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10946365319690253, -6.3100724219111726e-06, -6.310072058113292e-05, 0.1341981738805771, 1.8787743556458736e-06, 0.00032638496486470103, 0.9996100118902765], + [-0.10883226781007806, -1.2177733879070729e-05, -0.00012177733879070729, 0.1318926364183426, 3.725271199073177e-06, 0.0003191980067640543, 0.9992295059317203], + [-0.10824517696030346, -1.7634001778787933e-05, -0.00017634002142585814, 0.12974874675273895, 5.541753580473596e-06, 0.00031251655309461057, 0.9988582529369309], + [-0.10769927427915203, -2.2707719836034812e-05, -0.00022707720927428454, 0.12775516510009766, 7.330325843213359e-06, 0.00030630515539087355, 0.9984960291624968], + [-0.10719167668995669, -2.7425710868556052e-05, -0.00027425712323747575, 0.12590137124061584, 9.09294521989068e-06, 0.0003005308099091053, 0.998142616186421], + [-0.10671969255537025, -3.181291322107427e-05, -0.0003181291394867003, 0.12417753040790558, 1.0831430699909106e-05, 0.0002951628412120044, 0.9977978007878223], + [-0.10628082958766569, -3.589252446545288e-05, -0.00035892523010261357, 0.1225745677947998, 1.2547474398161285e-05, 0.00029017269844189286, 0.9974613748289103], + [-0.0968599058624398, -0.00012337604130152613, -0.00033376028295606375, 0.08820036798715591, 1.378227989334846e-05, 0.00018251637811772525, 0.9971327104622644], + [-0.09711226105667088, -0.00012103597691748291, -0.00031035972642712295, 0.08911982923746109, 1.5029957467049826e-05, 0.0001854270085459575, 0.9968120741787946], + [-0.09734695077753276, -0.00011885998537763953, -0.00028859981102868915, 0.08997482806444168, 1.6289604900521226e-05, 0.00018813494534697384, 0.9964992693384843], + [-0.09756521120718856, -0.00011683656339300796, -0.0002683655184227973, 0.09076987206935883, 1.7560383639647625e-05, 0.0001906543766381219, 0.9961941041558584], + [-0.09776819875400798, -0.00011495500075398013, -0.00024954992113634944, 0.09150917828083038, 1.88415124284802e-05, 0.00019299845735076815, 0.9958963915774781], + [-0.04038609594503885, -0.004023205488920212, -0.00023205348406918347, 0.31463244557380676, 3.578325777198188e-05, -0.23052246868610382, 0.9955856059993178], + [-0.04045497259462703, -0.0040215784683823586, -0.00021578377345576882, 0.3147938847541809, 5.273369970382191e-05, -0.23044875264167786, 0.9952824091350698], + [-0.04052024540574341, -0.004020065534859896, -0.0002006547583732754, 0.31494399905204773, 6.96922215865925e-05, -0.2303769439458847, 0.9949866152926238], + [-0.04058213580150532, -0.004018658772110939, -0.00018658647604752332, 0.3150835931301117, 8.665826317155734e-05, -0.2303069829940796, 0.9946980433511353], + [-0.04064085643555087, -0.004017350263893604, -0.00017350453708786517, 0.3152133822441101, 0.0001036312896758318, -0.23023882508277893, 0.9944165166465714], + [-0.04069661948485031, -0.0040161339566111565, -0.000161339805345051, 0.3153340816497803, 0.00012061082088621333, -0.23017242550849915, 0.9941418628602553], + [-0.04074960358984859, -0.004015002865344286, -0.0001500279613537714, 0.31544631719589233, 0.00013759639114141464, -0.23010770976543427, 0.9938739139103233], + [-0.040799986954527745, -0.004013950936496258, -0.000139509211294353, 0.31555068492889404, 0.00015458758571185172, -0.2300446629524231, 0.9936125058460087], + [-0.04084793909529766, -0.004012972582131624, -0.00012972795229870826, 0.31564775109291077, 0.00017158400441985577, -0.22998322546482086, 0.99335747874467], + [-0.040893596047652886, -0.004012063145637512, -0.00012063248141203076, 0.3157379925251007, 0.00018858526891563088, -0.22992335259914398, 0.9931086766114875], + [-0.040937118274140864, -0.004011217504739761, -0.00011217471183044836, 0.31582191586494446, 0.00020559107360895723, -0.22986499965190887, 0.9928659472817497], + [-0.0409786245190571, -0.004010431002825499, -0.0001043099255184643, 0.31589996814727783, 0.00022260106925386935, -0.22980812191963196, 0.9926291423256576], + [-0.041018249714166545, -0.004009699448943138, -9.699655493022874e-05, 0.31597253680229187, 0.0002396149793639779, -0.22975268959999084, 0.9923981169555751], + [-0.041056095371993916, -0.004009019583463669, -9.019594290293753e-05, 0.3160400092601776, 0.0002566325129009783, -0.22969865798950195, 0.9921727299356587], + [-0.041092279220044096, -0.004008387215435505, -8.387213165406138e-05, 0.3161027431488037, 0.0002736534224823117, -0.2296459972858429, 0.991952843493798], + [0.3910602049801107, -0.17847982048988342, 0.17520178854465485, -0.9919443130493164, -0.0012358271051198244, -0.43927818536758423, 0.9875400426961929], + [0.3728127754776832, -0.16218021512031555, 0.33819782733917236, -0.9469498991966248, -0.0012358271051198244, -0.418121874332428, 0.9836890276104427], + [0.3507208261109926, -0.14702340960502625, 0.4897659122943878, -0.9051101207733154, -0.0012358271051198244, -0.3794669806957245, 0.9802772670978159], + [0.33052168875038607, -0.13292928040027618, 0.6307072639465332, -0.8662038445472717, -0.0012358271051198244, -0.34457075595855713, 0.9772155204395125], + [0.31196315588541873, -0.11982330679893494, 0.7617669701576233, -0.830025315284729, -0.0012358271051198244, -0.31283509731292725, 0.9744541209523172], + [0.2948547458290457, -0.1076362207531929, 0.8836377859115601, -0.7963834404945374, -0.0012358271051198244, -0.2838205397129059, 0.9719767824781306], + [0.27904976480994237, -0.09630359709262848, 0.9969640374183655, -0.7651001811027527, -0.0012358271051198244, -0.25719547271728516, 0.9697871497690216], + [0.2644281689694541, -0.0857655256986618, 1.1023447513580322, -0.7360102534294128, -0.0012358271051198244, -0.23269745707511902, 0.9678939521880274], + [0.25118140077284884, -0.07596629858016968, 1.2003370523452759, -0.7089598774909973, -0.002314679091796279, -0.2101103514432907, 0.9663002834303565], + [0.2389150006695386, -0.06685411185026169, 1.2914588451385498, -0.6838060617446899, -0.0033552534878253937, -0.1892513930797577, 0.9649991785284114], + [-0.07901424315348991, 0.2572912275791168, 1.2009122371673584, 0.21098390221595764, -0.003034190973266959, 0.08168985694646835, 0.9640429283994295], + [-0.06462022053982568, 0.24887140095233917, 1.1167140007019043, 0.18774132430553436, -0.002748497761785984, 0.051885414868593216, 0.9631736928535165], + [-0.051341863217181795, 0.241041898727417, 1.0384190082550049, 0.16612830758094788, -0.002495693741366267, 0.024573015049099922, 0.9623884128742163], + [-0.038794570414420915, 0.23376135528087616, 0.9656134843826294, 0.14603063464164734, -0.0022734731901437044, -0.0015452472725883126, 0.9616834933561276], + [-0.02727243474777478, 0.22699125111103058, 0.8979125022888184, 0.12734206020832062, -0.0020796917378902435, -0.025287091732025146, 0.9610549332646039], + [-0.016701299459840592, 0.22069580852985382, 0.8349581360816956, 0.10996375977993011, -0.0019123556558042765, -0.046827398240566254, 0.9604984525950518], + [-0.007015004831310648, 0.21484176814556122, 0.77641761302948, 0.09380389004945755, -0.0017696106806397438, -0.06631841510534286, 0.960009608840235], + [0.0018467047985609802, 0.20939815044403076, 0.7219814658164978, 0.078777015209198, -0.0016497325850650668, -0.08389700949192047, 0.9595838985390357], + [0.00994047632837133, 0.20433619618415833, 0.6713619828224182, 0.06480371952056885, -0.0015511182136833668, -0.09969261288642883, 0.9592168418991078], + [0.01732120216671505, 0.19962915778160095, 0.6242915391921997, 0.05181010439991951, -0.001472276751883328, -0.11383365094661713, 0.9589040503149374], + [0.5091351260568596, 0.18219728767871857, 0.44997286796569824, -1.1394410133361816, -0.001472276751883328, -0.7252450585365295, 0.9587681111885773], + [0.5139989779286086, 0.16598761081695557, 0.28787603974342346, -1.1841872930526733, -0.001472276751883328, -0.6978006362915039, 0.9587904679721979], + [0.5185418167319423, 0.15091441571712494, 0.13714411854743958, -1.225796103477478, -0.001472276751883328, -0.6722335815429688, 0.9589498270423709], + [0.51885924037396, 0.13689802587032318, -0.003019690979272127, -1.2644877433776855, -0.001472276751883328, -0.6343601942062378, 0.9592242556540338], + [0.5173505210709428, 0.12386436760425568, -0.13335634768009186, -1.3004666566848755, -0.001472276751883328, -0.593455970287323, 0.9595791248723795], + [0.5184302249753999, 0.11174451559782028, -0.2545548677444458, -1.333923101425171, -0.001472276751883328, -0.5646713376045227, 0.9599940969615668], + [0.5224928584304824, 0.10047440975904465, -0.36725589632987976, -1.365033745765686, -0.001472276751883328, -0.5490943193435669, 0.9604526447819721], + [0.5280438958049607, 0.08999447524547577, -0.4720552861690521, -1.393963098526001, -0.001472276751883328, -0.5409742593765259, 0.960942258826627], + [0.5346631335970315, 0.08024930208921432, -0.5695069432258606, -1.4208643436431885, -0.0036344616673886776, -0.5364716649055481, 0.9614542357182847], + [0.5413127450841172, 0.07118739187717438, -0.6601260900497437, -1.4458792209625244, -0.0058347126469016075, -0.5338196754455566, 0.9619831418920445], + [0.7082116168003382, -0.11038433760404587, -0.6138433814048767, -1.9471006393432617, -0.008797692134976387, -0.6413612365722656, 0.9607405300190316], + [0.7042939608425406, -0.1060805693268776, -0.5708056688308716, -1.9352203607559204, -0.01174259278923273, -0.6358973979949951, 0.9596426684609639], + [0.24831279792116212, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011739371344447136, -1.0561350584030151, 0.952430201176377], + [0.2605646218326958, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.01178255956619978, -1.09934401512146, 0.9449690078640667], + [0.2718220379521747, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011868905276060104, -1.1372101306915283, 0.9373360301855578], + [0.28187099517007774, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.01199538167566061, -1.1699283123016357, 0.9295956164929802], + [0.2907922906315725, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012159174308180809, -1.1982460021972656, 0.9218004861200195], + [0.29874013254349824, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.01235766801983118, -1.2229489088058472, 0.9139932139127096], + [0.30586049504387924, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012588429264724255, -1.2446823120117188, 0.9062078294862433], + [0.31227171779225527, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012849196791648865, -1.2639342546463013, 0.8984713202557664], + [0.31613837939627004, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013137864880263805, -1.2727845907211304, 0.890804948172658], + [0.31598466647005247, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013452478684484959, -1.2648652791976929, 0.8832253574194441], + [0.412307398886842, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.015475008636713028, -1.1827421188354492, 0.875901053699282], + [0.40834035227403603, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01745983213186264, -1.1762652397155762, 0.8685500023249335], + [0.40459407470573316, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.01940959133207798, -1.1697709560394287, 0.8612116165161448], + [0.4010615788878822, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.021326744928956032, -1.1632810831069946, 0.8539169219698891], + [0.39773876014683174, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02321358025074005, -1.1568107604980469, 0.8466900757753881], + [0.3946252502771808, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.025072220712900162, -1.1503701210021973, 0.8395496933996105], + [0.3917251408411536, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026904644444584846, -1.1439656019210815, 0.8325099606152043], + [0.38904724328331075, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028712689876556396, -1.1376007795333862, 0.8255815419106031], + [0.3866048728576752, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030498066917061806, -1.1312776803970337, 0.818772311184273], + [0.3844147674325609, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03226236253976822, -1.1249967813491821, 0.8120879340440293], + [0.38249530688908656, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.034007057547569275, -1.118757963180542, 0.8055323294502604], + [0.3808636470380862, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.03573352470993996, -1.1125606298446655, 0.7991080348309247], + [0.3795324926695101, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.03744304180145264, -1.106404185295105, 0.7928164947139084], + [0.37850665054287286, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.039136793464422226, -1.100287675857544, 0.7866582890856323], + [0.3777801819633453, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.040815893560647964, -1.094210147857666, 0.7806333143686989], + [-0.20729777909370484, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.038344670087099075, 0.2426171749830246, 0.7746891641094066], + [-0.21818560264028714, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03580063208937645, 0.22653359174728394, 0.768857914097388], + [-0.21585936156737215, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03318887948989868, 0.19066141545772552, 0.7629371203539954], + [-0.21170539606511912, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030514167621731758, 0.18755827844142914, 0.7569298493810652], + [-0.2082546880932433, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027780907228589058, 0.1886463463306427, 0.7509517971922638], + [-0.20765132059944635, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.024993203580379486, 0.1893969476222992, 0.7449545261546827], + [-0.20931310928896568, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022154873237013817, 0.1900661289691925, 0.7388997712783383], + [-0.21194799696328787, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019269464537501335, 0.19072136282920837, 0.7327627342863612], + [-0.21487979774071636, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016340281814336777, 0.19137810170650482, 0.726534773886686], + [-0.217839502176056, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013370390981435776, 0.19203892350196838, 0.72022400558647], + [-0.3953891079754344, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013370390981435776, 0.1986016035079956, 0.724840854185572], + [-0.39486614266660935, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007358826231211424, 0.19661948084831238, 0.7293932460262814], + [-0.10759649751357757, 0.16584111750125885, 0.6584112048149109, 0.5665791034698486, -0.007358826231211424, -0.15328480303287506, 0.7349058161108437], + [-0.09036072132795119, 0.1436968892812729, 0.43696895241737366, 0.5290815234184265, -0.007358826231211424, -0.18148404359817505, 0.7405128616799562], + [-0.07369937041296183, 0.1231052428483963, 0.2310524582862854, 0.4942130148410797, -0.007358826231211424, -0.21117648482322693, 0.7461701549526497], + [-0.06381701228028135, 0.10395731776952744, 0.039573147892951965, 0.46178919076919556, -0.007358826231211424, -0.217171773314476, 0.7518367441941683], + [-0.055415743881643206, 0.08615188300609589, -0.13848116993904114, 0.4316386580467224, -0.007358826231211424, -0.21726959943771362, 0.7574720838700055], + [-0.0466145040604287, 0.06959482282400131, -0.3040517568588257, 0.40360206365585327, -0.005887060891836882, -0.22208988666534424, 0.7630477127348814], + [-0.03318032454594341, 0.05419861152768135, -0.4580138921737671, 0.37753111124038696, -0.005887060891836882, -0.24583345651626587, 0.768545673778488], + [-0.020609027396592147, 0.03988185524940491, -0.6011814475059509, 0.35328808426856995, -0.005887060891836882, -0.26900291442871094, 0.7739557730076617], + [-0.00884738160424083, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.005887060891836882, -0.29115262627601624, 0.7792738195520029], + [0.0021526107575593704, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.005887060891836882, -0.3121010661125183, 0.7844993819957966], + [0.23092860055943876, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.006316260434687138, -0.6732545495033264, 0.7807180815256229], + [0.22203645253943774, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006723836064338684, -0.6487880349159241, 0.777189561263008], + [0.21375181990764777, -0.26899752020835876, -0.6899752616882324, -0.16974768042564392, -0.007111303508281708, -0.6259075403213501, 0.7739044654886423], + [-0.5908803176998131, -0.24663199484348297, -0.4663200080394745, -0.13187538087368011, -0.007111303508281708, 2.3516433238983154, 0.7714640447550488], + [-0.6025141066934809, -0.22583456337451935, -0.25834566354751587, -0.09665840119123459, -0.007111303508281708, 2.343456745147705, 0.7699120400719075], + [-0.6035832997589058, -0.2064952701330185, -0.06495276838541031, -0.06391053646802902, -0.007111303508281708, 2.2982985973358154, 0.7692452258750052], + [-0.5297092393754228, -0.1885119080543518, 0.11488097161054611, -0.033458687365055084, -0.007111303508281708, 2.00077748298645, 0.7693473090415099], + [-0.5292549307682339, -0.17178937792778015, 0.2821062207221985, -0.005141880363225937, -0.007111303508281708, 1.9879966974258423, 0.7700537236118319], + [-0.8676624855778264, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.01135850790888071, 5.69266414642334, 0.7638278009790337], + [-0.8480258972379789, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015552760101854801, 5.643935680389404, 0.7576461193038383], + [-0.8396424971861073, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.019697772338986397, 5.59476900100708, 0.7514720746944674], + [-0.836060292926218, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.02379699796438217, 5.54469633102417, 0.7452774336652609], + [-0.8343545265510168, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027853645384311676, 5.493298530578613, 0.7390478495218085], + [-0.999999999999923, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027853645384311676, 6.132761478424072, 0.7446808313863519], + [-0.9999999999999263, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027853645384311676, 6.175716876983643, 0.7501764234493237], + [-0.9999999999999294, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027853645384311676, 6.21760368347168, 0.7555379766814936], + [-0.999999999999932, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027853645384311676, 6.258456707000732, 0.7607687603226371], + [-0.9999999999999345, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027853645384311676, 6.298305988311768, 0.765871963874974], + [-0.9999999999999989, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027853645384311676, 6.337148666381836, 0.7708506990480516], + [-0.9999999999999988, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027853645384311676, 6.375036239624023, 0.775708001655932], + [0.21049512553768698, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.003978789318352938, -6.231379508972168, 0.780446833468498], + [0.2167229865238455, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03572205454111099, -6.270630836486816, 0.7850700840173425], + [0.22259849652426045, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06738241016864777, -6.309582233428955, 0.7895805723576782], + [0.22835713541223146, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09896565973758698, -6.349024772644043, 0.7939810487872736], + [0.23442855370863105, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.13047721982002258, -6.390467166900635, 0.7982741965234642], + [0.248353420679028, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16192211210727692, -6.4614481925964355, 0.8020599373232822], + [0.25067633677385975, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19330500066280365, -6.4907050132751465, 0.8054052405018639], + [0.25126092480715734, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.22463025152683258, -6.514287948608398, 0.808214631238123], + [0.250099985295841, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25590190291404724, -6.532121181488037, 0.8103390489042367], + [0.24689576802597524, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2871236801147461, -6.543070316314697, 0.8116433931864653], + [0.9999999999999986, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2871236801147461, -7.163768768310547, 0.8135545394151179], + [0.9999999999999986, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2871236801147461, -7.178984642028809, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.6300897116143003, -0.0759519413113594, 0.05048057436943054, -2.187089681625366, -0.0002551604702603072, -0.36715421080589294, 0.9991124139302132], + [0.570021419692685, -0.0712578147649765, 0.09742186218500137, -1.9766871929168701, -0.00048577398410998285, -0.357476145029068, 0.9982771386678583], + [0.5144052650105083, -0.06689280271530151, 0.14107200503349304, -1.781036376953125, -0.0006935615674592555, -0.3493639826774597, 0.9974910563680077], + [0.4630606278577127, -0.06283382326364517, 0.18166175484657288, -1.5991029739379883, -0.0008801235817372799, -0.3431893289089203, 0.9967511103297959], + [0.4156212116391389, -0.05905943363904953, 0.21940568089485168, -1.4299253225326538, -0.0010469482513144612, -0.33857160806655884, 0.996054354716816], + [0.37150541385694374, -0.05554967001080513, 0.2545033097267151, -1.272608995437622, -0.0011954192304983735, -0.3342752754688263, 0.9953979847183112], + [0.3304802499251104, -0.05228598415851593, 0.2871401607990265, -1.1263223886489868, -0.0013268234906718135, -0.33027783036231995, 0.9947793526160259], + [-0.5103119485721853, 0.01770082116127014, 0.2670082151889801, 2.0106611251831055, -0.0013268234906718135, -0.27072757482528687, 0.9947870032699171], + [-0.4871247531139276, 0.015828775241971016, 0.24828776717185974, 1.9267513751983643, -0.001102035865187645, -0.27190864086151123, 0.9947971654884007], + [-0.4655545265752654, 0.014087983407080173, 0.23087982833385468, 1.8487247228622437, -0.0008863512775860727, -0.27304553985595703, 0.9948095529007845] + ] + }, + "2025_default": { + "before": { + "factor": 3.6600000858306885, + "negLimit": -3.0, + "posLimit": 3.0 + }, + "after": { + "factor": 3.6600000858306885, + "negLimit": -3.6600000858306885, + "posLimit": 3.6600000858306885 + }, + "rows": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.1000419596173212, -6.3100724219111726e-06, -6.310072058113292e-05, 0.09995962679386139, 1.399434836457658e-06, 0.00010129198199138045, 0.9996100118902765], + [-0.09957267603318784, -1.2177733879070729e-05, -0.00012177733879070729, 0.09824388474225998, 2.774849235720467e-06, 9.798955579753965e-05, 0.9992295059317203], + [-0.09913630335274988, -1.7634001778787933e-05, -0.00017634002142585814, 0.09664839506149292, 4.127926786168246e-06, 9.492012031842023e-05, 0.9988582529369309], + [-0.0987305336073542, -2.2707719836034812e-05, -0.00022707720927428454, 0.0951647162437439, 5.460232841869583e-06, 9.206731920130551e-05, 0.9984960291624968], + [-0.0983532241033397, -2.7425710868556052e-05, -0.00027425712323747575, 0.09378502517938614, 6.773223049094668e-06, 8.941596024669707e-05, 0.998142616186421], + [-0.09800238149944195, -3.181291322107427e-05, -0.0003181291394867003, 0.09250204265117645, 8.06825210020179e-06, 8.695188444107771e-05, 0.9977978007878223], + [-0.09767614986126376, -3.589252446545288e-05, -0.00035892523010261357, 0.09130898118019104, 9.3465778263635e-06, 8.46619441290386e-05, 0.9974613748289103], + [-0.0906673555152992, -0.00012337604130152613, -0.00033376028295606375, 0.06570431590080261, 1.0266438039252535e-05, 3.4840086300391704e-05, 0.9971327104622644], + [-0.0908549993923562, -0.00012103597691748291, -0.00031035972642712295, 0.06638883799314499, 1.119588159781415e-05, 3.6202189221512526e-05, 0.9968120741787946], + [-0.09102950607063971, -0.00011885998537763953, -0.00028859981102868915, 0.06702535599470139, 1.2134236385463737e-05, 3.74701339751482e-05, 0.9964992693384843], + [-0.09119179556600669, -0.00011683656339300796, -0.0002683655184227973, 0.06761724501848221, 1.3080877579341177e-05, 3.865048711304553e-05, 0.9961941041558584], + [-0.09134272615685958, -0.00011495500075398013, -0.00024954992113634944, 0.06816762685775757, 1.4035224921826739e-05, 3.974936407757923e-05, 0.9958963915774781], + [-0.01996371573553552, -0.004023205488920212, -0.00023205348406918347, 0.23997238278388977, 2.695681541808881e-05, -0.23059208691120148, 0.9955856059993178], + [-0.020020306586320584, -0.0040215784683823586, -0.00021578377345576882, 0.24009454250335693, 3.9884980651549995e-05, -0.23052002489566803, 0.9952824091350698], + [-0.020074058243435496, -0.004020065534859896, -0.0002006547583732754, 0.24020811915397644, 5.281926496536471e-05, -0.23044979572296143, 0.9949866152926238], + [-0.02012515337474716, -0.004018658772110939, -0.00018658647604752332, 0.24031373858451843, 6.575923907803372e-05, -0.2303813248872757, 0.9946980433511353], + [-0.020173757713139062, -0.004017350263893604, -0.00017350453708786517, 0.24041196703910828, 7.870449917390943e-05, -0.23031458258628845, 0.9944165166465714], + [-0.020220024205998142, -0.0040161339566111565, -0.000161339805345051, 0.24050329625606537, 9.165467781713232e-05, -0.23024950921535492, 0.9941418628602553], + [-0.020264097164136057, -0.004015002865344286, -0.0001500279613537714, 0.2405882328748703, 0.00010460942576173693, -0.2301860749721527, 0.9938739139103233], + [-0.020306108140690598, -0.004013950936496258, -0.000139509211294353, 0.2406671941280365, 0.00011756843014154583, -0.23012422025203705, 0.9936125058460087], + [-0.02034618421336529, -0.004012972582131624, -0.00012972795229870826, 0.24074062705039978, 0.00013053139264229685, -0.23006391525268555, 0.99335747874467], + [-0.020384443862206083, -0.004012063145637512, -0.00012063248141203076, 0.24080891907215118, 0.00014349802222568542, -0.23000513017177582, 0.9931086766114875], + [-0.020420996981293797, -0.004011217504739761, -0.00011217471183044836, 0.24087241291999817, 0.00015646807150915265, -0.22994780540466309, 0.9928659472817497], + [-0.020455940755107285, -0.004010431002825499, -0.0001043099255184643, 0.2409314513206482, 0.0001694413076620549, -0.22989189624786377, 0.9926291423256576], + [-0.02048937620788005, -0.004009699448943138, -9.699655493022874e-05, 0.24098636209964752, 0.0001824174978537485, -0.22983740270137787, 0.9923981169555751], + [-0.02052139167532128, -0.004009019583463669, -9.019594290293753e-05, 0.24103742837905884, 0.00019539643835742027, -0.22978425025939941, 0.9921727299356587], + [-0.02055206694872401, -0.004008387215435505, -8.387213165406138e-05, 0.24108490347862244, 0.000208377925446257, -0.2297324240207672, 0.991952843493798], + [0.37125703585399955, -0.17847982048988342, 0.17520178854465485, -0.9918082356452942, -0.0013008954701945186, -0.3814098834991455, 0.9875400426961929], + [0.3563249116250143, -0.16218021512031555, 0.33819782733917236, -0.946868360042572, -0.0013008954701945186, -0.37206515669822693, 0.9836890276104427], + [0.3400332838792249, -0.14702340960502625, 0.4897659122943878, -0.9050739407539368, -0.0013008954701945186, -0.35422003269195557, 0.9802772670978159], + [0.3217350521682795, -0.13292928040027618, 0.6307072639465332, -0.8661898374557495, -0.0013008954701945186, -0.32572245597839355, 0.9772155204395125], + [0.30491287464790134, -0.11982330679893494, 0.7617669701576233, -0.8300200700759888, -0.0013008954701945186, -0.29980576038360596, 0.9744541209523172], + [0.2894013817616517, -0.1076362207531929, 0.8836377859115601, -0.7963812947273254, -0.0013008954701945186, -0.2761189341545105, 0.9719767824781306], + [0.2750710937464448, -0.09630359709262848, 0.9969640374183655, -0.7650993466377258, -0.0013008954701945186, -0.2543935775756836, 0.9697871497690216], + [0.26181467125900454, -0.0857655256986618, 1.1023447513580322, -0.7360098361968994, -0.0013008954701945186, -0.23441553115844727, 0.9678939521880274], + [0.24983044597727005, -0.07596629858016968, 1.2003370523452759, -0.7089597582817078, -0.0023797473404556513, -0.21600757539272308, 0.9663002834303565], + [0.23873606444946352, -0.06685411185026169, 1.2914588451385498, -0.6838060021400452, -0.0034203215036541224, -0.19901923835277557, 0.9649991785284114], + [-0.0705208363838269, 0.2572912275791168, 1.2009122371673584, 0.21098388731479645, -0.0030992592219263315, 0.052963316440582275, 0.9640429283994295], + [-0.05791127976724981, 0.24887140095233917, 1.1167140007019043, 0.1877412647008896, -0.0028135660104453564, 0.029326602816581726, 0.9631736928535165], + [-0.04623994586562036, 0.241041898727417, 1.0384190082550049, 0.1661282330751419, -0.002560762222856283, 0.007540617138147354, 0.9623884128742163], + [-0.03523192766033561, 0.23376135528087616, 0.9656134843826294, 0.1460305154323578, -0.0023385416716337204, -0.013294951058924198, 0.9616834933561276], + [-0.025079714113015437, 0.22699125111103058, 0.8979125022888184, 0.1273418664932251, -0.002144760685041547, -0.0323595255613327, 0.9610549332646039], + [-0.01572118218989378, 0.22069580852985382, 0.8349581360816956, 0.10996348410844803, -0.0019774248357862234, -0.049782607704401016, 0.9604984525950518], + [-0.007101273280377882, 0.21484176814556122, 0.77641761302948, 0.0938035100698471, -0.0018346804426982999, -0.06567493826150894, 0.960009608840235], + [0.0008297808296861664, 0.20939815044403076, 0.7219814658164978, 0.0787765309214592, -0.0017148031620308757, -0.08013449609279633, 0.9595838985390357], + [0.008118299997240544, 0.20433619618415833, 0.6713619828224182, 0.0648031160235405, -0.0016161897219717503, -0.0932527706027031, 0.9592168418991078], + [0.014808633638411376, 0.19962915778160095, 0.6242915391921997, 0.05180941894650459, -0.0015373493079096079, -0.1051197424530983, 0.9589040503149374], + [0.4621020573416811, 0.18219728767871857, 0.44997286796569824, -1.139389991760254, -0.0015373493079096079, -0.5709168910980225, 0.9587681111885773], + [0.4713936456137784, 0.16598761081695557, 0.28787603974342346, -1.1840639114379883, -0.0015373493079096079, -0.5606254935264587, 0.9587904679721979], + [0.4803378636321708, 0.15091441571712494, 0.13714411854743958, -1.2255961894989014, -0.0015373493079096079, -0.5520401000976562, 0.9589498270423709], + [0.48935347370831944, 0.13689802587032318, -0.003019690979272127, -1.2642362117767334, -0.0015373493079096079, -0.5467880964279175, 0.9592242556540338], + [0.49761720293209916, 0.12386436760425568, -0.13335634768009186, -1.3002347946166992, -0.0015373493079096079, -0.542256772518158, 0.9595791248723795], + [0.5055234657170684, 0.11174451559782028, -0.2545548677444458, -1.3337390422821045, -0.0015373493079096079, -0.5389915108680725, 0.9599940969615668], + [0.5130901657853517, 0.10047440975904465, -0.36725589632987976, -1.3649104833602905, -0.0015373493079096079, -0.5367147326469421, 0.9604526447819721], + [0.5203109047218069, 0.08999447524547577, -0.4720552861690521, -1.393890619277954, -0.0015373493079096079, -0.5351468920707703, 0.960942258826627], + [0.5277450384735141, 0.08024930208921432, -0.5695069432258606, -1.4208241701126099, -0.0036994728725403547, -0.5340712070465088, 0.9614542357182847], + [0.5348026953298156, 0.07118739187717438, -0.6601260900497437, -1.4458574056625366, -0.0058996910229325294, -0.5333346724510193, 0.9619831418920445], + [0.6780078736348712, -0.11038433760404587, -0.6138433814048767, -1.9470629692077637, -0.008862612769007683, -0.559460461139679, 0.9607405300190316], + [0.6747115695706011, -0.1060805693268776, -0.5708056688308716, -1.9351692199707031, -0.011807435192167759, -0.5562520027160645, 0.9596426684609639], + [0.17851530759705644, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011804213747382164, -0.9532887935638428, 0.952430201176377], + [0.18678538061932282, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.011847402900457382, -0.9791561961174011, 0.9449690078640667], + [0.1949221573654882, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011933748610317707, -1.0030080080032349, 0.9373360301855578], + [0.2026603194855928, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.012060224078595638, -1.024595022201538, 0.9295956164929802], + [0.2099276450828452, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012224017642438412, -1.0440384149551392, 0.9218004861200195], + [0.21672051159074684, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.012422511354088783, -1.0615546703338623, 0.9139932139127096], + [0.22305534883649292, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012653272598981857, -1.077350378036499, 0.9062078294862433], + [0.22895277393356475, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012914039194583893, -1.0915987491607666, 0.8984713202557664], + [0.23443345341931823, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013202708214521408, -1.1044427156448364, 0.890804948172658], + [0.23951749819606138, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013517322018742561, -1.1160025596618652, 0.8832253574194441], + [0.39289334290020206, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.01553985197097063, -1.1072732210159302, 0.875901053699282], + [0.388718206914192, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01752467453479767, -1.100295901298523, 0.8685500023249335], + [0.3847635472904388, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.019474433735013008, -1.0933153629302979, 0.8612116165161448], + [0.3810239175048684, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.02139158733189106, -1.0863571166992188, 0.8539169219698891], + [0.3774964362735405, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02327842265367508, -1.0794397592544556, 0.8466900757753881], + [0.3741815825976844, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.02513706311583519, -1.0725765228271484, 0.8395496933996105], + [0.3710838694605647, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026969488710165024, -1.0657763481140137, 0.8325099606152043], + [0.3682120755403503, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028777534142136574, -1.0590451955795288, 0.8255815419106031], + [0.36557903498433153, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030562909319996834, -1.05238676071167, 0.818772311184273], + [0.36320061149412136, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03232720494270325, -1.0458028316497803, 0.8120879340440293], + [0.3610940314528291, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.0340718999505043, -1.0392942428588867, 0.8055323294502604], + [0.35927519417236253, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.035798367112874985, -1.0328611135482788, 0.7991080348309247], + [0.35775566889097404, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.037507884204387665, -1.0265032052993774, 0.7928164947139084], + [0.35653949259157774, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.03920163959264755, -1.0202194452285767, 0.7866582890856323], + [0.3556205446497881, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.04088073596358299, -1.01400887966156, 0.7806333143686989], + [-0.18928970090431746, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.0384095124900341, 0.1780533492565155, 0.7746891641094066], + [-0.1998281345720566, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03586547449231148, 0.1654033213853836, 0.768857914097388], + [-0.19824261810433141, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03325372561812401, 0.13446398079395294, 0.7629371203539954], + [-0.19419930945511207, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030579011887311935, 0.13123857975006104, 0.7569298493810652], + [-0.19074162262832509, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027845751494169235, 0.1318981796503067, 0.7509517971922638], + [-0.1899161965066632, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.025058045983314514, 0.13255788385868073, 0.7449545261546827], + [-0.1911287448852193, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022219715639948845, 0.1332218497991562, 0.7388997712783383], + [-0.19318406105815286, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019334308803081512, 0.1338927447795868, 0.7327627342863612], + [-0.19546555151826855, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016405124217271805, 0.13457146286964417, 0.726534773886686], + [-0.19773300519680453, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013435234315693378, 0.1352570652961731, 0.72022400558647], + [-0.3129858658797515, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013435234315693378, 0.15824465453624725, 0.724840854185572], + [-0.31099166787599797, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007423669099807739, 0.1564316302537918, 0.7293932460262814], + [-0.1016954787246937, 0.16584111750125885, 0.6584112048149109, 0.5665790438652039, -0.007423669099807739, -0.1395522952079773, 0.7349058161108437], + [-0.08300327240505596, 0.1436968892812729, 0.43696895241737366, 0.5290812253952026, -0.007423669099807739, -0.1789565533399582, 0.7405128616799562], + [-0.06918421965186021, 0.1231052428483963, 0.2310524582862854, 0.4942123293876648, -0.007423669099807739, -0.2024339735507965, 0.7461701549526497], + [-0.05736861692440621, 0.10395731776952744, 0.039573147892951965, 0.46178823709487915, -0.007423669099807739, -0.2196238934993744, 0.7518367441941683], + [-0.046647800181232595, 0.08615188300609589, -0.13848116993904114, 0.43163782358169556, -0.007423669099807739, -0.23217642307281494, 0.7574720838700055], + [-0.03697180534157927, 0.06959482282400131, -0.3040517568588257, 0.4036014974117279, -0.0059389350935816765, -0.2439926415681839, 0.7630477127348814], + [-0.027750959294197044, 0.05419861152768135, -0.4580138921737671, 0.37753087282180786, -0.0059389350935816765, -0.2554107904434204, 0.768545673778488], + [-0.01650420513479283, 0.03988185524940491, -0.6011814475059509, 0.3532879948616028, -0.0059389350935816765, -0.27798032760620117, 0.7739557730076617], + [-0.006215064317218847, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.0059389350935816765, -0.29863041639328003, 0.7792738195520029], + [0.0032896441892095135, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.0059389350935816765, -0.31771352887153625, 0.7844993819957966], + [0.1867415263504139, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.00636813510209322, -0.5570378303527832, 0.7807180815256229], + [0.17962014109123528, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006775710266083479, -0.5382837653160095, 0.777189561263008], + [0.17304498228624188, -0.26899752020835876, -0.6899752616882324, -0.16974766552448273, -0.007163177710026503, -0.520890474319458, 0.7739044654886423], + [-0.5087494300864623, -0.24663199484348297, -0.4663200080394745, -0.13187535107135773, -0.007163177710026503, 2.1945619583129883, 0.7714640447550488], + [-0.5218161964776654, -0.22583456337451935, -0.25834566354751587, -0.09665831178426743, -0.007163177710026503, 2.205286979675293, 0.7699120400719075], + [-0.5338882181449203, -0.2064952701330185, -0.06495276838541031, -0.06391043961048126, -0.007163177710026503, 2.212782382965088, 0.7692452258750052], + [-0.5112945374698926, -0.1885119080543518, 0.11488097161054611, -0.033458638936281204, -0.007163177710026503, 2.1033742427825928, 0.7693473090415099], + [-0.5120801247826361, -0.17178937792778015, 0.2821062207221985, -0.0051418752409517765, -0.007163177710026503, 2.1013295650482178, 0.7700537236118319], + [-0.7708238487688981, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.011410382576286793, 5.746920108795166, 0.7638278009790337], + [-0.7445005123731817, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015604634769260883, 5.698555946350098, 0.7576461193038383], + [-0.7287265403223198, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.01974964700639248, 5.6500163078308105, 0.7514720746944674], + [-0.7176819193766284, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.023848872631788254, 5.600953578948975, 0.7452774336652609], + [-0.7087817643717371, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027905520051717758, 5.551097869873047, 0.7390478495218085], + [-0.9199999685889073, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027905520051717758, 6.068759918212891, 0.7446808313863519], + [-0.9199999685889073, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027905520051717758, 6.111703872680664, 0.7501764234493237], + [-0.9199999685889073, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027905520051717758, 6.153583526611328, 0.7555379766814936], + [-0.9199999685889073, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027905520051717758, 6.194431781768799, 0.7607687603226371], + [-0.9199999685889073, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027905520051717758, 6.234278202056885, 0.765871963874974], + [-0.9199999685889073, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027905520051717758, 6.273124694824219, 0.7708506990480516], + [-0.9199999685889073, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027905520051717758, 6.311017990112305, 0.775708001655932], + [0.22799154825718387, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.0039269146509468555, -6.295364856719971, 0.780446833468498], + [0.23419523367937423, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03567017987370491, -6.334527492523193, 0.7850700840173425], + [0.24001124821910183, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06733053922653198, -6.373260974884033, 0.7895805723576782], + [0.24563307844267657, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09891378879547119, -6.412202835083008, 0.7939810487872736], + [0.2514091635182312, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.1304253488779068, -6.452564239501953, 0.7982741965234642], + [0.26319184231767545, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16187024116516113, -6.51570463180542, 0.8020599373232822], + [0.265450510692521, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19325312972068787, -6.544726848602295, 0.8054052405018639], + [0.26603509872581854, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.2245783805847168, -6.568309783935547, 0.808214631238123], + [0.2648741592145022, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25585001707077026, -6.586142539978027, 0.8103390489042367], + [0.26166994194463644, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2870718240737915, -6.5970916748046875, 0.8116433931864653], + [0.9199999685889073, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2870718240737915, -7.096859455108643, 0.8135545394151179], + [0.9199999685889073, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2870718240737915, -7.112162113189697, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.38513324930148474, -0.0759519413113594, 0.05048057436943054, -1.7808427810668945, -0.00020776498422492296, -0.33449462056159973, 0.9991124139302132], + [0.40075537473288914, -0.0712578147649765, 0.09742186218500137, -1.6257919073104858, -0.00039744071546010673, -0.33135300874710083, 0.9982771386678583], + [0.4201164532492807, -0.06689280271530151, 0.14107200503349304, -1.483040452003479, -0.0005704620853066444, -0.32857346534729004, 0.9974910563680077], + [0.3903238460794766, -0.06283382326364517, 0.18166175484657288, -1.3503772020339966, -0.0007280061254277825, -0.3260654807090759, 0.9967511103297959], + [0.35570301596556403, -0.05905943363904953, 0.21940568089485168, -1.2258175611495972, -0.0008710181573405862, -0.32375097274780273, 0.996054354716816], + [0.3229205375893875, -0.05554967001080513, 0.2545033097267151, -1.1077765226364136, -0.0010002587223425508, -0.32166072726249695, 0.9953979847183112], + [0.2916296151630097, -0.05228598415851593, 0.2871401607990265, -0.995150089263916, -0.001116359606385231, -0.31962889432907104, 0.9947793526160259], + [-0.4353541850257815, 0.01770082116127014, 0.2670082151889801, 1.7472336292266846, -0.001116359606385231, -0.28161153197288513, 0.9947870032699171], + [-0.410655696054713, 0.015828775241971016, 0.24828776717185974, 1.658023476600647, -0.0009229235001839697, -0.28300604224205017, 0.9947971654884007], + [-0.38813969742745874, 0.014087983407080173, 0.23087982833385468, 1.5766654014587402, -0.0007389792008325458, -0.284253865480423, 0.9948095529007845] + ] + }, + "2025_tuned": { + "before": { + "factor": 3.6600000858306885, + "negLimit": -3.0, + "posLimit": 3.0 + }, + "after": { + "factor": 3.6600000858306885, + "negLimit": -3.6600000858306885, + "posLimit": 3.6600000858306885 + }, + "rows": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10004176588515235, -6.3100724219111726e-06, -6.310072058113292e-05, 0.09995962679386139, 1.399434836457658e-06, 0.00010058288171421736, 0.9996100118902765], + [-0.0995724824028674, -1.2177733879070729e-05, -0.00012177733879070729, 0.09824388474225998, 2.774849235720467e-06, 9.72808338701725e-05, 0.9992295059317203], + [-0.09913610982047417, -1.7634001778787933e-05, -0.00017634002142585814, 0.09664839506149292, 4.127926786168246e-06, 9.421175491297618e-05, 0.9988582529369309], + [-0.09873034016950431, -2.2707719836034812e-05, -0.00022707720927428454, 0.0951647162437439, 5.460232841869583e-06, 9.135930304182693e-05, 0.9984960291624968], + [-0.09835303075647045, -2.7425710868556052e-05, -0.00027425712323747575, 0.09378502517938614, 6.773223049094668e-06, 8.870827150531113e-05, 0.998142616186421], + [-0.09800218824027186, -3.181291322107427e-05, -0.0003181291394867003, 0.09250204265117645, 8.06825210020179e-06, 8.62445158418268e-05, 0.9977978007878223], + [-0.09767595668666544, -3.589252446545288e-05, -0.00035892523010261357, 0.09130898118019104, 9.3465778263635e-06, 8.39548883959651e-05, 0.9974613748289103], + [-0.09066716284226353, -0.00012337604130152613, -0.00033376028295606375, 0.06570431590080261, 1.0266438039252535e-05, 3.4134864108636975e-05, 0.9971327104622644], + [-0.0908548067688955, -0.00012103597691748291, -0.00031035972642712295, 0.06638883799314499, 1.119588159781415e-05, 3.549714892869815e-05, 0.9968120741787946], + [-0.09102931349607103, -0.00011885998537763953, -0.00028859981102868915, 0.06702535599470139, 1.2134236385463737e-05, 3.6765271943295375e-05, 0.9964992693384843], + [-0.09119160303962716, -0.00011683656339300796, -0.0002683655184227973, 0.06761724501848221, 1.3080877579341177e-05, 3.794580334215425e-05, 0.9961941041558584], + [-0.09134253367794945, -0.00011495500075398013, -0.00024954992113634944, 0.06816762685775757, 1.4035224921826739e-05, 3.904485492967069e-05, 0.9958963915774781], + [-0.01944845290711774, -0.004023205488920212, -0.00023205348406918347, 0.23997238278388977, 2.695681541808881e-05, -0.23247814178466797, 0.9955856059993178], + [-0.019505220691704045, -0.0040215784683823586, -0.00021578377345576882, 0.24009454250335693, 3.9884980651549995e-05, -0.23240543901920319, 0.9952824091350698], + [-0.019559144034443626, -0.004020065534859896, -0.0002006547583732754, 0.24020811915397644, 5.281926496536471e-05, -0.23233458399772644, 0.9949866152926238], + [-0.01961040579724358, -0.004018658772110939, -0.00018658647604752332, 0.24031373858451843, 6.575923907803372e-05, -0.23226550221443176, 0.9946980433511353], + [-0.019659171897600212, -0.004017350263893604, -0.00017350453708786517, 0.24041196703910828, 7.870449917390943e-05, -0.23219816386699677, 0.9944165166465714], + [-0.019705595458651293, -0.0040161339566111565, -0.000161339805345051, 0.24050329625606537, 9.165467781713232e-05, -0.23213252425193787, 0.9941418628602553], + [-0.01974982095862555, -0.004015002865344286, -0.0001500279613537714, 0.2405882328748703, 0.00010460942576173693, -0.2320685237646103, 0.9938739139103233], + [-0.019791980110236407, -0.004013950936496258, -0.000139509211294353, 0.2406671941280365, 0.00011756843014154583, -0.23200613260269165, 0.9936125058460087], + [-0.01983220014338104, -0.004012972582131624, -0.00012972795229870826, 0.24074062705039978, 0.00013053139264229685, -0.23194530606269836, 0.99335747874467], + [-0.01987059968334614, -0.004012063145637512, -0.00012063248141203076, 0.24080891907215118, 0.00014349802222568542, -0.23188599944114685, 0.9931086766114875], + [-0.019907288762901165, -0.004011217504739761, -0.00011217471183044836, 0.24087241291999817, 0.00015646807150915265, -0.23182816803455353, 0.9928659472817497], + [-0.01994236469903559, -0.004010431002825499, -0.0001043099255184643, 0.2409314513206482, 0.0001694413076620549, -0.2317717969417572, 0.9926291423256576], + [-0.019975928642665286, -0.004009699448943138, -9.699655493022874e-05, 0.24098636209964752, 0.0001824174978537485, -0.2317168116569519, 0.9923981169555751], + [-0.020008069050680716, -0.004009019583463669, -9.019594290293753e-05, 0.24103742837905884, 0.00019539643835742027, -0.23166321218013763, 0.9921727299356587], + [-0.020038865830360516, -0.004008387215435505, -8.387213165406138e-05, 0.24108490347862244, 0.000208377925446257, -0.23161093890666962, 0.991952843493798], + [0.370812088545753, -0.17847982048988342, 0.17520178854465485, -0.9918082356452942, -0.0013008954701945186, -0.37976253032684326, 0.9875400426961929], + [0.3550224507624517, -0.16218021512031555, 0.33819782733917236, -0.946868360042572, -0.0013008954701945186, -0.3672393560409546, 0.9836890276104427], + [0.3387657012828988, -0.14702340960502625, 0.4897659122943878, -0.9050739407539368, -0.0013008954701945186, -0.349520742893219, 0.9802772670978159], + [0.320553117201625, -0.13292928040027618, 0.6307072639465332, -0.8661898374557495, -0.0013008954701945186, -0.32133904099464417, 0.9772155204395125], + [0.3038147853950517, -0.11982330679893494, 0.7617669701576233, -0.8300200700759888, -0.0013008954701945186, -0.29573220014572144, 0.9744541209523172], + [0.28838297435341453, -0.1076362207531929, 0.8836377859115601, -0.7963812947273254, -0.0013008954701945186, -0.27234020829200745, 0.9719767824781306], + [0.27412739976950157, -0.09630359709262848, 0.9969640374183655, -0.7650993466377258, -0.0013008954701945186, -0.2508915066719055, 0.9697871497690216], + [0.2609405940688192, -0.0857655256986618, 1.1023447513580322, -0.7360098361968994, -0.0013008954701945186, -0.2311713993549347, 0.9678939521880274], + [0.24902105124313956, -0.07596629858016968, 1.2003370523452759, -0.7089597582817078, -0.0023797473404556513, -0.21300318837165833, 0.9663002834303565], + [0.2379866968422148, -0.06685411185026169, 1.2914588451385498, -0.6838060021400452, -0.0034203215036541224, -0.19623741507530212, 0.9649991785284114], + [-0.05555523899531584, 0.2572912275791168, 1.2009122371673584, 0.21098388731479645, -0.0030992592219263315, -0.0023925956338644028, 0.9640429283994295], + [-0.04300703739640971, 0.24887140095233917, 1.1167140007019043, 0.1877412647008896, -0.0028135660104453564, -0.025814607739448547, 0.9631736928535165], + [-0.03144173312508024, 0.241041898727417, 1.0384190082550049, 0.1661282330751419, -0.002560762222856283, -0.04721926525235176, 0.9623884128742163], + [-0.020584306498731966, 0.23376135528087616, 0.9656134843826294, 0.1460305154323578, -0.0023385416716337204, -0.0675073191523552, 0.9616834933561276], + [-0.010623455738642828, 0.22699125111103058, 0.8979125022888184, 0.1273418664932251, -0.002144760685041547, -0.08587225526571274, 0.9610549332646039], + [-0.001494547853067832, 0.22069580852985382, 0.8349581360816956, 0.10996348410844803, -0.0019774248357862234, -0.10245289653539658, 0.9604984525950518], + [0.0068604057005683195, 0.21484176814556122, 0.77641761302948, 0.0938035100698471, -0.0018346804426982999, -0.11737086623907089, 0.960009608840235], + [0.014494764465175735, 0.20939815044403076, 0.7219814658164978, 0.0787765309214592, -0.0017148031620308757, -0.13073746860027313, 0.9595838985390357], + [0.02145925383556136, 0.20433619618415833, 0.6713619828224182, 0.0648031160235405, -0.0016161897219717503, -0.14266054332256317, 0.9592168418991078], + [0.027803413077598614, 0.19962915778160095, 0.6242915391921997, 0.05180941894650459, -0.0015373493079096079, -0.1532493233680725, 0.9589040503149374], + [0.4868611346439523, 0.18219728767871857, 0.44997286796569824, -1.139389991760254, -0.0015373493079096079, -0.6626362204551697, 0.9587681111885773], + [0.491999825957422, 0.16598761081695557, 0.28787603974342346, -1.1840639114379883, -0.0015373493079096079, -0.6369588971138, 0.9587904679721979], + [0.49674077912054715, 0.15091441571712494, 0.13714411854743958, -1.2255961894989014, -0.0015373493079096079, -0.6127965450286865, 0.9589498270423709], + [0.5020593921318688, 0.13689802587032318, -0.003019690979272127, -1.2642362117767334, -0.0015373493079096079, -0.5938507318496704, 0.9592242556540338], + [0.5055839611899835, 0.12386436760425568, -0.13335634768009186, -1.3002347946166992, -0.0015373493079096079, -0.5717793107032776, 0.9595791248723795], + [0.5103376594592743, 0.11174451559782028, -0.2545548677444458, -1.3337390422821045, -0.0015373493079096079, -0.5568405389785767, 0.9599940969615668], + [0.5159163517262825, 0.10047440975904465, -0.36725589632987976, -1.3649104833602905, -0.0015373493079096079, -0.5471976399421692, 0.9604526447819721], + [0.5219334806488688, 0.08999447524547577, -0.4720552861690521, -1.393890619277954, -0.0015373493079096079, -0.5411673784255981, 0.960942258826627], + [0.5286669727750853, 0.08024930208921432, -0.5695069432258606, -1.4208241701126099, -0.0036994728725403547, -0.5374927520751953, 0.9614542357182847], + [0.5353362743544783, 0.07118739187717438, -0.6601260900497437, -1.4458574056625366, -0.0058996910229325294, -0.535315215587616, 0.9619831418920445], + [0.6832885473599156, -0.11038433760404587, -0.6138433814048767, -1.9470629692077637, -0.008862612769007683, -0.5790515542030334, 0.9607405300190316], + [0.6795462170511046, -0.1060805693268776, -0.5708056688308716, -1.9351692199707031, -0.011807435192167759, -0.5741888880729675, 0.9596426684609639], + [0.1908011113905084, -0.2528565227985382, -0.7060651779174805, 0.0008099577389657497, -0.011804213747382164, -1.0196528434753418, 0.952430201176377], + [0.20074079294495029, -0.2654341459274292, -0.8318413496017456, -0.010858933441340923, -0.011847402900457382, -1.054008960723877, 0.9449690078640667], + [0.21005581328971235, -0.2771299183368683, -0.9487991333007812, -0.02170969545841217, -0.011933748610317707, -1.0834929943084717, 0.9373360301855578], + [0.2185519968501357, -0.28800567984580994, -1.0575568675994873, -0.031799692660570145, -0.012060224078595638, -1.108378291130066, 0.9295956164929802], + [0.22625973138345304, -0.29811891913414, -1.158689260482788, -0.0411822572350502, -0.012224017642438412, -1.129418134689331, 0.9218004861200195], + [0.2332688587860026, -0.30752310156822205, -1.2527310848236084, -0.04990699514746666, -0.012422511354088783, -1.1473722457885742, 0.9139932139127096], + [0.23966734021868588, -0.3162679374217987, -1.3401795625686646, -0.05802002176642418, -0.012653272598981857, -1.1628490686416626, 0.9062078294862433], + [0.245526388718592, -0.3243996798992157, -1.4214967489242554, -0.06556423008441925, -0.012914039194583893, -1.1762992143630981, 0.8984713202557664], + [0.250901259515652, -0.3319612741470337, -1.4971126317977905, -0.07257950305938721, -0.013202708214521408, -1.1880501508712769, 0.890804948172658], + [0.2558354548718358, -0.338992714881897, -1.5674270391464233, -0.07910291105508804, -0.013517322018742561, -1.198344111442566, 0.8832253574194441], + [0.3945829136566075, -0.8018531799316406, -1.4575316905975342, -0.5085219144821167, -0.01553985197097063, -1.1142884492874146, 0.875901053699282], + [0.39052898584298695, -0.7916341423988342, -1.3553414344787598, -0.4990411698818207, -0.01752467453479767, -1.1078277826309204, 0.8685500023249335], + [0.3866928098321055, -0.782131552696228, -1.2603157758712769, -0.4902251958847046, -0.019474433735013008, -1.1013531684875488, 0.8612116165161448], + [0.3830683242096016, -0.7732952833175659, -1.1719526052474976, -0.4820272922515869, -0.02139158733189106, -1.094887137413025, 0.8539169219698891], + [0.37965216174232946, -0.7650784850120544, -1.089784860610962, -0.47440415620803833, -0.02327842265367508, -1.088446021080017, 0.8466900757753881], + [0.3764444491749428, -0.7574377655982971, -1.0133779048919678, -0.4673154652118683, -0.02513706311583519, -1.0820410251617432, 0.8395496933996105], + [0.37344948299404424, -0.7503328323364258, -0.9423280358314514, -0.4607238173484802, -0.026969488710165024, -1.0756795406341553, 0.8325099606152043], + [0.3706759594198795, -0.7437259554862976, -0.8762596249580383, -0.45459431409835815, -0.028777534142136574, -1.0693663358688354, 0.8255815419106031], + [0.36813675695663267, -0.7375823259353638, -0.8148233890533447, -0.4488946199417114, -0.030562909319996834, -1.0631040334701538, 0.818772311184273], + [0.36584789570646514, -0.7318694591522217, -0.7576946020126343, -0.44359442591667175, -0.03232720494270325, -1.056894302368164, 0.8120879340440293], + [0.3638268463778931, -0.7265571355819702, -0.7045711874961853, -0.4386659264564514, -0.0340718999505043, -1.0507375001907349, 0.8055323294502604], + [0.36208980635370175, -0.7216172218322754, -0.6551723480224609, -0.434082955121994, -0.035798367112874985, -1.0446338653564453, 0.7991080348309247], + [0.36064865374996596, -0.7170236706733704, -0.6092369556427002, -0.42982131242752075, -0.037507884204387665, -1.0385830402374268, 0.7928164947139084], + [0.35950769748704137, -0.7127522230148315, -0.5665221810340881, -0.42585843801498413, -0.03920163959264755, -1.0325844287872314, 0.7866582890856323], + [0.35866100585350397, -0.7087802290916443, -0.5268022418022156, -0.422173410654068, -0.04088073596358299, -1.0266374349594116, 0.7806333143686989], + [-0.18886394348797958, -0.6875587105751038, -0.3145873546600342, 0.6213363409042358, -0.0384095124900341, 0.1763417273759842, 0.7746891641094066], + [-0.19935445167851054, -0.6678251028060913, -0.11725125461816788, 0.639644205570221, -0.03586547449231148, 0.1635800153017044, 0.768857914097388], + [-0.19824261830173168, -0.64947509765625, 0.06624923646450043, 0.6566684246063232, -0.03325372561812401, 0.13446398079395294, 0.7629371203539954], + [-0.19419930983956415, -0.6324115991592407, 0.23688414692878723, 0.6724991202354431, -0.030579011887311935, 0.13123857975006104, 0.7569298493810652], + [-0.19074162332080974, -0.6165444254875183, 0.3955555260181427, 0.6872198581695557, -0.027845751494169235, 0.1318981796503067, 0.7509517971922638], + [-0.18991619771810794, -0.6017897725105286, 0.5431021451950073, 0.7009085416793823, -0.025058045983314514, 0.13255789875984192, 0.7449545261546827], + [-0.19112874694352874, -0.5880696177482605, 0.6803039908409119, 0.7136374115943909, -0.022219715639948845, 0.13322186470031738, 0.7388997712783383], + [-0.19318406444226807, -0.5753113627433777, 0.8078863620758057, 0.7254738807678223, -0.019334308803081512, 0.13389275968074799, 0.7327627342863612], + [-0.19546555689832368, -0.5634476542472839, 0.9265236854553223, 0.7364804148674011, -0.016405124217271805, 0.13457147777080536, 0.726534773886686], + [-0.19773301347682157, -0.552415668964386, 1.0368430614471436, 0.7467153668403625, -0.013435234315693378, 0.13525710999965668, 0.72022400558647], + [-0.30919366177723145, 0.27866479754447937, 0.9641480445861816, 1.5177505016326904, -0.013435234315693378, 0.138100728392601, 0.724840854185572], + [-0.30725900353129726, 0.27190497517585754, 0.8965498208999634, 1.511479139328003, -0.007423669099807739, 0.13650169968605042, 0.7293932460262814], + [-0.08521481290160546, 0.16584111750125885, 0.6584112048149109, 0.5665790438652039, -0.007423669099807739, -0.2075527459383011, 0.7349058161108437], + [-0.06783400791318979, 0.1436968892812729, 0.43696895241737366, 0.5290812253952026, -0.007423669099807739, -0.24158689379692078, 0.7405128616799562], + [-0.05825252475310051, 0.1231052428483963, 0.2310524582862854, 0.4942123293876648, -0.007423669099807739, -0.24736443161964417, 0.7461701549526497], + [-0.05012086249249722, 0.10395731776952744, 0.039573147892951965, 0.46178823709487915, -0.007423669099807739, -0.24928022921085358, 0.7518367441941683], + [-0.04321249616872257, 0.08615188300609589, -0.13848116993904114, 0.43163782358169556, -0.007423669099807739, -0.2463187426328659, 0.7574720838700055], + [-0.035995895467763134, 0.06959482282400131, -0.3040517568588257, 0.4036014974117279, -0.0059389350935816765, -0.24804891645908356, 0.7630477127348814], + [-0.02817185116153802, 0.05419861152768135, -0.4580138921737671, 0.37753087282180786, -0.0059389350935816765, -0.25364869832992554, 0.768545673778488], + [-0.017897620847901936, 0.03988185524940491, -0.6011814475059509, 0.3532879948616028, -0.0059389350935816765, -0.27212369441986084, 0.7739557730076617], + [-0.008261216107912184, 0.026568876579403877, -0.7343112230300903, 0.33074474334716797, -0.0059389350935816765, -0.2900128662586212, 0.7792738195520029], + [0.0007627783865820081, 0.014189294539391994, -0.8581070303916931, 0.3097819983959198, -0.0059389350935816765, -0.30705922842025757, 0.7844993819957966], + [0.1969936943180487, -0.2797943651676178, -0.7979435324668884, -0.18803030252456665, -0.00636813510209322, -0.5982919335365295, 0.7807180815256229], + [0.18958238737076302, -0.27419981360435486, -0.7419981956481934, -0.178556889295578, -0.006775710266083479, -0.5784175992012024, 0.777189561263008], + [0.1826990815770707, -0.26899752020835876, -0.6899752616882324, -0.16974766552448273, -0.007163177710026503, -0.5598204731941223, 0.7739044654886423], + [-0.5589129262720587, -0.24663199484348297, -0.4663200080394745, -0.13187535107135773, -0.007163177710026503, 2.397239923477173, 0.7714640447550488], + [-0.5584810415223166, -0.22583456337451935, -0.25834566354751587, -0.09665831178426743, -0.007163177710026503, 2.3529441356658936, 0.7699120400719075], + [-0.5565616659645832, -0.2064952701330185, -0.06495276838541031, -0.06391043961048126, -0.007163177710026503, 2.3037376403808594, 0.7692452258750052], + [-0.4865217168598598, -0.1885119080543518, 0.11488097161054611, -0.033458638936281204, -0.007163177710026503, 2.003431558609009, 0.7693473090415099], + [-0.4843897726047696, -0.17178937792778015, 0.2821062207221985, -0.0051418752409517765, -0.007163177710026503, 1.9883670806884766, 0.7700537236118319], + [-0.7708238487688981, -0.4062393009662628, 0.4376069903373718, -0.7280921936035156, -0.011410382576286793, 5.746318817138672, 0.7638278009790337], + [-0.7445005123731817, -0.39177948236465454, 0.5822052955627441, -0.7190147042274475, -0.015604634769260883, 5.697494029998779, 0.7576461193038383], + [-0.7287265403223198, -0.3783334493637085, 0.7166655659675598, -0.7105735540390015, -0.01974964700639248, 5.648215293884277, 0.7514720746944674], + [-0.7176819193766284, -0.3658301532268524, 0.8416985273361206, -0.7027242183685303, -0.023848872631788254, 5.598015308380127, 0.7452774336652609], + [-0.7087817643717371, -0.3542034924030304, 0.9579651951789856, -0.695425271987915, -0.027905520051717758, 5.546477317810059, 0.7390478495218085], + [-0.9199999685889073, 7.306608200073242, 1.0660802125930786, 4.113862037658691, -0.027905520051717758, 6.068759918212891, 0.7446808313863519], + [-0.9199999685889073, 7.316661357879639, 1.1666151285171509, 4.12017297744751, -0.027905520051717758, 6.111703872680664, 0.7501764234493237], + [-0.9199999685889073, 7.326010227203369, 1.2601011991500854, 4.126042366027832, -0.027905520051717758, 6.153583526611328, 0.7555379766814936], + [-0.9199999685889073, 7.33470344543457, 1.347032904624939, 4.131499290466309, -0.027905520051717758, 6.194431781768799, 0.7607687603226371], + [-0.9199999685889073, 7.34278678894043, 1.4278696775436401, 4.1365742683410645, -0.027905520051717758, 6.234278202056885, 0.765871963874974], + [-0.9199999685889073, 8.232775688171387, 1.327759027481079, 4.695289611816406, -0.027905520051717758, 6.273124694824219, 0.7708506990480516], + [-0.9199999685889073, 8.223466873168945, 1.2346673011779785, 4.689445495605469, -0.027905520051717758, 6.311017990112305, 0.775708001655932], + [0.22799154825718387, 8.197281837463379, 0.9728226065635681, 5.45698881149292, 0.0039269146509468555, -6.295364856719971, 0.780446833468498], + [0.23419523367937423, 8.172933578491211, 0.7293363809585571, 5.441702842712402, 0.03567017987370491, -6.334527492523193, 0.7850700840173425], + [0.24001124821910183, 8.15029239654541, 0.5029214024543762, 5.427489280700684, 0.06733053922653198, -6.373260974884033, 0.7895805723576782], + [0.24563307844267657, 8.12923812866211, 0.2923808693885803, 5.414271831512451, 0.09891378879547119, -6.412202835083008, 0.7939810487872736], + [0.2514091635182312, 8.109660148620605, 0.09660171717405319, 5.401981353759766, 0.1304253488779068, -6.452564239501953, 0.7982741965234642], + [0.26319184231767545, 8.09145450592041, -0.08545099198818207, 5.390552520751953, 0.16187024116516113, -6.51570463180542, 0.8020599373232822], + [0.265450510692521, 8.074525833129883, -0.2547396421432495, 5.379924774169922, 0.19325312972068787, -6.544726848602295, 0.8054052405018639], + [0.26603509872581854, 8.058784484863281, -0.41215911507606506, 5.37004280090332, 0.2245783805847168, -6.568309783935547, 0.808214631238123], + [0.2648741592145022, 8.044145584106445, -0.5585416555404663, 5.36085319519043, 0.25585001707077026, -6.586142539978027, 0.8103390489042367], + [0.26166994194463644, 8.030533790588379, -0.694661021232605, 5.3523077964782715, 0.2870718240737915, -6.5970916748046875, 0.8116433931864653], + [0.9199999685889073, -8.164595603942871, -0.6459569931030273, -4.814634799957275, 0.2870718240737915, -7.096859455108643, 0.8135545394151179], + [0.9199999685889073, -8.160066604614258, -0.6006677150726318, -4.81179141998291, 0.2870718240737915, -7.112162113189697, 0.8154190723211203], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [0.38513324930148474, -0.0759519413113594, 0.05048057436943054, -1.7808427810668945, -0.00020776498422492296, -0.34127020835876465, 0.9991124139302132], + [0.40075537473288914, -0.0712578147649765, 0.09742186218500137, -1.6257919073104858, -0.00039744071546010673, -0.33461055159568787, 0.9982771386678583], + [0.4201164532492807, -0.06689280271530151, 0.14107200503349304, -1.483040452003479, -0.0005704620853066444, -0.32935744524002075, 0.9974910563680077], + [0.3902653702713881, -0.06283382326364517, 0.18166175484657288, -1.3503772020339966, -0.0007280061254277825, -0.3258514404296875, 0.9967511103297959], + [0.3556846194505165, -0.05905943363904953, 0.21940568089485168, -1.2258175611495972, -0.0008710181573405862, -0.32368361949920654, 0.996054354716816], + [0.3229036446280457, -0.05554967001080513, 0.2545033097267151, -1.1077765226364136, -0.0010002587223425508, -0.3215988874435425, 0.9953979847183112], + [0.29161282059042204, -0.05228598415851593, 0.2871401607990265, -0.995150089263916, -0.001116359606385231, -0.31956741213798523, 0.9947793526160259], + [-0.43281167838121426, 0.01770082116127014, 0.2670082151889801, 1.7472336292266846, -0.001116359606385231, -0.29091861844062805, 0.9947870032699171], + [-0.40825407552453624, 0.015828775241971016, 0.24828776717185974, 1.658023476600647, -0.0009229235001839697, -0.29179736971855164, 0.9947971654884007], + [-0.38586022378762674, 0.014087983407080173, 0.23087982833385468, 1.5766654014587402, -0.0007389792008325458, -0.29259806871414185, 0.9948095529007845] + ] + } + }, + "corrections": { + "2746116c4f1040ff28312cd481ed59a43ace3fc1": "Unwind freezes the integrator when steering magnitude decreases in either direction." + } +} diff --git a/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_replay.json b/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_replay.json new file mode 100644 index 0000000000..c8479aa328 --- /dev/null +++ b/openpilot/starpilot/flm/tests/testdata/ioniq6_controller_replay.json @@ -0,0 +1,139 @@ +{ + "sourceCommit": "678af783", + "controllerSha256": "3561d5ac43a72f9b68bc9e44042b8f5cbdca406dec940e7648c64607862a60f7", + "helperSha256": "2a7793c6ee4b53b45070d3267a01e8c7105dfd8df9d38cdfc96cfe4b672a125b", + "fields": ["output", "desiredLateralAccel", "desiredLateralJerk", "p", "i", "f", "directionalFilter"], + "cases": { + "2023_default": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10946385067439653, -6.3100724219111726e-06, -6.310072058113292e-05, 0.1341981738805771, 1.8787743556458736e-06, 0.00032710772939026356, 0.9996100118902765], + [-0.10883246512145582, -1.2177733879070729e-05, -0.00012177733879070729, 0.1318926364183426, 3.725271199073177e-06, 0.00031992016010917723, 0.9992295059317203], + [-0.10824537411387734, -1.7634001778787933e-05, -0.00017634002142585814, 0.12974874675273895, 5.541753580473596e-06, 0.00031323812436312437, 0.9988582529369309], + [-0.10769947128273318, -2.2707719836034812e-05, -0.00022707720927428454, 0.12775516510009766, 7.330325843213359e-06, 0.00030702617368660867, 0.9984960291624968], + [-0.28297200469611916, -0.000652122835163027, -0.006521228235214949, 1.1880364418029785, 0.00014593458035960793, -0.2816479206085205, 0.9981391809934517], + [-0.2756437166861801, -0.0012374084908515215, -0.012374084442853928, 1.1618024110794067, 0.0002814781910274178, -0.28237107396125793, 0.9977880370052482], + [-0.26883225664052884, -0.0017816586187109351, -0.017816586419939995, 1.1374077796936035, 0.0004141757672186941, -0.2830390930175781, 0.9974426531218326], + [-0.26250143520346325, -0.0022877503652125597, -0.02287750318646431, 1.1147234439849854, 0.0005442268447950482, -0.2836558222770691, 0.9971030722974821], + [0.4601949453186658, -0.1805993765592575, 0.1540062576532364, -1.188317060470581, -0.0012640818022191525, -0.49601319432258606, 0.992499586928128], + [0.4465996195441572, -0.1641511619091034, 0.31848835945129395, -1.14291250705719, -0.0012640818022191525, -0.4924542307853699, 0.9884772861214742], + [0.43407732863292336, -0.14885616302490234, 0.47143831849098206, -1.100691318511963, -0.0012640818022191525, -0.4894025921821594, 0.9849106631692192], + [0.41633289657380795, -0.13463354110717773, 0.6136646270751953, -1.0614302158355713, -0.0012640818022191525, -0.46395212411880493, 0.9817055989940047], + [0.39730472578123277, -0.12140807509422302, 0.7459192276000977, -1.0249220132827759, -0.0012640818022191525, -0.4308745861053467, 0.9788075568573854], + [0.4297113013265992, -0.6421098709106445, 0.8689011931419373, -1.042867660522461, -0.0012640818022191525, -0.7659497857093811, 0.9666235589852955], + [0.4248670128656576, -0.6306739449501038, 0.9832606315612793, -1.0322579145431519, -0.0012640818022191525, -0.7597172856330872, 0.954489222066301], + [0.42049364468176326, -0.6200397610664368, 1.0896021127700806, -1.0223921537399292, -0.0012640818022191525, -0.7535170316696167, 0.9424195214508498], + [0.4164368811483507, -0.6101512312889099, 1.1884877681732178, -1.0132180452346802, -0.0012640818022191525, -0.7473620176315308, 0.9304395954054268], + [0.3199540924834166, -0.06795595586299896, 1.2804404497146606, -0.8773695230484009, -0.0012640818022191525, -0.29505154490470886, 0.9299817995128876], + [0.060078582417879084, 0.1974666267633438, 1.1906663179397583, -0.14468130469322205, -0.0012640818022191525, -0.07431123405694962, 0.9303986060329053], + [0.07382922238852245, 0.1891186386346817, 1.1071864366531372, -0.1677255779504776, -0.0012665000976994634, -0.10168427973985672, 0.9308865510565729], + [0.08651897274157169, 0.18135595321655273, 1.0295594930648804, -0.18915419280529022, -0.0015543433837592602, -0.1265009641647339, 0.9314381973895504], + [0.09815910618563091, 0.17413750290870667, 0.9573751091957092, -0.20908039808273315, -0.0018725092522799969, -0.14894376695156097, 0.9320461536047748], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.2513814549455434, -0.003141704946756363, -0.004417050164192915, 1.0764470100402832, 0.00012558548769447953, -0.28566011786460876, 0.9995935936517069], + [-0.24625808545922598, -0.0035524412523955107, -0.008524413220584393, 1.0580368041992188, 0.0002490231127012521, -0.28612491488456726, 0.999194945848787], + [-0.2414972946123882, -0.003934380132704973, -0.012343800626695156, 1.0409173965454102, 0.0003704634727910161, -0.28655150532722473, 0.9988040108797638], + [-0.31353200913731205, 0.00156875466927886, -0.02031245268881321, 1.2875816822052002, 0.0005206813220866024, -0.2697177231311798, 0.9987354006918017] + ], + "2023_tuned": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10946365319690253, -6.3100724219111726e-06, -6.310072058113292e-05, 0.1341981738805771, 1.8787743556458736e-06, 0.00032638496486470103, 0.9996100118902765], + [-0.10883226781007806, -1.2177733879070729e-05, -0.00012177733879070729, 0.1318926364183426, 3.725271199073177e-06, 0.0003191980067640543, 0.9992295059317203], + [-0.10824517696030346, -1.7634001778787933e-05, -0.00017634002142585814, 0.12974874675273895, 5.541753580473596e-06, 0.00031251655309461057, 0.9988582529369309], + [-0.10769927427915203, -2.2707719836034812e-05, -0.00022707720927428454, 0.12775516510009766, 7.330325843213359e-06, 0.00030630515539087355, 0.9984960291624968], + [-0.28233191056000917, -0.000652122835163027, -0.006521228235214949, 1.1880364418029785, 0.00014593458035960793, -0.28399068117141724, 0.9981391809934517], + [-0.2749949064500627, -0.0012374084908515215, -0.012374084442853928, 1.1618024110794067, 0.0002814781910274178, -0.2847457230091095, 0.9977880370052482], + [-0.26817517909605, -0.0017816586187109351, -0.017816586419939995, 1.1374077796936035, 0.0004141757672186941, -0.2854440212249756, 0.9974426531218326], + [-0.26183652822545644, -0.0022877503652125597, -0.02287750318646431, 1.1147234439849854, 0.0005442268447950482, -0.28608939051628113, 0.9971030722974821], + [0.4595698571302159, -0.1805993765592575, 0.1540062576532364, -1.188317060470581, -0.0012640818022191525, -0.49372363090515137, 0.992499586928128], + [0.44595244427846414, -0.1641511619091034, 0.31848835945129395, -1.14291250705719, -0.0012640818022191525, -0.4900825619697571, 0.9884772861214742], + [0.43341988321633484, -0.14885616302490234, 0.47143831849098206, -1.100691318511963, -0.0012640818022191525, -0.48699232935905457, 0.9849106631692192], + [0.4146338623062182, -0.13463354110717773, 0.6136646270751953, -1.0614302158355713, -0.0012640818022191525, -0.4577219784259796, 0.9817055989940047], + [0.39571172853313513, -0.12140807509422302, 0.7459192276000977, -1.0249220132827759, -0.0012640818022191525, -0.42503249645233154, 0.9788075568573854], + [0.4297113005126837, -0.6421098709106445, 0.8689011931419373, -1.042867660522461, -0.0012640818022191525, -0.7659497857093811, 0.9666235589852955], + [0.4248670116005044, -0.6306739449501038, 0.9832606315612793, -1.0322579145431519, -0.0012640818022191525, -0.7597172856330872, 0.954489222066301], + [0.4204936427763009, -0.6200397610664368, 1.0896021127700806, -1.0223921537399292, -0.0012640818022191525, -0.7535170316696167, 0.9424195214508498], + [0.4164368783622407, -0.6101512312889099, 1.1884877681732178, -1.0132180452346802, -0.0012640818022191525, -0.7473620176315308, 0.9304395954054268], + [0.3188361342080046, -0.06795595586299896, 1.2804404497146606, -0.8773695230484009, -0.0012640818022191525, -0.2909505367279053, 0.9299817995128876], + [0.07886541128383386, 0.1974666267633438, 1.1906663179397583, -0.14468130469322205, -0.0012640818022191525, -0.14318642020225525, 0.9303986060329053], + [0.09212774529529907, 0.1891186386346817, 1.1071864366531372, -0.1677255779504776, -0.0012665000976994634, -0.16877123713493347, 0.9308865510565729], + [0.10426233987400049, 0.18135595321655273, 1.0295594930648804, -0.18915419280529022, -0.0015543433837592602, -0.1915545016527176, 0.9314381973895504], + [0.11528450629035937, 0.17413750290870667, 0.9573751091957092, -0.20908039808273315, -0.0018725092522799969, -0.2117334008216858, 0.9320461536047748], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.2507020459817548, -0.003141704946756363, -0.004417050164192915, 1.0764470100402832, 0.00012558548769447953, -0.2881467640399933, 0.9995935936517069], + [-0.24557222240998797, -0.0035524412523955107, -0.008524413220584393, 1.0580368041992188, 0.0002490231127012521, -0.2886351943016052, 0.999194945848787], + [-0.24080535398236808, -0.003934380132704973, -0.012343800626695156, 1.0409173965454102, 0.0003704634727910161, -0.2890840172767639, 0.9988040108797638], + [-0.31192240501086027, 0.00156875466927886, -0.02031245268881321, 1.2875816822052002, 0.0005206813220866024, -0.2756088972091675, 0.9987354006918017] + ], + "2025_default": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.1000419596173212, -6.3100724219111726e-06, -6.310072058113292e-05, 0.09995962679386139, 1.399434836457658e-06, 0.00010129198199138045, 0.9996100118902765], + [-0.09957267603318784, -1.2177733879070729e-05, -0.00012177733879070729, 0.09824388474225998, 2.774849235720467e-06, 9.798955579753965e-05, 0.9992295059317203], + [-0.09913630335274988, -1.7634001778787933e-05, -0.00017634002142585814, 0.09664839506149292, 4.127926786168246e-06, 9.492012031842023e-05, 0.9988582529369309], + [-0.0987305336073542, -2.2707719836034812e-05, -0.00022707720927428454, 0.0951647162437439, 5.460232841869583e-06, 9.206731920130551e-05, 0.9984960291624968], + [-0.20914663037612374, -0.000652122835163027, -0.006521228235214949, 0.9331316947937012, 0.00011432559404056519, -0.29679471254348755, 0.9981391809934517], + [-0.20378671594561765, -0.0012374084908515215, -0.012374084442853928, 0.913754940032959, 0.0002209303347626701, -0.2971450090408325, 0.9977880370052482], + [-0.19880095039411716, -0.0017816586187109351, -0.017816586419939995, 0.895721435546875, 0.00032543117413297296, -0.29746678471565247, 0.9974426531218326], + [-0.19416335817561867, -0.0022877503652125597, -0.02287750318646431, 0.8789377212524414, 0.00042797389323823154, -0.2977619171142578, 0.9971030722974821], + [0.4392321660999833, -0.1805993765592575, 0.1540062576532364, -1.1881484985351562, -0.0013800781453028321, -0.4364989101886749, 0.992499586928128], + [0.4258132064536378, -0.1641511619091034, 0.31848835945129395, -1.1428061723709106, -0.0013800781453028321, -0.4333744943141937, 0.9884772861214742], + [0.4134643642642225, -0.14885616302490234, 0.47143831849098206, -1.100642204284668, -0.0013800781453028321, -0.43070998787879944, 0.9849106631692192], + [0.4020555760971033, -0.13463354110717773, 0.6136646270751953, -1.0614110231399536, -0.0013800781453028321, -0.42824599146842957, 0.9817055989940047], + [0.3848995656490656, -0.12140807509422302, 0.7459192276000977, -1.0249145030975342, -0.0013800781453028321, -0.4015149474143982, 0.9788075568573854], + [0.4109087335446737, -0.6421098709106445, 0.8689011931419373, -1.042867660522461, -0.0013800781453028321, -0.7119354009628296, 0.9666235589852955], + [0.40548124993066065, -0.6306739449501038, 0.9832606315612793, -1.0322579145431519, -0.0013800781453028321, -0.705704391002655, 0.954489222066301], + [0.40050714696593104, -0.6200397610664368, 1.0896021127700806, -1.0223921537399292, -0.0013800781453028321, -0.6995058655738831, 0.9424195214508498], + [0.39584261470068033, -0.6101512312889099, 1.1884877681732178, -1.0132180452346802, -0.0013800781453028321, -0.6933526992797852, 0.9304395954054268], + [0.3149811146942059, -0.06795595586299896, 1.2804404497146606, -0.8773694038391113, -0.0013800781453028321, -0.29052385687828064, 0.9299817995128876], + [0.07278191701495691, 0.1974666267633438, 1.1906663179397583, -0.14468127489089966, -0.0013800781453028321, -0.12354271858930588, 0.9303986060329053], + [0.08476103001121033, 0.1891186386346817, 1.1071864366531372, -0.16772553324699402, -0.0013592970790341496, -0.1449497640132904, 0.9308865510565729], + [0.09583379534180414, 0.18135595321655273, 1.0295594930648804, -0.18915407359600067, -0.0016471401322633028, -0.16431504487991333, 0.9314381973895504], + [0.10599475260681573, 0.17413750290870667, 0.9573751091957092, -0.20908012986183167, -0.001965305535122752, -0.18178008496761322, 0.9320461536047748], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.18455691150215894, -0.003141704946756363, -0.004417050164192915, 0.8457168340682983, 9.866696200333536e-05, -0.2993770241737366, 0.9995935936517069], + [-0.1807869478147606, -0.0035524412523955107, -0.008524413220584393, 0.8320255279541016, 0.00019573660392779857, -0.2995831072330475, 0.999194945848787], + [-0.1772817750930907, -0.003934380132704973, -0.012343800626695156, 0.8192852139472961, 0.00029131988412700593, -0.2997693419456482, 0.9988040108797638], + [-0.23438617884934018, 0.00156875466927886, -0.02031245268881321, 1.0144683122634888, 0.00040967451059259474, -0.2860351800918579, 0.9987354006918017] + ], + "2025_tuned": [ + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.10004176588515235, -6.3100724219111726e-06, -6.310072058113292e-05, 0.09995962679386139, 1.399434836457658e-06, 0.00010058288171421736, 0.9996100118902765], + [-0.0995724824028674, -1.2177733879070729e-05, -0.00012177733879070729, 0.09824388474225998, 2.774849235720467e-06, 9.72808338701725e-05, 0.9992295059317203], + [-0.09913610982047417, -1.7634001778787933e-05, -0.00017634002142585814, 0.09664839506149292, 4.127926786168246e-06, 9.421175491297618e-05, 0.9988582529369309], + [-0.09873034016950431, -2.2707719836034812e-05, -0.00022707720927428454, 0.0951647162437439, 5.460232841869583e-06, 9.135930304182693e-05, 0.9984960291624968], + [-0.20850737366620653, -0.000652122835163027, -0.006521228235214949, 0.9331316947937012, 0.00011432559404056519, -0.299134761095047, 0.9981391809934517], + [-0.20313872630464402, -0.0012374084908515215, -0.012374084442853928, 0.913754940032959, 0.0002209303347626701, -0.29951703548431396, 0.9977880370052482], + [-0.1981446778400448, -0.0017816586187109351, -0.017816586419939995, 0.895721435546875, 0.00032543117413297296, -0.2998691201210022, 0.9974426531218326], + [-0.1934992417196338, -0.0022877503652125597, -0.02287750318646431, 0.8789377212524414, 0.00042797389323823154, -0.3001929819583893, 0.9971030722974821], + [0.4385985958463555, -0.1805993765592575, 0.1540062576532364, -1.1881484985351562, -0.0013800781453028321, -0.4341534674167633, 0.992499586928128], + [0.42515705373587437, -0.1641511619091034, 0.31848835945129395, -1.1428061723709106, -0.0013800781453028321, -0.4309435486793518, 0.9884772861214742], + [0.41279772620131083, -0.14885616302490234, 0.47143831849098206, -1.100642204284668, -0.0013800781453028321, -0.42823871970176697, 0.9849106631692192], + [0.4005006910087692, -0.13463354110717773, 0.6136646270751953, -1.0614110231399536, -0.0013800781453028321, -0.42247965931892395, 0.9817055989940047], + [0.3834282557554281, -0.12140807509422302, 0.7459192276000977, -1.0249145030975342, -0.0013800781453028321, -0.39605703949928284, 0.9788075568573854], + [0.41090873272070005, -0.6421098709106445, 0.8689011931419373, -1.042867660522461, -0.0013800781453028321, -0.7119354009628296, 0.9666235589852955], + [0.4054812486515245, -0.6306739449501038, 0.9832606315612793, -1.0322579145431519, -0.0013800781453028321, -0.705704391002655, 0.954489222066301], + [0.40050714504196294, -0.6200397610664368, 1.0896021127700806, -1.0223921537399292, -0.0013800781453028321, -0.6995058655738831, 0.9424195214508498], + [0.3958426118913092, -0.6101512312889099, 1.1884877681732178, -1.0132180452346802, -0.0013800781453028321, -0.6933526396751404, 0.9304395954054268], + [0.31389254542210765, -0.06795595586299896, 1.2804404497146606, -0.8773694038391113, -0.0013800781453028321, -0.28648287057876587, 0.9299817995128876], + [0.09121441906277902, 0.1974666267633438, 1.1906663179397583, -0.14468127489089966, -0.0013800781453028321, -0.19182172417640686, 0.9303986060329053], + [0.10272071436991616, 0.1891186386346817, 1.1071864366531372, -0.16772553324699402, -0.0013592970790341496, -0.21148933470249176, 0.9308865510565729], + [0.11325653863995695, 0.18135595321655273, 1.0295594930648804, -0.18915407359600067, -0.0016471401322633028, -0.2288757711648941, 0.9314381973895504], + [0.1228192862316972, 0.17413750290870667, 0.9573751091957092, -0.20908012986183167, -0.001965305535122752, -0.24413321912288666, 0.9320461536047748], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], + [-0.1838782763203542, -0.003141704946756363, -0.004417050164192915, 0.8457168340682983, 9.866696200333536e-05, -0.3018612265586853, 0.9995935936517069], + [-0.18010184692892778, -0.0035524412523955107, -0.008524413220584393, 0.8320255279541016, 0.00019573660392779857, -0.30209097266197205, 0.999194945848787], + [-0.176590585847015, -0.003934380132704973, -0.012343800626695156, 0.8192852139472961, 0.00029131988412700593, -0.30229949951171875, 0.9988040108797638], + [-0.23277761972196384, 0.00156875466927886, -0.02031245268881321, 1.0144683122634888, 0.00040967451059259474, -0.2919234335422516, 0.9987354006918017] + ] + }, + "corrections": { + "2746116c4f1040ff28312cd481ed59a43ace3fc1": "Unwind freezes the integrator when steering magnitude decreases in either direction." + } +}