fix path errors
This commit is contained in:
@@ -7,7 +7,7 @@ ORY-BOX:单传感器基础流程
|
||||
3. 按需计算接触区域
|
||||
4. 读取并可视化结果
|
||||
|
||||
SDK version: 0.4.3
|
||||
SDK version: 0.4.4
|
||||
"""
|
||||
import os
|
||||
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"video_source": "D:/repo/orisys-sdk/data/dd02-0703/1.mp4",
|
||||
"video_source": "D:/repo/orisys-sdk/data/dd02-0703/tune.mp4",
|
||||
"sensor_bundle_dir": "sensors/finger",
|
||||
"config_path": "sensors/finger/sensor.json",
|
||||
"config_path": "finger",
|
||||
"finger_assets_dir": "sensors/finger/assets/30fps-0703",
|
||||
"csv_save_dir": "./outputs/csv",
|
||||
"show_log": true,
|
||||
"show_flow_arrows": false,
|
||||
"arrow_background": "pure_color",
|
||||
"arrow_background": "unrolled",
|
||||
"free_rotate": true,
|
||||
"log_display_mode": "hidden"
|
||||
}
|
||||
|
||||
@@ -76,11 +76,37 @@ def _bgr_from_gray_or_bgr(img: np.ndarray) -> np.ndarray:
|
||||
return img
|
||||
|
||||
|
||||
def _resolve_calibration_sensor_name(config_name) -> str | None:
|
||||
"""Map a config path/name to a sensors/<name> bundle when one exists."""
|
||||
if config_name is None:
|
||||
return None
|
||||
from orisys.configs import resolve_sensor_bundle
|
||||
|
||||
text = str(config_name).strip()
|
||||
if not text:
|
||||
return None
|
||||
|
||||
path = Path(text)
|
||||
parts = path.parts
|
||||
if "sensors" in parts:
|
||||
idx = parts.index("sensors")
|
||||
if idx + 1 < len(parts):
|
||||
candidate = parts[idx + 1]
|
||||
if resolve_sensor_bundle(candidate) is not None:
|
||||
return candidate
|
||||
|
||||
stem = path.stem if path.suffix else text
|
||||
if resolve_sensor_bundle(stem) is not None:
|
||||
return stem
|
||||
return None
|
||||
|
||||
|
||||
def _snapshot_from_sensor(
|
||||
sensor,
|
||||
*,
|
||||
raw_image=None,
|
||||
processed_image=None,
|
||||
sensor_name: str | None = None,
|
||||
) -> Optional[FrameSnapshot]:
|
||||
"""Build a FrameSnapshot with HHD/forces refreshed every frame."""
|
||||
if sensor is None or sensor.img is None:
|
||||
@@ -124,6 +150,9 @@ def _snapshot_from_sensor(
|
||||
below_threshold_color=(160, 160, 160),
|
||||
)
|
||||
|
||||
cal_name = sensor_name or _resolve_calibration_sensor_name(
|
||||
getattr(sensor, "config_name", None)
|
||||
)
|
||||
fn_raw = float(fnormal)
|
||||
return FrameSnapshot(
|
||||
image=image_bgr,
|
||||
@@ -134,7 +163,7 @@ def _snapshot_from_sensor(
|
||||
normal_force=fn_raw,
|
||||
shear_x=float(fshearx),
|
||||
shear_y=float(fsheary),
|
||||
normal_force_calibrated=calibrate_normal_force(fn_raw),
|
||||
normal_force_calibrated=calibrate_normal_force(fn_raw, sensor_name=cal_name),
|
||||
fps=float(fps),
|
||||
timestamp=time.time(),
|
||||
raw_image=raw_image,
|
||||
@@ -198,6 +227,7 @@ class OrisysSensorAdapter(SensorAdapter):
|
||||
if self.sensor.frame is not None
|
||||
else None,
|
||||
processed_image=_bgr_from_gray_or_bgr(self.sensor.img),
|
||||
sensor_name=_resolve_calibration_sensor_name(self.config_name),
|
||||
)
|
||||
|
||||
def reset(self) -> None:
|
||||
@@ -274,6 +304,7 @@ class Dd06RoiAdapter(SensorAdapter):
|
||||
self.sensor,
|
||||
raw_image=frame,
|
||||
processed_image=rectified,
|
||||
sensor_name=_resolve_calibration_sensor_name(self.config_name),
|
||||
)
|
||||
|
||||
def reset(self) -> None:
|
||||
|
||||
@@ -646,22 +646,42 @@ class FingerDashboardWindow(QMainWindow):
|
||||
self._update_play_enabled_for_source()
|
||||
|
||||
def _select_config(self) -> None:
|
||||
from .preferences import (
|
||||
default_finger_config,
|
||||
normalize_config_preference,
|
||||
packaged_finger_bundle_root,
|
||||
)
|
||||
|
||||
start = packaged_finger_bundle_root()
|
||||
start_dir = str(start) if start is not None else "sensors/finger"
|
||||
path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"选择配置文件",
|
||||
"config",
|
||||
start_dir,
|
||||
"JSON (*.json);;所有文件 (*)",
|
||||
)
|
||||
if path:
|
||||
self.settings_panel.set_config_path(path)
|
||||
self.config.config = path
|
||||
config = normalize_config_preference(path) or default_finger_config()
|
||||
self.settings_panel.set_config_path(config)
|
||||
self.config.config = config
|
||||
self._save_preferences()
|
||||
|
||||
def _select_finger_assets(self) -> None:
|
||||
from .preferences import (
|
||||
default_finger_assets_dir,
|
||||
default_finger_config,
|
||||
normalize_assets_preference,
|
||||
normalize_config_preference,
|
||||
packaged_finger_bundle_root,
|
||||
)
|
||||
|
||||
start = packaged_finger_bundle_root()
|
||||
path = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
"选择传感器 bundle 目录",
|
||||
self.settings_panel.sensor_bundle_dir() or "sensors/finger",
|
||||
str(start) if start is not None else (
|
||||
self.settings_panel.sensor_bundle_dir() or "sensors/finger"
|
||||
),
|
||||
)
|
||||
if path:
|
||||
bundle_dir = Path(path)
|
||||
@@ -677,12 +697,13 @@ class FingerDashboardWindow(QMainWindow):
|
||||
if isinstance(rel_assets, str) and rel_assets.strip():
|
||||
assets_dir = bundle_dir / rel_assets
|
||||
if config_path.is_file():
|
||||
self.settings_panel.set_config_path(str(config_path))
|
||||
self.config.config = str(config_path)
|
||||
self.settings_panel.set_finger_export_dir(str(assets_dir))
|
||||
self.config.export_dir = str(assets_dir)
|
||||
config = normalize_config_preference(str(config_path)) or default_finger_config()
|
||||
self.settings_panel.set_config_path(config)
|
||||
self.config.config = config
|
||||
assets = normalize_assets_preference(str(assets_dir)) or default_finger_assets_dir()
|
||||
self.settings_panel.set_finger_export_dir(assets)
|
||||
self.config.export_dir = assets
|
||||
self._save_preferences()
|
||||
|
||||
def _select_csv_dir(self) -> None:
|
||||
path = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
|
||||
@@ -13,6 +13,17 @@ LEGACY_CAMERA_SELECTION_FILE = "camera_selection.json"
|
||||
# Keep preference.json at examples/gui/ for backward compatibility.
|
||||
_GUI_DIR = Path(__file__).resolve().parents[1]
|
||||
|
||||
# Old lab / repo-relative paths that predate packaged sensors/<name>/.
|
||||
_LEGACY_CONFIG_PATHS = {
|
||||
"dd02",
|
||||
"dd02-ov",
|
||||
"config/dd02-ov.json",
|
||||
"./config/dd02-ov.json",
|
||||
"config/finger.json",
|
||||
"./config/finger.json",
|
||||
"sensors/finger/sensor.json",
|
||||
}
|
||||
|
||||
|
||||
def preference_path() -> Path:
|
||||
# Keep preference file at examples/gui/preference.json
|
||||
@@ -23,6 +34,92 @@ def legacy_camera_selection_path() -> Path:
|
||||
return resource_path(LEGACY_CAMERA_SELECTION_FILE)
|
||||
|
||||
|
||||
def default_finger_config() -> str:
|
||||
"""Public product config stem resolved via packaged ``sensors/finger``."""
|
||||
return "finger"
|
||||
|
||||
|
||||
def default_finger_assets_dir() -> str:
|
||||
try:
|
||||
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
|
||||
|
||||
return DEFAULT_FINGER_EXPORT_DIR
|
||||
except ImportError:
|
||||
return "sensors/finger/assets/30fps-0703"
|
||||
|
||||
|
||||
def packaged_finger_bundle_root() -> Path | None:
|
||||
"""Filesystem root of the installed ``sensors/finger`` bundle when present."""
|
||||
try:
|
||||
from orisys.configs import resolve_sensor_bundle
|
||||
except ImportError:
|
||||
return None
|
||||
bundle = resolve_sensor_bundle("finger")
|
||||
return bundle.root if bundle is not None else None
|
||||
|
||||
|
||||
def packaged_finger_assets_root() -> Path | None:
|
||||
try:
|
||||
from orisys.configs import resolve_sensor_asset_dir
|
||||
except ImportError:
|
||||
return None
|
||||
return resolve_sensor_asset_dir("finger")
|
||||
|
||||
|
||||
def normalize_config_preference(value: str | None) -> str:
|
||||
"""Map legacy config paths to the packaged ``finger`` sensor name."""
|
||||
if value is None or not str(value).strip():
|
||||
return default_finger_config()
|
||||
text = str(value).strip().replace("\\", "/")
|
||||
if text in _LEGACY_CONFIG_PATHS or text.endswith("/dd02-ov.json"):
|
||||
return default_finger_config()
|
||||
|
||||
root = packaged_finger_bundle_root()
|
||||
if root is not None:
|
||||
try:
|
||||
if Path(value).resolve() == (root / "sensor.json").resolve():
|
||||
return default_finger_config()
|
||||
except OSError:
|
||||
pass
|
||||
return text
|
||||
|
||||
|
||||
def normalize_assets_preference(value: str | None) -> str:
|
||||
"""Prefer packaged ``sensors/finger/assets/...`` when saved paths are stale."""
|
||||
default = default_finger_assets_dir()
|
||||
if value is None or not str(value).strip():
|
||||
return default
|
||||
text = str(value).strip()
|
||||
posix = text.replace("\\", "/")
|
||||
if posix == default or posix.endswith("/sensors/finger/assets/30fps-0703"):
|
||||
return default
|
||||
|
||||
path = Path(text)
|
||||
if path.is_dir():
|
||||
packaged = packaged_finger_assets_root()
|
||||
if packaged is not None:
|
||||
try:
|
||||
if path.resolve() == packaged.resolve():
|
||||
return default
|
||||
except OSError:
|
||||
pass
|
||||
if "sensors/finger" in posix or path.name == "30fps-0703":
|
||||
return text if path.is_absolute() else default
|
||||
return text
|
||||
|
||||
return default
|
||||
|
||||
|
||||
def _normalize_preferences(prefs: dict[str, Any]) -> dict[str, Any]:
|
||||
prefs = dict(prefs)
|
||||
if "config_path" in prefs or prefs:
|
||||
prefs["config_path"] = normalize_config_preference(prefs.get("config_path"))
|
||||
if "finger_assets_dir" in prefs or prefs:
|
||||
prefs["finger_assets_dir"] = normalize_assets_preference(prefs.get("finger_assets_dir"))
|
||||
prefs.setdefault("sensor_bundle_dir", "sensors/finger")
|
||||
return prefs
|
||||
|
||||
|
||||
def _read_json(path: Path) -> dict[str, Any]:
|
||||
if not path.is_file():
|
||||
return {}
|
||||
@@ -34,14 +131,14 @@ def _read_json(path: Path) -> dict[str, Any]:
|
||||
|
||||
|
||||
def load_preferences() -> dict[str, Any]:
|
||||
"""Load preferences, migrating camera_id from legacy file when needed."""
|
||||
"""Load preferences, migrating camera_id / legacy config paths when needed."""
|
||||
prefs = _read_json(preference_path())
|
||||
if "video_source" not in prefs:
|
||||
legacy = _read_json(legacy_camera_selection_path())
|
||||
camera_id = legacy.get("camera_id")
|
||||
if camera_id is not None and str(camera_id).strip():
|
||||
prefs["video_source"] = str(camera_id).strip()
|
||||
return prefs
|
||||
return _normalize_preferences(prefs)
|
||||
|
||||
|
||||
def save_preferences(prefs: dict[str, Any]) -> None:
|
||||
@@ -49,9 +146,10 @@ def save_preferences(prefs: dict[str, Any]) -> None:
|
||||
if not isinstance(prefs, dict):
|
||||
return
|
||||
path = preference_path()
|
||||
normalized = _normalize_preferences(prefs)
|
||||
try:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(prefs, indent=2) + "\n", encoding="utf-8")
|
||||
path.write_text(json.dumps(normalized, indent=2) + "\n", encoding="utf-8")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -25,6 +25,23 @@ class SensorBundlePreset:
|
||||
export_dir: str
|
||||
|
||||
|
||||
def _packaged_finger_preset() -> SensorBundlePreset | None:
|
||||
"""Use logical names that resolve through the installed wheel sensors/ layout."""
|
||||
try:
|
||||
from orisys.configs import resolve_sensor_bundle
|
||||
except ImportError:
|
||||
return None
|
||||
bundle = resolve_sensor_bundle("finger")
|
||||
if bundle is None:
|
||||
return None
|
||||
return SensorBundlePreset(
|
||||
label="ORY-FINGER",
|
||||
bundle_dir="sensors/finger",
|
||||
config="finger",
|
||||
export_dir=DEFAULT_FINGER_EXPORT_DIR,
|
||||
)
|
||||
|
||||
|
||||
def _load_manifest(bundle_root: Path) -> dict:
|
||||
path = bundle_root / "manifest.json"
|
||||
if not path.is_file():
|
||||
@@ -50,6 +67,14 @@ def _bundle_from_root(bundle_root: Path, *, label: str | None = None) -> SensorB
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
# Packaged / checkout sensors/finger: keep resolvable product names, not absolute paths.
|
||||
if rel_bundle.replace("\\", "/").endswith("sensors/finger") or bundle_root.name == "finger":
|
||||
return SensorBundlePreset(
|
||||
label=label or "ORY-FINGER",
|
||||
bundle_dir="sensors/finger",
|
||||
config="finger",
|
||||
export_dir=DEFAULT_FINGER_EXPORT_DIR,
|
||||
)
|
||||
return SensorBundlePreset(
|
||||
label=label or "ORY-FINGER",
|
||||
bundle_dir=rel_bundle,
|
||||
@@ -59,6 +84,9 @@ def _bundle_from_root(bundle_root: Path, *, label: str | None = None) -> SensorB
|
||||
|
||||
|
||||
def default_finger_bundle() -> SensorBundlePreset:
|
||||
packaged = _packaged_finger_preset()
|
||||
if packaged is not None:
|
||||
return packaged
|
||||
for root in _repo_root_candidates():
|
||||
preset = _bundle_from_root(root / "sensors" / "finger", label="ORY-FINGER")
|
||||
if preset is not None:
|
||||
@@ -66,7 +94,7 @@ def default_finger_bundle() -> SensorBundlePreset:
|
||||
return SensorBundlePreset(
|
||||
label="ORY-FINGER",
|
||||
bundle_dir="sensors/finger",
|
||||
config="sensors/finger/sensor.json",
|
||||
config="finger",
|
||||
export_dir=DEFAULT_FINGER_EXPORT_DIR,
|
||||
)
|
||||
|
||||
@@ -108,6 +136,8 @@ def sensor_bundle_preset_index(
|
||||
for idx, preset in enumerate(presets):
|
||||
if config == preset.config and export_dir == preset.export_dir:
|
||||
return idx
|
||||
if config in ("finger", "dd02", "dd02-ov") and preset.config == "finger":
|
||||
return idx
|
||||
if config.endswith("/sensor.json") and export_dir.endswith("/" + Path(preset.export_dir).name):
|
||||
return idx
|
||||
return -1
|
||||
|
||||
@@ -16,6 +16,7 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
from viz.render_2d import ArrowBackground
|
||||
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
|
||||
|
||||
from ..layout import DashboardLayout, LAYOUT
|
||||
from ..mesh_view_state import MeshViewState
|
||||
@@ -157,7 +158,7 @@ class SettingsPanelWidget(QWidget):
|
||||
bundle_row.addWidget(self.btn_browse_finger_assets)
|
||||
root.addLayout(bundle_row)
|
||||
|
||||
self.config_edit = QLineEdit("sensors/finger/sensor.json")
|
||||
self.config_edit = QLineEdit("finger")
|
||||
self.config_edit.hide()
|
||||
self.btn_browse_config = QPushButton("…")
|
||||
self.btn_browse_config.hide()
|
||||
@@ -167,10 +168,9 @@ class SettingsPanelWidget(QWidget):
|
||||
self.cal_edit.setPlaceholderText("Optional calibration path")
|
||||
self.cal_edit.hide()
|
||||
|
||||
self.finger_assets_edit = QLineEdit("sensors/finger/assets/30fps-0703")
|
||||
self.finger_assets_edit = QLineEdit(DEFAULT_FINGER_EXPORT_DIR)
|
||||
self.finger_assets_edit.hide()
|
||||
self._apply_bundle_preset(self._bundle_presets[0])
|
||||
|
||||
root.addWidget(self._caption("CSV save directory"))
|
||||
csv_dir_row = QHBoxLayout()
|
||||
csv_dir_row.setSpacing(6)
|
||||
|
||||
@@ -7,7 +7,7 @@ ORY-MINI:单传感器基础流程
|
||||
3. 按需计算接触区域
|
||||
4. 读取并可视化结果
|
||||
|
||||
SDK version: 0.4.3
|
||||
SDK version: 0.4.4
|
||||
"""
|
||||
import os
|
||||
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
- Windows 下必须在 if __name__ == '__main__' 中调用 mp.freeze_support()
|
||||
- 每个传感器进程都会占用独立的 GPU 显存
|
||||
|
||||
SDK version: 0.4.3
|
||||
SDK version: 0.4.4
|
||||
"""
|
||||
import os
|
||||
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
|
||||
|
||||
@@ -7,6 +7,10 @@ from pathlib import Path
|
||||
import numpy as np
|
||||
|
||||
DEFAULT_FINGER_VIZ_POSE = "sensors/finger/assets/visualization/world_to_cam.npy"
|
||||
_LEGACY_FINGER_VIZ_POSES = {
|
||||
"assets/finger/visualization/world_to_cam.npy",
|
||||
DEFAULT_FINGER_VIZ_POSE,
|
||||
}
|
||||
|
||||
|
||||
def _finger_bundle_viz_pose_candidates() -> list[Path]:
|
||||
@@ -63,8 +67,9 @@ def resolve_viz_pose_path(path: str | Path | None = None) -> Path:
|
||||
here = Path(__file__).resolve()
|
||||
candidates: list[Path] = []
|
||||
|
||||
# Prefer the sensors/finger bundle for the default (and matching relative) path.
|
||||
if path is None or raw.as_posix() == DEFAULT_FINGER_VIZ_POSE or not raw.is_absolute():
|
||||
# Prefer the sensors/finger bundle for default / legacy relative paths.
|
||||
posix = raw.as_posix()
|
||||
if path is None or posix in _LEGACY_FINGER_VIZ_POSES or not raw.is_absolute():
|
||||
candidates.extend(_finger_bundle_viz_pose_candidates())
|
||||
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user