LIBRARY
Examples.CartPoleMPCExample
Cart-pole regulation with ACADOSMPC: from the cart at position 3 with the pendulum horizontal (θ = π/2), bring the cart to the origin with the pendulum hanging at rest, with the force bounded to ±5. Translated from the DyadControlSystems quadratic-MPC tutorial (Ts = 0.02, N = 15, Q1 = I, Q2 = Ts). The terminal weight is the LQR cost of the linearized model (terminal_lqr_cost = true), which the tutorial's QMPCProblem adds implicitly; without it the 0.3 s horizon is myopic and the loop oscillates. Verified in test/test_acados_tutorials.jl.
Usage
MPCComponents.Examples.CartPoleMPCExample(k=0)
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
Np | Prediction horizon (number of shooting intervals) | – | 15 |
terminal_lqr_cost | Use the infinite-horizon LQR cost of the model linearized at the origin as terminal weight (on the full state) instead of Qf; requires reference_tracking = false. In Julia the weight follows Q1 and Q2; in exported C it stays at its export-time value | – | !reference_tracking |
reference_tracking | Track references (adds the r input); false regulates to the origin | – | false |
Q1 | Output weight on C*x - r (ny × ny, e.g. diagonal([1.0, 10.0])); tunable. Default: the identity, or the weight the mpc object was built with | – | diagonal([1... 1.0, 1.0]) |
k | The constant value to output | – | 0 |
Variables
| Name | Description | Units |
|---|---|---|
pos | Cart position | – |
theta | Pendulum angle | – |
u1 | Force | – |
flag | acados status | – |
Behavior
Behavior of this component cannot be rendered because it includes path variables.
Source
dyad
"""
Cart-pole regulation with `ACADOSMPC`: from the cart at position 3 with the pendulum horizontal
(θ = π/2), bring the cart to the origin with the pendulum hanging at rest, with the force bounded to
±5. Translated from the DyadControlSystems quadratic-MPC tutorial (Ts = 0.02, N = 15, Q1 = I,
Q2 = Ts). The terminal weight is the LQR cost of the linearized model (`terminal_lqr_cost = true`),
which the tutorial's `QMPCProblem` adds implicitly; without it the 0.3 s horizon is myopic and the loop
oscillates. Verified in `test/test_acados_tutorials.jl`.
"""
example component CartPoleMPCExample
periodicclock = DiscreteComponents.PeriodicClock(dt = 0.02) {
"Dyad": {"placement": {"diagram": {"x1": 465, "x2": 565, "y1": 43, "y2": 143}}}
}
plant = MPCComponents.Examples.CartPolePlant(p0 = 3.0, th0 = 1.5707963267948966) {
"Dyad": {"placement": {"diagram": {"x1": 40, "x2": 140, "y1": 140, "y2": 240}}}
}
"Samplers of the four state variables"
s = [DiscreteComponents.Sampler() for i in 1:4] {
"Dyad": {"placement": {"diagram": {"x1": 194, "x2": 294, "y1": 140, "y2": 240}}}
}
zoh = DiscreteComponents.ZeroOrderHold() {
"Dyad": {"placement": {"diagram": {"x1": 464, "x2": 564, "y1": 163, "y2": 263}}}
}
mpc = MPCComponents.ACADOSMPC(dynamics = plant, inputs = ["F"], state_variables = ["p", "th", "v", "w"], outputs = ["p", "th", "v", "w"], Ts = 0.02, Np = Np, Q1 = Q1, Q2 = diagonal([0.02]), terminal_lqr_cost = terminal_lqr_cost, umin = [-5.0], umax = [5.0], reference_tracking = reference_tracking, levenberg_marquardt = 1.0, nlp_solver = MPCComponents.ACADOSSolver.SQP_RTI()) {
"Dyad": {"placement": {"diagram": {"x1": 330, "x2": 430, "y1": 140, "y2": 240}}}
}
angle_ref = BlockComponents.Sources.Constant(k = k) if reference_tracking {"Dyad": {"placement": {"diagram": {"x1": 40, "x2": 140, "y1": -90, "y2": 10}}}}
"Cart position"
variable pos::Real
"Pendulum angle"
variable theta::Real
"Force"
variable u1::Real
"acados status"
variable flag::Real
"The constant value to output"
parameter k::Real = 0
"Prediction horizon (number of shooting intervals)"
structural parameter Np::Integer = 15
"Use the infinite-horizon LQR cost of the model linearized at the origin as terminal weight (on the full state) instead of Qf; requires reference_tracking = false. In Julia the weight follows Q1 and Q2; in exported C it stays at its export-time value"
structural parameter terminal_lqr_cost::Boolean = !reference_tracking
"Track references (adds the r input); false regulates to the origin"
structural parameter reference_tracking::Boolean = false
"Output weight on C*x - r (ny × ny, e.g. diagonal([1.0, 10.0])); tunable. Default: the identity, or the weight the mpc object was built with"
structural parameter Q1::Real[4, 4] = diagonal([1.0, 1.0, 1.0, 1.0])
relations
pos = plant.pos
theta = plant.theta
u1 = mpc.u[1]
flag = mpc.exitflag
connect(plant.pos, s[1].u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 170, "y": 155}, {"x": 170, "y": 190}], "E": 2}],
"path": {}
}
}
connect(plant.theta, s[2].u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 170, "y": 178}, {"x": 170, "y": 190}], "E": 2}],
"path": {}
}
}
connect(plant.vel, s[3].u) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 145, "y": 190}], "E": 2}], "path": {}}}
connect(plant.omega, s[4].u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 170, "y": 228}, {"x": 170, "y": 190}], "E": 2}],
"path": {}
}
}
connect(s[1].y, mpc.x[1], periodicclock.y) {
"Dyad": {
"edges": [
{"S": 1, "M": [], "E": 2},
{"S": 2, "M": [{"x": 310, "y": 190}, {"x": 310, "y": 93}], "E": 3}
],
"path": {}
}
}
for i in 2:4
connect(s[i].y, mpc.x[i])
end
connect(mpc.u[1], zoh.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "path": {}}}
connect(zoh.y, plant.F) {
"Dyad": {
"edges": [
{
"S": 1,
"M": [
{"x": 580, "y": 213},
{"x": 580, "y": 300},
{"x": 20, "y": 300},
{"x": 20, "y": 190}
],
"E": 2
}
],
"path": {}
}
}
if reference_tracking
connect(angle_ref.y, mpc.r[2]) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 320, "y": -40}, {"x": 320, "y": 155}], "E": 2}],
"path": {}
}
}
mpc.r[1] = 0
mpc.r[3] = 0
mpc.r[4] = 0
end
metadata {"Dyad": {"doc": {"behavior": false}}}
endFlattened Source
dyad
"""
Cart-pole regulation with `ACADOSMPC`: from the cart at position 3 with the pendulum horizontal
(θ = π/2), bring the cart to the origin with the pendulum hanging at rest, with the force bounded to
±5. Translated from the DyadControlSystems quadratic-MPC tutorial (Ts = 0.02, N = 15, Q1 = I,
Q2 = Ts). The terminal weight is the LQR cost of the linearized model (`terminal_lqr_cost = true`),
which the tutorial's `QMPCProblem` adds implicitly; without it the 0.3 s horizon is myopic and the loop
oscillates. Verified in `test/test_acados_tutorials.jl`.
"""
example component CartPoleMPCExample
periodicclock = DiscreteComponents.PeriodicClock(dt = 0.02) {
"Dyad": {"placement": {"diagram": {"x1": 465, "x2": 565, "y1": 43, "y2": 143}}}
}
plant = MPCComponents.Examples.CartPolePlant(p0 = 3.0, th0 = 1.5707963267948966) {
"Dyad": {"placement": {"diagram": {"x1": 40, "x2": 140, "y1": 140, "y2": 240}}}
}
"Samplers of the four state variables"
s = [DiscreteComponents.Sampler() for i in 1:4] {
"Dyad": {"placement": {"diagram": {"x1": 194, "x2": 294, "y1": 140, "y2": 240}}}
}
zoh = DiscreteComponents.ZeroOrderHold() {
"Dyad": {"placement": {"diagram": {"x1": 464, "x2": 564, "y1": 163, "y2": 263}}}
}
mpc = MPCComponents.ACADOSMPC(dynamics = plant, inputs = ["F"], state_variables = ["p", "th", "v", "w"], outputs = ["p", "th", "v", "w"], Ts = 0.02, Np = Np, Q1 = Q1, Q2 = diagonal([0.02]), terminal_lqr_cost = terminal_lqr_cost, umin = [-5.0], umax = [5.0], reference_tracking = reference_tracking, levenberg_marquardt = 1.0, nlp_solver = MPCComponents.ACADOSSolver.SQP_RTI()) {
"Dyad": {"placement": {"diagram": {"x1": 330, "x2": 430, "y1": 140, "y2": 240}}}
}
angle_ref = BlockComponents.Sources.Constant(k = k) if reference_tracking {"Dyad": {"placement": {"diagram": {"x1": 40, "x2": 140, "y1": -90, "y2": 10}}}}
"Cart position"
variable pos::Real
"Pendulum angle"
variable theta::Real
"Force"
variable u1::Real
"acados status"
variable flag::Real
"The constant value to output"
parameter k::Real = 0
"Prediction horizon (number of shooting intervals)"
structural parameter Np::Integer = 15
"Use the infinite-horizon LQR cost of the model linearized at the origin as terminal weight (on the full state) instead of Qf; requires reference_tracking = false. In Julia the weight follows Q1 and Q2; in exported C it stays at its export-time value"
structural parameter terminal_lqr_cost::Boolean = !reference_tracking
"Track references (adds the r input); false regulates to the origin"
structural parameter reference_tracking::Boolean = false
"Output weight on C*x - r (ny × ny, e.g. diagonal([1.0, 10.0])); tunable. Default: the identity, or the weight the mpc object was built with"
structural parameter Q1::Real[4, 4] = diagonal([1.0, 1.0, 1.0, 1.0])
relations
pos = plant.pos
theta = plant.theta
u1 = mpc.u[1]
flag = mpc.exitflag
connect(plant.pos, s[1].u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 170, "y": 155}, {"x": 170, "y": 190}], "E": 2}],
"path": {}
}
}
connect(plant.theta, s[2].u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 170, "y": 178}, {"x": 170, "y": 190}], "E": 2}],
"path": {}
}
}
connect(plant.vel, s[3].u) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 145, "y": 190}], "E": 2}], "path": {}}}
connect(plant.omega, s[4].u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 170, "y": 228}, {"x": 170, "y": 190}], "E": 2}],
"path": {}
}
}
connect(s[1].y, mpc.x[1], periodicclock.y) {
"Dyad": {
"edges": [
{"S": 1, "M": [], "E": 2},
{"S": 2, "M": [{"x": 310, "y": 190}, {"x": 310, "y": 93}], "E": 3}
],
"path": {}
}
}
for i in 2:4
connect(s[i].y, mpc.x[i])
end
connect(mpc.u[1], zoh.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "path": {}}}
connect(zoh.y, plant.F) {
"Dyad": {
"edges": [
{
"S": 1,
"M": [
{"x": 580, "y": 213},
{"x": 580, "y": 300},
{"x": 20, "y": 300},
{"x": 20, "y": 190}
],
"E": 2
}
],
"path": {}
}
}
if reference_tracking
connect(angle_ref.y, mpc.r[2]) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 320, "y": -40}, {"x": 320, "y": 155}], "E": 2}],
"path": {}
}
}
mpc.r[1] = 0
mpc.r[3] = 0
mpc.r[4] = 0
end
metadata {"Dyad": {"doc": {"behavior": false}}}
endTest Cases
No test cases defined.
Related
Examples
Experiments
Analyses