granular op• Data kinds: scalar × scalar × scalar → scalar
• Call: import fullseye as fs; fs.ledger.spoon_tilt_critical(phi_deg: 'float', L: 'float', h0: 'float', lip: 'str' = 'wall') -> 'float' (to call the implementation directly, import granular; granular.spoon_tilt_critical(phi_deg: 'float', L: 'float', h0: 'float', lip: 'str' = 'wall') -> 'float'; from the registry, opsdrive.get("spoon_tilt_critical"))
Tilt θ_c [deg] at which powder starts to spill from a spoon (2-D cross-section, quasi-static, no wall friction — own derivation).
Model: floor length L (from the lip to the back wall; the back wall is perpendicular to the floor), powder heaped flat to depth h0 while horizontal. Lowering the lip tilts the floor by θ. The free surface of the powder can only stand up to φ (angle of repose) from horizontal, so the slope through the lip is φ − θ as seen from the floor.
• lip="wall" (default: the mouth has a rim and is initially filled flat up to the mouth, initial area L h0): the retainable cross-section is A(θ) = ½ L² tan(φ − θ) (the wedge between floor and surface). The tilt at which it can no longer retain more than L h0 is θ_c = φ − atan(2 h0 / L) (computed with atan2). The fuller the heap, the sooner it spills; as h0 → 0, θ_c → φ, and at θ = φ everything comes out. If 2 h0 / L ≥ tan φ, it cannot retain it even when horizontal (returns 0).
• lip="open" (a vessel with no wall at the mouth): the front face is already a slope at the angle of repose, so it spills from θ = 0⁺ —— always returns 0.
★Until 2026-10-05 the wedge slope for wall was written as tan φ − tan θ (a small-angle approximation, θ_c = atan(tan φ − 2 h0 / L)). At θ = 10 degrees and φ = 30 degrees the wedge slope was 10 % too large, and with L 50 mm and h0 5 mm θ_c came out as 20.67 degrees (exact 18.69 degrees). Raises ValueError: φ outside (0, 90), L / h0 ≤ 0, lip other than wall / open.
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• The canonical algorithm (author, year) and its uses are named in the family usage guide above.
• poc_granular_heap_repose — py -3.11 examples/poc_granular_heap_repose.py
scalar as input)spin_from_marker_sequence · carla_transform_matrix · carla_pose_to_world · carla_camera_pose · carla_xy_yaw · carla_scene_load · town_chain · osm_parse
granular)heap_volume_cone · heap_mass · heap_volume_heightmap · beverloo_rate · beverloo_fit · discharge_synth · dispense_mass_from_video · hopper_discharge_rate
*Provenance: granular.py — DRIVE operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.