Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert observation to per unit #621

Open
DEUCE1957 opened this issue Jul 1, 2024 · 0 comments
Open

Convert observation to per unit #621

DEUCE1957 opened this issue Jul 1, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@DEUCE1957
Copy link
Contributor

DEUCE1957 commented Jul 1, 2024

Specifications

Grid2op: 1.10.0
Python: 3.11.9
System: Windows 11

Is your feature request related to a problem? Please describe.

An backend-agnostic way to convert an observation vector to per-unit values. While nominal units are useful for us to interpret as humans, a per-unit scheme may provide better performance in a Neural Network since large absolute values (e.g. 160 kV) will now all be in a similar range (around 0-1) and thus not drown out smaller values. This should result in more stable learning.

At first inspection the AnalogStateConverter seems to normalize the observation vector, however inside the method the scaling values are fixed numbers (i.e. they are not determined based on the network characteristics, such as the nominal voltage in an area).

Alternatives Considered

I attempted to write my own per-unit conversion by making use of the PandaPower backend. However, the attributes of the network to not seem to match the production characteristics (prods_charac.csv) of the Environment (which are used to define fixed attributes like obs.gen_p_max). To see this run this code snippet:

import grid2op
import pandapower as pp
from grid2op.Backend import PandaPowerBackend
env = grid2op.make("rte_case14_realistic", backend=PandaPowerBackend())
obs = env.reset()
network = pp.from_json(Path(env.get_path_env()) / "grid.json")
display(network.gen.loc[:, ["max_p_mw", "min_p_mw", "name", "type", "bus", "vm_pu"]])
prods_charac = pd.read_csv(Path(env.get_path_env()) / "prods_charac.csv", sep=",")
display(prods_charac)

Here the 'max_p_mw' from the PandaPower Backend does not match the 'prod_charac.csv' (nor obs.max_p_mw). Similarly if we try to fetch the nominal voltages of the bus each generator is connected to:

display(network.bus.loc[network.gen.bus, "vn_kv"])

We get values of 138 kV, 138Kv, 20kV, 12kV and 138 kV compared to 142.1kV, 142.1kV, 22.0kV, 13.2kV and 142.1kV in ProdCharac.csv. Since the powerflow is run in Pandapower by default, I would expect these values to match.

This approach could perhaps work if I knew which of these values to normalize by. However, this does not extend to loads since the 'loads_charac.csv' file is not defined for the 'rte_case14_realistic' environment (even though it does have loads).

Solution

A per unit converter:

import numpy
from grid2op.Converter import Converter
class PerUnitConverter(Converter):

    def convert_obs(self, obs) -> numpy.array:
          pass

Alternatively, a method attached to BaseObservation that converts the observation to nominal values:

obs = env.reset()
obs.to_vect(pu=True)

For speed-up many of the fixed values could be cached (e.g. max power)

If the internal values inside Grid2op (i.e. obs.gen_p_max, etc.) are the correct ones to normalize by, then it would be convenient if the nominal voltages were exposed (e.g. obs.v_nom). Would make it feasible to implement the conversion.

@DEUCE1957 DEUCE1957 added the enhancement New feature or request label Jul 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant