# No. 50 (Brown 1868): "Two kinds of universal joints." Brown's figure 50 is the double joint: each
# shaft ends in a loop (a yoke), and between them a middle link of two loops, each end joined to its
# shaft's loop by a cross whose arms turn in the eyes of both.
#
# Model (cm): A comes up from the left and B goes down to the right, each 30 deg from the middle link.
# The two yokes on the middle link lie in one plane (in phase), so the second joint undoes the first
# joint's unevenness: B turns exactly with A, while the middle link speeds and slows between
# cos 30 and 1/cos 30 of A's speed, twice a turn,
# and each cross rocks +-30 deg in its eyes. Every joint is a hinge (a shaft in its bearing, a
# cross arm in its eyes); B's yoke eyes are pins on the second cross's arm ends. A is the one driven
# shaft. Generated by batch7/gen050.py.
number: 50
slug: double-universal-joint
name: Universal joint (double)
brown: "Two kinds of universal joints."
units: cm
sim: {timestep: 0.0001, integrator: implicitfast, iterations: 50, duration_s: 8, floor: false}
bodies:
  - id: shaftA
    shape: part
    pos: [0, -4.0, 10.0]
    density: 7800
    color: "#d9cfb6"
    pieces:
      - {kind: rod, from: [0, -17.8564, 2.0], to: [0.0, -6.2517, 8.7], radius: 0.6, color: "#8f8a80"}
      - {kind: rod, from: [0.0, -5.2517, 6.9679], to: [0.0, -7.2517, 10.4321], radius: 0.35}
      - {kind: rod, from: [0.0, -7.2517, 10.4321], to: [0.0, -5.0, 11.7321], radius: 0.35}
      - {kind: rod, from: [0.0, -5.2517, 6.9679], to: [0.0, -3.0, 8.2679], radius: 0.35}
      - {kind: rod, from: [0.0, -5.12, 11.9399], to: [0.0, -2.88, 8.0601], radius: 0.25, color: "#8f8a80"}
  - id: cross1
    shape: part
    pos: [0, -4.0, 10.0]
    mount: shaftA
    density: 7800
    color: "#a39d90"
    pieces:
      - {kind: rod, from: [0.0, -2.95, 8.1813], to: [0.0, -5.05, 11.8187], radius: 0.3, color: "#a39d90"}
      - {kind: rod, from: [-2.1, -4.0, 10.0], to: [2.1, -4.0, 10.0], radius: 0.3, color: "#a39d90"}
  - id: middle
    shape: part
    pos: [0, -4.0, 10.0]
    mount: cross1
    density: 7800
    color: "#e2d8bf"
    pieces:
      - {kind: rod, from: [0.0, -1.4, 10.0], to: [0.0, 1.4, 10.0], radius: 0.6}
      - {kind: rod, from: [-2.0, -1.4, 10.0], to: [2.0, -1.4, 10.0], radius: 0.35}
      - {kind: rod, from: [2.0, -1.4, 10.0], to: [2.0, -4.0, 10.0], radius: 0.35}
      - {kind: rod, from: [-2.0, -1.4, 10.0], to: [-2.0, -4.0, 10.0], radius: 0.35}
      - {kind: rod, from: [2.24, -4.0, 10.0], to: [-2.24, -4.0, 10.0], radius: 0.25, color: "#8f8a80"}
      - {kind: rod, from: [-2.0, 1.4, 10.0], to: [2.0, 1.4, 10.0], radius: 0.35}
      - {kind: rod, from: [2.0, 1.4, 10.0], to: [2.0, 4.0, 10.0], radius: 0.35}
      - {kind: rod, from: [-2.0, 1.4, 10.0], to: [-2.0, 4.0, 10.0], radius: 0.35}
      - {kind: rod, from: [2.24, 4.0, 10.0], to: [-2.24, 4.0, 10.0], radius: 0.25, color: "#8f8a80"}
  - id: cross2
    shape: part
    pos: [0, 4.0, 10.0]
    mount: middle
    density: 7800
    color: "#a39d90"
    pieces:
      - {kind: rod, from: [-2.1, 4.0, 10.0], to: [2.1, 4.0, 10.0], radius: 0.3, color: "#a39d90"}
      - {kind: rod, from: [0.0, 5.05, 11.8187], to: [0.0, 2.95, 8.1813], radius: 0.3, color: "#a39d90"}
  - id: shaftB
    shape: part
    pos: [0, 4.0, 10.0]
    density: 7800
    color: "#e8dec6"
    pieces:
      - {kind: rod, from: [0.0, 6.2517, 8.7], to: [0, 17.8564, 2.0], radius: 0.6, color: "#8f8a80"}
      - {kind: rod, from: [0.0, 7.2517, 10.4321], to: [0.0, 5.2517, 6.9679], radius: 0.35}
      - {kind: rod, from: [0.0, 5.2517, 6.9679], to: [0.0, 3.0, 8.2679], radius: 0.35}
      - {kind: rod, from: [0.0, 7.2517, 10.4321], to: [0.0, 5.0, 11.7321], radius: 0.35}
      - {kind: rod, from: [0.0, 2.88, 8.0601], to: [0.0, 5.12, 11.9399], radius: 0.25, color: "#8f8a80"}
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: rod, from: [0, -14.3923, 4.0], to: [0, -14.3923, -1.0], radius: 0.5}
      - {kind: rod, from: [-1.2, -14.3923, 4.0], to: [1.2, -14.3923, 4.0], radius: 0.9, color: "#b9b09c"}
      - {kind: rod, from: [0, 14.3923, 4.0], to: [0, 14.3923, -1.0], radius: 0.5}
      - {kind: rod, from: [-1.2, 14.3923, 4.0], to: [1.2, 14.3923, 4.0], radius: 0.9, color: "#b9b09c"}
      - {kind: poly, points: [[-4, -2], [4, -2], [4, -1], [-4, -1]], y: [-17.39, 17.39], color: "#b9b09c"}
joints:
  - {id: j_A, type: hinge, body: shaftA, axis: [0, 0.866, 0.5], damping: 0.002}   # the driven shaft, in its bearing
  - {id: j_c1a, type: hinge, body: cross1, axis: [0.0, -0.5, 0.866], damping: 0.0005}   # the cross in A's eyes
  - {id: j_c1m, type: hinge, body: middle, axis: [1.0, 0, 0], damping: 0.0005}   # the middle link's eyes on the cross
  - {id: j_c2m, type: hinge, body: cross2, axis: [1.0, 0, 0], damping: 0.0005}   # the second cross in the middle link's other eyes
  - {id: j_B, type: hinge, body: shaftB, axis: [0, 0.866, -0.5], damping: 0.02}   # the driven-on shaft in its bearing, and its load
# B's yoke eyes on the arm ends of the second cross (two pins on one line: a hinge, closing the loop)
pins:
  - {id: eye1, a: cross2, b: shaftB, at: [0.0, 3.0, 8.2679]}
  - {id: eye2, a: cross2, b: shaftB, at: [0.0, 5.0, 11.7321]}
driver: {joint: j_A, kind: velocity, rpm: 30, kv: 2, max_torque: 5}
checks:
  # B turns exactly with A (the second joint undoes the first)
  - {type: ratio, out: j_B, in: j_A, expect: 1, tol: 0.003, settle_s: 1, window_s: 6}
  - {type: ratio_range, out: j_B, in: j_A, min: 0.99, max: 1.01, settle_s: 1, window_s: 6}
  # each cross rocks in its eyes by the angle between the shafts it joins (30 deg), turn after turn
  - {type: amplitude, joint: j_c1a, min: 0.5079, max: 0.5393, settle_s: 1, window_s: 6}
  - {type: amplitude, joint: j_c1m, min: 0.5079, max: 0.5393, settle_s: 1, window_s: 6}
camera: {target: [0.0, 0.0, 7.0], position: [55, -30, 30], fov: 30}
display:
  output: j_B
  labels: {j_A: "Shaft A (driver)", j_B: "Shaft B", j_c1a: "Cross in A's yoke", j_c1m: "Middle link"}
  proof: {label: "Yoke eyes off the cross", sub: "B's eyes no longer hold the cross: A turns, B stands"}
