Files
orisys-app/apps/studio/config/locales/zh_CN.json
T
ykcheungab 92da51217c add session browsing, calibration diagnostics and the 2D layout preset
Phase 2 of the review: browse the whole session instead of only the rolling
window, diagnose a calibration from the recorded points, and provide the
reviewed two-panel layout.

What
- SessionStore gains extent(), visible(t0, t1, max_points) and
  statistics(t0, t1, unit). visible() walks only the blocks that overlap the
  window and decimates by taking each bucket's minimum and maximum, so a spike
  survives decimation and browsing a long session does not copy all of it.
- ForcePlotsPanel gains follow/browse modes, a whole-session overview strip
  with the current window, pan and wheel zoom, a rubber-band zoom toggle,
  a shared time cursor across all three channels, and a selection readout
  (duration, valid samples, per-axis peak/mean/std).
- CalibrationPoint records a bounded per-axis trace, an excluded flag, a
  validation flag and its fit residual. CalibrationRecorder gains
  set_excluded/set_validation/fit; the fit is a least-squares line over the
  non-excluded, non-validation points with per-point residuals and an
  independent validation error.
- The calibration table becomes the reviewed diagnostic view
  (reference load | FN | FX | FY | stability | state) with the residual shown
  next to the loaded axis, plus exclude/restore and mark-validation actions and
  a fit summary line. Double clicking a row opens the point's three-axis trace.
- Add a layout preset: free layout or 2D mode (depth map on the left, force
  charts on the right, calibration folded away), persisted in preferences.

Why
- Browsing is a display pause, not a capture pause: the record channel keeps
  running while the charts show an older window.
- Excluding a point removes it from the fit and from the exported calibration
  but keeps it on record, so the evidence for the decision is not destroyed.
- The non-loaded axes are recorded but never given a reference load: their true
  load is unknown during a single-axis calibration, so it stays empty.

Verification
- shared/tests/test_record_channel.py grows to 18 cases, covering extent,
  peak-preserving decimation, windowed reads, inverted/empty windows, unit-aware
  statistics and the time origin.
- tools/ui_check.py gains "session browsing" and "layout preset" sections
  (223 checks, 0 failures overall).
- apps/studio/tests/test_ui_smoke.py covers the same invariants.

Not in this change: synchronised playback of video, depth and curves. It needs
a decision on how depth is stored for replay (per-frame PNG, reduced-rate PNG,
or offline recomputation); the cursor plumbing (cursor_moved / set_cursor) is
already in place for it.
2026-09-13 13:34:26 +08:00

234 lines
9.9 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"app": {
"title": "Orisys Studio",
"about_title": "关于",
"about_body": "Orisys Studio 桌面应用\n版本: {app_version}",
"scaffold_hint": "脚手架界面 — 采集功能稍后加入"
},
"brand": {
"name": "ORISYS",
"tagline": "叠动科技"
},
"menu": {
"file": "文件",
"open_video": "打开视频…",
"reveal_config": "在资源管理器中显示配置…",
"view": "视图",
"theme": "主题",
"theme_dark": "深色",
"theme_light": "浅色",
"language": "语言",
"lang_zh": "简体中文",
"lang_en": "English",
"calibration_panel": "标定面板",
"finger_3d": "手指 3D 视图",
"show_fps": "显示 FPS",
"plot_settings": "绘图设置…",
"rotate_arrows": "旋转箭头图 90°",
"run": "运行 / 停止",
"stop": "取消采集",
"preview": "预览 / 停止预览",
"reset": "重置追踪器",
"help": "帮助",
"about": "关于"
},
"dialog": {
"plot_settings_title": "绘图设置",
"plot_window": "时间窗口",
"plot_window_tip": "力曲线时间窗口(秒)",
"plot_fn_max": "FN 上限",
"plot_fn_max_tip": "法向力纵轴上限(牛顿模式)",
"plot_shear_max": "剪切上限",
"plot_shear_max_tip": "剪切力 FX/FY 纵轴 ±上限(牛顿模式)",
"plot_fn_raw_max": "FN 原始上限",
"plot_fn_raw_max_tip": "未标定(原始)模式下的法向力纵轴上限。0 = 按数据自动量程;默认值按实测峰值设定,使静止时的抖动在图中不可见",
"plot_shear_raw_max": "原始剪切上限",
"plot_shear_raw_max_tip": "未标定(原始)模式下的剪切力 FX/FY 纵轴 ±上限。0 = 自动量程",
"reset_defaults": "恢复默认",
"ok": "确定",
"cancel": "取消"
},
"toolbar": {
"source": "来源",
"source_camera": "摄像机",
"source_video": "视频文件",
"search_cameras": "搜索",
"cam_id": "摄像机",
"browse_video": "浏览…",
"video_placeholder": "未选择视频",
"preview": "预览",
"preview_stop": "停止预览",
"run": "运行",
"stop": "停止",
"run_label": "▶ 运行",
"stop_label": "■ 停止",
"cancel_label": "■ 取消连接",
"cancel_tip": "中断连接(连接卡住时随时可用,快捷键 Esc)",
"run_unavailable": "当前不可运行",
"run_disabled_video": "请先选择一个视频文件",
"run_disabled_sensor": "此传感器类型暂不支持运行",
"reset": "重置",
"units": "单位",
"units_newton": "牛顿",
"units_raw": "原始"
},
"units": {
"newton_short": "N",
"raw_short": "raw"
},
"sensor": {
"type": "产品",
"config": "配置",
"thumb_placeholder": "产品型号"
},
"panels": {
"arrow": "形变箭头",
"view_arrows_pure": "箭头",
"view_arrows_stitched": "箭头/采集图像",
"view_depth": "深度图",
"view_mode_tip": "运行时的图像显示模式",
"arrow_empty": "尚未采集图像\n请选择视频或摄像机后点击「运行」",
"arrow_empty_tip": "运行或预览后在此显示形变箭头图",
"depth_unavailable": "本帧没有深度数据\n(不是深度为零,也未回退显示普通形变图)",
"depth_scale": "深度色标 {low} – {high}",
"depth_scale_tip": "本会话固定色标:色标范围锁定在首个有效深度帧,便于跨帧比较;灰色区域表示无深度数据",
"plots": "力曲线图",
"cal": "标定",
"mesh3d": "三维网格",
"mesh3d_empty": "手指三维视图占位 —\nOpen3D 网格稍后加入",
"mesh3d_empty_tip": "手指传感器的三维网格预览"
},
"chart": {
"fn": "FN",
"fx": "FX",
"fy": "FY",
"no_data": "—",
"mode_follow": "跟随实时",
"mode_browse": "浏览历史(显示暂停,采集与记录继续)",
"return_latest": "返回最新",
"return_latest_tip": "退出历史浏览,恢复跟随最新数据",
"overview": "全程总览",
"overview_tip": "把整个会话缩放到一屏;拖动下方总览条可移动视窗",
"box_zoom": "框选",
"box_zoom_tip": "切换为框选放大(拖动图表框选区域)",
"selection": "选区 {duration}s / {samples} 点 — {detail}",
"selection_empty": "选区无有效样本",
"browse_only_tip": "拖动或滚轮即可进入历史浏览"
},
"layout": {
"default": "自由布局",
"preset_2d_name": "二维模式(深度图 + 曲线)",
"preset_2d": "已切换到二维模式:左侧深度图、右侧三轴曲线,共用时间轴",
"preset_default": "已恢复自由布局"
},
"record": { "label": "记录",
"mode_video_data": "视频 + 数据",
"mode_data_only": "仅数据",
"mode_tip": "视频记录的是处理前的相机输入图像(不含箭头与文字叠加)。MP4 是有损封装,不等于无损原始数据。",
"start_label": "● 开始记录",
"stop_label": "■ 停止记录",
"start_tip": "开始记录本实验:视频、力数据与元数据写入同一目录",
"stop_tip": "停止记录并写入 session.json(随时可用)",
"requires_run": "请先点击「运行」开始采集,再开始记录",
"started": "已开始记录({mode})",
"start_failed": "无法开始记录: {error}",
"finished": "记录完成 — {frames} 帧 / {segments} 段,已写入 {path}",
"finished_with_problems": "记录完成,但存在问题: {detail}",
"alarm": "记录异常: {detail}"
},
"cal": {
"weight": "砝码重量 (N)",
"duration": "采集时长",
"record": "记录",
"recording_stop": "停止",
"record_disabled": "请先点击「运行」开始采集,再记录标定样本",
"record_cancelled": "已取消本次采集",
"empty_hint": "当前通道尚无样本:运行后选择通道并点击「记录」。",
"delete_row": "删除行",
"clear_channel": "清空通道",
"clear_all": "全部清空",
"export": "导出…",
"sn": "序列号",
"sn_placeholder": "序列号(可选)",
"live_raw_label": "实时原始值",
"live_raw": "实时原始值 FN={fn} FX={fx} FY={fy}",
"col_weight": "参考载荷",
"col_fn": "FN 均值",
"col_fx": "FX 均值",
"col_fy": "FY 均值",
"col_stability": "稳定性",
"col_state": "状态",
"col_raw": "原始均值",
"col_n": "n",
"col_std": "σ",
"state_ok": "正常",
"state_excluded": "已排除",
"state_validation": "验证点",
"state_exclude": "排除",
"state_exclude_tip": "把选中点排除出拟合与导出(记录保留,可恢复)",
"state_restore": "恢复",
"mark_validation": "设为验证点",
"mark_validation_tip": "把选中点留作独立验证点:不参与拟合,用于检验拟合",
"excluded": "该点已排除出拟合",
"restored": "该点已恢复",
"marked_validation": "该点已标记为验证点",
"unmarked_validation": "该点已取消验证点标记",
"fit_insufficient": "拟合需要至少 2 个有效点(当前 {count} 个)",
"fit_summary": "拟合 {channel}: N = {gain} × raw + {offset}({count} 点,最大残差 {residual} N)",
"fit_validation": "独立验证 {count} 点,最大偏差 {error} N",
"point_title": "标定点 {channel} @ {load} N",
"point_channel": "加载轴",
"point_direction": "方向",
"point_round": "轮次",
"point_duration": "实际采样时长",
"point_duration_value": "{actual} s(请求 {requested} s)",
"point_samples": "样本数",
"point_samples_value": "有效 {valid} / 共 {total}",
"point_axes": "三轴均值 ± 标准差",
"point_residual": "拟合残差",
"col_actions": "",
"recording": "正在采集标定样本…",
"recording_stop_tip": "点击可取消本次标定采集(随时可用)",
"record_ok": "已记录 weight={weight} raw={raw}",
"record_failed_few": "采集失败 — 样本过少",
"export_ok": "已导出 {path}",
"export_local": "同时写入 {path}",
"export_warnings": "跳过: {detail}",
"export_failed": "导出失败: {error}",
"apply_title": "应用标定",
"apply_confirm": "将刚导出的标定应用到当前设备?\n\n设备类型: {sensor_type}\n配置: {config}\n\n选择「否」只保留导出文件,不改动运行中的设备。",
"apply_skipped": "已导出,未应用到设备",
"apply_done": "标定已应用到 {sensor_type}",
"apply_no_target": "没有可应用的设备(请先运行一次采集)"
},
"status": {
"ready": "就绪",
"phase_idle": "空闲",
"phase_connecting": "连接中",
"phase_running": "运行中",
"phase_error": "出错",
"camera_none": "未发现摄像机",
"camera_found": "发现 {count} 个摄像机: {names}",
"preview_started": "预览已启动(摄像机 {camera_id})",
"preview_stopped": "预览已停止",
"preview_failed": "预览失败: {error}",
"connecting": "正在连接…",
"connect_slow": "连接耗时较长,可点击「取消连接」或按 Esc 中断",
"run_started": "运行中({source})",
"run_stopped": "已停止",
"run_stopping": "正在停止…(正在释放设备)",
"run_stopping_cancelled": "已取消连接(正在释放设备)",
"sample_invalid": "采样无效(第 {count} 次):{reason} — 该样本已标记无效,未计入曲线与标定",
"samples_dropped": "记录缓冲已达上限,最早的 {count} 个样本已被释放(全程记录不再完整)",
"run_failed": "启动失败: {error}",
"video_ended": "视频已结束",
"camera_disconnected": "摄像机已断开",
"reset_ok": "追踪器已重置",
"finger_run_unavailable": "此传感器类型暂不支持运行",
"video_required": "请先选择视频文件",
"config_missing": "未找到传感器配置: {type}",
"units_raw_fallback": "无标定数据 — 显示原始单位",
"reveal_failed": "无法打开配置位置: {error}"
}
}