Skip to content
LIBRARY
Examples.UKFPendulumExample.md

Examples.UKFPendulumExample ​

Damped pendulum driven by a sinusoidal torque, observed by a UKFObserver that estimates the angle and the angular velocity from the sampled angle alone. The observer's prediction model is the plant component itself (dynamics = plant, inputs = ["tau"]), and it starts from a wrong initial estimate (the pendulum starts at 45°, the observer at rest) to show the convergence of the estimate.

Usage ​

MPCComponents.Examples.UKFPendulumExample()

Parameters: ​

NameDescriptionUnitsDefault value
backendBackend of the observer–MPCComponen...kend.Auto()

Variables ​

NameDescriptionUnits
thetaAngle of the pendulum–
omegaAngular velocity of the pendulum–
theta_hatEstimated angle–
omega_hatEstimated angular velocity–

Behavior ​

Behavior of this component cannot be rendered because it includes path variables.

Source ​

dyad
"""
Damped pendulum driven by a sinusoidal torque, observed by a `UKFObserver` that estimates the angle
and the angular velocity from the sampled angle alone. The observer's prediction model is the plant
component itself (`dynamics = plant, inputs = ["tau"]`), and it starts from a wrong initial estimate
(the pendulum starts at 45°, the observer at rest) to show the convergence of the estimate.
"""
example component UKFPendulumExample
  periodicclock = DiscreteComponents.PeriodicClock(dt = 0.05) {
    "Dyad": {"placement": {"diagram": {"x1": 500, "y1": 640, "x2": 600, "y2": 740}}}
  }
  plant = MPCComponents.Examples.ACADOSPendulumPlant(theta0 = 0.7853981633974483) {
    "Dyad": {"placement": {"diagram": {"x1": 700, "y1": 300, "x2": 800, "y2": 400}}}
  }
  torque = BlockComponents.Sources.Sine(amplitude = 2.0, frequency = 0.5) {
    "Dyad": {"placement": {"diagram": {"x1": 100, "y1": 300, "x2": 200, "y2": 400}}}
  }
  su = DiscreteComponents.Sampler() {
    "Dyad": {"placement": {"diagram": {"x1": 300, "y1": 300, "x2": 400, "y2": 400}}}
  }
  sy = DiscreteComponents.Sampler() {
    "Dyad": {
      "placement": {"diagram": {"x1": 580, "y1": 490, "x2": 680, "y2": 590, "rot": 180}}
    }
  }
  zoh = DiscreteComponents.ZeroOrderHold() {
    "Dyad": {"placement": {"diagram": {"x1": 500, "y1": 300, "x2": 600, "y2": 400}}}
  }
  ukf = MPCComponents.UKFObserver(dynamics = plant, inputs = ["tau"], outputs = ["theta"], state_variables = ["th", "om"], Ts = 0.05, R1 = diagonal([1e-4, 1e-4]), R2 = diagonal([1e-3]), x0 = [0.0, 0.0], R0 = diagonal([1.0, 1.0]), final backend = backend) {
    "Dyad": {"placement": {"diagram": {"x1": 430, "y1": 470, "x2": 330, "y2": 570}}}
  }
  "Backend of the observer"
  structural parameter backend::MPCComponents.Backend = MPCComponents.Backend.Auto()
  "Angle of the pendulum"
  variable theta::Real
  "Angular velocity of the pendulum"
  variable omega::Real
  "Estimated angle"
  variable theta_hat::Real
  "Estimated angular velocity"
  variable omega_hat::Real
relations
  theta = plant.theta
  omega = plant.omega
  theta_hat = ukf.xhat[1]
  omega_hat = ukf.xhat[2]
  connect(torque.y, su.u)
  connect(su.y, zoh.u)
  connect(zoh.y, plant.tau)
  connect(su.y, ukf.u[1]) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 460, "y": 350}, {"x": 460, "y": 495}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.theta, sy.u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 860, "y": 335}, {"x": 860, "y": 540}], "E": 2}],
      "path": {}
    }
  }
  connect(sy.y, ukf.y[1], periodicclock.y) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 475, "y": 540}, {"x": 475, "y": 545}], "E": 2},
        {"S": 2, "M": [{"x": 435, "y": 690}], "E": 3}
      ],
      "path": {}
    }
  }
metadata {"Dyad": {"tests": {"case1": {"stop": 6}}, "doc": {"behavior": false}}}
end
Flattened Source
dyad
"""
Damped pendulum driven by a sinusoidal torque, observed by a `UKFObserver` that estimates the angle
and the angular velocity from the sampled angle alone. The observer's prediction model is the plant
component itself (`dynamics = plant, inputs = ["tau"]`), and it starts from a wrong initial estimate
(the pendulum starts at 45°, the observer at rest) to show the convergence of the estimate.
"""
example component UKFPendulumExample
  periodicclock = DiscreteComponents.PeriodicClock(dt = 0.05) {
    "Dyad": {"placement": {"diagram": {"x1": 500, "y1": 640, "x2": 600, "y2": 740}}}
  }
  plant = MPCComponents.Examples.ACADOSPendulumPlant(theta0 = 0.7853981633974483) {
    "Dyad": {"placement": {"diagram": {"x1": 700, "y1": 300, "x2": 800, "y2": 400}}}
  }
  torque = BlockComponents.Sources.Sine(amplitude = 2.0, frequency = 0.5) {
    "Dyad": {"placement": {"diagram": {"x1": 100, "y1": 300, "x2": 200, "y2": 400}}}
  }
  su = DiscreteComponents.Sampler() {
    "Dyad": {"placement": {"diagram": {"x1": 300, "y1": 300, "x2": 400, "y2": 400}}}
  }
  sy = DiscreteComponents.Sampler() {
    "Dyad": {
      "placement": {"diagram": {"x1": 580, "y1": 490, "x2": 680, "y2": 590, "rot": 180}}
    }
  }
  zoh = DiscreteComponents.ZeroOrderHold() {
    "Dyad": {"placement": {"diagram": {"x1": 500, "y1": 300, "x2": 600, "y2": 400}}}
  }
  ukf = MPCComponents.UKFObserver(dynamics = plant, inputs = ["tau"], outputs = ["theta"], state_variables = ["th", "om"], Ts = 0.05, R1 = diagonal([1e-4, 1e-4]), R2 = diagonal([1e-3]), x0 = [0.0, 0.0], R0 = diagonal([1.0, 1.0]), final backend = backend) {
    "Dyad": {"placement": {"diagram": {"x1": 430, "y1": 470, "x2": 330, "y2": 570}}}
  }
  "Backend of the observer"
  structural parameter backend::MPCComponents.Backend = MPCComponents.Backend.Auto()
  "Angle of the pendulum"
  variable theta::Real
  "Angular velocity of the pendulum"
  variable omega::Real
  "Estimated angle"
  variable theta_hat::Real
  "Estimated angular velocity"
  variable omega_hat::Real
relations
  theta = plant.theta
  omega = plant.omega
  theta_hat = ukf.xhat[1]
  omega_hat = ukf.xhat[2]
  connect(torque.y, su.u)
  connect(su.y, zoh.u)
  connect(zoh.y, plant.tau)
  connect(su.y, ukf.u[1]) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 460, "y": 350}, {"x": 460, "y": 495}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.theta, sy.u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 860, "y": 335}, {"x": 860, "y": 540}], "E": 2}],
      "path": {}
    }
  }
  connect(sy.y, ukf.y[1], periodicclock.y) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 475, "y": 540}, {"x": 475, "y": 545}], "E": 2},
        {"S": 2, "M": [{"x": 435, "y": 690}], "E": 3}
      ],
      "path": {}
    }
  }
metadata {"Dyad": {"tests": {"case1": {"stop": 6}}, "doc": {"behavior": false}}}
end


Test Cases ​

Test Case case1 ​

  • Examples

  • Experiments

  • Analyses