selfmotion op• Data kinds: matrix × table → table
• Call: import fullseye as fs; fs.ledger.fly_egomotion_from_flow(flow, lattice, axes=None, weights=None) (implementation को सीधे call करना हो तो import flyvision; flyvision.fly_egomotion_from_flow(flow, lattice, axes=None, weights=None), registry से लेना हो तो opsflyvision.get("fly_egomotion_from_flow"))
आँख के flow field से उसका least-squares rotation — और आँख का अपना आकार उत्तर की conditioning को कितना बिगाड़ता है।
> नीचे का विस्तृत विवरण मूल text में है — सारांश और headings का अनुवाद हो चुका है।
Given the flow f_i at known viewing directions d_i, a pure rotation w predicts f_i = -(w x d_i), which is linear in w: projecting on the tangent basis gives f_az = -w . (d x e_az) and f_el = -w . (d x e_el), so the estimate is one 2n x 3 least-squares solve with no iteration and no starting guess (Franz et al.'s linear egomotion estimate, *Biol. Cybern.* 2004).
The catch is not the algebra, it is the eye. A single patch of ommatidia sees a small piece of the sphere, and over a small piece the flow of a yaw and the flow of a sideways translation — or of a pitch — look nearly the same. This op therefore returns the condition number of that solve next to the answer, so that "the fit converged" and "the fit was identifiable" stay separate claims.
flow: (n, 2) azimuth/elevation components per ommatidium (fly_flow_from_directions or fly_matched_filter).
lattice: the eye they were measured on.
axes: None to solve for the full 3-D rotation, or a (k, 3) array of axes to restrict the fit to ([[0, 0, 1]] = yaw only, the well-conditioned question a forward-looking eye can actually answer).
weights: None or (n,) non-negative per-ommatidium weights — a confidence, e.g. the local contrast, or zeros to drop the rim.
Returns a dict::
{"omega_rad_s": (3,), "yaw_rad_s": float, "pitch_rad_s": float,
"roll_rad_s": float, "residual_rms": float, "flow_rms": float,
"explained": float, "condition": float, "n_ommatidia": int}
with yaw about +z (left positive), pitch about +y, roll about +x, and explained = 1 - residual_rms/flow_rms (1.0 = the flow is exactly a rotation, 0.0 = the fit explains none of it).
Ground truth: handed a fly_matched_filter template scaled by a known rate, it returns that rate to machine precision and explained = 1; handed a pure translation field it returns a small rate with a low explained; and the condition number of a narrow forward eye is large (the tests measure it) while the yaw-only fit is near 1.
Raises ValueError: a *flow* that is not (n, 2) for this lattice, non-finite entries, a malformed *axes* / *weights*, all-zero weights, and a lattice with fewer ommatidia than the fit has unknowns.
• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।
• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।
• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।
• poc_fly_optomotor_steering — py -3.11 examples/poc_fly_optomotor_steering.py
table को input के रूप में लेते हैं)fly_t4t5_field · fly_flow_from_directions · fly_matched_filter · fly_eye_merge · fly_hex_resample · fly_hs_readout
selfmotion)fly_matched_filter · fly_eye_merge
*Provenance: flyvision.py — FLYVISION operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.