rotation_window — DRIVE pegsym op

• Data kinds: scalar × scalar × scalar → table

• Call: import fullseye as fs; fs.ledger.rotation_window(n: 'int', apothem: 'float', clearance: 'float', chamfer: 'float' = 0.0, peg_vertices=None, hole_vertices=None, tol: 'float' = 1e-10, mu: 'float | None' = None) -> 'dict' (to call the implementation directly, import pegsym; pegsym.rotation_window(n: 'int', apothem: 'float', clearance: 'float', chamfer: 'float' = 0.0, peg_vertices=None, hole_vertices=None, tol: 'float' = 1e-10, mu: 'float | None' = None) -> 'dict'; from the registry, opsdrive.get("rotation_window"))

Usage

Rotation window within which the peg enters the hole (or its mouth, if chamfered). Closed form for a regular n-gon (derived): with centers aligned, the vertices lie at directions π/n ∓ φ from the face normal, and the peg enters if the normal-direction extent of the outermost vertex, a cos(π/n − |φ|), is at most A + δ (+ W): φ = π/n − arccos(x), x = (A + δ + W) cos(π/n)/A (if x ≥ 1 the window fills the half period π/n). Since arccos has a rounding floor near 1, it is written as atan2(√(1 − x²), x). If peg_vertices and hole_vertices are given, the windows in the positive and negative directions are also measured by bisection on the linear program (polygon_fit_check, translation also free) (second (independent) implementation; the only option for keyed shapes). Returns phi_fit (the narrowest part, not the mouth), phi_cap (chamfer mouth), period = 2π/n, M = ⌈period/(2 phi_cap)⌉ and lp (plus/minus: when vertices are given, both ends of the window entering the mouth = the connected interval containing 0; the scan divides the half period into 360 steps, the ends by bisection).

Passing mu also returns the limit where friction stops it (derived, 45° chamfer): for a vertex resting on the mouth (at β = π/n − φ from the face normal) to slide down the chamfer, the peg must rotate (for even n the lateral forces of opposite vertices cancel, so it does not translate). If the spring about the axis is weak, the moment of the contact forces about the axis balances at 0: the boundary is where the tangential component of the chamfer normal sin β/√2 equals the friction opposing the sliding direction (downhill on the face + rotation) μ/√(1 + sin²β); it rotates when s√(1 + s²) > √2 μ (s = sin β), i.e. when s² > (√(1 + 8μ²) − 1)/2. phi_friction = π/n − β*, phi_eff = max(phi_fit, min(phi_cap, phi_friction)) (the part that enters without relying on the chamfer does not depend on friction). For a hexagon (vertices close to the face normal) friction narrows the window; triangles and squares are determined by geometry —— confirmed in a MuJoCo prototype (--full of the PoC). Raises ValueError: n < 1, apothem ≤ 0, clearance < 0, chamfer < 0, mu < 0, only one of the vertices given.

References (sample data, literature)

• 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.

Runnable examples (verified samples that actually call this op)

• poc_peg_symmetry_search — py -3.11 examples/poc_peg_symmetry_search.py

Ops the type connects to (they accept table as input)

course_layout · course_occupancy · course_contains · world_build · world_camera · world_move · lidar_scan · rss_longitudinal_same

Same category (pegsym)

polygon_peg · polygon_offset · polygon_fit_check · polygon_two_point_depth · polygon_coverage_image · plane_topview · polygon_yaw_read · relative_yaw_from_images


*Provenance: pegsym.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.