Architecture
Julia simulation project for building and testing induction-machine control structures for AWES ground-station studies.
The project currently contains two modelling/simulation paths:
- ModelingToolkit symbolic models for simple scalar V/f validation.
- Hybrid FOC simulations with a continuous induction-machine plant and discrete controllers/observers, closer to the intended real implementation.
The current focus is the second path: a discrete FOC control structure with speed control, current control, rotor-flux/torque observation, optional load-torque estimation, and AWES profile playback from CSV.
1. Current folder structure
InductionMachineDrives_jl/
├── docs/
│ └── README_InductionMachineDrives_jl.md
├── profiles/
│ └── delta_kite_13_ms_profiles.csv
├── results/
├── scripts/
│ ├── run_foc_current_hybrid_steps.jl
│ ├── run_foc_current_steps.jl
│ ├── run_foc_speed_f1_160kw.jl
│ ├── run_foc_speed_f1_awes_profile.jl
│ ├── run_foc_speed_f1_awes_profile_efficiency.jl
│ ├── run_foc_speed_f1_ramp_load_estimator.jl
│ ├── run_foc_speed_f1_ramp_load_steps.jl
│ ├── run_foc_speed_mtpa_awes_profile.jl
│ ├── run_foc_torque_f1_steps.jl
│ ├── run_scalar_im.jl
│ ├── run_scalar_frequency_steps.jl
│ └── run_scalar_frequency_steps_load_steps.jl
└── src/
├── controls/
│ ├── scalar_vf_control.jl
│ └── FOC/
│ ├── current_controller.jl
│ ├── current_controller_discrete.jl
│ ├── outer_speed_flux_f1_discrete.jl
│ └── outer_torque_flux_f1_discrete.jl
├── estimators/
│ ├── load_torque_kalman_discrete.jl
│ ├── rotor_flux_observer_discrete.jl
│ └── rotor_flux_observer.jl
├── plants/
│ └── induction_machine_alpha_beta.jl
├── profiles/
│ ├── frequency_profiles.jl
│ └── load_profiles.jl
├── simulators/
│ ├── hybrid_foc_current_simulator.jl
│ ├── hybrid_foc_speed_f1_simulator.jl
│ └── hybrid_foc_torque_f1_simulator.jl
├── systems/
│ ├── foc_current_im_system.jl
│ └── scalar_im_system.jl
└── InductionMachineDrives_jl.jl2. Main project entry point
The main module file is:
src/InductionMachineDrives_jl.jlThis file includes all submodules/files and exports the main simulation functions.
Typical include structure:
include("profiles/frequency_profiles.jl")
include("profiles/load_profiles.jl")
include("controls/scalar_vf_control.jl")
include("controls/FOC/current_controller.jl")
include("controls/FOC/current_controller_discrete.jl")
include("controls/FOC/outer_torque_flux_f1_discrete.jl")
include("controls/FOC/outer_speed_flux_f1_discrete.jl")
include("plants/induction_machine_alpha_beta.jl")
include("estimators/rotor_flux_observer.jl")
include("estimators/rotor_flux_observer_discrete.jl")
include("estimators/load_torque_kalman_discrete.jl")
include("systems/scalar_im_system.jl")
include("systems/foc_current_im_system.jl")
include("simulators/hybrid_foc_current_simulator.jl")
include("simulators/hybrid_foc_torque_f1_simulator.jl")
include("simulators/hybrid_foc_speed_f1_simulator.jl")The most relevant exported simulation functions are:
simulate_scalar_im(...) # needs `using ModelingToolkit, OrdinaryDiffEq` (package extension)
simulate_foc_current_hybrid(...)
simulate_foc_torque_f1_hybrid(...)
simulate_foc_speed_f1_hybrid(...)3. Mechanical sign convention
The project now uses the following mechanical equation:
TL + Te = J*dω/dt + B*ωor equivalently:
J*dω/dt = Te + TL - B*ωMeaning:
Te > 0 electromagnetic torque accelerates toward positive speed
TL > 0 external/load torque also pulls toward positive speed
Bω viscous friction opposes motionThis is important for all plant, estimator, and feedforward logic.
For the speed-loop feedforward:
Te_ff = J*dωref/dt + B*ωref - TL_estTherefore, in speed-loop run scripts:
load_ff_sign = -1.0For AWES profile playback:
profile_torque_sign = 1.0should be used if the CSV torque profile already follows the convention:
positive torque_ref_Nm pulls toward positive speedUse:
profile_torque_sign = -1.0only if the CSV torque has the opposite sign convention.
4. Plant model
File
src/plants/induction_machine_alpha_beta.jlThis is the symbolic/MTK induction-machine model in stationary alpha-beta coordinates.
It defines the induction-machine equations:
stator voltage equations
rotor squirrel-cage equations
flux-current relations
electromagnetic torque
mechanical dynamicsThe mechanical equation should use the project convention:
J * D(ωm) ~ Te + Tload_cmd - B * ωmHybrid plant
The hybrid FOC simulations use a hand-written plant derivative function in:
src/simulators/hybrid_foc_current_simulator.jlThe corresponding mechanical derivative should be:
dωm = (Te + Tload - p.B * x.ωm) / p.JThe speed and torque FOC hybrid simulators reuse this plant implementation.
5. Scalar V/f model path
This path is useful for basic plant validation and comparison against Simulink.
Key files
src/controls/scalar_vf_control.jl
src/profiles/frequency_profiles.jl
src/profiles/load_profiles.jl
src/systems/scalar_im_system.jlMain scripts
scripts/run_scalar_frequency_steps.jl
scripts/run_scalar_frequency_steps_load_steps.jl
scripts/run_scalar_im.jlConcept
The scalar system builds a symbolic MTK system:
frequency profile -> scalar V/f control -> alpha-beta induction machine plant
load profile -----------------------------> plant mechanical inputThe scalar V/f controller generates alpha-beta stator voltages directly from a frequency command.
6. Hybrid FOC simulation path
The hybrid FOC path is the preferred architecture for controller development.
It uses:
continuous induction-machine plant
+
discrete observers/controllers
+
fixed-step simulation loopThis is closer to the real implementation, where controllers run at a fixed sampling time.
Core idea
At every sample time:
1. Read plant currents and mechanical speed/angle
2. Update rotor-flux/torque observer
3. Optionally update load-torque estimator
4. Update outer loop, if present
5. Update inner current controller
6. Convert dq voltage command to alpha-beta
7. Integrate the plant over one sample period
8. Store results7. Discrete inner current controller
File
src/controls/FOC/current_controller_discrete.jlPurpose
This is the discrete FOC current controller. It receives:
isd_ref, isq_ref
isd_meas, isq_meas
omega_e
lambda_rdand outputs:
vsd, vsqIt includes:
current reference limiting
optional measurement filtering
PI control
optional feedforward decoupling
optional voltage saturation
optional anti-windupMain types/functions
CurrentControllerDiscreteState
CurrentControllerDiscreteParams
CurrentControllerDiscreteOutput
current_controller_step!(...)8. Rotor-flux and torque observer
File
src/estimators/rotor_flux_observer_discrete.jlPurpose
This observer estimates rotor flux and torque from measured alpha-beta currents and mechanical rotor angle.
It outputs:
lambda_rd_e
lambda_rq_e
theta_e
i_sd_e
i_sq_e
Te_raw
omega_eThe current controller uses the observer outputs as its synchronous-frame measurements.
Main types/functions
RotorFluxObserverDiscreteState
RotorFluxObserverDiscreteParams
RotorFluxObserverDiscreteOutput
rotor_flux_observer_step!(...)9. Load-torque Kalman estimator
File
src/estimators/load_torque_kalman_discrete.jlPurpose
This estimator estimates the external torque TL from speed and electromagnetic torque.
It is based on the mechanical model:
J*dω/dt = Te + TL - B*ωDiscrete model:
ω[k+1] = (1 - B*Ts/J)*ω[k] + (Ts/J)*TL[k] + (Ts/J)*Te[k]
TL[k+1] = TL[k]Therefore, the estimator should use:
A12 = Ts / Jnot -Ts/J.
Main types/functions
LoadTorqueKalmanState
LoadTorqueKalmanParams
LoadTorqueKalmanOutput
load_torque_kalman_step!(...)For AWES profiles, where torque may be signed, it is usually safer to use:
TL_kalman_limit_positive = false10. Outer torque loop, F1 constant flux
File
src/controls/FOC/outer_torque_flux_f1_discrete.jlPurpose
Simplified outer-loop case equivalent to:
mode_control = 1 torque control
mode_torque = 1 simple torque-to-iq conversion
mode_flux = 1 constant id referenceIt converts:
Te_ref -> isd_ref, isq_refwith:
isd_ref = isd_nom
isq_ref = Te_ref / Kt_nomand current-circle limitation.
Used by
src/simulators/hybrid_foc_torque_f1_simulator.jl
scripts/run_foc_torque_f1_steps.jl11. Outer speed loop, F1 constant flux
File
src/controls/FOC/outer_speed_flux_f1_discrete.jlPurpose
Simplified speed-loop case equivalent to:
mode_control = 2 speed control
mode_torque = 1 simple torque-to-iq conversion
mode_flux = 1 constant id referenceIt converts:
speed_ref -> Te_ref -> isd_ref, isq_refusing a discrete speed PI and optional load-torque feedforward.
With the current mechanical convention:
J*dω/dt = Te + TL - B*ωload feedforward should use:
load_ff_sign = -1.0so that:
Te_ff = J*dωref/dt + B*ωref - TL_estUsed by
src/simulators/hybrid_foc_speed_f1_simulator.jl
scripts/run_foc_speed_f1_ramp_load_steps.jl
scripts/run_foc_speed_f1_ramp_load_estimator.jl
scripts/run_foc_speed_f1_awes_profile.jl12. Hybrid current-loop simulator
File
src/simulators/hybrid_foc_current_simulator.jlPurpose
Tests only the inner current controller:
isd_ref, isq_ref -> current controller -> voltage command -> plantIt is useful for debugging current tracking before adding torque or speed outer loops.
Main script
scripts/run_foc_current_hybrid_steps.jlTypical reference sequence
0–1 s id = 0 A, iq = 0 A
1–3 s id = 5 A, iq = 0 A
3–6 s id = 5 A, iq = 5 A
6–9 s id = 5 A, iq = -5 A
9–12 s id = 5 A, iq = 0 A13. Hybrid torque-loop simulator
File
src/simulators/hybrid_foc_torque_f1_simulator.jlPurpose
Tests the torque outer loop plus inner current loop:
Te_ref -> outer torque F1 -> isd_ref, isq_ref -> current controller -> plantMain script
scripts/run_foc_torque_f1_steps.jlTypical reference sequence
0–2 s Te_ref = 0 Nm
2–6 s Te_ref = +20 Nm
6–10 s Te_ref = -20 Nm
10–12 s Te_ref = 0 Nm14. Hybrid speed-loop simulator
File
src/simulators/hybrid_foc_speed_f1_simulator.jlPurpose
Tests speed outer-loop FOC with constant-flux F1 mode:
speed_ref -> speed PI -> Te_ref -> isd_ref, isq_ref -> current controller -> plantIt supports:
internal ramp speed references
internal load-step profiles
external CSV speed/load profiles
optional load-torque Kalman estimator
optional load-torque feedforward
abc reconstruction
electrical/mechanical power calculationMain scripts
scripts/run_foc_speed_f1_ramp_load_steps.jl
scripts/run_foc_speed_f1_ramp_load_estimator.jl
scripts/run_foc_speed_f1_awes_profile.jl15. AWES CSV profile playback
Input file
profiles/delta_kite_13_ms_profiles.csvExpected columns:
t_s
speed_ref_rpm
speed_ref_rad_s
torque_ref_NmThe current AWES run script uses:
speed_ref_rpm -> speed reference profile
torque_ref_Nm -> external torque profileThe simulator linearly interpolates between profile points at each simulation time, similar to Simulink timeseries behavior.
Main script
scripts/run_foc_speed_f1_awes_profile.jlImportant settings
speed_reference_source = :profile
load_source = :profile
profile_torque_sign = 1.0
wm_dot_max = 1e6
load_estimator = :kalman
use_load_feedforward = true
load_ff_sign = -1.0
TL_kalman_limit_positive = falsewm_dot_max = 1e6 effectively disables internal speed-reference ramp limiting, so the speed reference used by the PI follows the CSV profile closely.
16. Power and abc current reconstruction
The hybrid speed simulator reconstructs abc quantities from alpha-beta quantities assuming zero-sequence is zero:
ia = isα
ib = -0.5 * isα + sqrt(3)/2 * isβ
ic = -0.5 * isα - sqrt(3)/2 * isβ
va = vsα
vb = -0.5 * vsα + sqrt(3)/2 * vsβ
vc = -0.5 * vsα - sqrt(3)/2 * vsβInstantaneous stator electrical power:
Pelec = va*ia + vb*ib + vc*icMechanical electromagnetic power:
Pmech = Te * ωmExternal torque power:
Pload = TL * ωmFriction loss:
Pfric = B * ωm^2With the current sign convention:
Pload > 0 external torque injects mechanical power into the shaft
Pload < 0 external torque extracts mechanical power from the shaft17. Running simulations
The dedicated 160 kW induction-machine FOC F1 test is described in the 160 kW FOC F1 case.
From the project root, start Julia:
jlThen run simulations from the Julia prompt with include():
include("scripts/run_scalar_im.jl")
include("scripts/run_foc_current_hybrid_steps.jl")
include("scripts/run_foc_torque_f1_steps.jl")
include("scripts/run_foc_speed_f1_ramp_load_steps.jl")
include("scripts/run_foc_speed_f1_ramp_load_estimator.jl")
include("scripts/run_foc_speed_f1_awes_profile.jl")
include("scripts/run_foc_speed_f1_160kw.jl")For the AWES profile case:
include("scripts/run_foc_speed_f1_awes_profile.jl")The result CSV is saved in:
results/foc_speed_f1_awes_profile.csv18. Output results
Simulation outputs are saved in:
results/The AWES profile script saves:
results/foc_speed_f1_awes_profile.csvThis CSV includes:
speed reference and measured speed
torque reference, plant torque, observed torque, AWES torque, estimated load torque
dq currents
alpha-beta currents and voltages
reconstructed abc currents and voltages
electrical/mechanical/load/friction power
rotor flux and angle
saturation/debug signals19. Recommended validation workflow
Step 1: Validate current loop
include("scripts/run_foc_current_hybrid_steps.jl")Check:
id tracking
iq tracking
positive iq gives positive torque
negative iq gives negative torqueStep 2: Validate torque loop
include("scripts/run_foc_torque_f1_steps.jl")Check:
Te_ref -> iq_ref conversion
torque response
speed acceleration/decelerationStep 3: Validate speed loop without load estimator
load_estimator = :none
use_load_feedforward = falseStep 4: Validate load estimator only
load_estimator = :kalman
use_load_feedforward = falseCheck whether TL_est tracks Tload.
Step 5: Validate load feedforward
load_estimator = :kalman
use_load_feedforward = true
load_ff_sign = -1.0Check whether speed error improves when the load torque changes.
Step 6: Run AWES profile
include("scripts/run_foc_speed_f1_awes_profile.jl")Check:
speed profile tracking
AWES torque sign
estimated load torque
abc currents
Pelec, Pmech, Pload20. Common issues
Wrong load-torque sign
If enabling load feedforward makes the speed tracking worse, check:
load_ff_sign = -1.0
profile_torque_sign = 1.0and verify the mechanical convention:
J*dω/dt = Te + TL - BωAWES profile does not match input
Check:
speed_reference_source = :profile
load_source = :profile
wm_dot_max = 1e6Remember:
res.wm_ref = raw CSV speed reference after interpolation
res.wm_ref_ramp = ramp-limited reference used internally by the speed PILoad estimator cannot estimate negative torque
Set:
TL_kalman_limit_positive = false21. Current development status
Implemented:
scalar V/f MTK system
alpha-beta induction-machine plant
hybrid FOC current-loop simulation
discrete current controller
discrete rotor-flux/torque observer
discrete load-torque Kalman estimator
outer torque loop, T1 + F1
outer speed loop, T1 + F1
AWES speed/torque profile playback from CSV
abc current/voltage reconstruction
stator electrical power and mechanical power calculationNot yet implemented:
advanced FOC modes from the full MATLAB controller
MTPA / loss minimization modes
field-weakening
full voltage/current constraint management beyond the current controller level
higher-level AWES cycle energy metrics
comparison automation across controller options
parameter sweep / robustness batch scripts