# No. 138 (Brown 1868): "On turning the cam at the bottom a variable alternating rectilinear motion is imparted to the rod resting on it."
#
# Model (cm, gravity on): a three-lobed cam on a shaft (the one driven joint, 15 turns a minute, clockwise in the view), r = 4.8 + 1.2 cos 3(phi - 30 deg), drawn in a circle behind it as in the plate. The rod, in two guides above, rests on it by its weight,
# through a roller tip of 0.5 cm radius, and rises and falls 2.40 cm three times a turn, by real contact. Generator: opencode-runs/batch10/gen138.py.
number: 138
slug: three-lobed-cam-rod
name: A three-lobed cam lifting a rod
brown: "On turning the cam at the bottom a variable alternating rectilinear motion is imparted to the rod resting on it."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: true
  duration_s: 20.0
  floor: false
bodies:
  - id: cam
    shape: part
    pos: [0, 0, 0]
    mass: 1.0
    friction: 0.03
    color: "#d9cfb6"
    pieces:
      - {kind: rod, from: [0, -1.4, 0], to: [0, 3.6, 0], radius: 0.9, color: "#8f8a80"}   # the shaft, with its boss
      - {kind: disc, center: [0, 0], radius: 1.8, inner: 0.9, y: [-1.0, -0.8], collide: 0, color: "#b8ad97"}   # the boss ring
      - {kind: disc, center: [0, 0], radius: 7.0, inner: 0.0, y: [1.0, 1.4], collide: 0, color: "#cfc6b4"}   # the circle behind
      - {kind: poly, points: [[0, 0], [4.8, 0.0], [5.0911, 0.4454]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [5.0911, 0.4454], [5.318, 0.9377]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [5.318, 0.9377], [5.4561, 1.4619]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [5.4561, 1.4619], [5.4871, 1.9971]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [5.4871, 1.9971], [5.4008, 2.5184]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [5.4008, 2.5184], [5.1962, 3.0]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [5.1962, 3.0], [4.8814, 3.418]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [4.8814, 3.418], [4.4731, 3.7534]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [4.4731, 3.7534], [3.9941, 3.9941]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [3.9941, 3.9941], [3.4711, 4.1366]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [3.4711, 4.1366], [2.9313, 4.1863]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.9313, 4.1863], [2.4, 4.1569]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.4, 4.1569], [1.8973, 4.0688]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [1.8973, 4.0688], [1.4365, 3.9467]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [1.4365, 3.9467], [1.0227, 3.8168]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [1.0227, 3.8168], [0.6531, 3.7036]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [0.6531, 3.7036], [0.3173, 3.627]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [0.3173, 3.627], [0.0, 3.6]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [0.0, 3.6], [-0.3173, 3.627]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-0.3173, 3.627], [-0.6531, 3.7036]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-0.6531, 3.7036], [-1.0227, 3.8168]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-1.0227, 3.8168], [-1.4365, 3.9467]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-1.4365, 3.9467], [-1.8973, 4.0688]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-1.8973, 4.0688], [-2.4, 4.1569]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.4, 4.1569], [-2.9313, 4.1863]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.9313, 4.1863], [-3.4711, 4.1366]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-3.4711, 4.1366], [-3.9941, 3.9941]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-3.9941, 3.9941], [-4.4731, 3.7534]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-4.4731, 3.7534], [-4.8814, 3.418]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-4.8814, 3.418], [-5.1962, 3.0]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-5.1962, 3.0], [-5.4008, 2.5184]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-5.4008, 2.5184], [-5.4871, 1.9971]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-5.4871, 1.9971], [-5.4561, 1.4619]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-5.4561, 1.4619], [-5.318, 0.9377]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-5.318, 0.9377], [-5.0911, 0.4454]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-5.0911, 0.4454], [-4.8, 0.0]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-4.8, 0.0], [-4.4723, -0.3913]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-4.4723, -0.3913], [-4.1362, -0.7293]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-4.1362, -0.7293], [-3.8168, -1.0227]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-3.8168, -1.0227], [-3.534, -1.2863]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-3.534, -1.2863], [-3.2998, -1.5387]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-3.2998, -1.5387], [-3.1177, -1.8]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-3.1177, -1.8], [-2.9824, -2.0883]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.9824, -2.0883], [-2.8809, -2.4174]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.8809, -2.4174], [-2.7941, -2.7941]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.7941, -2.7941], [-2.6997, -3.2174]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.6997, -3.2174], [-2.575, -3.6775]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.575, -3.6775], [-2.4, -4.1569]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.4, -4.1569], [-2.1598, -4.6318]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-2.1598, -4.6318], [-1.8469, -5.0743]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-1.8469, -5.0743], [-1.4619, -5.4561]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-1.4619, -5.4561], [-1.014, -5.7505]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-1.014, -5.7505], [-0.5194, -5.9364]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-0.5194, -5.9364], [-0.0, -6.0]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [-0.0, -6.0], [0.5194, -5.9364]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [0.5194, -5.9364], [1.014, -5.7505]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [1.014, -5.7505], [1.4619, -5.4561]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [1.4619, -5.4561], [1.8469, -5.0743]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [1.8469, -5.0743], [2.1598, -4.6318]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.1598, -4.6318], [2.4, -4.1569]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.4, -4.1569], [2.575, -3.6775]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.575, -3.6775], [2.6997, -3.2174]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.6997, -3.2174], [2.7941, -2.7941]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.7941, -2.7941], [2.8809, -2.4174]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.8809, -2.4174], [2.9824, -2.0883]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [2.9824, -2.0883], [3.1177, -1.8]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [3.1177, -1.8], [3.2998, -1.5387]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [3.2998, -1.5387], [3.534, -1.2863]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [3.534, -1.2863], [3.8168, -1.0227]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [3.8168, -1.0227], [4.1362, -0.7293]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [4.1362, -0.7293], [4.4723, -0.3913]], y: [-0.8, 0.8], collide: 1}
      - {kind: poly, points: [[0, 0], [4.4723, -0.3913], [4.8, 0.0]], y: [-0.8, 0.8], collide: 1}
  - id: rod
    shape: part
    pos: [0, 0, 4.1]
    mass: 0.2
    friction: 0.03
    color: "#8f8a80"
    pieces:
      - {kind: rod, from: [0, -0.6, 4.1], to: [0, 0.6, 4.1], radius: 0.5, collide: 2, capsule: true}   # the rod's roller tip, on the cam
      - {kind: rod, from: [0, 0, 4.1], to: [0, 0, 32.1], radius: 0.4}   # the rod
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: poly, points: [[-1.2, -12], [1.2, -12], [0.9, 0], [-0.9, 0]], y: [3.2, 4.2]}   # the shaft's standard, behind
      - {kind: poly, points: [[-2.4, 11.1], [-0.7, 11.1], [-0.7, 12.9], [-2.4, 12.9]], y: [-1, 1]}   # the lower guide
      - {kind: poly, points: [[0.7, 11.1], [2.4, 11.1], [2.4, 12.9], [0.7, 12.9]], y: [-1, 1]}
      - {kind: poly, points: [[-2.4, 22.1], [-0.7, 22.1], [-0.7, 23.9], [-2.4, 23.9]], y: [-1, 1]}   # the upper guide
      - {kind: poly, points: [[0.7, 22.1], [2.4, 22.1], [2.4, 23.9], [0.7, 23.9]], y: [-1, 1]}
      - {kind: poly, points: [[2.4, 11.1], [3.4, 11.1], [3.4, 23.9], [2.4, 23.9]], y: [1.4, 2.4]}   # the post carrying the guides, behind
      - {kind: poly, points: [[-8, -13], [8, -13], [8, -12], [-8, -12]], y: [-3, 3], color: "#b9b09c"}
joints:
  - {id: j_s, type: hinge, body: cam, axis: [0, 1, 0], damping: 0.002}   # the one driven joint; + : clockwise
  - {id: j_x, type: slide, body: rod, axis: [0, 0, 1], range: [-1.5, 3.4], damping: 3.0}   # the rod in its guides; + : up
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_s, kind: velocity, rpm: 15.0, kv: 20.0, max_torque: 20.0}
checks:
  - {type: follow, out: j_x, in: j_s, expect: 0.0344, tol: 0.0017, min_r2: 0.98, settle_s: 8.2889, window_s: 0.0889}   # steepest rise, shaft 23.0..31.0 deg of turn 2
  - {type: follow, out: j_x, in: j_s, expect: -0.0344, tol: 0.0017, min_r2: 0.98, settle_s: 9.0222, window_s: 0.0889}   # steepest fall, shaft 89.0..97.0 deg of turn 2
  - {type: follow, out: j_x, in: j_s, expect: 0.0344, tol: 0.0017, min_r2: 0.98, settle_s: 13.6222, window_s: 0.0889}   # steepest rise, shaft 143.0..151.0 deg of turn 3
  - {type: follow, out: j_x, in: j_s, expect: -0.0344, tol: 0.0017, min_r2: 0.98, settle_s: 15.6889, window_s: 0.0889}   # steepest fall, shaft 329.0..337.0 deg of turn 3
  - {type: position, joint: j_x, min: -0.06, max: 2.46, settle_s: 1.0, window_s: 18.5}   # the stroke: 2.40 cm
  - {type: penetration, max: 0.001, settle_s: 0.5}
camera: {target: [0, 0, 7.0], position: [0, -92.0, 7.0], fov: 34}
display:
  output: j_x
  labels: {j_s: "Cam (driver)", j_x: "Rod"}
  proof: {label: "Cam out of contact", sub: "the shaft turns but the rod rests on its stop"}

