Skip to content

Commit a27c850

Browse files
committed
fixing some issues and implement test when reconnecting powerlines
Signed-off-by: DONNOT Benjamin <[email protected]>
1 parent c1f487c commit a27c850

File tree

6 files changed

+70
-21
lines changed

6 files changed

+70
-21
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ Native multi agents support:
137137
- [FIXED] a bug in updating the shunt in PandaPowerBackend (depdending on pandas version)
138138
- [FIXED] a bug when action that reconnect loads, storage units or shunts are done
139139
in the "obs.simulate" (results could depend from previous "obs.simulate" calls)
140+
- [FIXED] a bug in "obs.simulate" and "obs.get_forecast_env" : when a line was disconnected
141+
and the user tried to reconnect it (without specifying on which bus) it could do something
142+
different than "env.step" (with the same action)
140143
- [ADDED] possibility to set the "thermal limits" when calling `env.reset(..., options={"thermal limit": xxx})`
141144
- [ADDED] possibility to retrieve some structural information about elements with
142145
with `gridobj.get_line_info(...)`, `gridobj.get_load_info(...)`, `gridobj.get_gen_info(...)`

grid2op/Backend/backend.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
Grid2OpException,
3737
)
3838
from grid2op.Space import GridObjects, ElTypeInfo, DEFAULT_N_BUSBAR_PER_SUB, DEFAULT_ALLOW_DETACHMENT
39+
import grid2op.Observation # for type hints
40+
import grid2op.Action # for type hints
3941

4042

4143
# TODO method to get V and theta at each bus, could be in the same shape as check_kirchoff
@@ -1920,7 +1922,7 @@ def get_action_to_set(self) -> "grid2op.Action.CompleteAction":
19201922

19211923
def update_from_obs(self,
19221924
obs: "grid2op.Observation.CompleteObservation",
1923-
force_update: Optional[bool]=False):
1925+
force_update: Optional[bool]=False) -> "grid2op.Action._BackendAction._BackendAction":
19241926
"""
19251927
Takes an observation as input and update the internal state of `self` to match the state of the backend
19261928
that produced this observation.
@@ -1954,18 +1956,18 @@ def update_from_obs(self,
19541956
)
19551957

19561958
cls = type(self)
1957-
backend_action = cls.my_bk_act_class()
1959+
backend_action : "grid2op.Action._BackendAction._BackendAction" = cls.my_bk_act_class()
19581960
act = cls._complete_action_class()
19591961
line_status = self._aux_get_line_status_to_set(obs.line_status)
19601962
# skip the action part and update directly the backend action !
19611963
dict_ = {
19621964
"set_bus": obs.topo_vect,
19631965
"set_line_status": line_status,
19641966
"injection": {
1965-
"prod_p": obs.prod_p,
1966-
"prod_v": obs.prod_v,
1967-
"load_p": obs.load_p,
1968-
"load_q": obs.load_q,
1967+
"prod_p": obs._get_gen_p_for_forecasts(),
1968+
"prod_v": obs._get_gen_v_for_forecasts(),
1969+
"load_p": obs._get_load_p_for_forecasts(),
1970+
"load_q": obs._get_load_q_for_forecasts(),
19691971
},
19701972
}
19711973

@@ -1991,6 +1993,7 @@ def update_from_obs(self,
19911993
act.update(dict_)
19921994
backend_action += act
19931995
self.apply_action(backend_action)
1996+
return backend_action
19941997

19951998
def assert_grid_correct(self, _local_dir_cls=None) -> None:
19961999
"""

grid2op/Environment/_env_prev_state.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,21 @@ def update_from_other(self,
118118
tmp[:] = getattr(other, attr_nm)
119119
else:
120120
setattr(self, attr_nm, getattr(other, attr_nm))
121-
121+
122122
def prevent_modification(self):
123+
self._aux_modif()
124+
self._can_modif = False
125+
126+
def force_update(self, other: "_EnvPreviousState"):
127+
"""This is used when initializing the forecast env. This removes the "cst" part,
128+
set it to the value given by other, and then assign it to const.
129+
"""
130+
self._can_modif = True
131+
self._aux_modif(True)
132+
self.update_from_other(other)
133+
self.prevent_modification()
134+
135+
def _aux_modif(self, writeable_flag=False):
123136
for attr_nm in ["_load_p",
124137
"_load_q",
125138
"_gen_p",
@@ -132,8 +145,7 @@ def prevent_modification(self):
132145
tmp = getattr(self, attr_nm)
133146
if tmp.size > 1:
134147
# can't set flags on array of size 1 apparently
135-
tmp.flags.writeable = False
136-
self._can_modif = False
148+
tmp.flags.writeable = writeable_flag
137149

138150
def _aux_update(self,
139151
el_topo_vect : np.ndarray,

grid2op/Environment/_obsEnv.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ def init(
393393
# TODO set the shunts here
394394
# update the action that set the grid to the real value
395395
self._previous_conn_state.update_from_other(obs._prev_conn)
396+
# remember the last connection state
397+
self._backend_action_set.last_topo_registered.values[:] = obs._prev_conn._topo_vect
396398
gen_p = obs._get_gen_p_for_forecasts()
397399
gen_v = obs._get_gen_v_for_forecasts()
398400
load_p = obs._get_load_p_for_forecasts()

grid2op/Environment/baseEnv.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,14 +1476,26 @@ def _has_been_initialized(self):
14761476
np.zeros(bk_type.n_shunt, dtype=dt_float),
14771477
np.zeros(bk_type.n_shunt, dtype=dt_int),
14781478
)
1479-
try:
1480-
self._previous_conn_state.update_from_backend(self.backend)
1481-
except Exception as exc_:
1482-
# nothing to do in this case
1483-
self.logger.warning(f"Impossible to retrieve the initial state of the grid before running the initial powerflow: {exc_}")
1484-
self._previous_conn_state._topo_vect[:] = 1 # I force assign everything to busbar 1 by default...
1485-
self._cst_prev_state_at_init = copy.deepcopy(self._previous_conn_state)
1486-
self._cst_prev_state_at_init.prevent_modification()
1479+
1480+
if self._init_obs is None:
1481+
# regular environment, initialized from scratch
1482+
try:
1483+
self._previous_conn_state.update_from_backend(self.backend)
1484+
except Exception as exc_:
1485+
# nothing to do in this case
1486+
self.logger.warning(f"Impossible to retrieve the initial state of the grid before running the initial powerflow: {exc_}")
1487+
self._previous_conn_state._topo_vect[:] = 1 # I force assign everything to busbar 1 by default...
1488+
self._cst_prev_state_at_init = copy.deepcopy(self._previous_conn_state)
1489+
self._cst_prev_state_at_init.prevent_modification()
1490+
else:
1491+
# environment initialized from an observation, eg forecast_env
1492+
self._cst_prev_state_at_init = copy.deepcopy(self._init_obs._prev_conn)
1493+
self._cst_prev_state_at_init.prevent_modification()
1494+
self._previous_conn_state.update_from_other(self._cst_prev_state_at_init)
1495+
# TODO this has to be done also in "_reset_to_orig_state" but I don't know why...
1496+
1497+
# update backend_action with the "last known" state
1498+
self._backend_action.last_topo_registered.values[:] = self._previous_conn_state._topo_vect
14871499

14881500
def _update_parameters(self):
14891501
"""update value for the new parameters"""
@@ -4626,6 +4638,11 @@ def _reset_to_orig_state(self, obs):
46264638

46274639
# soft overflow
46284640
self._timestep_overflow[:] = obs.timestep_overflow
4641+
4642+
# previous "connected" state of all elements
4643+
self._previous_conn_state.update_from_other(obs._prev_conn) # already done with _cst_prev_XXX
4644+
self._backend_action.last_topo_registered.values[:] = obs._prev_conn._topo_vect
4645+
# self._backend_action.current_topo.values[:] = obs._prev_conn._topo_vect
46294646

46304647
def forecasts(self):
46314648
# ensure that the "env.chronics_handler.forecasts" is called at most once per step

grid2op/Environment/environment.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
from grid2op.operator_attention import LinearAttentionBudget
3535
from grid2op.Space import DEFAULT_N_BUSBAR_PER_SUB, DEFAULT_ALLOW_DETACHMENT, GRID2OP_CURRENT_VERSION_STR
3636
from grid2op.typing_variables import RESET_OPTIONS_TYPING, N_BUSBAR_PER_SUB_TYPING
37-
from grid2op.MakeEnv.PathUtils import USE_CLASS_IN_FILE
3837

3938

4039
class Environment(BaseEnv):
@@ -202,6 +201,7 @@ def __init__(
202201
self._allow_loaded_backend : bool = _allow_loaded_backend
203202

204203
# for gym compatibility (action_spacen and observation_space initialized below)
204+
# for plotting
205205
self.reward_range = None
206206
self._viewer = None
207207
self.metadata = None
@@ -212,7 +212,8 @@ def __init__(
212212
# needs to be done before "_init_backend" otherwise observationClass is not defined in the
213213
# observation space (real_env_kwargs)
214214
self._observationClass_orig = observationClass
215-
# for plotting
215+
216+
# init the backend
216217
self._init_backend(
217218
chronics_handler,
218219
backend,
@@ -533,6 +534,14 @@ def _init_backend(
533534
# reset everything to be consistent
534535
self._reset_vectors_and_timings()
535536

537+
# 1.11 and detachement: forecasted env
538+
if self._init_obs is not None:
539+
# update the backend
540+
self._backend_action = self.backend.update_from_obs(self._init_obs)
541+
self._backend_action.last_topo_registered.values[:] = self._init_obs._prev_conn._topo_vect
542+
self._cst_prev_state_at_init.force_update(self._init_obs._prev_conn)
543+
self._previous_conn_state.update_from_other(self._init_obs._prev_conn)
544+
536545
def max_episode_duration(self):
537546
"""
538547
Return the maximum duration (in number of steps) of the current episode.
@@ -963,11 +972,14 @@ def reset_grid(self,
963972
if self._thermal_limit_a is not None:
964973
self.backend.set_thermal_limit(self._thermal_limit_a.astype(dt_float))
965974

966-
self._backend_action = self._backend_action_class()
967975
self.nb_time_step = -1 # to have init obs at step 1 (and to prevent 'setting to proper state' "action" to be illegal)
968976

969977
if self._init_obs is not None:
970-
self.backend.update_from_obs(self._init_obs)
978+
# update the backend
979+
self._backend_action = self.backend.update_from_obs(self._init_obs)
980+
self._backend_action.last_topo_registered.values[:] = self._init_obs._prev_conn._topo_vect
981+
else:
982+
self._backend_action = self._backend_action_class()
971983

972984
init_action = None
973985
if not self._parameters.IGNORE_INITIAL_STATE_TIME_SERIE:

0 commit comments

Comments
 (0)