31750f0f84
支持显式无载荷置零、处理线程内切换模型及完整标定包快照。shared、界面检查与兼容测试通过;Studio 全量仍有一项回放停止时序测试失败。
101 lines
6.8 KiB
Markdown
101 lines
6.8 KiB
Markdown
# Sensor bundles
|
|
|
|
Every sensor configuration the Studio offers is a folder under `apps/studio/config/sensors/`
|
|
holding `sensor.json` — the processing configuration. `orisys_app_shared.sensors.bundle_catalog`
|
|
scans that folder and the writable user root beside it, and resolves each candidate through the
|
|
SDK's `orisys.sensors.resolve_bundle`, so the picker shows what the SDK decided rather than a
|
|
second opinion computed in the UI.
|
|
|
|
`finger/` also carries `manifest.json`, the bundle descriptor. A descriptor states the profile's
|
|
identity and its files instead of leaving both to be inferred, which is what lets the bundle keep
|
|
its meaning when the folder is moved or renamed.
|
|
|
|
## Picker rows
|
|
|
|
A configuration row in the sensor dialog is **the bundle's name and nothing else**: the
|
|
descriptor's `display_name` when there is one, otherwise the folder name (`box`, `mini`, `finger`,
|
|
`finger-mems`, and whatever the operator called their own folder). Everything else — the origin,
|
|
the resolved root, the `profile_id`, the bundle shape, the SDK's verdict with what it means, the
|
|
calibration selection and every finding — is written in the details surface directly under the
|
|
selector, where the sentences fit.
|
|
|
|
One exception: two entries offered together that would otherwise read alike each get a suffix.
|
|
Across roots that is the origin (`Box (shipped)` beside `Box (user)`); when one root supplies both
|
|
(for example one `display_name` declared by two folders) the origin cannot separate them and the
|
|
folder is used instead. Nothing is collapsed or shadowed, and the same tree always produces the
|
|
same rows.
|
|
|
|
## The finger descriptor
|
|
|
|
| Field | Value | Why |
|
|
|---|---|---|
|
|
| `schema_version` | `1` | The SDK's current descriptor schema (`CURRENT_DESCRIPTOR_SCHEMA`). |
|
|
| `profile_id` | `orisys.finger.r01` | The processing profile this folder is: finger design revision `r01`, whose unroll map and camera scale the configuration pins. Never a product-family name. |
|
|
| `display_name` | `Finger` | Shown in the picker. Excluded from the processing fingerprint. |
|
|
| `product_family` | `finger` | What the operator calls it. `finger-mems` is a different family on a different pipeline. |
|
|
| `processing_backend` | `uv_unroll` | The pipeline the finger actually runs: `FingerRuntime` builds a UV domain from the export's unroll map, then flow and force. |
|
|
| `sensor_json` | `sensor.json` | The configuration, still the only place camera, tracker and contact settings live. |
|
|
| `computational_assets.unroll_map` | `assets/30fps-0703/unroll_map_uv_s0.42.npz` | The map the chain loads. `finger_worker` derives that name for itself from the export folder and `camera.source_scale`, so the descriptor and the chain are checked against each other. Required: without it the profile fails. |
|
|
| `assets.scene` | `scene/finger-display-1.0.0.oryscene` | The compiled package the 3D pane draws. Visualization only: a missing one never blocks processing. |
|
|
|
|
Every path is relative to the bundle root, and the SDK refuses an absolute path or a `..` escape
|
|
when it parses the descriptor. `assets/visualization/` is deliberately left out of `assets`: it is
|
|
offline compiler input, the packaged build strips it, and nothing at runtime reads it.
|
|
|
|
`sensor.json` declares `"type": "single_camera"` while the descriptor says `uv_unroll`. With a
|
|
descriptor present the descriptor decides, and it is the truthful one — the finger path never
|
|
builds a single-camera processor. Do not "correct" `type`: it is part of the hashed configuration
|
|
(only `name`, `version` and `display_name` are skipped), so editing it would re-identify every
|
|
recorded finger pass and change no number.
|
|
|
|
## Compatibility keys
|
|
|
|
`name`, `assets_dir` and `viz_pose` are kept beside the descriptor fields — the shape this bundle
|
|
had before it carried a descriptor. They are relative too, so they do not weaken rename safety,
|
|
and they keep readers that never learned about the descriptor working:
|
|
|
|
| Key | Reader |
|
|
|---|---|
|
|
| `assets_dir` | `orisys/configs.resolve_sensor_bundle` → `resolve_sensor_asset_dir`, which `orisys.finger.exports` consults for a bundled export; `acquisition/geometry.py::describe_sensor_geometry`, the device-geometry check the 3D pane runs; `build/studio/build.ps1`, which checks the packaged copy; `orisys-sdk/examples/gui/viewer3d/presets.py`. |
|
|
| `viz_pose` | `orisys-sdk/examples/viz/mesh_camera.py`. |
|
|
| `name` | Nothing reads it today; it is kept because it belongs to the legacy shape. |
|
|
|
|
Dropping a key means migrating those readers first, not tidying up the JSON.
|
|
|
|
## Verification
|
|
|
|
### Multi-point force calibration
|
|
|
|
Finger sessions accept SDK schema 3 files through the existing calibration-file picker and
|
|
operator-confirmed SN. The SDK checks processing settings, geometry and coordinate-map identity;
|
|
a mismatch blocks loading rather than falling back to raw values. Keep the JSON and its declared
|
|
NPZ artifacts together. The file format and supported models are defined in the
|
|
[SDK calibration contract](../../../../orisys-sdk/docs/calibration-model-contract.zh.md).
|
|
|
|
After starting, remove all load and select **Unloaded zero**. Confirm that the next 30 processed
|
|
frames are unloaded. Contact, invalid readings or tracker reset cancel an unfinished measurement.
|
|
Zero values belong to this session; tracker reset and model replacement require a new zero.
|
|
Model replacement is applied between frames on the SDK HHD thread. The rail reports per-axis
|
|
zero, contact, coverage and range states; an unavailable newton value stays unavailable while raw
|
|
measurements remain accessible. Selecting a tracker reference alone never implies zero load.
|
|
|
|
For bare-video recomputation, explicitly confirm the unloaded 30-frame interval starting at the
|
|
selected reference frame. This choice changes the analysis cache identity; a short or invalid
|
|
interval fails the pass. Leave the option unchecked for legacy calibration or when no unloaded
|
|
interval has been verified.
|
|
|
|
Recording format 1.5 appends `calibration_status` and `calibration_reference` JSON columns to
|
|
`forces.csv`; existing columns keep their positions. Raw validity and per-axis model validity
|
|
are distinct. Recordings store each schema 3 JSON with its artifacts in a directory identified by
|
|
the SDK model fingerprint, so recorded calibration remains loadable without the original folder.
|
|
Older recordings remain readable and carry no invented zero or model-state information.
|
|
|
|
`apps/studio/tests/test_sensor_catalog_root.py` asserts the descriptor's fields, that every
|
|
declared path is relative and present, that the declared map is the one the running chain derives
|
|
for itself (the SDK's `scaled_map_cache_path`, so `_s0.42.npz` and never a neighbouring
|
|
`_s0.4.npz`), and that a copy of the bundle under another folder name keeps its `profile_id`, its
|
|
processing fingerprint and all of its resolved paths inside the copy.
|
|
|
|
The descriptor grammar itself is owned by the SDK:
|
|
[orisys-sdk/docs/sensor-bundles.md](../../../../orisys-sdk/docs/sensor-bundles.md).
|