diff --git a/.gitignore b/.gitignore index f6c3b0be..bfcc7603 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ examples/logs/ /my_examples/ .vscode/settings.json .vscode/launch.json + +plots/ \ No newline at end of file diff --git a/README.md b/README.md index 008c4e40..8fa0842f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,6 @@ if __name__ == '__main__': env = gem.make("Finite-CC-PMSM-v0") # instantiate a discretely controlled PMSM env.reset() for _ in range(10000): - env.render() # visualize environment (states, references), rewards, done, _ =\ env.step(env.action_space.sample()) # pick random control actions if done: diff --git a/examples/classic_controllers/classic_controllers.py b/examples/classic_controllers/classic_controllers.py index 9a0e234a..e18b3f4b 100644 --- a/examples/classic_controllers/classic_controllers.py +++ b/examples/classic_controllers/classic_controllers.py @@ -1,4 +1,4 @@ -from gym.spaces import Discrete, Box, MultiDiscrete +from gymnasium.spaces import Discrete, Box, MultiDiscrete from gym_electric_motor.physical_systems import SynchronousMotorSystem, DcMotorSystem, DcSeriesMotor, \ DcExternallyExcitedMotor, DoublyFedInductionMotorSystem, SquirrelCageInductionMotorSystem from gym_electric_motor.reference_generators import MultipleReferenceGenerator, SwitchedReferenceGenerator @@ -347,27 +347,52 @@ def automated_gain(environment, stages, controller_type, _controllers, **control elif _controllers[controller_type][0] == CascadedController: for i in range(len(stages)): - if _controllers[stages_a[i]['controller_type']][1] == ContinuousController: - - if i == 0: - p_gain = mp['l'] / (environment.physical_system.tau * a) / u_a_lim * i_a_lim - i_gain = p_gain / (environment.physical_system.tau * a ** 2) - - if _controllers[stages_a[i]['controller_type']][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau - stages_a[i]['d_gain'] = stages_a[i].get('d_gain', d_gain) - - elif i == 1: - t_n = environment.physical_system.tau * a ** 2 - p_gain = environment.physical_system.mechanical_load.j_total / ( - a * t_n) / i_a_lim * omega_lim - i_gain = p_gain / (a * t_n) - if _controllers[stages_a[i]['controller_type']][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau - stages_a[i]['d_gain'] = stages_a[i].get('d_gain', d_gain) - - stages_a[i]['p_gain'] = stages_a[i].get('p_gain', p_gain) - stages_a[i]['i_gain'] = stages_a[i].get('i_gain', i_gain) + if type(stages_a[i]) is list: + if _controllers[stages_a[i][0]['controller_type']][1] == ContinuousController: #had to add [0] to make dict in list acessable + + if i == 0: + p_gain = mp['l'] / (environment.physical_system.tau * a) / u_a_lim * i_a_lim + i_gain = p_gain / (environment.physical_system.tau * a ** 2) + + if _controllers[stages_a[i][0]['controller_type']][2] == PIDController: + d_gain = p_gain * environment.physical_system.tau + stages_a[i][0]['d_gain'] = stages_a[i][0].get('d_gain', d_gain) + + elif i == 1: + t_n = environment.physical_system.tau * a ** 2 + p_gain = environment.physical_system.mechanical_load.j_total / ( + a * t_n) / i_a_lim * omega_lim + i_gain = p_gain / (a * t_n) + if _controllers[stages_a[i][0]['controller_type']][2] == PIDController: + d_gain = p_gain * environment.physical_system.tau + stages_a[i][0]['d_gain'] = stages_a[i][0].get('d_gain', d_gain) + + stages_a[i][0]['p_gain'] = stages_a[i][0].get('p_gain', p_gain)#? + stages_a[i][0]['i_gain'] = stages_a[i][0].get('i_gain', i_gain)#? + + elif type(stages_a[i]) is dict: + if _controllers[stages_a[i]['controller_type']][1] == ContinuousController: #had to add [0] to make dict in list acessable + + if i == 0: + p_gain = mp['l'] / (environment.physical_system.tau * a) / u_a_lim * i_a_lim + i_gain = p_gain / (environment.physical_system.tau * a ** 2) + + if _controllers[stages_a[i]['controller_type']][2] == PIDController: + d_gain = p_gain * environment.physical_system.tau + stages_a[i]['d_gain'] = stages_a[i].get('d_gain', d_gain) + + elif i == 1: + t_n = environment.physical_system.tau * a ** 2 + p_gain = environment.physical_system.mechanical_load.j_total / ( + a * t_n) / i_a_lim * omega_lim + i_gain = p_gain / (a * t_n) + if _controllers[stages_a[i]['controller_type']][2] == PIDController: + d_gain = p_gain * environment.physical_system.tau + stages_a[i]['d_gain'] = stages_a[i].get('d_gain', d_gain) + + stages_a[i]['p_gain'] = stages_a[i].get('p_gain', p_gain)#? + stages_a[i]['i_gain'] = stages_a[i].get('i_gain', i_gain)#? + stages = stages_a if not stages_e else [stages_a, stages_e] diff --git a/examples/classic_controllers/classic_controllers_dc_motor_example.py b/examples/classic_controllers/classic_controllers_dc_motor_example.py index d8767cc5..d0a12bbd 100644 --- a/examples/classic_controllers/classic_controllers_dc_motor_example.py +++ b/examples/classic_controllers/classic_controllers_dc_motor_example.py @@ -38,8 +38,7 @@ external_ref_plots = [ExternallyReferencedStatePlot(state) for state in states] # initialize the gym-electric-motor environment - env = gem.make(motor, visualization=MotorDashboard(additional_plots=external_ref_plots)) - + env = gem.make(motor, visualization=MotorDashboard(additional_plots=external_ref_plots), render_mode="figure_once") """ initialize the controller @@ -47,20 +46,19 @@ environment gym-electric-motor environment external_ref_plots (optional) plots of the environment, to plot all reference values stages (optional) structure of the controller - automated_gain (optional) if True (default), the controller will be tune automatically + automated_gain (optional) if True (default), the controller will be tuned automatically a (optional) tuning parameter of the symmetrical optimum (default: 4) """ + visualization = MotorDashboard(additional_plots=external_ref_plots) controller = Controller.make(env, external_ref_plots=external_ref_plots) - state, reference = env.reset() - + state, reference = env.reset(seed = None) # simulate the environment for i in range(10001): action = controller.control(state, reference) - env.render() - (state, reference), reward, done, _ = env.step(action) - if done: + (state, reference), reward, terminated, truncated, _ = env.step(action) + if terminated: env.reset() controller.reset() diff --git a/examples/classic_controllers/classic_controllers_ind_motor_example.py b/examples/classic_controllers/classic_controllers_ind_motor_example.py index 3908f10d..d026eb37 100644 --- a/examples/classic_controllers/classic_controllers_ind_motor_example.py +++ b/examples/classic_controllers/classic_controllers_ind_motor_example.py @@ -50,10 +50,9 @@ # simulate the environment for i in range(10001): - env.render() action = controller.control(state, reference) - (state, reference), reward, done, _ = env.step(action) - if done: + (state, reference), reward, terminated, truncated, _ = env.step(action) + if terminated: env.reset() controller.reset() env.close() diff --git a/examples/classic_controllers/classic_controllers_synch_motor_example.py b/examples/classic_controllers/classic_controllers_synch_motor_example.py index 3af8f8c8..045dc432 100644 --- a/examples/classic_controllers/classic_controllers_synch_motor_example.py +++ b/examples/classic_controllers/classic_controllers_synch_motor_example.py @@ -54,10 +54,9 @@ # simulate the environment for i in range(10001): - env.render() action = controller.control(state, reference) - (state, reference), reward, done, _ = env.step(action) - if done: + (state, reference), reward, terminated, truncated, _ = env.step(action) + if terminated: env.reset() controller.reset() diff --git a/examples/classic_controllers/controllers/cascaded_controller.py b/examples/classic_controllers/controllers/cascaded_controller.py index 680c47ab..e526060e 100644 --- a/examples/classic_controllers/controllers/cascaded_controller.py +++ b/examples/classic_controllers/controllers/cascaded_controller.py @@ -1,5 +1,5 @@ from .continuous_controller import ContinuousController -from gym.spaces import Box, Discrete, MultiDiscrete +from gymnasium.spaces import Box, Discrete, MultiDiscrete from gym_electric_motor.physical_systems import DcExternallyExcitedMotor from .plot_external_data import plot @@ -16,6 +16,7 @@ class CascadedController: def __init__(self, environment, stages, _controllers, visualization, ref_states, external_ref_plots=(), **controller_kwargs): + self.env = environment self.visualization = visualization self.action_space = environment.action_space self.state_space = environment.physical_system.state_space @@ -171,9 +172,10 @@ def control(self, state, reference): else: action = np.array([action, action_u_e], dtype='object') - # Plot the external references - plot(external_reference_plots=self.external_ref_plots, state_names=self.state_names, - visualization=self.visualization, external_data=self.get_plot_data()) + if self.env.render_mode != None: + # Plot the external references + plot(external_reference_plots=self.external_ref_plots, state_names=self.state_names, + visualization=self.visualization, external_data=self.get_plot_data()) return action diff --git a/examples/classic_controllers/controllers/cascaded_foc_controller.py b/examples/classic_controllers/controllers/cascaded_foc_controller.py index 4a525e86..80c78013 100644 --- a/examples/classic_controllers/controllers/cascaded_foc_controller.py +++ b/examples/classic_controllers/controllers/cascaded_foc_controller.py @@ -1,7 +1,7 @@ from .continuous_controller import ContinuousController from .torque_to_current_conversion import TorqueToCurrentConversion from .plot_external_data import plot -from gym.spaces import Box +from gymnasium.spaces import Box import numpy as np @@ -53,7 +53,7 @@ def __init__(self, environment, stages, _controllers, ref_states, external_ref_ self.mp = environment.physical_system.electrical_motor.motor_parameter self.psi_p = self.mp.get('psi_p', 0) - self.dead_time = 1.5 if environment.physical_system.converter._dead_time else 0.5 + self.dead_time = 0.5 self.decoupling = controller_kwargs.get('decoupling', True) self.ref_state_idx = [self.i_sq_idx, self.i_sd_idx] diff --git a/examples/classic_controllers/controllers/continuous_action_controller.py b/examples/classic_controllers/controllers/continuous_action_controller.py index 4412bbfb..25be55ac 100644 --- a/examples/classic_controllers/controllers/continuous_action_controller.py +++ b/examples/classic_controllers/controllers/continuous_action_controller.py @@ -1,4 +1,4 @@ -from gym.spaces import Box +from gymnasium.spaces import Box from gym_electric_motor.physical_systems import DcMotorSystem, DcExternallyExcitedMotor from .plot_external_data import plot import numpy as np diff --git a/examples/classic_controllers/controllers/dicrete_action_controller.py b/examples/classic_controllers/controllers/dicrete_action_controller.py index a7629b54..4785a192 100644 --- a/examples/classic_controllers/controllers/dicrete_action_controller.py +++ b/examples/classic_controllers/controllers/dicrete_action_controller.py @@ -1,5 +1,5 @@ from .plot_external_data import plot -from gym.spaces import Discrete, MultiDiscrete +from gymnasium.spaces import Discrete, MultiDiscrete from gym_electric_motor.physical_systems import DcMotorSystem, DcExternallyExcitedMotor import numpy as np diff --git a/examples/classic_controllers/controllers/discrete_controller.py b/examples/classic_controllers/controllers/discrete_controller.py index fcf44ce9..d17fbfdb 100644 --- a/examples/classic_controllers/controllers/discrete_controller.py +++ b/examples/classic_controllers/controllers/discrete_controller.py @@ -1,4 +1,4 @@ -from gym.spaces import Discrete, MultiDiscrete +from gymnasium.spaces import Discrete, MultiDiscrete class DiscreteController: diff --git a/examples/classic_controllers/controllers/foc_controller.py b/examples/classic_controllers/controllers/foc_controller.py index 3c0541fe..f0918c85 100644 --- a/examples/classic_controllers/controllers/foc_controller.py +++ b/examples/classic_controllers/controllers/foc_controller.py @@ -1,6 +1,6 @@ from .plot_external_data import plot from gym_electric_motor.physical_systems import SynchronousMotorSystem -from gym.spaces import Box +from gymnasium.spaces import Box import numpy as np diff --git a/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py b/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py index 48cfb1a8..b6ee8229 100644 --- a/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py +++ b/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py @@ -2,7 +2,7 @@ from .induction_motor_torque_to_current_conversion import InductionMotorTorqueToCurrentConversion from .flux_observer import FluxObserver from .plot_external_data import plot -from gym.spaces import Box +from gymnasium.spaces import Box import numpy as np diff --git a/examples/classic_controllers/controllers/induction_motor_foc.py b/examples/classic_controllers/controllers/induction_motor_foc.py index 53f7de56..699cd06e 100644 --- a/examples/classic_controllers/controllers/induction_motor_foc.py +++ b/examples/classic_controllers/controllers/induction_motor_foc.py @@ -1,6 +1,6 @@ from .flux_observer import FluxObserver from .plot_external_data import plot -from gym.spaces import Box +from gymnasium.spaces import Box import numpy as np diff --git a/examples/classic_controllers/controllers/torque_to_current_conversion.py b/examples/classic_controllers/controllers/torque_to_current_conversion.py index d0c0833f..54362614 100644 --- a/examples/classic_controllers/controllers/torque_to_current_conversion.py +++ b/examples/classic_controllers/controllers/torque_to_current_conversion.py @@ -10,12 +10,12 @@ class TorqueToCurrentConversion: This class represents the torque controller for cascaded control of synchronous motors. For low speeds only the current limitation of the motor is important. The current vector to set a desired torque is selected so that the amount of the current vector is minimum (Maximum Torque per Current). For higher speeds, the voltage limitation - of the synchronous motor or the actuator must also be taken into account. This is done by converting the + of the synchronous motor or the actuator must also be taken into account. This is terminated by converting the available voltage to a speed-dependent maximum flux. An additional modulation controller is used for the flux control. By limiting the flux and the maximum torque per flux (MTPF), an operating point for the flux and the - torque is obtained. This is then converted into a current operating point. The conversion can be done by + torque is obtained. This is then converted into a current operating point. The conversion can be terminated by different methods (parameter torque_control). On the one hand, maps can be determined in advance by - interpolation or analytically, or the analytical determination can be done online. + interpolation or analytically, or the analytical determination can be terminated online. For the visualization of the operating points, both for the current operating points as well as the flux and torque operating points, predefined plots are available (plot_torque: default True). Also the values of the modulation controller can be visualized (plot_modulation: default False). diff --git a/examples/classic_controllers/custom_classic_controllers_dc_motor_example.py b/examples/classic_controllers/custom_classic_controllers_dc_motor_example.py index 9805c669..c2aafa38 100644 --- a/examples/classic_controllers/custom_classic_controllers_dc_motor_example.py +++ b/examples/classic_controllers/custom_classic_controllers_dc_motor_example.py @@ -39,7 +39,7 @@ external_ref_plots = [ExternallyReferencedStatePlot(state) for state in states] # initialize the gym-electric-motor environment - env = gem.make(motor, visualization=MotorDashboard(additional_plots=external_ref_plots)) + env = gem.make(motor, visualization=MotorDashboard(additional_plots=external_ref_plots), render_mode = 'figure') """ initialize the controller @@ -74,9 +74,8 @@ # simulate the environment for i in range(10001): action = controller.control(state, reference) - env.render() - (state, reference), reward, done, _ = env.step(action) - if done: + (state, reference), reward, terminated, truncated, _ = env.step(action) + if terminated: env.reset() controller.reset() diff --git a/examples/classic_controllers/custom_classic_controllers_ind_motor_example.py b/examples/classic_controllers/custom_classic_controllers_ind_motor_example.py index a09b6835..d4d5a0f9 100644 --- a/examples/classic_controllers/custom_classic_controllers_ind_motor_example.py +++ b/examples/classic_controllers/custom_classic_controllers_ind_motor_example.py @@ -53,10 +53,9 @@ # simulate the environment for i in range(10001): - env.render() action = controller.control(state, reference) - (state, reference), reward, done, _ = env.step(action) - if done: + (state, reference), reward, terminated, truncated, _ = env.step(action) + if terminated: env.reset() controller.reset() env.close() diff --git a/examples/classic_controllers/custom_classic_controllers_synch_motor_example.py b/examples/classic_controllers/custom_classic_controllers_synch_motor_example.py index d9881a94..59bb2789 100644 --- a/examples/classic_controllers/custom_classic_controllers_synch_motor_example.py +++ b/examples/classic_controllers/custom_classic_controllers_synch_motor_example.py @@ -35,7 +35,8 @@ # initialize the gym-electric-motor environment env = gem.make(env_id, visualization=MotorDashboard(additional_plots=external_ref_plots), - motor=dict(limit_values=limit_values, nominal_values=nominal_values, motor_parameter=motor_parameter)) + motor=dict(limit_values=limit_values, nominal_values=nominal_values, motor_parameter=motor_parameter), + render_mode = 'figure') """ initialize the controller @@ -104,10 +105,9 @@ # simulate the environment for i in range(10001): - env.render() action = controller.control(state, reference) - (state, reference), reward, done, _ = env.step(action) - if done: + (state, reference), reward, terminated, truncated, _ = env.step(action) + if terminated: env.reset() controller.reset() diff --git a/examples/classic_controllers/external_plot.py b/examples/classic_controllers/external_plot.py index b28da770..679736c0 100644 --- a/examples/classic_controllers/external_plot.py +++ b/examples/classic_controllers/external_plot.py @@ -25,14 +25,13 @@ class ExternalPlot(TimePlot): >>> # setting the labels of the plots >>> external_plot.set_label({'y_label': 'y', 'state_label': '$state$', 'ref_label': '$reference$', ... 'add_label': ['$add_1$', '$add_2$']}) - >>> done = True + >>> terminated = True >>> for t in range(100000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() >>> data = [np.sin(t / 500), np.sin(t / 1000), np.sin(t / 1500), np.sin(t / 2000)] >>> external_plot.add_data(data) # passing the data to the external plot - >>> (state, reference), reward, done, _ = env.step([0, 0]) + >>> (state, reference), reward, terminated, truncated, _ = env.step([0, 0]) """ def __init__(self, referenced=False, additional_lines=0, min=0, max=1): @@ -111,7 +110,7 @@ def initialize(self, axis): # If the state is referenced plot also the reference line if self._referenced: self._reference_line, = self._axis.plot(self._x_data, self._reference_data, **self._ref_line_config, zorder=self.add_lines+1) - axis.lines = axis.lines[::-1] + #axis.lines = axis.lines[::-1] self._lines.append(self._reference_line) self._y_data = [self._state_data, self._reference_data] @@ -149,8 +148,8 @@ def set_label(self, labels): if 'add_label' in labels.keys(): self.add_labels = labels['add_label'] - def on_step_end(self, k, state, reference, reward, done): - super().on_step_end(k, state, reference, reward, done) + def on_step_end(self, k, state, reference, reward, terminated): + super().on_step_end(k, state, reference, reward, terminated) idx = self.data_idx self._x_data[idx] = self._t diff --git a/examples/classic_controllers/externally_referenced_state_plot.py b/examples/classic_controllers/externally_referenced_state_plot.py index d18a15f0..b0daf0ae 100644 --- a/examples/classic_controllers/externally_referenced_state_plot.py +++ b/examples/classic_controllers/externally_referenced_state_plot.py @@ -13,15 +13,14 @@ class ExternallyReferencedStatePlot(StatePlot): 'DqCont-SC-PMSM-v0', visualization=dict(additional_plots=(my_externally_referenced_plot,), ) - done = True + terminated = True for _ in range(10000): - if done: + if terminated: state, reference = env.reset() external_reference_value = my_external_isd_reference_generator.get_reference() my_externally_referenced_plot.external_reference(external_reference_value) - env.render() action = env.action_space.sample() - (state, reference), reward, done, _ = env.step(action) + (state, reference), reward, terminated, truncated, _ = env.step(action) """ def __init__(self, state): diff --git a/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py b/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py new file mode 100644 index 00000000..2e7b40d2 --- /dev/null +++ b/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py @@ -0,0 +1,87 @@ +from classic_controllers import Controller +from externally_referenced_state_plot import ExternallyReferencedStatePlot +import gym_electric_motor as gem +from gym_electric_motor.visualization import MotorDashboard +from gym_electric_motor.reference_generators import SinusoidalReferenceGenerator +import time + +if __name__ == '__main__': + + """ + motor type: 'PermExDc' Permanently Excited DC Motor + 'ExtExDc' Externally Excited MC Motor + 'SeriesDc' DC Series Motor + 'ShuntDc' DC Shunt Motor + + control type: 'SC' Speed Control + 'TC' Torque Control + 'CC' Current Control + + action_type: 'Cont' Continuous Action Space + 'Finite' Discrete Action Space + """ + + motor_type = 'PermExDc' + control_type = 'SC' + action_type = 'Cont' + + motor = action_type + '-' + control_type + '-' + motor_type + '-v0' + + if motor_type in ['PermExDc', 'SeriesDc']: + states = ['omega', 'torque', 'i', 'u'] + elif motor_type == 'ShuntDc': + states = ['omega', 'torque', 'i_a', 'i_e', 'u'] + elif motor_type == 'ExtExDc': + states = ['omega', 'torque', 'i_a', 'i_e', 'u_a', 'u_e'] + else: + raise KeyError(motor_type + ' is not available') + + # definition of the plotted variables + external_ref_plots = [ExternallyReferencedStatePlot(state) for state in states] + + # definition of the reference generator + + ref_generator = SinusoidalReferenceGenerator(amplitude_range= (1,1), + frequency_range= (5,5), + offset_range = (0,0), + episode_lengths = (10001, 10001)) + + # initialize the gym-electric-motor environment + env = gem.make(motor, + visualization=MotorDashboard(additional_plots=external_ref_plots), + scale_plots=True, + render_mode="figure", + reference_generator = ref_generator) + + env.metadata["filename_prefix"] = "integration-test" + env.metadata["filename_suffix"] = "" + env.metadata["save_figure_on_close"] = False + env.metadata["hold_figure_on_close"] = True + """ + initialize the controller + + Args: + environment gym-electric-motor environment + external_ref_plots (optional) plots of the environment, to plot all reference values + stages (optional) structure of the controller + automated_gain (optional) if True (default), the controller will be tuned automatically + a (optional) tuning parameter of the symmetrical optimum (default: 4) + + """ + controller = Controller.make(env, external_ref_plots=external_ref_plots) + + state, reference = env.reset(seed=1337) + # simulate the environment + for i in range(10001): + action = controller.control(state, reference) + #if i % 100 == 0: + # (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) + #else: + (state, reference), reward, terminated, truncated, _ = env.step(action) + + + if terminated: + env.reset() + controller.reset() + + env.close() \ No newline at end of file diff --git a/examples/environment_features/GEM_cookbook.ipynb b/examples/environment_features/GEM_cookbook.ipynb index 05ee8cd5..b832ad51 100644 --- a/examples/environment_features/GEM_cookbook.ipynb +++ b/examples/environment_features/GEM_cookbook.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -10,6 +11,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -50,6 +52,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -142,6 +145,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -149,6 +153,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -159,6 +164,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -169,29 +175,33 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Warning: Cannot change to a different GUI toolkit: widget. Using notebook instead.\n" + ] + }, + { + "data": { + "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.get_websocket_type = function () {\n if (typeof WebSocket !== 'undefined') {\n return WebSocket;\n } else if (typeof MozWebSocket !== 'undefined') {\n return MozWebSocket;\n } else {\n alert(\n 'Your browser does not have WebSocket support. ' +\n 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n 'Firefox 4 and 5 are also supported but you ' +\n 'have to enable WebSockets in about:config.'\n );\n }\n};\n\nmpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n this.id = figure_id;\n\n this.ws = websocket;\n\n this.supports_binary = this.ws.binaryType !== undefined;\n\n if (!this.supports_binary) {\n var warnings = document.getElementById('mpl-warnings');\n if (warnings) {\n warnings.style.display = 'block';\n warnings.textContent =\n 'This browser does not support binary websocket messages. ' +\n 'Performance may be slow.';\n }\n }\n\n this.imageObj = new Image();\n\n this.context = undefined;\n this.message = undefined;\n this.canvas = undefined;\n this.rubberband_canvas = undefined;\n this.rubberband_context = undefined;\n this.format_dropdown = undefined;\n\n this.image_mode = 'full';\n\n this.root = document.createElement('div');\n this.root.setAttribute('style', 'display: inline-block');\n this._root_extra_style(this.root);\n\n parent_element.appendChild(this.root);\n\n this._init_header(this);\n this._init_canvas(this);\n this._init_toolbar(this);\n\n var fig = this;\n\n this.waiting = false;\n\n this.ws.onopen = function () {\n fig.send_message('supports_binary', { value: fig.supports_binary });\n fig.send_message('send_image_mode', {});\n if (fig.ratio !== 1) {\n fig.send_message('set_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\n }\n fig.send_message('refresh', {});\n };\n\n this.imageObj.onload = function () {\n if (fig.image_mode === 'full') {\n // Full images could contain transparency (where diff images\n // almost always do), so we need to clear the canvas so that\n // there is no ghosting.\n fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n }\n fig.context.drawImage(fig.imageObj, 0, 0);\n };\n\n this.imageObj.onunload = function () {\n fig.ws.close();\n };\n\n this.ws.onmessage = this._make_on_message_function(this);\n\n this.ondownload = ondownload;\n};\n\nmpl.figure.prototype._init_header = function () {\n var titlebar = document.createElement('div');\n titlebar.classList =\n 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n var titletext = document.createElement('div');\n titletext.classList = 'ui-dialog-title';\n titletext.setAttribute(\n 'style',\n 'width: 100%; text-align: center; padding: 3px;'\n );\n titlebar.appendChild(titletext);\n this.root.appendChild(titlebar);\n this.header = titletext;\n};\n\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute('tabindex', '0');\n canvas_div.setAttribute(\n 'style',\n 'border: 1px solid #ddd;' +\n 'box-sizing: content-box;' +\n 'clear: both;' +\n 'min-height: 1px;' +\n 'min-width: 1px;' +\n 'outline: 0;' +\n 'overflow: hidden;' +\n 'position: relative;' +\n 'resize: both;' +\n 'z-index: 2;'\n );\n\n function on_keyboard_event_closure(name) {\n return function (event) {\n return fig.key_event(event, name);\n };\n }\n\n canvas_div.addEventListener(\n 'keydown',\n on_keyboard_event_closure('key_press')\n );\n canvas_div.addEventListener(\n 'keyup',\n on_keyboard_event_closure('key_release')\n );\n\n this._canvas_extra_style(canvas_div);\n this.root.appendChild(canvas_div);\n\n var canvas = (this.canvas = document.createElement('canvas'));\n canvas.classList.add('mpl-canvas');\n canvas.setAttribute(\n 'style',\n 'box-sizing: content-box;' +\n 'pointer-events: none;' +\n 'position: relative;' +\n 'z-index: 0;'\n );\n\n this.context = canvas.getContext('2d');\n\n var backingStore =\n this.context.backingStorePixelRatio ||\n this.context.webkitBackingStorePixelRatio ||\n this.context.mozBackingStorePixelRatio ||\n this.context.msBackingStorePixelRatio ||\n this.context.oBackingStorePixelRatio ||\n this.context.backingStorePixelRatio ||\n 1;\n\n this.ratio = (window.devicePixelRatio || 1) / backingStore;\n\n var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n 'canvas'\n ));\n rubberband_canvas.setAttribute(\n 'style',\n 'box-sizing: content-box;' +\n 'left: 0;' +\n 'pointer-events: none;' +\n 'position: absolute;' +\n 'top: 0;' +\n 'z-index: 1;'\n );\n\n // Apply a ponyfill if ResizeObserver is not implemented by browser.\n if (this.ResizeObserver === undefined) {\n if (window.ResizeObserver !== undefined) {\n this.ResizeObserver = window.ResizeObserver;\n } else {\n var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n this.ResizeObserver = obs.ResizeObserver;\n }\n }\n\n this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n var nentries = entries.length;\n for (var i = 0; i < nentries; i++) {\n var entry = entries[i];\n var width, height;\n if (entry.contentBoxSize) {\n if (entry.contentBoxSize instanceof Array) {\n // Chrome 84 implements new version of spec.\n width = entry.contentBoxSize[0].inlineSize;\n height = entry.contentBoxSize[0].blockSize;\n } else {\n // Firefox implements old version of spec.\n width = entry.contentBoxSize.inlineSize;\n height = entry.contentBoxSize.blockSize;\n }\n } else {\n // Chrome <84 implements even older version of spec.\n width = entry.contentRect.width;\n height = entry.contentRect.height;\n }\n\n // Keep the size of the canvas and rubber band canvas in sync with\n // the canvas container.\n if (entry.devicePixelContentBoxSize) {\n // Chrome 84 implements new version of spec.\n canvas.setAttribute(\n 'width',\n entry.devicePixelContentBoxSize[0].inlineSize\n );\n canvas.setAttribute(\n 'height',\n entry.devicePixelContentBoxSize[0].blockSize\n );\n } else {\n canvas.setAttribute('width', width * fig.ratio);\n canvas.setAttribute('height', height * fig.ratio);\n }\n /* This rescales the canvas back to display pixels, so that it\n * appears correct on HiDPI screens. */\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n\n rubberband_canvas.setAttribute('width', width);\n rubberband_canvas.setAttribute('height', height);\n\n // And update the size in Python. We ignore the initial 0/0 size\n // that occurs as the element is placed into the DOM, which should\n // otherwise not happen due to the minimum size styling.\n if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n fig.request_resize(width, height);\n }\n }\n });\n this.resizeObserverInstance.observe(canvas_div);\n\n function on_mouse_event_closure(name) {\n /* User Agent sniffing is bad, but WebKit is busted:\n * https://bugs.webkit.org/show_bug.cgi?id=144526\n * https://bugs.webkit.org/show_bug.cgi?id=181818\n * The worst that happens here is that they get an extra browser\n * selection when dragging, if this check fails to catch them.\n */\n var UA = navigator.userAgent;\n var isWebKit = /AppleWebKit/.test(UA) && !/Chrome/.test(UA);\n if(isWebKit) {\n return function (event) {\n /* This prevents the web browser from automatically changing to\n * the text insertion cursor when the button is pressed. We\n * want to control all of the cursor setting manually through\n * the 'cursor' event from matplotlib */\n event.preventDefault()\n return fig.mouse_event(event, name);\n };\n } else {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n }\n\n canvas_div.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n canvas_div.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n canvas_div.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n canvas_div.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n canvas_div.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n canvas_div.addEventListener(\n 'mouseleave',\n on_mouse_event_closure('figure_leave')\n );\n\n canvas_div.addEventListener('wheel', function (event) {\n if (event.deltaY < 0) {\n event.step = 1;\n } else {\n event.step = -1;\n }\n on_mouse_event_closure('scroll')(event);\n });\n\n canvas_div.appendChild(canvas);\n canvas_div.appendChild(rubberband_canvas);\n\n this.rubberband_context = rubberband_canvas.getContext('2d');\n this.rubberband_context.strokeStyle = '#000000';\n\n this._resize_canvas = function (width, height, forward) {\n if (forward) {\n canvas_div.style.width = width + 'px';\n canvas_div.style.height = height + 'px';\n }\n };\n\n // Disable right mouse context menu.\n canvas_div.addEventListener('contextmenu', function (_e) {\n event.preventDefault();\n return false;\n });\n\n function set_focus() {\n canvas.focus();\n canvas_div.focus();\n }\n\n window.setTimeout(set_focus, 100);\n};\n\nmpl.figure.prototype._init_toolbar = function () {\n var fig = this;\n\n var toolbar = document.createElement('div');\n toolbar.classList = 'mpl-toolbar';\n this.root.appendChild(toolbar);\n\n function on_click_closure(name) {\n return function (_event) {\n return fig.toolbar_button_onclick(name);\n };\n }\n\n function on_mouseover_closure(tooltip) {\n return function (event) {\n if (!event.currentTarget.disabled) {\n return fig.toolbar_button_onmouseover(tooltip);\n }\n };\n }\n\n fig.buttons = {};\n var buttonGroup = document.createElement('div');\n buttonGroup.classList = 'mpl-button-group';\n for (var toolbar_ind in mpl.toolbar_items) {\n var name = mpl.toolbar_items[toolbar_ind][0];\n var tooltip = mpl.toolbar_items[toolbar_ind][1];\n var image = mpl.toolbar_items[toolbar_ind][2];\n var method_name = mpl.toolbar_items[toolbar_ind][3];\n\n if (!name) {\n /* Instead of a spacer, we start a new button group. */\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n buttonGroup = document.createElement('div');\n buttonGroup.classList = 'mpl-button-group';\n continue;\n }\n\n var button = (fig.buttons[name] = document.createElement('button'));\n button.classList = 'mpl-widget';\n button.setAttribute('role', 'button');\n button.setAttribute('aria-disabled', 'false');\n button.addEventListener('click', on_click_closure(method_name));\n button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n\n var icon_img = document.createElement('img');\n icon_img.src = '_images/' + image + '.png';\n icon_img.srcset = '_images/' + image + '_large.png 2x';\n icon_img.alt = tooltip;\n button.appendChild(icon_img);\n\n buttonGroup.appendChild(button);\n }\n\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n\n var fmt_picker = document.createElement('select');\n fmt_picker.classList = 'mpl-widget';\n toolbar.appendChild(fmt_picker);\n this.format_dropdown = fmt_picker;\n\n for (var ind in mpl.extensions) {\n var fmt = mpl.extensions[ind];\n var option = document.createElement('option');\n option.selected = fmt === mpl.default_extension;\n option.innerHTML = fmt;\n fmt_picker.appendChild(option);\n }\n\n var status_bar = document.createElement('span');\n status_bar.classList = 'mpl-message';\n toolbar.appendChild(status_bar);\n this.message = status_bar;\n};\n\nmpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n // which will in turn request a refresh of the image.\n this.send_message('resize', { width: x_pixels, height: y_pixels });\n};\n\nmpl.figure.prototype.send_message = function (type, properties) {\n properties['type'] = type;\n properties['figure_id'] = this.id;\n this.ws.send(JSON.stringify(properties));\n};\n\nmpl.figure.prototype.send_draw_message = function () {\n if (!this.waiting) {\n this.waiting = true;\n this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n }\n};\n\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n var format_dropdown = fig.format_dropdown;\n var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n fig.ondownload(fig, format);\n};\n\nmpl.figure.prototype.handle_resize = function (fig, msg) {\n var size = msg['size'];\n if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n fig._resize_canvas(size[0], size[1], msg['forward']);\n fig.send_message('refresh', {});\n }\n};\n\nmpl.figure.prototype.handle_rubberband = function (fig, msg) {\n var x0 = msg['x0'] / fig.ratio;\n var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n var x1 = msg['x1'] / fig.ratio;\n var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n x0 = Math.floor(x0) + 0.5;\n y0 = Math.floor(y0) + 0.5;\n x1 = Math.floor(x1) + 0.5;\n y1 = Math.floor(y1) + 0.5;\n var min_x = Math.min(x0, x1);\n var min_y = Math.min(y0, y1);\n var width = Math.abs(x1 - x0);\n var height = Math.abs(y1 - y0);\n\n fig.rubberband_context.clearRect(\n 0,\n 0,\n fig.canvas.width / fig.ratio,\n fig.canvas.height / fig.ratio\n );\n\n fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n};\n\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.canvas_div.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n for (var key in msg) {\n if (!(key in fig.buttons)) {\n continue;\n }\n fig.buttons[key].disabled = !msg[key];\n fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n }\n};\n\nmpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n if (msg['mode'] === 'PAN') {\n fig.buttons['Pan'].classList.add('active');\n fig.buttons['Zoom'].classList.remove('active');\n } else if (msg['mode'] === 'ZOOM') {\n fig.buttons['Pan'].classList.remove('active');\n fig.buttons['Zoom'].classList.add('active');\n } else {\n fig.buttons['Pan'].classList.remove('active');\n fig.buttons['Zoom'].classList.remove('active');\n }\n};\n\nmpl.figure.prototype.updated_canvas_event = function () {\n // Called whenever the canvas gets updated.\n this.send_message('ack', {});\n};\n\n// A function to construct a web socket function for onmessage handling.\n// Called in the figure constructor.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\nfunction getModifiers(event) {\n var mods = [];\n if (event.ctrlKey) {\n mods.push('ctrl');\n }\n if (event.altKey) {\n mods.push('alt');\n }\n if (event.shiftKey) {\n mods.push('shift');\n }\n if (event.metaKey) {\n mods.push('meta');\n }\n return mods;\n}\n\n/*\n * return a copy of an object with only non-object keys\n * we need this to avoid circular references\n * https://stackoverflow.com/a/24161582/3208463\n */\nfunction simpleKeys(original) {\n return Object.keys(original).reduce(function (obj, key) {\n if (typeof original[key] !== 'object') {\n obj[key] = original[key];\n }\n return obj;\n }, {});\n}\n\nmpl.figure.prototype.mouse_event = function (event, name) {\n if (name === 'button_press') {\n this.canvas.focus();\n this.canvas_div.focus();\n }\n\n // from https://stackoverflow.com/q/1114465\n var boundingRect = this.canvas.getBoundingClientRect();\n var x = (event.clientX - boundingRect.left) * this.ratio;\n var y = (event.clientY - boundingRect.top) * this.ratio;\n\n this.send_message(name, {\n x: x,\n y: y,\n button: event.button,\n step: event.step,\n modifiers: getModifiers(event),\n guiEvent: simpleKeys(event),\n });\n\n return false;\n};\n\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.figure.prototype.toolbar_button_onclick = function (name) {\n if (name === 'download') {\n this.handle_save(this, null);\n } else {\n this.send_message('toolbar_button', { name: name });\n }\n};\n\nmpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n this.message.textContent = tooltip;\n};\n\n///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n// prettier-ignore\nvar _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.mpl_figure_comm = function (comm, msg) {\n // This is the function which gets called when the mpl process\n // starts-up an IPython Comm through the \"matplotlib\" channel.\n\n var id = msg.content.data.id;\n // Get hold of the div created by the display call when the Comm\n // socket was opened in Python.\n var element = document.getElementById(id);\n var ws_proxy = comm_websocket_adapter(comm);\n\n function ondownload(figure, _format) {\n window.open(figure.canvas.toDataURL());\n }\n\n var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n\n // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n // web socket which is closed, not our websocket->open comm proxy.\n ws_proxy.onopen();\n\n fig.parent_element = element;\n fig.cell_info = mpl.find_output_cell(\"
\");\n if (!fig.cell_info) {\n console.error('Failed to find cell for figure', id, fig);\n return;\n }\n fig.cell_info[0].output_area.element.on(\n 'cleared',\n { fig: fig },\n fig._remove_fig_handler\n );\n};\n\nmpl.figure.prototype.handle_close = function (fig, msg) {\n var width = fig.canvas.width / fig.ratio;\n fig.cell_info[0].output_area.element.off(\n 'cleared',\n fig._remove_fig_handler\n );\n fig.resizeObserverInstance.unobserve(fig.canvas_div);\n\n // Update the output cell to use the data from the current canvas.\n fig.push_to_output();\n var dataURL = fig.canvas.toDataURL();\n // Re-enable the keyboard manager in IPython - without this line, in FF,\n // the notebook keyboard shortcuts fail.\n IPython.keyboard_manager.enable();\n fig.parent_element.innerHTML =\n '';\n fig.close_ws(fig, msg);\n};\n\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.figure.prototype.push_to_output = function (_remove_interactive) {\n // Turn the data on the canvas into data in the output cell.\n var width = this.canvas.width / this.ratio;\n var dataURL = this.canvas.toDataURL();\n this.cell_info[1]['text/html'] =\n '';\n};\n\nmpl.figure.prototype.updated_canvas_event = function () {\n // Tell IPython that the notebook contents must change.\n IPython.notebook.set_dirty(true);\n this.send_message('ack', {});\n var fig = this;\n // Wait a second, then push the new image to the DOM so\n // that it is saved nicely (might be nice to debounce this).\n setTimeout(function () {\n fig.push_to_output();\n }, 1000);\n};\n\nmpl.figure.prototype._init_toolbar = function () {\n var fig = this;\n\n var toolbar = document.createElement('div');\n toolbar.classList = 'btn-toolbar';\n this.root.appendChild(toolbar);\n\n function on_click_closure(name) {\n return function (_event) {\n return fig.toolbar_button_onclick(name);\n };\n }\n\n function on_mouseover_closure(tooltip) {\n return function (event) {\n if (!event.currentTarget.disabled) {\n return fig.toolbar_button_onmouseover(tooltip);\n }\n };\n }\n\n fig.buttons = {};\n var buttonGroup = document.createElement('div');\n buttonGroup.classList = 'btn-group';\n var button;\n for (var toolbar_ind in mpl.toolbar_items) {\n var name = mpl.toolbar_items[toolbar_ind][0];\n var tooltip = mpl.toolbar_items[toolbar_ind][1];\n var image = mpl.toolbar_items[toolbar_ind][2];\n var method_name = mpl.toolbar_items[toolbar_ind][3];\n\n if (!name) {\n /* Instead of a spacer, we start a new button group. */\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n buttonGroup = document.createElement('div');\n buttonGroup.classList = 'btn-group';\n continue;\n }\n\n button = fig.buttons[name] = document.createElement('button');\n button.classList = 'btn btn-default';\n button.href = '#';\n button.title = name;\n button.innerHTML = '';\n button.addEventListener('click', on_click_closure(method_name));\n button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n buttonGroup.appendChild(button);\n }\n\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n\n // Add the status bar.\n var status_bar = document.createElement('span');\n status_bar.classList = 'mpl-message pull-right';\n toolbar.appendChild(status_bar);\n this.message = status_bar;\n\n // Add the close button to the window.\n var buttongrp = document.createElement('div');\n buttongrp.classList = 'btn-group inline pull-right';\n button = document.createElement('button');\n button.classList = 'btn btn-mini btn-primary';\n button.href = '#';\n button.title = 'Stop Interaction';\n button.innerHTML = '';\n button.addEventListener('click', function (_evt) {\n fig.handle_close(fig, {});\n });\n button.addEventListener(\n 'mouseover',\n on_mouseover_closure('Stop Interaction')\n );\n buttongrp.appendChild(button);\n var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n titlebar.insertBefore(buttongrp, titlebar.firstChild);\n};\n\nmpl.figure.prototype._remove_fig_handler = function (event) {\n var fig = event.data.fig;\n if (event.target !== this) {\n // Ignore bubbled events from children.\n return;\n }\n fig.close_ws(fig, {});\n};\n\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.figure.prototype._canvas_extra_style = function (el) {\n // this is important to make the div 'focusable\n el.setAttribute('tabindex', 0);\n // reach out to IPython and tell the keyboard manager to turn it's self\n // off when our div gets focus\n\n // location in version 3\n if (IPython.notebook.keyboard_manager) {\n IPython.notebook.keyboard_manager.register_events(el);\n } else {\n // location in version 2\n IPython.keyboard_manager.register_events(el);\n }\n};\n\nmpl.figure.prototype._key_event_extra = function (event, _name) {\n // Check for shift+enter\n if (event.shiftKey && event.which === 13) {\n this.canvas_div.blur();\n // select the cell after this one\n var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n IPython.notebook.select(index + 1);\n }\n};\n\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.find_output_cell = function (html_output) {\n // Return the cell and output element which can be found *uniquely* in the notebook.\n // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n // IPython event is triggered only after the cells have been serialised, which for\n // our purposes (turning an active figure into a static one), is too late.\n var cells = IPython.notebook.get_cells();\n var ncells = cells.length;\n for (var i = 0; i < ncells; i++) {\n var cell = cells[i];\n if (cell.cell_type === 'code') {\n for (var j = 0; j < cell.output_area.outputs.length; j++) {\n var data = cell.output_area.outputs[j];\n if (data.data) {\n // IPython >= 3 moved mimebundle to data attribute of output\n data = data.data;\n }\n if (data['text/html'] === html_output) {\n return [cell, data, j];\n }\n }\n }\n }\n};\n\n// Register the function which deals with the matplotlib target/channel.\n// The kernel may be null if the page has been refreshed.\nif (IPython.notebook.kernel !== null) {\n IPython.notebook.kernel.comm_manager.register_target(\n 'matplotlib',\n mpl.mpl_figure_comm\n );\n}\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9c613fb7abf54461a575817c30e50706", - "version_major": 2, - "version_minor": 0 - }, - "image/png": "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F19UbGysJMfhVyNHjpQknT9/Xu+//76mTZumbt26udTfr18/LViwQI888kilHgcAAAA4+OQekMTERG3dulW33367srKy1KhRI61cudLbZVUfVqvj8KqiS9EQUTJWdALVlXKr4PArq9WqxMREBQYG6sSJExo/frx2796tqKgopaWlKTk5Wa1atZLk+BjmkgNIs2bN1KxZM1mtVrVo0cL5RY+tWrVSVlaWM2/69Olq06aNOnXqpMOHD+vw4cOSpMmTJ+v//b//p3Pnzmno0KGSpJycHG3ZskV33323JMfJ6CdOnNBDDz2kli1bulz69++v1KK9QgAAAKg0nxxABg8erHPnzmngwIG65ZZbdO211+qaa67xdlmogMzMTDVv3lwhISEKDw/Xrl271LZtWw0cOFBpaWnauXOny/khW7dudRlASn5KWEBAgPN6QECACgsLJTm+N+XLL7/UV1995by/oo83zsnJUUFBgfOLIiVp2bJlSkpKUkxMjCTHHreUlJRSP2mtf//+2rJli3bs2FG1DwwAAICf8skBZPfu3YqIiNCePXv0xz/+UZ9//rkeffRRb5eFChg7dqx27twpyXFyeXh4uIYOHark5GTl5+crOjraeX7PqlWrtHr16nJ9YpbkOMyrTp06Cg0N1fbt25WZmem8bcSIEZoxY4bat2+vadOmSbr406+WLVumTz/9tNR1JyUlyRhT7poAAABQOp88ByQoKEjGGM2bN0/PPfechgwZonbt2nm7LFTS5MmTtWnTJoWFhalTp04aMGCAjh8/rp49e+qmm25Sy5YtFR8fr6uvvrpc6+3Ro4dmzZqlhIQEJSYmOp8rqampqlu3rnr16qUuXbooKSlJffv21W233abBgwe7YxMBAABwBT45gDzyyCO6+eabdfLkSb300kuSpF9//dW7RaHS3nvvvYtidevW1datW0vNb9SokbZs2eK8/s9//tP586233qrly5dLchym9dlnn120fMuWLfXQQw9JkmrXrq3du3dLksaPH1/xjQAAAECleO0QrKFDh+rs2bOS5DxhuMiIESO0du1a7dy5U7Vr19aBAwd06623eqNMAAAAAFXIa3tAateurfz8fNWqVUuNGjXS1VdfrdatW6tt27Zq06aNbrrpJiUkJEiSmjZtqvnz53urVAAAAABVxGsDyOzZs50/Hzx4UJmZmc4TiJcu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y5frxIkTeuihhy7a09G/f3+lpqYygAAAAPgwTkKHW2VmZqp58+YKCQlReHi4du3apbZt22rgwIFKS0vTzp071aZNG5f8oj0gy5YtU1JSkmJiYpy3p6amKiUlpdTDrPr3768tW7Zox44d7t8wAAAAVAh7QOBWY8eO1dixYyVJ+/fv1w033KChQ4cqIyND+fn5io6O1r59+yRJK1as0Jo1a5wnl5f26VfLli275H0lJSXxUbwAAAA+jgEEHjN58mRt2rRJYWFh6tSpkwYMGKDjx4/rrrvuUps2bdSnTx81bdpUtWrVkiTddtttGjx4sJerBgAAQFViAIHHvPfeexfF6tatqy1btkiSvvrqK+3du9d52/jx4z1WGwAAADyDc0AkTZkyRe3bt1d4eLjq1q2rfv36OQ8LKtKlSxdZLBaXy4UnOx8+fFi9evVSWFiY6tatq3Hjxun8+ar5NCp/sGPHjkp9YSEAAAB8H3tAJK1bt05jxoxR+/btdf78eU2YMEHdunXTnj17VLt2bWfeiBEj9Morrzivh4WFOX8uLCxUr169FBsbq40bN+ro0aMaNmyYgoKC9Je//MWj21NdjRgxwtslAAAAwM0YQCR99tlnLtfnz5+vunXrauvWrercubMzHhYWptjY2FLXsWrVKu3Zs0erV69WvXr11LZtW02aNEnPPvusXnrpJQUHB7t1GwAAAIDqgEOwSpGbmytJio52/fbvf/zjH4qJiVHLli31/PPP68yZM87bMjIy1KpVK9WrV88Z6969u/Ly8rR7927PFA4AAAD4OPaAXMBut+uJJ57Qb37zG7Vs2dIZv/feexUfH6+4uDjt2LFDzz77rPbt26ePP/5YkpSdne0yfEhyXs/Ozi71vvLz85Wfn++8npeXJ0my2Wyy2WwuuTabTcYY2e122e32ym8oqozdbpcxRjabTVartczLFfX4wl6jZqLf/oV++xf67V/oc+UxgFxgzJgx2rVrlzZs2OASHzlypPPnVq1aqX79+rrzzjv13XffqUmTJhW6rylTpujll1++KL527VqX80skKTAwULGxsTp9+rQKCgoqdH9wj4KCAp09e1br16+v0IcOpKenu6Eq+Cr67V/ot3+h3/6h5BEwqBgGkBLGjh2r5cuXa/369WrQoMFlczt06CBJOnDggJo0aaLY2Fht3rzZJefYsWOSdMnzRp5//nk99dRTzut5eXlq2LCh7rjjDtWpU8cl99y5c/rhhx901VVXKTQ0tNzbBvc5d+6catWqpc6dO5erNzabTenp6eratauCgoLcWCF8Af32L/Tbv9Bv/1J0xAoqjgFEkjFGjz76qD755BN9/vnnaty48RWX2b59uySpfv36kqSOHTvqz3/+s3JyclS3bl1Jjr+EREREKCEhodR1hISEKCQk5KJ4UFDQRW9ghYWFslgsCggIUEAAp+74koCAAFksllL7VhYVXQ7VE/32L/Tbv9Bv/0CPK48BRI7Drj788EMtWbJE4eHhznM2IiMjVatWLX333Xf68MMPddddd6lOnTrasWOHnnzySXXu3Nn5vRXdunVTQkKChg4dqqlTpyo7O1svvPCCxowZU+qQAQAAAPgj/pQuadasWcrNzVWXLl1Uv35952XRokWSpODgYK1evVrdunVT8+bN9fTTT6t///5atmyZcx1Wq1XLly+X1WpVx44dNWTIEA0bNszle0MAAAAAf8ceEDkOwbqchg0bat26dVdcT3x8vFasWFFVZQEAAAA1DntAAAAAAHgMAwgAAAAAj2EAgc8rOkTupZdecrkOAACA6odzQODzZs2apcDAQP3666967rnn1LNnTyUnJ3u7LAAAAFQAe0DgEaNGjdJ9991XoWX/8Ic/KDc3V//3f/+n3r17M3wAAABUYwwg8IgpU6Zozpw5FVp29uzZioyM1GOPPaZly5bpiy++KDXvgQce0AsvvOASy8jIkNVqVa9evSp03wAAAKhaDCDwiOjoaNWuXbtCy44aNUojR45U7dq19eqrr+q22267KKewsFDLly9Xnz59XOKpqal69NFHtX79eh05cqRC9w8AAICqwwACt8vKypLFYlFWVlaFlrdYLJKKT0Ivul7Sxo0bFRQUpPbt2ztjp0+f1qJFizR69Gj16tVL8+fPr9D9AwAAoOowgMDtMjMzFRUVpUaNGrntPpYuXarevXu7DCeLFy9W8+bN1axZMw0ZMkRz587lE7QAAAC8jE/BqmkOb5JWvyzln6qa9YVGSHe+KF13a4VXsX37drVu3bpq6rmEJUuWaPr06S6x1NRUDRkyRJLUo0cP5ebmat26derSpYtbawEAAMClMYDUNBtnSIc3Vv06KzGAZGZmqm3btlVXzwX27t2rI0eO6M4773TG9u3bp82bN+uTTz6R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eOABb5fmddHR0d4u4SKFhYVavny5Pv30U2csNTVVjz76qFJTU3XkyBHFxcV5sUIAAICax6f2gERGRmrfvn3O63fddZeWLVumpKQkPfzww16srGwGDRqk119/XS+++KLatm2r7du367PPPrvoxHR/k5WVJYvFoqysLG+X4mLjxo0KCgpS+/btJUmnT5/WokWLNHr0aPXq1Uvz58/3boEAAAA1kE/tAXnnnXc0cOBAJScnq02bNvrmm28UGOhTJV7R2LFjNXbsWG+X4VMyMzMVFRWlRo0aebsUF0uXLlXv3r1lsVgkSYsXL1bz5s3VrFkzDRkyRE888YSef/555+0AAACoPJ/aA5KYmKj//Oc/uu2225SVlaVrr71WK1as8HZZqKTt27erdevW3i7jIkuWLFGfPn2c11NTUzVkyBBJUo8ePZSbm6t169Z5qzwAAIAayacGkMGDB+vcuXMaOHCgbrnlFl177bW65pprvF1W9VNYKNlsxZeiLy4sGSv6Ep0r5RYWVrqczMxMtW3bttLrqUp79+7VkSNHdOedd0qS9u3bp82bN2vw4MGSHN+7MmjQIKWmpnqzTAAAgBrHpwaQ3bt3KyIiQnv27NEf//hHff7553r00Ue9XVb1M2mSFBxcfFmwwBEPCyuO3XCDI/bGG665Rb9wX3ON4/qkSZUuZ/v27WrTpo0k6d1339XNN9+sli1batCgQZIcff/Nb36jxMREPfnkk86hICsrS23atNF9992nG264QaNHj1ZaWpo6dOigli1bav/+/c77uPvuu9WuXTu1bNnS+VG/GRkZSkpK0vnz53Xs2DHdcMMNys7OluQ4/Kpr167O7+1ITU3V+fPnFRcXp8DAQAUGBmrWrFn617/+pdzc3Eo/BgAAAHDwqRMsgoKCZIzRvHnz9Nxzz2nIkCFq166dt8uqfv70J+mPfyy+brU6/i3tmzufekp64omLc3/+2fFvJb9zJC8vT1lZWWrbtq1OnDiht99+W1u3bpXVatXJkyeVn5+vwYMHa+HChUpISFC/fv1cDtfau3evFi9erKZNm6ply5a66qqr9NVXX+mdd97RzJkz9dZbb0mS3n//fUVHR+vXX39V+/btdc8996hjx47q3LmzXnvtNX399dd68cUXnd/JsmTJEo0cOVKSdP78eb3//vuaNm2aunXr5lJ/v379tGDBAj3yyCOV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AFTDBpAPPvhAKSkpCgsL02OPPabHHntMtWrV0p133qkPP/zQ2+UBAAAAfq9GnQPy5z//WVOnTtWTTz7pjD322GN64403NGnSJN17771erA4AAABAjdoD8v3336t3794Xxfv06aODBw96oSIAAAAAJdWoAaRhw4Zas2bNRfHVq1erYcOGXqgIAAAAQEk16hCsp59+Wo899pi2b9+uTp06SZK+/PJLzZ8/X2+99ZaXqwMAAABQowaQ0aNHKzY2VtOmTdPixYslSS1atNCiRYvUt29fL1cHAAAAoEYNIJL0u9/9Tr/73e+8XQYAAACAUtSoc0AAAAAA+LZqvwckOjpa3377rWJiYnT11VfLYrFcMveXX37xYGUAAAAALlTtB5Dp06crPDzc+fPlBhAAAAAA3lXtB5Dhw4c7f77//vu9VwgAAACAK6pR54BYrVbl5ORcFP/vf/8rq9XqhYoAAAAAlFSjBhBjTKnx/Px8BQcHe7gaAAAAABeq9odgSdL//d//SZIsFov+/ve/66qrrnLeVlhYqPXr16t58+beKg8AAADA/9SIAWT69OmSHHtAZs+e7XK4VXBwsBo1aqTZs2d7qzwAAAAA/1MjBpCDBw9Kku644w59/PHHuvrqq71cEQAAAIDS1IgBpMjatWu9XQIAAACAy6hRJ6H3799fr7322kXxqVOnasCAAV6oCAAAAEBJNWoAWb9+ve66666L4j179tT69eu9UBEAAACAkmrUAHL69OlSP243KChIeXl5XqgIAAAAQEk1agBp1aqVFi1adFF84cKFSkhI8EJFAAAAAEqqUSeh/+lPf9Lvf/97fffdd/rtb38rSVqzZo0WLFigjz76qMzrmTJlij7++GN98803qlWrljp16qTXXntNzZo1u+Qy8+fP1wMPPOASCwkJ0blz5yq2MQAAAEANVKMGkN69eystLU1/+ctf9M9//lO1atVS69attXr1aiUnJ5d5PevWrdOYMWPUvn17nT9/XhMmTFC3bt20Z88e1a5d+5LLRUREaN++fc7rFoulUtsDAAAA1DQ1agCRpF69eqlXr14XxXft2qWWLVuWaR2fffaZy/X58+erbt262rp1qzp37nzJ5SwWi2JjY8tXMAAAAOBHatwAUtKpU6e0YMEC/f3vf9fWrVtVWFhYofXk5uZKkqKjoy+bd/r0acXHx8tut+vmm2/W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", "text/html": [ - "\n", - "
\n", - "
\n", - " Figure\n", - "
\n", - " \n", - "
\n", - " " + "
" ], "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + "" ] }, "metadata": {}, @@ -211,27 +221,28 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ - "done = True\n", + "terminated = True\n", "\n", "for _ in range(10000):\n", - " if done:\n", + " if terminated:\n", " # Reset the environment\n", " # This is required initally or after an episode end due to a constraint violation in the env.\n", " state, references = env.reset()\n", - " # visualize environment. Red vertical lines indicate a constraint violation and therefore, a reset environment.\n", + " # Visualization of environment: Red vertical lines indicate a constraint violation and therefore, a reset environment.\n", " # Blue vertical lines indicate an additional reset by the user which is not due to a terminated episode.\n", - " env.render() \n", + " \n", " # pick random control actions\n", " action = env.action_space.sample()\n", " # Execute one control cycle on the environment\n", - " (states, references), rewards, done, _ = env.step(action) " + " (states, references), rewards, terminated, truncated, _ = env.step(action) " ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -254,6 +265,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -261,6 +273,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -284,6 +297,7 @@ "* state_filter(list(str))\n", "* callbacks(list(Callback))\n", "* physical_system_wrappers(iterable(PhysicalSystemWrapper))\n", + "* render_mode(str)\n", "\n", "#### Environment-arg type:\n", "The `env-arg` type is a short notation for all parameters that can be passed in three different ways to override the default behavior. Exemplary, it is shown how to change the reference generator of an environment in three different ways:\n", @@ -310,6 +324,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -339,6 +354,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -389,7 +405,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -417,6 +433,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -431,7 +448,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -439,6 +456,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -453,7 +471,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -465,6 +483,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -486,7 +505,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -501,6 +520,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -522,7 +542,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -566,6 +586,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -583,7 +604,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -597,6 +618,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -612,7 +634,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -623,6 +645,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -650,7 +673,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -682,6 +705,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -697,7 +721,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -717,6 +741,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -734,11 +759,11 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ - "import gym\n", + "import gymnasium as gym\n", "import numpy as np\n", "\n", "from gym_electric_motor.physical_system_wrappers import PhysicalSystemWrapper\n", @@ -809,7 +834,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -817,6 +842,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -831,7 +857,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -851,7 +877,7 @@ " load=load,\n", " reward_function=rf,\n", " tau=tau,\n", - " supply=supply,\n", + " #supply=supply,\n", " reference_generator=rg,\n", " ode_solver='euler',\n", " callbacks=my_callback,\n", @@ -861,42 +887,16 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### 2.9 Seeding\n", - "The random processes in the environment can be made reproducible by seeding the environments. The `env.seed()` method has to be called after the initialization and before the first reset to seed all random generators.\n", - "\n", - "The `env.seed` method returns a list of seeds that are used in the different random generators in the environment.\n", - "The first entry in the list is the base-seed which can be used afterwards to reset the random generators to the previous state." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "# Without any argument, a random base-seed will be generated\n", - "initial_seeds = env.seed()\n", - "\n", - "# ... execute the env for multiple steps / episodes ...\n", - "new_seeds = env.seed(initial_seeds[0])\n", - "\n", - "# ... execute the env again for multiple steps / episodes ... \n", - "# these episodes will use the SAME randomly generated numbers\n", - "print(initial_seeds == new_seeds)" + "The random processes in the environment can be made reproducible by seeding the environments. The seeding takes place when resetting an environment, i.e. calling `env.reset(seed=seed)` with the keyword argument `seed`. " ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -904,6 +904,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -966,14 +967,15 @@ "env.reset()\n", "k = 0\n", "for i in range(int(3e4)): \n", - " env.render() # visualize environment\n", - " (states, refs), rewards, done, _ = env.step(env.action_space.sample()) # pick random control actions\n", - " if done:\n", + "\n", + " (states, refs), rewards, terminated, truncated, _ = env.step(env.action_space.sample()) # pick random control actions\n", + " if terminated:\n", " env.reset()\n", "env.close()" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -997,7 +999,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.5" + "version": "3.10.6" }, "varInspector": { "cols": { diff --git a/examples/environment_features/external_speed_profile.py b/examples/environment_features/external_speed_profile.py index 38e8b8cb..89f38236 100644 --- a/examples/environment_features/external_speed_profile.py +++ b/examples/environment_features/external_speed_profile.py @@ -82,11 +82,10 @@ cum_rew = 0 for i in range(5000): - env.render() action = env.action_space.sample() - (state, reference), reward, done, _ = env.step(action) + (state, reference), reward, terminated, truncated, _ = env.step(action) - if done: + if terminated: state, _ = env.reset() cum_rew += reward diff --git a/examples/environment_features/scim_ideal_grid_simulation.py b/examples/environment_features/scim_ideal_grid_simulation.py index 4c41f9ab..7d47db5f 100644 --- a/examples/environment_features/scim_ideal_grid_simulation.py +++ b/examples/environment_features/scim_ideal_grid_simulation.py @@ -76,7 +76,7 @@ def grid_voltage(t): time = idx * tau # apply the voltage as given by the grid - (state, reference), reward, done, _ = env.step(u_abc(time)) + (state, reference), reward, terminated, truncated, _ = env.step(u_abc(time)) # save the results of this simulation step STATE = np.append(STATE, np.transpose([state * limits]), axis=1) diff --git a/examples/environment_features/userdefined_initialization.py b/examples/environment_features/userdefined_initialization.py index e12ca853..7ae529c3 100644 --- a/examples/environment_features/userdefined_initialization.py +++ b/examples/environment_features/userdefined_initialization.py @@ -77,11 +77,10 @@ # Here we should have omega in the interval [60 1/s, 80 1/s] and current closely around 25 A for i in range(5000): - env.render() action = env.action_space.sample() - (state, reference), reward, done, _ = env.step(action) + (state, reference), reward, terminated, truncated, _ = env.step(action) - if done: + if terminated: break diff --git a/examples/reinforcement_learning_controllers/ddpg_pmsm_dq_current_control.py b/examples/reinforcement_learning_controllers/ddpg_pmsm_dq_current_control.py index 7fc41442..d72110e0 100644 --- a/examples/reinforcement_learning_controllers/ddpg_pmsm_dq_current_control.py +++ b/examples/reinforcement_learning_controllers/ddpg_pmsm_dq_current_control.py @@ -6,7 +6,7 @@ from rl.agents import DDPGAgent from rl.memory import SequentialMemory from rl.random import OrnsteinUhlenbeckProcess -from gym.wrappers import FlattenObservation +from gymnasium.wrappers import FlattenObservation import numpy as np import sys import os @@ -17,8 +17,8 @@ from gym_electric_motor.visualization import MotorDashboard from gym_electric_motor.visualization.motor_dashboard_plots import MeanEpisodeRewardPlot from gym_electric_motor.physical_systems.mechanical_loads import ConstantSpeedLoad -from gym.core import Wrapper -from gym.spaces import Box, Tuple +from gymnasium.core import Wrapper +from gymnasium.spaces import Box, Tuple from gym_electric_motor.constraints import SquaredConstraint from gym_electric_motor.physical_system_wrappers import DqToAbcActionProcessor, DeadTimeProcessor diff --git a/examples/reinforcement_learning_controllers/ddpg_series_omega_control.py b/examples/reinforcement_learning_controllers/ddpg_series_omega_control.py index 83782434..0faa4738 100644 --- a/examples/reinforcement_learning_controllers/ddpg_series_omega_control.py +++ b/examples/reinforcement_learning_controllers/ddpg_series_omega_control.py @@ -10,7 +10,7 @@ from rl.agents import DDPGAgent from rl.memory import SequentialMemory from rl.random import OrnsteinUhlenbeckProcess -from gym.wrappers import FlattenObservation +from gymnasium.wrappers import FlattenObservation import sys import os sys.path.append(os.path.abspath(os.path.join('..'))) diff --git a/examples/reinforcement_learning_controllers/dqn_series_current_control.py b/examples/reinforcement_learning_controllers/dqn_series_current_control.py index d1939d2a..ac3bae2a 100644 --- a/examples/reinforcement_learning_controllers/dqn_series_current_control.py +++ b/examples/reinforcement_learning_controllers/dqn_series_current_control.py @@ -8,7 +8,7 @@ from rl.agents.dqn import DQNAgent from rl.policy import LinearAnnealedPolicy, EpsGreedyQPolicy from rl.memory import SequentialMemory -from gym.wrappers import FlattenObservation +from gymnasium.wrappers import FlattenObservation import sys import os sys.path.append(os.path.abspath(os.path.join('..'))) diff --git a/examples/reinforcement_learning_controllers/keras_rl2_dqn_disc_pmsm_example.ipynb b/examples/reinforcement_learning_controllers/keras_rl2_dqn_disc_pmsm_example.ipynb index 590b32bb..cfb86a82 100644 --- a/examples/reinforcement_learning_controllers/keras_rl2_dqn_disc_pmsm_example.ipynb +++ b/examples/reinforcement_learning_controllers/keras_rl2_dqn_disc_pmsm_example.ipynb @@ -119,9 +119,9 @@ " MultipleReferenceGenerator,\\\n", " WienerProcessReferenceGenerator\n", "from gym_electric_motor.visualization import MotorDashboard\n", - "from gym.spaces import Discrete, Box\n", - "from gym.wrappers import FlattenObservation, TimeLimit\n", - "from gym import ObservationWrapper" + "from gymnasium.spaces import Discrete, Box\n", + "from gymnasium.wrappers import FlattenObservation, TimeLimit\n", + "from gymnasium import ObservationWrapper" ] }, { diff --git a/examples/reinforcement_learning_controllers/stable_baselines3_dqn_disc_pmsm_example.ipynb b/examples/reinforcement_learning_controllers/stable_baselines3_dqn_disc_pmsm_example.ipynb index 745cf3bf..470f9dd1 100644 --- a/examples/reinforcement_learning_controllers/stable_baselines3_dqn_disc_pmsm_example.ipynb +++ b/examples/reinforcement_learning_controllers/stable_baselines3_dqn_disc_pmsm_example.ipynb @@ -111,9 +111,9 @@ " WienerProcessReferenceGenerator\n", "from gym_electric_motor.visualization import MotorDashboard\n", "from gym_electric_motor.core import Callback\n", - "from gym.spaces import Discrete, Box\n", - "from gym.wrappers import FlattenObservation, TimeLimit\n", - "from gym import ObservationWrapper" + "from gymnasium.spaces import Discrete, Box\n", + "from gymnasium.wrappers import FlattenObservation, TimeLimit\n", + "from gymnasium import ObservationWrapper" ] }, { diff --git a/gym_electric_motor/__init__.py b/gym_electric_motor/__init__.py index 0f9e3b70..2a73df67 100644 --- a/gym_electric_motor/__init__.py +++ b/gym_electric_motor/__init__.py @@ -5,7 +5,7 @@ from .core import ConstraintMonitor from .random_component import RandomComponent from .constraints import Constraint, LimitConstraint -from .utils import make, register_superclass +from .utils import register_superclass register_superclass(RewardFunction) register_superclass(ElectricMotorVisualization) @@ -18,14 +18,18 @@ import gym_electric_motor.physical_systems import gym_electric_motor.envs import gym_electric_motor.physical_system_wrappers +import gym_electric_motor.core -from gym.envs.registration import register -import gym +make = core.ElectricMotorEnvironment.make + +from gymnasium.envs.registration import register +import gymnasium from packaging import version # Add all superclasses of the modules to the registry. -# Deactivate the order enforce wrapper that is put around a created env per default from gym-version 0.21.0 onwards -registration_kwargs = dict(order_enforce=False) if version.parse(gym.__version__) >= version.parse('0.21.0') else dict() +# Deactivate the order enforce wrapper that is put around a created env per default from gymnasium-version 0.21.0 onwards +registration_kwargs = dict(order_enforce=False) if version.parse(gymnasium.__version__) >= version.parse('0.21.0') else dict() +registration_kwargs['disable_env_checker'] = True envs_path = 'gym_electric_motor.envs:' diff --git a/gym_electric_motor/callbacks.py b/gym_electric_motor/callbacks.py index 22bd78f2..5cab3ad9 100644 --- a/gym_electric_motor/callbacks.py +++ b/gym_electric_motor/callbacks.py @@ -76,7 +76,7 @@ def set_env(self, env): else: self._env.reference_generator._limit_margin = self._limit_margin - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): # See docstring of superclass if self._update_time == 'step': self._step += 1 diff --git a/gym_electric_motor/core.py b/gym_electric_motor/core.py index bf0752ad..d6b16a8f 100644 --- a/gym_electric_motor/core.py +++ b/gym_electric_motor/core.py @@ -17,17 +17,23 @@ - Visualization of the PhysicalSystems state, reference and reward for the user. """ -import gym +import os +import datetime + +import gymnasium import numpy as np -from gym.spaces import Box +from gymnasium.spaces import Box from .utils import instantiate from .random_component import RandomComponent from .constraints import Constraint, LimitConstraint import gym_electric_motor as gem +import matplotlib.pyplot +from matplotlib.figure import Figure +import matplotlib -class ElectricMotorEnvironment(gym.core.Env): +class ElectricMotorEnvironment(gymnasium.core.Env): """ Description: The main class connecting all modules of the gym-electric-motor environments. @@ -84,6 +90,11 @@ class ElectricMotorEnvironment(gym.core.Env): The reward function can terminate an episode, if a physical limit of the motor has been violated. """ + env_id = None + metadata = {"render_modes": [None, "figure", "figure_once", "figure_academic"], + "save_figure_on_close": False, + "hold_figure_on_close": True} + @property def physical_system(self): """ @@ -109,7 +120,7 @@ def reference_generator(self, reference_generator): reference_generator(ReferenceGenerator): The new reference generator of the environment. """ self._reference_generator = reference_generator - self._done = True + self._terminated = True @property def reward_function(self): @@ -128,7 +139,7 @@ def reward_function(self, reward_function): reward_function(RewardFunction): The new reward function of the environment. """ self._reward_function = reward_function - self._done = True + self._terminated = True @property def constraint_monitor(self): @@ -165,7 +176,7 @@ def visualizations(self): return self._visualizations def __init__(self, physical_system, reference_generator, reward_function, visualization=(), state_filter=None, - callbacks=(), constraints=(), physical_system_wrappers=(), **kwargs): + callbacks=(), constraints=(), physical_system_wrappers=(), render_mode=None, scale_plots = None, **kwargs): """ Setting and initialization of all environments' modules. @@ -186,6 +197,7 @@ def __init__(self, physical_system, reference_generator, reward_function, visual state_filter(list(str)): Selection of states that are shown in the observation. physical_system_wrappers(iterable(PhysicalSystemWrapper)): PhysicalSystemWrapper instances to be wrapped around the physical system. + render_mode(str) : if visualization is given, render_mode is set to "figure", else render_mode ist set to None callbacks(list(Callback)): Callbacks being called in the environment **kwargs: Arguments to be passed to the modules. """ @@ -219,34 +231,54 @@ def __init__(self, physical_system, reference_generator, reward_function, visual states_low = self._physical_system.state_space.low[self.state_filter] states_high = self._physical_system.state_space.high[self.state_filter] state_space = Box(states_low, states_high, dtype=np.float64) - self.observation_space = gym.spaces.Tuple(( + self.observation_space = gymnasium.spaces.Tuple(( state_space, self._reference_generator.reference_space )) self.action_space = self.physical_system.action_space self.reward_range = self._reward_function.reward_range - self._done = True + # new API splits done into two attributes + self._terminated = True + self._truncated = False + + # Set render mode and metadata + assert render_mode in self.metadata["render_modes"] + self.render_mode = render_mode + + self.scale_plots = scale_plots + self._callbacks = list(callbacks) self._callbacks += list(self._visualizations) self._call_callbacks('set_env', self) + def make(env_id, *args, **kwargs): + env = gymnasium.make(env_id, *args, **kwargs) + env.metadata["filename_prefix"] = env_id + + timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S") + env.metadata["filename_suffix"] = f"_{timestamp}" + + return env + def _call_callbacks(self, func_name, *args): """Calls each callback's func_name function with *args""" for callback in self._callbacks: func = getattr(callback, func_name) func(*args) - def reset(self, *_, **__): + def reset(self, seed = None,*_, **__): """ Reset of the environment and all its modules to an initial state. Returns: The initial observation consisting of the initial state and initial reference. """ + + self._seed(seed) self._call_callbacks('on_reset_begin') - self._done = False + self._terminated = False state = self._physical_system.reset() - reference, next_ref, trajectories = self.reference_generator.reset(state) + reference, next_ref, _ = self.reference_generator.reset(state) self._reward_function.reset(state, reference) self._call_callbacks('on_reset_end', state, reference) return state[self.state_filter], next_ref @@ -267,11 +299,11 @@ def step(self, action): Returns: observation(Tuple(ndarray(float),ndarray(float)): Tuple of the new state and the next reference. reward(float): Amount of reward received for the last step. - done(bool): Flag, indicating if a reset is required before new steps can be taken. + terminated(bool): Flag, indicating if a reset is required before new steps can be taken. {}: An empty dictionary for consistency with the OpenAi Gym interface. """ - assert not self._done, 'A reset is required before the environment can perform further steps' + assert not self._terminated, 'A reset is required before the environment can perform further steps' self._call_callbacks('on_step_begin', self.physical_system.k, action) state = self._physical_system.simulate(action) reference = self.reference_generator.get_reference(state) @@ -279,14 +311,19 @@ def step(self, action): reward = self._reward_function.reward( state, reference, self._physical_system.k, action, violation_degree ) - self._done = violation_degree >= 1.0 + self._terminated = violation_degree >= 1.0 ref_next = self.reference_generator.get_reference_observation(state) self._call_callbacks( - 'on_step_end', self.physical_system.k, state, reference, reward, self._done + 'on_step_end', self.physical_system.k, state, reference, reward, self._terminated ) - return (state[self.state_filter], ref_next), reward, self._done, {} - def seed(self, seed=None): + # Call render code + if self.render_mode == "figure": + self.render() + + return (state[self.state_filter], ref_next), reward, self._terminated, self._truncated, {} + + def _seed(self, seed=None): sg = np.random.SeedSequence(seed) components = [ self._physical_system, @@ -299,6 +336,46 @@ def seed(self, seed=None): if isinstance(rc, gem.RandomComponent): rc.seed(sub) return [sg.entropy] + + def save_fig(self, figure, filetype="png"): + """ Save figure with timestamped as filename """ + # create output folder if it not exists + output_folder_name = "plots" + if not os.path.exists(output_folder_name): + # Create the folder "gem_output" + os.makedirs(output_folder_name) + + filename_prefix = self.metadata["filename_prefix"] + filename_suffix = self.metadata["filename_suffix"] + filename = f"{output_folder_name}/{filename_prefix}{filename_suffix}.{filetype}" + figure.savefig(filename, dpi=300) + + def rendering_on_close(self): + + # Figure Mode + if self.render_mode and self.render_mode.startswith("figure"): + + # Academic Mode (latex font) + if self.render_mode == "figure_academic": + matplotlib.rcParams.update({ + "text.usetex": True, + "font.family": "Helvetica" + }) + + self.render() + + # Save figure with timestamp as filename + if self.metadata["save_figure_on_close"]: + if self.render_mode == "figure_academic": + self.save_fig(self.figure(), filetype="pdf") + else: + self.save_fig(self.figure()) + + # Blocking plot call to still interactive with it + if self.metadata["hold_figure_on_close"]: + matplotlib.pyplot.show(block=True) + + def close(self): """Called when the environment is deleted. Closes all its modules.""" @@ -307,6 +384,15 @@ def close(self): self._physical_system.close() self._reference_generator.close() + self.rendering_on_close() + + + def figure(self) -> Figure: + """ Get main figure (MotorDashboard) """ + assert len(self._visualizations) == 1 + motor_dashboard = self._visualizations[0] + assert len(motor_dashboard._figures) == 1 + return motor_dashboard._figures[0] class ReferenceGenerator: """The abstract base class for reference generators in gym electric motor environments. @@ -546,7 +632,7 @@ def state_positions(self): def action_space(self): """ Returns: - gym.Space: An OpenAI Gym Space that describes the possible actions on the system. + gymnasium.Space: An OpenAI Gym Space that describes the possible actions on the system. """ return self._action_space @@ -554,7 +640,7 @@ def action_space(self): def state_space(self): """ Returns: - gym.Space: An OpenAI Gym Space that describes the possible states of the system. + gymnasium.Space: An OpenAI Gym Space that describes the possible states of the system. """ return self._state_space @@ -577,8 +663,8 @@ def nominal_state(self): def __init__(self, action_space, state_space, state_names, tau): """ Args: - action_space(gym.Space): The set of allowed actions on the system. - state_space(gym.Space): The set of possible systems states. + action_space(gymnasium.Space): The set of allowed actions on the system. + state_space(gymnasium.Space): The set of possible systems states. state_names(ndarray(str)): The names of the systems states tau(float): The systems simulation time interval. """ @@ -645,7 +731,7 @@ def on_step_begin(self, k, action): """Gets called at the beginning of each step""" pass - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): """Gets called at the end of each step""" pass diff --git a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_cc_extex_dc_env.py b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_cc_extex_dc_env.py index 5a5cc252..d7604d9c 100644 --- a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_cc_extex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_cc_extex_dc_env.py @@ -76,16 +76,15 @@ class ContCurrentControlDcExternallyExcitedMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -156,5 +155,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_sc_extex_dc_env.py b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_sc_extex_dc_env.py index 59ff3741..c1a22090 100644 --- a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_sc_extex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_sc_extex_dc_env.py @@ -76,16 +76,15 @@ class ContSpeedControlDcExternallyExcitedMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -149,5 +148,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_tc_extex_dc_env.py b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_tc_extex_dc_env.py index 583191d2..d3f6c194 100644 --- a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_tc_extex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/cont_tc_extex_dc_env.py @@ -76,16 +76,15 @@ class ContTorqueControlDcExternallyExcitedMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i_a', 'i_e',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -149,5 +148,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_cc_extex_dc_env.py b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_cc_extex_dc_env.py index 0b3777cf..232de8a5 100644 --- a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_cc_extex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_cc_extex_dc_env.py @@ -76,16 +76,15 @@ class FiniteCurrentControlDcExternallyExcitedMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -153,5 +152,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_sc_extex_dc_env.py b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_sc_extex_dc_env.py index 321a28d9..de2836a6 100644 --- a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_sc_extex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_sc_extex_dc_env.py @@ -76,16 +76,15 @@ class FiniteSpeedControlDcExternallyExcitedMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -150,5 +149,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_tc_extex_dc_env.py b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_tc_extex_dc_env.py index bbcba120..5a6986e1 100644 --- a/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_tc_extex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/extex_dc_motor_env/finite_tc_extex_dc_env.py @@ -76,16 +76,15 @@ class FiniteTorqueControlDcExternallyExcitedMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5,physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5,physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -148,5 +147,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_cc_permex_dc_env.py b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_cc_permex_dc_env.py index a9c38fb5..c6fe0e88 100644 --- a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_cc_permex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_cc_permex_dc_env.py @@ -76,17 +76,16 @@ class ContCurrentControlDcPermanentlyExcitedMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__( self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=() + constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs ): """ Args: @@ -146,5 +145,5 @@ def __init__( super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_sc_permex_dc_env.py b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_sc_permex_dc_env.py index 70a4da74..217297f0 100644 --- a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_sc_permex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_sc_permex_dc_env.py @@ -76,16 +76,15 @@ class ContSpeedControlDcPermanentlyExcitedMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -145,5 +144,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_tc_permex_dc_env.py b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_tc_permex_dc_env.py index 7cc7d36e..7cba7ab8 100644 --- a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_tc_permex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/cont_tc_permex_dc_env.py @@ -76,17 +76,16 @@ class ContTorqueControlDcPermanentlyExcitedMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -148,5 +147,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_cc_permex_dc_env.py b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_cc_permex_dc_env.py index c2f8eba7..07ee24e6 100644 --- a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_cc_permex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_cc_permex_dc_env.py @@ -76,17 +76,16 @@ class FiniteCurrentControlDcPermanentlyExcitedMotorEnv(ElectricMotorEnvironment) ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__( self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=() + constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs ): """ Args: @@ -145,5 +144,5 @@ def __init__( super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_sc_permex_dc_env.py b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_sc_permex_dc_env.py index 8abde974..35e3dbd7 100644 --- a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_sc_permex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_sc_permex_dc_env.py @@ -76,17 +76,16 @@ class FiniteSpeedControlDcPermanentlyExcitedMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__( self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=() + constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs ): """ Args: @@ -148,5 +147,5 @@ def __init__( super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_tc_permex_dc_env.py b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_tc_permex_dc_env.py index 21207b01..00a81039 100644 --- a/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_tc_permex_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/permex_dc_motor_env/finite_tc_permex_dc_env.py @@ -76,17 +76,16 @@ class FiniteTorqueControlDcPermanentlyExcitedMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__( self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=() + constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs ): """ Args: @@ -145,6 +144,6 @@ def __init__( super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_cc_series_dc_env.py b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_cc_series_dc_env.py index 016e1878..0d18b2ca 100644 --- a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_cc_series_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_cc_series_dc_env.py @@ -76,16 +76,15 @@ class ContCurrentControlDcSeriesMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -144,5 +143,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_sc_series_dc_env.py b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_sc_series_dc_env.py index 46d99492..018757c0 100644 --- a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_sc_series_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_sc_series_dc_env.py @@ -76,17 +76,16 @@ class ContSpeedControlDcSeriesMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -146,6 +145,6 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_tc_series_dc_env.py b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_tc_series_dc_env.py index 432f737f..0fbb1a58 100644 --- a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_tc_series_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/cont_tc_series_dc_env.py @@ -76,17 +76,16 @@ class ContTorqueControlDcSeriesMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -143,5 +142,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_cc_series_dc_env.py b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_cc_series_dc_env.py index c1cf1bd2..57ef5a8c 100644 --- a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_cc_series_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_cc_series_dc_env.py @@ -76,16 +76,15 @@ class FiniteCurrentControlDcSeriesMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -142,5 +141,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_sc_series_dc_env.py b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_sc_series_dc_env.py index 01e8368b..e6cf017b 100644 --- a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_sc_series_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_sc_series_dc_env.py @@ -76,16 +76,15 @@ class FiniteSpeedControlDcSeriesMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -145,6 +144,6 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_tc_series_dc_env.py b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_tc_series_dc_env.py index 6a1e6f3b..930cb898 100644 --- a/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_tc_series_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/series_dc_motor_env/finite_tc_series_dc_env.py @@ -76,16 +76,15 @@ class FiniteTorqueControlDcSeriesMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i',), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -144,5 +143,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_cc_shunt_dc_env.py b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_cc_shunt_dc_env.py index 85a4d1e0..f868e0c4 100644 --- a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_cc_shunt_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_cc_shunt_dc_env.py @@ -77,17 +77,16 @@ class ContCurrentControlDcShuntMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -147,5 +146,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),) + physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),), **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_sc_shunt_dc_env.py b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_sc_shunt_dc_env.py index cb0b78d3..826b67a4 100644 --- a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_sc_shunt_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_sc_shunt_dc_env.py @@ -77,17 +77,16 @@ class ContSpeedControlDcShuntMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -148,5 +147,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),) + physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),), **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_tc_shunt_dc_env.py b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_tc_shunt_dc_env.py index ee0da0aa..698607de 100644 --- a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_tc_shunt_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/cont_tc_shunt_dc_env.py @@ -77,17 +77,16 @@ class ContTorqueControlDcShuntMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -152,5 +151,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),) + physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),), **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_cc_shunt_dc_env.py b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_cc_shunt_dc_env.py index 00bf0c08..e49ac86b 100644 --- a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_cc_shunt_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_cc_shunt_dc_env.py @@ -77,17 +77,16 @@ class FiniteCurrentControlDcShuntMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -146,5 +145,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),) + physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),), **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_sc_shunt_dc_env.py b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_sc_shunt_dc_env.py index b8b0a13a..f1b376b6 100644 --- a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_sc_shunt_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_sc_shunt_dc_env.py @@ -77,17 +77,16 @@ class FiniteSpeedControlDcShuntMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -148,5 +147,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),) + physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),), **kwargs ) diff --git a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_tc_shunt_dc_env.py b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_tc_shunt_dc_env.py index 180fa309..03e1cee4 100644 --- a/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_tc_shunt_dc_env.py +++ b/gym_electric_motor/envs/gym_dcm/shunt_dc_motor_env/finite_tc_shunt_dc_env.py @@ -77,17 +77,16 @@ class FiniteTorqueControlDcShuntMotorEnv(ElectricMotorEnvironment): ... converter=my_overridden_converter, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), - constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=()): + constraints=('i_a', 'i_e'), calc_jacobian=True, tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -144,5 +143,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),) + physical_system_wrappers=tuple(physical_system_wrappers) + (CurrentSumProcessor(('i_a', 'i_e')),), **kwargs ) diff --git a/gym_electric_motor/envs/gym_eesm/cont_cc_eesm_env.py b/gym_electric_motor/envs/gym_eesm/cont_cc_eesm_env.py index 8f846906..7f07e548 100644 --- a/gym_electric_motor/envs/gym_eesm/cont_cc_eesm_env.py +++ b/gym_electric_motor/envs/gym_eesm/cont_cc_eesm_env.py @@ -77,17 +77,16 @@ class ContCurrentControlExternallyExcitedSynchronousMotorEnv(ElectricMotorEnviro ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')), LimitConstraint(('i_e',))), calc_jacobian=True, - tau=1e-4, physical_system_wrappers=()): + tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -165,5 +164,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_eesm/cont_sc_eesm_env.py b/gym_electric_motor/envs/gym_eesm/cont_sc_eesm_env.py index 8f6f7f55..7ecb11b7 100644 --- a/gym_electric_motor/envs/gym_eesm/cont_sc_eesm_env.py +++ b/gym_electric_motor/envs/gym_eesm/cont_sc_eesm_env.py @@ -77,17 +77,16 @@ class ContSpeedControlExternallyExcitedSynchronousMotorEnv(ElectricMotorEnvironm ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')), LimitConstraint(('i_e',))), calc_jacobian=True, - tau=1e-4, physical_system_wrappers=()): + tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -155,5 +154,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_eesm/cont_tc_eesm_env.py b/gym_electric_motor/envs/gym_eesm/cont_tc_eesm_env.py index aff20613..b07248a1 100644 --- a/gym_electric_motor/envs/gym_eesm/cont_tc_eesm_env.py +++ b/gym_electric_motor/envs/gym_eesm/cont_tc_eesm_env.py @@ -78,17 +78,16 @@ class ContTorqueControlExternallyExcitedSynchronousMotorEnv(ElectricMotorEnviron ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')), LimitConstraint(('i_e',))), calc_jacobian=True, - tau=1e-4, physical_system_wrappers=()): + tau=1e-4, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -161,5 +160,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_eesm/finite_cc_eesm_env.py b/gym_electric_motor/envs/gym_eesm/finite_cc_eesm_env.py index 6c627566..058b7b8d 100644 --- a/gym_electric_motor/envs/gym_eesm/finite_cc_eesm_env.py +++ b/gym_electric_motor/envs/gym_eesm/finite_cc_eesm_env.py @@ -77,17 +77,16 @@ class FiniteCurrentControlExternallyExcitedSynchronousMotorEnv(ElectricMotorEnvi ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')), LimitConstraint(('i_e',))), calc_jacobian=True, - tau=1e-5, physical_system_wrappers=()): + tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -160,5 +159,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_eesm/finite_sc_eesm_env.py b/gym_electric_motor/envs/gym_eesm/finite_sc_eesm_env.py index 0587a20f..b0d4f275 100644 --- a/gym_electric_motor/envs/gym_eesm/finite_sc_eesm_env.py +++ b/gym_electric_motor/envs/gym_eesm/finite_sc_eesm_env.py @@ -77,17 +77,16 @@ class FiniteSpeedControlExternallyExcitedSynchronousMotorEnv(ElectricMotorEnviro ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')), LimitConstraint(('i_e',))), calc_jacobian=True, - tau=1e-5, physical_system_wrappers=()): + tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -155,5 +154,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_eesm/finite_tc_eesm_env.py b/gym_electric_motor/envs/gym_eesm/finite_tc_eesm_env.py index 2890b0fa..7e09ab53 100644 --- a/gym_electric_motor/envs/gym_eesm/finite_tc_eesm_env.py +++ b/gym_electric_motor/envs/gym_eesm/finite_tc_eesm_env.py @@ -77,17 +77,16 @@ class FiniteTorqueControlExternallyExcitedSynchronousMotorEnv(ElectricMotorEnvir ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')), LimitConstraint(('i_e',))), calc_jacobian=True, - tau=1e-5, physical_system_wrappers=()): + tau=1e-5, physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -155,5 +154,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_cc_dfim_env.py b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_cc_dfim_env.py index cc9575b7..aef2bdad 100644 --- a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_cc_dfim_env.py +++ b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_cc_dfim_env.py @@ -84,18 +84,17 @@ class ContCurrentControlDoublyFedInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__( self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=() + physical_system_wrappers=(), **kwargs ): """ Args: @@ -174,5 +173,5 @@ def __init__( super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_sc_dfim_env.py b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_sc_dfim_env.py index f83b5503..5b655c9f 100644 --- a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_sc_dfim_env.py +++ b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_sc_dfim_env.py @@ -84,17 +84,16 @@ class ContSpeedControlDoublyFedInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -163,5 +162,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_tc_dfim_env.py b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_tc_dfim_env.py index 0666944e..dcd6b4be 100644 --- a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_tc_dfim_env.py +++ b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/cont_tc_dfim_env.py @@ -84,17 +84,16 @@ class ContTorqueControlDoublyFedInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -167,5 +166,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_cc_dfim_env.py b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_cc_dfim_env.py index 71b83c26..3f5c6e4c 100644 --- a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_cc_dfim_env.py +++ b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_cc_dfim_env.py @@ -84,17 +84,16 @@ class FiniteCurrentControlDoublyFedInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -172,5 +171,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_sc_dfim_env.py b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_sc_dfim_env.py index 130208ad..2154ba2c 100644 --- a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_sc_dfim_env.py +++ b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_sc_dfim_env.py @@ -84,17 +84,16 @@ class FiniteSpeedControlDoublyFedInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -163,5 +162,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_tc_dfim_env.py b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_tc_dfim_env.py index e230e384..70830114 100644 --- a/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_tc_dfim_env.py +++ b/gym_electric_motor/envs/gym_im/doubly_fed_induction_motor_envs/finite_tc_dfim_env.py @@ -84,17 +84,16 @@ class FiniteTorqueControlDoublyFedInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -161,5 +160,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_cc_scim_env.py b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_cc_scim_env.py index 26b660d0..b74aa172 100644 --- a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_cc_scim_env.py +++ b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_cc_scim_env.py @@ -82,17 +82,16 @@ class ContCurrentControlSquirrelCageInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -161,5 +160,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_sc_scim_env.py b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_sc_scim_env.py index 25b592d8..0f0740e7 100644 --- a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_sc_scim_env.py +++ b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_sc_scim_env.py @@ -82,17 +82,16 @@ class ContSpeedControlSquirrelCageInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), physical_system_wrappers=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), - calc_jacobian=True, tau=1e-4): + calc_jacobian=True, tau=1e-4, **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -153,5 +152,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_tc_scim_env.py b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_tc_scim_env.py index b3b7d248..bdd32746 100644 --- a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_tc_scim_env.py +++ b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/cont_tc_scim_env.py @@ -82,17 +82,16 @@ class ContTorqueControlSquirrelCageInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -156,5 +155,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_cc_scim_env.py b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_cc_scim_env.py index f6f495b1..f98f0ab7 100644 --- a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_cc_scim_env.py +++ b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_cc_scim_env.py @@ -82,17 +82,16 @@ class FiniteCurrentControlSquirrelCageInductionMotorEnv(ElectricMotorEnvironment ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -161,5 +160,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_sc_scim_env.py b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_sc_scim_env.py index 19236fc8..8232ce9b 100644 --- a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_sc_scim_env.py +++ b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_sc_scim_env.py @@ -82,17 +82,16 @@ class FiniteSpeedControlSquirrelCageInductionMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -153,5 +152,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_tc_scim_env.py b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_tc_scim_env.py index ad6a677f..7fa8846d 100644 --- a/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_tc_scim_env.py +++ b/gym_electric_motor/envs/gym_im/squirrel_cage_induction_motor_envs/finite_tc_scim_env.py @@ -82,17 +82,16 @@ class FiniteTorqueControlSquirrelCageInductionMotorEnv(ElectricMotorEnvironment) ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -150,5 +149,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_pmsm/cont_cc_pmsm_env.py b/gym_electric_motor/envs/gym_pmsm/cont_cc_pmsm_env.py index 4d607460..ec0f07cc 100644 --- a/gym_electric_motor/envs/gym_pmsm/cont_cc_pmsm_env.py +++ b/gym_electric_motor/envs/gym_pmsm/cont_cc_pmsm_env.py @@ -77,17 +77,16 @@ class ContCurrentControlPermanentMagnetSynchronousMotorEnv(ElectricMotorEnvironm ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -156,5 +155,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_pmsm/cont_sc_pmsm_env.py b/gym_electric_motor/envs/gym_pmsm/cont_sc_pmsm_env.py index 2f96ba5c..83be801c 100644 --- a/gym_electric_motor/envs/gym_pmsm/cont_sc_pmsm_env.py +++ b/gym_electric_motor/envs/gym_pmsm/cont_sc_pmsm_env.py @@ -77,17 +77,16 @@ class ContSpeedControlPermanentMagnetSynchronousMotorEnv(ElectricMotorEnvironmen ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -146,5 +145,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_pmsm/cont_tc_pmsm_env.py b/gym_electric_motor/envs/gym_pmsm/cont_tc_pmsm_env.py index 7722621a..e9a6d3e3 100644 --- a/gym_electric_motor/envs/gym_pmsm/cont_tc_pmsm_env.py +++ b/gym_electric_motor/envs/gym_pmsm/cont_tc_pmsm_env.py @@ -77,17 +77,16 @@ class ContTorqueControlPermanentMagnetSynchronousMotorEnv(ElectricMotorEnvironme ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -151,5 +150,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_pmsm/finite_cc_pmsm_env.py b/gym_electric_motor/envs/gym_pmsm/finite_cc_pmsm_env.py index e8f90edd..a4b78982 100644 --- a/gym_electric_motor/envs/gym_pmsm/finite_cc_pmsm_env.py +++ b/gym_electric_motor/envs/gym_pmsm/finite_cc_pmsm_env.py @@ -77,17 +77,16 @@ class FiniteCurrentControlPermanentMagnetSynchronousMotorEnv(ElectricMotorEnviro ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -156,5 +155,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_pmsm/finite_sc_pmsm_env.py b/gym_electric_motor/envs/gym_pmsm/finite_sc_pmsm_env.py index 4f09c436..041f9078 100644 --- a/gym_electric_motor/envs/gym_pmsm/finite_sc_pmsm_env.py +++ b/gym_electric_motor/envs/gym_pmsm/finite_sc_pmsm_env.py @@ -77,17 +77,16 @@ class FiniteSpeedControlPermanentMagnetSynchronousMotorEnv(ElectricMotorEnvironm ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -146,5 +145,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_pmsm/finite_tc_pmsm_env.py b/gym_electric_motor/envs/gym_pmsm/finite_tc_pmsm_env.py index 79fc525b..6228d54a 100644 --- a/gym_electric_motor/envs/gym_pmsm/finite_tc_pmsm_env.py +++ b/gym_electric_motor/envs/gym_pmsm/finite_tc_pmsm_env.py @@ -77,17 +77,16 @@ class FiniteTorqueControlPermanentMagnetSynchronousMotorEnv(ElectricMotorEnviron ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -145,5 +144,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_srm/srm_continuous_control_env.py b/gym_electric_motor/envs/gym_srm/srm_continuous_control_env.py index da2ccb12..5a012949 100644 --- a/gym_electric_motor/envs/gym_srm/srm_continuous_control_env.py +++ b/gym_electric_motor/envs/gym_srm/srm_continuous_control_env.py @@ -1,7 +1,7 @@ -import gym +import gymnasium -class SRMContinuousControlEnv(gym.Env): +class SRMContinuousControlEnv(gymnasium.Env): metadata = {'render.modes': ['human']} def __init__(self): diff --git a/gym_electric_motor/envs/gym_srm/srm_finite_control_env.py b/gym_electric_motor/envs/gym_srm/srm_finite_control_env.py index 133a1cf3..cdbacd52 100644 --- a/gym_electric_motor/envs/gym_srm/srm_finite_control_env.py +++ b/gym_electric_motor/envs/gym_srm/srm_finite_control_env.py @@ -1,7 +1,7 @@ -import gym +import gymnasium -class SRMFiniteControlEnv(gym.Env): +class SRMFiniteControlEnv(gymnasium.Env): metadata = {'render.modes': ['human']} def __init__(self): diff --git a/gym_electric_motor/envs/gym_synrm/cont_cc_synrm_env.py b/gym_electric_motor/envs/gym_synrm/cont_cc_synrm_env.py index 69258072..3b2b42a8 100644 --- a/gym_electric_motor/envs/gym_synrm/cont_cc_synrm_env.py +++ b/gym_electric_motor/envs/gym_synrm/cont_cc_synrm_env.py @@ -77,17 +77,16 @@ class ContCurrentControlSynchronousReluctanceMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -156,5 +155,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_synrm/cont_sc_synrm_env.py b/gym_electric_motor/envs/gym_synrm/cont_sc_synrm_env.py index 7d79eff8..32ac8682 100644 --- a/gym_electric_motor/envs/gym_synrm/cont_sc_synrm_env.py +++ b/gym_electric_motor/envs/gym_synrm/cont_sc_synrm_env.py @@ -77,17 +77,16 @@ class ContSpeedControlSynchronousReluctanceMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -147,5 +146,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_synrm/cont_tc_synrm_env.py b/gym_electric_motor/envs/gym_synrm/cont_tc_synrm_env.py index 34b319bd..e7365ae0 100644 --- a/gym_electric_motor/envs/gym_synrm/cont_tc_synrm_env.py +++ b/gym_electric_motor/envs/gym_synrm/cont_tc_synrm_env.py @@ -77,17 +77,16 @@ class ContTorqueControlSynchronousReluctanceMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-4, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -151,5 +150,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_synrm/finite_cc_synrm_env.py b/gym_electric_motor/envs/gym_synrm/finite_cc_synrm_env.py index 04c8aded..e79608dd 100644 --- a/gym_electric_motor/envs/gym_synrm/finite_cc_synrm_env.py +++ b/gym_electric_motor/envs/gym_synrm/finite_cc_synrm_env.py @@ -77,17 +77,16 @@ class FiniteCurrentControlSynchronousReluctanceMotorEnv(ElectricMotorEnvironment ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -156,5 +155,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_synrm/finite_sc_synrm_env.py b/gym_electric_motor/envs/gym_synrm/finite_sc_synrm_env.py index 9c2d3f79..7ade4aec 100644 --- a/gym_electric_motor/envs/gym_synrm/finite_sc_synrm_env.py +++ b/gym_electric_motor/envs/gym_synrm/finite_sc_synrm_env.py @@ -77,17 +77,16 @@ class FiniteSpeedControlSynchronousReluctanceMotorEnv(ElectricMotorEnvironment): ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -148,5 +147,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/envs/gym_synrm/finite_tc_synrm_env.py b/gym_electric_motor/envs/gym_synrm/finite_tc_synrm_env.py index 7d86e9e8..4336ad23 100644 --- a/gym_electric_motor/envs/gym_synrm/finite_tc_synrm_env.py +++ b/gym_electric_motor/envs/gym_synrm/finite_tc_synrm_env.py @@ -77,17 +77,16 @@ class FiniteTorqueControlSynchronousReluctanceMotorEnv(ElectricMotorEnvironment) ... ode_solver=my_overridden_solver, ... reference_generator=my_new_ref_gen_instance ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solver=None, reward_function=None, reference_generator=None, visualization=None, state_filter=None, callbacks=(), constraints=(SquaredConstraint(('i_sq', 'i_sd')),), calc_jacobian=True, tau=1e-5, - physical_system_wrappers=()): + physical_system_wrappers=(), **kwargs): """ Args: supply(env-arg): Specification of the :py:class:`.VoltageSupply` for the environment @@ -145,5 +144,5 @@ def __init__(self, supply=None, converter=None, motor=None, load=None, ode_solve super().__init__( physical_system=physical_system, reference_generator=reference_generator, reward_function=reward_function, constraints=constraints, visualization=visualization, state_filter=state_filter, callbacks=callbacks, - physical_system_wrappers=physical_system_wrappers + physical_system_wrappers=physical_system_wrappers, **kwargs ) diff --git a/gym_electric_motor/physical_system_wrappers/cos_sin_processor.py b/gym_electric_motor/physical_system_wrappers/cos_sin_processor.py index 690dee4c..bf2415cf 100644 --- a/gym_electric_motor/physical_system_wrappers/cos_sin_processor.py +++ b/gym_electric_motor/physical_system_wrappers/cos_sin_processor.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import numpy as np from gym_electric_motor.physical_system_wrappers import PhysicalSystemWrapper @@ -38,7 +38,7 @@ def set_physical_system(self, physical_system): self._remove_idx = self._angle_index if self._remove_angle else [] low = np.concatenate((np.delete(physical_system.state_space.low, self._remove_idx), [-1., -1.])) high = np.concatenate((np.delete(physical_system.state_space.high, self._remove_idx), [1., 1.])) - self.state_space = gym.spaces.Box(low, high, dtype=np.float64) + self.state_space = gymnasium.spaces.Box(low, high, dtype=np.float64) self._limits = np.concatenate((np.delete(physical_system.limits, self._remove_idx), [1., 1.])) self._nominal_state = np.concatenate((np.delete(physical_system.nominal_state, self._remove_idx), [1., 1.])) diff --git a/gym_electric_motor/physical_system_wrappers/current_sum_processor.py b/gym_electric_motor/physical_system_wrappers/current_sum_processor.py index e3f25224..08816ac4 100644 --- a/gym_electric_motor/physical_system_wrappers/current_sum_processor.py +++ b/gym_electric_motor/physical_system_wrappers/current_sum_processor.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import numpy as np from gym_electric_motor.physical_system_wrappers import PhysicalSystemWrapper @@ -29,7 +29,7 @@ def set_physical_system(self, physical_system): # Define the new state space as concatenation of the old state space and [-1,1] for i_sum low = np.concatenate((physical_system.state_space.low, [-1.])) high = np.concatenate((physical_system.state_space.high, [1.])) - self.state_space = gym.spaces.Box(low, high, dtype=np.float64) + self.state_space = gymnasium.spaces.Box(low, high, dtype=np.float64) # Set the new limits / nominal values of the state vector current_limit = self._limit(physical_system.limits[self._current_indices]) diff --git a/gym_electric_motor/physical_system_wrappers/dead_time_processor.py b/gym_electric_motor/physical_system_wrappers/dead_time_processor.py index 39b6a213..f447cc48 100644 --- a/gym_electric_motor/physical_system_wrappers/dead_time_processor.py +++ b/gym_electric_motor/physical_system_wrappers/dead_time_processor.py @@ -1,7 +1,7 @@ from collections import deque import numpy as np -import gym.spaces +import gymnasium.spaces from gym_electric_motor.physical_system_wrappers import PhysicalSystemWrapper @@ -45,11 +45,11 @@ def set_physical_system(self, physical_system): super().set_physical_system(physical_system) if self._reset_actions is None: action_space = physical_system.action_space - if isinstance(action_space, gym.spaces.Discrete): + if isinstance(action_space, gymnasium.spaces.Discrete): reset_action = 0 - elif isinstance(action_space, gym.spaces.MultiDiscrete): + elif isinstance(action_space, gymnasium.spaces.MultiDiscrete): reset_action = [np.zeros_like(action_space.nvec)] - elif isinstance(action_space, gym.spaces.Box): + elif isinstance(action_space, gymnasium.spaces.Box): reset_action = np.zeros(action_space.shape, dtype=np.float64) else: raise AssertionError( diff --git a/gym_electric_motor/physical_system_wrappers/dq_to_abc_action_processor.py b/gym_electric_motor/physical_system_wrappers/dq_to_abc_action_processor.py index 9946f2bf..042af41a 100644 --- a/gym_electric_motor/physical_system_wrappers/dq_to_abc_action_processor.py +++ b/gym_electric_motor/physical_system_wrappers/dq_to_abc_action_processor.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import numpy as np import gym_electric_motor.physical_systems as ps @@ -91,7 +91,7 @@ class _ClassicDqToAbcActionProcessor(DqToAbcActionProcessor): @property def action_space(self): - return gym.spaces.Box(-1, 1, shape=(2,), dtype=np.float64) + return gymnasium.spaces.Box(-1, 1, shape=(2,), dtype=np.float64) def simulate(self, action): # Docstring of superclass @@ -116,7 +116,7 @@ class _DFIMDqToAbcActionProcessor(DqToAbcActionProcessor): @property def action_space(self): - return gym.spaces.Box(-1, 1, shape=(4,)) + return gymnasium.spaces.Box(-1, 1, shape=(4,)) def __init__(self, physical_system=None): super().__init__('epsilon', physical_system=physical_system) diff --git a/gym_electric_motor/physical_system_wrappers/flux_observer.py b/gym_electric_motor/physical_system_wrappers/flux_observer.py index 41ce0d8c..c3f176b0 100644 --- a/gym_electric_motor/physical_system_wrappers/flux_observer.py +++ b/gym_electric_motor/physical_system_wrappers/flux_observer.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import numpy as np import gym_electric_motor as gem @@ -62,7 +62,7 @@ def set_physical_system(self, physical_system): psi_limit = self._l_m * physical_system.limits[physical_system.state_names.index('i_sd')] low = np.concatenate((physical_system.state_space.low, [-psi_limit, -np.pi])) high = np.concatenate((physical_system.state_space.high, [psi_limit, np.pi])) - self.state_space = gym.spaces.Box(low, high, dtype=np.float64) + self.state_space = gymnasium.spaces.Box(low, high, dtype=np.float64) self._current_indices = [physical_system.state_positions[name] for name in self._current_names] self._limits = np.concatenate((physical_system.limits, [psi_limit, np.pi])) self._nominal_state = np.concatenate((physical_system.nominal_state, [psi_limit, np.pi])) diff --git a/gym_electric_motor/physical_systems/converters.py b/gym_electric_motor/physical_systems/converters.py index d33b9959..3ccd4e0e 100644 --- a/gym_electric_motor/physical_systems/converters.py +++ b/gym_electric_motor/physical_systems/converters.py @@ -1,5 +1,5 @@ import numpy as np -from gym.spaces import Discrete, Box, MultiDiscrete +from gymnasium.spaces import Discrete, Box, MultiDiscrete from ..utils import instantiate @@ -16,11 +16,11 @@ class PowerElectronicConverter: | E.g. (0, 1) - Only positive currents / (-1, 1) Positive and negative currents """ - #: gym.Space that defines Minimum, Maximum and Dimension of possible output voltage of the converter + #: gymnasium.Space that defines Minimum, Maximum and Dimension of possible output voltage of the converter voltages = None - #: gym.Space that defines Minimum, Maximum and Dimension of possible output current of the converter + #: gymnasium.Space that defines Minimum, Maximum and Dimension of possible output current of the converter currents = None - #: gym.Space that defines the set of all possible actions for the converter + #: gymnasium.Space that defines the set of all possible actions for the converter action_space = None #: Default action that is taken after a reset. _reset_action = None diff --git a/gym_electric_motor/physical_systems/electric_motors/electric_motor.py b/gym_electric_motor/physical_systems/electric_motors/electric_motor.py index fc2563a5..91cba614 100644 --- a/gym_electric_motor/physical_systems/electric_motors/electric_motor.py +++ b/gym_electric_motor/physical_systems/electric_motors/electric_motor.py @@ -183,7 +183,7 @@ def initialize(self, state_space, state_positions, **__): initial_states attribute Args: - state_space(gym.Box): normalized state space boundaries (given by physical system) + state_space(gymnasium.Box): normalized state space boundaries (given by physical system) state_positions(dict): indices of system states (given by physical system) """ # for organization purposes @@ -285,7 +285,7 @@ def reset(self, state_space, state_positions, **__): """Reset the motors state to a new initial state. (Default 0) Args: - state_space(gym.Box): normalized state space boundaries + state_space(gymnasium.Box): normalized state space boundaries state_positions(dict): indexes of system states Returns: numpy.ndarray(float): The initial motor states. diff --git a/gym_electric_motor/physical_systems/mechanical_loads/mechanical_load.py b/gym_electric_motor/physical_systems/mechanical_loads/mechanical_load.py index bf16438b..841110c1 100644 --- a/gym_electric_motor/physical_systems/mechanical_loads/mechanical_load.py +++ b/gym_electric_motor/physical_systems/mechanical_loads/mechanical_load.py @@ -104,7 +104,7 @@ def initialize(self, state_space, state_positions, nominal_state, **__): Args: nominal_state(list): nominal values for each state given from physical system - state_space(gym.spaces.Box): normalized state space boundaries + state_space(gymnasium.spaces.Box): normalized state space boundaries state_positions(dict): indexes of system states """ # for order and organization purposes @@ -175,7 +175,7 @@ def reset(self, state_space, state_positions, nominal_state, **__): Args: nominal_state(list): nominal values for each state given from physical system - state_space(gym.Box): normalized state space boundaries + state_space(gymnasium.Box): normalized state space boundaries state_positions(dict): indexes of system states Returns: numpy.ndarray(float): The initial motor states. diff --git a/gym_electric_motor/physical_systems/mechanical_loads/polynomial_static_load.py b/gym_electric_motor/physical_systems/mechanical_loads/polynomial_static_load.py index 5a6bb351..9106b816 100644 --- a/gym_electric_motor/physical_systems/mechanical_loads/polynomial_static_load.py +++ b/gym_electric_motor/physical_systems/mechanical_loads/polynomial_static_load.py @@ -27,12 +27,11 @@ class PolynomialStaticLoad(MechanicalLoad): ... 'Cont-SC-ExtExDc-v0', ... load=my_poly_static_load ... ) - >>> done = True + >>> terminated = True >>> for _ in range(1000): - >>> if done: + >>> if terminated: >>> state, reference = env.reset() - >>> env.render() - >>> (state, reference), reward, done, _ = env.step(env.action_space.sample()) + >>> (state, reference), reward, terminated, truncated, _ = env.step(env.action_space.sample()) """ diff --git a/gym_electric_motor/physical_systems/physical_systems.py b/gym_electric_motor/physical_systems/physical_systems.py index 9cdc29a9..5ce61805 100644 --- a/gym_electric_motor/physical_systems/physical_systems.py +++ b/gym_electric_motor/physical_systems/physical_systems.py @@ -1,5 +1,5 @@ import numpy as np -from gym.spaces import Box +from gymnasium.spaces import Box import warnings import gym_electric_motor as gem diff --git a/gym_electric_motor/reference_generators/const_reference_generator.py b/gym_electric_motor/reference_generators/const_reference_generator.py index 16279311..f8001ee4 100644 --- a/gym_electric_motor/reference_generators/const_reference_generator.py +++ b/gym_electric_motor/reference_generators/const_reference_generator.py @@ -1,7 +1,7 @@ import numpy as np from gym_electric_motor.core import ReferenceGenerator from gym_electric_motor.utils import set_state_array -from gym.spaces import Box +from gymnasium.spaces import Box class ConstReferenceGenerator(ReferenceGenerator): diff --git a/gym_electric_motor/reference_generators/multiple_reference_generator.py b/gym_electric_motor/reference_generators/multiple_reference_generator.py index 12b40ad5..e6342ff3 100644 --- a/gym_electric_motor/reference_generators/multiple_reference_generator.py +++ b/gym_electric_motor/reference_generators/multiple_reference_generator.py @@ -1,5 +1,5 @@ import numpy as np -from gym.spaces import Box +from gymnasium.spaces import Box from ..core import ReferenceGenerator from ..utils import instantiate diff --git a/gym_electric_motor/reference_generators/subepisoded_reference_generator.py b/gym_electric_motor/reference_generators/subepisoded_reference_generator.py index 266abf65..c8742e5f 100644 --- a/gym_electric_motor/reference_generators/subepisoded_reference_generator.py +++ b/gym_electric_motor/reference_generators/subepisoded_reference_generator.py @@ -1,5 +1,5 @@ import numpy as np -from gym.spaces import Box +from gymnasium.spaces import Box from ..random_component import RandomComponent from ..core import ReferenceGenerator diff --git a/gym_electric_motor/reference_generators/switched_reference_generator.py b/gym_electric_motor/reference_generators/switched_reference_generator.py index 17d82026..48f3e9e1 100644 --- a/gym_electric_motor/reference_generators/switched_reference_generator.py +++ b/gym_electric_motor/reference_generators/switched_reference_generator.py @@ -1,5 +1,5 @@ import numpy as np -from gym.spaces import Box +from gymnasium.spaces import Box from ..random_component import RandomComponent from ..core import ReferenceGenerator @@ -47,7 +47,7 @@ def set_modules(self, physical_system): sub_generator.set_modules(physical_system) ref_space_low = np.min([sub_generator.reference_space.low for sub_generator in self._sub_generators], axis=0) ref_space_high = np.max([sub_generator.reference_space.high for sub_generator in self._sub_generators], axis=0) - self.reference_space = Box(ref_space_low, ref_space_high) + self.reference_space = Box(ref_space_low, ref_space_high, dtype=float) self._referenced_states = self._sub_generators[0].referenced_states for sub_generator in self._sub_generators: assert np.all(sub_generator.referenced_states == self._referenced_states), \ diff --git a/gym_electric_motor/reference_generators/zero_reference_generator.py b/gym_electric_motor/reference_generators/zero_reference_generator.py index 2a0fa698..fe10190b 100644 --- a/gym_electric_motor/reference_generators/zero_reference_generator.py +++ b/gym_electric_motor/reference_generators/zero_reference_generator.py @@ -1,5 +1,5 @@ import numpy as np -from gym.spaces import Box +from gymnasium.spaces import Box from ..core import ReferenceGenerator diff --git a/gym_electric_motor/utils.py b/gym_electric_motor/utils.py index b71f88c8..7c907f00 100644 --- a/gym_electric_motor/utils.py +++ b/gym_electric_motor/utils.py @@ -1,5 +1,5 @@ import numpy as np -import gym +import gymnasium def state_dict_to_state_array(state_dict, state_array, state_names): @@ -19,7 +19,7 @@ def state_dict_to_state_array(state_dict, state_array, state_names): for ind, key in enumerate(state_names): try: state_array[ind] = state_dict[key] - except KeyError: + except KeyError: # TODO pass @@ -158,5 +158,5 @@ def update_parameter_dict(source_dict, update_dict, copy=True): return new_dict -#: Short notation for the gym.make call to avoid the necessary import of gym when making environments. -make = gym.make +#: Short notation for the gymnasium.make call to avoid the necessary import of gym when making environments. +# make = gymnasium.make diff --git a/gym_electric_motor/visualization/console_printer.py b/gym_electric_motor/visualization/console_printer.py index 8b1941c3..6226c96b 100644 --- a/gym_electric_motor/visualization/console_printer.py +++ b/gym_electric_motor/visualization/console_printer.py @@ -54,7 +54,7 @@ def on_step_begin(self, k, action): self._k = k self._action = action - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): """Gets called at each step of the environment. Handles per step printing as well es constraint violation printing""" self._k = k @@ -62,7 +62,7 @@ def on_step_end(self, k, state, reference, reward, done): self._reference = reference self._reward = reward self._cum_reward += reward - self._done = done + self._done = terminated def render(self): if self._print_freq > 0: diff --git a/gym_electric_motor/visualization/motor_dashboard.py b/gym_electric_motor/visualization/motor_dashboard.py index e98c495c..8bd65e7f 100644 --- a/gym_electric_motor/visualization/motor_dashboard.py +++ b/gym_electric_motor/visualization/motor_dashboard.py @@ -1,7 +1,7 @@ from gym_electric_motor.core import ElectricMotorVisualization from .motor_dashboard_plots import StatePlot, ActionPlot, RewardPlot, TimePlot, EpisodePlot, StepPlot import matplotlib.pyplot as plt -import gym +import gymnasium class MotorDashboard(ElectricMotorVisualization): @@ -33,7 +33,7 @@ def update_interval(self): def __init__( self, state_plots=(), action_plots=(), reward_plot=False, additional_plots=(), - update_interval=1000, time_plot_width=10000, style=None + update_interval=1000, time_plot_width=10000, style=None, scale_plots = None ): """ Args: @@ -90,6 +90,9 @@ def __init__( self._k = 0 self._update_render = False + #self._scale_plots = scale_plots + + def on_reset_begin(self): """Called before the environment is reset. All subplots are reset.""" for plot in self._plots: @@ -115,7 +118,7 @@ def on_step_begin(self, k, action): for plot in self._plots: plot.on_step_begin(k, action) - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): """The information after the step is passed Args: @@ -124,10 +127,10 @@ def on_step_end(self, k, state, reference, reward, done): reference(array(float)): The reference corresponding to the state :math:`s^*_k`. reward(float): The reward that has been received for the last action that lead to the current state :math:`r_{k}`. - done(bool): Flag, that indicates, if the last action lead to a terminal state :math:`t_{k}`. + terminated(bool): Flag, that indicates, if the last action lead to a terminal state :math:`t_{k}`. """ for plot in self._plots: - plot.on_step_end(k, state, reference, reward, done) + plot.on_step_end(k, state, reference, reward, terminated) self._k += 1 if self._k % self._update_interval == 0: self._update_render = True @@ -152,9 +155,9 @@ def set_env(self, env): if self._state_plots == 'all': self._state_plots = state_names if self._action_plots == 'all': - if type(env.action_space) is gym.spaces.Discrete: + if type(env.action_space) is gymnasium.spaces.Discrete: self._action_plots = [0] - elif type(env.action_space) in (gym.spaces.Box, gym.spaces.MultiDiscrete): + elif type(env.action_space) in (gymnasium.spaces.Box, gymnasium.spaces.MultiDiscrete): self._action_plots = list(range(env.action_space.shape[0])) self._time_plots = [] @@ -165,7 +168,7 @@ def set_env(self, env): self._time_plots.append(StatePlot(state)) if len(self._action_plots) > 0: - assert type(env.action_space) in (gym.spaces.Box, gym.spaces.Discrete, gym.spaces.MultiDiscrete), \ + assert type(env.action_space) in (gymnasium.spaces.Box, gymnasium.spaces.Discrete, gymnasium.spaces.MultiDiscrete), \ f'Action space of type {type(env.action_space)} not supported for plotting.' for action in self._action_plots: ap = ActionPlot(action) @@ -270,11 +273,14 @@ def _initialize_figures_window(self): for plot, axis in zip(self._time_plots, axes_step): plot.initialize(axis) + self._figures[0].align_ylabels() + def _update(self): """Called every *update cycle* steps to refresh the figure.""" for plot in self._plots: plot.render() for fig in self._figures: + #fig.align_ylabels() fig.canvas.draw() fig.canvas.flush_events() diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/action_plot.py b/gym_electric_motor/visualization/motor_dashboard_plots/action_plot.py index 99431998..c47a9a19 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/action_plot.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/action_plot.py @@ -1,4 +1,4 @@ -from gym.spaces import Box, Discrete, MultiDiscrete +from gymnasium.spaces import Box, Discrete, MultiDiscrete import numpy as np from .base_plots import TimePlot diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/base_plots.py b/gym_electric_motor/visualization/motor_dashboard_plots/base_plots.py index 80fe6be8..3dd20f4d 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/base_plots.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/base_plots.py @@ -172,10 +172,10 @@ def on_reset_begin(self): self._reset_memory.append(self._t) self._done = False - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): self._k += 1 self._t += self._tau - self._done = done + self._done = terminated def render(self): super().render() @@ -195,6 +195,15 @@ def _scale_x_axis(self): lower_lim = upper_lim - self._x_width * self._tau self._axis.set_xlim(lower_lim, upper_lim) + def _scale_y_axis(self): + if self._scale_plots_to_data: + + y_min = min(np.nanmin(self._y_data[0]), np.nanmin(self._y_data[1])) + y_max = max(np.nanmax(self._y_data[0]), np.nanmax(self._y_data[1])) + + self._axis.set_ylim(y_min-np.sign(y_min)*0.1*y_min, + y_max+np.sign(y_max)*0.1*y_max) + class EpisodePlot(MotorDashboardPlot): """Base Plot class that all episode based plots .""" diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/cumulative_constraint_violation_plot.py b/gym_electric_motor/visualization/motor_dashboard_plots/cumulative_constraint_violation_plot.py index acd4d489..43b51214 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/cumulative_constraint_violation_plot.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/cumulative_constraint_violation_plot.py @@ -20,9 +20,9 @@ def reset_data(self): super().reset_data() self._violations = [0] - def on_step_end(self, k, state, reference, reward, done): - super().on_step_end(k, state, reference, reward, done) - if done: + def on_step_end(self, k, state, reference, reward, terminated): + super().on_step_end(k, state, reference, reward, terminated) + if terminated: # Add another point for a step-like plot self._x_data.append(self._k - 1) self._violations.append(self._no_of_violations) diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/episode_length_plot.py b/gym_electric_motor/visualization/motor_dashboard_plots/episode_length_plot.py index a171cda6..f4068434 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/episode_length_plot.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/episode_length_plot.py @@ -21,7 +21,7 @@ def initialize(self, axis): super().initialize(axis) self._lines.append(self._axis.plot([], [], color=self._colors[0])[0]) - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): self._episode_length = k def reset_data(self): diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/mean_episode_reward_plot.py b/gym_electric_motor/visualization/motor_dashboard_plots/mean_episode_reward_plot.py index ce98c2d3..418258a8 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/mean_episode_reward_plot.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/mean_episode_reward_plot.py @@ -22,8 +22,8 @@ def initialize(self, axis): self._y_data.append(self._reward_data) self._lines.append(self._axis.plot([], self._reward_data, color=self._colors[0])[0]) - def on_step_end(self, k, state, reference, reward, done): - super().on_step_end(k, state, reference, reward, done) + def on_step_end(self, k, state, reference, reward, terminated): + super().on_step_end(k, state, reference, reward, terminated) self._reward_sum += reward self._episode_length = k diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/reward_plot.py b/gym_electric_motor/visualization/motor_dashboard_plots/reward_plot.py index 354437bc..8a2b1d63 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/reward_plot.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/reward_plot.py @@ -34,8 +34,8 @@ def reset_data(self): super().reset_data() self._reward_data = np.full(shape=self._x_data.shape, fill_value=np.nan) - def on_step_end(self, k, state, reference, reward, done): + def on_step_end(self, k, state, reference, reward, terminated): idx = self.data_idx self._x_data[idx] = self._t self._reward_data[idx] = reward - super().on_step_end(k, state, reference, reward, done) + super().on_step_end(k, state, reference, reward, terminated) diff --git a/gym_electric_motor/visualization/motor_dashboard_plots/state_plot.py b/gym_electric_motor/visualization/motor_dashboard_plots/state_plot.py index 9f278d9e..83930b04 100644 --- a/gym_electric_motor/visualization/motor_dashboard_plots/state_plot.py +++ b/gym_electric_motor/visualization/motor_dashboard_plots/state_plot.py @@ -71,6 +71,10 @@ def __init__(self, state): # Flag, if the passed data is normalized self._normalized = True + self._scale_plots_to_data = False + + + def set_env(self, env): # Docstring of superclass super().set_env(env) @@ -97,6 +101,10 @@ def set_env(self, env): # Set the y-axis label self._label = self.state_labels.get(self._state, self._state) + self._scale_plots_to_data = env.scale_plots + + + def reset_data(self): super().reset_data() # Initialize the data containers @@ -138,8 +146,8 @@ def initialize(self, axis): self._y_data = [self._state_data, self._ref_data] - def on_step_end(self, k, state, reference, reward, done): - super().on_step_end(k, state, reference, reward, done) + def on_step_end(self, k, state, reference, reward, terminated): + super().on_step_end(k, state, reference, reward, terminated) # Write the data to the data containers state_ = state[self._state_idx] ref = reference[self._state_idx] diff --git a/requirements.txt b/requirements.txt index 36077ac8..428fdccb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ scipy>=1.4.1 gym<0.24.0,>=0.15.4 pytest>=5.2.2 pytest-cov +gymnasium>=0.29.0 \ No newline at end of file diff --git a/tests/conf.py b/tests/conf.py index 830ee6c3..d50214e0 100644 --- a/tests/conf.py +++ b/tests/conf.py @@ -2,7 +2,7 @@ from matplotlib import pyplot as plt import matplotlib from gym_electric_motor.core import * -from gym.spaces import Box +from gymnasium.spaces import Box import pytest # region parameter definition diff --git a/tests/integration_tests/test_environment_execution.py b/tests/integration_tests/test_environment_execution.py index 2815f905..f9e2b267 100644 --- a/tests/integration_tests/test_environment_execution.py +++ b/tests/integration_tests/test_environment_execution.py @@ -16,14 +16,14 @@ def test_execution(dc_motor, control_task, action_type, version, no_of_steps): env_id = f'{action_type}-{control_task}-{dc_motor}-{version}' env = gem.make(env_id) - done = True + terminated = True for i in range(no_of_steps): - if done: + if terminated: observation = env.reset() state, reference = observation action = env.action_space.sample() assert action in env.action_space - observation, reward, done, info = env.step(action) + observation, reward, terminated, truncated, info = env.step(action) assert not np.any(np.isnan(observation[0])), 'An invalid nan-value is in the state.' assert not np.any(np.isnan(observation[1])), 'An invalid nan-value is in the reference.' assert info == {} diff --git a/tests/integration_tests/test_environment_seeding.py b/tests/integration_tests/test_environment_seeding.py index db5c6cfb..c036d437 100644 --- a/tests/integration_tests/test_environment_seeding.py +++ b/tests/integration_tests/test_environment_seeding.py @@ -19,41 +19,37 @@ def test_seeding_same_env(dc_motor, control_task, action_type, version, no_of_st """This test assures that an environment that is seeded two times with the same seed generates the same episodes.""" env_id = f'{action_type}-{control_task}-{dc_motor}-{version}' env = gem.make(env_id) - # Seed the environment initially - env.seed(seed) # Sample actions that are used in both executions actions = [env.action_space.sample() for _ in range(no_of_steps)] - done = True + terminated = True states1 = [] references1 = [] rewards1 = [] - done1 = [] + terminated1 = [] # Execute the env for i in range(no_of_steps): - if done: - state, reference = env.reset() - (state, reference), reward, done, info = env.step(actions[i]) + if terminated: + state, reference = env.reset(seed) + (state, reference), reward, terminated, truncated, info = env.step(actions[i]) rewards1.append(reward) states1.append(state) references1.append(reference) - done1.append(done) + terminated1.append(terminated) - # Seed the environment again with the same seed - env.seed(seed) - done = True + terminated = True states2 = [] references2 = [] rewards2 = [] - done2 = [] + terminated2 = [] # Execute the environment again for i in range(no_of_steps): - if done: - state, reference = env.reset() - (state, reference), reward, done, info = env.step(actions[i]) + if terminated: + state, reference = env.reset(seed) + (state, reference), reward, terminated, truncated, info = env.step(actions[i]) rewards2.append(reward) states2.append(state) references2.append(reference) - done2.append(done) + terminated2.append(terminated) # Assure that the epsiodes of the initially and reseeded environment are equal references1 = np.array(references1).flatten() @@ -61,7 +57,7 @@ def test_seeding_same_env(dc_motor, control_task, action_type, version, no_of_st assert(np.all(np.array(states1) == np.array(states2))) assert(np.all(np.array(references1).flatten() == np.array(references2).flatten())) assert(np.all(np.array(rewards1) == np.array(rewards2))) - assert (np.all(np.array(done1) == np.array(done2))) + assert (np.all(np.array(terminated1) == np.array(terminated2))) @pytest.mark.parametrize('no_of_steps', [100]) @@ -74,45 +70,43 @@ def test_seeding_new_env(dc_motor, control_task, action_type, version, no_of_ste """This test assures that two equal environments that are seeded with the same seed generate the same episodes.""" env_id = f'{action_type}-{control_task}-{dc_motor}-{version}' env = gem.make(env_id) - env.seed(seed) actions = [env.action_space.sample() for _ in range(no_of_steps)] - done = True + terminated = True states1 = [] references1 = [] rewards1 = [] - done1 = [] + terminated1 = [] for i in range(no_of_steps): - if done: - state, reference = env.reset() - (state, reference), reward, done, info = env.step(actions[i]) + if terminated: + state, reference = env.reset(seed) + (state, reference), reward, terminated, truncated, info = env.step(actions[i]) rewards1.append(reward) states1.append(state) references1.append(reference) - done1.append(done) + terminated1.append(terminated) env = gem.make(env_id) - env.seed(seed) - done = True + terminated = True states2 = [] references2 = [] rewards2 = [] - done2 = [] + terminated2 = [] for i in range(no_of_steps): - if done: - state, reference = env.reset() + if terminated: + state, reference = env.reset(seed) action = env.action_space.sample() assert action in env.action_space - (state, reference), reward, done, info = env.step(actions[i]) + (state, reference), reward, terminated, truncated, info = env.step(actions[i]) rewards2.append(reward) states2.append(state) references2.append(reference) - done2.append(done) + terminated2.append(terminated) # Assure that the episodes of both environments are equal assert (np.all(np.array(states1) == np.array(states2))) assert (np.all(np.array(references1).flatten() == np.array(references2).flatten())) assert (np.all(np.array(rewards1) == np.array(rewards2))) - assert (np.all(np.array(done1) == np.array(done2))) + assert (np.all(np.array(terminated1) == np.array(terminated2))) diff --git a/tests/test_core.py b/tests/test_core.py index 00f57bd7..fd8034fd 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2,12 +2,12 @@ import numpy as np from tests.testing_utils import DummyPhysicalSystem, DummyReferenceGenerator, DummyRewardFunction, DummyVisualization,\ DummyCallback, DummyConstraintMonitor, DummyConstraint, mock_instantiate, instantiate_dict -from gym.spaces import Tuple, Box +from gymnasium.spaces import Tuple, Box import gym_electric_motor from gym_electric_motor.core import ElectricMotorEnvironment, RewardFunction, \ ReferenceGenerator, PhysicalSystem, ConstraintMonitor, Constraint from gym_electric_motor.constraints import LimitConstraint -import gym +import gymnasium import gym_electric_motor as gem @@ -86,6 +86,7 @@ def test_initialization( state_space = Box( physical_system.state_space.low[state_idxs], physical_system.state_space.high[state_idxs], + dtype=float ) assert Tuple( (state_space, reference_generator.reference_space) @@ -131,7 +132,7 @@ def test_step(self, env, action, set_done): for callback in cbs: assert callback.step_begin == 0 assert callback.step_end == 0 - (state, reference), reward, done, _ = env.step(action) + (state, reference), reward, terminated, truncated, _ = env.step(action) # Each of callback's step functions were called in step for callback in cbs: assert callback.step_begin == 1 @@ -143,7 +144,7 @@ def test_step(self, env, action, set_done): 'State passed to the Reference Generator not equal to Physical System state' assert ps.action == action, 'Action passed to Physical System not equal to selected action' assert reward == -1 if set_done else 1 - assert done == set_done + assert terminated == set_done # If episode terminated, no further step without reset if set_done: with pytest.raises(Exception): @@ -254,8 +255,8 @@ def test_referenced_states(self, reference_generator): class TestPhysicalSystem: def test_initialization(self): - action_space = gym.spaces.Discrete(3) - state_space = gym.spaces.Box(-1, 1, shape=(3,)) + action_space = gymnasium.spaces.Discrete(3) + state_space = gymnasium.spaces.Box(-1, 1, shape=(3,)) state_names = [f'dummy_state_{i}' for i in range(3)] tau = 1 ps = PhysicalSystem(action_space, state_space, state_names, tau) diff --git a/tests/test_physical_system_wrappers/test_cos_sin_processor.py b/tests/test_physical_system_wrappers/test_cos_sin_processor.py index 279bbabc..bffa3cc6 100644 --- a/tests/test_physical_system_wrappers/test_cos_sin_processor.py +++ b/tests/test_physical_system_wrappers/test_cos_sin_processor.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import pytest import numpy as np import gym_electric_motor as gem @@ -22,7 +22,7 @@ def test_nominal_state(self, processor, physical_system): def test_state_space(self, processor, physical_system): low = np.concatenate((physical_system.state_space.low, [-1, -1])) high = np.concatenate((physical_system.state_space.high, [1, 1])) - space = gym.spaces.Box(low, high) + space = gymnasium.spaces.Box(low, high, dtype=float) assert processor.state_space == space def test_reset(self, processor, physical_system): diff --git a/tests/test_physical_system_wrappers/test_dead_time_processor.py b/tests/test_physical_system_wrappers/test_dead_time_processor.py index d325ee78..89e05fba 100644 --- a/tests/test_physical_system_wrappers/test_dead_time_processor.py +++ b/tests/test_physical_system_wrappers/test_dead_time_processor.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import pytest import numpy as np import gym_electric_motor as gem @@ -32,22 +32,22 @@ def test_simulate(self, reset_processor, physical_system, action): ['action_space', 'actions', 'reset_action'], [ [ - gym.spaces.Box(-100, 100, shape=(3,)), + gymnasium.spaces.Box(-100, 100, shape=(3,)), [np.array([1., 2., 3.]), np.array([0., 1., 2.]), np.array([-1, 2, 3])], np.array([0., 0., 0.]) ], [ - gym.spaces.Box(-100, 100, shape=(1,)), + gymnasium.spaces.Box(-100, 100, shape=(1,)), [np.array([-1.]), np.array([0.]), np.array([-5.]), np.array([-6.]), np.array([-7.])], np.array([0.]) ], [ - gym.spaces.MultiDiscrete([10, 20, 30]), + gymnasium.spaces.MultiDiscrete([10, 20, 30]), [[5, 8, 7], [3, 4, 5], [0, 0, 1], [0, 1, 1], [0, 0, 1]], [0, 0, 0] ], [ - gym.spaces.Discrete(12), + gymnasium.spaces.Discrete(12), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0 ] @@ -67,7 +67,7 @@ def test_execution(self, unset_processor, physical_system, action_space, actions @pytest.mark.parametrize('processor', [gem.physical_system_wrappers.DeadTimeProcessor()]) def test_false_action_space(self, processor, physical_system): - physical_system._action_space = gym.spaces.MultiBinary(5) + physical_system._action_space = gymnasium.spaces.MultiBinary(5) with pytest.raises(AssertionError): assert processor.set_physical_system(physical_system) diff --git a/tests/test_physical_system_wrappers/test_dq_to_abc_action_processor.py b/tests/test_physical_system_wrappers/test_dq_to_abc_action_processor.py index 84de3efc..14deaca1 100644 --- a/tests/test_physical_system_wrappers/test_dq_to_abc_action_processor.py +++ b/tests/test_physical_system_wrappers/test_dq_to_abc_action_processor.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import pytest import numpy as np import gym_electric_motor as gem @@ -20,7 +20,7 @@ def processor(self, physical_system): return gem.physical_system_wrappers.DqToAbcActionProcessor.make('PMSM', physical_system=physical_system) def test_action_space(self, processor, physical_system): - space = gym.spaces.Box(-1, 1, shape=(2,), dtype=np.float64) + space = gymnasium.spaces.Box(-1, 1, shape=(2,), dtype=np.float64) assert processor.action_space == space @pytest.mark.parametrize( diff --git a/tests/test_physical_system_wrappers/test_flux_observer.py b/tests/test_physical_system_wrappers/test_flux_observer.py index ab562a97..2a8826fe 100644 --- a/tests/test_physical_system_wrappers/test_flux_observer.py +++ b/tests/test_physical_system_wrappers/test_flux_observer.py @@ -1,4 +1,4 @@ -import gym +import gymnasium import pytest import numpy as np import gym_electric_motor as gem @@ -44,7 +44,7 @@ def test_state_space(self, processor, physical_system): psi_abs_max = 200.0 low = np.concatenate((physical_system.state_space.low, [-psi_abs_max, -np.pi])) high = np.concatenate((physical_system.state_space.high, [psi_abs_max, np.pi])) - space = gym.spaces.Box(low, high, dtype=np.float64) + space = gymnasium.spaces.Box(low, high, dtype=np.float64) assert processor.state_space == space def test_reset(self, processor, physical_system): diff --git a/tests/test_physical_systems/test_converters.py b/tests/test_physical_systems/test_converters.py index 10695061..4096a82c 100644 --- a/tests/test_physical_systems/test_converters.py +++ b/tests/test_physical_systems/test_converters.py @@ -7,7 +7,7 @@ import tests.conf as cf from gym_electric_motor.utils import make_module from random import seed, uniform, randint -from gym.spaces import Discrete, Box +from gymnasium.spaces import Discrete, Box # region first version tests diff --git a/tests/test_physical_systems/test_mechanical_loads.py b/tests/test_physical_systems/test_mechanical_loads.py index 2805163e..d7dfc849 100644 --- a/tests/test_physical_systems/test_mechanical_loads.py +++ b/tests/test_physical_systems/test_mechanical_loads.py @@ -1,7 +1,7 @@ import pytest import gym_electric_motor as gem from gym_electric_motor.physical_systems import PolynomialStaticLoad, MechanicalLoad, ConstantSpeedLoad, ExternalSpeedLoad -from gym.spaces import Box +from gymnasium.spaces import Box import numpy as np from scipy import signal import math @@ -118,7 +118,7 @@ def test_MechanicalLoad_reset(concreteMechanicalLoad): # random testcase for the necessary parameters needed for initialization test_positions = {'omega': 0} test_nominal = np.array([80]) - # gym.Box state space with random size + # gymnasium.Box state space with random size test_space = Box(low=-1.0, high=1.0, shape=(3,)) # set additional random kwargs resetVal = concreteMechanicalLoad.reset(a=7, b=9, @@ -216,7 +216,7 @@ def test_mechanical_ode(self, const_speed_load): def test_reset(self, const_speed_load): test_positions = {'omega': 0} test_nominal = np.array([80]) - # gym.Box state space with random size + # gymnasium.Box state space with random size test_space = Box(low=-1.0, high=1.0, shape=(3,)) reset_val = const_speed_load.reset(state_positions=test_positions, nominal_state=test_nominal, @@ -286,7 +286,7 @@ def test_mechanical_ode(self, ext_speed_load, omega, expected_result): def test_reset(self, ext_speed_load): test_positions = {'omega': 0} test_nominal = np.array([80]) - # gym.Box state space with random size + # gymnasium.Box state space with random size test_space = Box(low=-1.0, high=1.0, shape=(3,)) reset_var = ext_speed_load.reset(state_positions=test_positions, nominal_state=test_nominal, diff --git a/tests/test_physical_systems/test_physical_systems.py b/tests/test_physical_systems/test_physical_systems.py index 264ea64d..1c12f42f 100644 --- a/tests/test_physical_systems/test_physical_systems.py +++ b/tests/test_physical_systems/test_physical_systems.py @@ -3,7 +3,7 @@ mock_instantiate, instantiate_dict from gym_electric_motor.physical_systems import physical_systems as ps, converters as cv, electric_motors as em,\ mechanical_loads as ml, voltage_supplies as vs, solvers as sv -from gym.spaces import Box +from gymnasium.spaces import Box import pytest @@ -41,7 +41,8 @@ def scml_system(self, monkeypatch): '_build_state_space', lambda _, state_names: Box( low=np.zeros_like(state_names, dtype=float), - high=np.zeros_like(state_names, dtype=float) + high=np.zeros_like(state_names, dtype=float), + dtype=float ) ) return self.class_to_test( diff --git a/tests/test_reference_generators/test_reference_generators.py b/tests/test_reference_generators/test_reference_generators.py index 1ea86769..94fa46ca 100644 --- a/tests/test_reference_generators/test_reference_generators.py +++ b/tests/test_reference_generators/test_reference_generators.py @@ -1,4 +1,4 @@ -import gym +import gymnasium from numpy.random import seed import numpy.random as rd import pytest @@ -196,12 +196,12 @@ def test_set_modules(self, monkeypatch, setup): sub_generator[0]._limit_margin = (1, 0) sub_generator[1]._limit_margin = (0, 0.5) - expected_space = gym.spaces.Box(-1, 0.5, shape=(1,)) + expected_space = gymnasium.spaces.Box(-1, 0.5, shape=(1,)) self._sub_generator = sub_generator test_object = SwitchedReferenceGenerator(sub_generator) self._physical_system = DummyPhysicalSystem(7) - self._physical_system._state_space = gym.spaces.Box(-1, 1, shape=self._physical_system.state_space.shape) + self._physical_system._state_space = gymnasium.spaces.Box(-1, 1, shape=self._physical_system.state_space.shape) # call function to test test_object.set_modules(self._physical_system) # verify the expected results @@ -705,14 +705,14 @@ def physical_system(self): @pytest.fixture def reference_generator(self, physical_system): - rg = ConstReferenceGenerator(reference_state=physical_system.state_names[1], reference_value=1) + rg = ConstReferenceGenerator(reference_state=physical_system.state_names[1], reference_value=1.0) rg.set_modules(physical_system) return rg @pytest.mark.parametrize('reference_value, reference_state', [(0.8, 'abc')]) def test_initialization(self, reference_value, reference_state): rg = ConstReferenceGenerator(reference_value=reference_value, reference_state=reference_state) - assert rg.reference_space == Box(np.array([reference_value]), np.array([reference_value])) + assert rg.reference_space == Box(np.array([reference_value]), np.array([reference_value]), dtype=np.float64) assert rg._reference_value == reference_value assert rg._reference_state == reference_state diff --git a/tests/testing_utils.py b/tests/testing_utils.py index ff49b8bd..0272261b 100644 --- a/tests/testing_utils.py +++ b/tests/testing_utils.py @@ -8,7 +8,7 @@ import gym_electric_motor.physical_systems.converters as cv from gym_electric_motor.physical_systems.physical_systems import SCMLSystem import numpy as np -from gym.spaces import Box, Discrete +from gymnasium.spaces import Box, Discrete from scipy.integrate import ode from tests.conf import system, jacobian, permex_motor_parameter from gym_electric_motor.utils import instantiate @@ -199,7 +199,7 @@ def __init__(self, **kwargs): self.last_action = None self.last_time_step = None self.closed = False - self.done = False + self.terminated = False self.kwargs = kwargs super().__init__()