feat: ForceStreamSession 使用固定设计帧率的输出滤波(T07)
新增 FixedRateOutputFilter:设计帧率在会话创建时固定,实测帧率漂移和长间隔只报告、不重新设计也不清历史;request_output_settings 可跨线程排队,在力线程帧边界切换,只重建滤波链、清空历史,不改零点和参考版本,并发出 output_filter_changed StreamEvent(设置、指纹、生效帧、预热)。结果行带滤波设置身份与预热状态。已发布 ForceReadout 和旧 ForceSession/ForceOutputFilter 默认行为不变;设计帧率下与旧会话逐位一致。回归 391 项、lint 通过。
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 新力侧会话(T06a/T06b)
|
||||
# 新力侧会话(T06a/T06b、T07 输出滤波)
|
||||
|
||||
本文件是单路 SensorStream 计划 T06a/T06b 的 SDK 合同:新的力侧会话直接消费 T05 的
|
||||
本文件是单路 SensorStream 计划 T06a/T06b/T07 的 SDK 合同:新的力侧会话直接消费 T05 的
|
||||
`ImageMeasurement`(T03 `MeasurementFrame` 头 + 同帧 raw/field),参考版本取帧上的
|
||||
`reference_generation`。旧 `ForceSession` 仍为 App 保留到 T09/T10 迁移,本会话不提供
|
||||
`process_measurement`、`request_zero_external_reset`、`tracker_reset_seq` 等旧外部复位接口。
|
||||
@@ -40,14 +40,39 @@
|
||||
迟到、无效和带质量标记的结果不会被丢弃;拒绝帧仍保留 raw 特征。
|
||||
- **数值等价与滤波。** 零点/标定换算/读数滤波复用已发布算法;同一输入、无复位、同一标定时
|
||||
与旧 `ForceSession` 逐帧相等(T06a 覆盖标量曲线、无标定、median+lowpass 滤波器;T06b 覆盖
|
||||
`context` 与同帧 field)和 FN-only 全局增益模型(`outputs=["fn"]`);`settings` 为
|
||||
固定设计帧率与显式滤波切换属于 T07,不在本会话实现。
|
||||
field 模型与 FN-only 全局增益模型,三类标定都在同一平台同一次运行中对照旧会话)。
|
||||
- **三类标定与不匹配。** 标量曲线、field、FN-only 各有有效测试;无标定会话保持 raw 与
|
||||
`uncalibrated` 状态;field 模型缺 `context` 时构造报 `CalibrationError`,基线帧缺 field 或
|
||||
模型拒绝帧时零点失败并给出 `invalid_input`/原因;FN-only 的 FX/FY 永远保持 NaN +
|
||||
`uncalibrated`,不冒充三轴标定。
|
||||
- **输出滤波(T07)。** 设计帧率在构造时固定(`design_sample_rate_hz`),实测帧率漂移和长
|
||||
间隔只作为 `measured_sample_rate_hz`/`sample_rate_irregular` 诊断,不重新设计链路、不清空
|
||||
历史。`request_output_settings(settings)` 可从任意线程发出,只在力线程下一帧边界生效:只
|
||||
重建滤波链并清空其历史,图像参考与已完成的零点不变;相同设置是空操作。每次实际切换发出
|
||||
一个 `output_filter_changed` StreamEvent(规范化设置、指纹、算法版本、生效帧、设计帧率、
|
||||
预热信息,可 JSON 往返),由 `drain_events()` 取出。预热帧数为
|
||||
`max(1, median_window) + 2×lowpass_order(低通开启时)`;结果行提供当前设置身份与预热计数。
|
||||
全阶段关闭时输出与输入完全相同(含 NaN 与带符号的零)。已发布 `ForceOutputFilter`/旧会话
|
||||
的自适应调频默认行为不变。
|
||||
- **线程与只读。** 一个实例只属于一个力侧线程;输入数组只读,输出只含标量/状态/不可变进度。
|
||||
|
||||
## 输出滤波示例
|
||||
|
||||
```python
|
||||
from orisys.force_readout import OutputSettings
|
||||
from orisys.force_stream_session import ForceStreamSession
|
||||
|
||||
session = ForceStreamSession(
|
||||
sensor_family="box",
|
||||
settings=OutputSettings(sample_rate_hz=30.0, median_window=3, lowpass_hz=5.0),
|
||||
design_sample_rate_hz=30.0,
|
||||
)
|
||||
new_settings = OutputSettings(sample_rate_hz=30.0, median_window=5, lowpass_hz=10.0)
|
||||
session.request_output_settings(new_settings)
|
||||
assert session.output_settings.median_window == 3, "switch waits for a frame boundary"
|
||||
assert session.design_sample_rate_hz == 30.0
|
||||
```
|
||||
|
||||
## 示例
|
||||
|
||||
```python
|
||||
@@ -72,8 +97,9 @@ assert row.zero.phase in ("resetting", "collecting")
|
||||
|
||||
## 后续
|
||||
|
||||
T06b 已交付标量/field/FN-only 三类标定与旧 ForceSession 的完整数值等价;spatial_gain/接触
|
||||
映射模型不在 T06b 验收范围,需要时另立任务。
|
||||
T07 才改变输出滤波的帧率与切换语义;T09/T10 迁移 App 后删除旧 `ForceSession`。
|
||||
T06b 已交付标量/field/FN-only 三类标定与旧 ForceSession 的完整数值等价;T07 已交付固定
|
||||
设计帧率、显式切换事件与历史/直通合同。spatial_gain/接触映射模型不在 T06/T07 验收范围,
|
||||
需要时另立任务。
|
||||
T08 接单路流入口;T09/T10 迁移 App 后删除旧 `ForceSession`。
|
||||
另一项后续任务:删除旧 `ForceSession` 之前,先把零点、标定、读数引擎从旧类中抽出来,
|
||||
避免新会话依赖待删除的类型(T06b 或 T09 之前)。
|
||||
避免新会话依赖待删除的类型(T09 之前)。
|
||||
|
||||
Reference in New Issue
Block a user