把同帧测量、空载归零、模型推断与共用后处理收进一个 SDK 会话,Studio 显示与记录使用同一样本;旧 Sensor 读数接口保持兼容。以 force session 与受影响 SDK 套件、lint 与文档门禁验证,硬件与真实载荷精度未验证。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CpCfJF6SvonMKmPZhzKZHb
5.9 KiB
力读数工作流(ForceSession)
用途:SDK 显式力读数会话(studio-force/1)的公共接口参考。状态:已实现并接入 Studio,2026-10-20;
硬件、真实相机与真实载荷精度未验证。需求与验收矩阵见
流程规格,实施状态见
重写计划。
测量、标定模型、空载基线与输出后处理全部由本会话拥有;调用方只提供源帧与帧身份,
发送归零/换模型请求,并分发返回的 ForceOutput。这样同一帧只测量、推断、后处理各一次,
显示与记录拿到同一个不可变输出。
入口与版本
from orisys import ForceSession, WORKFLOW_VERSION
WORKFLOW_VERSION = "studio-force/1" 是处理顺序与语义的稳定身份,随每个输出返回,
记录、缓存键与诊断引用它;改变顺序或语义时必须提升该版本。
构造显式启用测量源(Sensor 或 FingerRuntime)的会话接缝:
session = ForceSession(
source=runtime, # 已打开、由调用方负责 close
sensor_family="finger", # box | mini | finger | finger-mems
device_id="FINGER-001", # 可选,用于标定身份校验
context=context, # schema 3 模型需要的实际管线身份
calibration=model, # Calibration(schema 1/2)、ModelCalibration(schema 3)或 None
settings=output_settings, # 可选;默认 OutputSettings(sample_rate_hz=30.0)
)
构造失败不会留下“半切换”的会话;旧 Sensor.read_info / ForceReadout.apply 路径在
未构造 ForceSession 时保持原语义,本模块不与旧路径并行运行。
主要方法与属性
| 成员 | 说明 |
|---|---|
process_frame(source_frame, stamp) -> ForceOutput |
唯一逐帧入口:测量 → 归零状态 → 标定 → 后处理。同一 (session_id, frame_id) 重复调用返回同一缓存对象且不推进状态;乱序帧显式失败并清除完成标志 |
read_sdk_frame(source_frame, stamp) -> SdkReading |
只做同帧测量(图像准备、光流/HHD、可选接触/场),不推断、不读数滤波 |
request_zero(*, reference_id, declared_unloaded, replay_window=None) -> ZeroProgress |
启动唯一空载归零操作;declared_unloaded 必须为空载确认;拒绝带载相对置零 |
update_zero(reading) -> ZeroProgress |
推进归零状态机并执行本帧一次模型推断;迟到代次的结果被忽略 |
invalidate(*, reason) -> ZeroProgress |
断流、取消、换模型或测量配置变化时作废基线/完成状态与滤波历史 |
apply_calibration(reading, zero) -> CalibratedReading |
不复用旧结果、不重复推断,给出未做读数滤波的 raw/N 与逐轴状态 |
apply_filter(measurement) -> ForceOutput |
唯一后处理:raw 与 N 各自独立地 median → low-pass → 可关闭逐轴阈值 |
set_calibration(calibration, *, context=None) |
帧边界原子换模型;校验失败保留原模型、基线与完成状态 |
zero、calibration_fingerprint、output_settings、last_output |
只读状态/身份;output_settings 是实际生效参数 |
帧身份
FrameStamp(session_id, frame_id, source_frame_id, signal_time_s, time_basis);后处理低通的
采样率来自信号时间,不取离线处理耗时。实时与顺序录像只替换源适配器,其余流程相同。
归零(空载基线)
request_zero(declared_unloaded=True, reference_id=...)只登记请求并递增参考代次;- 处理线程在下一个帧边界重置 tracker,然后才测量该帧;
- 采集重置后连续 30 个有效处理帧,按模型类型得到基线:标量模型取 raw 中位数,
场模型委托
ModelCalibration用同一增益图加权后的 30 帧中位数; - 第 30 帧仍为基线帧;第 31 帧起
phase="ready"、completed=True并输出 N,effective_from_frame_id指向该帧。
基线未完成、无效帧、窗口不足或已取消时 N 为 NaN、状态显式;窗口不足不越界补帧。
录像重算用 replay_window=(start, end) 在声明区间执行同一操作。
后处理与有效设置
OutputSettings(sample_rate_hz, median_window=1, lowpass_hz=0.0, lowpass_order=2, raw_threshold=0.0, newton_threshold=0.0)。每阶段由自身值关闭(median=1、lowpass=0、
threshold=0),全关时对有效值严格直通(NaN 保留);无效轴不进入滤波历史。
ForceOutput.settings 返回实际生效的参数(例如截止频率达到 Nyquist 时解析为 off)。
离线重滤波
from orisys.force_readout import process_output_sequence
raw_out, newton_out, effective = process_output_sequence(
settings, raw_samples, newton_samples,
raw_valid=None, newton_valid=None, signal_times_s=times,
)
该函数只重放输出级(带完整 warm-up),用于从已存未滤波序列生成新参数下的最终输出; 不重新测量、不打开模型链。
状态与诊断
逐轴状态:ok、out_of_range、zero_unavailable、no_contact、coordinate_unmapped、
outside_coverage、invalid_input、uncalibrated、measurement_failed、frame_order、
signal_time_order。仅 ok/out_of_range 携带可用牛顿值;模型不输出的轴(例如 FN-only
模型的 FX/FY)恒为 NaN + uncalibrated。缺失值与有效零分开。
CalibratedReading.diagnostics 提供 reference_id、baseline_N、baseline_raw_fn/fx/fy、
model_fingerprint、mapping、extrapolated_fraction、coverage_fraction、area_scale、
pending_reference_frames 等;调用方存储或展示,不据此改写逐轴有效性。
场模型质量(外推、覆盖)与 downsample 差异属于诊断,不替代有效性判断;
hhd_downsample 不同是唯一允许的管线身份差异,其余差异仍拒绝并报告。