补齐 Autocal 实时反馈与稳定窗口复核
显示实时力值、曲线及 UV 图层,并保存人工确认窗口和零载检查基准。定向测试、真实视频预览与已录会话复核闭环验证通过。
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"""Live operator feedback must preserve sample validity and UV orientation."""
|
||||
|
||||
from dataclasses import replace
|
||||
|
||||
import numpy as np
|
||||
from orisys_app_shared.acquisition.models import SdkPacket
|
||||
|
||||
|
||||
class Worker:
|
||||
is_running = True
|
||||
|
||||
def __init__(self):
|
||||
self.sinks = []
|
||||
|
||||
def add_sink(self, sink):
|
||||
self.sinks.append(sink)
|
||||
|
||||
def remove_sink(self, sink):
|
||||
self.sinks.remove(sink)
|
||||
|
||||
|
||||
def packet(**values):
|
||||
image = np.full((64, 80, 3), (10, 20, 30), dtype=np.uint8)
|
||||
base = SdkPacket(raw_frame=image.copy(), processed_frame=image,
|
||||
timestamp=100, mono_t=1, fps=30, process_ms=1,
|
||||
session_id=1, frame_id=1, normal_force_raw=12,
|
||||
shear_x_raw=2, shear_y_raw=-3)
|
||||
return replace(base, **values)
|
||||
|
||||
|
||||
def test_force_feedback_consumes_every_sample_and_breaks_invalid_gaps(qt_app):
|
||||
from orisys_autocal.ui.live_force_view import LiveForceView
|
||||
worker = Worker()
|
||||
view = LiveForceView(worker)
|
||||
for item in (packet(), packet(frame_id=2, mono_t=1.1, stale_forces=True),
|
||||
packet(frame_id=3, mono_t=1.2, normal_force_raw=20)):
|
||||
worker.sinks[0](item)
|
||||
view.refresh()
|
||||
assert view.history.sample_count == 3
|
||||
x, y = view.curves[0].getData()
|
||||
np.testing.assert_allclose(x, [0, .1, .2])
|
||||
assert y[0] == 12 and np.isnan(y[1]) and y[2] == 20
|
||||
assert "20 raw" in view.readings.text()
|
||||
assert "20.000 N" not in view.readings.text()
|
||||
view.on_packet(packet(session_id=2, normal_force=4, force_calibrated=True,
|
||||
calibrated_axes=("fn",)))
|
||||
view.refresh()
|
||||
assert view.history.sample_count == 1
|
||||
assert "4.000 N" in view.readings.text()
|
||||
assert "2.000 N" not in view.readings.text()
|
||||
worker.is_running = False
|
||||
view.refresh()
|
||||
assert view.state.text()
|
||||
view.shutdown()
|
||||
assert not worker.sinks
|
||||
|
||||
|
||||
def test_display_toggles_redraw_same_frame_without_mutating_measurements(qt_app, monkeypatch):
|
||||
from orisys_autocal.ui import finger_source_panel
|
||||
panel = finger_source_panel.FingerSourcePanel()
|
||||
item = packet(flow=np.full((64, 80, 2), 2., dtype=float),
|
||||
depth=np.full((64, 80), .5), valid_mask=np.ones((64, 80), bool),
|
||||
flow_valid=True, flow_frame_id=1, depth_valid=True, depth_frame_id=1)
|
||||
original = item.processed_frame.copy()
|
||||
panel._last_packet = item
|
||||
frames = []
|
||||
monkeypatch.setattr(panel, "_show_frame", lambda frame: frames.append(frame.copy()))
|
||||
panel._redraw()
|
||||
np.testing.assert_array_equal(frames[-1], original)
|
||||
panel.background_check.setChecked(False)
|
||||
assert not np.array_equal(frames[-1], original)
|
||||
solid = frames[-1]
|
||||
panel.depth_check.setChecked(True)
|
||||
assert not np.array_equal(frames[-1], solid)
|
||||
depth = frames[-1]
|
||||
panel.arrows_check.setChecked(True)
|
||||
assert not np.array_equal(frames[-1], depth)
|
||||
assert frames[-1].shape == original.shape
|
||||
np.testing.assert_array_equal(item.processed_frame, original)
|
||||
assert np.all(item.flow == 2)
|
||||
panel._last_packet = replace(item, flow_valid=False, depth_frame_id=0)
|
||||
panel._redraw()
|
||||
assert panel.display_note.text()
|
||||
np.testing.assert_array_equal(frames[-1], solid)
|
||||
panel.shutdown()
|
||||
Reference in New Issue
Block a user