Skip to content
LIBRARY
Examples.CartPoleMPCExample.md

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: ​

NameDescriptionUnitsDefault value
NpPrediction horizon (number of shooting intervals)–15
terminal_lqr_costUse 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_trackingTrack references (adds the r input); false regulates to the origin–false
Q1Output 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])
kThe constant value to output–0

Variables ​

NameDescriptionUnits
posCart position–
thetaPendulum angle–
u1Force–
flagacados 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}}}
end
Flattened 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}}}
end


Test Cases ​

No test cases defined.

  • Examples

  • Experiments

  • Analyses