# No. 90 (Brown 1868): "A modification of the above; an elongated yoke being substituted for the circular
# strap, to obviate the necessity for any vibrating motion of the rod which works in fixed guides."
#
# Model (cm): the crank-shaft (the one driven joint, 30 turns a minute, clockwise in the view) carries the
# eccentric of No. 89, a 3.2 cm disc 1.5 cm off centre. Instead of a strap, the eccentric works between the two
# upright faces of an elongated yoke (10.4 cm tall, 0.2 mm clearance a side) by real contact; the
# yoke and its rod, all one piece, slide in fixed guides on both sides and never vibrate. The rod's travel is
# exactly harmonic, x = e (cos t - 1), 3 cm in all. Generator: opencode-runs/batch8/gen090.py.
number: 90
slug: eccentric-elongated-yoke
name: An eccentric working an elongated yoke and its rod
brown: "A modification of the above; an elongated yoke being substituted for the circular strap, to obviate the necessity for any vibrating motion of the rod which works in fixed guides."
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.8, color: "#8f8a80"}   # the crank-shaft
      - {kind: poly, points: [[4.7, 0.0], [4.6878, 0.2789], [4.6514, 0.5557], [4.591, 0.8282], [4.507, 1.0945], [4.4002, 1.3524], [4.2713, 1.6], [4.1213, 1.8354], [3.9513, 2.0569], [3.7627, 2.2627], [3.5569, 2.4513], [3.3354, 2.6213], [3.1, 2.7713], [2.8524, 2.9002], [2.5945, 3.007], [2.3282, 3.091], [2.0557, 3.1514], [1.7789, 3.1878], [1.5, 3.2], [1.2211, 3.1878], [0.9443, 3.1514], [0.6718, 3.091], [0.4055, 3.007], [0.1476, 2.9002], [-0.1, 2.7713], [-0.3354, 2.6213], [-0.5569, 2.4513], [-0.7627, 2.2627], [-0.9513, 2.0569], [-1.1213, 1.8354], [-1.2713, 1.6], [-1.4002, 1.3524], [-1.507, 1.0945], [-1.591, 0.8282], [-1.6514, 0.5557], [-1.6878, 0.2789], [-1.7, 0.0], [-1.6878, -0.2789], [-1.6514, -0.5557], [-1.591, -0.8282], [-1.507, -1.0945], [-1.4002, -1.3524], [-1.2713, -1.6], [-1.1213, -1.8354], [-0.9513, -2.0569], [-0.7627, -2.2627], [-0.5569, -2.4513], [-0.3354, -2.6213], [-0.1, -2.7713], [0.1476, -2.9002], [0.4055, -3.007], [0.6718, -3.091], [0.9443, -3.1514], [1.2211, -3.1878], [1.5, -3.2], [1.7789, -3.1878], [2.0557, -3.1514], [2.3282, -3.091], [2.5945, -3.007], [2.8524, -2.9002], [3.1, -2.7713], [3.3354, -2.6213], [3.5569, -2.4513], [3.7627, -2.2627], [3.9513, -2.0569], [4.1213, -1.8354], [4.2713, -1.6], [4.4002, -1.3524], [4.507, -1.0945], [4.591, -0.8282], [4.6514, -0.5557], [4.6878, -0.2789]], y: [-0.8, 0.8], collide: 1}   # the eccentric (a 72-gon)
  - id: yoke
    shape: part
    pos: [1.5, 0, 0]
    mass: 0.6
    friction: 0.05
    color: "#b8ad97"
    pieces:
      - {kind: poly, points: [[-2.62, -5.2], [-1.72, -5.2], [-1.72, 5.2], [-2.62, 5.2]], y: [-0.9, 0.9], collide: 2}   # the yoke's left face
      - {kind: poly, points: [[4.72, -5.2], [5.62, -5.2], [5.62, 5.2], [4.72, 5.2]], y: [-0.9, 0.9], collide: 2}   # its right face
      - {kind: poly, points: [[-2.62, 5.2], [5.62, 5.2], [5.62, 6.0], [-2.62, 6.0]], y: [-0.9, 0.9]}   # its top
      - {kind: poly, points: [[-2.62, -6.0], [5.62, -6.0], [5.62, -5.2], [-2.62, -5.2]], y: [-0.9, 0.9]}   # its bottom
      - {kind: rod, from: [-2.62, 0, 0], to: [-16, 0, 0], radius: 0.45}   # the rod, to the left
      - {kind: rod, from: [5.62, 0, 0], to: [20, 0, 0], radius: 0.45}   # and to the right
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: poly, points: [[-1.6, -10], [1.6, -10], [1.1, 0], [-1.1, 0]], y: [1.8, 2.8]}   # the shaft's standard, behind
      - {kind: poly, points: [[-14.0, 0.6], [-11.0, 0.6], [-11.0, 1.5], [-14.0, 1.5]], y: [-1, 1]}   # a fixed guide
      - {kind: poly, points: [[-14.0, -1.5], [-11.0, -1.5], [-11.0, -0.6], [-14.0, -0.6]], y: [-1, 1]}
      - {kind: poly, points: [[-13.0, -10], [-12.0, -10], [-12.0, -1.5], [-13.0, -1.5]], y: [1.0, 1.8]}   # its post, behind
      - {kind: poly, points: [[14.5, 0.6], [17.5, 0.6], [17.5, 1.5], [14.5, 1.5]], y: [-1, 1]}   # a fixed guide
      - {kind: poly, points: [[14.5, -1.5], [17.5, -1.5], [17.5, -0.6], [14.5, -0.6]], y: [-1, 1]}
      - {kind: poly, points: [[15.5, -10], [16.5, -10], [16.5, -1.5], [15.5, -1.5]], y: [1.0, 1.8]}   # its post, behind
      - {kind: poly, points: [[-15, -11], [19, -11], [19, -10], [-15, -10]], 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: [1, 0, 0], damping: 3.0}   # the rod in its guides (the valve's resistance, which keeps one face in contact each way); + : to the right
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_s, kind: velocity, rpm: 30, kv: 2.0, max_torque: 20}
checks:
  - {type: follow, out: j_v, in: j_s, expect: -0.015, tol: 0.0003, min_r2: 0.995, settle_s: 2.45, window_s: 0.1}   # mid-stroke: e a radian
  - {type: follow, out: j_v, in: j_s, expect: 0.015, tol: 0.0003, min_r2: 0.995, settle_s: 3.45, window_s: 0.1}   # ... and back
  - {type: position, joint: j_v, min: -3.08, max: 0.08, settle_s: 0.5, window_s: 9}   # the throw: twice the eccentricity
  - {type: penetration, max: 0.001, settle_s: 0.5}
camera: {target: [2, 0, -2], position: [2, -75, 6], fov: 34}
display:
  output: j_v
  labels: {j_s: "Crank-shaft (driver)", j_v: "Yoke and rod"}
  proof: {label: "Eccentric out of contact", sub: "the shaft turns but the yoke stands"}

