c78f7a304f
按实际运行上下文核对其余处理参数,保留文件指纹与设备身份校验。115 项标定及运行时检查通过。
135 lines
5.1 KiB
Python
135 lines
5.1 KiB
Python
"""Feature identities use effective measurement settings, never display metadata."""
|
|
|
|
from copy import deepcopy
|
|
import json
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
from orisys.calibration_context import build_context, domain_fingerprint
|
|
|
|
|
|
def config():
|
|
return {"camera": {"resolution_raw": [1280, 720], "resolution_stitch": [700, 750]},
|
|
"tracker": {"dis_mode": 4}}
|
|
|
|
|
|
@pytest.mark.parametrize("raw,expected", [(None, 1), ("bad", 1), (0, 1), (-3, 1), ("3", 3), (3.7, 3)])
|
|
def test_hhd_uses_actual_sensor_normalization(raw, expected):
|
|
data = config()
|
|
data["tracker"]["hhd_downsample"] = raw
|
|
assert build_context(data)["hhd_downsample"] == expected
|
|
|
|
|
|
def test_default_values_equal_explicit_effective_settings():
|
|
implicit = build_context(config())
|
|
data = config()
|
|
data["tracker"]["hhd_downsample"] = 1
|
|
explicit = build_context(data, {"flow_ema_alpha": 1.0})
|
|
assert implicit["hhd_downsample"] == 1
|
|
assert implicit["filters"]["measurement"] == {"flow_ema_alpha": 1.0}
|
|
assert implicit["feature_signature_sha256"] == explicit["feature_signature_sha256"]
|
|
|
|
|
|
def test_measurement_filters_change_identity_but_readout_and_paths_do_not():
|
|
data = config()
|
|
original = build_context(data)
|
|
assert build_context(data, {"flow_ema_alpha": 0.5})["feature_signature_sha256"] != original["feature_signature_sha256"]
|
|
data.update(name="other", video="D:/other.mp4", cal_path="E:/calibration.json")
|
|
assert build_context(data, {"force_median_window": 7, "force_lowpass_cutoff_hz": 2}) == original
|
|
|
|
|
|
def test_explicit_empty_filter_mapping_overrides_config_defaults():
|
|
data = config()
|
|
data["filters"] = {"flow_ema_alpha": 0.5}
|
|
assert build_context(data, {})["filters"]["measurement"] == {"flow_ema_alpha": 1.0}
|
|
|
|
|
|
def test_source_scale_numeric_types_have_identical_identity():
|
|
assert build_context(config(), source_scale=1) == build_context(config(), source_scale=1.0)
|
|
|
|
|
|
def test_domain_fingerprint_binds_map_content_not_only_dimensions():
|
|
domain = {"map_x": np.zeros((2, 3)), "map_y": np.zeros((2, 3)),
|
|
"valid_mask": np.ones((2, 3), dtype=bool), "world_xyz": np.zeros((2, 3, 3))}
|
|
original = domain_fingerprint(domain)
|
|
for key in domain:
|
|
changed = deepcopy(domain)
|
|
changed[key].flat[0] = not changed[key].flat[0] if key == "valid_mask" else 1
|
|
assert domain_fingerprint(changed) != original
|
|
assert domain_fingerprint({key: value.copy() for key, value in domain.items()}) == original
|
|
|
|
|
|
def _model(data):
|
|
from orisys.calibration import parse
|
|
|
|
return parse({
|
|
"schema_version": 3, "unit": "N",
|
|
"identity": {"sensor_type": "box", "sn": "A1"},
|
|
"pipeline": build_context(data),
|
|
"model": {
|
|
"type": "global_gain/1", "input_profile": "force_delta/1",
|
|
"output_frame": "sdk_force/1", "outputs": ["fn"],
|
|
"params": {"gains_N_per_raw": {"fn": .001}, "valid_force_range_N": [0, 3]},
|
|
},
|
|
})
|
|
|
|
|
|
@pytest.mark.parametrize("downsample", [1, 2, 4])
|
|
def test_downsample_only_difference_accepts_existing_model_without_rewriting_it(downsample):
|
|
from orisys.calibration import validate_for_device
|
|
|
|
data = config()
|
|
data["tracker"]["hhd_downsample"] = 3
|
|
model = _model(data)
|
|
original = model.to_dict()
|
|
fingerprint = model.fingerprint
|
|
data["tracker"]["hhd_downsample"] = downsample
|
|
actual = build_context(data)
|
|
assert json.loads(json.dumps(actual)) == actual
|
|
assert actual["feature_signature_sha256"] != model.pipeline["feature_signature_sha256"]
|
|
validate_for_device(model, "box", "A1", pipeline=actual)
|
|
model.validate_for_context(actual)
|
|
assert model.to_dict() == original
|
|
assert model.fingerprint == fingerprint
|
|
assert actual["hhd_downsample"] == downsample
|
|
|
|
|
|
def test_runtime_context_binds_a_different_downsample_model_and_predicts():
|
|
from orisys.force_readout import ForceReadout
|
|
from orisys.sensor import Sensor
|
|
|
|
data = config()
|
|
data["tracker"]["hhd_downsample"] = 3
|
|
sensor = Sensor.__new__(Sensor)
|
|
sensor._config = data
|
|
sensor.calibration = _model(data)
|
|
sensor._force_raw = (100.0, 0.0, 0.0)
|
|
sensor._force_readout = ForceReadout({})
|
|
sensor._model_readouts = {}
|
|
sensor._reset_calibration_session()
|
|
data["tracker"]["hhd_downsample"] = 2
|
|
sensor.bind_calibration_context(build_context(data))
|
|
sensor.set_calibration_reference({"fn": 100.0}, reference_id="unloaded")
|
|
result = sensor.apply_calibration_frame(
|
|
frame_id=1, timestamp_s=0.1, raw=(120.0, 0.0, 0.0), contact_found=True,
|
|
)
|
|
assert result.values_N["fn"] == pytest.approx(.02)
|
|
|
|
|
|
@pytest.mark.parametrize("section,key,value", [
|
|
("camera", "resolution_raw", [640, 480]),
|
|
("tracker", "dis_mode", 1),
|
|
("tracker", "flow_iterations", 99),
|
|
("contact", "threshold", .9),
|
|
("filters", "flow_ema_alpha", .5),
|
|
])
|
|
def test_downsample_tolerance_does_not_hide_other_pipeline_changes(section, key, value):
|
|
data = config()
|
|
data["tracker"]["hhd_downsample"] = 3
|
|
model = _model(data)
|
|
data["tracker"]["hhd_downsample"] = 2
|
|
data.setdefault(section, {})[key] = value
|
|
with pytest.raises(ValueError, match="pipeline mismatch"):
|
|
model.validate_for_context(build_context(data))
|