# No. 283 (Brown 1868): "By a vibratory motion of the handle, motion is communicated by the pinion to the racks. This is used in working small air pumps for scientific experiments."
#
# Model (cm, gravity on): a pinion (16 teeth, module 0.8, pitch radius 6.4) on a fixed shaft is rocked by its handle (the one driven joint, 0.8 rad either way at 0.35 Hz). It meshes with two upright racks, one each side,
# sliding in guides on the frame; each carries a piston-rod and piston working in an air-pump barrel below the base. Turning the pinion clockwise raises the left rack and lowers the right one, 6.4 cm to the radian each (5.1 cm either way).
# The racks are equal, so their weights balance through the pinion; the pumps' resistance is the slides' damping, and the pistons bottom in their barrels (6.32 cm from the middle). Generator: opencode-runs/batch12/gen283.py.
number: 283
slug: pinion-two-racks-air-pump
name: A rocking pinion working two racks for an air pump
brown: "By a vibratory motion of the handle, motion is communicated by the pinion to the racks. This is used in working small air pumps for scientific experiments."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: true
  duration_s: 10.0
  floor: false
bodies:
  - id: pinion
    shape: part
    pos: [0, 0, 0]
    mass: 0.3
    friction: 0.1
    color: "#d9cfb6"
    pieces:
      - {kind: disc, center: [0, 0], radius: 5.55, inner: 0.9, y: [-1.4, -0.2], collide: 0}
      - {kind: poly, points: [[-5.6, 0.8441], [-5.6, -0.8441], [-6.96, -0.3491], [-6.96, 0.3491]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-5.4967, -1.3632], [-4.8507, -2.9229], [-6.2966, -2.986], [-6.5638, -2.341]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-4.5567, -3.3629], [-3.3629, -4.5567], [-4.6746, -5.1683], [-5.1683, -4.6746]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-2.9229, -4.8507], [-1.3632, -5.4967], [-2.341, -6.5638], [-2.986, -6.2966]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-0.8441, -5.6], [0.8441, -5.6], [0.3491, -6.96], [-0.3491, -6.96]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[1.3632, -5.4967], [2.9229, -4.8507], [2.986, -6.2966], [2.341, -6.5638]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[3.3629, -4.5567], [4.5567, -3.3629], [5.1683, -4.6746], [4.6746, -5.1683]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[4.8507, -2.9229], [5.4967, -1.3632], [6.5638, -2.341], [6.2966, -2.986]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[5.6, -0.8441], [5.6, 0.8441], [6.96, 0.3491], [6.96, -0.3491]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[5.4967, 1.3632], [4.8507, 2.9229], [6.2966, 2.986], [6.5638, 2.341]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[4.5567, 3.3629], [3.3629, 4.5567], [4.6746, 5.1683], [5.1683, 4.6746]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[2.9229, 4.8507], [1.3632, 5.4967], [2.341, 6.5638], [2.986, 6.2966]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[0.8441, 5.6], [-0.8441, 5.6], [-0.3491, 6.96], [0.3491, 6.96]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-1.3632, 5.4967], [-2.9229, 4.8507], [-2.986, 6.2966], [-2.341, 6.5638]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-3.3629, 4.5567], [-4.5567, 3.3629], [-5.1683, 4.6746], [-4.6746, 5.1683]], y: [-1.4, -0.2], collide: 1}
      - {kind: poly, points: [[-4.8507, 2.9229], [-5.4967, 1.3632], [-6.5638, 2.341], [-6.2966, 2.986]], y: [-1.4, -0.2], collide: 1}
      - {kind: disc, center: [0, 0], radius: 2.0, y: [-2.4, -1.4], collide: 0, color: "#b8ad97"}   # the boss
      - {kind: rod, from: [0, -2.0, 0], to: [-3.5, -2.0, 8.9], radius: 0.45, collide: 0, color: "#8f8a80"}   # the handle
      - {kind: rod, from: [-3.5, -2.0, 8.9], to: [-6.5, -2.0, 12.4], radius: 0.45, collide: 0, color: "#8f8a80"}
      - {kind: rod, from: [-6.5, -3.6, 12.4], to: [-6.5, -2.0, 12.4], radius: 0.8, collide: 0, color: "#5f5a52"}   # its knob
  - id: rack_l
    shape: part
    pos: [-7.9, 0, 0]
    mass: 0.3
    friction: 0.1
    color: "#b8ad97"
    pieces:
      - {kind: poly, points: [[-8.6, -15.0796], [-7.2, -15.0796], [-7.2, 15.0796], [-8.6, 15.0796]], y: [-1.4, -0.2], collide: 0}   # the bar behind the teeth
      - {kind: disc, center: [-7.9, 15.0796], radius: 0.7, y: [-1.4, -0.2], collide: 0}
      - {kind: poly, points: [[-7.2, -14.642], [-7.2, -13.004], [-6.0, -13.4408], [-6.0, -14.2052]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, -12.1287], [-7.2, -10.4908], [-6.0, -10.9275], [-6.0, -11.6919]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, -9.6154], [-7.2, -7.9775], [-6.0, -8.4143], [-6.0, -9.1787]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, -7.1021], [-7.2, -5.4642], [-6.0, -5.901], [-6.0, -6.6654]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, -4.5889], [-7.2, -2.9509], [-6.0, -3.3877], [-6.0, -4.1521]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, -2.0756], [-7.2, -0.4377], [-6.0, -0.8744], [-6.0, -1.6388]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, 0.4377], [-7.2, 2.0756], [-6.0, 1.6388], [-6.0, 0.8744]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, 2.9509], [-7.2, 4.5889], [-6.0, 4.1521], [-6.0, 3.3877]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, 5.4642], [-7.2, 7.1021], [-6.0, 6.6654], [-6.0, 5.901]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, 7.9775], [-7.2, 9.6154], [-6.0, 9.1787], [-6.0, 8.4143]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, 10.4908], [-7.2, 12.1287], [-6.0, 11.6919], [-6.0, 10.9275]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[-7.2, 13.004], [-7.2, 14.642], [-6.0, 14.2052], [-6.0, 13.4408]], y: [-1.4, -0.2], collide: 2}
      - {kind: rod, from: [-7.9, -0.8, -15.0796], to: [-7.9, -0.8, -27.5996], radius: 0.35, collide: 0, color: "#8f8a80"}   # the piston-rod
      - {kind: poly, points: [[-9.8, -28.5996], [-6.0, -28.5996], [-6.0, -27.5996], [-9.8, -27.5996]], y: [-2.6, 1.0], collide: 0, color: "#6f6a60"}   # the piston, in its barrel
  - id: rack_r
    shape: part
    pos: [7.9, 0, 0]
    mass: 0.3
    friction: 0.1
    color: "#b8ad97"
    pieces:
      - {kind: poly, points: [[7.2, -15.0796], [8.6, -15.0796], [8.6, 15.0796], [7.2, 15.0796]], y: [-1.4, -0.2], collide: 0}   # the bar behind the teeth
      - {kind: disc, center: [7.9, 15.0796], radius: 0.7, y: [-1.4, -0.2], collide: 0}
      - {kind: poly, points: [[7.2, -14.642], [7.2, -13.004], [6.0, -13.4408], [6.0, -14.2052]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, -12.1287], [7.2, -10.4908], [6.0, -10.9275], [6.0, -11.6919]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, -9.6154], [7.2, -7.9775], [6.0, -8.4143], [6.0, -9.1787]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, -7.1021], [7.2, -5.4642], [6.0, -5.901], [6.0, -6.6654]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, -4.5889], [7.2, -2.9509], [6.0, -3.3877], [6.0, -4.1521]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, -2.0756], [7.2, -0.4377], [6.0, -0.8744], [6.0, -1.6388]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, 0.4377], [7.2, 2.0756], [6.0, 1.6388], [6.0, 0.8744]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, 2.9509], [7.2, 4.5889], [6.0, 4.1521], [6.0, 3.3877]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, 5.4642], [7.2, 7.1021], [6.0, 6.6654], [6.0, 5.901]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, 7.9775], [7.2, 9.6154], [6.0, 9.1787], [6.0, 8.4143]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, 10.4908], [7.2, 12.1287], [6.0, 11.6919], [6.0, 10.9275]], y: [-1.4, -0.2], collide: 2}
      - {kind: poly, points: [[7.2, 13.004], [7.2, 14.642], [6.0, 14.2052], [6.0, 13.4408]], y: [-1.4, -0.2], collide: 2}
      - {kind: rod, from: [7.9, -0.8, -15.0796], to: [7.9, -0.8, -27.5996], radius: 0.35, collide: 0, color: "#8f8a80"}   # the piston-rod
      - {kind: poly, points: [[6.0, -28.5996], [9.8, -28.5996], [9.8, -27.5996], [6.0, -27.5996]], y: [-2.6, 1.0], collide: 0, color: "#6f6a60"}   # the piston, in its barrel
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: rod, from: [0, -0.2, 0], to: [0, 2.8, 0], radius: 0.9, collide: 0, color: "#8f8a80"}   # the pinion's shaft
      - {kind: poly, points: [[-1.4, -22.5996], [1.4, -22.5996], [1.0, 0], [-1.0, 0]], y: [2.0, 3.0], collide: 0}   # its standard behind
      - {kind: poly, points: [[-9.7, 3.2], [-6.1, 3.2], [-6.1, 7.6], [-9.7, 7.6]], y: [-2.2, 1.0], collide: 0, color: "#b9b09c"}   # a rack's guide
      - {kind: poly, points: [[6.1, 3.2], [9.7, 3.2], [9.7, 7.6], [6.1, 7.6]], y: [-2.2, 1.0], collide: 0, color: "#b9b09c"}   # a rack's guide
      - {kind: rod, from: [-13.1, 1.6, -22.5996], to: [-13.1, 1.6, 8.6], radius: 1.1, collide: 0}
      - {kind: rod, from: [13.1, 1.6, -22.5996], to: [13.1, 1.6, 8.6], radius: 1.1, collide: 0}
      - {kind: poly, points: [[-14.9, 3.2], [-9.7, 3.2], [-9.7, 7.6], [-14.9, 7.6]], y: [-1.0, 1.0], collide: 0, color: "#b9b09c"}   # the brackets holding the guides
      - {kind: poly, points: [[9.7, 3.2], [14.9, 3.2], [14.9, 7.6], [9.7, 7.6]], y: [-1.0, 1.0], collide: 0, color: "#b9b09c"}
      - {kind: poly, points: [[-17.1, -23.7996], [17.1, -23.7996], [17.1, -22.5996], [-17.1, -22.5996]], y: [-3.5, 3.5], collide: 0, color: "#b9b09c"}   # the base plate
      - {kind: poly, points: [[-10.2, -34.5996], [-5.6, -34.5996], [-5.6, -23.7996], [-10.2, -23.7996]], y: [-2.8, 1.2], collide: 0, color: "#a39a86"}   # an air-pump barrel
      - {kind: poly, points: [[5.6, -34.5996], [10.2, -34.5996], [10.2, -23.7996], [5.6, -23.7996]], y: [-2.8, 1.2], collide: 0, color: "#a39a86"}   # an air-pump barrel
joints:
  - {id: j_p, type: hinge, body: pinion, axis: [0, 1, 0], damping: 0.002}   # the one driven joint, the handle; + : clockwise
  - {id: j_l, type: slide, body: rack_l, axis: [0, 0, 1], range: [-6.32, 6.32], damping: 3.0}   # the left rack and its piston; + : up
  - {id: j_r, type: slide, body: rack_r, axis: [0, 0, 1], range: [-6.32, 6.32], damping: 3.0}   # the right rack; + : up
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_p, kind: velocity, rpm: 0, swing: {amplitude: 0.8, hz: 0.35}, kv: 20.0, max_torque: 10}
checks:
  - {type: follow, out: j_l, in: j_p, expect: 0.064, tol: 0.0032, min_r2: 0.995, settle_s: 0.5, window_s: 8.0}   # the left rack rises as the pinion turns clockwise
  - {type: follow, out: j_r, in: j_p, expect: -0.064, tol: 0.0032, min_r2: 0.995, settle_s: 0.5, window_s: 8.0}   # and the right one falls
  - {type: amplitude, joint: j_l, min: 0.0461, max: 0.0589, settle_s: 0.5, window_s: 9}
camera: {target: [0, 0, -20.7], position: [0, -160.0, -20.7], fov: 34}
display:
  output: j_l
  labels: {j_p: "Handle and pinion (driver)", j_l: "Left rack", j_r: "Right rack"}
  proof: {label: "Pinion out of contact", sub: "the handle rocks but the racks stand"}

