从 repeat/capture 读取帧、力和采集来源,使诊断符合现有录制目录。既有诊断检查和多点目录案例通过,该案例在 HEAD 原实现中失败。
orisys-app
Desktop applications that consume the Orisys SDK.
| App | Status | Qt binding |
|---|---|---|
apps/studio |
The customer-facing shell (theme / locale / prefs / logging, acquisition, 3D) | PySide6 |
apps/autocal |
Internal 5-axis calibration platform control | PySide6 |
apps/internal |
Stub, superseded by apps/autocal |
— |
Both shipped apps are PySide6 — Qt's LGPLv3 binding. PyQt5's free option is
GPLv3-or-commercial, which is why the studio was migrated off it: a closed-source
product would otherwise need a licence purchase. The rule is enforced, not just
documented: neither app may import PyQt5/PyQt6/PySide2, and shared/ (used by both) may
import PySide6 and nothing else. See apps/studio/tests/test_studio_binding_purity.py and
apps/autocal/tests/test_binding_purity.py.
One practical consequence: pyqtgraph binds to whichever toolkit it imports first, so a
development environment that still has PyQt5 installed can build plots from the wrong
binding. orisys_studio.main sets PYQTGRAPH_QT_LIB=PySide6 before anything imports it,
and the purity test asserts that importing the app pulls in no other binding.
Layout
shared/— common paths, prefs, theme, i18n, logging, and the ZMotion clientshared/resources/zmotion/— vendored ZMotion runtime DLLs (internal use only)apps/studio/config/— locales, default prefs, editablesensors/copiesapps/studio/outputs/— generated logs and calibration exports (gitignored)apps/autocal/— internal platform control; seeapps/autocal/README.mdbuild/— Windows PyInstaller packaging (build/studio/build.ps1)
Selecting which app's paths resolve
orisys_app_shared.paths reads ORISYS_APP_ID (an apps/ directory name) to
decide which product's config/, preference.json and outputs/ a process
owns. Each app's launcher sets it before importing the shared package; when it
is unset the studio is assumed, which keeps existing callers working unchanged.
A named app whose config/ is missing raises rather than silently resolving
another product's tree.
Run (studio shell)
cd D:\repo\orisys-app
python -m pip install -e .\shared -e .\apps\studio
python .\apps\studio\run.py
Or without install:
$env:PYTHONPATH = "D:\repo\orisys-app\shared\src;D:\repo\orisys-app\apps\studio\src"
python D:\repo\orisys-app\apps\studio\run.py
Local orisys SDK
orisys_app_shared.force imports orisys.calibration at module scope, so the
studio app cannot start against an SDK build that predates that module
(the published 0.5.2 wheel does not include it). When working from a repo
checkout, install the SDK from source instead of from an index:
python -m pip install .\..\orisys-sdk # same checkout that built this app
If a pip build is blocked by the environment, the equivalent manual install is
to copy orisys-sdk/src/orisys/**/*.py over site-packages/orisys/ and delete
the stale __init__.cp310-win_amd64.pyd (an extension module shadows the
package __init__.py, which hides sibling modules such as calibration.py).
Verifying UI changes
Both tools render the real main window with the offscreen Qt platform — no display, camera or sensor hardware required:
python .\apps\studio\tools\ui_check.py # layout/theme assertions
python .\apps\studio\tools\ui_snapshot.py --theme light --demo `
--sensor finger --panels cal,3d --size 1600x900 --out shot.png
ui_check.py needs only the runtime dependencies. The pytest suite in
shared/tests and apps/studio/tests covers the same ground plus locale and
preference-schema parity:
pip install pytest
python -m pytest
On Windows the offscreen platform finds no fonts unless QT_QPA_FONTDIR points
at C:\Windows\Fonts; both tools set it automatically.
ui_check.py also runs the palette rules (WCAG contrast, colour separation,
ramp monotonicity) that guard the brand tokens; see
apps/studio/docs/ui-palette.md for the
colour system, its relationship to the UI design spec, and every deliberate
deviation from it.
Layout follows apps/studio/docs/ui-layout.md:
which controller owns the arrangement, the fixed effect set every view change
must apply, each view's pane priority and degradation order, when a numeric
geometry argument is legitimate, and which of these rules are not yet
mechanically enforced.
ui_check.py includes a record channel section as well; see
apps/studio/docs/record-channel.md for
why recording and calibration sampling no longer hang off the UI refresh timer,
and for the data-reliability fixes that came with it.
The merge gate
One command runs everything a change must not break, and it is the only check that is meant to be unskippable:
powershell -NoProfile -ExecutionPolicy Bypass -File tools\gate.ps1
It runs tools/lint_gate.py over the changed files, the full studio suite, the full
shared suite, and ui_check.py; writes each one's output to
.scratch/gate/gate-<run-id>/; and holds the run to three contracts — an empty
tools/known_failures.txt, the skip ceilings and collection floors in
tools/skip_budget.txt, and zero findings anywhere. It exits 0 only when all of
that holds.
The gate platform is Windows: the suites render real Qt widgets offscreen, and two
checks are platform-sensitive (docs/test-repair-plan.zh.md
§3 #11 and #13), so a green Linux run is not the same statement.
An optional pre-push hook calls it, so a failing gate blocks the push. It is
deliberately not installed for you:
git config core.hooksPath .githooks # enable; `git config --unset core.hooksPath` disables
Day-to-day development still uses targeted test runs
(docs/test-execution-plan.zh.md); the gate is what
runs before a change is committed or handed over.
Branding
Window / EXE icon: shared/resources/branding/logo.png
Top bar / About: shared/resources/branding/logo_topbar.png
Dark mode is the default. Logos currently sit on a black tile; a transparent (or light) variant may be needed for polished light mode later.
Versioning
- Studio app version (
orisys_studio.__version__) — shown in Help → About and used for releases. - Shared package version (
orisys_app_shared.__version__) — internal library version. - Shared API (
orisys_app_shared.API_VERSION) — compatibility tag. Studio declaresREQUIRES_SHARED_API; startup logs a warning on mismatch.
Deferred
Run/Stop pipeline, arrow/force plots, units, calibration capture, Open3D finger mesh, sync-from-wheel for config/sensors, PyInstaller packaging, and the internal app.