# No. 391 (Brown 1868): "Reciprocating into rotary motion. The weighted racks, A, A1, are pivoted to the end of a piston-rod, and pins at the end of the said racks work in fixed guide-grooves, b, b, in such manner that one rack operates upon the cog-wheel in ascending and the other in descending, and so continuous rotary motion is produced. The elbow lever, C, and spring, d, are for carrying the pin of the right-hand rack over the upper angle in its guide-groove, b."
#
# Reading of the figure (cm, gravity on, Brown's elevation): the piston-rod's crosshead (the one driven joint, up and down 18 cm,
# 0.2 strokes a second) carries the racks A (left) and A1 (right) on pivots a. Each rack's weight hangs on an arm to the left of
# its pivot, so it leans the left rack off the cog-wheel (16 teeth, module 1.25) and the right one into it. A pin on an arm at each
# rack's top runs in a fixed groove b round a D-shaped island: the left pin goes up the outer side (rack off the wheel) and down
# the inner (in mesh), turning the wheel as the rack descends; the right pin goes up the inner side (in mesh) and down the outer,
# turning the wheel the same way as it ascends. Each groove's head slopes the pin across, and a spring catch (Brown's elbow lever C
# and spring d, here one at each groove's head) lets the pin over the upper angle and keeps it from going back.
# Kinematics: a whole stroke (18 cm) in mesh would turn the wheel 1.80 rad at its 10 cm pitch radius; each rack swings into
# mesh over the first ~2 cm of its working stroke, so the wheel turns about 1.6 rad a stroke, one way (the advance check).
# Generator: opencode-runs/batch14/gen391.py.
number: 391
slug: weighted-racks-reciprocating-to-rotary
name: Weighted racks turning a cog-wheel one way from a piston-rod
brown: "Reciprocating into rotary motion."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: true
  duration_s: 26
  floor: false
bodies:
  - id: crosshead
    shape: part
    pos: [0, 0, -38.0]
    density: 7800
    color: "#8f8a80"
    pieces:
      - {kind: poly, points: [[-13.1625, -39.4], [13.1625, -39.4], [13.1625, -38.6], [-13.1625, -38.6]], y: [1.0, 1.8], collide: 0}   # the crosshead
      - {kind: rod, from: [0, 1.4, -39.4], to: [0, 1.4, -47.0], radius: 0.8, collide: 0}   # the piston-rod
  - id: wheel
    shape: part
    pos: [0, 0, 0]
    density: 2000
    friction: 0.05
    color: "#d9cfb6"
    pieces:
      - {kind: wheel, center: [0, 0], teeth: 16, tooth: [[8.4375, -0.126], [11.25, 0.0393], [11.25, 0.0607], [8.4375, 0.226]], root: 8.4375, rim: 7.0, hub: 2.4, spokes: 0, y: [-0.8, 0.8], collide: 2}
      - {kind: disc, center: [0, 0], radius: 1.1, y: [-1.2, 1.2], collide: 0, color: "#55504a"}
  - id: rack_l
    shape: part
    mount: crosshead
    pos: [-12.3625, 0, -38.0]
    density: 2000
    friction: 0.05
    color: "#c9bea5"
    pieces:
      - {kind: poly, points: [[-13.2809, -37.1075], [-11.6934, -36.9081], [-17.3786, 8.3362], [-18.9661, 8.1367]], y: [-0.8, 0.8], collide: 0}   # the rack's bar
      - {kind: poly, points: [[-14.5142, -14.4595], [-11.887, -12.8086], [-11.9169, -12.5705], [-14.8709, -11.6209]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-15.0038, -10.5632], [-12.3766, -8.9123], [-12.4065, -8.6742], [-15.3605, -7.7246]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-15.4934, -6.6668], [-12.8662, -5.0159], [-12.8961, -4.7778], [-15.8501, -3.8282]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-15.983, -2.7705], [-13.3558, -1.1196], [-13.3857, -0.8815], [-16.3397, 0.0681]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-16.4726, 1.1259], [-13.8454, 2.7768], [-13.8753, 3.0149], [-16.8293, 3.9645]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-16.9622, 5.0222], [-14.335, 6.6731], [-14.3649, 6.9112], [-17.3189, 7.8608]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-17.4518, 8.9186], [-14.8246, 10.5695], [-14.8545, 10.8076], [-17.8085, 11.7572]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-17.9414, 12.8149], [-15.3142, 14.4658], [-15.3441, 14.7039], [-18.2981, 15.6535]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-18.431, 16.7113], [-15.8038, 18.3622], [-15.8337, 18.6003], [-18.7876, 19.5499]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-18.829, 7.0453], [-21.0118, 6.771], [-21.1489, 7.8624], [-18.9661, 8.1367]], y: [-0.8, 0.8], collide: 0}   # the arm to the pin
      - {kind: rod, from: [-21.0741, 0.8, 7.2671], to: [-21.0741, 3.0, 7.2671], radius: 0.5, collide: 1, capsule: true, color: "#55504a"}   # the pin
      - {kind: poly, points: [[-20.2502, -39.3943], [-12.3126, -38.3969], [-12.4124, -37.6031], [-20.35, -38.6005]], y: [-0.8, 0.8], collide: 0}   # the weight's arm
      - {kind: disc, center: [-20.3001, -38.9974], radius: 2.6, y: [-2.2, 2.2], collide: 0, color: "#8f8a80"}   # the weight
      - {kind: disc, center: [-12.3625, -38.0], radius: 0.9, y: [-1.0, 1.0], collide: 0, color: "#55504a"}   # the pivot a
  - id: rack_r
    shape: part
    mount: crosshead
    pos: [12.3625, 0, -38.0]
    density: 2000
    friction: 0.05
    color: "#c9bea5"
    pieces:
      - {kind: poly, points: [[13.1625, -37.0], [11.5625, -37.0], [11.5625, 8.6], [13.1625, 8.6]], y: [-0.8, 0.8], collide: 0}   # the rack's bar
      - {kind: poly, points: [[11.5625, -14.6749], [8.75, -13.3645], [8.75, -13.1245], [11.5625, -11.814]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, -10.7479], [8.75, -9.4375], [8.75, -9.1975], [11.5625, -7.887]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, -6.8209], [8.75, -5.5105], [8.75, -5.2705], [11.5625, -3.96]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, -2.8939], [8.75, -1.5835], [8.75, -1.3435], [11.5625, -0.033]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, 1.033], [8.75, 2.3435], [8.75, 2.5835], [11.5625, 3.8939]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, 4.96], [8.75, 6.2705], [8.75, 6.5105], [11.5625, 7.8209]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, 8.887], [8.75, 10.1975], [8.75, 10.4375], [11.5625, 11.7479]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, 12.814], [8.75, 14.1245], [8.75, 14.3645], [11.5625, 15.6749]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[11.5625, 16.741], [8.75, 18.0515], [8.75, 18.2915], [11.5625, 19.6019]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[13.1625, 7.5], [15.3625, 7.5], [15.3625, 8.6], [13.1625, 8.6]], y: [-0.8, 0.8], collide: 0}   # the arm to the pin
      - {kind: rod, from: [15.3625, 0.8, 8.0], to: [15.3625, 3.0, 8.0], radius: 0.5, collide: 1, capsule: true, color: "#55504a"}   # the pin
      - {kind: poly, points: [[4.3625, -38.4], [12.3625, -38.4], [12.3625, -37.6], [4.3625, -37.6]], y: [-0.8, 0.8], collide: 0}   # the weight's arm
      - {kind: disc, center: [4.3625, -38.0], radius: 2.6, y: [-2.2, 2.2], collide: 0, color: "#8f8a80"}   # the weight
      - {kind: disc, center: [12.3625, -38.0], radius: 0.9, y: [-1.0, 1.0], collide: 0, color: "#55504a"}   # the pivot a
  - id: catch_l
    shape: part
    pos: [-18.2183, 0, 7.1434]
    mass: 0.02
    friction: 0.05
    color: "#9a8f7a"
    pieces:
      - {kind: poly, points: [[-18.3983, 7.1434], [-18.0383, 7.1434], [-17.5183, 14.541], [-18.3983, 15.641]], y: [1.4, 2.6], collide: 2}
      - {kind: disc, center: [-18.2183, 7.1434], radius: 0.4, y: [1.2, 2.8000000000000003], collide: 0, color: "#55504a"}
  - id: catch_r
    shape: part
    pos: [18.7895, 0, 9.2398]
    mass: 0.02
    friction: 0.05
    color: "#9a8f7a"
    pieces:
      - {kind: poly, points: [[18.6095, 9.2398], [18.9695, 9.2398], [19.4895, 14.1892], [18.6095, 15.2892]], y: [1.4, 2.6], collide: 2}
      - {kind: disc, center: [18.7895, 9.2398], radius: 0.4, y: [1.2, 2.8000000000000003], collide: 0, color: "#55504a"}
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#bdb29a"
    pieces:
      - {kind: poly, points: [[-21.8241, -3.5869], [-14.6125, -2.4259], [-13.6125, -3.2778], [-22.8241, -4.7608]], y: [1.4, 2.6], collide: 2}   # the groove b's outer wall
      - {kind: poly, points: [[-14.6125, -2.4259], [-14.6125, 18.5445], [-13.6125, 20.2766], [-13.6125, -3.2778]], y: [1.4, 2.6], collide: 2}
      - {kind: poly, points: [[-14.6125, 18.5445], [-21.8241, 14.3809], [-22.8241, 14.9582], [-13.6125, 20.2766]], y: [1.4, 2.6], collide: 2}
      - {kind: poly, points: [[-21.8241, 14.3809], [-21.8241, -3.5869], [-22.8241, -4.7608], [-22.8241, 14.9582]], y: [1.4, 2.6], collide: 2}
      - {kind: poly, points: [[-20.3241, 2.5454], [-16.1125, 0.4135], [-16.1125, 6.6946], [-20.3241, 9.1262]], y: [1.4, 2.6], collide: 2}   # its island (the D)
      - {kind: poly, points: [[-22.8241, -4.7608], [-13.6125, -3.2778], [-13.6125, 20.2766], [-22.8241, 14.9582]], y: [2.6, 3.4000000000000004], collide: 0, color: "#cdc3ad"}   # the groove's back plate
      - {kind: poly, points: [[14.6125, -4.3199], [21.8241, -3.1589], [22.8241, -4.0108], [13.6125, -5.4937]], y: [1.4, 2.6], collide: 2}   # the groove b's outer wall
      - {kind: poly, points: [[21.8241, -3.1589], [21.8241, 17.8629], [22.8241, 19.595], [22.8241, -4.0108]], y: [1.4, 2.6], collide: 2}
      - {kind: poly, points: [[21.8241, 17.8629], [14.6125, 13.6993], [13.6125, 14.2766], [22.8241, 19.595]], y: [1.4, 2.6], collide: 2}
      - {kind: poly, points: [[14.6125, 13.6993], [14.6125, -4.3199], [13.6125, -5.4937], [13.6125, 14.2766]], y: [1.4, 2.6], collide: 2}
      - {kind: poly, points: [[16.1125, 1.8125], [20.3241, -0.3194], [20.3241, 9.3874], [16.1125, 11.0721]], y: [1.4, 2.6], collide: 2}   # its island (the D)
      - {kind: poly, points: [[13.6125, -5.4937], [22.8241, -4.0108], [22.8241, 19.595], [13.6125, 14.2766]], y: [2.6, 3.4000000000000004], collide: 0, color: "#cdc3ad"}   # the groove's back plate
      - {kind: rod, from: [0, 0.8, 0], to: [0, 3.4, 0], radius: 0.7, collide: 0, color: "#8f8a80"}   # the wheel's shaft
      - {kind: poly, points: [[-2.0, -51.0], [2.0, -51.0], [2.0, -49.0], [-2.0, -49.0]], y: [0.4, 2.4], collide: 0}   # the rod's guide
joints:
  - {id: j_c, type: slide, body: crosshead, axis: [0, 0, 1], damping: 0.5}   # the piston-rod (the one driven joint); + : up
  - {id: j_g, type: hinge, body: wheel, axis: [0, -1, 0], damping: 0.03}   # the cog-wheel; + : anticlockwise as drawn (Brown's arrows)
  - {id: j_l, type: hinge, body: rack_l, axis: [0, 1, 0], damping: 0.002}   # rack A on its pivot a
  - {id: j_r, type: hinge, body: rack_r, axis: [0, 1, 0], damping: 0.002}   # rack A1
  - {id: j_catch_l, type: hinge, body: catch_l, axis: [0, 1, 0], damping: 0.0005, stiffness: 0.02, springref: -0.15, range: [0, 1.3]}   # the catch's spring (d); its stop holds the pin from going back
  - {id: j_catch_r, type: hinge, body: catch_r, axis: [0, 1, 0], damping: 0.0005, stiffness: 0.02, springref: -0.15, range: [0, 1.3]}   # the catch's spring (d); its stop holds the pin from going back
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_c, kind: velocity, rpm: 0, swing: {amplitude: 0.09, hz: 0.2}, kv: 1000000.0, max_torque: 2000.0}
checks:
  - {type: advance, joint: j_g, beat: j_c, expect: 1.6, tol: 0.08, settle_s: 2.5, window_s: 20}   # the wheel's turn to each stroke of the rod (see the comment above)
  - {type: monotonic, joint: j_g, direction: 1, max_back: 0.25, settle_s: 0.0, window_s: 25}   # from rest it goes one way only (the teeth's play: under 0.25 rad back)
  - {type: turning, joint: j_g, direction: 1, min_mean: 0.45, min_fraction: 0.6, settle_s: 2.5, window_s: 20}
  - {type: penetration, max: 0.002, settle_s: 0.5}
camera: {target: [0, 0, -13.0], position: [0, -150.0, -11.0], fov: 44}
display:
  output: j_g
  labels: {j_c: "Piston-rod (driver)", j_g: "Cog-wheel", j_l: "Rack A", j_r: "Rack A1"}

