From 6a0658f3d71e3b908ccb9a184c12192a580b6aa9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Nov 2024 15:24:19 +0530 Subject: [PATCH 1/6] test for classic controllers, dc motor, dcExternallyExcited motor --- .../classic_controllers_dc_motor_example.py | 2 +- .../classic_controllers_ind_motor_example.py | 2 +- ...classic_controllers_synch_motor_example.py | 2 +- ...om_classic_controllers_dc_motor_example.py | 2 +- ...m_classic_controllers_ind_motor_example.py | 2 +- ...ation_test_classic_controllers_dc_motor.py | 2 +- .../test_classic_controllers.py | 28 ++ .../test_electric_motors.py | 253 ++++++++++++++++++ 8 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 tests/test_controllers_examples/test_classic_controllers.py 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/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..f8ea5874 100644 --- a/tests/test_physical_systems/test_electric_motors.py +++ b/tests/test_physical_systems/test_electric_motors.py @@ -0,0 +1,253 @@ +import pytest +import gym_electric_motor as gem +from gym_electric_motor.physical_systems.electric_motors import ( + ElectricMotor, + DcMotor, + DcExternallyExcitedMotor, + DcPermanentlyExcitedMotor +) +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=350, torque=38.0, i=210, i_a=210, i_e=215, u=60, u_a=60, u_e=65) +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),} + +@pytest.fixture +def defaultElectricMotor(): + """ + pytest fixture that returns a default electric motor object + :return: electric motor object initialized with default values + """ + return ElectricMotor() + + +@pytest.fixture +def concreteElectricMotor(): + """ + pytest fixture that returns a electric motor object + :return: Electric motor object initialized with concrete initializer + """ + return ElectricMotor(None,None,None,test_electricmotor_default_initializer,None) + +@pytest.fixture +def defaultDCMotor(): + """ + pytest fixture that returns a DC motor object + :return: Electric motor object initialized with concrete values + """ + return DcMotor() + +@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 defaultDcExternallyExcitedMotor(): + """ + pytest fixture that returns a DC ExternallyExcited motor object + :return: ExternallyExcited DC motor object with default values + """ + return DcExternallyExcitedMotor() + +@pytest.fixture +def defaultDcPermanentlyExcitedMotor(): + """ + pytest fixture that returns a Dc Permanently Excited motor object + :return: Permanently Excited DC motor object with default values + """ + return DcPermanentlyExcitedMotor() + +@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) + +def test_InitElectricMotor(defaultElectricMotor,concreteElectricMotor): + """ + Test whether the Electric motor object attributes are initialized with the correct values + :param defaultElectricMotor: + :param concreteElectricMotor: + :return: + """ + 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(defaultDCMotor, concreteDCMotor): + + """ + Test whether the DC motor object are initialized with correct values" + :param defaultDCMotor: + :param concreteDCMotor: + :return: + """ + 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 == {"i_a": 10.0, "i_e": 15.0} + +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_electrical_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): + + inputvoltages = Box(0, 1, shape=(2,), dtype=np.float64) + inputscurrents = Box(-1, 1, shape=(2,), dtype=np.float64) + + expectedlow = { + "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} + + assert concreteDCMotor.get_state_space(inputscurrents,inputvoltages)[0] == expectedlow + assert concreteDCMotor.get_state_space(inputscurrents,inputvoltages)[1] == expectedhigh + +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 = {'i_a': 100.0, 'i_e': 20.0} + + assert concreteDCMotor._initial_states == new_initial_state + assert np.array_equal(concreteDCMotor.reset(extex_state_space,extex_state_positions),default_Initial_state_array) + assert concreteDCMotor._initial_states == default_initial_state + + +def test_defaultDCMotor_reset(defaultDCMotor): + 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 = {'i_a': 1.0, 'i_e': 2.0} + + 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 + +def test_defaultDCExternallyExcitedMotor(defaultDcExternallyExcitedMotor, defaultDCMotor): + + 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 + +def test_DcExternallyExcitedMotor_electrical_jacobian(defaultDcExternallyExcitedMotor,defaultDCMotor) : + 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]) + + From e4b905e58839eb87c639336c8e96baf12680450f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Nov 2024 15:24:19 +0530 Subject: [PATCH 2/6] test for classic controllers, dc motor, dcExternallyExcited motor --- .../classic_controllers_dc_motor_example.py | 2 +- .../classic_controllers_ind_motor_example.py | 2 +- ...classic_controllers_synch_motor_example.py | 2 +- ...om_classic_controllers_dc_motor_example.py | 2 +- ...m_classic_controllers_ind_motor_example.py | 2 +- ...ation_test_classic_controllers_dc_motor.py | 2 +- .../test_classic_controllers.py | 28 ++ .../test_electric_motors.py | 253 ++++++++++++++++++ 8 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 tests/test_controllers_examples/test_classic_controllers.py 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/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..f8ea5874 100644 --- a/tests/test_physical_systems/test_electric_motors.py +++ b/tests/test_physical_systems/test_electric_motors.py @@ -0,0 +1,253 @@ +import pytest +import gym_electric_motor as gem +from gym_electric_motor.physical_systems.electric_motors import ( + ElectricMotor, + DcMotor, + DcExternallyExcitedMotor, + DcPermanentlyExcitedMotor +) +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=350, torque=38.0, i=210, i_a=210, i_e=215, u=60, u_a=60, u_e=65) +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),} + +@pytest.fixture +def defaultElectricMotor(): + """ + pytest fixture that returns a default electric motor object + :return: electric motor object initialized with default values + """ + return ElectricMotor() + + +@pytest.fixture +def concreteElectricMotor(): + """ + pytest fixture that returns a electric motor object + :return: Electric motor object initialized with concrete initializer + """ + return ElectricMotor(None,None,None,test_electricmotor_default_initializer,None) + +@pytest.fixture +def defaultDCMotor(): + """ + pytest fixture that returns a DC motor object + :return: Electric motor object initialized with concrete values + """ + return DcMotor() + +@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 defaultDcExternallyExcitedMotor(): + """ + pytest fixture that returns a DC ExternallyExcited motor object + :return: ExternallyExcited DC motor object with default values + """ + return DcExternallyExcitedMotor() + +@pytest.fixture +def defaultDcPermanentlyExcitedMotor(): + """ + pytest fixture that returns a Dc Permanently Excited motor object + :return: Permanently Excited DC motor object with default values + """ + return DcPermanentlyExcitedMotor() + +@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) + +def test_InitElectricMotor(defaultElectricMotor,concreteElectricMotor): + """ + Test whether the Electric motor object attributes are initialized with the correct values + :param defaultElectricMotor: + :param concreteElectricMotor: + :return: + """ + 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(defaultDCMotor, concreteDCMotor): + + """ + Test whether the DC motor object are initialized with correct values" + :param defaultDCMotor: + :param concreteDCMotor: + :return: + """ + 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 == {"i_a": 10.0, "i_e": 15.0} + +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_electrical_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): + + inputvoltages = Box(0, 1, shape=(2,), dtype=np.float64) + inputscurrents = Box(-1, 1, shape=(2,), dtype=np.float64) + + expectedlow = { + "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} + + assert concreteDCMotor.get_state_space(inputscurrents,inputvoltages)[0] == expectedlow + assert concreteDCMotor.get_state_space(inputscurrents,inputvoltages)[1] == expectedhigh + +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 = {'i_a': 100.0, 'i_e': 20.0} + + assert concreteDCMotor._initial_states == new_initial_state + assert np.array_equal(concreteDCMotor.reset(extex_state_space,extex_state_positions),default_Initial_state_array) + assert concreteDCMotor._initial_states == default_initial_state + + +def test_defaultDCMotor_reset(defaultDCMotor): + 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 = {'i_a': 1.0, 'i_e': 2.0} + + 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 + +def test_defaultDCExternallyExcitedMotor(defaultDcExternallyExcitedMotor, defaultDCMotor): + + 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 + +def test_DcExternallyExcitedMotor_electrical_jacobian(defaultDcExternallyExcitedMotor,defaultDCMotor) : + 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]) + + From 341fc6a635217d696bcc7417c3af4e008d7c04a2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Nov 2024 21:15:09 +0530 Subject: [PATCH 3/6] fix for the examples and test --- .../classic_controllers.py | 92 +++++++++---------- .../controllers/cascaded_foc_controller.py | 46 +++++----- .../controllers/flux_observer.py | 14 +-- .../induction_motor_cascaded_foc.py | 28 +++--- ...tion_motor_torque_to_current_conversion.py | 24 ++--- .../torque_to_current_conversion.py | 24 ++--- 6 files changed, 114 insertions(+), 114 deletions(-) diff --git a/examples/classic_controllers/classic_controllers.py b/examples/classic_controllers/classic_controllers.py index 9ade5e6b..1f4ca931 100644 --- a/examples/classic_controllers/classic_controllers.py +++ b/examples/classic_controllers/classic_controllers.py @@ -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.unwrapped.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.unwrapped.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.unwrapped.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,7 +187,7 @@ 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.unwrapped.action_space) ref_states = controller_kwargs["ref_states"] stages = [] if isinstance(environment.unwrapped.physical_system.unwrapped, DcMotorSystem): # Checking type of motor @@ -253,7 +253,7 @@ def automated_controller_design(environment, **controller_kwargs): ] elif isinstance( - environment.physical_system.unwrapped, + environment.unwrapped.physical_system.unwrapped, (SquirrelCageInductionMotorSystem, DoublyFedInductionMotorSystem), ): if "i_sq" in ref_states or "torque" in ref_states: @@ -323,19 +323,19 @@ def automated_gain(environment, stages, controller_type, _controllers, **control 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")] + elif isinstance(environment.unwrapped.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) @@ -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.unwrapped.physical_system.tau * a) / u_e_lim * i_e_lim + i_gain = p_gain / (environment.unwrapped.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.unwrapped.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.unwrapped.physical_system.tau * a) / u_a_lim * i_a_lim + i_gain = p_gain / (environment.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.physical_system.tau stages_a[0]["d_gain"] = stages_a[0].get("d_gain", d_gain) elif _controllers[controller_type][0] == CascadedController: @@ -445,7 +445,7 @@ def automated_gain(environment, stages, controller_type, _controllers, **control i_gain = p_gain / (environment.unwrapped.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.unwrapped.physical_system.tau stages_a[i]["d_gain"] = stages_a[i].get("d_gain", d_gain) elif i == 1: @@ -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.unwrapped.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.unwrapped.physical_system.tau * a) / u_sd_lim * i_sd_lim + i_gain_d = p_gain_d / (1.5 * environment.unwrapped.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.unwrapped.physical_system.tau * a) / u_sq_lim * i_sq_lim + i_gain_q = p_gain_q / (1.5 * environment.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.physical_system.tau * a) / u_sd_lim * i_sd_lim + i_gain_d = p_gain_d / (1.5 * environment.unwrapped.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.unwrapped.physical_system.tau * a) / u_sq_lim * i_sq_lim + i_gain_q = p_gain_q / (1.5 * environment.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.physical_system.tau overlaid[0]["d_gain"] = overlaid[0].get("d_gain", d_gain) stages = [stages[0], overlaid] diff --git a/examples/classic_controllers/controllers/cascaded_foc_controller.py b/examples/classic_controllers/controllers/cascaded_foc_controller.py index 6b63fb49..58c4e68c 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.unwrapped.physical_system.electrical_motor.t_32 + q = environment.unwrapped.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.unwrapped.physical_system.tau + + self.action_space = environment.unwrapped.action_space + self.state_space = environment.unwrapped.physical_system.state_space + self.state_names = environment.unwrapped.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.unwrapped.physical_system.limits + self.nominal_values = environment.unwrapped.physical_system.nominal_state - self.mp = environment.physical_system.electrical_motor.motor_parameter + self.mp = environment.unwrapped.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.unwrapped.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.unwrapped.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/flux_observer.py b/examples/classic_controllers/controllers/flux_observer.py index f785d5d7..54d04e83 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.unwrapped.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.unwrapped.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.unwrapped.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.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): """ diff --git a/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py b/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py index 5a175f62..ee0a7426 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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.physical_system.limits + self.nominal_values = self.env.unwrapped.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.unwrapped.physical_system.tau - self.dq_to_abc_transformation = environment.physical_system.dq_to_abc_space + self.dq_to_abc_transformation = environment.unwrapped.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.unwrapped.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_torque_to_current_conversion.py b/examples/classic_controllers/controllers/induction_motor_torque_to_current_conversion.py index beecc1ac..13d8a72f 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.unwrapped.physical_system.nominal_state + self.state_space = self.env.unwrapped.physical_system.state_space # Calculate parameters of the motor - mp = self.env.physical_system.electrical_motor.motor_parameter + mp = self.env.unwrapped.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.unwrapped.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.unwrapped.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/torque_to_current_conversion.py b/examples/classic_controllers/controllers/torque_to_current_conversion.py index ca1f19e2..fec3ff44 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.unwrapped.physical_system.electrical_motor.motor_parameter + self.limit = environment.unwrapped.physical_system.limits + self.nominal_values = environment.unwrapped.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.unwrapped.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 From f022115b998bc3266c57e31340da0d4161aa9df9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Nov 2024 21:49:53 +0530 Subject: [PATCH 4/6] np.complex to complex for flux observer --- examples/classic_controllers/controllers/flux_observer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/classic_controllers/controllers/flux_observer.py b/examples/classic_controllers/controllers/flux_observer.py index 54d04e83..c982992a 100644 --- a/examples/classic_controllers/controllers/flux_observer.py +++ b/examples/classic_controllers/controllers/flux_observer.py @@ -21,7 +21,7 @@ def __init__(self, env): ) # 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.get_wrapper_attr('state_names').index("i_sa"), env.get_wrapper_attr('state_names').index("i_sb"), @@ -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) From aabf5d816af08e52d06c00ed7f2558f4f49e3ceb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2024 14:11:52 +0530 Subject: [PATCH 5/6] change to get_wrapper_attr() --- .../classic_controllers.py | 136 +++++++++--------- .../controllers/cascaded_controller.py | 30 ++-- .../controllers/cascaded_foc_controller.py | 22 +-- .../continuous_action_controller.py | 24 ++-- .../controllers/dicrete_action_controller.py | 12 +- .../controllers/flux_observer.py | 6 +- .../controllers/foc_controller.py | 50 +++---- .../induction_motor_cascaded_foc.py | 16 +-- .../controllers/induction_motor_foc.py | 6 +- ...tion_motor_torque_to_current_conversion.py | 10 +- .../controllers/on_off_controller.py | 2 +- .../controllers/pi_controller.py | 2 +- .../controllers/three_point_controller.py | 2 +- .../torque_to_current_conversion.py | 8 +- .../test_electric_motors.py | 2 +- 15 files changed, 164 insertions(+), 164 deletions(-) diff --git a/examples/classic_controllers/classic_controllers.py b/examples/classic_controllers/classic_controllers.py index 1f4ca931..f9433c79 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('state_names'): 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.unwrapped.physical_system, 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.unwrapped.physical_system, 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.unwrapped.physical_system, 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.unwrapped.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.unwrapped.physical_system.unwrapped, + environment.get_wrapper_attr('physical_system').unwrapped, (SquirrelCageInductionMotorSystem, DoublyFedInductionMotorSystem), ): if "i_sq" in ref_states or "torque" in ref_states: @@ -314,16 +314,16 @@ 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.unwrapped.physical_system, SynchronousMotorSystem): + 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")] @@ -341,9 +341,9 @@ def automated_gain(environment, stages, controller_type, _controllers, **control 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.unwrapped.physical_system.tau * a) / u_e_lim * i_e_lim - i_gain = p_gain / (environment.unwrapped.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.unwrapped.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.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) 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.unwrapped.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.unwrapped.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.unwrapped.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.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) 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.unwrapped.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.unwrapped.physical_system.tau * a) / u_sd_lim * i_sd_lim - i_gain_d = p_gain_d / (1.5 * environment.unwrapped.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.unwrapped.physical_system.tau * a) / u_sq_lim * i_sq_lim - i_gain_q = p_gain_q / (1.5 * environment.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.physical_system.tau * a) / u_sd_lim * i_sd_lim - i_gain_d = p_gain_d / (1.5 * environment.unwrapped.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.unwrapped.physical_system.tau * a) / u_sq_lim * i_sq_lim - i_gain_q = p_gain_q / (1.5 * environment.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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/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 58c4e68c..1a237ab4 100644 --- a/examples/classic_controllers/controllers/cascaded_foc_controller.py +++ b/examples/classic_controllers/controllers/cascaded_foc_controller.py @@ -28,14 +28,14 @@ def __init__( torque_control="interpolate", **controller_kwargs, ): - t32 = environment.unwrapped.physical_system.electrical_motor.t_32 - q = environment.unwrapped.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.unwrapped.physical_system.tau + self.tau = environment.get_wrapper_attr('physical_system').tau - self.action_space = environment.unwrapped.action_space - self.state_space = environment.unwrapped.physical_system.state_space - self.state_names = environment.unwrapped.state_names + 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") @@ -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.unwrapped.physical_system.limits - self.nominal_values = environment.unwrapped.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.unwrapped.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.unwrapped.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.unwrapped.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 c982992a..69d340dd 100644 --- a/examples/classic_controllers/controllers/flux_observer.py +++ b/examples/classic_controllers/controllers/flux_observer.py @@ -8,16 +8,16 @@ class FluxObserver: """ def __init__(self, env): - mp = env.unwrapped.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.unwrapped.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.unwrapped.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) 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 ee0a7426..446bd4d0 100644 --- a/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py +++ b/examples/classic_controllers/controllers/induction_motor_cascaded_foc.py @@ -28,9 +28,9 @@ def __init__( **controller_kwargs, ): self.env = environment - self.action_space = environment.unwrapped.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.unwrapped.physical_system.state_space + self.state_space = environment.get_wrapper_attr('physical_system').state_space self.state_names = environment.get_wrapper_attr('state_names') self.stages = stages @@ -43,7 +43,7 @@ def __init__( 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.unwrapped.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.unwrapped.physical_system.limits - self.nominal_values = self.env.unwrapped.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.unwrapped.physical_system.tau + self.tau = self.env.get_wrapper_attr('physical_system').tau - self.dq_to_abc_transformation = environment.unwrapped.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.unwrapped.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 13d8a72f..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,18 +24,18 @@ def __init__( update_interval=1000, ): self.env = environment - self.nominal_values = self.env.unwrapped.physical_system.nominal_state - self.state_space = self.env.unwrapped.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.unwrapped.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.unwrapped.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.get_wrapper_attr('state_names').index("i_sd") @@ -45,7 +45,7 @@ def __init__( 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.unwrapped.physical_system.limits + 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 fec3ff44..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.unwrapped.physical_system.electrical_motor.motor_parameter - self.limit = environment.unwrapped.physical_system.limits - self.nominal_values = environment.unwrapped.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,7 +38,7 @@ 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.unwrapped.physical_system.tau + self.tau = environment.get_wrapper_attr('physical_system').tau self.omega_idx = environment.get_wrapper_attr('state_names').index("omega") self.i_sd_idx = environment.get_wrapper_attr('state_names').index("i_sd") diff --git a/tests/test_physical_systems/test_electric_motors.py b/tests/test_physical_systems/test_electric_motors.py index f8ea5874..df65b982 100644 --- a/tests/test_physical_systems/test_electric_motors.py +++ b/tests/test_physical_systems/test_electric_motors.py @@ -12,7 +12,7 @@ #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=350, torque=38.0, i=210, i_a=210, i_e=215, u=60, u_a=60, u_e=65) +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, From 3c68f04023c942b442809cfd56e60eaf9045f4df Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Dec 2024 19:56:45 +0530 Subject: [PATCH 6/6] test for Dc PermanentlyExcited, Series and shunt motors --- .../test_electric_motors.py | 437 ++++++++++++++---- 1 file changed, 356 insertions(+), 81 deletions(-) diff --git a/tests/test_physical_systems/test_electric_motors.py b/tests/test_physical_systems/test_electric_motors.py index df65b982..fa7a7f3b 100644 --- a/tests/test_physical_systems/test_electric_motors.py +++ b/tests/test_physical_systems/test_electric_motors.py @@ -4,7 +4,9 @@ ElectricMotor, DcMotor, DcExternallyExcitedMotor, - DcPermanentlyExcitedMotor + DcPermanentlyExcitedMotor, + DcSeriesMotor, + DcShuntMotor ) from gymnasium.spaces import Box import numpy as np @@ -13,46 +15,14 @@ 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_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),} - -@pytest.fixture -def defaultElectricMotor(): - """ - pytest fixture that returns a default electric motor object - :return: electric motor object initialized with default values - """ - return ElectricMotor() - - -@pytest.fixture -def concreteElectricMotor(): - """ - pytest fixture that returns a electric motor object - :return: Electric motor object initialized with concrete initializer - """ - return ElectricMotor(None,None,None,test_electricmotor_default_initializer,None) - -@pytest.fixture -def defaultDCMotor(): - """ - pytest fixture that returns a DC motor object - :return: Electric motor object initialized with concrete values - """ - return DcMotor() +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),} @pytest.fixture def concreteDCMotor(): @@ -63,36 +33,36 @@ def concreteDCMotor(): return DcMotor(test_dcmotor_parameter,test_dcmotor_nominal_values,test_dcmotor_limits,test_dcmotor_default_initializer) @pytest.fixture -def defaultDcExternallyExcitedMotor(): - """ - pytest fixture that returns a DC ExternallyExcited motor object - :return: ExternallyExcited DC motor object with default values +def concreteDcPermanentlyExcitedMotor(): + """ + pytest fixture that returns a Dc Permanently Excited motor object + :return: Permanently Excited DC motor object with concrete values """ - return DcExternallyExcitedMotor() + return DcPermanentlyExcitedMotor(test_DcPermanentlyExcitedMotor_parameter,None,None,test_DcPermanentlyExcitedMotor_initializer) @pytest.fixture -def defaultDcPermanentlyExcitedMotor(): - """ - pytest fixture that returns a Dc Permanently Excited motor object - :return: Permanently Excited DC motor object with default values +def concreteDCSeriesMotor(): """ - return DcPermanentlyExcitedMotor() + 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 ConcreteDcPermanentlyExcitedMotor(): - """ - pytest fixture that returns a Dc Permanently Excited motor object - :return: Permanently Excited DC motor object with concrete values +def concreteDCShuntMotor(): + """ + pytest fixture that returns a Dc Shunt motor object + :return: Dc Shunt motor object with concrete values """ - return DcPermanentlyExcitedMotor(test_DcPermanentlyExcitedMotor_parameter,None,None,test_DcPermanentlyExcitedMotor_initializer) + return DcShuntMotor(test_DcShuntMotor_parameter,None,None,test_DcShuntMotor_initializer) -def test_InitElectricMotor(defaultElectricMotor,concreteElectricMotor): +def test_InitElectricMotor(): """ Test whether the Electric motor object attributes are initialized with the correct values - :param defaultElectricMotor: - :param concreteElectricMotor: - :return: + """ + defaultElectricMotor = ElectricMotor() + concreteElectricMotor = ElectricMotor(None,None,None,test_electricmotor_default_initializer,None) assert defaultElectricMotor.motor_parameter == {} assert defaultElectricMotor.nominal_values == {} assert defaultElectricMotor.limits == {} @@ -101,20 +71,19 @@ def test_InitElectricMotor(defaultElectricMotor,concreteElectricMotor): with pytest.raises(NotImplementedError): concreteElectricMotor.electrical_ode(np.random.rand(1, 1),[0,0.5,1,1.5],16.0) -def test_InitDCMotor(defaultDCMotor, concreteDCMotor): +def test_InitDCMotor(concreteDCMotor): """ Test whether the DC motor object are initialized with correct values" - :param defaultDCMotor: - :param concreteDCMotor: :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 == {"i_a": 10.0, "i_e": 15.0} + assert concreteDCMotor._initial_states == test_dcmotor_default_initializer["states"] def test_DCMotor_torque(concreteDCMotor): @@ -130,7 +99,7 @@ def test_DCMotor_i_in(concreteDCMotor): assert concreteDCMotor.i_in(currents) == expectedcurrent -def test_DCMotor_electrical_ode(concreteDCMotor): +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"] @@ -154,11 +123,10 @@ def test_DCMotor_electrical_ode(concreteDCMotor): assert np.array_equal(concreteDCMotor.electrical_ode(state,u_in,omega), expectedElectricalOde) def test_DCMotor_get_state_space(concreteDCMotor): - - inputvoltages = Box(0, 1, shape=(2,), dtype=np.float64) - inputscurrents = Box(-1, 1, shape=(2,), dtype=np.float64) - - expectedlow = { + 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 , @@ -166,11 +134,19 @@ def test_DCMotor_get_state_space(concreteDCMotor): "u_a": 0, "u_e": 0, } - - expectedhigh = {"omega": 1, "torque": 1, "i_a": 1, "i_e": 1, "u_a": 1, "u_e": 1} - - assert concreteDCMotor.get_state_space(inputscurrents,inputvoltages)[0] == expectedlow - assert concreteDCMotor.get_state_space(inputscurrents,inputvoltages)[1] == expectedhigh + 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} @@ -188,14 +164,13 @@ def test_ConcreteDCMotor_reset(concreteDCMotor): extex_state_space = Box(low=-1, high=1, shape=(7,), dtype=np.float64) assert concreteDCMotor._initial_states == default_initial_state - concreteDCMotor._initial_states = {'i_a': 100.0, 'i_e': 20.0} - + 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) - assert concreteDCMotor._initial_states == default_initial_state -def test_defaultDCMotor_reset(defaultDCMotor): +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] @@ -212,20 +187,27 @@ def test_defaultDCMotor_reset(defaultDCMotor): extex_state_space = Box(low=-1, high=1, shape=(7,), dtype=np.float64) assert defaultDCMotor._initial_states == default_initial_state - defaultDCMotor._initial_states = {'i_a': 1.0, 'i_e': 2.0} + 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 -def test_defaultDCExternallyExcitedMotor(defaultDcExternallyExcitedMotor, defaultDCMotor): +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 - -def test_DcExternallyExcitedMotor_electrical_jacobian(defaultDcExternallyExcitedMotor,defaultDCMotor) : +""" +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] @@ -250,4 +232,297 @@ def test_DcExternallyExcitedMotor_electrical_jacobian(defaultDcExternallyExcited 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 + +""" +does i_in function will work because of the index [0] instead 0 + +def test_DcPermanentlyExcitedMotor_i_in(concreteDcPermanentlyExcitedMotor): + state = [100,200,300] + expected_return = state[0] + 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 + + """ + 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 + +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) + +""" +does i_in function will work because of the index [0] instead 0 +def test_DCSeriesMotor_i_in(concreteDCSeriesMotor): + currents = [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) + +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] + expectedexpectedcurrent = [5 + 10] + assert concreteDCShuntMotor.i_in(currents) == expectedexpectedcurrent + 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 \ No newline at end of file