补充 Finger 模型切换与逐帧接触状态
按实际几何和处理参数校验切换模型,并保留帧内接触状态。88 项相关测试通过。
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -386,6 +387,31 @@ class FingerRuntime:
|
||||
"""Set an explicitly measured unloaded reference for this finger stream."""
|
||||
self.tactile.raw_sensor.set_calibration_reference(raw, reference_id=reference_id)
|
||||
|
||||
def set_calibration(self, calibration, *, device_id=None):
|
||||
"""Replace the model at a caller-owned frame boundary, validating actual geometry."""
|
||||
from .. import calibration as cal_mod
|
||||
from ..calibration_context import build_context, domain_fingerprint, sha256_file
|
||||
|
||||
sensor = self.tactile.raw_sensor
|
||||
selected = cal_mod.load(calibration, strict=True) if isinstance(calibration, (str, Path)) else calibration
|
||||
serial = device_id or sensor.device_id
|
||||
if selected is not None and serial:
|
||||
selected = cal_mod.validate_for_device(selected, "finger", serial)
|
||||
context = None
|
||||
if getattr(selected, "schema_version", None) == 3:
|
||||
if selected.input_profile == "fn_delta_autocal_uv/1":
|
||||
uv_map = selected.coordinate_map
|
||||
if uv_map is None or uv_map.shape[:2] != (self.geometry.out_height, self.geometry.out_width):
|
||||
raise ValueError("calibration coordinate map does not match finger output shape")
|
||||
context = build_context(
|
||||
self.geometry.config, sensor.filters_state(),
|
||||
geometry_sha256=sha256_file(self.geometry.export_paths.mesh),
|
||||
source_scale=self.geometry.source_scale, coordinates=selected.pipeline.get("coordinates"),
|
||||
output_domain_sha256=domain_fingerprint(self.domain), processing_backend="uv_unroll",
|
||||
preprocessing={"flip_source_vertical": self.frame_processor.flip_source_vertical,
|
||||
"mirror": sensor.mirror})
|
||||
sensor.set_calibration(selected, context=context)
|
||||
|
||||
@property
|
||||
def calibration_status(self):
|
||||
"""Copy the current per-axis calibration validity state."""
|
||||
|
||||
@@ -156,6 +156,7 @@ class FrameSnapshot:
|
||||
source_metadata: Any = None
|
||||
force_units: tuple[str, str, str] | None = None
|
||||
calibration_status: dict[str, str] | None = None
|
||||
contact_found: bool | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -658,6 +659,7 @@ class StreamPipeline:
|
||||
torque=float(getattr(sensor, "ftor", 0.0)),
|
||||
force_units=tuple(getattr(sensor, "force_units", (getattr(sensor, "force_unit", "raw"),) * 3)),
|
||||
calibration_status=dict(getattr(sensor, "calibration_status", {})),
|
||||
contact_found=bool(getattr(sensor, "centroid_found", False)),
|
||||
# Both already private per-frame copies owned by this snapshot.
|
||||
image=frame if "image" in include else None,
|
||||
flow=flow if "flow" in include else None,
|
||||
|
||||
Reference in New Issue
Block a user