nominal_values = {key: 0.7 * limit for key, limit in limit_values.items()} # Create the environment env = gem.make( 'emotor-pmsm-cont-v1', # Pass a class with extra parameters visualization=MotorDashboard, visu_period=1, load=ConstantSpeedLoad(omega_fixed=1000 * np.pi / 30), control_space='dq', # Pass a string (with extra parameters) ode_solver='scipy.solve_ivp', solver_kwargs={}, # Pass an instance reference_generator=rg, plotted_variables=['i_sq', 'i_sd', 'u_sq', 'u_sd'], reward_weights={ 'i_sq': 1000, 'i_sd': 1000 }, reward_power=0.5, observed_states=['i_sq', 'i_sd'], dead_time=True, u_sup=400, motor_parameter=motor_parameter, limit_values=limit_values, nominal_values=nominal_values, state_filter=['i_sq', 'i_sd', 'epsilon']) # Due to the dead time in the system, the env = AppendLastActionWrapper(env)
from rl.agents import DDPGAgent from rl.memory import SequentialMemory from rl.random import GaussianWhiteNoiseProcess from gym_electric_motor.reference_generators import MultiReferenceGenerator, WienerProcessReferenceGenerator, \ StepReferenceGenerator, SinusoidalReferenceGenerator from gym_electric_motor.visualization import MotorDashboard from gym.wrappers import FlattenObservation # Create the environment env = gem.make( 'emotor-dc-series-cont-v1', # Pass a class with extra parameters visualization=MotorDashboard, visu_period=1, # Take standard class and pass parameters (Load) load_parameter=dict(a=0, b=.0, c=0.0, j_load=.5), # Pass a string (with extra parameters) ode_solver='euler', solver_kwargs={}, # Pass an instance reference_generator=WienerProcessReferenceGenerator(reference_state='i')) # Keras-rl DDPG-agent only accepts flat observations env = FlattenObservation(env) nb_actions = env.action_space.shape[0] actor = Sequential() actor.add(Flatten(input_shape=(1, ) + env.observation_space.shape)) actor.add(Dense(16)) actor.add(Activation('relu')) actor.add(Dense(16))
env = gem.make( # Choose the permanent magnet synchronous motor with continuous-control-set 'PMSMCont-v1', # Set the mechanical load to have constant speed load=ConstantSpeedLoad(omega_fixed=1000 * np.pi / 30), # Set the frame of control inputs, dq is the flux oriented coordinate system control_space='dq', # Define which numerical solver is to be used for the simulation ode_solver='scipy.solve_ivp', solver_kwargs={}, # Pass the previously defined reference generator reference_generator=rg, # Set weighting of different addends of the reward function reward_weights={ 'i_sq': 1000, 'i_sd': 1000 }, # Exponent of the reward function # Here we use a square root function reward_power=0.5, # Define which state variables are to be monitored concerning limit violations # Here, only overcurrent will lead to termination observed_states=['i_sq', 'i_sd'], # Consider converter dead time within the simulation # This means that a given action will show effect only with one step delay # This is realistic behavior of drive applications dead_time=True, # Set the DC-link supply voltage u_sup=400, # Pass the previously defined motor parameters motor_parameter=motor_parameter, # Pass the updated motor limits and nominal values limit_values=limit_values, nominal_values=nominal_values, # Define which states will be shown in the state observation (what we can "measure") state_filter=['i_sd', 'i_sq', 'epsilon'], # Defines which variables to plot via the builtin dashboard monitor visualization=MotorDashboard( plots=['i_sd', 'i_sq', 'action_0', 'action_1', 'mean_reward']), visu_period=1, )
sys.path.append(os.path.abspath(os.path.join('..'))) import gym_electric_motor as gem from gym_electric_motor.reference_generators import * from gym_electric_motor.visualization import MotorDashboard if __name__ == '__main__': env = gem.make( 'emotor-dc-series-cont-v1', # Pass an instance visualization=MotorDashboard(plotted_variables=['all'], visu_period=1), # Take standard class and pass parameters (Load) load_parameter=dict(a=0.01, b=.1, c=0.1, j_load=.05), # Pass a string (with extra parameters) ode_solver='euler', solver_kwargs={}, # Pass a Class with extra parameters reference_generator=MultiReferenceGenerator( sub_generators=[ SinusoidalReferenceGenerator, WienerProcessReferenceGenerator(), StepReferenceGenerator() ], p=[0.1, 0.8, 0.1], super_episode_length=(1000, 10000))) controller = Controller.make('cascaded_pi', env) state, reference = env.reset() start = time.time() cum_rew = 0 for i in range(100000): env.render()
import gym_electric_motor as gem from gym_electric_motor.visualization import MotorDashboard from gym_electric_motor.reference_generators import WienerProcessReferenceGenerator if __name__ == '__main__': # Run the option parsing # Get the environment and extract the number of actions. env = gem.make( 'emotor-dc-series-disc-v1', state_filter=['i'], # Pass an instance visualization=MotorDashboard(visu_period=0.5, plotted_variables=['omega', 'i', 'u']), converter='Disc-4QC', # Take standard class and pass parameters (Load) a=0, b=.1, c=1.1, j_load=0.4, # Pass a string (with extra parameters) ode_solver='euler', solver_kwargs={}, # Pass a Class with extra parameters reference_generator=WienerProcessReferenceGenerator( reference_state='i', sigma_range=(5e-3, 5e-1))) nb_actions = env.action_space.n env = FlattenObservation(env) model = Sequential() model.add(Flatten(input_shape=(1, ) + env.observation_space.shape)) model.add(Dense(4)) model.add(LeakyReLU(alpha=0.05)) model.add(Dense(4))
env = gem.make( # Define the series DC motor with continuous-control-set 'DcSeriesCont-v1', # Set the parameters of the motor motor_parameter=dict(r_a=2.5, r_e=4.5, l_a=9.7e-3, l_e_prime=9.2e-3, l_e=9.2e-3, j_rotor=0.001), # Set the parameters of the mechanical polynomial load (the default load class) load_parameter=dict(a=0, b=.0, c=0.01, j_load=.001), # Weighting of different addends of the reward function # This can be used to assign higher or lower priorities to different states # As only one state is weighted here, the value does not make a major difference reward_weights={'omega': 1000}, # Exponent of the reward function # Here we use a square root function reward_power=0.5, # Define which state variables are to be monitored concerning limit violations # None means that a limit violation will never trigger an env.reset observed_states=None, # Define which numerical solver is to be used for the simulation ode_solver='scipy.solve_ivp', solver_kwargs=dict(method='BDF'), # Define and parameterize the reference generator for the speed reference reference_generator=WienerProcessReferenceGenerator(reference_state='omega', sigma_range=(5e-3, 1e-2)), # Defines which variables to plot via the builtin dashboard monitor visualization=MotorDashboard(['omega', 'torque', 'i', 'u', 'u_sup', 'reward']), visu_period=1, )
if __name__ == '__main__': """ Continuous mode: The action is the average (normalized) voltage per time step which is assumed to be transferred to a PWM/SVM converter to generate the switching sequence. Discrete mode: The action is the switching state of the power converter i.e., a quantity from a discrete set of switching states which can be generated by the converter. """ env = gem.make('DcPermExDisc-v1', visualization=MotorDashboard( plots=['omega', 'torque', 'i', 'u', 'u_sup'], visu_period=1), ode_solver='scipy.solve_ivp', solver_kwargs=dict(), reference_generator=rg.SwitchedReferenceGenerator( sub_generators=[ rg.SinusoidalReferenceGenerator, rg.WienerProcessReferenceGenerator(), rg.StepReferenceGenerator() ], p=[0.1, 0.8, 0.1], super_episode_length=(1000, 10000))) # Assign a simple on/off controller controller = Controller.make('on_off', env) state, reference = env.reset() start = time.time() cum_rew = 0 for i in range(100000): env.render() action = controller.control(state, reference)
def test_make(self): if self.key != '': env = gem.make(self.key) assert type(env) == self.test_class
Continuous mode: The action is the average (normalized) voltage per time step which is assumed to be transferred to a PWM converter to generate the switching sequence. Discrete mode: The action is the switching state of the power converter i.e., a quantity from a discrete set of switching states which can be generated by the converter. """ env = gem.make( 'DcSeriesCont-v1', # replace with 'DcSeriesDisc-v1' for discrete controllers state_filter=['omega', 'i'], # Pass an instance visualization=MotorDashboard(plots=['i', 'omega']), # Take standard class and pass parameters (Load) motor_parameter=dict(r_a=15e-3, r_e=15e-3, l_a=100e-3, l_e=100e-3), load_parameter=dict(a=0, b=.1, c=.1, j_load=0.04), # Pass a string (with extra parameters) ode_solver='scipy.solve_ivp', solver_kwargs={}, # Pass a Class with extra parameters reference_generator=rg.WienerProcessReferenceGenerator()) # Assign a PI-controller to the speed control problem controller = Controller.make('pi_controller', env) state, reference = env.reset() # get the system time to measure program duration start = time.time() cum_rew = 0
ref = 'omega' env = gem.make( #'DcExtExDisc-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i_a', 'i_e', 'u_a', 'u_e'], visu_period=1), motor_parameter=dict(j_rotor=0.00005), load_parameter={'a': 0, 'b': 0, 'c': 0, 'j_load': 0}, #'DcPermExDisc-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i', 'u'], visu_period=1), #'DcSeriesDisc-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i', 'u'], visu_period=1), #'DcShuntDisc-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i_a', 'i_e', 'u'], visu_period=1), motor_parameter=dict(j_rotor=0.01), load_parameter={'a': 0, 'b': 0, 'c': 0, 'j_load': 0}, #'DcExtExCont-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i_a', 'i_e', 'u_a', 'u_e'], visu_period=1), motor_parameter=dict(j_rotor=0.00005), load_parameter={'a': 0, 'b': 0, 'c': 0, 'j_load': 0}, 'DcPermExCont-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i', 'u'], visu_period=1), #'DcSeriesCont-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i', 'u'], visu_period=1), #'DcShuntCont-v1', visualization=MotorDashboard(plots=['omega', 'torque', 'i_a', 'i_e', 'u'], visu_period=1), ode_solver='scipy.solve_ivp', solver_kwargs=dict(), #load=ConstantSpeedLoad(omega_fixed=50 * np.pi / 30), reference_generator=rg.SwitchedReferenceGenerator( sub_generators=[ rg.SinusoidalReferenceGenerator(reference_state=ref, amplitude_range=(0, 0.3), offset_range=(0, 0.2)), rg.WienerProcessReferenceGenerator(reference_state=ref, amplitude_range=(0, 0.3), offset_range=(0, 0.2)), rg.StepReferenceGenerator(reference_state=ref, amplitude_range=(0, 0.3), offset_range=(0, 0.2)) ], p=[0.5, 0.25, 0.25], super_episode_length=(10000, 100000)), )
from gym_electric_motor.reference_generators import WienerProcessReferenceGenerator from gym_electric_motor.visualization import MotorDashboard if __name__ == '__main__': tf.compat.v1.disable_eager_execution() # Create the environment env = gem.make( 'emotor-dc-series-cont-v1', # Pass a class with extra parameters visualization=MotorDashboard, visu_period=1, motor_parameter=dict(r_a=1e-1, r_e=1e-1), # Take standard class and pass parameters (Load) load_parameter=dict(a=0, b=.0, c=0.05, j_load=.05), reward_weights={'omega': 1000}, reward_power=0.5, observed_states=None, # Pass a string (with extra parameters) ode_solver='euler', solver_kwargs={}, # Pass an instance reference_generator=WienerProcessReferenceGenerator( reference_state='omega', sigma_range=(5e-3, 1e-2))) # Keras-rl DDPG-agent accepts flat observations only env = FlattenObservation(env) nb_actions = env.action_space.shape[0] # CAUTION: Do not use layers that behave differently in training and # testing # (e.g. dropout, batch-normalization, etc..)
sys.path.append(os.path.abspath(os.path.join('..'))) import gym_electric_motor as gem from gym_electric_motor import reference_generators as rg from gym_electric_motor.visualization import MotorDashboard if __name__ == '__main__': env = gem.make( 'emotor-dc-series-cont-v1', # Pass an instance visualization=MotorDashboard(plotted_variables='all', visu_period=1), motor_parameter=dict(r_a=15e-3, r_e=15e-3, l_a=1e-3, l_e=1e-3), # Take standard class and pass parameters (Load) load_parameter=dict(a=0.01, b=.1, c=0.1, j_load=.06), # Pass a string (with extra parameters) ode_solver='scipy.solve_ivp', solver_kwargs=dict(), # Pass a Class with extra parameters reference_generator=rg.SwitchedReferenceGenerator( sub_generators=[ rg.SinusoidalReferenceGenerator, rg.WienerProcessReferenceGenerator(), rg.StepReferenceGenerator() ], p=[0.1, 0.8, 0.1], super_episode_length=(1000, 10000))) controller = Controller.make('cascaded_pi', env) state, reference = env.reset() start = time.time() cum_rew = 0 for i in range(100000): env.render()
def set_env(time_limit=True, gamma=0.99, N=0, M=0, training=True, callbacks=[]): # define motor arguments motor_parameter = dict( p=3, # [p] = 1, nb of pole pairs r_s=17.932e-3, # [r_s] = Ohm, stator resistance l_d=0.37e-3, # [l_d] = H, d-axis inductance l_q=1.2e-3, # [l_q] = H, q-axis inductance psi_p=65.65e-3, # [psi_p] = Vs, magnetic flux of the permanent magnet ) u_sup = 350 nominal_values = dict(omega=4000 * 2 * np.pi / 60, i=230, u=u_sup) limit_values = dict(omega=4000 * 2 * np.pi / 60, i=1.5 * 230, u=u_sup) q_generator = WienerProcessReferenceGenerator(reference_state='i_sq') d_generator = WienerProcessReferenceGenerator(reference_state='i_sd') rg = MultipleReferenceGenerator([q_generator, d_generator]) tau = 1e-5 max_eps_steps = 10000 if training: motor_initializer = { 'random_init': 'uniform', 'interval': [[-230, 230], [-230, 230], [-np.pi, np.pi]] } # motor_initializer={'random_init': 'gaussian'} reward_function = gem.reward_functions.WeightedSumOfErrors( observed_states=['i_sq', 'i_sd'], reward_weights={ 'i_sq': 10, 'i_sd': 10 }, constraint_monitor=SqdCurrentMonitor(), gamma=gamma, reward_power=1) else: motor_initializer = {'random_init': 'gaussian'} reward_function = gem.reward_functions.WeightedSumOfErrors( observed_states=['i_sq', 'i_sd'], reward_weights={ 'i_sq': 0.5, 'i_sd': 0.5 }, # comparable reward constraint_monitor=SqdCurrentMonitor(), gamma=0.99, # comparable reward reward_power=1) # creating gem environment env = gem.make( # define a PMSM with discrete action space "PMSMDisc-v1", # visualize the results visualization=MotorDashboard(plots=['i_sq', 'i_sd', 'reward']), # parameterize the PMSM and update limitations motor_parameter=motor_parameter, limit_values=limit_values, nominal_values=nominal_values, # define the random initialisation for load and motor load='ConstSpeedLoad', load_initializer={ 'random_init': 'uniform', }, motor_initializer=motor_initializer, reward_function=reward_function, # define the duration of one sampling step tau=tau, u_sup=u_sup, # turn off terminations via limit violation, parameterize the rew-fct reference_generator=rg, ode_solver='euler', callbacks=callbacks, ) # appling wrappers and modifying environment env.action_space = Discrete(7) eps_idx = env.physical_system.state_names.index('epsilon') i_sd_idx = env.physical_system.state_names.index('i_sd') i_sq_idx = env.physical_system.state_names.index('i_sq') if time_limit: gem_env = TimeLimit( AppendNLastActionsWrapper( AppendNLastOberservationsWrapper( EpsilonWrapper(FlattenObservation(env), eps_idx, i_sd_idx, i_sq_idx), N), M), max_eps_steps) else: gem_env = AppendNLastActionsWrapper( AppendNLastOberservationsWrapper( EpsilonWrapper(FlattenObservation(env), eps_idx, i_sd_idx, i_sq_idx), N), M) return gem_env
amplitude * np.sin(omega * t + phi_initial + phi) ] return u_abc return grid_voltage # Create the environment env = gem.make( # Choose the squirrel cage induction motor (SCIM) with continuous-control-set "SCIMCont-v1", # Define the numerical solver for the simulation ode_solver="scipy.ode", # Define which state variables are to be monitored concerning limit violations # "None" means, that limit violation will not necessitate an env.reset() observed_states=None, # Parameterize the mechanical load (we set everything to zero such that only j_rotor is significant) load_parameter=dict(a=0, b=0, c=0, j_load=0), # Set the sampling time tau=1e-5) tau = env._physical_system.tau limits = env._physical_system.limits # reset the environment such that the simulation can be started (state, reference) = env.reset() # We define these arrays in order to save our simulation results in them
sys.path.append(os.path.abspath(os.path.join('..'))) import gym_electric_motor as gem from gym_electric_motor.reward_functions import WeightedSumOfErrors from gym_electric_motor.visualization import MotorDashboard from gym_electric_motor.reference_generators import WienerProcessReferenceGenerator if __name__ == '__main__': env = gem.make( 'emotor-dc-series-disc-v1', state_filter=['omega', 'i'], # Pass an instance reward_function=WeightedSumOfErrors(observed_states='i'), visualization=MotorDashboard(update_period=1e-2, visu_period=1e-1, plotted_variables=['omega', 'i', 'u']), converter='Disc-1QC', # Take standard class and pass parameters (Load) motor_parameter=dict(r_a=15e-3, r_e=15e-3, l_a=1e-3, l_e=1e-3), load_parameter=dict(a=0, b=.1, c=.1, j_load=0.04), # Pass a string (with extra parameters) ode_solver='euler', solver_kwargs={}, # Pass a Class with extra parameters reference_generator=WienerProcessReferenceGenerator(reference_state='i', sigma_range=(3e-3, 3e-2)) ) env = FlattenObservation(env) nb_actions = env.action_space.n window_length = 1 model = Sequential() model.add(Flatten(input_shape=(window_length,) + env.observation_space.shape)) model.add(Dense(16, activation='relu'))
} # initializer for a specific speed load_init = {'states': {'omega': 20}} if __name__ == '__main__': env = gem.make( 'DcSeriesCont-v1', visualization=MotorDashboard(plots=['omega', 'i'], dark_mode=False), motor_parameter=dict(j_rotor=0.001), load_parameter=dict(a=0, b=0.1, c=0, j_load=0.001), ode_solver='scipy.solve_ivp', solver_kwargs=dict(), reference_generator=rg.SwitchedReferenceGenerator( sub_generators=[ rg.SinusoidalReferenceGenerator(reference_state='omega'), rg.WienerProcessReferenceGenerator(reference_state='omega'), rg.StepReferenceGenerator(reference_state='omega') ], p=[0.2, 0.6, 0.2], super_episode_length=(1000, 10000)), # Pass the predefined initializers motor_initializer=gaussian_init, load_initializer=uniform_init, ) # After the setup is done, we are ready to simulate the environment # We make use of a standard PI speed controller controller = Controller.make('pi_controller', env) start = time.time() cum_rew = 0
""" Continuous mode: The action is the average (normalized) voltage per time step which is assumed to be transferred to a PWM/SVM converter to generate the switching sequence. Discrete mode: The action is the switching state of the power converter i.e., a quantity from a discrete set of switching states which can be generated by the converter. """ env = gem.make( 'DcPermExDisc-v1', visualization=MotorDashboard( state_plots=['omega', 'torque', 'i', 'u', 'u_sup']), ode_solver='scipy.solve_ivp', solver_kwargs=dict(), reference_generator=rg.SwitchedReferenceGenerator( sub_generators=[ rg.SinusoidalReferenceGenerator, rg.WienerProcessReferenceGenerator(), rg.StepReferenceGenerator() ], p=[0.1, 0.8, 0.1], super_episode_length=(1000, 10000)), # Override the observation of the current limit of 'i' which is selected per default # The 'on_off' Controller cannot comply to any limits. constraints=()) # Assign a simple on/off controller controller = Controller.make('on_off', env) state, reference = env.reset() start = time.time() cum_rew = 0 for i in range(100000):
parser.add_argument("--mode", type=str, required=True) parser.add_argument("--output", type=str, default='outputs') parser.add_argument("--weights", type=str, default=None) parser.add_argument("--constrained", type=int, default=1) args = parser.parse_args() # Create the environment # Default DcSeries Motor Parameters are changed to have more dynamic system and to see faster learning results. env = gem.make( 'emotor-dc-series-cont-v1', # Pass a class with extra parameters visualization=MotorDashboard, visu_period=5, motor_parameter=dict(r_a=2.5, r_e=4.5, l_a=9.7e-3, l_e_prime=9.2e-3, l_e=9.2e-3, j_rotor=0.001), # Take standard class and pass parameters (Load) load_parameter=dict(a=0, b=.0, c=0.01, j_load=.001), reward_weights={'omega': 1000}, reward_power=0.5, observed_states=None, # Constraint violation monitoring is disabled for presentation purpose # Pass a string (with extra parameters) plotted_variables=['omega', 'i', 'u'], ode_solver='scipy.solve_ivp', solver_kwargs=dict(method='BDF'), # Pass an instance reference_generator=SquareReferenceGenerator(reference_state='omega') # reference_generator=WienerProcessReferenceGenerator(reference_state='omega', sigma_range=(5e-3, 1e-2)) ) density_max_func = interpolate.interp1d( x=[0.15, 0.2, 0.25, 0.3, 1.0], y=[120, 80, 10, 10, 10], kind='slinear', fill_value=10000, bounds_error=False,
# External speed profiles can be given by an ExternalSpeedLoad, # inital value is given by bias of the profile sampling_time = 1e-4 if __name__ == '__main__': # Create the environment env = gem.make( 'DcSeriesCont-v1', ode_solver='scipy.solve_ivp', solver_kwargs=dict(), tau=sampling_time, reference_generator=const_switch_gen, visualization=MotorDashboard(state_plots=['omega', 'i'], reward_plot=True), # define which load to use, feel free to try these examples: # using ExternalSpeedLoad: #load=ExternalSpeedLoad(speed_profile=sinus_lambda, tau=sampling_time, amplitude=10, frequency=2, bias=4) load=ExternalSpeedLoad(speed_profile=saw_lambda, tau=sampling_time, amplitude=40, frequency=5, bias=40) #load=ExternalSpeedLoad(speed_profile=constant_lambda, value=3, load_initializer={'random_init': 'uniform', 'interval': [[20, 80]]}) #(ExternalSpeedLoad will not use the passed initializer and print a corresponding warning instead) # using ConstantSpeedLoad (this class also accepts an initializer): #load=ConstantSpeedLoad(omega_fixed=42, load_initializer={'random_init': 'uniform', 'interval': [[20, 80]]}) ) # After the setup is done, we are ready to simulate the environment # We make use of a standard PI current controller controller = Controller.make('pi_controller', env) episode_duration = 0.2 # episode duration in seconds steps_per_episode = int(episode_duration / sampling_time)
env = gem.make( # Define the series DC motor with finite-control-set 'DcSeriesDisc-v1', # Set the electric parameters of the motor motor_parameter=dict(r_a=15e-3, r_e=15e-3, l_a=1e-3, l_e=1e-3), # Set the parameters of the mechanical polynomial load (the default load class) load_parameter=dict(a=0, b=.1, c=.1, j_load=0.04), # Defines the utilized power converter, which determines the action space # 'Disc-1QC' is our notation for a discontinuous one-quadrant converter, # which is a one-phase buck converter with available actions 'switch on' and 'switch off' converter='Disc-1QC', # Define which states will be shown in the state observation (what we can "measure") state_filter=['omega', 'i'], # Define the reward function and to which state variable it applies # Here, we define it for current control reward_function=WeightedSumOfErrors(observed_states='i'), # Defines which numerical solver is to be used for the simulation # euler is fastest but not most precise ode_solver='euler', solver_kwargs={}, # Define and parameterize the reference generator for the current reference reference_generator=WienerProcessReferenceGenerator( reference_state='i', sigma_range=(3e-3, 3e-2)), # Defines which variables to plot via the builtin dashboard monitor visualization=MotorDashboard(state_plots=['i', 'omega']), )
""" Continuous mode: The action is the average (normalized) voltage per time step which is assumed to be transferred to a PWM converter to generate the switching sequence. Discrete mode: The action is the switching state of the power converter i.e., a quantity from a discrete set of switching states which can be generated by the converter. """ env = gem.make( 'DcSeriesCont-v1', # replace with 'DcSeriesDisc-v1' for discrete controllers state_filter=['omega', 'i'], # Pass an instance visualization=MotorDashboard( state_plots=['i', 'omega'], reward_plot=True, action_plots='all', additional_plots=[CumulativeConstraintViolationPlot(), MeanEpisodeRewardPlot()] ), # Take standard class and pass parameters (Load) motor_parameter=dict(r_a=15e-3, r_e=15e-3, l_a=100e-3, l_e=100e-3), load_parameter=dict(a=0, b=.1, c=.1, j_load=0.04), # Pass a string (with extra parameters) ode_solver='euler', solver_kwargs={}, # Pass a Class with extra parameters reference_generator=rg.WienerProcessReferenceGenerator() ) # Assign a PI-controller to the speed control problem controller = Controller.make('pi_controller', env) state, reference = env.reset() # get the system time to measure program duration start = time.time()