"""
auto_params
パラメータの自動保存・読み込みを管理するモジュール
アプリ起動時に前回のパラメータを復元し,変更時に自動保存する
ファイル構成:
params/
├── control.json PD 制御 + 最後に使用した手法
├── detect_current.json 現行手法の画像処理パラメータ
├── detect_blackhat.json 案A の画像処理パラメータ
├── detect_dual_norm.json 案B の画像処理パラメータ
└── detect_robust.json 案C の画像処理パラメータ
"""
import json
from dataclasses import asdict
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 制御パラメータファイル
_CONTROL_FILE: Path = _PARAMS_DIR / "control.json"
# 検出手法ごとのファイル名
_DETECT_FILES: dict[str, str] = {
"current": "detect_current.json",
"blackhat": "detect_blackhat.json",
"dual_norm": "detect_dual_norm.json",
"robust": "detect_robust.json",
}
def save_control(
params: PdParams, method: str,
) -> None:
"""PD 制御パラメータと最後に使用した手法を保存する
Args:
params: PD 制御パラメータ
method: 最後に使用した検出手法の識別子
"""
_PARAMS_DIR.mkdir(exist_ok=True)
data = asdict(params)
data["last_method"] = method
_write_json(_CONTROL_FILE, data)
def load_control() -> tuple[PdParams, str]:
"""PD 制御パラメータと最後に使用した手法を読み込む
Returns:
(PD 制御パラメータ, 最後に使用した手法の識別子)
"""
if not _CONTROL_FILE.exists():
return PdParams(), "current"
data = _read_json(_CONTROL_FILE)
method = data.pop("last_method", "current")
known = PdParams.__dataclass_fields__
filtered = {
k: v for k, v in data.items()
if k in known
}
return PdParams(**filtered), method
def save_detect_params(
method: str, params: ImageParams,
) -> None:
"""検出手法のパラメータを保存する
Args:
method: 検出手法の識別子
params: 画像処理パラメータ
"""
filename = _DETECT_FILES.get(method)
if filename is None:
return
_PARAMS_DIR.mkdir(exist_ok=True)
data = asdict(params)
data["method"] = method
_write_json(_PARAMS_DIR / filename, data)
def load_detect_params(method: str) -> ImageParams:
"""検出手法のパラメータを読み込む
Args:
method: 検出手法の識別子
Returns:
画像処理パラメータ(ファイルがない場合はデフォルト)
"""
filename = _DETECT_FILES.get(method)
if filename is None:
return ImageParams(method=method)
path = _PARAMS_DIR / filename
if not path.exists():
return ImageParams(method=method)
data = _read_json(path)
known = ImageParams.__dataclass_fields__
filtered = {
k: v for k, v in data.items()
if k in known
}
filtered["method"] = method
return ImageParams(**filtered)
def _write_json(path: Path, data: dict) -> None:
"""JSON ファイルに書き込む"""
with open(path, "w", encoding="utf-8") as f:
json.dump(
data, f, ensure_ascii=False, indent=2,
)
def _read_json(path: Path) -> dict:
"""JSON ファイルを読み込む"""
with open(path, "r", encoding="utf-8") as f:
return json.load(f)