"""
param_store
パラメータプリセットの保存・読み込みを管理するモジュール
画像処理パラメータと PD 制御パラメータを独立して管理する
"""
import json
from dataclasses import asdict, dataclass
from pathlib import Path
from pc.steering.pd_control import PdParams
from pc.vision.line_detector import ImageParams
# プリセット保存ディレクトリ
_PARAMS_DIR: Path = (
Path(__file__).resolve().parent.parent.parent.parent
/ "params"
)
_PD_FILE: Path = _PARAMS_DIR / "presets_pd.json"
_IMAGE_FILE: Path = _PARAMS_DIR / "presets_image.json"
# ── PD 制御プリセット ─────────────────────────
@dataclass
class PdPreset:
"""PD 制御パラメータのプリセット
Attributes:
title: プリセットのタイトル
memo: メモ
params: PD 制御パラメータ
"""
title: str
memo: str
params: PdParams
def load_pd_presets() -> list[PdPreset]:
"""PD 制御プリセット一覧を読み込む"""
return _load_presets(
_PD_FILE, PdPreset, "params", PdParams,
)
def add_pd_preset(preset: PdPreset) -> None:
"""PD 制御プリセットを追加する"""
presets = load_pd_presets()
presets.append(preset)
_save_presets(
_PD_FILE, presets, "params",
)
def delete_pd_preset(index: int) -> None:
"""PD 制御プリセットを削除する"""
presets = load_pd_presets()
if 0 <= index < len(presets):
presets.pop(index)
_save_presets(
_PD_FILE, presets, "params",
)
# ── 画像処理プリセット ────────────────────────
@dataclass
class ImagePreset:
"""画像処理パラメータのプリセット
Attributes:
title: プリセットのタイトル
memo: メモ
image_params: 画像処理パラメータ
"""
title: str
memo: str
image_params: ImageParams
def load_image_presets() -> list[ImagePreset]:
"""画像処理プリセット一覧を読み込む"""
return _load_presets(
_IMAGE_FILE, ImagePreset,
"image_params", ImageParams,
)
def add_image_preset(preset: ImagePreset) -> None:
"""画像処理プリセットを追加する"""
presets = load_image_presets()
presets.append(preset)
_save_presets(
_IMAGE_FILE, presets, "image_params",
)
def delete_image_preset(index: int) -> None:
"""画像処理プリセットを削除する"""
presets = load_image_presets()
if 0 <= index < len(presets):
presets.pop(index)
_save_presets(
_IMAGE_FILE, presets, "image_params",
)
# ── 共通処理 ──────────────────────────────────
def _load_presets(path, preset_cls, params_key, params_cls):
"""プリセットファイルを読み込む"""
if not path.exists():
return []
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
known = params_cls.__dataclass_fields__
presets = []
for item in data:
if params_key in item:
filtered = {
k: v
for k, v in item[params_key].items()
if k in known
}
params = params_cls(**filtered)
else:
params = params_cls()
presets.append(preset_cls(
title=item["title"],
memo=item["memo"],
**{params_key: params},
))
return presets
def _save_presets(path, presets, params_key):
"""プリセットファイルに保存する"""
path.parent.mkdir(exist_ok=True)
data = []
for preset in presets:
data.append({
"title": preset.title,
"memo": preset.memo,
params_key: asdict(
getattr(preset, params_key),
),
})
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)