# No. 79 (Brown 1868): "Reciprocating rectilinear motion of the rod, B, produces a nearly continuous
# rotary movement of the ratchet-faced wheel, A, by the pawls attached to the extremities of the
# vibrating radial arms, C, C."
#
# Model (cm): A, a 30-tooth ratchet (tips r 5.0), turns clockwise on a fixed centre. The two radial arms
# C, C swing loose on A's axis, one 42 deg above and one below the horizontal. A link from
# each arm's extremity is pinned to the rod B, which slides to and fro 2.74 cm in its guide, worked
# by a crank and connecting-rod (the crank is the one driven joint, 30 turns a minute). Drawing B out
# pulls the upper arm down and the lower arm up; pushing it back does the reverse, so the arms swing
# oppositely, about 1.60 pitch each. Each arm carries a pawl on a pin at its extremity, sprung onto A's
# teeth: the upper pawl pushes a tooth while B goes out, the lower while B comes back, and each slides
# back over a tooth while the other drives. So A moves on both strokes, a tooth each: nearly
# continuous rotation, 2 teeth a crank turn. A's bearing friction holds it while a pawl slides back.
# Generator: opencode-runs/batch8/gen079.py.
number: 79
slug: rod-radial-arms-two-pawls
name: Nearly continuous rotation from a sliding rod by two radial arms
brown: "Reciprocating rectilinear motion of the rod, B, produces a nearly continuous rotary movement of the ratchet-faced wheel, A, by the pawls attached to the extremities of the vibrating radial arms, C, C."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: false
  duration_s: 13
  floor: false
bodies:
  - id: wheel_a
    shape: part
    pos: [0, 0, 0]
    friction: 0.1
    color: "#d9cfb6"
    pieces:
      - {kind: disc, center: [0, 0], radius: 4.3, inner: 0.6, y: [-0.5, 0.5]}
      - {kind: poly, points: [[3.2079, 2.7109], [3.819, 3.2273], [3.7015, 1.9847]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[3.7015, 1.9847], [4.4065, 2.3628], [4.0332, 1.1718]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[4.0332, 1.1718], [4.8015, 1.395], [4.1887, 0.3076]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[4.1887, 0.3076], [4.9866, 0.3662], [4.1611, -0.57]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[4.1611, -0.57], [4.9537, -0.6786], [3.9517, -1.4227]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[3.9517, -1.4227], [4.7044, -1.6937], [3.5695, -2.2132]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[3.5695, -2.2132], [4.2495, -2.6348], [3.0314, -2.907]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[3.0314, -2.907], [3.6088, -3.4607], [2.3608, -3.4737]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[2.3608, -3.4737], [2.8104, -4.1354], [1.5869, -3.8887]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[1.5869, -3.8887], [1.8892, -4.6294], [0.7438, -4.1336]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[0.7438, -4.1336], [0.8854, -4.921], [-0.1319, -4.1979]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-0.1319, -4.1979], [-0.1571, -4.9975], [-1.0018, -4.0788]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-1.0018, -4.0788], [-1.1927, -4.8557], [-1.828, -3.7813]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-1.828, -3.7813], [-2.1762, -4.5016], [-2.5742, -3.3187]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-2.5742, -3.3187], [-3.0645, -3.9508], [-3.2079, -2.7109]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-3.2079, -2.7109], [-3.819, -3.2273], [-3.7015, -1.9847]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-3.7015, -1.9847], [-4.4065, -2.3628], [-4.0332, -1.1718]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-4.0332, -1.1718], [-4.8015, -1.395], [-4.1887, -0.3076]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-4.1887, -0.3076], [-4.9866, -0.3662], [-4.1611, 0.57]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-4.1611, 0.57], [-4.9537, 0.6786], [-3.9517, 1.4227]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-3.9517, 1.4227], [-4.7044, 1.6937], [-3.5695, 2.2132]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-3.5695, 2.2132], [-4.2495, 2.6348], [-3.0314, 2.907]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-3.0314, 2.907], [-3.6088, 3.4607], [-2.3608, 3.4737]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-2.3608, 3.4737], [-2.8104, 4.1354], [-1.5869, 3.8887]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-1.5869, 3.8887], [-1.8892, 4.6294], [-0.7438, 4.1336]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[-0.7438, 4.1336], [-0.8854, 4.921], [0.1319, 4.1979]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[0.1319, 4.1979], [0.1571, 4.9975], [1.0018, 4.0788]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[1.0018, 4.0788], [1.1927, 4.8557], [1.828, 3.7813]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[1.828, 3.7813], [2.1762, 4.5016], [2.5742, 3.3187]], y: [-0.5, 0.5], collide: 1}
      - {kind: poly, points: [[2.5742, 3.3187], [3.0645, 3.9508], [3.2079, 2.7109]], y: [-0.5, 0.5], collide: 1}
  - id: arm_1
    shape: part
    pos: [0, 0, 0]
    color: "#b8ad97"
    pieces:
      - {kind: disc, center: [0, 0], radius: 1.1, inner: 0.6, y: [-1.2, -0.6]}
      - {kind: rod, from: [0, -0.8999999999999999, 0], to: [5.3506, -0.8999999999999999, 4.8177], radius: 0.35}
      - {kind: disc, center: [5.3506, 4.8177], radius: 0.55, y: [-1.2, -0.6]}
      - {kind: rod, from: [4.2424, -0.8999999999999999, 5.0559], to: [5.3506, -0.8999999999999999, 4.8177], radius: 0.25}
      - {kind: rod, from: [4.2424, -1.2, 5.0559], to: [4.2424, 0.5, 5.0559], radius: 0.18, color: "#8f8a80"}   # the pawl's pin
  - id: arm_2
    shape: part
    pos: [0, 0, 0]
    color: "#b8ad97"
    pieces:
      - {kind: disc, center: [0, 0], radius: 1.1, inner: 0.6, y: [-2.0, -1.4]}
      - {kind: rod, from: [0, -1.7, 0], to: [5.3506, -1.7, -4.8177], radius: 0.35}
      - {kind: disc, center: [5.3506, -4.8177], radius: 0.55, y: [-2.0, -1.4]}
      - {kind: rod, from: [5.4716, -1.7, -3.6907], to: [5.3506, -1.7, -4.8177], radius: 0.25}
      - {kind: rod, from: [5.4716, -2.0, -3.6907], to: [5.4716, 0.5, -3.6907], radius: 0.18, color: "#8f8a80"}   # the pawl's pin
  - id: pawl_1
    shape: part
    pos: [4.2424, 0, 5.0559]
    mount: arm_1
    friction: 0.1
    color: "#6b5a44"
    pieces:
      - {kind: rod, from: [4.2424, 0, 5.0559], to: [4.1136, 0, 2.375], radius: 0.15, capsule: true, collide: 2}
  - id: pawl_2
    shape: part
    pos: [5.4716, 0, -3.6907]
    mount: arm_2
    friction: 0.1
    color: "#6b5a44"
    pieces:
      - {kind: rod, from: [5.4716, 0, -3.6907], to: [2.792, 0, -3.8428], radius: 0.15, capsule: true, collide: 2}
  - id: link_1
    shape: part
    pos: [5.3506, 0, 4.8177]
    mount: arm_1
    color: "#a39d90"
    pieces:
      - {kind: rod, from: [5.3506, -2.2, 4.8177], to: [13.0, -2.2, 0], radius: 0.28}
      - {kind: disc, center: [5.3506, 4.8177], radius: 0.45, y: [-2.5, -1.9000000000000001]}
  - id: link_2
    shape: part
    pos: [5.3506, 0, -4.8177]
    mount: arm_2
    color: "#a39d90"
    pieces:
      - {kind: rod, from: [5.3506, -3.0, -4.8177], to: [13.0, -3.0, 0], radius: 0.28}
      - {kind: disc, center: [5.3506, -4.8177], radius: 0.45, y: [-3.3, -2.7]}
  - id: rod_b
    shape: part
    pos: [13.0, 0, 0]
    color: "#8f8a80"
    pieces:
      - {kind: disc, center: [13.0, 0], radius: 0.6, y: [-3.4, -1.8]}   # B's knuckle, the links' pin
      - {kind: rod, from: [13.0, -2.6, 0], to: [16.1, -2.6, 0], radius: 0.32}
      - {kind: disc, center: [15.5, 0], radius: 0.45, y: [-2.9, -2.3000000000000003]}
  - id: crank
    shape: part
    pos: [23.3815, 0, 0]
    color: "#a39d90"
    pieces:
      - {kind: disc, center: [23.3815, 0], radius: 2.0719, y: [-1.6, -1.0]}   # the crank, behind the connecting-rod
      - {kind: rod, from: [23.3815, -2.0, 1.3719], to: [23.3815, -1.0, 1.3719], radius: 0.22, color: "#8f8a80"}
  - id: conrod
    shape: part
    pos: [23.3815, 0, 1.3719]
    mount: crank
    color: "#b8ad97"
    pieces:
      - {kind: rod, from: [23.3815, -2.1, 1.3719], to: [15.5, -2.1, 0], radius: 0.25}
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: rod, from: [0, -2.2, 0], to: [0, 2.2, 0], radius: 0.6, color: "#8f8a80"}   # A's axle
      - {kind: poly, points: [[-1.2, -10], [1.2, -10], [0.9, 0], [-0.9, 0]], y: [1.2, 2.2]}   # A's standard, behind
      - {kind: poly, points: [[13.9, -10], [14.9, -10], [14.9, -0.6], [13.9, -0.6]], y: [-3.2, -2.9]}   # B's guide post
      - {kind: poly, points: [[13.9, 0.5], [14.9, 0.5], [14.9, 1.0], [13.9, 1.0]], y: [-3.2, -2.9]}
      - {kind: poly, points: [[22.8815, -10], [23.8815, -10], [23.8815, 0], [22.8815, 0]], y: [-0.8, -0.2]}   # the crank's standard
      - {kind: rod, from: [23.3815, -1.0, 0], to: [23.3815, -0.2, 0], radius: 0.35, color: "#8f8a80"}
      - {kind: poly, points: [[-8, -11], [27.3815, -11], [27.3815, -10], [-8, -10]], y: [-4, 3], color: "#b9b09c"}
joints:
  - {id: j_k, type: hinge, body: crank, axis: [0, -1, 0], damping: 0.0005}   # the one driven joint
  - {id: j_cr, type: hinge, body: conrod, axis: [0, 1, 0], damping: 0.0002}
  - {id: j_b, type: slide, body: rod_b, axis: [1, 0, 0], damping: 0.05}
  - {id: j_c1, type: hinge, body: arm_1, axis: [0, 1, 0], damping: 0.0005}   # + : clockwise
  - {id: j_c2, type: hinge, body: arm_2, axis: [0, 1, 0], damping: 0.0005}
  - {id: j_l1, type: hinge, body: link_1, axis: [0, 1, 0], damping: 0.0002}
  - {id: j_l2, type: hinge, body: link_2, axis: [0, 1, 0], damping: 0.0002}
  - {id: j_p1, type: hinge, body: pawl_1, axis: [0, 1, 0], damping: 0.0002, range: [-0.6, 0.6], stiffness: 0.01, springref: 0.25}   # sprung onto the teeth
  - {id: j_p2, type: hinge, body: pawl_2, axis: [0, 1, 0], damping: 0.0002, range: [-0.6, 0.6], stiffness: 0.01, springref: 0.25}
  - {id: j_a, type: hinge, body: wheel_a, axis: [0, 1, 0], damping: 0.002, frictionloss: 0.01}
pins:
  - {"id": "pin_b1", "a": "link_1", "b": "rod_b", "at": [13.0, -2.2, 0]}
  - {"id": "pin_b2", "a": "link_2", "b": "rod_b", "at": [13.0, -3.0, 0]}
  - {"id": "pin_r", "a": "conrod", "b": "rod_b", "at": [15.5, -2.1, 0]}
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_k, kind: velocity, rpm: 30.0, kv: 2.0, max_torque: 20}
checks:
  - {type: ratio, out: j_a, in: j_k, expect: 0.0667, tol: 0.001, settle_s: 3, window_s: 10}   # a tooth a stroke: 2 teeth a crank turn
  - {type: penetration, max: 0.001, settle_s: 0.5}
camera: {target: [11.6907, 0, -2], position: [11.6907, -60, 1], fov: 34}
display:
  output: j_a
  labels: {j_k: "Crank (driver)", j_b: "Rod B", j_c1: "Upper arm C", j_c2: "Lower arm C", j_a: "Ratchet-faced wheel A"}
  proof: {label: "Pawls out of contact", sub: "the arms vibrate but A never moves"}

