Skip to content
LIBRARY
examples.Cartpole.md

examples.Cartpole

Inverted pendulum on a cart.

The cart moves along the world x-axis by means of a prismatic joint and is driven by a force actuator. The pendulum is a cylinder attached to the cart through a revolute joint, with an additional point mass at the tip. The pendulum angle phi is zero when the pendulum points straight up.

The force input u drives the cart, and the variables x, v, phi, w expose the cart position and velocity as well as the pendulum angle and angular velocity.

Usage

MultibodyComponents.examples.Cartpole()

Connectors

  • u - This connector represents a real signal as an input to a component (RealInput)

Variables

NameDescriptionUnits
xCart positionm
vCart velocitym/s
phiPendulum angle, zero when the pendulum points uprad
wPendulum angular velocityrad/s

Behavior

julia
using MultibodyComponents #hide
using ModelingToolkit #hide
@named sys = MultibodyComponents.examples.Cartpole() #hide
let eqs = full_equations(sys); Base.length(eqs) > 25 ? nothing : eqs end #hide
<< @example-block not executed in draft mode >>

Source

dyad
"""
Inverted pendulum on a cart.

The cart moves along the world x-axis by means of a prismatic joint and is
driven by a force actuator. The pendulum is a cylinder attached to the cart
through a revolute joint, with an additional point mass at the tip. The
pendulum angle `phi` is zero when the pendulum points straight up.

The force input `u` drives the cart, and the variables `x`, `v`, `phi`, `w`
expose the cart position and velocity as well as the pendulum angle and
angular velocity.
"""
component Cartpole
  "Force driving the cart along the prismatic axis"
  u = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -100, "x2": 0, "y1": 450, "y2": 550}}}
  }
  fixed = MultibodyComponents.Fixed() {
    "Dyad": {"placement": {"diagram": {"x1": 200, "x2": 300, "y1": 230, "y2": 330}}}
  }
  cart = MultibodyComponents.BodyShape(m = 1, r = [0.2, 0, 0], shape = "box", width = 0.1, height = 0.1, color = [0.2, 0.2, 0.2, 1]) {
    "Dyad": {"placement": {"diagram": {"x1": 400, "x2": 500, "y1": 230, "y2": 330}}}
  }
  mounting_point = MultibodyComponents.FixedTranslation(r = [0.1, 0, 0]) {
    "Dyad": {"placement": {"diagram": {"x1": 390, "x2": 490, "y1": 300, "y2": 400}}}
  }
  prismatic = MultibodyComponents.Prismatic(n = [1, 0, 0], statePriority = 100, color = [0.5, 0.5, 0.5, 1]) {
    "Dyad": {"placement": {"diagram": {"x1": 270, "x2": 370, "y1": 230, "y2": 330}}}
  }
  revolute = MultibodyComponents.Revolute(n = [0, 0, 1], statePriority = 100) {
    "Dyad": {"placement": {"diagram": {"x1": 510, "x2": 610, "y1": 300, "y2": 400}}}
  }
  pendulum = MultibodyComponents.BodyCylinder(r = [0, 0.5, 0], diameter = 0.015, color = [0.5, 0.5, 0.5, 1]) {
    "Dyad": {"placement": {"diagram": {"x1": 630, "x2": 730, "y1": 300, "y2": 400}}}
  }
  motor = TranslationalComponents.Sources.Force() {
    "Dyad": {"placement": {"diagram": {"x1": 270, "x2": 170, "y1": 480, "y2": 380}}}
  }
  tip = MultibodyComponents.Body(m = 0.05) {
    "Dyad": {"placement": {"diagram": {"x1": 740, "x2": 840, "y1": 300, "y2": 400}}}
  }
  "Cart position"
  variable x::Length
  "Cart velocity"
  variable v::Velocity
  "Pendulum angle, zero when the pendulum points up"
  variable phi::Angle
  "Pendulum angular velocity"
  variable w::AngularVelocity
relations
  connect(fixed.frame_b, prismatic.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(prismatic.frame_b, cart.frame_a, mounting_point.frame_a) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [], "E": 2},
        {"S": -1, "M": [{"x": 390, "y": 350}], "E": 3}
      ],
      "junctions": [{"x": 390, "y": 280}]
    }
  }
  connect(mounting_point.frame_b, revolute.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(revolute.frame_b, pendulum.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(pendulum.frame_b, tip.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(motor.flange_a, prismatic.support) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 320, "y": 430}], "E": 2}]}}
  connect(motor.flange_b, prismatic.axis) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 130, "y": 430}, {"x": 130, "y": 230}], "E": 2}]}
  }
  connect(u, motor.f) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 220, "y": 500}], "E": 2}]}}
  x = prismatic.s
  v = prismatic.v
  phi = revolute.phi
  w = revolute.w
metadata {"Dyad": {"labels": [{"label": "$(instance)", "x": 500, "y": 1100, "rot": 0}]}}
end
Flattened Source
dyad
"""
Inverted pendulum on a cart.

The cart moves along the world x-axis by means of a prismatic joint and is
driven by a force actuator. The pendulum is a cylinder attached to the cart
through a revolute joint, with an additional point mass at the tip. The
pendulum angle `phi` is zero when the pendulum points straight up.

The force input `u` drives the cart, and the variables `x`, `v`, `phi`, `w`
expose the cart position and velocity as well as the pendulum angle and
angular velocity.
"""
component Cartpole
  "Force driving the cart along the prismatic axis"
  u = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -100, "x2": 0, "y1": 450, "y2": 550}}}
  }
  fixed = MultibodyComponents.Fixed() {
    "Dyad": {"placement": {"diagram": {"x1": 200, "x2": 300, "y1": 230, "y2": 330}}}
  }
  cart = MultibodyComponents.BodyShape(m = 1, r = [0.2, 0, 0], shape = "box", width = 0.1, height = 0.1, color = [0.2, 0.2, 0.2, 1]) {
    "Dyad": {"placement": {"diagram": {"x1": 400, "x2": 500, "y1": 230, "y2": 330}}}
  }
  mounting_point = MultibodyComponents.FixedTranslation(r = [0.1, 0, 0]) {
    "Dyad": {"placement": {"diagram": {"x1": 390, "x2": 490, "y1": 300, "y2": 400}}}
  }
  prismatic = MultibodyComponents.Prismatic(n = [1, 0, 0], statePriority = 100, color = [0.5, 0.5, 0.5, 1]) {
    "Dyad": {"placement": {"diagram": {"x1": 270, "x2": 370, "y1": 230, "y2": 330}}}
  }
  revolute = MultibodyComponents.Revolute(n = [0, 0, 1], statePriority = 100) {
    "Dyad": {"placement": {"diagram": {"x1": 510, "x2": 610, "y1": 300, "y2": 400}}}
  }
  pendulum = MultibodyComponents.BodyCylinder(r = [0, 0.5, 0], diameter = 0.015, color = [0.5, 0.5, 0.5, 1]) {
    "Dyad": {"placement": {"diagram": {"x1": 630, "x2": 730, "y1": 300, "y2": 400}}}
  }
  motor = TranslationalComponents.Sources.Force() {
    "Dyad": {"placement": {"diagram": {"x1": 270, "x2": 170, "y1": 480, "y2": 380}}}
  }
  tip = MultibodyComponents.Body(m = 0.05) {
    "Dyad": {"placement": {"diagram": {"x1": 740, "x2": 840, "y1": 300, "y2": 400}}}
  }
  "Cart position"
  variable x::Length
  "Cart velocity"
  variable v::Velocity
  "Pendulum angle, zero when the pendulum points up"
  variable phi::Angle
  "Pendulum angular velocity"
  variable w::AngularVelocity
relations
  connect(fixed.frame_b, prismatic.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(prismatic.frame_b, cart.frame_a, mounting_point.frame_a) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [], "E": 2},
        {"S": -1, "M": [{"x": 390, "y": 350}], "E": 3}
      ],
      "junctions": [{"x": 390, "y": 280}]
    }
  }
  connect(mounting_point.frame_b, revolute.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(revolute.frame_b, pendulum.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(pendulum.frame_b, tip.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(motor.flange_a, prismatic.support) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 320, "y": 430}], "E": 2}]}}
  connect(motor.flange_b, prismatic.axis) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 130, "y": 430}, {"x": 130, "y": 230}], "E": 2}]}
  }
  connect(u, motor.f) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 220, "y": 500}], "E": 2}]}}
  x = prismatic.s
  v = prismatic.v
  phi = revolute.phi
  w = revolute.w
metadata {"Dyad": {"labels": [{"label": "$(instance)", "x": 500, "y": 1100, "rot": 0}]}}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses