# No. 91 (Brown 1868): "Triangular eccentric, giving an intermittent reciprocating rectilinear motion, used in
# France for the valve motion of steam engines."
#
# Model (cm): the shaft (the one driven joint, 15 turns a minute, clockwise in the view) carries at one corner a
# curved triangle: three arcs, each struck from the opposite corner with the side (6 cm) as radius, so that it
# is 6 cm wide whichever way it is turned. It works by real contact between the two horizontal faces of a
# square yoke 6 cm apart (and 0.1 mm clearance), whose rods slide up and down in fixed guides. While the
# corner on the shaft is lowest the yoke rests at the top (60 deg of the turn); for 120 deg the arcs about the
# other corners carry it down; while the arc about the shaft is lowest it rests at the bottom (6 cm down, 60 deg);
# and it is carried up again in the last 120 deg. Generator: opencode-runs/batch8/gen091.py.
number: 91
slug: triangular-eccentric
name: A triangular eccentric giving a reciprocating motion with rests
brown: "Triangular eccentric, giving an intermittent reciprocating rectilinear motion, used in France for the valve motion of steam engines."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: true
  duration_s: 10
  floor: false
bodies:
  - id: shaft
    shape: part
    pos: [0, 0, 0]
    mass: 1.0
    friction: 0.05
    color: "#d9cfb6"
    pieces:
      - {kind: rod, from: [0, -2.4, 0], to: [0, 3.0, 0], radius: 0.6, color: "#8f8a80"}   # the shaft
      - {kind: poly, points: [[3.0, 5.1962], [2.7705, 5.3221], [2.5357, 5.4378], [2.2961, 5.5433], [2.0521, 5.6382], [1.8042, 5.7223], [1.5529, 5.7956], [1.2986, 5.8578], [1.0419, 5.9088], [0.7832, 5.9487], [0.5229, 5.9772], [0.2617, 5.9943], [0.0, 6.0], [-0.2617, 5.9943], [-0.5229, 5.9772], [-0.7832, 5.9487], [-1.0419, 5.9088], [-1.2986, 5.8578], [-1.5529, 5.7956], [-1.8042, 5.7223], [-2.0521, 5.6382], [-2.2961, 5.5433], [-2.5357, 5.4378], [-2.7705, 5.3221], [-3.0, 5.1962], [-2.9943, 4.9344], [-2.9772, 4.6732], [-2.9487, 4.413], [-2.9088, 4.1543], [-2.8578, 3.8975], [-2.7956, 3.6432], [-2.7223, 3.3919], [-2.6382, 3.144], [-2.5433, 2.9001], [-2.4378, 2.6604], [-2.3221, 2.4257], [-2.1962, 2.1962], [-2.0603, 1.9724], [-1.9149, 1.7547], [-1.7601, 1.5436], [-1.5963, 1.3394], [-1.4237, 1.1426], [-1.2426, 0.9535], [-1.0535, 0.7725], [-0.8567, 0.5999], [-0.6526, 0.436], [-0.4415, 0.2812], [-0.2238, 0.1358], [-0.0, 0.0], [0.2238, 0.1358], [0.4415, 0.2812], [0.6526, 0.436], [0.8567, 0.5999], [1.0535, 0.7725], [1.2426, 0.9535], [1.4237, 1.1426], [1.5963, 1.3394], [1.7601, 1.5436], [1.9149, 1.7547], [2.0603, 1.9724], [2.1962, 2.1962], [2.3221, 2.4257], [2.4378, 2.6604], [2.5433, 2.9001], [2.6382, 3.144], [2.7223, 3.3919], [2.7956, 3.6432], [2.8578, 3.8975], [2.9088, 4.1543], [2.9487, 4.413], [2.9772, 4.6732], [2.9943, 4.9344]], y: [-0.8, 0.8], collide: 1}   # the triangular eccentric
  - id: yoke
    shape: part
    pos: [0, 0, 0]
    mass: 0.8
    friction: 0.05
    color: "#b8ad97"
    pieces:
      - {kind: poly, points: [[-7.4, -0.91], [7.4, -0.91], [7.4, -0.01], [-7.4, -0.01]], y: [-0.9, 0.9], collide: 2}   # the yoke's lower face
      - {kind: poly, points: [[-7.4, 6.01], [7.4, 6.01], [7.4, 6.91], [-7.4, 6.91]], y: [-0.9, 0.9], collide: 2}   # its upper face
      - {kind: poly, points: [[-7.4, -0.91], [-6.6, -0.91], [-6.6, 6.91], [-7.4, 6.91]], y: [-0.9, 0.9]}   # its sides
      - {kind: poly, points: [[6.6, -0.91], [7.4, -0.91], [7.4, 6.91], [6.6, 6.91]], y: [-0.9, 0.9]}
      - {kind: rod, from: [0, 0, 6.91], to: [0, 0, 16.0], radius: 0.5}   # the rod above
      - {kind: rod, from: [0, 0, -0.91], to: [0, 0, -13], radius: 0.5}   # and below
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: poly, points: [[-1.2, -14], [1.2, -14], [0.8, 0], [-0.8, 0]], y: [1.8, 2.8]}   # the shaft's standard, behind
      - {kind: poly, points: [[-1.6, 8.0], [-0.65, 8.0], [-0.65, 9.5], [-1.6, 9.5]], y: [-1, 1]}   # the upper guide
      - {kind: poly, points: [[0.65, 8.0], [1.6, 8.0], [1.6, 9.5], [0.65, 9.5]], y: [-1, 1]}
      - {kind: poly, points: [[-1.6, -10], [-0.65, -10], [-0.65, -8.5], [-1.6, -8.5]], y: [-1, 1]}   # the lower guide
      - {kind: poly, points: [[0.65, -10], [1.6, -10], [1.6, -8.5], [0.65, -8.5]], y: [-1, 1]}
      - {kind: poly, points: [[-10, 8.0], [10, 8.0], [10, 9.5], [-10, 9.5]], y: [1.0, 1.8]}   # the cross-heads, behind
      - {kind: poly, points: [[-10, -10], [10, -10], [10, -8.5], [-10, -8.5]], y: [1.0, 1.8]}
      - {kind: poly, points: [[-10, -14], [-9, -14], [-9, 9.5], [-10, 9.5]], y: [1.0, 1.8]}   # the posts
      - {kind: poly, points: [[9, -14], [10, -14], [10, 9.5], [9, 9.5]], y: [1.0, 1.8]}
      - {kind: poly, points: [[-12, -15], [12, -15], [12, -14], [-12, -14]], y: [-3, 3], color: "#b9b09c"}
joints:
  - {id: j_s, type: hinge, body: shaft, axis: [0, 1, 0], damping: 0.002}   # the one driven joint; + : clockwise
  - {id: j_v, type: slide, body: yoke, axis: [0, 0, 1], range: [-7.5, 0.5], damping: 3.0}   # the yoke in its guides (its collars stop it 1.5 cm below its stroke); + : up
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_s, kind: velocity, rpm: 15, kv: 20.0, max_torque: 20}
checks:
  - {type: position, joint: j_v, min: -0.04, max: 0.04, settle_s: 3.7222, window_s: 0.5556}   # at rest above while the corner on the shaft is lowest
  - {type: position, joint: j_v, min: -6.04, max: -5.96, settle_s: 5.7222, window_s: 0.5556}   # at rest below, S down, while the arc about the shaft is lowest
  - {type: follow, out: j_v, in: j_s, expect: -0.0506, tol: 0.001, min_r2: 0.995, settle_s: 4.9444, window_s: 0.1111}   # mid-fall
  - {type: follow, out: j_v, in: j_s, expect: 0.0506, tol: 0.001, min_r2: 0.995, settle_s: 6.9444, window_s: 0.1111}   # mid-rise
  - {type: position, joint: j_v, min: -6.08, max: 0.08, settle_s: 0.5, window_s: 9}
  - {type: penetration, max: 0.001, settle_s: 0.5}
camera: {target: [0, 0, -1], position: [0, -80, 4], fov: 34}
display:
  output: j_v
  labels: {j_s: "Shaft (driver)", j_v: "Yoke"}
  proof: {label: "Triangle out of contact", sub: "the shaft turns but the yoke falls and stands"}

