# No. 386 (Brown 1868): "Folding library ladder. It is shown open, partly open, and closed; the rounds are pivoted to the side-pieces, which are fitted together to form a round pole when closed, the rounds shutting up inside."
#
# Model (cm, gravity on): two side-pieces, each a half-round 114 cm long of radius 6, their flat faces toward each other; four rounds 28 cm long
# pivoted to both by pins in those faces. The left side-piece stands fixed; the right hangs on the rounds alone. The hand (the one driven joint)
# swings the lowest round about its pivot ±0.79 rad at 0.1 Hz from 0.8 rad (partly open): level, the ladder is open 28 cm wide;
# upright, the right side-piece has risen 28 cm and come over against the left, the flat faces meet and make a round pole of 12 cm,
# and the rounds stand up inside it between the faces; the faces' meeting (a real contact) stops the folding. The pinned rounds form parallelograms, so every round follows the lowest and
# the right side-piece stays upright throughout; release its pins on the upper rounds and they drop instead of rising with it.
# Generator: opencode-runs/batch13/gen386.py.
number: 386
slug: folding-library-ladder
name: Folding library ladder
brown: "Folding library ladder. It is shown open, partly open, and closed; the rounds are pivoted to the side-pieces, which are fitted together to form a round pole when closed, the rounds shutting up inside."
units: cm
sim: {timestep: 0.001, integrator: implicitfast, iterations: 60, duration_s: 10, floor: false}
bodies:
  - id: side_l
    shape: part
    pos: [0, 0, 0]
    fixed: true
    color: "#a8875a"
    pieces:
      - {kind: loft, a: [[-0.0, -6.0, 0], [-1.8541, -5.7063, 0], [-3.5267, -4.8541, 0], [-4.8541, -3.5267, 0], [-5.7063, -1.8541, 0], [-6.0, 0.0, 0], [-5.7063, 1.8541, 0], [-4.8541, 3.5267, 0], [-3.5267, 4.8541, 0], [-1.8541, 5.7063, 0], [-0.0, 6.0, 0]], b: [[-0.0, -6.0, 114.0], [-1.8541, -5.7063, 114.0], [-3.5267, -4.8541, 114.0], [-4.8541, -3.5267, 114.0], [-5.7063, -1.8541, 114.0], [-6.0, 0.0, 114.0], [-5.7063, 1.8541, 114.0], [-4.8541, 3.5267, 114.0], [-3.5267, 4.8541, 114.0], [-1.8541, 5.7063, 114.0], [-0.0, 6.0, 114.0]], collide: 1}   # the fixed side-piece, a half-round, its flat face toward the other
      - {kind: rod, from: [0, -1.6, 10.0], to: [0, 1.6, 10.0], radius: 0.45, collide: 0, color: "#7d7468"}   # pivot 1's pin
      - {kind: rod, from: [0, -1.6, 40.0], to: [0, 1.6, 40.0], radius: 0.45, collide: 0, color: "#7d7468"}   # pivot 2's pin
      - {kind: rod, from: [0, -1.6, 70.0], to: [0, 1.6, 70.0], radius: 0.45, collide: 0, color: "#7d7468"}   # pivot 3's pin
      - {kind: rod, from: [0, -1.6, 100.0], to: [0, 1.6, 100.0], radius: 0.45, collide: 0, color: "#7d7468"}   # pivot 4's pin
  - id: round0
    shape: part
    pos: [0, 0, 10.0]
    density: 650
    color: "#c9a873"
    pieces:
      - {kind: rod, from: [0, 0, 10.0], to: [19.5078, 0, 30.086], radius: 1.3, collide: 0}   # a round, pivoted on the fixed side-piece's face; the hand works the lowest
  - id: round1
    shape: part
    pos: [0, 0, 40.0]
    density: 650
    color: "#c9a873"
    pieces:
      - {kind: rod, from: [0, 0, 40.0], to: [19.5078, 0, 60.086], radius: 1.3, collide: 0}
  - id: round2
    shape: part
    pos: [0, 0, 70.0]
    density: 650
    color: "#c9a873"
    pieces:
      - {kind: rod, from: [0, 0, 70.0], to: [19.5078, 0, 90.086], radius: 1.3, collide: 0}
  - id: round3
    shape: part
    pos: [0, 0, 100.0]
    density: 650
    color: "#c9a873"
    pieces:
      - {kind: rod, from: [0, 0, 100.0], to: [19.5078, 0, 120.086], radius: 1.3, collide: 0}
  - id: side_r
    shape: part
    pos: [19.5078, 0, 30.086]
    mount: round0
    density: 600
    color: "#b08f62"
    pieces:
      - {kind: loft, a: [[19.5078, -6.0, 20.086], [21.3619, -5.7063, 20.086], [23.0345, -4.8541, 20.086], [24.3619, -3.5267, 20.086], [25.2141, -1.8541, 20.086], [25.5078, 0.0, 20.086], [25.2141, 1.8541, 20.086], [24.3619, 3.5267, 20.086], [23.0345, 4.8541, 20.086], [21.3619, 5.7063, 20.086], [19.5078, 6.0, 20.086]], b: [[19.5078, -6.0, 134.086], [21.3619, -5.7063, 134.086], [23.0345, -4.8541, 134.086], [24.3619, -3.5267, 134.086], [25.2141, -1.8541, 134.086], [25.5078, 0.0, 134.086], [25.2141, 1.8541, 134.086], [24.3619, 3.5267, 134.086], [23.0345, 4.8541, 134.086], [21.3619, 5.7063, 134.086], [19.5078, 6.0, 134.086]], collide: 2}   # the other side-piece, hung on the rounds
      - {kind: rod, from: [19.5078, -1.6, 30.086], to: [19.5078, 1.6, 30.086], radius: 0.45, collide: 0, color: "#7d7468"}
      - {kind: rod, from: [19.5078, -1.6, 60.086], to: [19.5078, 1.6, 60.086], radius: 0.45, collide: 0, color: "#7d7468"}
      - {kind: rod, from: [19.5078, -1.6, 90.086], to: [19.5078, 1.6, 90.086], radius: 0.45, collide: 0, color: "#7d7468"}
      - {kind: rod, from: [19.5078, -1.6, 120.086], to: [19.5078, 1.6, 120.086], radius: 0.45, collide: 0, color: "#7d7468"}
joints:
  - {id: j_0, type: hinge, body: round0, axis: [0, 1, 0], damping: 0.02}   # the lowest round: the one driven joint; + : opening (the free end goes down)
  - {id: j_1, type: hinge, body: round1, axis: [0, 1, 0], damping: 0.02}   # round 2 on its pivot
  - {id: j_2, type: hinge, body: round2, axis: [0, 1, 0], damping: 0.02}   # round 3 on its pivot
  - {id: j_3, type: hinge, body: round3, axis: [0, 1, 0], damping: 0.02}   # round 4 on its pivot
  - {id: j_r, type: hinge, body: side_r, axis: [0, 1, 0], damping: 0.02}   # the right side-piece on the lowest round's other pin
pins:
  - {id: p_1, a: side_r, b: round1, at: [19.5078, 0, 60.086]}   # round 2's pin in the right side-piece
  - {id: p_2, a: side_r, b: round2, at: [19.5078, 0, 90.086]}   # round 3's pin in the right side-piece
  - {id: p_3, a: side_r, b: round3, at: [19.5078, 0, 120.086]}   # round 4's pin in the right side-piece
driver: {joint: j_0, kind: velocity, rpm: 0, swing: {amplitude: 0.79, hz: 0.1}, kv: 3000.0, max_torque: 60}
checks:
  - {type: follow, out: j_1, in: j_0, expect: 1.0, tol: 0.03, min_r2: 0.99, settle_s: 0.3, window_s: 9}   # the rounds stay parallel
  - {type: follow, out: j_3, in: j_0, expect: 1.0, tol: 0.03, min_r2: 0.99, settle_s: 0.3, window_s: 9}
  - {type: follow, out: j_r, in: j_0, expect: -1.0, tol: 0.03, min_r2: 0.99, settle_s: 0.3, window_s: 9}   # the right side-piece stays upright
  - {type: position, joint: j_0, min: 0.7, max: 0.82, settle_s: 2.35, window_s: 0.3}   # open: the rounds level
  - {type: position, joint: j_0, min: -0.7908, max: -0.6708, settle_s: 7.35, window_s: 0.3}   # shut: the rounds upright inside the pole
camera: {target: [12.0, 0, 64.0], position: [52.0, -300.0, 89.0], fov: 34.0}
display:
  output: j_r
  labels: {j_0: "Lowest round (driver)", j_3: "Top round", j_r: "Right side-piece"}
  proof: {label: "Upper rounds unpinned", sub: "they drop instead of rising with the side-piece"}
