Newer
Older
RobotCar / src / pc / steering / param_store.py
"""
param_store
パラメータの保存・読み込みを管理するモジュール
1つの JSON ファイルに複数のパラメータセットを格納する
"""

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

# パラメータ保存先のファイルパス
_STORE_PATH: Path = (
    Path(__file__).resolve().parent.parent.parent.parent
    / "pd_params.json"
)


@dataclass
class ParamEntry:
    """パラメータセットの1エントリ

    Attributes:
        title: パラメータセットのタイトル
        memo: メモ(用途や特徴の説明)
        params: PD 制御パラメータ
        image_params: 画像処理パラメータ
    """
    title: str
    memo: str
    params: PdParams
    image_params: ImageParams


def load_entries() -> list[ParamEntry]:
    """保存済みのパラメータ一覧を読み込む

    Returns:
        パラメータエントリのリスト
    """
    if not _STORE_PATH.exists():
        return []

    with open(_STORE_PATH, "r", encoding="utf-8") as f:
        data = json.load(f)

    entries: list[ParamEntry] = []
    for item in data:
        image_params = ImageParams(
            **item["image_params"],
        ) if "image_params" in item else ImageParams()

        entries.append(ParamEntry(
            title=item["title"],
            memo=item["memo"],
            params=PdParams(**item["params"]),
            image_params=image_params,
        ))
    return entries


def save_entries(entries: list[ParamEntry]) -> None:
    """パラメータ一覧をファイルに保存する

    Args:
        entries: パラメータエントリのリスト
    """
    data = []
    for entry in entries:
        data.append({
            "title": entry.title,
            "memo": entry.memo,
            "params": asdict(entry.params),
            "image_params": asdict(entry.image_params),
        })

    with open(_STORE_PATH, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)


def add_entry(entry: ParamEntry) -> None:
    """パラメータセットを追加する

    Args:
        entry: 追加するエントリ
    """
    entries = load_entries()
    entries.append(entry)
    save_entries(entries)


def delete_entry(index: int) -> None:
    """パラメータセットを削除する

    Args:
        index: 削除するエントリのインデックス
    """
    entries = load_entries()
    if 0 <= index < len(entries):
        entries.pop(index)
        save_entries(entries)