diff --git a/examples/classic_controllers/classic_controllers.py b/examples/classic_controllers/classic_controllers.py index 9ade5e6b..2411bec1 100644 --- a/examples/classic_controllers/classic_controllers.py +++ b/examples/classic_controllers/classic_controllers.py @@ -106,7 +106,7 @@ def get_visualization(environment, **controller_kwargs): controller_kwargs["external_plot"] = ext_plot controller_kwargs["external_ref_plots"] = ref_plot - for visualization in environment.unwrapped.visualizations: + for visualization in environment.get_wrapper_attr('visualizations'): if isinstance(visualization, MotorDashboard): controller_kwargs["update_interval"] = visualization.update_interval controller_kwargs["visualization"] = True @@ -118,17 +118,17 @@ def get_visualization(environment, **controller_kwargs): def reference_states(environment, **controller_kwargs): """This method searches the environment for all referenced states and writes them to an array.""" ref_states = [] - if isinstance(environment.unwrapped.reference_generator, MultipleReferenceGenerator): - for rg in environment.unwrapped.reference_generator._sub_generators: + if isinstance(environment.get_wrapper_attr('reference_generator'), MultipleReferenceGenerator): + for rg in environment.get_wrapper_attr('reference_generator')._sub_generators: if isinstance(rg, SwitchedReferenceGenerator): ref_states.append(rg._sub_generators[0]._reference_state) else: ref_states.append(rg._reference_state) - elif isinstance(environment.unwrapped.reference_generator, SwitchedReferenceGenerator): - ref_states.append(environment.unwrapped.reference_generator._sub_generators[0]._reference_state) + elif isinstance(environment.get_wrapper_attr('reference_generator'), SwitchedReferenceGenerator): + ref_states.append(environment.get_wrapper_attr('reference_generator')._sub_generators[0]._reference_state) else: - ref_states.append(environment.unwrapped.reference_generator._reference_state) + ref_states.append(environment.get_wrapper_attr('reference_generator')._reference_state) controller_kwargs["ref_states"] = np.array(ref_states) return controller_kwargs @@ -136,7 +136,7 @@ def reference_states(environment, **controller_kwargs): def find_controller_type(environment, stages, **controller_kwargs): _stages = stages - if isinstance(environment.unwrapped.physical_system, DcMotorSystem): + if isinstance(environment.get_wrapper_attr('physical_system'), DcMotorSystem): if type(stages) is list: if len(stages) > 1: if type(stages[0]) is list: @@ -154,7 +154,7 @@ def find_controller_type(environment, stages, **controller_kwargs): else: controller_type = stages _stages = [{"controller_type": stages}] - elif isinstance(environment.physical_system.unwrapped, SynchronousMotorSystem): + elif isinstance(environment.get_wrapper_attr('physical_system'), SynchronousMotorSystem): if len(stages) == 2: if len(stages[1]) == 1 and "i_sq" in controller_kwargs["ref_states"]: controller_type = "foc_controller" @@ -163,7 +163,7 @@ def find_controller_type(environment, stages, **controller_kwargs): else: controller_type = "cascaded_foc_controller" - elif isinstance(environment.physical_system.unwrapped, SquirrelCageInductionMotorSystem): + elif isinstance(environment.get_wrapper_attr('physical_system'), SquirrelCageInductionMotorSystem): if len(stages) == 2: if len(stages[1]) == 1 and "i_sq" in controller_kwargs["ref_states"]: controller_type = "foc_rotor_flux_observer" @@ -172,7 +172,7 @@ def find_controller_type(environment, stages, **controller_kwargs): else: controller_type = "cascaded_foc_rotor_flux_observer" - elif isinstance(environment.physical_system.unwrapped, DoublyFedInductionMotorSystem): + elif isinstance(environment.get_wrapper_attr('physical_system'), DoublyFedInductionMotorSystem): if len(stages) == 2: if len(stages[1]) == 1 and "i_sq" in controller_kwargs["ref_states"]: controller_type = "foc_rotor_flux_observer" @@ -187,10 +187,10 @@ def find_controller_type(environment, stages, **controller_kwargs): def automated_controller_design(environment, **controller_kwargs): """This method automatically designs the controller based on the given motor environment and control task.""" - action_space_type = type(environment.action_space) + action_space_type = type(environment.get_wrapper_attr('action_space')) ref_states = controller_kwargs["ref_states"] stages = [] - if isinstance(environment.unwrapped.physical_system.unwrapped, DcMotorSystem): # Checking type of motor + if isinstance(environment.get_wrapper_attr('physical_system').unwrapped, DcMotorSystem): # Checking type of motor if "omega" in ref_states or "torque" in ref_states: # Checking control task controller_type = "cascaded_controller" @@ -212,13 +212,13 @@ def automated_controller_design(environment, **controller_kwargs): controller_type = stages[0]["controller_type"] # Add stage for i_e current of the ExtExDC - if isinstance(environment.unwrapped.physical_system.electrical_motor, DcExternallyExcitedMotor): + if isinstance(environment.get_wrapper_attr('physical_system').electrical_motor, DcExternallyExcitedMotor): if action_space_type is Box: stages = [stages, [{"controller_type": "pi_controller"}]] else: stages = [stages, [{"controller_type": "three_point"}]] - elif isinstance(environment.unwrapped.physical_system.unwrapped, SynchronousMotorSystem): + elif isinstance(environment.get_wrapper_attr('physical_system').unwrapped, SynchronousMotorSystem): if "i_sq" in ref_states or "torque" in ref_states: # Checking control task controller_type = "foc_controller" if "i_sq" in ref_states else "cascaded_foc_controller" if action_space_type is Discrete: @@ -253,7 +253,7 @@ def automated_controller_design(environment, **controller_kwargs): ] elif isinstance( - environment.physical_system.unwrapped, + environment.get_wrapper_attr('physical_system').unwrapped, (SquirrelCageInductionMotorSystem, DoublyFedInductionMotorSystem), ): if "i_sq" in ref_states or "torque" in ref_states: @@ -314,36 +314,36 @@ def automated_gain(environment, stages, controller_type, _controllers, **control """ ref_states = controller_kwargs["ref_states"] - mp = environment.unwrapped.physical_system.electrical_motor.motor_parameter - limits = environment.unwrapped.physical_system.limits - omega_lim = limits[environment.unwrapped.state_names.index("omega")] - if isinstance(environment.unwrapped.physical_system.unwrapped, DcMotorSystem): - i_a_lim = limits[environment.unwrapped.physical_system.CURRENTS_IDX[0]] - i_e_lim = limits[environment.unwrapped.physical_system.CURRENTS_IDX[-1]] - u_a_lim = limits[environment.unwrapped.physical_system.VOLTAGES_IDX[0]] - u_e_lim = limits[environment.unwrapped.physical_system.VOLTAGES_IDX[-1]] - - elif isinstance(environment.physical_system.unwrapped, SynchronousMotorSystem): - i_sd_lim = limits[environment.state_names.index("i_sd")] - i_sq_lim = limits[environment.state_names.index("i_sq")] - u_sd_lim = limits[environment.state_names.index("u_sd")] - u_sq_lim = limits[environment.state_names.index("u_sq")] - torque_lim = limits[environment.state_names.index("torque")] + mp = environment.get_wrapper_attr('physical_system').electrical_motor.motor_parameter + limits = environment.get_wrapper_attr('physical_system').limits + omega_lim = limits[environment.get_wrapper_attr('state_names').index("omega")] + if isinstance(environment.get_wrapper_attr('physical_system').unwrapped, DcMotorSystem): + i_a_lim = limits[environment.get_wrapper_attr('physical_system').CURRENTS_IDX[0]] + i_e_lim = limits[environment.get_wrapper_attr('physical_system').CURRENTS_IDX[-1]] + u_a_lim = limits[environment.get_wrapper_attr('physical_system').VOLTAGES_IDX[0]] + u_e_lim = limits[environment.get_wrapper_attr('physical_system').VOLTAGES_IDX[-1]] + + elif isinstance(environment.get_wrapper_attr('physical_system'), SynchronousMotorSystem): + i_sd_lim = limits[environment.get_wrapper_attr('state_names').index("i_sd")] + i_sq_lim = limits[environment.get_wrapper_attr('state_names').index("i_sq")] + u_sd_lim = limits[environment.get_wrapper_attr('state_names').index("u_sd")] + u_sq_lim = limits[environment.get_wrapper_attr('state_names').index("u_sq")] + torque_lim = limits[environment.get_wrapper_attr('state_names').index("torque")] else: - i_sd_lim = limits[environment.state_names.index("i_sd")] - i_sq_lim = limits[environment.state_names.index("i_sq")] - u_sd_lim = limits[environment.state_names.index("u_sd")] - u_sq_lim = limits[environment.state_names.index("u_sq")] - torque_lim = limits[environment.state_names.index("torque")] + i_sd_lim = limits[environment.get_wrapper_attr('state_names').index("i_sd")] + i_sq_lim = limits[environment.get_wrapper_attr('state_names').index("i_sq")] + u_sd_lim = limits[environment.get_wrapper_attr('state_names').index("u_sd")] + u_sq_lim = limits[environment.get_wrapper_attr('state_names').index("u_sq")] + torque_lim = limits[environment.get_wrapper_attr('state_names').index("torque")] # The parameter a is a design parameter when designing a controller according to the SO a = controller_kwargs.get("a", 4) automated_gain = controller_kwargs.get("automated_gain", True) - if isinstance(environment.unwrapped.physical_system.electrical_motor, DcSeriesMotor): + if isinstance(environment.get_wrapper_attr('physical_system').electrical_motor, DcSeriesMotor): mp["l"] = mp["l_a"] + mp["l_e"] - elif isinstance(environment.unwrapped.physical_system.unwrapped, DcMotorSystem): + elif isinstance(environment.get_wrapper_attr('physical_system').unwrapped, DcMotorSystem): mp["l"] = mp["l_a"] if "automated_gain" not in controller_kwargs.keys() or automated_gain: @@ -361,14 +361,14 @@ def automated_gain(environment, stages, controller_type, _controllers, **control stages_a = stages[0] stages_e = stages[1] - p_gain = mp["l_e"] / (environment.physical_system.tau * a) / u_e_lim * i_e_lim - i_gain = p_gain / (environment.physical_system.tau * a**2) + p_gain = mp["l_e"] / (environment.get_wrapper_attr('physical_system').tau * a) / u_e_lim * i_e_lim + i_gain = p_gain / (environment.get_wrapper_attr('physical_system').tau * a**2) stages_e[0]["p_gain"] = stages_e[0].get("p_gain", p_gain) stages_e[0]["i_gain"] = stages_e[0].get("i_gain", i_gain) if stages_e[0]["controller_type"] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau stages_e[0]["d_gain"] = stages_e[0].get("d_gain", d_gain) elif type(environment) in finite_extex_envs: stages_a = stages[0] @@ -379,19 +379,19 @@ def automated_gain(environment, stages, controller_type, _controllers, **control if _controllers[controller_type][0] == ContinuousActionController: if "i" in ref_states or "i_a" in ref_states or "torque" in ref_states: - 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) + p_gain = mp["l"] / (environment.get_wrapper_attr('physical_system').tau * a) / u_a_lim * i_a_lim + i_gain = p_gain / (environment.get_wrapper_attr('physical_system').tau * a**2) stages_a[0]["p_gain"] = stages_a[0].get("p_gain", p_gain) stages_a[0]["i_gain"] = stages_a[0].get("i_gain", i_gain) if _controllers[controller_type][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau stages_a[0]["d_gain"] = stages_a[0].get("d_gain", d_gain) elif "omega" in ref_states: p_gain = ( - environment.physical_system.mechanical_load.j_total + environment.get_wrapper_attr('physical_system').mechanical_load.j_total * mp["r_a"] ** 2 / (a * mp["l"]) / u_a_lim @@ -403,7 +403,7 @@ def automated_gain(environment, stages, controller_type, _controllers, **control stages_a[0]["i_gain"] = stages_a[0].get("i_gain", i_gain) if _controllers[controller_type][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau stages_a[0]["d_gain"] = stages_a[0].get("d_gain", d_gain) elif _controllers[controller_type][0] == CascadedController: @@ -413,24 +413,24 @@ def automated_gain(environment, stages, controller_type, _controllers, **control _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.unwrapped.physical_system.tau * a) / u_a_lim * i_a_lim - i_gain = p_gain / (environment.unwrapped.physical_system.tau * a**2) + p_gain = mp["l"] / (environment.get_wrapper_attr('physical_system').tau * a) / u_a_lim * i_a_lim + i_gain = p_gain / (environment.get_wrapper_attr('physical_system').tau * a**2) if _controllers[stages_a[i][0]["controller_type"]][2] == PIDController: - d_gain = p_gain * environment.unwrapped.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau stages_a[i][0]["d_gain"] = stages_a[i][0].get("d_gain", d_gain) elif i == 1: - t_n = environment.unwrapped.physical_system.tau * a**2 + t_n = environment.get_wrapper_attr('physical_system').tau * a**2 p_gain = ( - environment.unwrapped.physical_system.mechanical_load.j_total + environment.get_wrapper_attr('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.unwrapped.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('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) # ? @@ -441,24 +441,24 @@ def automated_gain(environment, stages, controller_type, _controllers, **control _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.unwrapped.physical_system.tau * a) / u_a_lim * i_a_lim - i_gain = p_gain / (environment.unwrapped.physical_system.tau * a**2) + p_gain = mp["l"] / (environment.get_wrapper_attr('physical_system').tau * a) / u_a_lim * i_a_lim + i_gain = p_gain / (environment.get_wrapper_attr('physical_system').tau * a**2) if _controllers[stages_a[i]["controller_type"]][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau stages_a[i]["d_gain"] = stages_a[i].get("d_gain", d_gain) elif i == 1: - t_n = environment.unwrapped.physical_system.tau * a**2 + t_n = environment.get_wrapper_attr('physical_system').tau * a**2 p_gain = ( - environment.unwrapped.physical_system.mechanical_load.j_total + environment.get_wrapper_attr('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.unwrapped.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('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) # ? @@ -467,15 +467,15 @@ def automated_gain(environment, stages, controller_type, _controllers, **control stages = stages_a if not stages_e else [stages_a, stages_e] elif _controllers[controller_type][0] == FieldOrientedController: - if type(environment.action_space) == Box: + if type(environment.get_wrapper_attr('action_space')) == Box: stage_d = stages[0][0] stage_q = stages[0][1] if "i_sq" in ref_states and _controllers[stage_q["controller_type"]][1] == ContinuousController: - p_gain_d = mp["l_d"] / (1.5 * environment.physical_system.tau * a) / u_sd_lim * i_sd_lim - i_gain_d = p_gain_d / (1.5 * environment.physical_system.tau * a**2) + p_gain_d = mp["l_d"] / (1.5 * environment.get_wrapper_attr('physical_system').tau * a) / u_sd_lim * i_sd_lim + i_gain_d = p_gain_d / (1.5 * environment.get_wrapper_attr('physical_system').tau * a**2) - p_gain_q = mp["l_q"] / (1.5 * environment.physical_system.tau * a) / u_sq_lim * i_sq_lim - i_gain_q = p_gain_q / (1.5 * environment.physical_system.tau * a**2) + p_gain_q = mp["l_q"] / (1.5 * environment.get_wrapper_attr('physical_system').tau * a) / u_sq_lim * i_sq_lim + i_gain_q = p_gain_q / (1.5 * environment.get_wrapper_attr('physical_system').tau * a**2) stage_d["p_gain"] = stage_d.get("p_gain", p_gain_d) stage_d["i_gain"] = stage_d.get("i_gain", i_gain_d) @@ -484,26 +484,26 @@ def automated_gain(environment, stages, controller_type, _controllers, **control stage_q["i_gain"] = stage_q.get("i_gain", i_gain_q) if _controllers[stage_d["controller_type"]][2] == PIDController: - d_gain_d = p_gain_d * environment.physical_system.tau + d_gain_d = p_gain_d * environment.get_wrapper_attr('physical_system').tau stage_d["d_gain"] = stage_d.get("d_gain", d_gain_d) if _controllers[stage_q["controller_type"]][2] == PIDController: - d_gain_q = p_gain_q * environment.physical_system.tau + d_gain_q = p_gain_q * environment.get_wrapper_attr('physical_system').tau stage_q["d_gain"] = stage_q.get("d_gain", d_gain_q) stages = [[stage_d, stage_q]] elif _controllers[controller_type][0] == CascadedFieldOrientedController: - if type(environment.action_space) is Box: + if type(environment.get_wrapper_attr('action_space')) is Box: stage_d = stages[0][0] stage_q = stages[0][1] if "torque" not in controller_kwargs["ref_states"]: overlaid = stages[1] - p_gain_d = mp["l_d"] / (1.5 * environment.physical_system.tau * a) / u_sd_lim * i_sd_lim - i_gain_d = p_gain_d / (1.5 * environment.physical_system.tau * a**2) + p_gain_d = mp["l_d"] / (1.5 * environment.get_wrapper_attr('physical_system').tau * a) / u_sd_lim * i_sd_lim + i_gain_d = p_gain_d / (1.5 * environment.get_wrapper_attr('physical_system').tau * a**2) - p_gain_q = mp["l_q"] / (1.5 * environment.physical_system.tau * a) / u_sq_lim * i_sq_lim - i_gain_q = p_gain_q / (1.5 * environment.physical_system.tau * a**2) + p_gain_q = mp["l_q"] / (1.5 * environment.get_wrapper_attr('physical_system').tau * a) / u_sq_lim * i_sq_lim + i_gain_q = p_gain_q / (1.5 * environment.get_wrapper_attr('physical_system').tau * a**2) stage_d["p_gain"] = stage_d.get("p_gain", p_gain_d) stage_d["i_gain"] = stage_d.get("i_gain", i_gain_d) @@ -512,11 +512,11 @@ def automated_gain(environment, stages, controller_type, _controllers, **control stage_q["i_gain"] = stage_q.get("i_gain", i_gain_q) if _controllers[stage_d["controller_type"]][2] == PIDController: - d_gain_d = p_gain_d * environment.physical_system.tau + d_gain_d = p_gain_d * environment.get_wrapper_attr('physical_system').tau stage_d["d_gain"] = stage_d.get("d_gain", d_gain_d) if _controllers[stage_q["controller_type"]][2] == PIDController: - d_gain_q = p_gain_q * environment.physical_system.tau + d_gain_q = p_gain_q * environment.get_wrapper_attr('physical_system').tau stage_q["d_gain"] = stage_q.get("d_gain", d_gain_q) if ( @@ -524,7 +524,7 @@ def automated_gain(environment, stages, controller_type, _controllers, **control and _controllers[overlaid[0]["controller_type"]][1] == ContinuousController ): t_n = p_gain_d / i_gain_d - j_total = environment.physical_system.mechanical_load.j_total + j_total = environment.get_wrapper_attr('physical_system').mechanical_load.j_total p_gain = j_total / (a**2 * t_n) / torque_lim * omega_lim i_gain = p_gain / (a * t_n) @@ -532,7 +532,7 @@ def automated_gain(environment, stages, controller_type, _controllers, **control overlaid[0]["i_gain"] = overlaid[0].get("i_gain", i_gain) if _controllers[overlaid[0]["controller_type"]][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau overlaid[0]["d_gain"] = overlaid[0].get("d_gain", d_gain) stages = [[stage_d, stage_q], overlaid] @@ -546,18 +546,18 @@ def automated_gain(environment, stages, controller_type, _controllers, **control and _controllers[stages[3][0]["controller_type"]][1] == ContinuousController ): p_gain = ( - environment.physical_system.mechanical_load.j_total + environment.get_wrapper_attr('physical_system').mechanical_load.j_total / (1.5 * a**2 * mp["p"] * np.abs(mp["l_d"] - mp["l_q"])) / i_sq_lim * omega_lim ) - i_gain = p_gain / (1.5 * environment.physical_system.tau * a) + i_gain = p_gain / (1.5 * environment.get_wrapper_attr('physical_system').tau * a) stages[3][0]["p_gain"] = stages[3][0].get("p_gain", p_gain) stages[3][0]["i_gain"] = stages[3][0].get("i_gain", i_gain) if _controllers[stages[3][0]["controller_type"]][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau stages[3][0]["d_gain"] = stages[3][0].get("d_gain", d_gain) elif _controllers[controller_type][0] == InductionMotorFieldOrientedController: @@ -612,7 +612,7 @@ def automated_gain(environment, stages, controller_type, _controllers, **control and _controllers[overlaid[0]["controller_type"]][1] == ContinuousController ): t_n = p_gain / i_gain - j_total = environment.physical_system.mechanical_load.j_total + j_total = environment.get_wrapper_attr('physical_system').mechanical_load.j_total p_gain = j_total / (a**2 * t_n) / torque_lim * omega_lim i_gain = p_gain / (a * t_n) @@ -620,7 +620,7 @@ def automated_gain(environment, stages, controller_type, _controllers, **control overlaid[0]["i_gain"] = overlaid[0].get("i_gain", i_gain) if _controllers[overlaid[0]["controller_type"]][2] == PIDController: - d_gain = p_gain * environment.physical_system.tau + d_gain = p_gain * environment.get_wrapper_attr('physical_system').tau overlaid[0]["d_gain"] = overlaid[0].get("d_gain", d_gain) stages = [stages[0], overlaid] diff --git a/examples/classic_controllers/classic_controllers_dc_motor_example.py b/examples/classic_controllers/classic_controllers_dc_motor_example.py index 85a0ddfc..224f0a36 100644 --- a/examples/classic_controllers/classic_controllers_dc_motor_example.py +++ b/examples/classic_controllers/classic_controllers_dc_motor_example.py @@ -67,5 +67,5 @@ env.reset() controller.reset() - motor_dashboard.show_and_hold() + motor_dashboard.show() env.close() diff --git a/examples/classic_controllers/classic_controllers_ind_motor_example.py b/examples/classic_controllers/classic_controllers_ind_motor_example.py index 074a1f21..68146f70 100644 --- a/examples/classic_controllers/classic_controllers_ind_motor_example.py +++ b/examples/classic_controllers/classic_controllers_ind_motor_example.py @@ -68,5 +68,5 @@ if terminated: env.reset() controller.reset() - motor_dashboard.show_and_hold() + motor_dashboard.show() 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 4a367e0a..9ff0ad4d 100644 --- a/examples/classic_controllers/classic_controllers_synch_motor_example.py +++ b/examples/classic_controllers/classic_controllers_synch_motor_example.py @@ -72,5 +72,5 @@ env.reset() controller.reset() - motor_dashboard.show_and_hold() + motor_dashboard.show() env.close() diff --git a/examples/classic_controllers/controllers/cascaded_controller.py b/examples/classic_controllers/controllers/cascaded_controller.py index e5b8e968..94167506 100644 --- a/examples/classic_controllers/controllers/cascaded_controller.py +++ b/examples/classic_controllers/controllers/cascaded_controller.py @@ -27,28 +27,28 @@ def __init__( ): self.env = environment self.visualization = visualization - self.action_space = environment.action_space - self.state_space = environment.unwrapped.physical_system.state_space - self.state_names = environment.unwrapped.state_names - - self.i_e_idx = environment.unwrapped.physical_system.CURRENTS_IDX[-1] - self.i_a_idx = environment.unwrapped.physical_system.CURRENTS_IDX[0] - self.u_idx = environment.unwrapped.physical_system.VOLTAGES_IDX[-1] - self.omega_idx = environment.unwrapped.state_names.index("omega") - self.torque_idx = environment.unwrapped.state_names.index("torque") + self.action_space = environment.get_wrapper_attr('action_space') + self.state_space = environment.get_wrapper_attr('physical_system').state_space + self.state_names = environment.get_wrapper_attr('state_names') + + self.i_e_idx = environment.get_wrapper_attr('physical_system').CURRENTS_IDX[-1] + self.i_a_idx = environment.get_wrapper_attr('physical_system').CURRENTS_IDX[0] + self.u_idx = environment.get_wrapper_attr('physical_system').VOLTAGES_IDX[-1] + self.omega_idx = environment.get_wrapper_attr('state_names').index("omega") + self.torque_idx = environment.get_wrapper_attr('state_names').index("torque") self.ref_idx = np.where(ref_states != "i_e")[0][0] self.ref_state_idx = [ self.i_a_idx, - environment.unwrapped.state_names.index(ref_states[self.ref_idx]), + environment.get_wrapper_attr('state_names').index(ref_states[self.ref_idx]), ] - self.limit = environment.unwrapped.physical_system.limits[environment.unwrapped.state_filter] - self.nominal_values = environment.unwrapped.physical_system.nominal_state[environment.unwrapped.state_filter] + self.limit = environment.get_wrapper_attr('physical_system').limits[environment.get_wrapper_attr('state_filter')] + self.nominal_values = environment.get_wrapper_attr('physical_system').nominal_state[environment.get_wrapper_attr('state_filter')] - self.control_e = isinstance(environment.unwrapped.physical_system.electrical_motor, DcExternallyExcitedMotor) + self.control_e = isinstance(environment.get_wrapper_attr('physical_system').electrical_motor, DcExternallyExcitedMotor) self.control_omega = 0 - mp = environment.unwrapped.physical_system.electrical_motor.motor_parameter + mp = environment.get_wrapper_attr('physical_system').electrical_motor.motor_parameter self.psi_e = mp.get("psie_e", False) self.l_e = mp.get("l_e_prime", False) self.r_e = mp.get("r_e", None) @@ -110,7 +110,7 @@ def __init__( # Set up the plots self.external_ref_plots = external_ref_plots - internal_refs = np.array([environment.unwrapped.state_names[i] for i in self.ref_state_idx]) + internal_refs = np.array([environment.get_wrapper_attr('state_names')[i] for i in self.ref_state_idx]) ref_states_plotted = np.unique(np.append(ref_states, internal_refs)) for external_plots in self.external_ref_plots: external_plots.set_reference(ref_states_plotted) diff --git a/examples/classic_controllers/controllers/cascaded_foc_controller.py b/examples/classic_controllers/controllers/cascaded_foc_controller.py index 6b63fb49..1a237ab4 100644 --- a/examples/classic_controllers/controllers/cascaded_foc_controller.py +++ b/examples/classic_controllers/controllers/cascaded_foc_controller.py @@ -28,25 +28,25 @@ def __init__( torque_control="interpolate", **controller_kwargs, ): - t32 = environment.physical_system.electrical_motor.t_32 - q = environment.physical_system.electrical_motor.q + t32 = environment.get_wrapper_attr('physical_system').electrical_motor.t_32 + q = environment.get_wrapper_attr('physical_system').electrical_motor.q self.backward_transformation = lambda quantities, eps: t32(q(quantities, eps)) - self.tau = environment.physical_system.tau - - self.action_space = environment.action_space - self.state_space = environment.physical_system.state_space - self.state_names = environment.state_names - - self.i_sd_idx = environment.state_names.index("i_sd") - self.i_sq_idx = environment.state_names.index("i_sq") - self.u_sd_idx = environment.state_names.index("u_sd") - self.u_sq_idx = environment.state_names.index("u_sq") - self.u_a_idx = environment.state_names.index("u_a") - self.u_b_idx = environment.state_names.index("u_b") - self.u_c_idx = environment.state_names.index("u_c") - self.omega_idx = environment.state_names.index("omega") - self.eps_idx = environment.state_names.index("epsilon") - self.torque_idx = environment.state_names.index("torque") + self.tau = environment.get_wrapper_attr('physical_system').tau + + self.action_space = environment.get_wrapper_attr('action_space') + self.state_space = environment.get_wrapper_attr('physical_system').state_space + self.state_names = environment.get_wrapper_attr('state_names') + + self.i_sd_idx = environment.get_wrapper_attr('state_names').index("i_sd") + self.i_sq_idx = environment.get_wrapper_attr('state_names').index("i_sq") + self.u_sd_idx = environment.get_wrapper_attr('state_names').index("u_sd") + self.u_sq_idx = environment.get_wrapper_attr('state_names').index("u_sq") + self.u_a_idx = environment.get_wrapper_attr('state_names').index("u_a") + self.u_b_idx = environment.get_wrapper_attr('state_names').index("u_b") + self.u_c_idx = environment.get_wrapper_attr('state_names').index("u_c") + self.omega_idx = environment.get_wrapper_attr('state_names').index("omega") + self.eps_idx = environment.get_wrapper_attr('state_names').index("epsilon") + self.torque_idx = environment.get_wrapper_attr('state_names').index("torque") self.external_ref_plots = external_ref_plots self.torque_control = "torque" in ref_states or "omega" in ref_states @@ -59,10 +59,10 @@ def __init__( self.omega_control = "omega" in ref_states and type(environment) self.has_cont_action_space = type(self.action_space) is Box - self.limit = environment.physical_system.limits - self.nominal_values = environment.physical_system.nominal_state + self.limit = environment.get_wrapper_attr('physical_system').limits + self.nominal_values = environment.get_wrapper_attr('physical_system').nominal_state - self.mp = environment.physical_system.electrical_motor.motor_parameter + self.mp = environment.get_wrapper_attr('physical_system').electrical_motor.motor_parameter self.psi_p = self.mp.get("psi_p", 0) self.dead_time = 0.5 self.decoupling = controller_kwargs.get("decoupling", True) @@ -136,7 +136,7 @@ def __init__( for i in range(3) ] self.i_abc_idx = [ - environment.state_names.index(state) for state in ["i_a", "i_b", "i_c"] + environment.get_wrapper_attr('state_names').index(state) for state in ["i_a", "i_b", "i_c"] ] self.ref = np.zeros( @@ -145,7 +145,7 @@ def __init__( # Set up the plots plot_ref = np.append( - np.array([environment.state_names[i] for i in self.ref_state_idx]), + np.array([environment.get_wrapper_attr('state_names')[i] for i in self.ref_state_idx]), ref_states, ) for ext_ref_plot in self.external_ref_plots: diff --git a/examples/classic_controllers/controllers/continuous_action_controller.py b/examples/classic_controllers/controllers/continuous_action_controller.py index e58f9c7f..db18e43a 100644 --- a/examples/classic_controllers/controllers/continuous_action_controller.py +++ b/examples/classic_controllers/controllers/continuous_action_controller.py @@ -20,28 +20,28 @@ def __init__( external_ref_plots=(), **controller_kwargs, ): - assert type(environment.action_space) is Box and isinstance( - environment.physical_system, DcMotorSystem + assert type(environment.get_wrapper_attr('action_space')) is Box and isinstance( + environment.get_wrapper_attr('physical_system'), DcMotorSystem ), "No suitable action space for Continuous Action Controller" - self.action_space = environment.action_space - self.state_names = environment.state_names + self.action_space = environment.get_wrapper_attr('action_space') + self.state_names = environment.get_wrapper_attr('state_names') self.ref_idx = np.where(ref_states != "i_e")[0][0] - self.ref_state_idx = environment.state_names.index(ref_states[self.ref_idx]) - self.i_idx = environment.physical_system.CURRENTS_IDX[-1] - self.u_idx = environment.physical_system.VOLTAGES_IDX[-1] - self.limit = environment.physical_system.limits[environment.state_filter] - self.nominal_values = environment.physical_system.nominal_state[ - environment.state_filter + self.ref_state_idx = environment.get_wrapper_attr('state_names').index(ref_states[self.ref_idx]) + self.i_idx = environment.get_wrapper_attr('physical_system').CURRENTS_IDX[-1] + self.u_idx = environment.get_wrapper_attr('physical_system').VOLTAGES_IDX[-1] + self.limit = environment.get_wrapper_attr('physical_system').limits[environment.get_wrapper_attr('state_filter')] + self.nominal_values = environment.get_wrapper_attr('physical_system').nominal_state[ + environment.get_wrapper_attr('state_filter') ] self.omega_idx = self.state_names.index("omega") self.action = np.zeros(self.action_space.shape[0]) self.control_e = isinstance( - environment.physical_system.electrical_motor, DcExternallyExcitedMotor + environment.get_wrapper_attr('physical_system').electrical_motor, DcExternallyExcitedMotor ) - mp = environment.physical_system.electrical_motor.motor_parameter + mp = environment.get_wrapper_attr('physical_system').electrical_motor.motor_parameter self.psi_e = mp.get("psi_e", None) self.l_e = mp.get("l_e_prime", None) diff --git a/examples/classic_controllers/controllers/dicrete_action_controller.py b/examples/classic_controllers/controllers/dicrete_action_controller.py index b0e04e26..35a79328 100644 --- a/examples/classic_controllers/controllers/dicrete_action_controller.py +++ b/examples/classic_controllers/controllers/dicrete_action_controller.py @@ -19,20 +19,20 @@ def __init__( external_ref_plots=(), **controller_kwargs, ): - assert type(environment.action_space) in [ + assert type(environment.get_wrapper_attr('action_space')) in [ Discrete, MultiDiscrete, ] and isinstance( - environment.physical_system, DcMotorSystem + environment.get_wrapper_attr('physical_system'), DcMotorSystem ), "No suitable action space for Discrete Action Controller" self.ref_idx = np.where(ref_states != "i_e")[0][0] - self.ref_state_idx = environment.state_names.index(ref_states[self.ref_idx]) - self.i_idx = environment.physical_system.CURRENTS_IDX[-1] + self.ref_state_idx = environment.get_wrapper_attr('state_names').index(ref_states[self.ref_idx]) + self.i_idx = environment.get_wrapper_attr('physical_system').CURRENTS_IDX[-1] self.control_e = isinstance( - environment.physical_system.electrical_motor, DcExternallyExcitedMotor + environment.get_wrapper_attr('physical_system').electrical_motor, DcExternallyExcitedMotor ) - self.state_names = environment.state_names + self.state_names = environment.get_wrapper_attr('state_names') self.external_ref_plots = external_ref_plots for ext_ref_plot in self.external_ref_plots: diff --git a/examples/classic_controllers/controllers/flux_observer.py b/examples/classic_controllers/controllers/flux_observer.py index f785d5d7..69d340dd 100644 --- a/examples/classic_controllers/controllers/flux_observer.py +++ b/examples/classic_controllers/controllers/flux_observer.py @@ -8,26 +8,26 @@ class FluxObserver: """ def __init__(self, env): - mp = env.physical_system.electrical_motor.motor_parameter + mp = env.get_wrapper_attr('physical_system').electrical_motor.motor_parameter self.l_m = mp["l_m"] # Main induction self.l_r = mp["l_m"] + mp["l_sigr"] # Induction of the rotor self.r_r = mp["r_r"] # Rotor resistance self.p = mp["p"] # Pole pair number - self.tau = env.physical_system.tau # Sampling time + self.tau = env.get_wrapper_attr('physical_system').tau # Sampling time # function to transform the currents from abc to alpha/beta coordinates self.abc_to_alphabeta_transformation = ( - env.physical_system.abc_to_alphabeta_space + env.get_wrapper_attr('physical_system').abc_to_alphabeta_space ) # Integrated values of the flux for the two directions (Re: alpha, Im: beta) - self.integrated = np.complex(0, 0) + self.integrated = complex(0, 0) self.i_s_idx = [ - env.state_names.index("i_sa"), - env.state_names.index("i_sb"), - env.state_names.index("i_sc"), + env.get_wrapper_attr('state_names').index("i_sa"), + env.get_wrapper_attr('state_names').index("i_sb"), + env.get_wrapper_attr('state_names').index("i_sc"), ] - self.omega_idx = env.state_names.index("omega") + self.omega_idx = env.get_wrapper_attr('state_names').index("omega") def estimate(self, state): """ @@ -47,9 +47,9 @@ def estimate(self, state): [i_s_alpha, i_s_beta] = self.abc_to_alphabeta_transformation(i_s) # Calculate delta flux - delta = np.complex( + delta = complex( i_s_alpha, i_s_beta - ) * self.r_r * self.l_m / self.l_r - self.integrated * np.complex( + ) * self.r_r * self.l_m / self.l_r - self.integrated * complex( self.r_r / self.l_r, -omega ) @@ -59,4 +59,4 @@ def estimate(self, state): def reset(self): # Reset the integrated value - self.integrated = np.complex(0, 0) + self.integrated = complex(0, 0) diff --git a/examples/classic_controllers/controllers/foc_controller.py b/examples/classic_controllers/controllers/foc_controller.py index 7fce5e32..64e536d4 100644 --- a/examples/classic_controllers/controllers/foc_controller.py +++ b/examples/classic_controllers/controllers/foc_controller.py @@ -24,40 +24,40 @@ def __init__( **controller_kwargs, ): assert isinstance( - environment.physical_system, SynchronousMotorSystem + environment.get_wrapper_attr('physical_system'), SynchronousMotorSystem ), "No suitable Environment for FOC Controller" - t32 = environment.physical_system.electrical_motor.t_32 - q = environment.physical_system.electrical_motor.q + t32 = environment.get_wrapper_attr('physical_system').electrical_motor.t_32 + q = environment.get_wrapper_attr('physical_system').electrical_motor.q self.backward_transformation = lambda quantities, eps: t32(q(quantities, eps)) - self.tau = environment.physical_system.tau + self.tau = environment.get_wrapper_attr('physical_system').tau self.ref_d_idx = np.where(ref_states == "i_sd")[0][0] self.ref_q_idx = np.where(ref_states == "i_sq")[0][0] - self.d_idx = environment.state_names.index(ref_states[self.ref_d_idx]) - self.q_idx = environment.state_names.index(ref_states[self.ref_q_idx]) - - self.action_space = environment.action_space - self.state_space = environment.physical_system.state_space - self.state_names = environment.state_names - - self.i_sd_idx = environment.state_names.index("i_sd") - self.i_sq_idx = environment.state_names.index("i_sq") - self.u_sd_idx = environment.state_names.index("u_sd") - self.u_sq_idx = environment.state_names.index("u_sq") - self.u_a_idx = environment.state_names.index("u_a") - self.u_b_idx = environment.state_names.index("u_b") - self.u_c_idx = environment.state_names.index("u_c") - self.omega_idx = environment.state_names.index("omega") - self.eps_idx = environment.state_names.index("epsilon") - - self.limit = environment.physical_system.limits - self.mp = environment.physical_system.electrical_motor.motor_parameter + self.d_idx = environment.get_wrapper_attr('state_names').index(ref_states[self.ref_d_idx]) + self.q_idx = environment.get_wrapper_attr('state_names').index(ref_states[self.ref_q_idx]) + + self.action_space = environment.get_wrapper_attr('action_space') + self.state_space = environment.get_wrapper_attr('physical_system').state_space + self.state_names = environment.get_wrapper_attr('state_names') + + self.i_sd_idx = environment.get_wrapper_attr('state_names').index("i_sd") + self.i_sq_idx = environment.get_wrapper_attr('state_names').index("i_sq") + self.u_sd_idx = environment.get_wrapper_attr('state_names').index("u_sd") + self.u_sq_idx = environment.get_wrapper_attr('state_names').index("u_sq") + self.u_a_idx = environment.get_wrapper_attr('state_names').index("u_a") + self.u_b_idx = environment.get_wrapper_attr('state_names').index("u_b") + self.u_c_idx = environment.get_wrapper_attr('state_names').index("u_c") + self.omega_idx = environment.get_wrapper_attr('state_names').index("omega") + self.eps_idx = environment.get_wrapper_attr('state_names').index("epsilon") + + self.limit = environment.get_wrapper_attr('physical_system').limits + self.mp = environment.get_wrapper_attr('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 + 1.5 if environment.get_wrapper_attr('physical_system').converter._dead_time else 0.5 ) self.has_cont_action_space = type(self.action_space) is Box @@ -89,7 +89,7 @@ def __init__( for i in range(3) ] self.i_abc_idx = [ - environment.state_names.index(state) for state in ["i_a", "i_b", "i_c"] + environment.get_wrapper_attr('state_names').index(state) for state in ["i_a", "i_b", "i_c"] ] def control(self, state, reference): diff --git a/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py b/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py index 5a175f62..446bd4d0 100644 --- a/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py +++ b/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py @@ -28,22 +28,22 @@ def __init__( **controller_kwargs, ): self.env = environment - self.action_space = environment.action_space + self.action_space = environment.get_wrapper_attr('action_space') self.has_cont_action_space = type(self.action_space) is Box - self.state_space = environment.physical_system.state_space - self.state_names = environment.state_names + self.state_space = environment.get_wrapper_attr('physical_system').state_space + self.state_names = environment.get_wrapper_attr('state_names') self.stages = stages self.flux_observer = FluxObserver(self.env) - self.i_sd_idx = self.env.state_names.index("i_sd") - self.i_sq_idx = self.env.state_names.index("i_sq") + self.i_sd_idx = self.env.get_wrapper_attr('state_names').index("i_sd") + self.i_sq_idx = self.env.get_wrapper_attr('state_names').index("i_sq") self.u_s_abc_idx = [ - self.env.state_names.index(state) for state in ["u_sa", "u_sb", "u_sc"] + self.env.get_wrapper_attr('state_names').index(state) for state in ["u_sa", "u_sb", "u_sc"] ] - self.omega_idx = self.env.state_names.index("omega") - self.torque_idx = self.env.state_names.index("torque") + self.omega_idx = self.env.get_wrapper_attr('state_names').index("omega") + self.torque_idx = self.env.get_wrapper_attr('state_names').index("torque") - mp = self.env.physical_system.electrical_motor.motor_parameter + mp = self.env.get_wrapper_attr('physical_system').electrical_motor.motor_parameter self.p = mp["p"] self.l_m = mp["l_m"] self.l_sigma_s = mp["l_sigs"] @@ -53,14 +53,14 @@ def __init__( self.r_s = mp["r_s"] self.tau_r = self.l_r / self.r_r self.sigma = (self.l_s * self.l_r - self.l_m**2) / (self.l_s * self.l_r) - self.limits = self.env.physical_system.limits - self.nominal_values = self.env.physical_system.nominal_state + self.limits = self.env.get_wrapper_attr('physical_system').limits + self.nominal_values = self.env.get_wrapper_attr('physical_system').nominal_state self.tau_sigma = ( self.sigma * self.l_s / (self.r_s + self.r_r * self.l_m**2 / self.l_r**2) ) - self.tau = self.env.physical_system.tau + self.tau = self.env.get_wrapper_attr('physical_system').tau - self.dq_to_abc_transformation = environment.physical_system.dq_to_abc_space + self.dq_to_abc_transformation = environment.get_wrapper_attr('physical_system').dq_to_abc_space self.torque_control = "torque" in ref_states or "omega" in ref_states self.current_control = "i_sd" in ref_states @@ -89,7 +89,7 @@ def __init__( self.external_ref_plots = external_ref_plots self.external_ref_plots = external_ref_plots plot_ref = np.append( - np.array([environment.state_names[i] for i in self.ref_state_idx]), + np.array([environment.get_wrapper_attr('state_names')[i] for i in self.ref_state_idx]), ref_states, ) for ext_ref_plot in self.external_ref_plots: diff --git a/examples/classic_controllers/controllers/induction_motor_foc.py b/examples/classic_controllers/controllers/induction_motor_foc.py index dc5c6f3b..3bdea43f 100644 --- a/examples/classic_controllers/controllers/induction_motor_foc.py +++ b/examples/classic_controllers/controllers/induction_motor_foc.py @@ -23,10 +23,10 @@ def __init__( **controller_kwargs, ): self.env = environment - self.action_space = environment.action_space + self.action_space = environment.get_wrapper_attr('action_space') self.has_cont_action_space = type(self.action_space) is Box - self.state_space = environment.physical_system.state_space - self.state_names = environment.state_names + self.state_space = environment.get_wrapper_attr('physical_system').state_space + self.state_names = environment.get_wrapper_attr('state_names') self.stages = stages self.flux_observer = FluxObserver(self.env) diff --git a/examples/classic_controllers/controllers/induction_motor_torque_to_current_conversion.py b/examples/classic_controllers/controllers/induction_motor_torque_to_current_conversion.py index beecc1ac..ea3b3dcb 100644 --- a/examples/classic_controllers/controllers/induction_motor_torque_to_current_conversion.py +++ b/examples/classic_controllers/controllers/induction_motor_torque_to_current_conversion.py @@ -24,28 +24,28 @@ def __init__( update_interval=1000, ): self.env = environment - self.nominal_values = self.env.physical_system.nominal_state - self.state_space = self.env.physical_system.state_space + self.nominal_values = self.env.get_wrapper_attr('physical_system').nominal_state + self.state_space = self.env.get_wrapper_attr('physical_system').state_space # Calculate parameters of the motor - mp = self.env.physical_system.electrical_motor.motor_parameter + mp = self.env.get_wrapper_attr('physical_system').electrical_motor.motor_parameter self.l_m = mp["l_m"] self.l_r = self.l_m + mp["l_sigr"] self.l_s = self.l_m + mp["l_sigs"] self.r_r = mp["r_r"] self.r_s = mp["r_s"] self.p = mp["p"] - self.tau = self.env.physical_system.tau + self.tau = self.env.get_wrapper_attr('physical_system').tau tau_s = self.l_s / self.r_s - self.i_sd_idx = self.env.state_names.index("i_sd") - self.i_sq_idx = self.env.state_names.index("i_sq") - self.torque_idx = self.env.state_names.index("torque") - self.u_sa_idx = environment.state_names.index("u_sa") - self.u_sd_idx = environment.state_names.index("u_sd") - self.u_sq_idx = environment.state_names.index("u_sq") - self.omega_idx = environment.state_names.index("omega") - self.limits = self.env.physical_system.limits + self.i_sd_idx = self.env.get_wrapper_attr('state_names').index("i_sd") + self.i_sq_idx = self.env.get_wrapper_attr('state_names').index("i_sq") + self.torque_idx = self.env.get_wrapper_attr('state_names').index("torque") + self.u_sa_idx = environment.get_wrapper_attr('state_names').index("u_sa") + self.u_sd_idx = environment.get_wrapper_attr('state_names').index("u_sd") + self.u_sq_idx = environment.get_wrapper_attr('state_names').index("u_sq") + self.omega_idx = environment.get_wrapper_attr('state_names').index("omega") + self.limits = self.env.get_wrapper_attr('physical_system').limits p_gain = stages[0][1]["p_gain"] * 2 * tau_s**2 # flux controller p gain i_gain = p_gain / self.tau # flux controller i gain diff --git a/examples/classic_controllers/controllers/on_off_controller.py b/examples/classic_controllers/controllers/on_off_controller.py index 300cd46d..6e2fb2ef 100644 --- a/examples/classic_controllers/controllers/on_off_controller.py +++ b/examples/classic_controllers/controllers/on_off_controller.py @@ -19,7 +19,7 @@ def __init__( self.switch_off_level = 2 if action_space in [3, 4] and not control_e else 0 if cascaded: - self.switch_off_level = int(environment.physical_system.state_space.low[0]) + self.switch_off_level = int(environment.get_wrapper_attr('physical_system').state_space.low[0]) self.action = self.switch_on_level diff --git a/examples/classic_controllers/controllers/pi_controller.py b/examples/classic_controllers/controllers/pi_controller.py index a07c67a5..660f8493 100644 --- a/examples/classic_controllers/controllers/pi_controller.py +++ b/examples/classic_controllers/controllers/pi_controller.py @@ -9,7 +9,7 @@ class PIController(PController, IController): """ def __init__(self, environment, p_gain=5, i_gain=5, param_dict={}, **controller_kwargs): - self.tau = environment.unwrapped.physical_system.tau + self.tau = environment.get_wrapper_attr('physical_system').tau p_gain = param_dict.get("p_gain", p_gain) i_gain = param_dict.get("i_gain", i_gain) diff --git a/examples/classic_controllers/controllers/three_point_controller.py b/examples/classic_controllers/controllers/three_point_controller.py index c6cd825f..a91d0761 100644 --- a/examples/classic_controllers/controllers/three_point_controller.py +++ b/examples/classic_controllers/controllers/three_point_controller.py @@ -28,7 +28,7 @@ def __init__( self.negative = 2 if action_space in [3, 4, 8] and not control_e else 0 if cascaded: - self.negative = int(environment.physical_system.state_space.low[0]) + self.negative = int(environment.get_wrapper_attr('physical_system').state_space.low[0]) self.positive = 1 self.neutral = 0 diff --git a/examples/classic_controllers/controllers/torque_to_current_conversion.py b/examples/classic_controllers/controllers/torque_to_current_conversion.py index ca1f19e2..e6eaf750 100644 --- a/examples/classic_controllers/controllers/torque_to_current_conversion.py +++ b/examples/classic_controllers/controllers/torque_to_current_conversion.py @@ -28,9 +28,9 @@ def __init__( update_interval=1000, torque_control="interpolate", ): - self.mp = environment.physical_system.electrical_motor.motor_parameter - self.limit = environment.physical_system.limits - self.nominal_values = environment.physical_system.nominal_state + self.mp = environment.get_wrapper_attr('physical_system').electrical_motor.motor_parameter + self.limit = environment.get_wrapper_attr('physical_system').limits + self.nominal_values = environment.get_wrapper_attr('physical_system').nominal_state self.torque_control = torque_control self.l_d = self.mp["l_d"] @@ -38,15 +38,15 @@ def __init__( self.p = self.mp["p"] self.psi_p = self.mp.get("psi_p", 0) self.invert = -1 if (self.psi_p == 0 and self.l_q < self.l_d) else 1 - self.tau = environment.physical_system.tau + self.tau = environment.get_wrapper_attr('physical_system').tau - self.omega_idx = environment.state_names.index("omega") - self.i_sd_idx = environment.state_names.index("i_sd") - self.i_sq_idx = environment.state_names.index("i_sq") - self.u_sd_idx = environment.state_names.index("u_sd") - self.u_sq_idx = environment.state_names.index("u_sq") - self.torque_idx = environment.state_names.index("torque") - self.epsilon_idx = environment.state_names.index("epsilon") + self.omega_idx = environment.get_wrapper_attr('state_names').index("omega") + self.i_sd_idx = environment.get_wrapper_attr('state_names').index("i_sd") + self.i_sq_idx = environment.get_wrapper_attr('state_names').index("i_sq") + self.u_sd_idx = environment.get_wrapper_attr('state_names').index("u_sd") + self.u_sq_idx = environment.get_wrapper_attr('state_names').index("u_sq") + self.torque_idx = environment.get_wrapper_attr('state_names').index("torque") + self.epsilon_idx = environment.get_wrapper_attr('state_names').index("epsilon") self.a_max = 2 / np.sqrt(3) # maximum modulation level self.k_ = 0.95 @@ -56,7 +56,7 @@ def __init__( 1 / (self.mp["l_q"] / (1.25 * self.mp["r_s"])) * (alpha - 1) / alpha**2 ) - self.u_a_idx = environment.state_names.index("u_a") + self.u_a_idx = environment.get_wrapper_attr('state_names').index("u_a") self.u_dc = np.sqrt(3) * self.limit[self.u_a_idx] self.limited = False self.integrated = 0 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 af6b414f..ce5acff6 100644 --- a/examples/classic_controllers/custom_classic_controllers_dc_motor_example.py +++ b/examples/classic_controllers/custom_classic_controllers_dc_motor_example.py @@ -92,5 +92,5 @@ env.reset() controller.reset() - motor_dashboard.show_and_hold() + motor_dashboard.show() env.close() 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 135403f5..8c7f02ca 100644 --- a/examples/classic_controllers/custom_classic_controllers_ind_motor_example.py +++ b/examples/classic_controllers/custom_classic_controllers_ind_motor_example.py @@ -78,5 +78,5 @@ env.reset() controller.reset() - motor_dashboard.show_and_hold() + motor_dashboard.show() env.close() diff --git a/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py b/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py index b22dc7ce..464223aa 100644 --- a/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py +++ b/examples/classic_controllers/integration_test_classic_controllers_dc_motor.py @@ -83,4 +83,4 @@ env.close() # motor_dashboard.save_to_file(filename="integration_test") - motor_dashboard.show_and_hold() + motor_dashboard.show() diff --git a/tests/test_controllers_examples/test_classic_controllers.py b/tests/test_controllers_examples/test_classic_controllers.py new file mode 100644 index 00000000..68db152c --- /dev/null +++ b/tests/test_controllers_examples/test_classic_controllers.py @@ -0,0 +1,28 @@ +import os +import subprocess + +import pytest + +file_names = ["classic_controllers_dc_motor_example.py", + "classic_controllers_ind_motor_example.py", + "classic_controllers_synch_motor_example.py", + "custom_classic_controllers_dc_motor_example.py" , + "custom_classic_controllers_ind_motor_example.py", + "custom_classic_controllers_synch_motor_example.py", + "integration_test_classic_controllers_dc_motor.py" + ] + +@pytest.mark.parametrize("file_name", file_names) +def test_run_classic_controllers(file_name): + # Run the script and capture the output + directory = "examples" + subdirectory = "classic_controllers" + result = subprocess.run(["python", os.path.join(directory, subdirectory, file_name)], capture_output=True, text=True) + + # Check if the script ran successfully (exit code 0) + assert result.returncode == 0, file_name + " did not exit successfully" + + + + + \ No newline at end of file diff --git a/tests/test_physical_systems/test_electric_motors.py b/tests/test_physical_systems/test_electric_motors.py index e69de29b..ba586bdc 100644 --- a/tests/test_physical_systems/test_electric_motors.py +++ b/tests/test_physical_systems/test_electric_motors.py @@ -0,0 +1,1123 @@ +import math +import pytest +import gym_electric_motor as gem +from gym_electric_motor.physical_systems.electric_motors import ( + ElectricMotor, + DcMotor, + DcExternallyExcitedMotor, + DcPermanentlyExcitedMotor, + DcSeriesMotor, + DcShuntMotor, + ThreePhaseMotor, + InductionMotor, + DoublyFedInductionMotor, + SquirrelCageInductionMotor, + SynchronousMotor, + SynchronousReluctanceMotor, + ExternallyExcitedSynchronousMotor, + PermanentMagnetSynchronousMotor +) +from gymnasium.spaces import Box +import numpy as np + +#parameters for dc motor +test_dcmotor_parameter = {"r_a": 16e-2, "r_e": 16e-1, "l_a": 19e-5, "l_e_prime": 1.7e-2, "l_e": 5.4e-1, "j_rotor": 0.025} +test_dcmotor_nominal_values = dict(omega=350, torque=16.5, i=100, i_a=96, i_e=87, u=65, u_a=65, u_e=61) +test_dcmotor_limits = dict(omega=400, torque=38.0, i=210, i_a=210, i_e=215, u=100, u_a=100, u_e=100) +test_dcmotor_default_initializer = {"states": {"i_a": 10.0, "i_e": 15.0}, "interval": None, "random_init": None, "random_params": (None, None),} +test_electricmotor_default_initializer = {"states": {"omega": 16.0}, "interval": None, "random_init": None, "random_params": (None, None),} +test_DcPermanentlyExcitedMotor_parameter = {"r_a": 16e-5, "l_a": 19e-2, "psi_e": 0.00165, "j_rotor": 0.05,} +test_DcPermanentlyExcitedMotor_initializer = {"states": {"i": 10.0}, "interval": None, "random_init": None, "random_params": (None, None),} +test_DcSeriesMotor_parameter = {"r_a": 16e-2,"r_e": 48e-2,"l_a": 19e-3,"l_e_prime": 1.7e-2,"l_e": 5.4e-2,"j_rotor": 0.25,} +test_DcSeriesMotor_initializer = {"states": {"i": 5.0}, "interval": None, "random_init": None, "random_params": (None, None),} +test_DcShuntMotor_parameter = {"r_a": 16e-3, "r_e": 5e-1, "l_a": 20e-6, "l_e_prime": 1.7e-3, "l_e": 5.4e-3, "j_rotor": 0.025,} +test_DcShuntMotor_initializer = {"states": {"i_a": 10.0, "i_e": 0.0},"interval": None,"random_init": None,"random_params": (None, None),} +test_Induction_motor_parameter = {"p": 3,"l_m": 143.75e-3,"l_sigs": 5.87e-3,"l_sigr": 5.87e-2,"j_rotor": 1.1e-3,"r_s": 3,"r_r": 1.355,} +test_DcInductionMotor_initializer = {"states": {"i_salpha": 1.0,"i_sbeta": 0.0,"psi_ralpha": 0.0,"psi_rbeta": 0.0,"epsilon": 0.0,},"interval": None,"random_init": None,"random_params": (None, None),} +test_ReluctanceMotor_parameter = {"p": 4,"l_d": 1e-3,"l_q": 1e-3,"j_rotor": 1e-3,"r_s": 0.5,} +test_ReluctanceMotor_initializer = { + "states": {"i_sq": 1.0, "i_sd": 2.0, "epsilon": 10.0}, + "interval": None, + "random_init": None, + "random_params": (None, None), + } +test_ExtExcSyncMotor_parameter = {'p': 3,'l_d': 1.66e-1,'l_q': 0.35e-1,'l_m': 1.589e-5,'l_e': 1.74e-3,'j_rotor': 0.3883,'r_s': 15.55e-3,'r_e': 7.2e-3,'k': 65,} +test_ExtExcSyncMotor_initializer = { + "states": {"i_sq": 2.0, "i_sd": 1.0, "i_e": 2.0, "epsilon": 2.0}, + "interval": None, + "random_init": None, + "random_params": (None, None), + } +test_PermMagSyncMotor_parameter = {"p": 3,"l_d": 0.37e-6,"l_q": 1.2e-6,"j_rotor": 0.03883,"r_s": 18,"psi_p": 66e-6,} +test_PermMagSyncMotor_initializer = {"states": {"i_sq": 10.0, "i_sd": 5.0, "epsilon": 10.0}, + "interval": None, + "random_init": None, + "random_params": (None, None), + } +@pytest.fixture +def concreteDCMotor(): + """ + pytest fixture that returns a DC motor object + :return: Electric motor object initialized with concrete values + """ + return DcMotor(test_dcmotor_parameter,test_dcmotor_nominal_values,test_dcmotor_limits,test_dcmotor_default_initializer) + +@pytest.fixture +def concreteDcPermanentlyExcitedMotor(): + """ + pytest fixture that returns a Dc Permanently Excited motor object + :return: Permanently Excited DC motor object with concrete values + """ + return DcPermanentlyExcitedMotor(test_DcPermanentlyExcitedMotor_parameter,None,None,test_DcPermanentlyExcitedMotor_initializer) + +@pytest.fixture +def concreteDCSeriesMotor(): + """ + pytest fixture that returns a Dc Series motor object + :return: Dc Series motor object with concrete values + """ + return DcSeriesMotor(test_DcSeriesMotor_parameter,None,None,test_DcSeriesMotor_initializer) + +@pytest.fixture +def concreteDCShuntMotor(): + """ + pytest fixture that returns a Dc Shunt motor object + :return: Dc Shunt motor object with concrete values + """ + return DcShuntMotor(test_DcShuntMotor_parameter,None,None,test_DcShuntMotor_initializer) + +@pytest.fixture +def concreteInductionMotor(): + """ + pytest fixture that returns a Dc Shunt motor object + :return: Dc Shunt motor object with concrete values + """ + return InductionMotor(test_Induction_motor_parameter,None,None,test_DcInductionMotor_initializer ) + +def test_InitElectricMotor(): + """ + Test whether the Electric motor object attributes are initialized with the correct values + + """ + defaultElectricMotor = ElectricMotor() + concreteElectricMotor = ElectricMotor(None,None,None,test_electricmotor_default_initializer,None) + assert defaultElectricMotor.motor_parameter == {} + assert defaultElectricMotor.nominal_values == {} + assert defaultElectricMotor.limits == {} + assert defaultElectricMotor._initial_states == {} + assert concreteElectricMotor._initial_states == {'omega': 16.0} + with pytest.raises(NotImplementedError): + concreteElectricMotor.electrical_ode(np.random.rand(1, 1),[0,0.5,1,1.5],16.0) + +def test_InitDCMotor(concreteDCMotor): + + """ + Test whether the DC motor object are initialized with correct values" + :return: + """ + defaultDCMotor = DcMotor() + assert defaultDCMotor.motor_parameter == {"r_a": 16e-3, "r_e": 16e-2, "l_a": 19e-6, "l_e_prime": 1.7e-3, "l_e": 5.4e-3, "j_rotor": 0.0025} + assert defaultDCMotor.nominal_values == dict(omega=300, torque=16.0, i=97, i_a=97, i_e=97, u=60, u_a=60, u_e=60) + assert concreteDCMotor.motor_parameter == test_dcmotor_parameter + assert concreteDCMotor.nominal_values == test_dcmotor_nominal_values + assert concreteDCMotor.limits == test_dcmotor_limits + assert concreteDCMotor._initial_states == test_dcmotor_default_initializer["states"] + +def test_DCMotor_torque(concreteDCMotor): + + currents = [100, 10, 2, 3] + expectedtorque = concreteDCMotor.motor_parameter["l_e_prime"]* currents[0] * currents[1] + + assert concreteDCMotor.torque(currents) == expectedtorque + +def test_DCMotor_i_in(concreteDCMotor): + + currents = [100, 10, 2, 3] + expectedcurrent = currents + + assert concreteDCMotor.i_in(currents) == expectedcurrent + +def test_DCMotor_el_ode(concreteDCMotor): + + concreteDCMotor._model_constants[0] = concreteDCMotor._model_constants[0] / concreteDCMotor.motor_parameter["l_a"] + concreteDCMotor._model_constants[1] = concreteDCMotor._model_constants[1] / concreteDCMotor.motor_parameter["l_e"] + u_in = [10,20] + omega = 60 + state = [10.0,15.0] + + expectedElectricalOde = np.matmul( + concreteDCMotor._model_constants, + np.array( + [ + state[0], + state[1], + omega * state[1], + u_in[0], + u_in[1], + ] + ), + ) + + assert np.array_equal(concreteDCMotor.electrical_ode(state,u_in,omega), expectedElectricalOde) + +def test_DCMotor_get_state_space(concreteDCMotor): + u1 = Box(0, 1, shape=(2,), dtype=np.float64) + input_current = Box(-1, 1, shape=(2,), dtype=np.float64) + u2 = Box(-1, 1, shape=(2,), dtype=np.float64) + expectedLowfor_u1 = { + "omega":0, + "torque": -1, + "i_a": -1 , + "i_e": -1 , + "u_a": 0, + "u_e": 0, + } + expectedhigh = {"omega": 1, "torque": 1, "i_a": 1, "i_e": 1, "u_a": 1, "u_e": 1} + expectedLowfor_u2 = { + "omega":-1, + "torque": -1, + "i_a": -1 , + "i_e": -1 , + "u_a": -1, + "u_e": -1, + } + assert expectedLowfor_u1== concreteDCMotor.get_state_space(input_current,u1)[0] + assert expectedhigh == concreteDCMotor.get_state_space(input_current,u1)[1] + assert expectedLowfor_u2== concreteDCMotor.get_state_space(input_current,u2)[0] + assert expectedhigh == concreteDCMotor.get_state_space(input_current,u2)[1] + +def test_ConcreteDCMotor_reset(concreteDCMotor): + new_initial_state = {'i_a': 100.0, 'i_e': 20.0} + default_initial_state = {"i_a": 10.0, "i_e": 15.0} + default_Initial_state_array = [10.0, 15.0] + extex_state_positions = { + "omega": 0, + "torque": 1, + "i":2, + "i_a":3, + "i_e": 4, + "u_a": 5, + "u_e": 6, + } + + extex_state_space = Box(low=-1, high=1, shape=(7,), dtype=np.float64) + assert concreteDCMotor._initial_states == default_initial_state + concreteDCMotor._initial_states = new_initial_state + assert concreteDCMotor._initial_states == new_initial_state + assert np.array_equal(concreteDCMotor.reset(extex_state_space,extex_state_positions),default_Initial_state_array) + concreteDCMotor.initializer["states"] = new_initial_state + concreteDCMotor.reset(extex_state_space,extex_state_positions) + assert concreteDCMotor._initial_states == new_initial_state + +def test_defaultDCMotor_reset(): + defaultDCMotor = DcMotor() + new_initial_state = {'i_a': 1.0, 'i_e': 2.0} + default_initial_state = {"i_a": 0.0, "i_e": 0.0} + default_Initial_state_array = [0.0, 0.0] + extex_state_positions = { + "omega": 0, + "torque": 1, + "i":2, + "i_a":3, + "i_e": 4, + "u_a": 5, + "u_e": 6, + } + + extex_state_space = Box(low=-1, high=1, shape=(7,), dtype=np.float64) + + assert defaultDCMotor._initial_states == default_initial_state + defaultDCMotor._initial_states = new_initial_state + + assert defaultDCMotor._initial_states == new_initial_state + assert np.array_equal(defaultDCMotor.reset(extex_state_space,extex_state_positions),default_Initial_state_array) + assert defaultDCMotor._initial_states == default_initial_state + defaultDCMotor.initializer["states"] = new_initial_state + defaultDCMotor.reset(extex_state_space,extex_state_positions) + assert defaultDCMotor._initial_states == new_initial_state + +def test_defaultDCExternallyExcitedMotor(): + + defaultDcExternallyExcitedMotor = DcExternallyExcitedMotor() + defaultDCMotor = DcMotor() + assert defaultDcExternallyExcitedMotor.motor_parameter == defaultDCMotor.motor_parameter + assert defaultDcExternallyExcitedMotor._default_initializer == defaultDCMotor._default_initializer + assert defaultDcExternallyExcitedMotor._initial_limits == defaultDCMotor._initial_limits + assert defaultDcExternallyExcitedMotor._nominal_values == defaultDCMotor._nominal_values +""" +No defaultDCExternallyExcitedMotor_reset is tested as it would be same as test_defaultDCMotor_reset +""" + +def test_DcExternallyExcitedMotor_el_jacobian() : + defaultDcExternallyExcitedMotor = DcExternallyExcitedMotor() + defaultDCMotor = DcMotor() + mp = defaultDCMotor.motor_parameter + omega = 60 + state =[0.0,0.0] + I_A_IDX = 0 + I_E_IDX = 1 + expected_jacobian = ( + np.array( + [ + [-mp["r_a"] / mp["l_a"], -mp["l_e_prime"] / mp["l_a"] * omega], + [0, -mp["r_e"] / mp["l_e"]], + ] + ), + np.array([-mp["l_e_prime"] * state[I_E_IDX] / mp["l_a"], 0]), + np.array( + [ + mp["l_e_prime"] * state[I_E_IDX], + mp["l_e_prime"] * state[I_A_IDX], + ] + ), + ) + assert np.array_equal(defaultDcExternallyExcitedMotor.electrical_jacobian(state,[],omega)[0],expected_jacobian[0]) + assert np.array_equal(defaultDcExternallyExcitedMotor.electrical_jacobian(state,[],omega)[1],expected_jacobian[1]) + assert np.array_equal(defaultDcExternallyExcitedMotor.electrical_jacobian(state,[],omega)[2],expected_jacobian[2]) + +def test_InitDcPermanentlyExcitedMotor(concreteDcPermanentlyExcitedMotor): + defaultDcPermanentlyExcitedMotor = DcPermanentlyExcitedMotor() + assert defaultDcPermanentlyExcitedMotor.motor_parameter == {"r_a": 16e-3, "l_a": 19e-6, "psi_e": 0.165, "j_rotor": 0.025,} + assert defaultDcPermanentlyExcitedMotor._default_initializer == {"states": {"i": 0.0}, "interval": None, "random_init": None, "random_params": (None, None),} + assert defaultDcPermanentlyExcitedMotor.nominal_values == dict(omega=300, torque=16.0, i=97, u=60) + assert defaultDcPermanentlyExcitedMotor.limits == dict(omega=400, torque=38.0, i=210, u=60) + assert defaultDcPermanentlyExcitedMotor.HAS_JACOBIAN + assert defaultDcPermanentlyExcitedMotor.CURRENTS_IDX[0] == 0 + assert concreteDcPermanentlyExcitedMotor._default_initializer == defaultDcPermanentlyExcitedMotor._default_initializer + assert concreteDcPermanentlyExcitedMotor.nominal_values == defaultDcPermanentlyExcitedMotor.nominal_values + assert concreteDcPermanentlyExcitedMotor.motor_parameter == test_DcPermanentlyExcitedMotor_parameter + assert concreteDcPermanentlyExcitedMotor.initializer == test_DcPermanentlyExcitedMotor_initializer + assert concreteDcPermanentlyExcitedMotor._initial_states == test_DcPermanentlyExcitedMotor_initializer["states"] + +def test_DcPermanentlyExcitedMotor_torque(concreteDcPermanentlyExcitedMotor): + state = [100, 10, 2, 3] + expected_torque = concreteDcPermanentlyExcitedMotor.motor_parameter["psi_e"]*state[0] + assert concreteDcPermanentlyExcitedMotor.torque(state) == expected_torque + +def test_DcPermanentlyExcitedMotor_i_in(concreteDcPermanentlyExcitedMotor): + state = np.array([100,200,300]) + expected_return = state[concreteDcPermanentlyExcitedMotor.CURRENTS_IDX] + assert concreteDcPermanentlyExcitedMotor.i_in(state) == expected_return + + +def test__DcPermanentlyExcitedMotor_el_ode(concreteDcPermanentlyExcitedMotor): + state = [10.0,15.0] + u_in = [10,20] + omega = 60 + expectedODE = np.matmul(concreteDcPermanentlyExcitedMotor._model_constants, [omega] + np.atleast_1d(state[0]).tolist() + [u_in[0]]) + assert np.array_equal(concreteDcPermanentlyExcitedMotor.electrical_ode(state,u_in,omega),expectedODE) + +def test_DcPermanentlyExcitedMotor_el_jacobian(concreteDcPermanentlyExcitedMotor): + defaultDcPermanentlyExcitedMotor = DcPermanentlyExcitedMotor() + mp = concreteDcPermanentlyExcitedMotor.motor_parameter + u_in = [10,20] + omega = 60 + state = [10.0,15.0] + expectedJacobian = ( + np.array([[-mp["r_a"] / mp["l_a"]]]), + np.array([-mp["psi_e"] / mp["l_a"]]), + np.array([mp["psi_e"]]), + ) + default_mp = concreteDcPermanentlyExcitedMotor._default_motor_parameter + default_jacobian = ( + np.array([[-default_mp["r_a"] / default_mp["l_a"]]]), + np.array([-default_mp["psi_e"] / default_mp["l_a"]]), + np.array([default_mp["psi_e"]]), + ) + assert expectedJacobian[0] == concreteDcPermanentlyExcitedMotor.electrical_jacobian(state,u_in,omega)[0] + assert expectedJacobian[1] == concreteDcPermanentlyExcitedMotor.electrical_jacobian(state,u_in,omega)[1] + assert expectedJacobian[2] == concreteDcPermanentlyExcitedMotor.electrical_jacobian(state,u_in,omega)[2] + assert default_jacobian[0] == defaultDcPermanentlyExcitedMotor.electrical_jacobian(state,u_in,omega)[0] + assert default_jacobian[1] == defaultDcPermanentlyExcitedMotor.electrical_jacobian(state,u_in,omega)[1] + assert default_jacobian[2] == defaultDcPermanentlyExcitedMotor.electrical_jacobian(state,u_in,omega)[2] + +def test_DcPermanentlyExcitedMotor_get_state_space(concreteDcPermanentlyExcitedMotor): + u1 = Box(0, 1, shape=(2,), dtype=np.float64) + input_current = Box(-1, 1, shape=(2,), dtype=np.float64) + u2 = Box(-1, 1, shape=(2,), dtype=np.float64) + expectedLowfor_u1 ={ + "omega": 0, + "torque": -1, + "i": -1, + "u": 0, + } + expectedHighfor_u1 = { + "omega": 1, + "torque": 1, + "i": 1, + "u": 1, + } + expectedLowfor_u2 = { + "omega": -1 , + "torque": -1 , + "i": -1 , + "u": -1 , + } + expectedHighfor_u2 = { + "omega": 1 , + "torque": 1 , + "i": 1 , + "u": 1 , + } + assert expectedLowfor_u1 == concreteDcPermanentlyExcitedMotor.get_state_space(input_current,u1)[0] + assert expectedHighfor_u1 == concreteDcPermanentlyExcitedMotor.get_state_space(input_current,u1)[1] + assert expectedLowfor_u2 == concreteDcPermanentlyExcitedMotor.get_state_space(input_current,u2)[0] + assert expectedHighfor_u2 == concreteDcPermanentlyExcitedMotor.get_state_space(input_current,u2)[1] + +def test_DcPermanentlyExcitedMotor_reset(concreteDcPermanentlyExcitedMotor): + new_initial_state = {"i": 100.0} + default_initial_state = {"i": 10.0} + default_Initial_state_array = [10.0] + ex_state_positions = { + "omega": 0, + "torque": 1, + "i":2, + "u":3 + } + + ex_state_space = Box(low=-1, high=1, shape=(4,), dtype=np.float64) + assert concreteDcPermanentlyExcitedMotor._initial_states == default_initial_state + concreteDcPermanentlyExcitedMotor._initial_states = new_initial_state + assert concreteDcPermanentlyExcitedMotor._initial_states == new_initial_state + assert np.array_equal(concreteDcPermanentlyExcitedMotor.reset(ex_state_space,ex_state_positions),default_Initial_state_array) + assert concreteDcPermanentlyExcitedMotor._initial_states == default_initial_state + concreteDcPermanentlyExcitedMotor.initializer["states"] = new_initial_state + concreteDcPermanentlyExcitedMotor.reset(ex_state_space,ex_state_positions) + assert concreteDcPermanentlyExcitedMotor._initial_states == new_initial_state + """ + default motor reset + + """ + defaultDcPermanentlyExcitedMotor = DcPermanentlyExcitedMotor() + default_initialState = {"i": 0.0} + default_InitialState_array = [0.0] + + assert defaultDcPermanentlyExcitedMotor._initial_states == default_initialState + defaultDcPermanentlyExcitedMotor._initial_states = new_initial_state + assert defaultDcPermanentlyExcitedMotor._initial_states == new_initial_state + assert np.array_equal(defaultDcPermanentlyExcitedMotor.reset(ex_state_space,ex_state_positions),default_InitialState_array) + assert defaultDcPermanentlyExcitedMotor._initial_states == default_initialState + defaultDcPermanentlyExcitedMotor.initializer["states"] = new_initial_state + defaultDcPermanentlyExcitedMotor.reset(ex_state_space,ex_state_positions) + assert defaultDcPermanentlyExcitedMotor._initial_states == new_initial_state + +def test_InitDCSeriesMotor(concreteDCSeriesMotor): + defaultDCSeriesMotor = DcSeriesMotor() + assert defaultDCSeriesMotor.motor_parameter == {"r_a": 16e-3, "r_e": 48e-3, "l_a": 19e-6, "l_e_prime": 1.7e-3, "l_e": 5.4e-3, "j_rotor": 0.0025,} + assert defaultDCSeriesMotor._default_initializer == {"states": {"i": 0.0}, "interval": None, "random_init": None, "random_params": (None, None),} + assert defaultDCSeriesMotor.nominal_values == dict(omega=300, torque=16.0, i=97, i_a=97, i_e=97, u=60, u_a=60, u_e=60) + assert defaultDCSeriesMotor.limits == dict(omega=400, torque=38.0, i=210, i_a=210, i_e=210, u=60, u_a=60, u_e=60) + assert defaultDCSeriesMotor.HAS_JACOBIAN + assert defaultDCSeriesMotor.I_IDX == 0 + assert defaultDCSeriesMotor.CURRENTS_IDX[0] == 0 + assert concreteDCSeriesMotor.motor_parameter == test_DcSeriesMotor_parameter + assert concreteDCSeriesMotor._default_initializer == defaultDCSeriesMotor._default_initializer + assert concreteDCSeriesMotor.initializer == test_DcSeriesMotor_initializer + assert concreteDCSeriesMotor.nominal_values == defaultDCSeriesMotor.nominal_values + assert concreteDCSeriesMotor.limits == defaultDCSeriesMotor.limits + assert concreteDCSeriesMotor._initial_states == test_DcSeriesMotor_initializer["states"] + +def test_DCSeriesMotor_Torque(concreteDCSeriesMotor): + + currents = [100, 10, 2, 3] + expectedtorque = concreteDCSeriesMotor.motor_parameter["l_e_prime"]* currents[0] * currents[0] + assert concreteDCSeriesMotor.torque(currents) == expectedtorque + +def test_DCSeriesMotor_el_ode(concreteDCSeriesMotor): + state = [10.0,15.0] + u_in = [10,20] + omega = 60 + expectedODE = np.matmul(concreteDCSeriesMotor._model_constants,np.array([state[0], omega * state[0], u_in[0]]),) + assert np.array_equal(concreteDCSeriesMotor.electrical_ode(state,u_in,omega),expectedODE) + +def test_DCSeriesMotor_i_in(concreteDCSeriesMotor): + currents = np.array([100, 10, 2, 3]) + expectedcurrent = currents[concreteDCSeriesMotor.CURRENTS_IDX] + assert concreteDCSeriesMotor.i_in(currents) == expectedcurrent + + +def test_DCSeriesMotor_get_state_space(concreteDCSeriesMotor): + expectedHigh = {"omega": 1, "torque": 1, "i": 1, "u": 1,} + u1 = Box(0, 1, shape=(2,), dtype=np.float64) + i1 = Box(0, 1, shape=(2,), dtype=np.float64) + u2 = Box(-1, 1, shape=(2,), dtype=np.float64) + i2 = Box(-1, 1, shape=(2,), dtype=np.float64) + expectedLowfor_u1_i1 = {"omega": 0, "torque": 0, "i": 0, "u": 0,} + expectedLowfor_u1_i2 = {"omega": 0, "torque": 0, "i": -1, "u": 0,} + expectedLowfor_u2_i1 = {"omega": 0, "torque": 0, "i": 0, "u": -1,} + expectedLowfor_u2_i2 = {"omega": 0, "torque": 0, "i": -1, "u": -1,} + + assert concreteDCSeriesMotor.get_state_space(i1,u1)[0] == expectedLowfor_u1_i1 + assert concreteDCSeriesMotor.get_state_space(i1,u1)[1] == expectedHigh + assert concreteDCSeriesMotor.get_state_space(i2,u1)[0] == expectedLowfor_u1_i2 + assert concreteDCSeriesMotor.get_state_space(i2,u1)[1] == expectedHigh + assert concreteDCSeriesMotor.get_state_space(i1,u2)[0] == expectedLowfor_u2_i1 + assert concreteDCSeriesMotor.get_state_space(i1,u2)[1] == expectedHigh + assert concreteDCSeriesMotor.get_state_space(i2,u2)[0] == expectedLowfor_u2_i2 + assert concreteDCSeriesMotor.get_state_space(i2,u2)[1] == expectedHigh + +def test_DCSeriesMotor_el_jacobian(concreteDCSeriesMotor): + defaultDCSeriesMotor = DcSeriesMotor() + mp = concreteDCSeriesMotor._motor_parameter + default_mp = concreteDCSeriesMotor._default_motor_parameter + state = [10.0,15.0] + u_in = [10,20] + omega = 60 + + expectedJacobian = ( + np.array([[-(mp["r_a"] + mp["r_e"] + mp["l_e_prime"] * omega) / (mp["l_a"] + mp["l_e"])]]), + np.array([-mp["l_e_prime"] * state[concreteDCSeriesMotor.I_IDX] / (mp["l_a"] + mp["l_e"])]), + np.array([2 * mp["l_e_prime"] * state[concreteDCSeriesMotor.I_IDX]]), + ) + default_jacobian = ( + np.array([[-(default_mp["r_a"] + default_mp["r_e"] + default_mp["l_e_prime"] * omega) / (default_mp["l_a"] + default_mp["l_e"])]]), + np.array([-default_mp["l_e_prime"] * state[concreteDCSeriesMotor.I_IDX] / (default_mp["l_a"] + default_mp["l_e"])]), + np.array([2 * default_mp["l_e_prime"] * state[concreteDCSeriesMotor.I_IDX]]), + ) + assert expectedJacobian[0] == concreteDCSeriesMotor.electrical_jacobian(state,u_in,omega)[0] + assert expectedJacobian[1] == concreteDCSeriesMotor.electrical_jacobian(state,u_in,omega)[1] + assert expectedJacobian[2] == concreteDCSeriesMotor.electrical_jacobian(state,u_in,omega)[2] + assert default_jacobian[0] == defaultDCSeriesMotor.electrical_jacobian(state,u_in,omega)[0] + assert default_jacobian[1] == defaultDCSeriesMotor.electrical_jacobian(state,u_in,omega)[1] + assert default_jacobian[2] == defaultDCSeriesMotor.electrical_jacobian(state,u_in,omega)[2] + +def test_DCSeriesMotor_reset(concreteDCSeriesMotor): + default_initial_state = {"i": 5.0} + default_Initial_state_array = [5.0] + new_initial_state = {"i": 100.0} + series_state_positions = {"omega": 0,"torque": 1,"i":2, "i_a":3, "i_e":4, "u":5, "u_a":6, "u_e":7} + series_state_space = Box(low=-1, high=1, shape=(8,), dtype=np.float64) + assert concreteDCSeriesMotor._initial_states == default_initial_state + concreteDCSeriesMotor._initial_states = new_initial_state + assert concreteDCSeriesMotor._initial_states == new_initial_state + assert np.array_equal(concreteDCSeriesMotor.reset(series_state_space,series_state_positions),default_Initial_state_array) + concreteDCSeriesMotor.initializer["states"] = new_initial_state + concreteDCSeriesMotor.reset(series_state_space,series_state_positions) + assert concreteDCSeriesMotor._initial_states == new_initial_state + +def test_InitDCShuntMotor(concreteDCShuntMotor): + defaultDCShuntMotor = DcShuntMotor() + + assert defaultDCShuntMotor._default_motor_parameter =={"r_a": 16e-3, "r_e": 4e-1, "l_a": 19e-6, "l_e_prime": 1.7e-3, "l_e": 5.4e-3, "j_rotor": 0.0025,} + assert defaultDCShuntMotor._default_initializer == {"states": {"i_a": 0.0, "i_e": 0.0},"interval": None,"random_init": None,"random_params": (None, None),} + assert defaultDCShuntMotor.HAS_JACOBIAN + assert defaultDCShuntMotor._default_motor_parameter == defaultDCShuntMotor.motor_parameter + assert defaultDCShuntMotor._default_initializer == defaultDCShuntMotor.initializer + assert defaultDCShuntMotor._default_nominal_values == dict(omega=300, torque=16.0, i=97, i_a=97, i_e=97, u=60, u_a=60, u_e=60) + assert defaultDCShuntMotor._default_limits == dict(omega=400, torque=38.0, i=210, i_a=210, i_e=210, u=60, u_a=60, u_e=60) + assert concreteDCShuntMotor.motor_parameter == test_DcShuntMotor_parameter + assert concreteDCShuntMotor._default_motor_parameter == defaultDCShuntMotor._default_motor_parameter + assert concreteDCShuntMotor.initializer == test_DcShuntMotor_initializer + assert concreteDCShuntMotor._default_initializer == defaultDCShuntMotor._default_initializer + assert concreteDCShuntMotor._initial_states == test_DcShuntMotor_initializer["states"] + assert concreteDCShuntMotor._default_nominal_values == defaultDCShuntMotor._default_nominal_values + assert concreteDCShuntMotor._default_limits == defaultDCShuntMotor._default_limits + assert concreteDCShuntMotor.I_A_IDX == 0 + assert concreteDCShuntMotor.I_E_IDX == 1 + +def test_DCShuntMotor_i_in(concreteDCShuntMotor): + defaultDCShuntMotor = DcShuntMotor() + currents = [5, 10, 20, 25] + expectedcurrent = [5 + 10] + assert concreteDCShuntMotor.i_in(currents) == expectedcurrent + assert defaultDCShuntMotor.i_in(currents) == concreteDCShuntMotor.i_in(currents) + +def test_DCShuntMotor_el_ode(concreteDCShuntMotor): + state = [5, 10, 20, 25] + u_in = [10,20] + omega = 60 + expectedOde = np.matmul(concreteDCShuntMotor._model_constants,np.array([state[0],state[1],omega * state[1],u_in[0],u_in[0],]),) + assert np.array_equal(concreteDCShuntMotor.electrical_ode(state,u_in,omega),expectedOde) + +def test_DCShuntMotor_el_jacobian(concreteDCShuntMotor): + defaultDCShuntMotor = DcShuntMotor() + state = [5, 10, 20, 25] + u_in = [10,20] + omega = 60 + mp = concreteDCShuntMotor._motor_parameter + default_mp = concreteDCShuntMotor._default_motor_parameter + expectedJacobian = ( + np.array([[-mp["r_a"] / mp["l_a"], -mp["l_e_prime"] / mp["l_a"] * omega],[0, -mp["r_e"] / mp["l_e"]],]), + np.array([-mp["l_e_prime"] * state[1] / mp["l_a"], 0]), + np.array([mp["l_e_prime"] * state[1],mp["l_e_prime"] * state[0],]), + ) + defaultJacobian = ( + np.array([[-default_mp["r_a"] / default_mp["l_a"], -default_mp["l_e_prime"] / default_mp["l_a"] * omega],[0, -default_mp["r_e"] / default_mp["l_e"]],]), + np.array([-default_mp["l_e_prime"] * state[1] / default_mp["l_a"], 0]), + np.array([default_mp["l_e_prime"] * state[1],default_mp["l_e_prime"] * state[0],]), + ) + assert np.array_equal(expectedJacobian[0], concreteDCShuntMotor.electrical_jacobian(state,u_in,omega)[0]) + assert np.array_equal(expectedJacobian[1], concreteDCShuntMotor.electrical_jacobian(state,u_in,omega)[1]) + assert np.array_equal(expectedJacobian[2], concreteDCShuntMotor.electrical_jacobian(state,u_in,omega)[2]) + assert np.array_equal(defaultJacobian[0], defaultDCShuntMotor.electrical_jacobian(state,u_in,omega)[0]) + assert np.array_equal(defaultJacobian[1], defaultDCShuntMotor.electrical_jacobian(state,u_in,omega)[1]) + assert np.array_equal(defaultJacobian[2], defaultDCShuntMotor.electrical_jacobian(state,u_in,omega)[2]) + +def test_DCShuntMotor_get_state_space(concreteDCShuntMotor): + expectedHigh = {"omega": 1, "torque": 1, "i_a": 1,"i_e": 1,"u": 1,} + u1 = Box(0, 1, shape=(2,), dtype=np.float64) + i1 = Box(0, 1, shape=(2,), dtype=np.float64) + u2 = Box(-1, 1, shape=(2,), dtype=np.float64) + i2 = Box(-1, 1, shape=(2,), dtype=np.float64) + expectedLowfor_u1_i1 = {"omega": 0, "torque": 0, "i_a": 0,"i_e": 0,"u": 0,} + expectedLowfor_u1_i2 = {"omega": 0, "torque": -1, "i_a": -1,"i_e": -1,"u": 0,} + expectedLowfor_u2_i1 = {"omega": 0, "torque": 0, "i_a": 0,"i_e": 0,"u": -1,} + expectedLowfor_u2_i2 = {"omega": 0, "torque": -1, "i_a": -1,"i_e": -1,"u": -1,} + + assert concreteDCShuntMotor.get_state_space(i1,u1)[0] == expectedLowfor_u1_i1 + assert concreteDCShuntMotor.get_state_space(i1,u1)[1] == expectedHigh + assert concreteDCShuntMotor.get_state_space(i2,u1)[0] == expectedLowfor_u1_i2 + assert concreteDCShuntMotor.get_state_space(i2,u1)[1] == expectedHigh + assert concreteDCShuntMotor.get_state_space(i1,u2)[0] == expectedLowfor_u2_i1 + assert concreteDCShuntMotor.get_state_space(i1,u2)[1] == expectedHigh + assert concreteDCShuntMotor.get_state_space(i2,u2)[0] == expectedLowfor_u2_i2 + assert concreteDCShuntMotor.get_state_space(i2,u2)[1] == expectedHigh + +def test_ThreePhaseMotor_t_23(): + defaultThreePhaseMotor = ThreePhaseMotor() + t23 = 2 / 3 * np.array([ + [1, -0.5, -0.5], + [0, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3)] + ]) + u_abc = [1, 2, 3] #[u_a, u_b, u_c] + expectedU_out = np.matmul(t23, u_abc) # [u_alpha, u_beta] + assert np.array_equal(defaultThreePhaseMotor.t_23(u_abc),expectedU_out) + +def test_ThreePhaseMotor_t_32(): + defaultThreePhaseMotor = ThreePhaseMotor() + t32 = np.array([ + [1, 0], + [-0.5, 0.5 * np.sqrt(3)], + [-0.5, -0.5 * np.sqrt(3)] + ]) + u_alpha_beta = [10,20] # [u_alpha, u_beta] + expectedU_out = np.matmul(t32, u_alpha_beta) # [u_a, u_b, u_c] + assert np.array_equal(defaultThreePhaseMotor.t_32(u_alpha_beta),expectedU_out) + +def test_ThreePhaseMotor_q(): + defaultThreePhaseMotor = ThreePhaseMotor() + epsilon = 15 # Current electrical angle of the motor + input_dq = [10,20] + cos = math.cos(epsilon) + sin = math.sin(epsilon) + out_alpha_beta = cos * input_dq[0] - sin * input_dq[1], sin * input_dq[0] + cos * input_dq[1] + assert defaultThreePhaseMotor.q(input_dq,epsilon) == out_alpha_beta + +def test_ThreePhaseMotor_q_inv(): + defaultThreePhaseMotor = ThreePhaseMotor() + epsilon = 15 # Current electrical angle of the motor + e = -epsilon + input_alpha_beta = [10,20] + cos = math.cos(e) + sin = math.sin(e) + out_dq = cos * input_alpha_beta[0] - sin * input_alpha_beta[1], sin * input_alpha_beta[0] + cos * input_alpha_beta[1] + assert defaultThreePhaseMotor.q_inv(input_alpha_beta,epsilon) == out_dq + +def test_ThreePhaseMotor_q_me(): + defaultInductionMotorMotor = InductionMotor(test_Induction_motor_parameter,None,None,None,None) + epsilon = 10 #Current mechanical angle of the motor + e = epsilon* defaultInductionMotorMotor._motor_parameter["p"] + input_dq = [10,20] + cos = math.cos(e) + sin = math.sin(e) + out_alpha_beta = cos * input_dq[0] - sin * input_dq[1], sin * input_dq[0] + cos * input_dq[1] + assert defaultInductionMotorMotor.q_me(input_dq,epsilon) == out_alpha_beta + +def test_ThreePhaseMotor_q_inv_me(): + defaultInductionMotorMotor = InductionMotor(test_Induction_motor_parameter,None,None,None,None) + epsilon = 10 #Current mechanical angle of the motor + e = -epsilon* defaultInductionMotorMotor._motor_parameter["p"] + input_dq = [10,20] + cos = math.cos(e) + sin = math.sin(e) + out_alpha_beta = cos * input_dq[0] - sin * input_dq[1], sin * input_dq[0] + cos * input_dq[1] + assert defaultInductionMotorMotor.q_inv_me(input_dq,epsilon) == out_alpha_beta + +def test_InitInductionMotor(concreteInductionMotor): + defaultInductionMotor = InductionMotor() + + assert defaultInductionMotor._default_motor_parameter =={"p": 2,"l_m": 143.75e-3,"l_sigs": 5.87e-3,"l_sigr": 5.87e-3,"j_rotor": 1.1e-3,"r_s": 2.9338,"r_r": 1.355,} + assert defaultInductionMotor._default_initializer == {"states": {"i_salpha": 0.0,"i_sbeta": 0.0,"psi_ralpha": 0.0,"psi_rbeta": 0.0,"epsilon": 0.0,}, + "interval": None, + "random_init": None, + "random_params": (None, None), + } + assert defaultInductionMotor.HAS_JACOBIAN + assert defaultInductionMotor._default_nominal_values == dict(omega=3e3 * np.pi / 30, torque=0.0, i=3.9, epsilon=math.pi, u=560) + assert defaultInductionMotor._default_limits == dict(omega=4e3 * np.pi / 30, torque=0.0, i=5.5, epsilon=math.pi, u=560) + assert concreteInductionMotor.motor_parameter == test_Induction_motor_parameter + assert concreteInductionMotor._default_motor_parameter == defaultInductionMotor._default_motor_parameter + assert concreteInductionMotor._default_motor_parameter == defaultInductionMotor.motor_parameter + assert concreteInductionMotor._initial_states == test_DcInductionMotor_initializer["states"] + assert concreteInductionMotor._default_nominal_values == defaultInductionMotor._default_nominal_values + assert concreteInductionMotor._default_limits == defaultInductionMotor._default_limits + assert defaultInductionMotor.I_SALPHA_IDX == 0 + assert defaultInductionMotor.I_SBETA_IDX == 1 + +def test_InductionMotor_el_ode(concreteInductionMotor): + state = [5, 10, 15, 20, 10] #[i_salpha, i_sbeta, psi_ralpha, psi_rbeta, epsilon] + u_in = np.array([(10,11), (1,2)]) #[u_salpha, u_sbeta, u_ralpha, u_rbeta] + omega = 60 + expectedOde = np.matmul( + concreteInductionMotor._model_constants, + np.array( + [ + # omega, i_alpha, i_beta, psi_ralpha, psi_rbeta, omega * psi_ralpha, omega * psi_rbeta, u_salpha, u_sbeta, u_ralpha, u_rbeta, + omega, + state[concreteInductionMotor.I_SALPHA_IDX], + state[concreteInductionMotor.I_SBETA_IDX], + state[concreteInductionMotor.PSI_RALPHA_IDX], + state[concreteInductionMotor.PSI_RBETA_IDX], + omega * state[concreteInductionMotor.PSI_RALPHA_IDX], + omega * state[concreteInductionMotor.PSI_RBETA_IDX], + u_in[0, 0], + u_in[0, 1], + u_in[1, 0], + u_in[1, 1], + ] + ), + ) + assert np.array_equal(expectedOde, concreteInductionMotor.electrical_ode(state,u_in,omega)) + +def test_InductionMotor_i_in(concreteInductionMotor): + state = np.array([(1, 2), (10, 11), (20,21)]) + expectedcurrent = np.array([(1, 2), (10, 11)]) + assert np.array_equal(expectedcurrent,concreteInductionMotor.i_in(state)) + +def test_InductionMotor_torque(concreteInductionMotor): + mp = concreteInductionMotor._motor_parameter + states = [5, 10, 15, 20, 10] #[i_salpha, i_sbeta, psi_ralpha, psi_rbeta, epsilon] + expectedTorque = ( + 1.5 + * mp["p"] + * mp["l_m"] + / (mp["l_m"] + mp["l_sigr"]) + * ( + states[concreteInductionMotor.PSI_RALPHA_IDX] * states[concreteInductionMotor.I_SBETA_IDX] + - states[concreteInductionMotor.PSI_RBETA_IDX] * states[concreteInductionMotor.I_SALPHA_IDX] + ) + ) + assert np.array_equal(concreteInductionMotor.torque(states),expectedTorque) + +def test_InductionMotor_el_jacobian(concreteInductionMotor): + mp = concreteInductionMotor._motor_parameter + l_s = mp["l_m"] + mp["l_sigs"] + l_r = mp["l_m"] + mp["l_sigr"] + sigma = (l_s * l_r - mp["l_m"] ** 2) / (l_s * l_r) + tau_r = l_r / mp["r_r"] + tau_sig = sigma * l_s / (mp["r_s"] + mp["r_r"] * (mp["l_m"] ** 2) / (l_r**2)) + state = [5, 10, 15, 20, 10] #[i_salpha, i_sbeta, psi_ralpha, psi_rbeta, epsilon] + u_in = np.array([(10,11), (1,2)])#[u_salpha, u_sbeta, u_ralpha, u_rbeta] + omega = 60 + + expectedJacobian = ( + np.array( + [ # dx'/dx + # i_alpha i_beta psi_alpha psi_beta epsilon + [ + -1 / tau_sig, + 0, + mp["l_m"] * mp["r_r"] / (sigma * l_s * l_r**2), + omega * mp["l_m"] * mp["p"] / (sigma * l_r * l_s), + 0, + ], + [ + 0, + -1 / tau_sig, + -omega * mp["l_m"] * mp["p"] / (sigma * l_r * l_s), + mp["l_m"] * mp["r_r"] / (sigma * l_s * l_r**2), + 0, + ], + [mp["l_m"] / tau_r, 0, -1 / tau_r, -omega * mp["p"], 0], + [0, mp["l_m"] / tau_r, omega * mp["p"], -1 / tau_r, 0], + [0, 0, 0, 0, 0], + ] + ), + np.array( + [ # dx'/dw + mp["l_m"] * mp["p"] / (sigma * l_r * l_s) * state[concreteInductionMotor.PSI_RBETA_IDX], + -mp["l_m"] * mp["p"] / (sigma * l_r * l_s) * state[concreteInductionMotor.PSI_RALPHA_IDX], + -mp["p"] * state[concreteInductionMotor.PSI_RBETA_IDX], + mp["p"] * state[concreteInductionMotor.PSI_RALPHA_IDX], + mp["p"], + ] + ), + np.array( + [ # dT/dx + -state[concreteInductionMotor.PSI_RBETA_IDX] * 3 / 2 * mp["p"] * mp["l_m"] / l_r, + state[concreteInductionMotor.PSI_RALPHA_IDX] * 3 / 2 * mp["p"] * mp["l_m"] / l_r, + state[concreteInductionMotor.I_SBETA_IDX] * 3 / 2 * mp["p"] * mp["l_m"] / l_r, + -state[concreteInductionMotor.I_SALPHA_IDX] * 3 / 2 * mp["p"] * mp["l_m"] / l_r, + 0, + ] + ), + ) + + assert np.array_equal(expectedJacobian[0],concreteInductionMotor.electrical_jacobian(state,u_in,omega)[0]) + assert np.array_equal(expectedJacobian[1],concreteInductionMotor.electrical_jacobian(state,u_in,omega)[1]) + assert np.array_equal(expectedJacobian[2],concreteInductionMotor.electrical_jacobian(state,u_in,omega)[2]) + + +""" +def test_InductionMotor_reset(concreteInductionMotor): + #_nominal_values ---> _initial_limits + new_initial_state = {"i_salpha": 5.0,"i_sbeta": 6.0,"psi_ralpha": 0.0,"psi_rbeta": 0.0,"epsilon": 10.0,} + default_initial_state = {"i_salpha": 1.0,"i_sbeta": 0.0,"psi_ralpha": 0.0,"psi_rbeta": 0.0,"epsilon": 0.0,} + default_initial_state_array = [1,0,0,0,0] + InductionMotor_state_positions = { + "i_salpha": 0, + "i_sbeta": 1, + "psi_ralpha": 2, + "psi_rbeta": 3, + "omega": 4, + "torque": 5, + "epsilon":6, + "u": 7 + } + assert concreteInductionMotor._initial_states == default_initial_state + concreteInductionMotor._initial_states = new_initial_state + assert concreteInductionMotor._initial_states == new_initial_state + InductionMotor_state_space = Box(low=-1, high=1, shape=(8,), dtype=np.float64) + assert np.array_equal(concreteInductionMotor.reset(InductionMotor_state_space,InductionMotor_state_positions),default_initial_state_array) +""" +def test_InitDoublyFedIM(): + defaultDoublyFedIM = DoublyFedInductionMotor() + + assert defaultDoublyFedIM.motor_parameter == {"p": 2,"l_m": 297.5e-3,"l_sigs": 25.71e-3,"l_sigr": 25.71e-3,"j_rotor": 13.695e-3,"r_s": 4.42,"r_r": 3.51,} + assert defaultDoublyFedIM._default_initializer == {"states": {"i_salpha": 0.0,"i_sbeta": 0.0,"psi_ralpha": 0.0,"psi_rbeta": 0.0,"epsilon": 0.0,}, + "interval": None, + "random_init": None, + "random_params": (None, None), + } + assert defaultDoublyFedIM._default_nominal_values == dict(omega=1650 * np.pi / 30, torque=0.0, i=7.5, epsilon=math.pi, u=720) + assert defaultDoublyFedIM._default_limits == dict(omega=1800 * np.pi / 30, torque=0.0, i=9, epsilon=math.pi, u=720) + assert defaultDoublyFedIM.IO_CURRENTS == (["i_sa", "i_sb", "i_sc", "i_salpha", "i_sbeta", "i_sd", "i_sq"] + defaultDoublyFedIM.IO_ROTOR_CURRENTS) + assert defaultDoublyFedIM.HAS_JACOBIAN + +def test_InitSquirrelCageIM(): + defaultSquirrelCageIM = SquirrelCageInductionMotor() + defaultDoublyFedIM = DoublyFedInductionMotor() + assert defaultSquirrelCageIM.motor_parameter == {"p": 2,"l_m": 143.75e-3,"l_sigs": 5.87e-3,"l_sigr": 5.87e-3,"j_rotor": 1.1e-3,"r_s": 2.9338,"r_r": 1.355,} + assert defaultSquirrelCageIM._default_initializer == defaultDoublyFedIM._default_initializer + assert defaultSquirrelCageIM._default_limits == dict(omega=4e3 * np.pi / 30, torque=0.0, i=5.5, epsilon=math.pi, u=560) + new_motor_parameter = {"p": 3,"l_m": 140,"l_sigs": 5.87e-3,"l_sigr": 5.87e-2,"j_rotor": 1.1e-3,"r_s": 2.9338,"r_r": 1.1,} + initializer = {"states": {"i_salpha": 0.0,"i_sbeta": 0.0,"psi_ralpha": 0.0,"psi_rbeta": 0.0,"epsilon": 0.0,}, + "interval": None, + "random_init": None, + "random_params": (None, None), + } + concreteSquirrelCageIM = SquirrelCageInductionMotor(new_motor_parameter,None,None,initializer,None) + assert concreteSquirrelCageIM.initializer == initializer + assert concreteSquirrelCageIM.motor_parameter == new_motor_parameter + +def test_SquirrelCageIM_el_ode(): + defaultSquirrelCageIM = SquirrelCageInductionMotor() + state = [5, 10, 15, 20, 10] #[i_salpha, i_sbeta, psi_ralpha, psi_rbeta, epsilon] + u_salphabeta = [10,11] + u_in = np.array([(10,11), (0,0)]) + omega = 60 + expectedOde = np.matmul( + defaultSquirrelCageIM._model_constants, + np.array( + [ + omega, + state[defaultSquirrelCageIM.I_SALPHA_IDX], + state[defaultSquirrelCageIM.I_SBETA_IDX], + state[defaultSquirrelCageIM.PSI_RALPHA_IDX], + state[defaultSquirrelCageIM.PSI_RBETA_IDX], + omega * state[defaultSquirrelCageIM.PSI_RALPHA_IDX], + omega * state[defaultSquirrelCageIM.PSI_RBETA_IDX], + u_in[0, 0], + u_in[0, 1], + u_in[1, 0], + u_in[1, 1], + ] + ), + ) + assert np.array_equal(expectedOde, defaultSquirrelCageIM.electrical_ode(state,u_salphabeta,omega)) + +# ._update_model() is not implemented and hence cant be initialized - discuss +def test_InitSynchronousMotor(): + with pytest.raises(NotImplementedError): + SynchronousMotor() + +def test_InitSynchronousReluctanceMotor(): + defaultReluctanceMotor = SynchronousReluctanceMotor() + assert defaultReluctanceMotor._default_motor_parameter == {"p": 4,"l_d": 10.1e-3,"l_q": 4.1e-3,"j_rotor": 0.8e-3,"r_s": 0.57,} + assert defaultReluctanceMotor.HAS_JACOBIAN + assert defaultReluctanceMotor.motor_parameter == defaultReluctanceMotor._default_motor_parameter + assert defaultReluctanceMotor._initial_states == defaultReluctanceMotor._default_initializer["states"] + concreteReluctanceMotor = SynchronousReluctanceMotor(test_ReluctanceMotor_parameter,None,None,test_ReluctanceMotor_initializer) + assert concreteReluctanceMotor.motor_parameter == test_ReluctanceMotor_parameter + assert concreteReluctanceMotor._initializer == test_ReluctanceMotor_initializer + assert concreteReluctanceMotor._default_motor_parameter == defaultReluctanceMotor._default_motor_parameter + assert concreteReluctanceMotor._initial_states == test_ReluctanceMotor_initializer["states"] + assert defaultReluctanceMotor.I_SD_IDX == 0 + assert defaultReluctanceMotor.I_SQ_IDX == 1 + assert defaultReluctanceMotor.EPSILON_IDX == 2 + assert defaultReluctanceMotor.CURRENTS == ["i_sd", "i_sq"] + assert defaultReluctanceMotor.VOLTAGES == ["u_sd", "u_sq"] + +def test_SyncReluctanceMotor_torque(): + defaultReluctanceMotor = SynchronousReluctanceMotor() + mp = defaultReluctanceMotor._motor_parameter + currents = [10,15] + expectedTorque = 1.5 * mp["p"] * ((mp["l_d"] - mp["l_q"]) * currents[defaultReluctanceMotor.I_SD_IDX]) * currents[defaultReluctanceMotor.I_SQ_IDX] + assert np.array_equal(defaultReluctanceMotor.torque(currents),expectedTorque) + +def test_SyncReluctanceMotor_el_jacobian(): + defaultReluctanceMotor = SynchronousReluctanceMotor() + state = [2,4,10]#[i_sd, i_sq, epsilon] + omega = 60 + u_in = [5,10]#[u_sd, u_sq] + mp = defaultReluctanceMotor._motor_parameter + expectedJacobian = ( + np.array( + [ + [ + -mp["r_s"] / mp["l_d"], + mp["l_q"] / mp["l_d"] * mp["p"] * omega, + 0, + ], + [ + -mp["l_d"] / mp["l_q"] * mp["p"] * omega, + -mp["r_s"] / mp["l_q"], + 0, + ], + [0, 0, 0], + ] + ), + np.array( + [ + mp["p"] * mp["l_q"] / mp["l_d"] * state[defaultReluctanceMotor.I_SQ_IDX], + -mp["p"] * mp["l_d"] / mp["l_q"] * state[defaultReluctanceMotor.I_SD_IDX], + mp["p"], + ] + ), + np.array( + [ + 1.5 * mp["p"] * (mp["l_d"] - mp["l_q"]) * state[defaultReluctanceMotor.I_SQ_IDX], + 1.5 * mp["p"] * (mp["l_d"] - mp["l_q"]) * state[defaultReluctanceMotor.I_SD_IDX], + 0, + ] + ), + ) + assert np.array_equal(expectedJacobian[0],defaultReluctanceMotor.electrical_jacobian(state,u_in,omega)[0]) + assert np.array_equal(expectedJacobian[1],defaultReluctanceMotor.electrical_jacobian(state,u_in,omega)[1]) + assert np.array_equal(expectedJacobian[2],defaultReluctanceMotor.electrical_jacobian(state,u_in,omega)[2]) + +def test_SyncReluctanceMotor_el_ode(): + defaultReluctanceMotor = SynchronousReluctanceMotor() + state = [2,4,10]#[i_sd, i_sq, epsilon] + omega = 60 + u_in = [5,10]#[u_sd, u_sq] + expectedOde = np.matmul( + defaultReluctanceMotor._model_constants, + np.array( + [ + omega, + state[defaultReluctanceMotor.I_SD_IDX], + state[defaultReluctanceMotor.I_SQ_IDX], + u_in[0], + u_in[1], + omega * state[defaultReluctanceMotor.I_SD_IDX], + omega * state[defaultReluctanceMotor.I_SQ_IDX], + ] + ), + ) + assert np.array_equal(defaultReluctanceMotor.electrical_ode(state,u_in,omega),expectedOde) + +def test_SyncReluctanceMotor_i_in(): + defaultReluctanceMotor = SynchronousReluctanceMotor() + state = np.array([1,2,3,5,8,9]) + expectedCurrent = [1,2] + assert np.array_equal(defaultReluctanceMotor.i_in(state),expectedCurrent) + +def test_SyncReluctanceMotor_reset(): + defaultReluctanceMotor = SynchronousReluctanceMotor() + default_initial_state = {"i_sq": 0.0, "i_sd": 0.0, "epsilon": 0.0} + default_Initial_state_array = [0,0,0] + new_initial_state = {"i_sq": 1.0, "i_sd": 2.0, "epsilon": 10.0} + ReluctanceMotor_state_positions = {"i_sq": 0,"i_sd": 1,"torque": 2,"omega": 3,"epsilon": 4,"u": 5,} + ReluctanceMotor_state_space = Box(low=-1, high=1, shape=(6,), dtype=np.float64) + assert defaultReluctanceMotor._initial_states == default_initial_state + defaultReluctanceMotor._initial_states = new_initial_state + assert defaultReluctanceMotor._initial_states == new_initial_state + assert np.array_equal(defaultReluctanceMotor.reset(ReluctanceMotor_state_space,ReluctanceMotor_state_positions),default_Initial_state_array) + defaultReluctanceMotor.initializer["states"] = new_initial_state + defaultReluctanceMotor.reset(ReluctanceMotor_state_space,ReluctanceMotor_state_positions) + assert defaultReluctanceMotor._initial_states == new_initial_state + +def test_InitExtExcitedSynchronousMotor(): + ExtExcSyncMotor = ExternallyExcitedSynchronousMotor() + assert ExtExcSyncMotor._default_motor_parameter == {'p': 3,'l_d': 1.66e-3,'l_q': 0.35e-3,'l_m': 1.589e-3,'l_e': 1.74e-3,'j_rotor': 0.3883,'r_s': 15.55e-3,'r_e': 7.2e-3,'k': 65.21,} + assert ExtExcSyncMotor.HAS_JACOBIAN + mp = ExtExcSyncMotor._motor_parameter + ExtExcSyncMotor._default_motor_parameter.update({'r_E':mp['k'] ** 2 * 3/2 * mp['r_e'], 'l_M':mp['k'] * 3/2 * mp['l_m'], 'l_E': mp['k'] ** 2 * 3/2 * mp['l_e'], 'i_k_rs':2 / 3 / mp['k'], 'sigma':1 - mp['l_M'] ** 2 / (mp['l_d'] * mp['l_E'])}) + assert ExtExcSyncMotor.motor_parameter == ExtExcSyncMotor._default_motor_parameter + assert ExtExcSyncMotor._initial_states == ExtExcSyncMotor._default_initializer["states"] + concreteExtExcSyncMotor = ExternallyExcitedSynchronousMotor(test_ExtExcSyncMotor_parameter,None,None,test_ExtExcSyncMotor_initializer) + newmp = concreteExtExcSyncMotor._motor_parameter + test_ExtExcSyncMotor_parameter.update({'r_E':newmp['k'] ** 2 * 3/2 * newmp['r_e'], 'l_M':newmp['k'] * 3/2 * newmp['l_m'], 'l_E': newmp['k'] ** 2 * 3/2 * newmp['l_e'], 'i_k_rs':2 / 3 / newmp['k'], 'sigma':1 - newmp['l_M'] ** 2 / (newmp['l_d'] * newmp['l_E'])}) + assert concreteExtExcSyncMotor.motor_parameter == test_ExtExcSyncMotor_parameter + assert concreteExtExcSyncMotor._initializer == test_ExtExcSyncMotor_initializer + assert concreteExtExcSyncMotor._default_motor_parameter == ExtExcSyncMotor._default_motor_parameter + assert concreteExtExcSyncMotor._initial_states == test_ExtExcSyncMotor_initializer["states"] + assert ExtExcSyncMotor.I_SD_IDX == 0 + assert ExtExcSyncMotor.I_SQ_IDX == 1 + assert ExtExcSyncMotor.EPSILON_IDX == 3 + assert ExtExcSyncMotor.CURRENTS == ["i_sd", "i_sq", "i_e"] + assert ExtExcSyncMotor.VOLTAGES == ["u_sd", "u_sq", "u_e"] + +""" +what should the u_in and how come the u_dqe[2], +""" +def test_ExtExcitedSynchronousMotor_el_ode(): + ExtExcSyncMotor = ExternallyExcitedSynchronousMotor() + state = [5, 5, 10]#[i_sd, i_sq, epsilon] + omega = 60 + u_in = [50, 60, 50]#[u_sd, u_sq] + expectedOde = np.matmul( + ExtExcSyncMotor._model_constants, + np.array( + [ + omega, + state[ExtExcSyncMotor.I_SD_IDX], + state[ExtExcSyncMotor.I_SQ_IDX], + state[ExtExcSyncMotor.I_E_IDX], + u_in[0], + u_in[1], + u_in[2], + omega * state[ExtExcSyncMotor.I_SD_IDX], + omega * state[ExtExcSyncMotor.I_SQ_IDX], + omega * state[ExtExcSyncMotor.I_E_IDX] + ] + ) + ) + assert np.array_equal(ExtExcSyncMotor.electrical_ode(state,u_in,omega),expectedOde) + +def test_ExtExcitedSynchronousMotor_torque(): + ExtExcSyncMotor = ExternallyExcitedSynchronousMotor() + mp = ExtExcSyncMotor._motor_parameter + currents = [2,3,4]#["i_sd", "i_sq", "i_e"] + expectedTorque = 1.5 * mp["p"] * (mp["l_M"] * currents[ExtExcSyncMotor.I_E_IDX] * mp["i_k_rs"] + (mp["l_d"] - mp["l_q"]) * currents[ExtExcSyncMotor.I_SD_IDX]) * currents[ExtExcSyncMotor.I_SQ_IDX] + assert np.array_equal(ExtExcSyncMotor.torque(currents),expectedTorque) + +def test_ExtExcitedSynchronousMotor_el_jacobian(): + ExtExcSyncMotor = ExternallyExcitedSynchronousMotor() + mp = ExtExcSyncMotor._motor_parameter + state = [5, 5, 10]#[i_sd, i_sq, epsilon] + omega = 60 + u_in = [50, 60, 50]#[u_sd, u_sq] + expectedJacobian = ( + np.array([ # dx'/dx + [ -mp["r_s"] / (mp["l_d"] * mp["sigma"]), mp["l_q"] / (mp["sigma"] * mp["l_d"]) * omega * mp["p"], mp["l_M"] * mp["r_E"] / (mp["sigma"] * mp["l_d"] * mp["l_E"]) * mp["i_k_rs"], 0], + [ -mp["l_d"] / mp["l_q"] * omega * mp["p"], -mp["r_s"] / mp["l_q"], -omega * mp["p"] * mp["l_M"] / mp["l_q"] * mp["i_k_rs"], 0], + [mp["l_M"] * mp["r_s"] / (mp["sigma"] * mp["l_d"] * mp["l_E"] * mp["i_k_rs"]), -omega * mp["p"] * mp["l_M"] * mp["l_q"] / (mp["sigma"] * mp["l_d"] * mp["l_E"] * mp["i_k_rs"]), -mp["r_E"] / (mp["sigma"] * mp["l_E"]), 0], + [ 0, 0, 0, 0], + ]), + np.array([ # dx'/dw + mp["p"] * mp["l_q"] / (mp["l_d"] * mp["sigma"]) * state[ExtExcSyncMotor.I_SQ_IDX], + -mp["p"] * mp["l_d"] / mp["l_q"] * state[ExtExcSyncMotor.I_SD_IDX] - mp["p"] * mp["l_M"] / mp["l_q"] * state[ExtExcSyncMotor.I_E_IDX] * mp["i_k_rs"], + -mp["p"] * mp["l_M"] * mp["l_q"] / (mp["sigma"] * mp["l_d"] * mp["l_E"] * mp["i_k_rs"]) * state[ExtExcSyncMotor.I_SQ_IDX], + mp["p"], + ]), + np.array([ # dT/dx + 1.5 * mp["p"] * (mp["l_d"] - mp["l_q"]) * state[ExtExcSyncMotor.I_SQ_IDX], + 1.5 * mp["p"] * (mp["l_M"] * state[ExtExcSyncMotor.I_E_IDX] * mp["i_k_rs"] + (mp["l_d"] - mp["l_q"]) * state[ExtExcSyncMotor.I_SD_IDX]), + 1.5 * mp["p"] * mp["l_M"] * mp["i_k_rs"] * state[ExtExcSyncMotor.I_SQ_IDX], + 0, + ]) + ) + assert np.array_equal(expectedJacobian[0],ExtExcSyncMotor.electrical_jacobian(state,u_in,omega)[0]) + assert np.array_equal(expectedJacobian[1],ExtExcSyncMotor.electrical_jacobian(state,u_in,omega)[1]) + assert np.array_equal(expectedJacobian[2],ExtExcSyncMotor.electrical_jacobian(state,u_in,omega)[2]) + +def test_ExtExcitedSynchronousMotor_i_in(): + ExtExcSyncMotor = ExternallyExcitedSynchronousMotor() + state = np.array([10,20,3,5,8,9]) + expectedCurrent = [10,20,3] + assert np.array_equal(ExtExcSyncMotor.i_in(state),expectedCurrent) + +def test_ExtExcSyncMotor_reset(): + ExtExcSyncMotor = ExternallyExcitedSynchronousMotor() + default_initial_state = {"i_sq": 0.0, "i_sd": 0.0, "i_e": 0.0, "epsilon": 0.0} + default_Initial_state_array = [0,0,0,0] + new_initial_state = {"i_sq": 10.0, "i_sd": 0.0, "i_e": 10.0, "epsilon": 5.0} + ExtExcSyncMotor_state_positions = {"i_sq": 0,"i_sd": 1,"i_e": 2,"epsilon": 3,"torque": 4,"omega": 5,"u": 6} + ExtExcSyncMotor_state_space = Box(low=-1, high=1, shape=(7,), dtype=np.float64) + assert ExtExcSyncMotor._initial_states == default_initial_state + ExtExcSyncMotor._initial_states = new_initial_state + assert (ExtExcSyncMotor.reset(ExtExcSyncMotor_state_space,ExtExcSyncMotor_state_positions),default_Initial_state_array) + ExtExcSyncMotor.initializer["states"] = new_initial_state + ExtExcSyncMotor.reset(ExtExcSyncMotor_state_space,ExtExcSyncMotor_state_positions) + assert ExtExcSyncMotor._initial_states == new_initial_state + +def test_InitPermMagSyncMotor(): + defaultPermMagSyncMotor = PermanentMagnetSynchronousMotor() + assert defaultPermMagSyncMotor._default_motor_parameter == {"p": 3,"l_d": 0.37e-3,"l_q": 1.2e-3,"j_rotor": 0.03883,"r_s": 18e-3,"psi_p": 66e-3,} + assert defaultPermMagSyncMotor.HAS_JACOBIAN + assert defaultPermMagSyncMotor.motor_parameter == defaultPermMagSyncMotor._default_motor_parameter + assert defaultPermMagSyncMotor._initial_states == defaultPermMagSyncMotor._default_initializer["states"] + concretePermMagSyncMotor = PermanentMagnetSynchronousMotor(test_PermMagSyncMotor_parameter,None,None,test_PermMagSyncMotor_initializer) + assert concretePermMagSyncMotor.motor_parameter == test_PermMagSyncMotor_parameter + assert concretePermMagSyncMotor.initializer == test_PermMagSyncMotor_initializer + assert concretePermMagSyncMotor._initial_states == test_PermMagSyncMotor_initializer["states"] + assert defaultPermMagSyncMotor.CURRENTS_IDX == SynchronousMotor.CURRENTS_IDX + assert defaultPermMagSyncMotor.CURRENTS == SynchronousMotor.CURRENTS + +def test_PermMagSyncMotor_torque(): + defaultPermMagSyncMotor = PermanentMagnetSynchronousMotor() + mp = defaultPermMagSyncMotor._motor_parameter + currents = [3,1,2,3] + expectedTorque = ( + 1.5 * mp["p"] * (mp["psi_p"] + (mp["l_d"] - mp["l_q"]) * currents[defaultPermMagSyncMotor.I_SD_IDX]) * currents[defaultPermMagSyncMotor.I_SQ_IDX] + ) + assert defaultPermMagSyncMotor.torque(currents) == expectedTorque + +def test_PermMagSyncMotor_el_Jacobian(): + defaultPermMagSyncMotor = PermanentMagnetSynchronousMotor() + mp = defaultPermMagSyncMotor._motor_parameter + state = [5, 5] + omega = 60 + u_in = [50, 60] + expectedJacobian = ( + np.array( + [ # dx'/dx + [ + -mp["r_s"] / mp["l_d"], + mp["l_q"] / mp["l_d"] * omega * mp["p"], + 0, + ], + [ + -mp["l_d"] / mp["l_q"] * omega * mp["p"], + -mp["r_s"] / mp["l_q"], + 0, + ], + [0, 0, 0], + ] + ), + np.array( + [ # dx'/dw + mp["p"] * mp["l_q"] / mp["l_d"] * state[defaultPermMagSyncMotor.I_SQ_IDX], + -mp["p"] * mp["l_d"] / mp["l_q"] * state[defaultPermMagSyncMotor.I_SD_IDX] - mp["p"] * mp["psi_p"] / mp["l_q"], + mp["p"], + ] + ), + np.array( + [ # dT/dx + 1.5 * mp["p"] * (mp["l_d"] - mp["l_q"]) * state[defaultPermMagSyncMotor.I_SQ_IDX], + 1.5 * mp["p"] * (mp["psi_p"] + (mp["l_d"] - mp["l_q"]) * state[defaultPermMagSyncMotor.I_SD_IDX]), + 0, + ] + ), + ) + assert np.array_equal(expectedJacobian[0],defaultPermMagSyncMotor.electrical_jacobian(state,u_in,omega)[0]) + +def test_PermMagSyncMotor_el_ODE(): + defaultPermMagSyncMotor = PermanentMagnetSynchronousMotor() + state = [5, 5] + omega = 60 + u_in = [50, 60] + state = [5, 5] + #assert defaultPermMagSyncMotor.electrical_ode(state,u_in,omega) == SynchronousMotor.electrical_ode(state,u_in,omega) \ No newline at end of file