Source code for smartcer.gym.controllers.base

"""
Base class of the controllers of `SmartCerEnv`: baselines that choose one action per battery.

Adapted from storage-node-environment (`storage_node_env/gym/controllers/base.py`): continuous
actions in [-1, 1] in `storage_node_ids` order instead of a discrete index. A controller is bound to
an environment and may read its community (data and battery states), unlike an agent, which sees
only the observation.
"""

from abc import ABC, abstractmethod
from typing import Any

import gymnasium as gym
import numpy as np

from smartcer.gym.cer_env import SmartCerEnv


[docs] class Controller(ABC): """ Chooses the actions of a `SmartCerEnv`, one per battery. Attributes: name: Controller name, used for the output folders of a run; a subclass may set it per instance (e.g. from a mode). env: The unwrapped environment the controller acts on. """ name: str def __init__(self, env: gym.Env) -> None: """ Bind the controller to an environment. Args: env: A `SmartCerEnv`, possibly wrapped. Raises: TypeError: If the unwrapped environment is not a `SmartCerEnv`. """ unwrapped = env.unwrapped if not isinstance(unwrapped, SmartCerEnv): raise TypeError(f'{type(self).__name__} needs a SmartCerEnv, got ' f'{type(unwrapped).__name__}') self.env = unwrapped def __repr__(self) -> str: return f'{type(self).__name__}({self.env.community.name!r})'
[docs] def reset(self) -> None: """ Prepare a new episode; called after `env.reset()`. Stateless controllers do nothing. """
[docs] @abstractmethod def act(self, observation: np.ndarray, info: dict[str, Any]) -> np.ndarray: """ Actions for the step `env.current_step`. Args: observation: Latest observation of the environment. info: Latest info of the environment. Returns: np.ndarray: One action per battery in [-1, 1], float32 or float64, in `storage_node_ids` order. """