# No. 88 (Brown 1868): "Continuous rotary converted into intermittent rotary motion. The disk-wheel, B, carrying
# the stops, C, D, turns on a center eccentric to the cam, A. On continuous rotary motion being given to the cam, A,
# intermittent rotary motion is imparted to the wheel, B. The stops free themselves from the offset of the cam at
# every half-revolution, the wheel, B, remaining at rest until the cam has completed its revolution, when the same
# motion is repeated."
#
# Model (cm): the cam A (the one driven joint, 15 turns a minute, clockwise in the view) is a 2.4 cm disc
# with one offset standing out to 4.05 cm. The disk-wheel B turns on a stud 1.0 cm to the right of A's centre
# and carries two stops, C and D, half a turn apart at 4.0 cm from its own centre, so that the stops pass from
# 3.0 to 5.0 cm from A's centre. Only on A's side of B is a stop within the offset's reach: the offset
# meets the stop there by real contact and carries B round clockwise until, B having turned half a turn, the stop
# has moved out past the offset's end and frees itself. The other stop is then within reach, and B (whose stud has a
# little friction) rests until the offset comes round to it at the next revolution. Generator: opencode-runs/batch8/gen088.py.
number: 88
slug: intermittent-rotary-eccentric-stops
name: An intermittent half-turn from a cam and an eccentric wheel
brown: "Continuous rotary converted into intermittent rotary motion. The disk-wheel, B, carrying the stops, C, D, turns on a center eccentric to the cam, A. On continuous rotary motion being given to the cam, A, intermittent rotary motion is imparted to the wheel, B. The stops free themselves from the offset of the cam at every half-revolution, the wheel, B, remaining at rest until the cam has completed its revolution, when the same motion is repeated."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: true
  duration_s: 20
  floor: false
bodies:
  - id: cam_a
    shape: part
    pos: [0, 0, 0]
    mass: 0.5
    friction: 0.1
    color: "#d9cfb6"
    pieces:
      - {kind: disc, center: [0, 0], radius: 2.4, inner: 0.5, y: [-2.0, -0.6]}   # the cam A
      - {kind: poly, points: [[1.1539, -1.4251], [2.8775, -2.8714], [3.3275, -2.3352], [2.1824, -0.1995]], y: [-2.0, -0.6], collide: 1}   # its offset
      - {kind: rod, from: [0, -2.0, 0], to: [0, -4.4, 0], radius: 0.5, color: "#8f8a80"}   # its shaft, to the front
  - id: wheel_b
    shape: part
    pos: [1.0, 0, 0]
    mass: 0.6
    friction: 0.1
    color: "#b8ad97"
    pieces:
      - {kind: disc, center: [1.0, 0], radius: 5.6, inner: 0.6, y: [0.0, 0.6]}   # the disk-wheel B
      - {kind: rod, from: [-0.3681, 0.0, -3.7588], to: [-0.3681, -2.2, -3.7588], radius: 0.4, collide: 2, capsule: true, color: "#6b5a44"}   # the stop C
      - {kind: rod, from: [2.3681, 0.0, 3.7588], to: [2.3681, -2.2, 3.7588], radius: 0.4, collide: 2, capsule: true, color: "#6b5a44"}   # the stop D
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: rod, from: [1.0, 0.6, 0], to: [1.0, 2.4, 0], radius: 0.6, color: "#8f8a80"}   # B's stud
      - {kind: poly, points: [[0.0, -7.0], [2.0, -7.0], [1.7, 0], [0.30000000000000004, 0]], y: [1.6, 2.4]}   # its standard, behind
      - {kind: poly, points: [[-0.6, -7.0], [0.6, -7.0], [0.45, 0], [-0.45, 0]], y: [-5.2, -4.4]}   # A's standard, in front (slender, to show the cam)
      - {kind: poly, points: [[-7, -7.8], [9, -7.8], [9, -7.0], [-7, -7.0]], y: [-5.4, 2.6], color: "#b9b09c"}
joints:
  - {id: j_A, type: hinge, body: cam_a, axis: [0, 1, 0], damping: 0.002}   # the one driven joint; + : clockwise
  - {id: j_B, type: hinge, body: wheel_b, axis: [0, 1, 0], damping: 0.02, frictionloss: 0.01}   # + : clockwise
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_A, kind: velocity, rpm: 15.0, kv: 2.0, max_torque: 20}
checks:
  - {type: ratio, out: j_B, in: j_A, expect: 0.5, tol: 0.01, settle_s: 3.5, window_s: 12}   # half a turn of B for each turn of A, dwell to dwell
  - {type: position, joint: j_B, min: 3.10, max: 3.25, settle_s: 3.25, window_s: 1.2}   # at rest after the first half-turn, while A completes its turn
  - {type: position, joint: j_B, min: 6.24, max: 6.39, settle_s: 7.25, window_s: 1.2}   # ... after the second
  - {type: position, joint: j_B, min: 9.38, max: 9.53, settle_s: 11.25, window_s: 1.2}
  - {type: position, joint: j_B, min: 12.52, max: 12.67, settle_s: 15.25, window_s: 1.2}
  - {type: penetration, max: 0.001, settle_s: 0.5}
camera: {target: [0.5, 0, -1.5], position: [9, -54, 5], fov: 34}
display:
  output: j_B
  labels: {j_A: "Cam A (driver)", j_B: "Disk-wheel B"}
  proof: {label: "Offset out of contact", sub: "the cam turns but the wheel stands"}

