Skip to content

Commit

Permalink
Use dataclasses to parametrize the machine models, both the system mo…
Browse files Browse the repository at this point in the history
…del and the parameter estimates in the control system (#131)

* Use the dataclasses to parametrize the system model

* Use the MachineModelPars dataclasses to parametrize the control systems as well

* Try to use Union in the dataclass
  • Loading branch information
mhinkkan authored Jun 7, 2024
1 parent 4cf9e40 commit dd04fde
Show file tree
Hide file tree
Showing 35 changed files with 365 additions and 264 deletions.
2 changes: 1 addition & 1 deletion docs/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Several powerful open-source IDEs are available for Python. The following instru

After completing the above steps, the virtual environment can be found in the ``.venv`` directory at the root of the repository. Now you should be able to run all the examples as well as to modify the existing code. When you start VS Code next time, it will automatically detect the virtual environment and use it.

If you installed the ``dev`` requirements, you can also use the interactive IPython console (click on the *Play* button dropdown menu in VS Code). If you aim to work with the documentation, install also the ``docs`` requirements. For previewing the documentation in VS Code, you can install the Esbonio extension: https://docs.esbon.io/en/latest/lsp/editors/vscode.html.
If you installed the ``dev`` dependencies, you can also use the interactive IPython console (click on the *Play* button dropdown menu in VS Code). If you aim to work with the documentation, install also the ``doc`` dependencies. For previewing the documentation in VS Code, you can install the Esbonio extension: https://docs.esbon.io/en/latest/lsp/editors/vscode.html.

If you use Windows, you may need to change the default terminal from the PowerShell to the Command Prompt (press Ctrl+Shift+P for the command palette and search for *Terminal: Select Default Profile*).

Expand Down
10 changes: 6 additions & 4 deletions examples/flux_vector/plot_flux_vector_pmsm_2kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot
from motulator.drive.utils import (
BaseValues, NominalValues, plot, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand All @@ -20,18 +21,19 @@
# %%
# Configure the system model.

machine = model.SynchronousMachine(
mdl_par = SynchronousMachinePars(
n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545)
machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)

# %%
# Configure the control system.

par = control.ModelPars(n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545, J=.015)
par = mdl_par # Assume accurate machine model parameter estimates
cfg = control.FluxTorqueReferenceCfg(par, max_i_s=1.5*base.i, k_u=.9)
ctrl = control.FluxVectorCtrl(par, cfg, T_s=250e-6, sensorless=True)
ctrl = control.FluxVectorCtrl(par, cfg, J=.015, T_s=250e-6, sensorless=True)

# %%
# Set the speed reference and the external load torque.
Expand Down
17 changes: 9 additions & 8 deletions examples/flux_vector/plot_flux_vector_pmsyrm_5kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand Down Expand Up @@ -144,25 +145,25 @@ def i_s(psi_s):
# %%
# Configure the system model.

machine = model.SynchronousMachine(n_p=2, R_s=.63, i_s=i_s, psi_s0=psi_s0)
mdl_par = SynchronousMachinePars(n_p=2, R_s=.63)
machine = model.SynchronousMachine(mdl_par, i_s=i_s, psi_s0=psi_s0)
# Magnetically linear PM-SyRM model for comparison
# machine = model.sm.SynchronousMachine(
# n_p=2, R_s=.63, L_d=18e-3, L_q=110e-3, psi_f=.47)
# mdl_par = SynchronousMachinePars(
# n_p=2, R_s=.63, L_d=18e-3, L_q=110e-3, psi_f=.47)
# machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)
# mdl.pwm = model.CarrierComparison() # Enable the PWM model

# %%
# Configure the control system.

# Control system is based on the constant inductances
par = control.ModelPars(
n_p=2, R_s=.63, L_d=18e-3, L_q=110e-3, psi_f=.47, J=.015)
par = SynchronousMachinePars(n_p=2, R_s=.63, L_d=18e-3, L_q=110e-3, psi_f=.47)
# Limit the maximum reference flux to the base value
cfg = control.FluxTorqueReferenceCfg(
par, max_i_s=2*base.i, k_u=1, max_psi_s=base.psi)
ctrl = control.FluxVectorCtrl(par, cfg, sensorless=True)
ctrl = control.FluxVectorCtrl(par, cfg, J=.015, sensorless=True)
# Select a lower speed-estimation bandwidth to mitigate the saturation effects
ctrl.observer = control.Observer(
control.ObserverCfg(par, alpha_o=2*np.pi*40, sensorless=True))
Expand Down
17 changes: 10 additions & 7 deletions examples/flux_vector/plot_flux_vector_syrm_7kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand Down Expand Up @@ -48,10 +49,12 @@ def i_s(psi_s):
# %%
# Configure the system model.

machine = model.SynchronousMachine(n_p=2, R_s=.54, i_s=i_s, psi_s0=0)
mdl_par = SynchronousMachinePars(n_p=2, R_s=.54)
machine = model.SynchronousMachine(mdl_par, i_s=i_s, psi_s0=0)
# Magnetically linear SyRM model for comparison
# machine = model.sm.SynchronousMachine(
# n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
# mdl_par = SynchronousMachinePars(
# n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
# machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)
Expand All @@ -61,12 +64,12 @@ def i_s(psi_s):
# Furthermore, the inductance estimates L_d and L_q are intentionally set to
# lower values in order to demonstrate the PM-flux disturbance estimation.

par = control.ModelPars(
n_p=2, R_s=.54, L_d=.7*37e-3, L_q=.8*6.2e-3, psi_f=0, J=.015)
par = SynchronousMachinePars(
n_p=2, R_s=.54, L_d=.7*37e-3, L_q=.8*6.2e-3, psi_f=0)
# Disable MTPA since the control system does not consider the saturation
cfg = control.FluxTorqueReferenceCfg(
par, max_i_s=2*base.i, k_u=.9, min_psi_s=base.psi, max_psi_s=base.psi)
ctrl = control.FluxVectorCtrl(par, cfg, sensorless=True)
ctrl = control.FluxVectorCtrl(par, cfg, J=.015, sensorless=True)
# Since the saturation is not considered in the control system, the speed
# estimation bandwidth is set to a lower value. Furthermore, the PM-flux
# disturbance estimation is enabled at speeds above 2*pi*20 rad/s (electrical).
Expand Down
12 changes: 8 additions & 4 deletions examples/obs_vhz/plot_obs_vhz_ctrl_im_2kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

from motulator.drive import model
import motulator.drive.control.im as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, InductionMachinePars, InductionMachineInvGammaPars,
NominalValues, plot, Sequence)

# %%
# Compute base values based on the nominal values (just for figures).
Expand All @@ -24,8 +26,10 @@
# Configure the system model.

# Configure the induction machine using its inverse-Γ parameters
machine = model.InductionMachineInvGamma(
R_s=3.7, R_R=2.1, L_sgm=.021, L_M=.224, n_p=2)
mdl_ig_par = InductionMachineInvGammaPars(
n_p=2, R_s=3.7, R_R=2.1, L_sgm=.021, L_M=.224)
mdl_par = InductionMachinePars.from_inv_gamma_model_pars(mdl_ig_par)
machine = model.InductionMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)
Expand All @@ -34,7 +38,7 @@
# Configure the control system.

# Inverse-Γ model parameter estimates
par = control.ModelPars(R_s=3.7, R_R=2.1, L_sgm=.021, L_M=.224, n_p=2)
par = mdl_ig_par # Assume accurate machine model parameter estimates
cfg = control.ObserverBasedVHzCtrlCfg(
nom_psi_s=base.psi, max_i_s=1.5*base.i, slip_compensation=False)
ctrl = control.ObserverBasedVHzCtrl(par, cfg, T_s=250e-6)
Expand Down
8 changes: 5 additions & 3 deletions examples/obs_vhz/plot_obs_vhz_ctrl_pmsm_2kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand All @@ -22,16 +23,17 @@
# %%
# Configure the system model.

machine = model.SynchronousMachine(
mdl_par = SynchronousMachinePars(
n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545)
machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)

# %%
# Configure the control system.

par = control.ModelPars(n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545)
par = mdl_par # Assume accurate machine model parameter estimates
cfg = control.ObserverBasedVHzCtrlCfg(par, max_i_s=1.5*base.i)
ctrl = control.ObserverBasedVHzCtrl(par, cfg, T_s=250e-6)
#ctrl.rate_limiter = control.RateLimiter(2*np.pi*120)
Expand Down
8 changes: 5 additions & 3 deletions examples/obs_vhz/plot_obs_vhz_ctrl_pmsm_2kw_two_mass.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand All @@ -27,8 +28,9 @@
# %%
# Configure the system model.

machine = model.SynchronousMachine(
mdl_par = SynchronousMachinePars(
n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545)
machine = model.SynchronousMachine(mdl_par)
mechanics = model.TwoMassMechanics(
J_M=.005, J_L=.005, K_S=700, C_S=.01) # C_S=.13
converter = model.Inverter(u_dc=540)
Expand All @@ -37,7 +39,7 @@
# %%
# Configure the control system.

par = control.ModelPars(n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545)
par = mdl_par # Assume accurate machine model parameter estimates
cfg = control.ObserverBasedVHzCtrlCfg(par, max_i_s=1.5*base.i)
ctrl = control.ObserverBasedVHzCtrl(par, cfg, T_s=250e-6)
#ctrl.rate_limiter = control.RateLimiter(2*np.pi*120)
Expand Down
14 changes: 9 additions & 5 deletions examples/obs_vhz/plot_obs_vhz_ctrl_pmsyrm_thor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)
from motulator.drive.utils import (
import_syre_data, plot_flux_vs_current, plot_flux_map)

Expand Down Expand Up @@ -86,19 +87,22 @@ def i_s(psi_s):
# %%
# Configure the system model.

# Create the motor model
machine = model.SynchronousMachine(n_p=2, R_s=.2, i_s=i_s, psi_s0=psi_s0)
# Create the machine model
mdl_par = SynchronousMachinePars(
n_p=2, R_s=.2, L_d=4e-3, L_q=17e-3, psi_f=.134)
machine = model.SynchronousMachine(mdl_par, i_s=i_s, psi_s0=psi_s0)
# Magnetically linear PM-SyRM model
# machine = model.sm.SynchronousMachine(
# mdl_par = SynchronousMachinePars(
# n_p=2, R_s=.2, L_d=4e-3, L_q=17e-3, psi_f=.134)
# machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.0042)
converter = model.Inverter(u_dc=310)
mdl = model.Drive(converter, machine, mechanics)

# %%
# Configure the control system.

par = control.ModelPars(n_p=2, R_s=.2, L_d=4e-3, L_q=17e-3, psi_f=.134)
par = SynchronousMachinePars(n_p=2, R_s=.2, L_d=4e-3, L_q=17e-3, psi_f=.134)
cfg = control.ObserverBasedVHzCtrlCfg(par, max_i_s=2*base.i)
ctrl = control.ObserverBasedVHzCtrl(par, cfg, T_s=250e-6)

Expand Down
12 changes: 8 additions & 4 deletions examples/obs_vhz/plot_obs_vhz_ctrl_syrm_7kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import numpy as np
from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand Down Expand Up @@ -74,18 +75,21 @@ def i_s(psi_s):

# %%
# Configure the system model.
machine = model.SynchronousMachine(n_p=2, R_s=.54, i_s=i_s, psi_s0=0)

mdl_par = SynchronousMachinePars(n_p=2, R_s=.54)
machine = model.SynchronousMachine(mdl_par, i_s=i_s, psi_s0=0)
# Magnetically linear SyRM model for comparison
# machine = model.SynchronousMachine(
# mdl_par = SynchronousMachinePars(
# n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
# machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)

# %%
# Configure the control system.

par = control.ModelPars(n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
par = SynchronousMachinePars(n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
cfg = control.ObserverBasedVHzCtrlCfg(
par, max_i_s=2*base.i, min_psi_s=base.psi, max_psi_s=base.psi)
ctrl = control.ObserverBasedVHzCtrl(par, cfg)
Expand Down
10 changes: 6 additions & 4 deletions examples/signal_inj/plot_signal_inj_pmsm_2kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand All @@ -24,18 +25,19 @@
# %%
# Configure the system model.

machine = model.SynchronousMachine(
mdl_par = SynchronousMachinePars(
n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545)
machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)

# %%
# Configure the control system.

par = control.ModelPars(n_p=3, R_s=3.6, L_d=.036, L_q=.051, psi_f=.545, J=.015)
par = mdl_par # Assume accurate machine model parameter estimates
cfg = control.CurrentReferenceCfg(par, nom_w_m=base.w, max_i_s=2*base.i)
ctrl = control.SignalInjectionCtrl(par, cfg, T_s=250e-6)
ctrl = control.SignalInjectionCtrl(par, cfg, J=.015, T_s=250e-6)
# ctrl.current_ctrl = control.sm.CurrentCtrl(par, 2*np.pi*100)

# %%
Expand Down
11 changes: 6 additions & 5 deletions examples/signal_inj/plot_signal_inj_syrm_7kw.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import BaseValues, NominalValues, plot, Sequence
from motulator.drive.utils import (
BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

# %%
# Compute base values based on the nominal values (just for figures).
Expand All @@ -24,20 +25,20 @@
# %%
# Configure the system model.

machine = model.SynchronousMachine(
mdl_par = SynchronousMachinePars(
n_p=2, R_s=.54, L_d=41.5e-3, L_q=6.2e-3, psi_f=0)
machine = model.SynchronousMachine(mdl_par)
mechanics = model.Mechanics(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)

# %%
# Configure the control system.

par = control.ModelPars(
n_p=2, R_s=.54, L_d=41.5e-3, L_q=6.2e-3, psi_f=0, J=.015)
par = mdl_par # Assume accurate machine model parameter estimates
cfg = control.CurrentReferenceCfg(
par, nom_w_m=base.w, max_i_s=2*base.i, min_psi_s=.5*base.psi)
ctrl = control.SignalInjectionCtrl(par, cfg, T_s=250e-6)
ctrl = control.SignalInjectionCtrl(par, cfg, J=.015, T_s=250e-6)
# ctrl.current_ctrl = control.sm.CurrentCtrl(par, 2*np.pi*100)
# ctrl.signal_inj = control.sm.SignalInjection(par, U_inj=200)

Expand Down
Loading

0 comments on commit dd04fde

Please sign in to comment.