Skip to content
LIBRARY
PlanarMechanics.examples.trebuchet.Trebuchet.md

PlanarMechanics.examples.trebuchet.Trebuchet

A planar trebuchet built from PlanarMechanics components.

The machine stands on two ideal (no-slip) rolling wheels so the whole frame can recoil horizontally as it fires. A heavy counterweight hangs from a hinge on the short side of the throwing arm; the long side of the arm whips a sling, modeled with the Cable component (an open chain of n rigid links). The projectile is a Body attached to the free end of the sling.

Releasing the projectile is a structural change (a connection is removed) that cannot happen mid-simulation. The structural parameter attached selects the two variants: attached = true keeps the projectile connected to the sling end (used until the arm reaches the release angle), attached = false lets the projectile fly freely. The companion script run_trebuchet.jl simulates the attached model, stops at the release angle, and restarts the free model from the captured end state.

Each wheel hub frame rotates with the rolling angle, so a bearing Revolute sits between every wheel and the chassis; the two ground contacts keep the chassis level while it rolls.

Usage

MultibodyComponents.PlanarMechanics.examples.trebuchet.Trebuchet(rw=0.3, wheelbase=1.4, post_dx=0.7, post_h=4.7, L_long=3.0, L_short=1.0, L_hang=0.8, l_sling=2.0, sling_dir=[0, -1], d_sling=1, c_sling=0.2, m_chassis=80, m_arm=20, m_cw=300, m_sling=2, m_proj=15, I_cw=5, I_proj=0.5, I_arm=m_arm * L_long ^ 2 / 12, I_chassis=m_chassis * wheelbase ^ 2 / 12, phi0=-1.0)

Parameters:

NameDescriptionUnitsDefault value
attachedtrue
rwWheel radiusm0.3
wheelbaseDistance between the two wheel axlesm1.4
post_dxHorizontal offset of the pivot from the rear wheelm0.7
post_hHeight of the pivot above the wheel axlesm4.7
L_longLength of the long (throwing) arm from the fulcrum to the sling attachmentm3.0
L_shortLength of the short arm from the fulcrum to the counterweight hingem1.0
L_hangLength the counterweight hangs below its hingem0.8
l_slingTotal unstretched length of the slingm2.0
sling_dirHanging direction of the straight sling, resolved in the arm-tip frame[0, -1]
d_slingViscous damping of each sling joint (slight, for a more realistic sling)N.m.s/rad1
c_slingRotational stiffness of each sling joint (slight, for a more realistic sling)N.m/rad0.2
m_chassisMass of the chassis beamkg80
m_armMass of the throwing armkg20
m_cwMass of the counterweightkg300
m_slingTotal mass of the slingkg2
m_projMass of the projectilekg15
I_cwMoment of inertia of the counterweight about its center of masskg.m25
I_projMoment of inertia of the projectile about its center of masskg.m20.5
phi0Initial pivot angle: long arm down, counterweight raisedrad-1.0

Behavior

Source

dyad
"""
A planar trebuchet built from PlanarMechanics components.

The machine stands on two ideal (no-slip) rolling wheels so the whole frame can
recoil horizontally as it fires. A heavy counterweight hangs from a hinge on the
short side of the throwing arm; the long side of the arm whips a sling, modeled
with the `Cable` component (an open chain of `n` rigid links). The projectile is
a `Body` attached to the free end of the sling.

Releasing the projectile is a structural change (a connection is removed) that
cannot happen mid-simulation. The structural parameter `attached` selects the two
variants: `attached = true` keeps the projectile connected to the sling end
(used until the arm reaches the release angle), `attached = false` lets the
projectile fly freely. The companion script `run_trebuchet.jl` simulates the
attached model, stops at the release angle, and restarts the free model from the
captured end state.

Each wheel hub frame rotates with the rolling angle, so a bearing `Revolute`
sits between every wheel and the chassis; the two ground contacts keep the
chassis level while it rolls.
"""
example component Trebuchet
  world = MultibodyComponents.PlanarMechanics.World(render_ground = false, nominal_length = 2) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 140, "y1": 20, "x2": 240, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  # --- chassis on two no-slip wheels (wheel -> bearing -> chassis beam) ---
  wheel_rear = MultibodyComponents.PlanarMechanics.OneDOFRollingWheelJoint(radius = rw, x0 = 0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 250, "y1": 680, "x2": 350, "y2": 780, "rot": 0}
      },
      "tags": []
    }
  }
  wheel_front = MultibodyComponents.PlanarMechanics.OneDOFRollingWheelJoint(radius = rw, x0 = wheelbase) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 490, "y1": 680, "x2": 590, "y2": 780, "rot": 0}
      },
      "tags": []
    }
  }
  bear_rear = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = 0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 250, "y1": 580, "x2": 350, "y2": 680, "rot": 270}
      },
      "tags": []
    }
  }
  bear_front = MultibodyComponents.PlanarMechanics.Revolute() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 490, "y1": 580, "x2": 590, "y2": 680, "rot": 270}
      },
      "tags": []
    }
  }
  chassis = MultibodyComponents.PlanarMechanics.BodyShape(r = [wheelbase, 0], m = m_chassis, I = I_chassis, radius = 0.06) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 370, "y1": 510, "x2": 470, "y2": 610, "rot": 0}
      },
      "tags": []
    }
  }
  post = MultibodyComponents.PlanarMechanics.FixedTranslation(r = [post_dx, post_h]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 310, "y1": 380, "x2": 450, "y2": 520, "rot": 270}
      },
      "tags": []
    }
  }
  # --- throwing arm + hinged counterweight, rotating about the fulcrum ---
  pivot = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = phi0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 330, "y1": 270, "x2": 430, "y2": 370, "rot": 270}
      },
      "tags": []
    }
  }
  arm = MultibodyComponents.PlanarMechanics.BodyShape(r = [L_long, 0], m = m_arm, I = I_arm, radius = 0.05) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 350, "y1": 210, "x2": 250, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cw_ext = MultibodyComponents.PlanarMechanics.FixedTranslation(r = [-L_short, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 430, "y1": 210, "x2": 530, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cw_hinge = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = -phi0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 540, "y1": 210, "x2": 640, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cw_rod = MultibodyComponents.PlanarMechanics.FixedTranslation(r = [0, -L_hang]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 640, "y1": 270, "x2": 740, "y2": 370, "rot": 90}
      },
      "tags": []
    }
  }
  cw = MultibodyComponents.PlanarMechanics.Body(m = m_cw, I = I_cw, radius = 0.35) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 590, "y1": 380, "x2": 790, "y2": 580, "rot": 90}
      },
      "tags": []
    }
  }
  # --- sling + projectile ---
  # A free pivot connects the sling to the arm tip. The cable uses
  # `end_joints = false` so its far end is the last link's (massive) tip; this
  # keeps the released model well-posed (an enabled end joint left unloaded
  # after release would be a massless, undetermined rotational DOF).
  sling_pivot = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = 0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 240, "y1": 210, "x2": 140, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cable = MultibodyComponents.PlanarMechanics.Cable(n = 7, end_joints = false, l = l_sling, m = m_sling, dir = sling_dir, radius = 0.04, hasdamping = true, d_joint = d_sling, hasstiffness = true, c_joint = c_sling) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 210, "x2": 0, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  projectile = MultibodyComponents.PlanarMechanics.Body(m = m_proj, I = I_proj, radius = 0.12) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 0, "y1": 150, "x2": 100, "y2": 250, "rot": 90}
      },
      "tags": []
    }
  }
  damper = RotationalComponents.Components.Damper(d = 3) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 160, "y1": 350, "x2": 220, "y2": 410, "rot": 90}
      },
      "tags": []
    }
  }
  fixed = RotationalComponents.Components.Fixed() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 160, "y1": 430, "x2": 220, "y2": 490, "rot": 0}
      },
      "tags": []
    }
  }
  # Projectile connected to the sling end (true) or free-flying (false)
  structural parameter attached::Boolean = true
  # --- geometry parameters ---
  "Wheel radius"
  parameter rw::Length = 0.3
  "Distance between the two wheel axles"
  parameter wheelbase::Length = 1.4
  "Horizontal offset of the pivot from the rear wheel"
  parameter post_dx::Length = 0.7
  "Height of the pivot above the wheel axles"
  parameter post_h::Length = 4.7
  "Length of the long (throwing) arm from the fulcrum to the sling attachment"
  parameter L_long::Length = 3.0
  "Length of the short arm from the fulcrum to the counterweight hinge"
  parameter L_short::Length = 1.0
  "Length the counterweight hangs below its hinge"
  parameter L_hang::Length = 0.8
  "Total unstretched length of the sling"
  parameter l_sling::Length = 2.0
  "Hanging direction of the straight sling, resolved in the arm-tip frame"
  parameter sling_dir::Real[2] = [0, -1]
  "Viscous damping of each sling joint (slight, for a more realistic sling)"
  parameter d_sling::RotationalDampingConstant = 1
  "Rotational stiffness of each sling joint (slight, for a more realistic sling)"
  parameter c_sling::RotationalSpringConstant = 0.2
  # --- mass parameters ---
  "Mass of the chassis beam"
  parameter m_chassis::Mass = 80
  "Mass of the throwing arm"
  parameter m_arm::Mass = 20
  "Mass of the counterweight"
  parameter m_cw::Mass = 300
  "Total mass of the sling"
  parameter m_sling::Mass = 2
  "Mass of the projectile"
  parameter m_proj::Mass = 15
  # --- inertia parameters ---
  "Moment of inertia of the counterweight about its center of mass"
  parameter I_cw::MomentOfInertia = 5
  "Moment of inertia of the projectile about its center of mass"
  parameter I_proj::MomentOfInertia = 0.5
  "Moment of inertia of the throwing arm about its center of mass (thin rod)"
  final parameter I_arm::MomentOfInertia = m_arm * L_long ^ 2 / 12
  "Moment of inertia of the chassis beam about its center of mass (thin rod)"
  final parameter I_chassis::MomentOfInertia = m_chassis * wheelbase ^ 2 / 12
  # --- initial (cocked) configuration ---
  "Initial pivot angle: long arm down, counterweight raised"
  parameter phi0::Angle = -1.0
relations
  # cocked configuration: arm held down, counterweight hanging vertically, at rest
  # chassis carried by the two rolling wheels through bearings
  connect(wheel_rear.frame_a, bear_rear.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bear_rear.frame_b, chassis.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 300, "y": 560}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(wheel_front.frame_a, bear_front.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bear_front.frame_b, chassis.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 540, "y": 560}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(chassis.frame_a, post.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 380, "y": 500}],
      "renderStyle": "standard"
    }
  }
  connect(post.frame_b, pivot.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  # rigid lever about the fulcrum (pivot.frame_b)
  connect(pivot.frame_b, arm.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 380, "y": 260}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(pivot.frame_b, cw_ext.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 380, "y": 260}], "E": 2}],
      "junctions": [{"x": 380, "y": 280}],
      "renderStyle": "standard"
    }
  }
  connect(cw_ext.frame_b, cw_hinge.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cw_hinge.frame_b, cw_rod.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 690, "y": 260}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(cw_rod.frame_b, cw.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  # sling pivots freely at the arm tip; projectile at the open end (removed on release)
  connect(arm.frame_b, sling_pivot.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(sling_pivot.frame_b, cable.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(fixed.spline, damper.spline_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(damper.spline_a, sling_pivot.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  if attached
    connect(cable.frame_b, projectile.frame_a)
  end
metadata {"Dyad": {"tests": {}}}
end
Flattened Source
dyad
"""
A planar trebuchet built from PlanarMechanics components.

The machine stands on two ideal (no-slip) rolling wheels so the whole frame can
recoil horizontally as it fires. A heavy counterweight hangs from a hinge on the
short side of the throwing arm; the long side of the arm whips a sling, modeled
with the `Cable` component (an open chain of `n` rigid links). The projectile is
a `Body` attached to the free end of the sling.

Releasing the projectile is a structural change (a connection is removed) that
cannot happen mid-simulation. The structural parameter `attached` selects the two
variants: `attached = true` keeps the projectile connected to the sling end
(used until the arm reaches the release angle), `attached = false` lets the
projectile fly freely. The companion script `run_trebuchet.jl` simulates the
attached model, stops at the release angle, and restarts the free model from the
captured end state.

Each wheel hub frame rotates with the rolling angle, so a bearing `Revolute`
sits between every wheel and the chassis; the two ground contacts keep the
chassis level while it rolls.
"""
example component Trebuchet
  world = MultibodyComponents.PlanarMechanics.World(render_ground = false, nominal_length = 2) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 140, "y1": 20, "x2": 240, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  # --- chassis on two no-slip wheels (wheel -> bearing -> chassis beam) ---
  wheel_rear = MultibodyComponents.PlanarMechanics.OneDOFRollingWheelJoint(radius = rw, x0 = 0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 250, "y1": 680, "x2": 350, "y2": 780, "rot": 0}
      },
      "tags": []
    }
  }
  wheel_front = MultibodyComponents.PlanarMechanics.OneDOFRollingWheelJoint(radius = rw, x0 = wheelbase) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 490, "y1": 680, "x2": 590, "y2": 780, "rot": 0}
      },
      "tags": []
    }
  }
  bear_rear = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = 0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 250, "y1": 580, "x2": 350, "y2": 680, "rot": 270}
      },
      "tags": []
    }
  }
  bear_front = MultibodyComponents.PlanarMechanics.Revolute() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 490, "y1": 580, "x2": 590, "y2": 680, "rot": 270}
      },
      "tags": []
    }
  }
  chassis = MultibodyComponents.PlanarMechanics.BodyShape(r = [wheelbase, 0], m = m_chassis, I = I_chassis, radius = 0.06) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 370, "y1": 510, "x2": 470, "y2": 610, "rot": 0}
      },
      "tags": []
    }
  }
  post = MultibodyComponents.PlanarMechanics.FixedTranslation(r = [post_dx, post_h]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 310, "y1": 380, "x2": 450, "y2": 520, "rot": 270}
      },
      "tags": []
    }
  }
  # --- throwing arm + hinged counterweight, rotating about the fulcrum ---
  pivot = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = phi0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 330, "y1": 270, "x2": 430, "y2": 370, "rot": 270}
      },
      "tags": []
    }
  }
  arm = MultibodyComponents.PlanarMechanics.BodyShape(r = [L_long, 0], m = m_arm, I = I_arm, radius = 0.05) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 350, "y1": 210, "x2": 250, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cw_ext = MultibodyComponents.PlanarMechanics.FixedTranslation(r = [-L_short, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 430, "y1": 210, "x2": 530, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cw_hinge = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = -phi0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 540, "y1": 210, "x2": 640, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cw_rod = MultibodyComponents.PlanarMechanics.FixedTranslation(r = [0, -L_hang]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 640, "y1": 270, "x2": 740, "y2": 370, "rot": 90}
      },
      "tags": []
    }
  }
  cw = MultibodyComponents.PlanarMechanics.Body(m = m_cw, I = I_cw, radius = 0.35) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 590, "y1": 380, "x2": 790, "y2": 580, "rot": 90}
      },
      "tags": []
    }
  }
  # --- sling + projectile ---
  # A free pivot connects the sling to the arm tip. The cable uses
  # `end_joints = false` so its far end is the last link's (massive) tip; this
  # keeps the released model well-posed (an enabled end joint left unloaded
  # after release would be a massless, undetermined rotational DOF).
  sling_pivot = MultibodyComponents.PlanarMechanics.Revolute(phi(initial = 0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 240, "y1": 210, "x2": 140, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  cable = MultibodyComponents.PlanarMechanics.Cable(n = 7, end_joints = false, l = l_sling, m = m_sling, dir = sling_dir, radius = 0.04, hasdamping = true, d_joint = d_sling, hasstiffness = true, c_joint = c_sling) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 210, "x2": 0, "y2": 310, "rot": 0}
      },
      "tags": []
    }
  }
  projectile = MultibodyComponents.PlanarMechanics.Body(m = m_proj, I = I_proj, radius = 0.12) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 0, "y1": 150, "x2": 100, "y2": 250, "rot": 90}
      },
      "tags": []
    }
  }
  damper = RotationalComponents.Components.Damper(d = 3) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 160, "y1": 350, "x2": 220, "y2": 410, "rot": 90}
      },
      "tags": []
    }
  }
  fixed = RotationalComponents.Components.Fixed() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 160, "y1": 430, "x2": 220, "y2": 490, "rot": 0}
      },
      "tags": []
    }
  }
  # Projectile connected to the sling end (true) or free-flying (false)
  structural parameter attached::Boolean = true
  # --- geometry parameters ---
  "Wheel radius"
  parameter rw::Length = 0.3
  "Distance between the two wheel axles"
  parameter wheelbase::Length = 1.4
  "Horizontal offset of the pivot from the rear wheel"
  parameter post_dx::Length = 0.7
  "Height of the pivot above the wheel axles"
  parameter post_h::Length = 4.7
  "Length of the long (throwing) arm from the fulcrum to the sling attachment"
  parameter L_long::Length = 3.0
  "Length of the short arm from the fulcrum to the counterweight hinge"
  parameter L_short::Length = 1.0
  "Length the counterweight hangs below its hinge"
  parameter L_hang::Length = 0.8
  "Total unstretched length of the sling"
  parameter l_sling::Length = 2.0
  "Hanging direction of the straight sling, resolved in the arm-tip frame"
  parameter sling_dir::Real[2] = [0, -1]
  "Viscous damping of each sling joint (slight, for a more realistic sling)"
  parameter d_sling::RotationalDampingConstant = 1
  "Rotational stiffness of each sling joint (slight, for a more realistic sling)"
  parameter c_sling::RotationalSpringConstant = 0.2
  # --- mass parameters ---
  "Mass of the chassis beam"
  parameter m_chassis::Mass = 80
  "Mass of the throwing arm"
  parameter m_arm::Mass = 20
  "Mass of the counterweight"
  parameter m_cw::Mass = 300
  "Total mass of the sling"
  parameter m_sling::Mass = 2
  "Mass of the projectile"
  parameter m_proj::Mass = 15
  # --- inertia parameters ---
  "Moment of inertia of the counterweight about its center of mass"
  parameter I_cw::MomentOfInertia = 5
  "Moment of inertia of the projectile about its center of mass"
  parameter I_proj::MomentOfInertia = 0.5
  "Moment of inertia of the throwing arm about its center of mass (thin rod)"
  final parameter I_arm::MomentOfInertia = m_arm * L_long ^ 2 / 12
  "Moment of inertia of the chassis beam about its center of mass (thin rod)"
  final parameter I_chassis::MomentOfInertia = m_chassis * wheelbase ^ 2 / 12
  # --- initial (cocked) configuration ---
  "Initial pivot angle: long arm down, counterweight raised"
  parameter phi0::Angle = -1.0
relations
  # cocked configuration: arm held down, counterweight hanging vertically, at rest
  # chassis carried by the two rolling wheels through bearings
  connect(wheel_rear.frame_a, bear_rear.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bear_rear.frame_b, chassis.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 300, "y": 560}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(wheel_front.frame_a, bear_front.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bear_front.frame_b, chassis.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 540, "y": 560}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(chassis.frame_a, post.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 380, "y": 500}],
      "renderStyle": "standard"
    }
  }
  connect(post.frame_b, pivot.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  # rigid lever about the fulcrum (pivot.frame_b)
  connect(pivot.frame_b, arm.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 380, "y": 260}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(pivot.frame_b, cw_ext.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 380, "y": 260}], "E": 2}],
      "junctions": [{"x": 380, "y": 280}],
      "renderStyle": "standard"
    }
  }
  connect(cw_ext.frame_b, cw_hinge.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cw_hinge.frame_b, cw_rod.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 690, "y": 260}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(cw_rod.frame_b, cw.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  # sling pivots freely at the arm tip; projectile at the open end (removed on release)
  connect(arm.frame_b, sling_pivot.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(sling_pivot.frame_b, cable.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(fixed.spline, damper.spline_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(damper.spline_a, sling_pivot.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  if attached
    connect(cable.frame_b, projectile.frame_a)
  end
metadata {"Dyad": {"tests": {}}}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses