Skip to content

Commit

Permalink
fixed review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
GitPascalP committed Aug 19, 2020
1 parent d2efda8 commit 11ca283
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 35 deletions.
13 changes: 5 additions & 8 deletions examples/external_speed_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,17 @@
# ConstantSpeedLoad, due to the already given profile by an ExternalSpeedLoad
load_init = {'random_init': 'uniform'},

# external speed profiles can be given by an ExternalSpeedLoad, ConstantSpeedLoad
# the initial value of the external load should be match with the profile
# offset to avoid complicated spikes after a new episode start
# defining a ConstandSpeedLoad
const_load = ConstantSpeedLoad(omega_fixed=42)
bias = 20
ext_load = ExternalSpeedLoad(omega_initial=bias,
speed_profile=sinus_lambda,
amp=10, f=2, b=bias)
# External speed profiles can be given by an ExternalSpeedLoad,
# inital value is given by bias of the profile
ext_load = ExternalSpeedLoad(speed_profile=sinus_lambda, amp=10, f=2, b=42)

if __name__ == '__main__':
env = gem.make(
'DcSeriesCont-v1',
# Pass an instance
visualization=MotorDashboard(plots=['omega','reward', 'i'],
visualization=MotorDashboard(plots=['omega', 'reward', 'i'],
dark_mode=False),
motor_parameter=dict(r_a=15e-3, r_e=15e-3, l_a=1e-3, l_e=1e-3),
# Take standard class and pass parameters (Load)
Expand Down
46 changes: 24 additions & 22 deletions gym_electric_motor/physical_systems/mechanical_loads.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import numpy as np
from scipy.stats import truncnorm

import warnings

# todo updateting intialization with load_initializer,
# now can be initialized directly in load class
class MechanicalLoad:
"""
The MechanicalLoad is the base class for all the mechanical systems attached to the electrical motors rotor.
The MechanicalLoad is the base class for all the mechanical systems attached
to the electrical motors rotor.
It contains an mechanical ode system as well as the state names, limits and nominal values
of the mechanical quantities. The only required state is 'omega' as the rotational speed of the motor shaft
in rad/s.
ExternalSpeedLoad and ConstantSpeedLoad can be initialized by giving the
initializer as an class parameter by instanziation
It contains an mechanical ode system as well as the state names, limits and
nominal values of the mechanical quantities. The only required state is
'omega' as the rotational speed of the motor shaft in rad/s.
ConstantSpeedLoad can be initialized with the initializer as an
class parameter by instantiation. ExternalSpeedLoad takes the first value
of the SpeedProfile as initial value.
Initialization is given by initializer(dict). Can be a constant state value
or random value in given interval.
Expand All @@ -22,6 +24,7 @@ class MechanicalLoad:
(only for random init), shape(num states, 2)
'random_init'(str): 'uniform' or 'normal'
'random_params(tuple): mue(float), sigma(int)
Example initializer(dict) for constant initialization:
{ 'states': {'omega': 16.0}}
Example initializer(dict) for random initialization:
Expand Down Expand Up @@ -334,11 +337,6 @@ class ExternalSpeedLoad(MechanicalLoad):

HAS_JACOBIAN = False

_default_initializer = {'states': {'omega': 0.0},
'interval': None,
'random_init': None,
'random_params': (None, None)}

@property
def omega(self):
"""
Expand All @@ -347,8 +345,8 @@ def omega(self):
"""
return self._omega_initial

def __init__(self, speed_profile=None, omega_initial=0,
tau=1e-4, load_initializer=None, **kwargs):
def __init__(self, speed_profile, tau=1e-4,
load_initializer=None, **kwargs):
"""
Args:
speed_profile(function): function or lambda expression
Expand All @@ -357,20 +355,20 @@ def __init__(self, speed_profile=None, omega_initial=0,
(lambda t, amplitude, freq: amplitude*numpy.sin(2*pi*f)))
with additional parameters:
amplitude(float), freq(float), time(float)
omega_initial(float)): Initial value for the speed in rad/s.
the initial value must be the same as the speed profile
offset for omptimal usage
tau(float): discrete time step of the system
kwargs(dict): further arguments for speed_profile
"""
self._initializer = self._default_initializer.copy()
self._initializer['states']['omega'] = omega_initial
super().__init__(load_initializer=load_initializer, **kwargs)

super().__init__(**kwargs)
warnings.warn('Given initializer will be overwritten with starting value from speed-profile, '
'to avoid complications at the load reset. It is recommended to choose starting value of'
' load by the defined speed-profile.',
UserWarning)

self.kwargs = kwargs
self._omega_initial = omega_initial
self._speed_profile = speed_profile
# setting initial load as speed-profile at time 0
self._omega_initial = self._speed_profile(t=0, **self.kwargs)
self._tau = tau
#self._jacobi = jacobi

Expand All @@ -388,6 +386,10 @@ def mechanical_jacobian(self, t, mechanical_state, torque):
# jacobian here not necessary, since omega is externally given
return None

def reset(self, **kwargs):
# Docstring of superclass
return np.asarray(self._omega_initial, dtype=float)[None]


class ConstantSpeedLoad(MechanicalLoad):
"""
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ gym>=0.15.4
pytest>=5.2.2
pytest-cov
pytest-lambda
warnings
18 changes: 13 additions & 5 deletions tests/test_physical_systems/test_mechanical_loads.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,11 @@ def test_PolynomialStaticLoad_MechanicalOde(concretePolynomialLoad, omega, expec
class TestMechanicalLoad:
key = ''
class_to_test = MechanicalLoad
kwargs = {}

def test_registered(self):
if self.key != '':
load = gem.utils.instantiate(MechanicalLoad, self.key)
load = gem.utils.instantiate(MechanicalLoad, self.key, **self.kwargs)
assert type(load) == self.class_to_test


Expand Down Expand Up @@ -248,17 +249,24 @@ class TestExtSpeedLoad(TestMechanicalLoad):

key = 'ExtSpeedLoad'
class_to_test = ExternalSpeedLoad
kwargs = dict(speed_profile=test_speed_profile,
amp=test_amp,
bias=test_bias,
freq=test_freq)

@pytest.fixture
def ext_speed_load(self):
return ExternalSpeedLoad(test_speed_profile, 10,
return ExternalSpeedLoad(speed_profile=test_speed_profile,
amp=test_amp, bias=test_bias, freq=test_freq)

def test_initialization(self):
load = ExternalSpeedLoad(test_speed_profile, 10,
load = ExternalSpeedLoad(speed_profile=test_speed_profile,
amp=test_amp, bias=test_bias, freq=test_freq)
assert load._speed_profile == test_speed_profile
assert load._omega_initial == 10
assert load.omega == test_speed_profile(t=0,
amp=test_amp,
bias=test_bias,
freq=test_freq)
for key in ['amp', 'bias', 'freq']:
assert key in load.kwargs

Expand Down Expand Up @@ -291,7 +299,7 @@ def test_reset(self, ext_speed_load):
]
)
def test_jacobian(self, omega, omega_initial, expected):
test_object = self.class_to_test(test_speed_profile, 10, amp=test_amp,
test_object = self.class_to_test(test_speed_profile, amp=test_amp,
bias=test_bias, freq=test_freq)

# 2 Runs to test independence on time and torque
Expand Down

0 comments on commit 11ca283

Please sign in to comment.