# No. 394 (Brown 1868): "C. Parsons's patent device for converting reciprocating motion into rotary, an endless rack provided with grooves on its side
# gearing with a pinion having two concentric flanges of different diameters. A substitute for crank in oscillating cylinder engine."
#
# Model (cm, gravity off: the engine lies on its side, as the rack's weight about the trunnions would otherwise stall it): the piston rod (the one
# driven joint) slides in an oscillating cylinder hung on trunnions 62 cm to the right, and carries the endless rack: 40 teeth inside a stadium
# (8 pitches of straight side, round ends of pitch radius 9.6). Steam is a double-acting push of 20 N (feet [j_x, j_x], each press-only)
# let in by the cylinder's own swing, as an oscillating engine's ports are: the push reverses as the cylinder tilts through the line of the pinion's centre
# (feet.timed on j_c, shape sign), so it changes over at each dead centre. The 12-tooth pinion on the fly-wheel shaft gears with the top side on one
# stroke and the bottom side on the other, and rolls round the round ends at the turns, the cylinder swinging to let the rack shift; so it turns one way.
# A flange on the pinion runs on the core of the rack's groove (a stadium of round ends 1.1) and keeps the pair in gear.
# Teeth and flange are real contact. Generator: opencode-runs/batch13/gen394.py.
number: 394
slug: parsons-endless-rack
name: Parsons's endless rack and pinion
brown: "C. Parsons's patent device for converting reciprocating motion into rotary, an endless rack provided with grooves on its side gearing with a pinion having two concentric flanges of different diameters. A substitute for crank in oscillating cylinder engine."
units: cm
sim: {timestep: 0.0002, integrator: implicitfast, iterations: 100, solver: PGS, multiccd: true, duration_s: 10, floor: false, gravity: 0}
bodies:
  - id: pinion
    shape: part
    pos: [0, 0, 0]
    density: 7800
    friction: 0.1
    color: "#d9cfb6"
    pieces:
      - {kind: disc, center: [0, 0], radius: 4.05, inner: 0.6, y: [-0.8, 0.8]}
      - {kind: poly, points: [[-0.5344, 4.053], [-2.1265, 3.4915], [-2.112, 4.9387], [-1.4535, 5.1709]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-2.4893, 3.2428], [-3.5873, 1.9605], [-4.2984, 3.2211], [-3.8443, 3.7514]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-3.7772, 1.5637], [-4.087, -0.0958], [-5.3331, 0.6403], [-5.2049, 1.3267]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-4.053, -0.5344], [-3.4915, -2.1265], [-4.9387, -2.112], [-5.1709, -1.4535]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-3.2428, -2.4893], [-1.9605, -3.5873], [-3.2211, -4.2984], [-3.7514, -3.8443]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[-1.5637, -3.7772], [0.0958, -4.087], [-0.6403, -5.3331], [-1.3267, -5.2049]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0.5344, -4.053], [2.1265, -3.4915], [2.112, -4.9387], [1.4535, -5.1709]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[2.4893, -3.2428], [3.5873, -1.9605], [4.2984, -3.2211], [3.8443, -3.7514]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[3.7772, -1.5637], [4.087, 0.0958], [5.3331, -0.6403], [5.2049, -1.3267]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[4.053, 0.5344], [3.4915, 2.1265], [4.9387, 2.112], [5.1709, 1.4535]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[3.2428, 2.4893], [1.9605, 3.5873], [3.2211, 4.2984], [3.7514, 3.8443]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[1.5637, 3.7772], [-0.0958, 4.087], [0.6403, 5.3331], [1.3267, 5.2049]], y: [-0.8, 0.8], collide: 1}
      - {kind: disc, center: [0, 0], radius: 3.7, y: [-2.0, -0.8], collide: 1, color: "#c4b89c"}   # the flange on the core
      - {kind: disc, center: [0, 0], radius: 5.96, y: [0.8, 1.4], color: "#c4b89c"}   # the larger flange, outside the rack's teeth (drawn)
      - {kind: rod, from: [0, -2.4, 0], to: [0, 7.0, 0], radius: 0.6, color: "#8f8a80"}   # the shaft
      - {kind: disc, center: [0, 0], radius: 11, inner: 8.8, y: [5.0, 8], density: 7800, color: "#b8ad97"}   # the fly-wheel, behind
  - id: cyl
    shape: part
    pos: [62.1855, 0, 0.0]
    mass: 3
    color: "#a89a7e"
    pieces:
      - {kind: poly, points: [[56.5508, -4.9497], [76.4911, -3.4059], [75.7964, 5.5672], [55.8561, 4.0234]], y: [-4.5, 4.5]}   # the oscillating cylinder
      - {kind: poly, points: [[54.9395, -3.57], [56.435, -3.4542], [55.9719, 2.5279], [54.4763, 2.4121]], y: [-4.5, 4.5], color: "#8f8a80"}   # its gland
  - id: rack
    shape: part
    pos: [0.3705, 0, -4.7857]
    mount: cyl
    mass: 1
    friction: 0.1
    color: "#b8ad97"
    pieces:
      - {kind: poly, points: [[-11.2719, 4.7441], [-9.6388, 4.8705], [-9.9817, 3.6404], [-10.7438, 3.5814]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-8.7661, 4.9381], [-7.1331, 5.0645], [-7.4759, 3.8344], [-8.238, 3.7754]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-6.2603, 5.1321], [-4.6273, 5.2585], [-4.9701, 4.0284], [-5.7322, 3.9694]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-3.7546, 5.3261], [-2.1215, 5.4525], [-2.4643, 4.2224], [-3.2265, 4.1634]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-1.2488, 5.5201], [0.3843, 5.6465], [0.0414, 4.4164], [-0.7207, 4.3574]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[1.257, 5.7141], [2.89, 5.8405], [2.5472, 4.6104], [1.7851, 4.5514]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[3.7628, 5.9081], [5.3958, 6.0345], [5.053, 4.8044], [4.2909, 4.7454]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[6.2686, 6.1021], [7.9016, 6.2285], [7.5588, 4.9984], [6.7966, 4.9394]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[8.7743, 6.2961], [10.4074, 6.4225], [10.0645, 5.1924], [9.3024, 5.1334]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[11.4968, 6.364], [13.1069, 6.0635], [12.4574, 4.964], [11.706, 5.1042]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[14.1441, 5.725], [15.6216, 5.018], [14.7096, 4.1241], [14.0201, 4.454]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[16.5359, 4.4226], [17.78, 3.3572], [16.6678, 2.7298], [16.0871, 3.227]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[18.509, 2.5455], [19.435, 1.1945], [18.1983, 0.8763], [17.7661, 1.5068]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[19.9291, 0.2217], [20.4739, -1.3229], [19.1969, -1.3102], [18.9427, -0.5893]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[20.6994, -2.3904], [20.8258, -4.0235], [19.5957, -3.6806], [19.5367, -2.9185]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[20.7673, -5.1129], [20.4668, -6.723], [19.3673, -6.0735], [19.5075, -5.3221]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[20.1283, -7.7602], [19.4213, -9.2377], [18.5274, -8.3257], [18.8573, -7.6362]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[18.8259, -10.152], [17.7605, -11.3961], [17.1331, -10.2838], [17.6303, -9.7032]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[16.9488, -12.1251], [15.5978, -13.0511], [15.2796, -11.8144], [15.9101, -11.3822]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[14.625, -13.5452], [13.0804, -14.09], [13.0931, -12.813], [13.814, -12.5588]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[12.0129, -14.3155], [10.3798, -14.4419], [10.7227, -13.2118], [11.4848, -13.1527]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[9.5071, -14.5095], [7.8741, -14.6359], [8.2169, -13.4057], [8.979, -13.3467]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[7.0013, -14.7034], [5.3683, -14.8299], [5.7111, -13.5997], [6.4732, -13.5407]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[4.4956, -14.8974], [2.8625, -15.0239], [3.2054, -13.7937], [3.9675, -13.7347]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[1.9898, -15.0914], [0.3567, -15.2179], [0.6996, -13.9877], [1.4617, -13.9287]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-0.516, -15.2854], [-2.149, -15.4119], [-1.8062, -14.1817], [-1.0441, -14.1227]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-3.0218, -15.4794], [-4.6548, -15.6059], [-4.312, -14.3757], [-3.5499, -14.3167]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-5.5275, -15.6734], [-7.1606, -15.7999], [-6.8177, -14.5697], [-6.0556, -14.5107]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-8.0333, -15.8674], [-9.6664, -15.9938], [-9.3235, -14.7637], [-8.5614, -14.7047]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-10.7558, -15.9354], [-12.3659, -15.6348], [-11.7164, -14.5353], [-10.965, -14.6756]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-13.4031, -15.2963], [-14.8806, -14.5893], [-13.9686, -13.6954], [-13.2791, -14.0254]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-15.7949, -13.9939], [-17.039, -12.9286], [-15.9267, -12.3012], [-15.3461, -12.7984]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-17.768, -12.1169], [-18.694, -10.7658], [-17.4573, -10.4477], [-17.0251, -11.0782]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-19.1881, -9.7931], [-19.7329, -8.2484], [-18.4559, -8.2612], [-18.2017, -8.9821]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-19.9584, -7.1809], [-20.0848, -5.5479], [-18.8547, -5.8907], [-18.7956, -6.6529]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-20.0263, -4.4584], [-19.7258, -2.8483], [-18.6263, -3.4979], [-18.7665, -4.2493]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-19.3873, -1.8111], [-18.6803, -0.3337], [-17.7863, -1.2456], [-18.1163, -1.9351]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-18.0849, 0.5806], [-17.0195, 1.8247], [-16.3921, 0.7125], [-16.8893, 0.1319]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-16.2078, 2.5537], [-14.8568, 3.4798], [-14.5386, 2.243], [-15.1691, 1.8109]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-13.884, 3.9738], [-12.3394, 4.5186], [-12.3521, 3.2417], [-13.073, 2.9874]], y: [-0.8, 0.8], collide: 2}
      - {kind: poly, points: [[-10.4554, 4.8073], [9.5908, 6.3593], [9.5137, 7.3563], [-10.5325, 5.8043]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[9.5908, 6.3593], [12.3019, 6.2137], [12.4854, 7.1968], [9.5137, 7.3563]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[12.3019, 6.2137], [14.8829, 5.3715], [15.3145, 6.2735], [12.4854, 7.1968]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[14.8829, 5.3715], [17.1579, 3.8899], [17.8084, 4.6495], [15.3145, 6.2735]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[17.1579, 3.8899], [18.972, 1.87], [19.7969, 2.4354], [17.8084, 4.6495]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[18.972, 1.87], [20.2015, -0.5506], [21.1446, -0.218], [19.7969, 2.4354]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[20.2015, -0.5506], [20.7626, -3.2069], [21.7596, -3.1297], [21.1446, -0.218]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[20.7626, -3.2069], [20.617, -5.918], [21.6001, -6.1015], [21.7596, -3.1297]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[20.617, -5.918], [19.7748, -8.499], [20.6768, -8.9306], [21.6001, -6.1015]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[19.7748, -8.499], [18.2932, -10.774], [19.0528, -11.4244], [20.6768, -8.9306]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[18.2932, -10.774], [16.2733, -12.5881], [16.8387, -13.413], [19.0528, -11.4244]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[16.2733, -12.5881], [13.8527, -13.8176], [14.1853, -14.7607], [16.8387, -13.413]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[13.8527, -13.8176], [11.1964, -14.3787], [11.2736, -15.3757], [14.1853, -14.7607]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-8.7727, -16.9276], [11.2736, -15.3757], [11.1964, -14.3787], [-8.8498, -15.9306]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-10.4554, 4.8073], [-13.1117, 4.2462], [-13.4443, 5.1893], [-10.5325, 5.8043]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-13.1117, 4.2462], [-15.5323, 3.0168], [-16.0977, 3.8416], [-13.4443, 5.1893]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-15.5323, 3.0168], [-17.5522, 1.2027], [-18.3118, 1.8531], [-16.0977, 3.8416]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-17.5522, 1.2027], [-19.0338, -1.0724], [-19.9358, -0.6407], [-18.3118, 1.8531]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-19.0338, -1.0724], [-19.876, -3.6534], [-20.859, -3.4699], [-19.9358, -0.6407]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-19.876, -3.6534], [-20.0216, -6.3644], [-21.0186, -6.4416], [-20.859, -3.4699]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-20.0216, -6.3644], [-19.4605, -9.0208], [-20.4036, -9.3534], [-21.0186, -6.4416]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-19.4605, -9.0208], [-18.231, -11.4414], [-19.0559, -12.0067], [-20.4036, -9.3534]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-18.231, -11.4414], [-16.4169, -13.4613], [-17.0673, -14.2208], [-19.0559, -12.0067]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-16.4169, -13.4613], [-14.1419, -14.9428], [-14.5735, -15.8449], [-17.0673, -14.2208]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-14.1419, -14.9428], [-11.5609, -15.7851], [-11.7444, -16.7681], [-14.5735, -15.8449]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[-11.5609, -15.7851], [-8.8498, -15.9306], [-8.7727, -16.9276], [-11.7444, -16.7681]], y: [-0.8, 1.6]}
      - {kind: poly, points: [[10.3087, -2.913], [10.5954, -2.9284], [10.8684, -3.0175], [11.1091, -3.1742], [11.3009, -3.3878], [11.431, -3.6438], [11.4903, -3.9248], [11.4749, -4.2115], [11.3858, -4.4845], [11.2291, -4.7252], [11.0155, -4.917], [10.7595, -5.0471], [10.4785, -5.1064], [-9.5677, -6.6584], [-9.8544, -6.643], [-10.1274, -6.5539], [-10.3681, -6.3972], [-10.5599, -6.1836], [-10.69, -5.9275], [-10.7493, -5.6466], [-10.7339, -5.3598], [-10.6448, -5.0868], [-10.4881, -4.8462], [-10.2745, -4.6543], [-10.0185, -4.5243], [-9.7375, -4.4649]], y: [-2.0, -0.8], collide: 2, color: "#a39d90"}   # the core of the groove, on which the flange runs
      - {kind: poly, points: [[-9.5986, -6.2596], [10.4476, -4.7076], [10.3396, -3.3118], [-9.7066, -4.8637]], y: [-0.8, 1.6], color: "#a39d90"}   # its web to the back plate (drawn)
      - {kind: poly, points: [[-20.1386, -17.8076], [22.6395, -14.4957], [20.8796, 8.2362], [-21.8985, 4.9244]], y: [1.6, 2.2], color: "#c9bfa9"}   # the back plate
      - {kind: rod, from: [21.4605, 0, -3.1529], to: [66.1736, 0, 0.3088], radius: 0.9, color: "#8f8a80"}   # the piston rod
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cdc0a4"
    pieces:
      - {kind: rod, from: [62.1855, -6.0, 0.0], to: [62.1855, 6.0, 0.0], radius: 1.0, color: "#6f6a60"}   # the trunnions
      - {kind: poly, points: [[60.1855, -14.0], [64.1855, -14.0], [64.1855, 0.0], [60.1855, 0.0]], y: [5.0, 7.0]}
      - {kind: poly, points: [[-2, -14], [2, -14], [2, 0], [-2, 0]], y: [7.0, 9.0]}   # the shaft's pedestal
joints:
  - {id: j_p, type: hinge, body: pinion, axis: [0, 1, 0], damping: 0.1}   # the pinion and fly-wheel
  - {id: j_c, type: hinge, body: cyl, axis: [0, 1, 0], damping: 0.05}   # the cylinder on its trunnions
  - {id: j_x, type: slide, body: rack, axis: [-0.997, 0, -0.0772], damping: 0.1}   # the piston rod and rack: the one driven joint; + : out of the cylinder (left)
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_x, kind: feet, feet: {joints: [j_x, j_x], sign: [1, -1], force: 20, timed: {joint: j_c, shape: sign, gain: 200, offset: 0.0772}}, max_torque: 200}
checks:
  - {type: turning, joint: j_p, direction: 1, min_mean: 5.0, min_fraction: 0.9, settle_s: 2.0, window_s: 6.0}   # the fly-wheel keeps turning one way: steam let in by the cylinder's own swing carries the rack round both ends
  - {type: monotonic, joint: j_p, direction: 1, max_back: 0.05, settle_s: 0.5, window_s: 7.5}   # never backs at a dead centre
  - {type: amplitude, joint: j_c, min: 0.07, max: 0.085, settle_s: 2.0, window_s: 6.0}   # the cylinder swings on its trunnions as the pinion goes from one side of the rack to the other
  - {type: penetration, max: 0.002, settle_s: 0.5}
camera: {target: [16, 0, -8], position: [16, -112, -8], fov: 34}
display:
  output: j_p
  labels: {j_x: "Piston rod and rack (driver)", j_p: "Pinion and fly-wheel", j_c: "Cylinder"}
