# No. 150 (Brown 1868): "A valve motion for working steam expansively. A series of cams of varying throw movable lengthwise on a shaft, so that either can act on a lever to which the valve-rod is connected."
#
# Model (cm, gravity on): the shaft (the one driven joint, 30 turns a minute) carries three eccentric cams of throw 2.2, 1.5 and 0.8 cm side by side and is slid lengthwise by the hand (the hand schedule: a spring-held carriage moved at 7 s and 14 s) so that each cam in turn comes under the lever's finger. The lever rests on the cam by its own weight
# (real contact) and, by a link pinned 12 cm from its pivot, works the valve-rod in its guides, whose stroke follows the throw of the cam in action. Generator: opencode-runs/batch10/gen150.py.
number: 150
slug: valve-motion-expansive-steam
name: A valve motion for working steam expansively
brown: "A valve motion for working steam expansively. A series of cams of varying throw movable lengthwise on a shaft, so that either can act on a lever to which the valve-rod is connected."
units: cm
sim:
  timestep: 0.0002
  integrator: implicitfast
  iterations: 100
  solver: PGS
  multiccd: true
  duration_s: 22.0
  floor: false
bodies:
  - id: carriage
    shape: part
    pos: [0, 0, 0]
    mass: 1.0
    color: "#8f8a80"
    pieces:
      - {kind: rod, from: [0, -2.6, 0], to: [0, 7.4, 0], radius: 1.2, color: "#8f8a80"}   # the shaft
  - id: cams
    shape: part
    pos: [0, 0, 0]
    mount: carriage
    mass: 20.0
    friction: 0.03
    color: "#d9cfb6"
    pieces:
      - {kind: loft, a: [[6.7, -1.9, 0.0], [6.6316, -1.9, 0.7814], [6.4286, -1.9, 1.5391], [6.0971, -1.9, 2.25], [5.6472, -1.9, 2.8925], [5.0925, -1.9, 3.4472], [4.45, -1.9, 3.8971], [3.7391, -1.9, 4.2286], [2.9814, -1.9, 4.4316], [2.2, -1.9, 4.5], [1.4186, -1.9, 4.4316], [0.6609, -1.9, 4.2286], [-0.05, -1.9, 3.8971], [-0.6925, -1.9, 3.4472], [-1.2472, -1.9, 2.8925], [-1.6971, -1.9, 2.25], [-2.0286, -1.9, 1.5391], [-2.2316, -1.9, 0.7814], [-2.3, -1.9, 0.0], [-2.2316, -1.9, -0.7814], [-2.0286, -1.9, -1.5391], [-1.6971, -1.9, -2.25], [-1.2472, -1.9, -2.8925], [-0.6925, -1.9, -3.4472], [-0.05, -1.9, -3.8971], [0.6609, -1.9, -4.2286], [1.4186, -1.9, -4.4316], [2.2, -1.9, -4.5], [2.9814, -1.9, -4.4316], [3.7391, -1.9, -4.2286], [4.45, -1.9, -3.8971], [5.0925, -1.9, -3.4472], [5.6472, -1.9, -2.8925], [6.0971, -1.9, -2.25], [6.4286, -1.9, -1.5391], [6.6316, -1.9, -0.7814]], b: [[6.7, -0.3, 0.0], [6.6316, -0.3, 0.7814], [6.4286, -0.3, 1.5391], [6.0971, -0.3, 2.25], [5.6472, -0.3, 2.8925], [5.0925, -0.3, 3.4472], [4.45, -0.3, 3.8971], [3.7391, -0.3, 4.2286], [2.9814, -0.3, 4.4316], [2.2, -0.3, 4.5], [1.4186, -0.3, 4.4316], [0.6609, -0.3, 4.2286], [-0.05, -0.3, 3.8971], [-0.6925, -0.3, 3.4472], [-1.2472, -0.3, 2.8925], [-1.6971, -0.3, 2.25], [-2.0286, -0.3, 1.5391], [-2.2316, -0.3, 0.7814], [-2.3, -0.3, 0.0], [-2.2316, -0.3, -0.7814], [-2.0286, -0.3, -1.5391], [-1.6971, -0.3, -2.25], [-1.2472, -0.3, -2.8925], [-0.6925, -0.3, -3.4472], [-0.05, -0.3, -3.8971], [0.6609, -0.3, -4.2286], [1.4186, -0.3, -4.4316], [2.2, -0.3, -4.5], [2.9814, -0.3, -4.4316], [3.7391, -0.3, -4.2286], [4.45, -0.3, -3.8971], [5.0925, -0.3, -3.4472], [5.6472, -0.3, -2.8925], [6.0971, -0.3, -2.25], [6.4286, -0.3, -1.5391], [6.6316, -0.3, -0.7814]], collide: 1, color: "#e2d9c0"}
      - {kind: loft, a: [[6.7, -0.3, 0.0], [6.6316, -0.3, 0.7814], [6.4286, -0.3, 1.5391], [6.0971, -0.3, 2.25], [5.6472, -0.3, 2.8925], [5.0925, -0.3, 3.4472], [4.45, -0.3, 3.8971], [3.7391, -0.3, 4.2286], [2.9814, -0.3, 4.4316], [2.2, -0.3, 4.5], [1.4186, -0.3, 4.4316], [0.6609, -0.3, 4.2286], [-0.05, -0.3, 3.8971], [-0.6925, -0.3, 3.4472], [-1.2472, -0.3, 2.8925], [-1.6971, -0.3, 2.25], [-2.0286, -0.3, 1.5391], [-2.2316, -0.3, 0.7814], [-2.3, -0.3, 0.0], [-2.2316, -0.3, -0.7814], [-2.0286, -0.3, -1.5391], [-1.6971, -0.3, -2.25], [-1.2472, -0.3, -2.8925], [-0.6925, -0.3, -3.4472], [-0.05, -0.3, -3.8971], [0.6609, -0.3, -4.2286], [1.4186, -0.3, -4.4316], [2.2, -0.3, -4.5], [2.9814, -0.3, -4.4316], [3.7391, -0.3, -4.2286], [4.45, -0.3, -3.8971], [5.0925, -0.3, -3.4472], [5.6472, -0.3, -2.8925], [6.0971, -0.3, -2.25], [6.4286, -0.3, -1.5391], [6.6316, -0.3, -0.7814]], b: [[6.0, 1.1, 0.0], [5.9316, 1.1, 0.7814], [5.7286, 1.1, 1.5391], [5.3971, 1.1, 2.25], [4.9472, 1.1, 2.8925], [4.3925, 1.1, 3.4472], [3.75, 1.1, 3.8971], [3.0391, 1.1, 4.2286], [2.2814, 1.1, 4.4316], [1.5, 1.1, 4.5], [0.7186, 1.1, 4.4316], [-0.0391, 1.1, 4.2286], [-0.75, 1.1, 3.8971], [-1.3925, 1.1, 3.4472], [-1.9472, 1.1, 2.8925], [-2.3971, 1.1, 2.25], [-2.7286, 1.1, 1.5391], [-2.9316, 1.1, 0.7814], [-3.0, 1.1, 0.0], [-2.9316, 1.1, -0.7814], [-2.7286, 1.1, -1.5391], [-2.3971, 1.1, -2.25], [-1.9472, 1.1, -2.8925], [-1.3925, 1.1, -3.4472], [-0.75, 1.1, -3.8971], [-0.0391, 1.1, -4.2286], [0.7186, 1.1, -4.4316], [1.5, 1.1, -4.5], [2.2814, 1.1, -4.4316], [3.0391, 1.1, -4.2286], [3.75, 1.1, -3.8971], [4.3925, 1.1, -3.4472], [4.9472, 1.1, -2.8925], [5.3971, 1.1, -2.25], [5.7286, 1.1, -1.5391], [5.9316, 1.1, -0.7814]], collide: 1, color: "#bfb394"}   # the ramp to the next cam
      - {kind: loft, a: [[6.0, 1.1, 0.0], [5.9316, 1.1, 0.7814], [5.7286, 1.1, 1.5391], [5.3971, 1.1, 2.25], [4.9472, 1.1, 2.8925], [4.3925, 1.1, 3.4472], [3.75, 1.1, 3.8971], [3.0391, 1.1, 4.2286], [2.2814, 1.1, 4.4316], [1.5, 1.1, 4.5], [0.7186, 1.1, 4.4316], [-0.0391, 1.1, 4.2286], [-0.75, 1.1, 3.8971], [-1.3925, 1.1, 3.4472], [-1.9472, 1.1, 2.8925], [-2.3971, 1.1, 2.25], [-2.7286, 1.1, 1.5391], [-2.9316, 1.1, 0.7814], [-3.0, 1.1, 0.0], [-2.9316, 1.1, -0.7814], [-2.7286, 1.1, -1.5391], [-2.3971, 1.1, -2.25], [-1.9472, 1.1, -2.8925], [-1.3925, 1.1, -3.4472], [-0.75, 1.1, -3.8971], [-0.0391, 1.1, -4.2286], [0.7186, 1.1, -4.4316], [1.5, 1.1, -4.5], [2.2814, 1.1, -4.4316], [3.0391, 1.1, -4.2286], [3.75, 1.1, -3.8971], [4.3925, 1.1, -3.4472], [4.9472, 1.1, -2.8925], [5.3971, 1.1, -2.25], [5.7286, 1.1, -1.5391], [5.9316, 1.1, -0.7814]], b: [[6.0, 2.7, 0.0], [5.9316, 2.7, 0.7814], [5.7286, 2.7, 1.5391], [5.3971, 2.7, 2.25], [4.9472, 2.7, 2.8925], [4.3925, 2.7, 3.4472], [3.75, 2.7, 3.8971], [3.0391, 2.7, 4.2286], [2.2814, 2.7, 4.4316], [1.5, 2.7, 4.5], [0.7186, 2.7, 4.4316], [-0.0391, 2.7, 4.2286], [-0.75, 2.7, 3.8971], [-1.3925, 2.7, 3.4472], [-1.9472, 2.7, 2.8925], [-2.3971, 2.7, 2.25], [-2.7286, 2.7, 1.5391], [-2.9316, 2.7, 0.7814], [-3.0, 2.7, 0.0], [-2.9316, 2.7, -0.7814], [-2.7286, 2.7, -1.5391], [-2.3971, 2.7, -2.25], [-1.9472, 2.7, -2.8925], [-1.3925, 2.7, -3.4472], [-0.75, 2.7, -3.8971], [-0.0391, 2.7, -4.2286], [0.7186, 2.7, -4.4316], [1.5, 2.7, -4.5], [2.2814, 2.7, -4.4316], [3.0391, 2.7, -4.2286], [3.75, 2.7, -3.8971], [4.3925, 2.7, -3.4472], [4.9472, 2.7, -2.8925], [5.3971, 2.7, -2.25], [5.7286, 2.7, -1.5391], [5.9316, 2.7, -0.7814]], collide: 1, color: "#cfc3a6"}
      - {kind: loft, a: [[6.0, 2.7, 0.0], [5.9316, 2.7, 0.7814], [5.7286, 2.7, 1.5391], [5.3971, 2.7, 2.25], [4.9472, 2.7, 2.8925], [4.3925, 2.7, 3.4472], [3.75, 2.7, 3.8971], [3.0391, 2.7, 4.2286], [2.2814, 2.7, 4.4316], [1.5, 2.7, 4.5], [0.7186, 2.7, 4.4316], [-0.0391, 2.7, 4.2286], [-0.75, 2.7, 3.8971], [-1.3925, 2.7, 3.4472], [-1.9472, 2.7, 2.8925], [-2.3971, 2.7, 2.25], [-2.7286, 2.7, 1.5391], [-2.9316, 2.7, 0.7814], [-3.0, 2.7, 0.0], [-2.9316, 2.7, -0.7814], [-2.7286, 2.7, -1.5391], [-2.3971, 2.7, -2.25], [-1.9472, 2.7, -2.8925], [-1.3925, 2.7, -3.4472], [-0.75, 2.7, -3.8971], [-0.0391, 2.7, -4.2286], [0.7186, 2.7, -4.4316], [1.5, 2.7, -4.5], [2.2814, 2.7, -4.4316], [3.0391, 2.7, -4.2286], [3.75, 2.7, -3.8971], [4.3925, 2.7, -3.4472], [4.9472, 2.7, -2.8925], [5.3971, 2.7, -2.25], [5.7286, 2.7, -1.5391], [5.9316, 2.7, -0.7814]], b: [[5.3, 4.1, 0.0], [5.2316, 4.1, 0.7814], [5.0286, 4.1, 1.5391], [4.6971, 4.1, 2.25], [4.2472, 4.1, 2.8925], [3.6925, 4.1, 3.4472], [3.05, 4.1, 3.8971], [2.3391, 4.1, 4.2286], [1.5814, 4.1, 4.4316], [0.8, 4.1, 4.5], [0.0186, 4.1, 4.4316], [-0.7391, 4.1, 4.2286], [-1.45, 4.1, 3.8971], [-2.0925, 4.1, 3.4472], [-2.6472, 4.1, 2.8925], [-3.0971, 4.1, 2.25], [-3.4286, 4.1, 1.5391], [-3.6316, 4.1, 0.7814], [-3.7, 4.1, 0.0], [-3.6316, 4.1, -0.7814], [-3.4286, 4.1, -1.5391], [-3.0971, 4.1, -2.25], [-2.6472, 4.1, -2.8925], [-2.0925, 4.1, -3.4472], [-1.45, 4.1, -3.8971], [-0.7391, 4.1, -4.2286], [0.0186, 4.1, -4.4316], [0.8, 4.1, -4.5], [1.5814, 4.1, -4.4316], [2.3391, 4.1, -4.2286], [3.05, 4.1, -3.8971], [3.6925, 4.1, -3.4472], [4.2472, 4.1, -2.8925], [4.6971, 4.1, -2.25], [5.0286, 4.1, -1.5391], [5.2316, 4.1, -0.7814]], collide: 1, color: "#bfb394"}   # the ramp to the next cam
      - {kind: loft, a: [[5.3, 4.1, 0.0], [5.2316, 4.1, 0.7814], [5.0286, 4.1, 1.5391], [4.6971, 4.1, 2.25], [4.2472, 4.1, 2.8925], [3.6925, 4.1, 3.4472], [3.05, 4.1, 3.8971], [2.3391, 4.1, 4.2286], [1.5814, 4.1, 4.4316], [0.8, 4.1, 4.5], [0.0186, 4.1, 4.4316], [-0.7391, 4.1, 4.2286], [-1.45, 4.1, 3.8971], [-2.0925, 4.1, 3.4472], [-2.6472, 4.1, 2.8925], [-3.0971, 4.1, 2.25], [-3.4286, 4.1, 1.5391], [-3.6316, 4.1, 0.7814], [-3.7, 4.1, 0.0], [-3.6316, 4.1, -0.7814], [-3.4286, 4.1, -1.5391], [-3.0971, 4.1, -2.25], [-2.6472, 4.1, -2.8925], [-2.0925, 4.1, -3.4472], [-1.45, 4.1, -3.8971], [-0.7391, 4.1, -4.2286], [0.0186, 4.1, -4.4316], [0.8, 4.1, -4.5], [1.5814, 4.1, -4.4316], [2.3391, 4.1, -4.2286], [3.05, 4.1, -3.8971], [3.6925, 4.1, -3.4472], [4.2472, 4.1, -2.8925], [4.6971, 4.1, -2.25], [5.0286, 4.1, -1.5391], [5.2316, 4.1, -0.7814]], b: [[5.3, 5.7, 0.0], [5.2316, 5.7, 0.7814], [5.0286, 5.7, 1.5391], [4.6971, 5.7, 2.25], [4.2472, 5.7, 2.8925], [3.6925, 5.7, 3.4472], [3.05, 5.7, 3.8971], [2.3391, 5.7, 4.2286], [1.5814, 5.7, 4.4316], [0.8, 5.7, 4.5], [0.0186, 5.7, 4.4316], [-0.7391, 5.7, 4.2286], [-1.45, 5.7, 3.8971], [-2.0925, 5.7, 3.4472], [-2.6472, 5.7, 2.8925], [-3.0971, 5.7, 2.25], [-3.4286, 5.7, 1.5391], [-3.6316, 5.7, 0.7814], [-3.7, 5.7, 0.0], [-3.6316, 5.7, -0.7814], [-3.4286, 5.7, -1.5391], [-3.0971, 5.7, -2.25], [-2.6472, 5.7, -2.8925], [-2.0925, 5.7, -3.4472], [-1.45, 5.7, -3.8971], [-0.7391, 5.7, -4.2286], [0.0186, 5.7, -4.4316], [0.8, 5.7, -4.5], [1.5814, 5.7, -4.4316], [2.3391, 5.7, -4.2286], [3.05, 5.7, -3.8971], [3.6925, 5.7, -3.4472], [4.2472, 5.7, -2.8925], [4.6971, 5.7, -2.25], [5.0286, 5.7, -1.5391], [5.2316, 5.7, -0.7814]], collide: 1, color: "#e2d9c0"}
  - id: lever
    shape: part
    pos: [-18.0, 0, 5.0]
    mass: 0.3
    friction: 0.03
    color: "#b8ad97"
    pieces:
      - {kind: poly, points: [[-19.5, 4.3], [0.0, 4.3], [0.0, 5.7], [-19.5, 5.7]], y: [-1.7, -0.5], collide: 0}
      - {kind: rod, from: [0.0, -1.2999999999999998, 5.0], to: [0.0, -0.9, 5.0], radius: 0.5, collide: 2, capsule: true, color: "#8f8a80"}   # the finger on the cam
  - id: link
    shape: part
    pos: [-6.0, 0, 5.0]
    mount: lever
    mass: 0.1
    color: "#c9bfa6"
    pieces:
      - {kind: poly, points: [[-6.35, 5.0], [-5.65, 5.0], [-5.65, 11.0], [-6.35, 11.0]], y: [-2.2, -1.7], collide: 0}
  - id: valve_rod
    shape: part
    pos: [-6.0, 0, 11.0]
    mass: 0.15
    color: "#d2c8ae"
    pieces:
      - {kind: poly, points: [[-6.7, 11.0], [-5.3, 11.0], [-5.3, 24.0], [-6.7, 24.0]], y: [-2.7, -2.2], collide: 0}
      - {kind: poly, points: [[-7.6, 23.0], [-4.4, 23.0], [-4.4, 24.6], [-7.6, 24.6]], y: [-2.7, -2.2], collide: 0, color: "#a89a7e"}   # the valve-rod's head
  - id: frame
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#cfc6b4"
    pieces:
      - {kind: poly, points: [[-1.8, -10], [1.8, -10], [1.4, 0], [-1.4, 0]], y: [6.2, 7.2]}   # the shaft's standard, behind
      - {kind: poly, points: [[-19.2, -10], [-16.8, -10], [-17.2, 5.0], [-18.8, 5.0]], y: [2.2, 3.2]}   # the lever's standard, behind
      - {kind: rod, from: [-18.0, -2.0, 5.0], to: [-18.0, 3.0, 5.0], radius: 0.7, color: "#8f8a80"}
      - {kind: poly, points: [[-7.6, 13.5], [-6.8, 13.5], [-6.8, 14.5], [-7.6, 14.5]], y: [-2.9000000000000004, -1.8000000000000003], collide: 0}
      - {kind: poly, points: [[-5.2, 13.5], [-4.4, 13.5], [-4.4, 14.5], [-5.2, 14.5]], y: [-2.9000000000000004, -1.8000000000000003], collide: 0}
      - {kind: poly, points: [[-7.6, 19.5], [-6.8, 19.5], [-6.8, 20.5], [-7.6, 20.5]], y: [-2.9000000000000004, -1.8000000000000003], collide: 0}
      - {kind: poly, points: [[-5.2, 19.5], [-4.4, 19.5], [-4.4, 20.5], [-5.2, 20.5]], y: [-2.9000000000000004, -1.8000000000000003], collide: 0}
      - {kind: poly, points: [[-25.0, -11], [25.0, -11], [25.0, -10], [-25.0, -10]], y: [-4, 9], color: "#b9b09c"}
joints:
  - {id: j_y, type: slide, body: carriage, axis: [0, 1, 0], range: [-8, 1], stiffness: 300.0, springref: 0, damping: 60.0}   # the hand slides the shaft lengthwise
  - {id: j_s, type: hinge, body: cams, axis: [0, 1, 0], damping: 0.002}   # the one driven joint; + : clockwise
  - {id: j_a, type: hinge, body: lever, axis: [0, 1, 0], range: [-0.6, 0.6], damping: 0.002}   # + : clockwise (the finger falls)
  - {id: j_k, type: hinge, body: link, axis: [0, 1, 0], damping: 0.002}
  - {id: j_r1, type: slide, body: valve_rod, axis: [0, 0, 1], damping: 0.05}   # the valve-rod; + : up
pins:
  - {id: pin_a, a: link, b: valve_rod, at: [-6.0, 0, 11.0]}
hand:
  - {t: 7.0, springref: {j_y: -3.0}}
  - {t: 14.0, springref: {j_y: -6.0}}
contact: {solref: [0.002, 1.0], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_s, kind: velocity, rpm: 30.0, kv: 100, max_torque: 100}
checks:
  - {type: follow, out: j_r1, in: j_s, expect: -0.0143, tol: 0.0011, min_r2: 0.99, settle_s: 3.8056, window_s: 0.3889}   # cam 1, shaft -35..35 deg
  - {type: follow, out: j_r1, in: j_s, expect: 0.014, tol: 0.0011, min_r2: 0.99, settle_s: 4.8056, window_s: 0.3889}   # cam 1, shaft 145..215 deg
  - {type: follow, out: j_r1, in: j_s, expect: -0.0143, tol: 0.0011, min_r2: 0.99, settle_s: 5.8056, window_s: 0.3889}   # cam 1, shaft -35..35 deg
  - {type: follow, out: j_r1, in: j_s, expect: 0.014, tol: 0.0011, min_r2: 0.99, settle_s: 6.8056, window_s: 0.3889}   # cam 1, shaft 145..215 deg
  - {type: follow, out: j_r1, in: j_s, expect: -0.0096, tol: 0.0008, min_r2: 0.99, settle_s: 9.8056, window_s: 0.3889}   # cam 2, shaft -35..35 deg
  - {type: follow, out: j_r1, in: j_s, expect: 0.0096, tol: 0.0008, min_r2: 0.99, settle_s: 10.8056, window_s: 0.3889}   # cam 2, shaft 145..215 deg
  - {type: follow, out: j_r1, in: j_s, expect: -0.0096, tol: 0.0008, min_r2: 0.99, settle_s: 11.8056, window_s: 0.3889}   # cam 2, shaft -35..35 deg
  - {type: follow, out: j_r1, in: j_s, expect: 0.0096, tol: 0.0008, min_r2: 0.99, settle_s: 12.8056, window_s: 0.3889}   # cam 2, shaft 145..215 deg
  - {type: follow, out: j_r1, in: j_s, expect: -0.0051, tol: 0.0004, min_r2: 0.99, settle_s: 17.8056, window_s: 0.3889}   # cam 3, shaft -35..35 deg
  - {type: follow, out: j_r1, in: j_s, expect: 0.0051, tol: 0.0004, min_r2: 0.99, settle_s: 18.8056, window_s: 0.3889}   # cam 3, shaft 145..215 deg
  - {type: follow, out: j_r1, in: j_s, expect: -0.0051, tol: 0.0004, min_r2: 0.99, settle_s: 19.8056, window_s: 0.3889}   # cam 3, shaft -35..35 deg
  - {type: follow, out: j_r1, in: j_s, expect: 0.0051, tol: 0.0004, min_r2: 0.99, settle_s: 20.8056, window_s: 0.3889}   # cam 3, shaft 145..215 deg
  - {type: position, joint: j_r1, min: -1.6195, max: 1.6152, settle_s: 1.0, window_s: 5.5}   # cam 1: stroke 2.93 cm
  - {type: position, joint: j_r1, min: -1.1505, max: 1.1497, settle_s: 9.5, window_s: 4.0}   # cam 2: stroke 2.00 cm
  - {type: position, joint: j_r1, min: -0.6834, max: 0.6833, settle_s: 16.5, window_s: 5.0}   # cam 3: stroke 1.07 cm
  - {type: penetration, max: 0.001, settle_s: 0.5}
camera: {target: [0, 0, 4.0], position: [-10.0, -84.0, 4.0], fov: 34}
display:
  output: j_r1
  labels: {j_s: "Cams (driver)", j_r1: "Valve-rod", j_y: "Shaft shifted"}
  proof: {label: "Cams out of contact", sub: "the shaft turns but the valve-rod stands"}

