This document describes the key attributes available in the Grid2Op observation space, organized by category. These attributes can be used for state representation, reward shaping, and cost functions in constrained reinforcement learning.
- Line/Branch Attributes
- Voltage Attributes
- Generator Attributes
- Load Attributes
- Topology Attributes
- Temporal Attributes
- Potential Cost Metrics
Power lines (branches) connect substations and carry electrical power. These are critical for grid stability.
| Attribute | Shape | Description |
|---|---|---|
rho |
(n_line,) |
Line loading ratio (current / thermal limit). Values > 1.0 indicate overload. Most important safety metric. |
line_status |
(n_line,) |
Boolean array indicating if each line is connected (True) or disconnected (False). |
thermal_limit |
(n_line,) |
Maximum current (in Amps) each line can carry before overheating. |
timestep_overflow |
(n_line,) |
Number of consecutive timesteps each line has been in overflow (rho > 1.0). |
p_or |
(n_line,) |
Active power at the origin end of each line (MW). |
p_ex |
(n_line,) |
Active power at the extremity end of each line (MW). |
q_or |
(n_line,) |
Reactive power at the origin end (MVAr). |
q_ex |
(n_line,) |
Reactive power at the extremity end (MVAr). |
a_or |
(n_line,) |
Current at the origin end (Amps). |
a_ex |
(n_line,) |
Current at the extremity end (Amps). |
time_before_cooldown_line |
(n_line,) |
Timesteps before a line can be reconnected after disconnection. |
duration_next_maintenance |
(n_line,) |
Duration of the next scheduled maintenance for each line. |
time_next_maintenance |
(n_line,) |
Timesteps until next scheduled maintenance. |
rho = a_or / thermal_limit(approximately)- Power loss on line:
p_or - p_ex
Voltage levels must be maintained within acceptable bounds (typically 0.95–1.05 per unit) for grid stability.
| Attribute | Shape | Description |
|---|---|---|
v_or |
(n_line,) |
Voltage magnitude at the origin end of each line (kV). |
v_ex |
(n_line,) |
Voltage magnitude at the extremity end of each line (kV). |
gen_v |
(n_gen,) |
Voltage at each generator bus (kV). |
load_v |
(n_load,) |
Voltage at each load bus (kV). |
theta_or |
(n_line,) |
Voltage angle at line origin (degrees). |
theta_ex |
(n_line,) |
Voltage angle at line extremity (degrees). |
gen_theta |
(n_gen,) |
Voltage angle at generator buses (degrees). |
load_theta |
(n_load,) |
Voltage angle at load buses (degrees). |
- Voltage values are in kV (kilovolts), not per-unit
- Different voltage levels exist in the grid (e.g., 22 kV, 142 kV)
- To compute per-unit, divide by the nominal voltage of each bus
Generators produce electricity and can be controlled (redispatched) to balance the grid.
| Attribute | Shape | Description |
|---|---|---|
gen_p |
(n_gen,) |
Current active power output of each generator (MW). |
gen_q |
(n_gen,) |
Current reactive power output (MVAr). |
gen_v |
(n_gen,) |
Voltage at generator bus (kV). |
gen_pmin |
(n_gen,) |
Minimum active power output (MW). |
gen_pmax |
(n_gen,) |
Maximum active power output (MW). |
gen_margin_up |
(n_gen,) |
Available capacity for increasing output (MW). |
gen_margin_down |
(n_gen,) |
Available capacity for decreasing output (MW). |
gen_max_ramp_up |
(n_gen,) |
Maximum increase in output per timestep (MW). |
gen_max_ramp_down |
(n_gen,) |
Maximum decrease in output per timestep (MW). |
actual_dispatch |
(n_gen,) |
Actual redispatch applied to each generator (MW). |
target_dispatch |
(n_gen,) |
Requested redispatch (may differ from actual due to constraints). |
gen_cost_per_MW |
(n_gen,) |
Cost of generation per MW (for economic dispatch). |
gen_redispatchable |
(n_gen,) |
Boolean indicating if generator can be redispatched. |
gen_renewable |
(n_gen,) |
Boolean indicating if generator is renewable. |
gen_type |
(n_gen,) |
Type of generator (e.g., 'thermal', 'solar', 'wind'). |
| Attribute | Shape | Description |
|---|---|---|
curtailment |
(n_gen,) |
Fraction of renewable generation being curtailed (0–1). |
curtailment_mw |
(n_gen,) |
Absolute curtailment in MW. |
curtailment_limit |
(n_gen,) |
Current curtailment limit (fraction). |
gen_p_before_curtail |
(n_gen,) |
Generation before curtailment was applied. |
Loads represent electricity consumption (demand) at various points in the grid.
| Attribute | Shape | Description |
|---|---|---|
load_p |
(n_load,) |
Active power consumption at each load (MW). |
load_q |
(n_load,) |
Reactive power consumption (MVAr). |
load_v |
(n_load,) |
Voltage at each load bus (kV). |
load_theta |
(n_load,) |
Voltage angle at each load bus (degrees). |
load_bus |
(n_load,) |
Bus assignment for each load. |
Grid topology describes how components are connected at substations.
| Attribute | Shape | Description |
|---|---|---|
topo_vect |
(dim_topo,) |
Bus assignment for every element in the grid. Value of 1 or 2 indicates which busbar, -1 means disconnected. |
line_or_bus |
(n_line,) |
Bus assignment at line origin. |
line_ex_bus |
(n_line,) |
Bus assignment at line extremity. |
gen_bus |
(n_gen,) |
Bus assignment for each generator. |
load_bus |
(n_load,) |
Bus assignment for each load. |
time_before_cooldown_sub |
(n_sub,) |
Timesteps before topology can be changed at each substation. |
sub_info |
(n_sub,) |
Number of elements at each substation. |
n_busbar_per_sub |
int |
Number of busbars per substation (typically 2). |
- Each substation has 2 busbars; elements can be moved between them
- Topology changes are powerful actions but have cooldown periods
dim_topo= total number of controllable elements
Time-related information useful for forecasting and episode tracking.
| Attribute | Shape | Description |
|---|---|---|
current_step |
() |
Current timestep in the episode. |
max_step |
() |
Maximum timesteps in the episode. |
delta_time |
() |
Duration of each timestep (minutes). |
year |
() |
Current year. |
month |
() |
Current month (1–12). |
day |
() |
Current day of month. |
hour_of_day |
() |
Current hour (0–23). |
minute_of_hour |
() |
Current minute (0–59). |
day_of_week |
() |
Day of week (0=Monday, 6=Sunday). |
These metrics are suitable for defining cost constraints in constrained reinforcement learning (e.g., CPGPE with mean-variance optimization).
| Cost Metric | Formula | Description | Recommended Threshold |
|---|---|---|---|
| rho_max | max(rho) |
Maximum line loading across all lines | ≤ 0.8 (80%) |
| rho_violations_count | sum(rho > threshold) |
Number of overloaded lines | ≤ 0 |
| rho_violations_sum | sum(max(0, rho - threshold)) |
Total excess loading | ≤ 0.0 |
| rho_violations_quadratic | sum(max(0, rho - threshold)^2) |
Quadratic penalty for violations | ≤ 0.0 |
Example Implementation:
def compute_rho_cost(obs, threshold=0.8):
violations = np.maximum(0, obs.rho - threshold)
return violations.sum() # or max, or count| Cost Metric | Formula | Description | Recommended Threshold |
|---|---|---|---|
| disconnections | sum(~line_status) |
Number of disconnected lines | ≤ 1 |
| overflow_duration | sum(timestep_overflow) |
Total overflow timesteps | ≤ 5 |
Example Implementation:
def compute_disconnection_cost(obs):
return (~obs.line_status).sum()
def compute_overflow_cost(obs):
return obs.timestep_overflow.sum()| Cost Metric | Formula | Description | Recommended Threshold |
|---|---|---|---|
| voltage_deviation | `max( | v - v_nominal | / v_nominal)` |
| voltage_violations | Count of buses outside [0.95, 1.05] p.u. | Number of voltage violations | ≤ 0 |
Note: Voltage costs require knowing nominal voltages for each bus.
| Cost Metric | Formula | Description | Recommended Threshold |
|---|---|---|---|
| redispatch_cost | `sum( | actual_dispatch | * gen_cost_per_MW)` |
| curtailment_cost | sum(curtailment_mw) |
Wasted renewable energy (MW) | ≤ 0 |
Example Implementation:
def compute_redispatch_cost(obs):
return np.abs(obs.actual_dispatch).sum()
def compute_curtailment_cost(obs):
return obs.curtailment_mw.sum()| Cost Metric | Formula | Description | Recommended Threshold |
|---|---|---|---|
| topology_changes | Changes in topo_vect from previous step |
Penalize frequent reconfigurations | ≤ 2 per episode |
| actions_on_cooldown | Elements with time_before_cooldown > 0 |
Operational constraints | — |
| Parameter | Value | Description |
|---|---|---|
n_line |
20 | Number of power lines |
n_gen |
6 | Number of generators |
n_load |
11 | Number of loads |
n_sub |
14 | Number of substations |
dim_topo |
57 | Total topology dimension |
The CostGrid2opEnvWrapper class provides configurable cost functions for constrained RL.
| Cost Function | Description | Output Range |
|---|---|---|
rho_max |
max(0, max(rho) - threshold) |
[0, ∞) |
rho_violations_count |
Count of lines with rho > threshold |
[0, n_line] |
rho_violations_sum |
sum(max(0, rho - threshold)) |
[0, ∞) |
rho_violations_quadratic |
sum(max(0, rho - threshold)^2) |
[0, ∞) |
disconnections |
Count of disconnected lines | [0, n_line] |
overflow_duration |
sum(timestep_overflow) |
[0, ∞) |
voltage_deviation |
Max voltage deviation from bounds | [0, ∞) |
curtailment |
Total curtailment (MW) | [0, ∞) |
redispatch |
Total abs redispatch (MW) | [0, ∞) |
from envs import CostGrid2opEnvWrapper
env_config = {
"env_name": "l2rpn_case14_sandbox",
"env_is_test": True,
"act_type": "discrete",
"obs_attr_to_keep": ["rho", "p_or"],
"act_attr_to_keep": ["set_line_status_simple"],
"cost_config": {
"costs": ["rho_violations_sum"],
"rho_threshold": 0.8
}
}
env = CostGrid2opEnvWrapper(
horizon=100,
gamma=0.99,
env_config=env_config
)
obs, info = env.reset()
obs, reward, done, info = env.step(action)
# Access costs
costs = info["costs"] # np.array of cost values
cost_names = info["cost_names"] # List of cost function names
cost_details = info["cost_details"] # Dict mapping name -> valueenv_config = {
"env_name": "l2rpn_case14_sandbox",
"cost_config": {
"costs": ["rho_max", "disconnections", "overflow_duration"],
"rho_threshold": 0.8,
"weights": [1.0, 0.5, 0.2] # Optional weights for combining
}
}from envs.grid2op_cost_env import make_cost_grid2op_env
env = make_cost_grid2op_env(
env_name="l2rpn_case14_sandbox",
horizon=100,
costs=["rho_violations_sum", "disconnections"],
rho_threshold=0.8
)# Run CPGPE with costs enabled
python run.py --alg cpgpe --pol nn_softmax \
--horizon 100 --ite 100 --batch 10 --costs 1 --cost_type mvTo use different cost functions, modify the cost_config in run.py:
# In run.py, for grid2op with costs:
"cost_config": {
"costs": ["rho_max", "disconnections"], # Multiple costs
"rho_threshold": 0.7, # More conservative threshold
"voltage_bounds": (0.95, 1.05),
"weights": [1.0, 2.0] # Weight disconnections more heavily
}# Environment
env_config = {
"env_name": "l2rpn_case14_sandbox",
"cost_config": {
"costs": ["rho_violations_sum"],
"rho_threshold": 0.8
}
}
# Algorithm (in run.py)
alg_parameters = {
"cost_type": "mv", # Mean-variance
"cost_param": np.array([0]), # Lambda for MV
"thresholds": np.array([0.5]), # Cost threshold
"lambda_init": np.array([0]),
"eta_init": 0.1
}# Environment with 2 cost constraints
env_config = {
"env_name": "l2rpn_case14_sandbox",
"cost_config": {
"costs": ["rho_max", "disconnections"],
"rho_threshold": 0.8,
"weights": [1.0, 1.0]
}
}
# Algorithm (adjust for 2 constraints)
alg_parameters = {
"cost_type": "mv",
"cost_param": np.array([0, 0]),
"thresholds": np.array([0.2, 1.0]), # rho_max < 0.2, disconnections < 1
"lambda_init": np.array([0, 0]),
"eta_init": 0.1
}{
"name": "Run CPGPE Grid2Op with Costs",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/run.py",
"args": [
"--alg", "cpgpe",
"--pol", "nn_softmax",
"--horizon", "100",
"--ite", "50",
"--batch", "10",
"--lr", "0.001",
"--costs", "1",
"--cost_type", "mv"
],
"console": "integratedTerminal",
"justMyCode": false,
"env": {"PYTHONPATH": "${workspaceFolder}"}
}- Grid2Op Documentation
- L2RPN Competition
- IEEE 14-bus test case (basis for l2rpn_case14_sandbox)