Examples.SaturatedLQRvsMPCExample ​
Comparison of a saturated LQR controller with an MPC controller on the double integrator DoubleIntegratorPlant, both regulating the position from -2 to the origin with the full state measured. The force is limited to umax.
The first loop uses an unconstrained LinearMPCController with the LQR cost-to-go as terminal cost, which coincides with the LQR controller, followed by a Limiter at the plant input. The controller is unaware of the saturation. The second loop uses the same weights, with the force bound and the velocity bound vmax given to the controller as constraints.
Verified in test/test_mpc.jl.
Usage ​
MPCComponents.Examples.SaturatedLQRvsMPCExample()
Parameters: ​
| Name | Description | Units | Default value |
|---|---|---|---|
umax | Force bound | – | 1.0 |
vmax | Velocity bound of the MPC controller | – | 0.8 |
Variables ​
| Name | Description | Units |
|---|---|---|
x_lqr | Position with the saturated LQR controller | – |
v_lqr | Velocity with the saturated LQR controller | – |
u_lqr | Force with the saturated LQR controller (after the limiter) | – |
x_mpc | Position with the MPC controller | – |
v_mpc | Velocity with the MPC controller | – |
u_mpc | Force with the MPC controller | – |
Behavior ​
Behavior of this component cannot be rendered because it includes path variables.
Source ​
"""
Comparison of a saturated LQR controller with an MPC controller on the double integrator
`DoubleIntegratorPlant`, both regulating the position from -2 to the origin with the full state
measured. The force is limited to ``|u| \\le`` `umax`.
The first loop uses an unconstrained `LinearMPCController` with the LQR cost-to-go as terminal cost,
which coincides with the LQR controller, followed by a `Limiter` at the plant input. The controller is
unaware of the saturation. The second loop uses the same weights, with the force bound and the velocity
bound ``|v| \\le`` `vmax` given to the controller as constraints.
Verified in `test/test_mpc.jl`.
"""
example component SaturatedLQRvsMPCExample
"Force bound"
structural parameter umax::Real = 1.0
"Velocity bound of the MPC controller"
structural parameter vmax::Real = 0.8
clock_lqr = DiscreteComponents.PeriodicClock(dt = 0.1) {}
clock_mpc = DiscreteComponents.PeriodicClock(dt = 0.1) {}
plant_lqr = MPCComponents.Examples.DoubleIntegratorPlant(x0 = -2.0) {}
plant_mpc = MPCComponents.Examples.DoubleIntegratorPlant(x0 = -2.0) {}
sx_lqr = DiscreteComponents.Sampler() {}
sv_lqr = DiscreteComponents.Sampler() {}
sx_mpc = DiscreteComponents.Sampler() {}
sv_mpc = DiscreteComponents.Sampler() {}
zoh_lqr = DiscreteComponents.ZeroOrderHold() {}
zoh_mpc = DiscreteComponents.ZeroOrderHold() {}
saturation = BlockComponents.Nonlinear.Limiter(final y_max = umax) {}
lqr = MPCComponents.LinearMPCController(dynamics = plant_lqr, inputs = ["u"], outputs = ["position", "velocity"], state_variables = ["x", "v"], Ts = 0.1, Np = 50, Q1 = [1.0, 0.0], Q2 = [0.01], reference_tracking = false, terminal_lqr_cost = true, R1 = [1.0, 1.0], R2 = [1e-6, 1e-6]) {}
mpc = MPCComponents.LinearMPCController(dynamics = plant_mpc, inputs = ["u"], outputs = ["position", "velocity"], state_variables = ["x", "v"], Ts = 0.1, Np = 50, Q1 = [1.0, 0.0], Q2 = [0.01], reference_tracking = false, terminal_lqr_cost = true, umin = [-umax], umax = [umax], ymin = [-1e3, -vmax], ymax = [1e3, vmax], R1 = [1.0, 1.0], R2 = [1e-6, 1e-6]) {}
"Position with the saturated LQR controller"
variable x_lqr::Real
"Velocity with the saturated LQR controller"
variable v_lqr::Real
"Force with the saturated LQR controller (after the limiter)"
variable u_lqr::Real
"Position with the MPC controller"
variable x_mpc::Real
"Velocity with the MPC controller"
variable v_mpc::Real
"Force with the MPC controller"
variable u_mpc::Real
relations
x_lqr = plant_lqr.position
v_lqr = plant_lqr.velocity
u_lqr = saturation.y
x_mpc = plant_mpc.position
v_mpc = plant_mpc.velocity
u_mpc = zoh_mpc.y
connect(plant_lqr.position, sx_lqr.u)
connect(plant_lqr.velocity, sv_lqr.u)
connect(sx_lqr.y, lqr.y[1], clock_lqr.y)
connect(sv_lqr.y, lqr.y[2])
connect(lqr.u[1], zoh_lqr.u)
connect(zoh_lqr.y, saturation.u)
connect(saturation.y, plant_lqr.u)
connect(plant_mpc.position, sx_mpc.u)
connect(plant_mpc.velocity, sv_mpc.u)
connect(sx_mpc.y, mpc.y[1], clock_mpc.y)
connect(sv_mpc.y, mpc.y[2])
connect(mpc.u[1], zoh_mpc.u)
connect(zoh_mpc.y, plant_mpc.u)
metadata {"Dyad": {"tests": {"case1": {"stop": 10}}, "doc": {"behavior": false}}}
endFlattened Source
"""
Comparison of a saturated LQR controller with an MPC controller on the double integrator
`DoubleIntegratorPlant`, both regulating the position from -2 to the origin with the full state
measured. The force is limited to ``|u| \\le`` `umax`.
The first loop uses an unconstrained `LinearMPCController` with the LQR cost-to-go as terminal cost,
which coincides with the LQR controller, followed by a `Limiter` at the plant input. The controller is
unaware of the saturation. The second loop uses the same weights, with the force bound and the velocity
bound ``|v| \\le`` `vmax` given to the controller as constraints.
Verified in `test/test_mpc.jl`.
"""
example component SaturatedLQRvsMPCExample
"Force bound"
structural parameter umax::Real = 1.0
"Velocity bound of the MPC controller"
structural parameter vmax::Real = 0.8
clock_lqr = DiscreteComponents.PeriodicClock(dt = 0.1) {}
clock_mpc = DiscreteComponents.PeriodicClock(dt = 0.1) {}
plant_lqr = MPCComponents.Examples.DoubleIntegratorPlant(x0 = -2.0) {}
plant_mpc = MPCComponents.Examples.DoubleIntegratorPlant(x0 = -2.0) {}
sx_lqr = DiscreteComponents.Sampler() {}
sv_lqr = DiscreteComponents.Sampler() {}
sx_mpc = DiscreteComponents.Sampler() {}
sv_mpc = DiscreteComponents.Sampler() {}
zoh_lqr = DiscreteComponents.ZeroOrderHold() {}
zoh_mpc = DiscreteComponents.ZeroOrderHold() {}
saturation = BlockComponents.Nonlinear.Limiter(final y_max = umax) {}
lqr = MPCComponents.LinearMPCController(dynamics = plant_lqr, inputs = ["u"], outputs = ["position", "velocity"], state_variables = ["x", "v"], Ts = 0.1, Np = 50, Q1 = [1.0, 0.0], Q2 = [0.01], reference_tracking = false, terminal_lqr_cost = true, R1 = [1.0, 1.0], R2 = [1e-6, 1e-6]) {}
mpc = MPCComponents.LinearMPCController(dynamics = plant_mpc, inputs = ["u"], outputs = ["position", "velocity"], state_variables = ["x", "v"], Ts = 0.1, Np = 50, Q1 = [1.0, 0.0], Q2 = [0.01], reference_tracking = false, terminal_lqr_cost = true, umin = [-umax], umax = [umax], ymin = [-1e3, -vmax], ymax = [1e3, vmax], R1 = [1.0, 1.0], R2 = [1e-6, 1e-6]) {}
"Position with the saturated LQR controller"
variable x_lqr::Real
"Velocity with the saturated LQR controller"
variable v_lqr::Real
"Force with the saturated LQR controller (after the limiter)"
variable u_lqr::Real
"Position with the MPC controller"
variable x_mpc::Real
"Velocity with the MPC controller"
variable v_mpc::Real
"Force with the MPC controller"
variable u_mpc::Real
relations
x_lqr = plant_lqr.position
v_lqr = plant_lqr.velocity
u_lqr = saturation.y
x_mpc = plant_mpc.position
v_mpc = plant_mpc.velocity
u_mpc = zoh_mpc.y
connect(plant_lqr.position, sx_lqr.u)
connect(plant_lqr.velocity, sv_lqr.u)
connect(sx_lqr.y, lqr.y[1], clock_lqr.y)
connect(sv_lqr.y, lqr.y[2])
connect(lqr.u[1], zoh_lqr.u)
connect(zoh_lqr.y, saturation.u)
connect(saturation.y, plant_lqr.u)
connect(plant_mpc.position, sx_mpc.u)
connect(plant_mpc.velocity, sv_mpc.u)
connect(sx_mpc.y, mpc.y[1], clock_mpc.y)
connect(sv_mpc.y, mpc.y[2])
connect(mpc.u[1], zoh_mpc.u)
connect(zoh_mpc.y, plant_mpc.u)
metadata {"Dyad": {"tests": {"case1": {"stop": 10}}, "doc": {"behavior": false}}}
endTest Cases ​
Test Case case1 ​
Related ​
Examples
Experiments
Analyses