Skip to content
LIBRARY
PlanarMechanics.examples.excavator.ControlledCylinder.md

PlanarMechanics.examples.excavator.ControlledCylinder

A hydraulic cylinder axis with its own valve, sensors, and cascade controller.

Bundles a ProportionalValve, a double-acting cylinder, position/velocity/force sensors at the cylinder flange, and a CascadeServoController into a single reusable actuator. The supply and tank ports connect to the shared hydraulic network; the mechanical flange drives the load (typically through a PlanarCylinderMount); the position, velocity, and acceleration reference inputs come from a trajectory generator.

Usage

MultibodyComponents.PlanarMechanics.examples.excavator.ControlledCylinder(Kv=5e-7, stroke=0.5, M=10, area_a=3e-3, area_b=2e-3, p_a0=1e6, p_b0=5e5, k_pos=6, v_max=0.5, k_vel=0.625, Ti_vel=1.5, f_max=8e4, ka_ff=0, k_force=0.08, Ti_force=0.02)

Parameters:

NameDescriptionUnitsDefault value
KvValve flow coefficient5e-7
strokeCylinder stroke (piston travel and barrel length)m0.5
MPiston masskg10
area_aCap-side piston aream23e-3
area_bRod-side piston aream22e-3
p_a0Initial cap-side chamber pressure1e6
p_b0Initial rod-side chamber pressure5e5
k_posPosition-loop bandwidth (commanded velocity per unit position error)6
v_maxRated cylinder speed (velocity limit and scale)0.5
k_velDimensionless velocity-loop gain0.625
Ti_velVelocity-loop integrator time constants1.5
f_maxRated cylinder force (force limit and scale)8e4
ka_ffAcceleration feedforward gain (reflected inertia)0
k_forceDimensionless force-loop gain0.08
Ti_forceForce-loop integrator time constants0.02

Connectors

  • port_p - (Port)

  • port_t - (Port)

  • flange - This connector represents a mechanical flange with position and force as the potential and flow variables, respectively. (Flange)

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

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

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

Behavior

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

Source

dyad
"""
A hydraulic cylinder axis with its own valve, sensors, and cascade controller.

Bundles a `ProportionalValve`, a double-acting cylinder, position/velocity/force
sensors at the cylinder flange, and a `CascadeServoController` into a single
reusable actuator. The supply and tank ports connect to the shared hydraulic
network; the mechanical `flange` drives the load (typically through a
`PlanarCylinderMount`); the position, velocity, and acceleration reference
inputs come from a trajectory generator.
"""
component ControlledCylinder
  "Supply (pump) port"
  port_p = HydraulicComponents.Interfaces.Port() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 300, "y1": 950, "x2": 400, "y2": 1050, "rot": 0}
      },
      "tags": []
    }
  }
  "Tank (return) port"
  port_t = HydraulicComponents.Interfaces.Port() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 600, "y1": 950, "x2": 700, "y2": 1050, "rot": 0}
      },
      "tags": []
    }
  }
  "Mechanical flange driving the load"
  flange = Flange() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  "Piston position reference"
  s_ref = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -50, "y1": 140, "x2": 50, "y2": 240}}}
  }
  "Piston velocity reference"
  v_ff = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -50, "y1": 450, "x2": 50, "y2": 550}}}
  }
  "Piston acceleration reference"
  a_ff = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -50, "y1": 700, "x2": 50, "y2": 800}}}
  }
  valve = ProportionalValve(Kv = Kv) {
    "Dyad": {"placement": {"diagram": {"x1": 480, "y1": 700, "x2": 630, "y2": 900}}}
  }
  cylinder = HydraulicComponents.Machines.DoubleActingCylinder(L = stroke, M = M, area_a = area_a, area_b = area_b, s0 = missing) {
    "Dyad": {"placement": {"diagram": {"x1": 440, "y1": 600, "x2": 640, "y2": 400}}}
  }
  psens = TranslationalComponents.Sensors.PositionSensor() {
    "Dyad": {
      "placement": {"diagram": {"x1": 130, "y1": 110, "x2": 210, "y2": 190, "rot": 90}}
    }
  }
  vsens = TranslationalComponents.Sensors.SpeedSensor() {
    "Dyad": {
      "placement": {"diagram": {"x1": 220, "y1": 110, "x2": 300, "y2": 190, "rot": 90}}
    }
  }
  fsens = TranslationalComponents.Sensors.ForceSensor() {
    "Dyad": {
      "placement": {"diagram": {"x1": 580, "y1": 190, "x2": 500, "y2": 270, "rot": 90}}
    }
  }
  servo = MultibodyComponents.CascadeServoController(final k_pos = k_pos, final v_max = v_max, final k_vel = k_vel, final Ti_vel = Ti_vel, final f_max = f_max, final ka_ff = ka_ff, final k_force = k_force, final Ti_force = Ti_force) {
    "Dyad": {"placement": {"diagram": {"x1": 150, "y1": 450, "x2": 350, "y2": 250}}}
  }
  "Valve flow coefficient"
  parameter Kv::Real = 5e-7
  "Cylinder stroke (piston travel and barrel length)"
  parameter stroke::Length = 0.5
  "Piston mass"
  parameter M::Mass = 10
  "Cap-side piston area"
  parameter area_a::Area = 3e-3
  "Rod-side piston area"
  parameter area_b::Area = 2e-3
  "Initial cap-side chamber pressure"
  parameter p_a0::Real = 1e6
  "Initial rod-side chamber pressure"
  parameter p_b0::Real = 5e5
  "Position-loop bandwidth (commanded velocity per unit position error)"
  parameter k_pos::Real = 6
  "Rated cylinder speed (velocity limit and scale)"
  parameter v_max::Real = 0.5
  "Dimensionless velocity-loop gain"
  parameter k_vel::Real = 0.625
  "Velocity-loop integrator time constant"
  parameter Ti_vel::Time = 1.5
  "Rated cylinder force (force limit and scale)"
  parameter f_max::Real = 8e4
  "Acceleration feedforward gain (reflected inertia)"
  parameter ka_ff::Real = 0
  "Dimensionless force-loop gain"
  parameter k_force::Real = 0.08
  "Force-loop integrator time constant"
  parameter Ti_force::Time = 0.02
relations
  initial cylinder.port_a.p = p_a0
  initial cylinder.port_b.p = p_b0
  connect(servo.s_ref, s_ref) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 0, "y": 350}], "E": 2}]}}
  connect(v_ff, servo.v_ff) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 206, "y": 500}], "E": 2}]}}
  connect(servo.a_ff, a_ff) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 292, "y": 750}], "E": 2}]}}
  connect(psens.s, servo.s_meas) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 170, "y": 201}, {"x": 192, "y": 201}], "E": 2}]}
  }
  connect(vsens.v, servo.v_meas) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 260, "y": 221}, {"x": 250, "y": 221}], "E": 2}]}
  }
  connect(port_t, valve.port_t) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 592.5, "y": 1000}], "E": 2}]}}
  connect(valve.port_b, cylinder.port_b) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 592.5, "y": 660}, {"x": 670, "y": 660}, {"x": 670, "y": 500}],
          "E": 2
        }
      ]
    }
  }
  connect(valve.port_a, cylinder.port_a) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 517.5, "y": 660}, {"x": 410, "y": 660}, {"x": 410, "y": 500}],
          "E": 2
        }
      ]
    }
  }
  connect(valve.port_p, port_p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 517.5, "y": 940}, {"x": 350, "y": 940}], "E": 2}]
    }
  }
  connect(fsens.f, servo.f_meas) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 308, "y": 230}], "E": 2}]}}
  connect(fsens.flange_b, flange) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 540, "y": 150}, {"x": 870, "y": 150}, {"x": 870, "y": 500}],
          "E": 2
        }
      ]
    }
  }
  connect(fsens.flange_a, cylinder.flange) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
metadata {
  "Dyad": {"icons": {"default": "dyad://MultibodyComponents/ControlledCylinder.svg"}}
}
end
Flattened Source
dyad
"""
A hydraulic cylinder axis with its own valve, sensors, and cascade controller.

Bundles a `ProportionalValve`, a double-acting cylinder, position/velocity/force
sensors at the cylinder flange, and a `CascadeServoController` into a single
reusable actuator. The supply and tank ports connect to the shared hydraulic
network; the mechanical `flange` drives the load (typically through a
`PlanarCylinderMount`); the position, velocity, and acceleration reference
inputs come from a trajectory generator.
"""
component ControlledCylinder
  "Supply (pump) port"
  port_p = HydraulicComponents.Interfaces.Port() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 300, "y1": 950, "x2": 400, "y2": 1050, "rot": 0}
      },
      "tags": []
    }
  }
  "Tank (return) port"
  port_t = HydraulicComponents.Interfaces.Port() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 600, "y1": 950, "x2": 700, "y2": 1050, "rot": 0}
      },
      "tags": []
    }
  }
  "Mechanical flange driving the load"
  flange = Flange() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  "Piston position reference"
  s_ref = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -50, "y1": 140, "x2": 50, "y2": 240}}}
  }
  "Piston velocity reference"
  v_ff = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -50, "y1": 450, "x2": 50, "y2": 550}}}
  }
  "Piston acceleration reference"
  a_ff = RealInput() {
    "Dyad": {"placement": {"diagram": {"x1": -50, "y1": 700, "x2": 50, "y2": 800}}}
  }
  valve = ProportionalValve(Kv = Kv) {
    "Dyad": {"placement": {"diagram": {"x1": 480, "y1": 700, "x2": 630, "y2": 900}}}
  }
  cylinder = HydraulicComponents.Machines.DoubleActingCylinder(L = stroke, M = M, area_a = area_a, area_b = area_b, s0 = missing) {
    "Dyad": {"placement": {"diagram": {"x1": 440, "y1": 600, "x2": 640, "y2": 400}}}
  }
  psens = TranslationalComponents.Sensors.PositionSensor() {
    "Dyad": {
      "placement": {"diagram": {"x1": 130, "y1": 110, "x2": 210, "y2": 190, "rot": 90}}
    }
  }
  vsens = TranslationalComponents.Sensors.SpeedSensor() {
    "Dyad": {
      "placement": {"diagram": {"x1": 220, "y1": 110, "x2": 300, "y2": 190, "rot": 90}}
    }
  }
  fsens = TranslationalComponents.Sensors.ForceSensor() {
    "Dyad": {
      "placement": {"diagram": {"x1": 580, "y1": 190, "x2": 500, "y2": 270, "rot": 90}}
    }
  }
  servo = MultibodyComponents.CascadeServoController(final k_pos = k_pos, final v_max = v_max, final k_vel = k_vel, final Ti_vel = Ti_vel, final f_max = f_max, final ka_ff = ka_ff, final k_force = k_force, final Ti_force = Ti_force) {
    "Dyad": {"placement": {"diagram": {"x1": 150, "y1": 450, "x2": 350, "y2": 250}}}
  }
  "Valve flow coefficient"
  parameter Kv::Real = 5e-7
  "Cylinder stroke (piston travel and barrel length)"
  parameter stroke::Length = 0.5
  "Piston mass"
  parameter M::Mass = 10
  "Cap-side piston area"
  parameter area_a::Area = 3e-3
  "Rod-side piston area"
  parameter area_b::Area = 2e-3
  "Initial cap-side chamber pressure"
  parameter p_a0::Real = 1e6
  "Initial rod-side chamber pressure"
  parameter p_b0::Real = 5e5
  "Position-loop bandwidth (commanded velocity per unit position error)"
  parameter k_pos::Real = 6
  "Rated cylinder speed (velocity limit and scale)"
  parameter v_max::Real = 0.5
  "Dimensionless velocity-loop gain"
  parameter k_vel::Real = 0.625
  "Velocity-loop integrator time constant"
  parameter Ti_vel::Time = 1.5
  "Rated cylinder force (force limit and scale)"
  parameter f_max::Real = 8e4
  "Acceleration feedforward gain (reflected inertia)"
  parameter ka_ff::Real = 0
  "Dimensionless force-loop gain"
  parameter k_force::Real = 0.08
  "Force-loop integrator time constant"
  parameter Ti_force::Time = 0.02
relations
  initial cylinder.port_a.p = p_a0
  initial cylinder.port_b.p = p_b0
  connect(servo.s_ref, s_ref) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 0, "y": 350}], "E": 2}]}}
  connect(v_ff, servo.v_ff) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 206, "y": 500}], "E": 2}]}}
  connect(servo.a_ff, a_ff) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 292, "y": 750}], "E": 2}]}}
  connect(psens.s, servo.s_meas) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 170, "y": 201}, {"x": 192, "y": 201}], "E": 2}]}
  }
  connect(vsens.v, servo.v_meas) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 260, "y": 221}, {"x": 250, "y": 221}], "E": 2}]}
  }
  connect(port_t, valve.port_t) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 592.5, "y": 1000}], "E": 2}]}}
  connect(valve.port_b, cylinder.port_b) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 592.5, "y": 660}, {"x": 670, "y": 660}, {"x": 670, "y": 500}],
          "E": 2
        }
      ]
    }
  }
  connect(valve.port_a, cylinder.port_a) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 517.5, "y": 660}, {"x": 410, "y": 660}, {"x": 410, "y": 500}],
          "E": 2
        }
      ]
    }
  }
  connect(valve.port_p, port_p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 517.5, "y": 940}, {"x": 350, "y": 940}], "E": 2}]
    }
  }
  connect(fsens.f, servo.f_meas) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 308, "y": 230}], "E": 2}]}}
  connect(fsens.flange_b, flange) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 540, "y": 150}, {"x": 870, "y": 150}, {"x": 870, "y": 500}],
          "E": 2
        }
      ]
    }
  }
  connect(fsens.flange_a, cylinder.flange) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
metadata {
  "Dyad": {"icons": {"default": "dyad://MultibodyComponents/ControlledCylinder.svg"}}
}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses