catch_plan_ballistic — DRIVE kendama op

• Data kinds: table → any

• Call: import fullseye as fs; fs.ledger.catch_plan_ballistic(kp: 'dict', *, v_max: 'float' = 2.0, a_max: 'float' = 20.0, g: 'float' = None, v_target: 'float' = 0.5, v_rel_max: 'float' = 1.0, n_planes: 'int' = 12, plane_step: 'float' = 0.02, clearance: 'bool' = False, margin: 'float' = 0.002) (to call the implementation directly, import kendama; kendama.catch_plan_ballistic(kp: 'dict', *, v_max: 'float' = 2.0, a_max: 'float' = 20.0, g: 'float' = None, v_target: 'float' = 0.5, v_rel_max: 'float' = 1.0, n_planes: 'int' = 12, plane_step: 'float' = 0.02, clearance: 'bool' = False, margin: 'float' = 0.002); from the registry, opsdrive.get("catch_plan_ballistic"))

Usage

Plan that computes the cup's arrival point from the slack ball's (p, v) with the closed form of the parabola. Returns plan(t, p, v, cup_state) → dict.

The catch is judged at the instant "the ball enters the top of the cup's window (rim plane + h_c + 1.5 r_b) downward with relative speed ≤ v_rel_max", so the plane is chosen at which the ball reaches the top of the window with speed v_target: from apex z_a = z + v_z²/(2g), z_c = z_a − (h_c + 1.5 r_b) − v_target²/(2g). The arrival time is the later root (descending) of z + v_z τ − ½ g τ² = z_c + h_c + 1.5 r_b, τ = (v_z + √(v_z² − 2g(z_c + h_c + 1.5 r_b − z)))/g, target xy = (x + v_x τ, y + v_y τ). If the cup cannot get there by τ with bang-bang motion (closed-form travel time: from rest 2√(d/a) or d/v + v/a, including the current speed if moving), the plane is lowered by plane_step and searched for up to n_planes levels (the lower, the more time, and the higher the arrival speed). If no plane is reachable in time, it returns the top level with feasible=False (betting on the plane with the lowest arrival speed. "Escaping to the bottom level" always yields an infeasible verdict as τ → 0 just before arrival, so the cup sinks 20 cm and drops the ball —— measured and rejected).

Return value {"target" (皿の中心), "t_hit", "z_plane", "v_ball_hit", "speed_hit", "feasible", "travel", "apex"}. clearance=True: until time τ_up when the bottom of the ball rises above the rim plane (+ margin), the cup is not moved sideways (only its height to the plane) —— the rim of the big cup is the highest point of the kendama, so once the ball is above the rim plane it does not collide wherever xy is. Whether it is in time is judged by τ − τ_up, and planes the ball never rises above are infeasible. Adds "landing" (landing point = final target) and "wait" (τ_up; 0 = no wait) to the return value. Limitations (honestly): the cup waits at rest at the target (relative speed at arrival = the ball's speed). Speed matching by "lowering the cup with the ball" on planes that cannot be reached in time is not implemented —— it relies on v_rel_max. Drag is ignored (a few mm over ≤ 0.5 s of flight for a 60 mm ball, and it vanishes because the plan is redone every step).

Empty input (kp as an empty dict) raises ValueError.

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)

• gallery_drive_kendama_racket — py -3.11 examples/gallery_drive_kendama_racket.py

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

course_crank · course_s_curve · course_turnaround · course_slope · course_intersection · course_parallel_parking · course_crossing · course_road

Same category (kendama)

kendama_params · elliptic_k_agm · pendulum_period_exact · pendulum_launch_speed · pendulum_rod_simulate · tether_tension_fixed · tether_slack_angle · swing_up_plan


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