RETINA
Experimental navigation project using optical flow.
Created: 4 August 2026

Difficulty project: 
Un piccolo robot che non cerca di riconoscere il mondo: guarda come il mondo si muove e usa quel movimento per non andarci a sbattere.
Se guidando un'automobile guardiamo un palo molto lontano, sembra quasi fermo. Un guardrail a mezzo metro dal finestrino, invece, ci passa accanto come un proiettile. RETINA nasce praticamente da questa osservazione: la velocità apparente delle cose contiene informazioni sulla loro posizione rispetto a noi.
RETINA non domanda alla telecamera: «Che oggetto è quello?».
La domanda è molto più semplice: «Come si sta muovendo, nell'immagine, quello che ho davanti?»
È una differenza piccola solo in apparenza. Un sistema di visione convenzionale può tentare di riconoscere una sedia, una parete, una persona o una porta. RETINA, invece, può ignorare quasi completamente il significato degli oggetti. Se una regione dell'immagine produce un movimento compatibile con qualcosa che si sta avvicinando troppo alla traiettoria del robot, quella regione è interessante. Il resto, per la navigazione, può anche non avere un nome.
1. Da due immagini nasce una piccola mappa del movimento
La telecamera acquisisce continuamente immagini della scena. RETINA confronta l'immagine corrente con quella precedente e suddivide il campo visivo in piccole zone. Per ogni zona cerca di stabilire in quale direzione e di quanto il contenuto si è spostato.
Il risultato non è una nuova fotografia. È una mappa di vettori: tante piccole frecce distribuite sull'immagine. La direzione della freccia indica la direzione dello spostamento apparente; la sua lunghezza rappresenta l'entità dello spostamento.
immagine precedente immagine corrente campo di moto
┌──────────┐ ┌──────────┐ ↖ ↑ ↑ ↗│ │ │ │ ← · · →│ ▓ │ → │ ▓ │→ ← · · →│ │ │ │ ↙ ↓ ↓ ↘└──────────┘ └──────────┘
Nel progetto corrente questa mappa è composta da 23 × 15 vettori: 345 piccoli osservatori del movimento. Non è una ricostruzione tridimensionale della scena, ma è già abbastanza ricca da mostrare strutture molto interessanti. Appendice A.1
2. Perché i vettori sono così utili?
Potremmo ridurre tutto a un solo numero: «ostacolo sì / ostacolo no». Sarebbe più leggero, ma butteremmo via una quantità enorme d'informazione.
Una mappa vettoriale ci dice contemporaneamente:
- dove il movimento è più intenso;
- se il moto è organizzato oppure casuale;
- se prevale una componente verso destra, sinistra, alto o basso;
- se il campo sembra espandersi da una zona;
- se una regione vicina al percorso del robot si comporta diversamente dal resto della scena;
- se il robot sta realmente traslando quando i motori dicono che dovrebbe farlo.
Dietro il banconeIl firmware conserva anche la mappa di optical flow grezza. Le componenti orizzontali e verticali sono salvate come valori con segno, senza imporre in fase di acquisizione una reinterpretazione successiva. Questo permette di riesaminare offline la stessa informazione che il robot aveva davanti durante il run.
3. Vicino e lontano: attenzione, non è un telemetro
Qui serve una precisazione importante. Un vettore lungo non significa automaticamente «oggetto vicino». Significa che quella parte dell'immagine si è spostata molto tra due fotogrammi.
Se il robot avanza e la scena è ragionevolmente statica, questo spostamento diventa però un ottimo indizio geometrico. A parità di moto della camera, ciò che è vicino tende a produrre un moto angolare maggiore di ciò che è lontano.
La trappola più comuneLa misura dipende dal movimento del robot, dall'orientamento della camera, dalla focale, dalla struttura della scena e perfino dalla presenza di superfici prive di texture. RETINA non trasforma ingenuamente la lunghezza di una freccia in centimetri.Questo è anche il motivo per cui il posizionamento della camera conta moltissimo. Se la camera guarda troppo in alto, il pavimento — che è uno dei riferimenti geometrici più preziosi — quasi sparisce. Se guarda troppo in basso, il sistema vede benissimo ciò che ha sotto il naso ma perde anticipo. Nel firmware esiste perciò una geometria prospettica legata all'altezza della camera, alla focale, all'inclinazione e all'ingombro fisico del robot. Appendice A.4
4. Non tutte le frecce meritano fiducia
Immaginiamo una parete bianca perfettamente uniforme. Spostiamo la camera di qualche centimetro. Quale punto della parete, nella seconda immagine, corrisponde a un certo punto della prima? Non lo sappiamo: sono tutti uguali.
Lo stesso problema compare in zone sature, troppo scure o prive di dettagli. Al contrario, spigoli, venature, scritte, fughe delle piastrelle e piccoli contrasti forniscono riferimenti utili.
Per questo RETINA non si limita a chiedere quanto sono lunghi i vettori. Cerca anche di capire quanto il movimento sia coerente: molte frecce che raccontano la stessa storia valgono molto di più di molte frecce che puntano a caso. Appendice A.2
Un paragone sempliceSe dieci persone in una piazza corrono tutte verso destra, probabilmente sta succedendo qualcosa verso sinistra. Se dieci persone camminano ognuna in una direzione diversa, dal gruppo non ricaviamo una direzione comune. La coerenza del campo di moto funziona, concettualmente, nello stesso modo.
5. Il robot non ha bisogno di una mappa del mondo
RETINA non costruisce necessariamente una planimetria per decidere la prossima frazione di secondo. Nel funzionamento normale gli interessa soprattutto stabilire se il corridoio davanti a sé resta compatibile con il passaggio del proprio corpo.
È una distinzione importante: non devo sapere che davanti a me c'è una scatola. Mi basta sapere che una parte della scena che invade il mio futuro passaggio sta producendo un campo di moto incompatibile con un avanzamento tranquillo.
Camera Camera Mappa Coerenza + Richiesta
frame n frame n+1 23×15 zone di
vettori prospettiche movimento
A questo punto il problema di visione si trasforma in un problema di controllo: avanti, prudenza, deviazione, stop o manovra di fuga.
6. Quando qualcosa va storto, comandano poche regole
Una delle caratteristiche più interessanti del progetto è che la parte di fuga non cerca di essere “intelligente”. È volutamente piccola, deterministica e difficile da contraddire.
Quando viene riconosciuto un pericolo, RETINA entra in una sequenza semplice:
┌─────────┐
│ FORWARD │
└────┬────┘
│ pericolo
▼
┌─────────────────┐
│ ESCAPE_REVERSE │ arretra davvero
└────────┬────────┘
▼
┌─────────────────┐
│ ESCAPE_TURN │ ruota lontano dal lato
└────────┬────────┘ pericoloso
▼
┌─────────────────┐
│ ESCAPE_CLEAR │ verifica di essersi liberato
└────────┬────────┘
▼
┌───────────┐
│ REFERENCE │ rinnova il riferimento temporale
└─────┬─────┘
▼
FORWARD
La filosofia è quasi meccanica: un pericolo appena rilevato non può essere seguito da un comando in avanti; una fuga deve iniziare con un vero arretramento; la rotazione avviene lontano dal lato ricordato come pericoloso; durante l'uscita quel lato resta temporaneamente “tabù”. Appendice A.5
8. C'è anche un ultimo “baffo” meccanico
Una telecamera può sbagliare. Una scena può essere impossibile. La luce può essere pessima. E soprattutto nessun algoritmo dovrebbe convincersi di essere infallibile.
RETINA mantiene quindi un ingresso fisico frontale indipendente, usato come ultima linea di difesa. Se arriva il contatto, la manovra di fuga assume autorità indipendentemente da ciò che la visione stava pensando.
Una buona regola di roboticaPiù una funzione è importante per evitare danni, meno è elegante affidarla a un solo sensore e a un solo ragionamento.
9. Una retina che si può riesaminare dopo
Durante un esperimento il robot raccoglie molti più dati di quelli strettamente necessari a girare le ruote. Registra eventi, percorso comportamentale, mappe complete di optical flow, dati inerziali e altre grandezze diagnostiche.
La cosa importante è che questa telemetria è progettata come osservatore passivo: serve per capire dopo cosa è successo, non per cambiare di nascosto la decisione presa dal controllore principale.
In altre parole possiamo far correre il robot, tornare al PC e porgli domande del tipo:
- cosa vedevi pochi istanti prima di fermarti?
- il flusso era coerente oppure rumoroso?
- la zona sinistra stava diventando più critica della destra?
- stavi veramente traslando?
- il giroscopio confermava la rotazione?
È qui che la scelta di conservare i vettori veri, invece di una semplice decisione binaria, diventa particolarmente preziosa.
10. E gli insetti?
La natura usa il movimento apparente da centinaia di milioni di anni. Mosche, api e altri animali sfruttano fenomeni legati all'optical flow per stabilizzare il volo, valutare passaggi, reagire all'avvicinamento di oggetti e mantenere distanze.
Ma sarebbe sbagliato immaginare una mosca che esegue il nostro stesso algoritmo. Nell'occhio composto molte direzioni dello spazio sono già campionate fisicamente da recettori diversi e il sistema nervoso dispone di circuiti specializzati che reagiscono alle correlazioni temporali del movimento.
Noi partiamo invece da una normale immagine bidimensionale e dobbiamo ricostruire numericamente ciò che l'architettura biologica ha in parte incorporato nell'hardware. RETINA, però, condivide con quell'approccio un principio interessante: per evitare un ostacolo non è sempre necessario sapere che cosa sia.
11. Cosa RETINA non è
RETINA non è un sistema di guida autonoma universale, non “comprende” una scena, non promette una misura metrica perfetta della profondità e non rende innocue tutte le condizioni ottiche.
È invece un esperimento molto concreto: verificare fino a che punto un piccolo sistema embedded possa muoversi affidandosi soprattutto alla struttura del movimento visivo, mantenendo il comportamento comprensibile, misurabile e riproducibile.
Forse la domanda più interessante non è «quanto è intelligente RETINA?», ma l'opposto: quanto poco deve sapere del mondo per riuscire comunque a muoversi?
12. Architettura in una pagina
- Camera - Acquisisce coppie successive della stessa scena.
- Motion estimator Blackfin - Calcola il miglior spostamento locale e genera la mappa di vettori.
- Mappa 23×15 - Rappresentazione compatta del movimento nel campo visivo.
- Metriche di coerenza - Separano moto organizzato da corrispondenze casuali o poco affidabili.
- Zone prospettiche - Concentrano l'attenzione nel volume che il corpo del robot dovrà attraversare.
- Controllore minimo - Decide avanzamento e sequenze deterministiche di fuga.
- IMU / giroscopio - Conferma e misura le rotazioni del corpo.
- Contatto frontale - Ultima linea fisica di sicurezza.
- Telemetria passiva - Registra vettori, eventi e stato per l'analisi offline.
Appendice tecnica
Questa sezione raccoglie i formalismi che nel testo principale avrebbero spezzato il racconto. I valori riportati sono riferiti al sorgente fornito con l'archivio del progetto; alcune costanti possono naturalmente cambiare nelle revisioni successive.
A.1 — Campo di moto e macroblocchi
Il motion estimator confronta un'immagine target con un'immagine di riferimento. Il campo utile viene organizzato in macroblocchi da 16 pixel e, nella configurazione documentata, produce una griglia logica:
Nx = 23, Ny = 15, N = 345 vettori
Ogni vettore contiene due componenti con segno:
vi = (vx,i, vy,i)
Le componenti generate dalla routine assembly sono espresse in unità di mezzo pixel. Il firmware conserva separatamente le componenti orizzontali e verticali come valori signed a 8 bit.
A.2 — Coerenza direzionale
Una misura utile non è soltanto la somma dei vettori, ma il rapporto fra il modulo della somma vettoriale e la somma dei moduli. In forma concettuale:
C = 100 · |Σ vi| / Σ |vi|
Se i vettori hanno direzioni casuali, la somma tende a cancellarsi e la coerenza scende. Se puntano prevalentemente nella stessa direzione, la risultante resta grande e la coerenza cresce. Il firmware calcola metriche analoghe su zone globali e locali, oltre a una coerenza radiale.
A.3 — Componente radiale ed espansione
Per ogni vettore si può considerare la direzione che unisce il centro ottico alla sua posizione nell'immagine. Indicando con ri tale direzione, una quantità proporzionale alla componente radiale è:
qi = vi · ri
La somma firmata delle componenti radiali e la loro coerenza forniscono un'indicazione di quanto il campo presenti una struttura di espansione o contrazione rispetto al centro ottico. Nel codice questa informazione è impiegata insieme ad altre metriche; non viene trattata come una misura autonoma e infallibile di distanza.
A.4 — Geometria prospettica del corridoio del robot
Il progetto definisce una geometria prospettica fissa che lega immagine e ingombro fisico. Nel sorgente analizzato compaiono, fra gli altri, i seguenti valori nominali:
- Larghezza logica della mappa: 368 px
- Macroblocco: 16 px
- Centro ottico usato dal modello: x ≈ 188 px, y ≈ 120 px
- Focale equivalente nel modello: ≈ 300 px
- Altezza camera: ≈ 135 mm
- Corridoio di sicurezza: ≈ 200 mm
- Altezza di sicurezza corpo: ≈ 160 mm
Una proiezione prospettica elementare usa relazioni del tipo:
x' = f X / Z, y' = f Y / Z
Da altezza della camera, inclinazione, focale e dimensioni del corpo si possono quindi determinare, riga per riga, intervalli dell'immagine che corrispondono al volume futuro occupato dal robot. Il firmware mantiene limiti distinti per il controllo della pista e per quello dell'altezza.
A.5 — Macchina a stati minima
Gli stati principali dichiarati nel controllore sono:
RETINA3_FORWARDRETINA3_ESCAPE_REVERSERETINA3_ESCAPE_TURNRETINA3_ESCAPE_CLEARRETINA3_REFERENCERETINA3_FAULT
La scelta è volutamente monotona durante una fuga: una nuova evidenza di pericolo può rinforzare o aggravare l'escape, ma non deve consentire a un altro modulo di annullarlo arbitrariamente.
Nel sorgente sono codificate anche alcune invarianti progettuali: nessun pericolo fresco può essere seguito da FORWARD; ogni fuga inizia con una reale fase di retromarcia; la rotazione avviene lontano dal lato di pericolo memorizzato; quel lato rimane temporaneamente escluso durante la fase di clear.
A.6 — Verifica del moto e controllo della rotazione
Il controller usa il flusso anche come osservatore del movimento del telaio. Durante l'avanzamento una mancanza persistente di traslazione può portare a incrementare progressivamente il PWM, purché non vi siano contemporaneamente evidenze di ostacolo. Quando il moto torna verificabile, il comando può rilassarsi verso il valore di crociera.
Per la rotazione la IMU MPU9250 fornisce feedback giroscopico. L'integrazione concettuale della velocità angolare è:
θ(t) = ∫ ω(t) dt
Il software prevede soglie, timeout e una modalità degradata quando il feedback giroscopico non è disponibile con sufficiente affidabilità.
A.7 — Telemetria scientifica
Il formato di telemetria salva per ogni mappa completa le 345 componenti orizzontali e le 345 verticali, insieme a metadati quali attività, numero di vettori non nulli, coerenza globale, coerenza del terreno, componente radiale, PWM, esposizione, guadagno, stato del controllore e informazioni giroscopiche.
Nel progetto sono presenti inoltre stream separati per eventi, percorso, IMU, odometria comportamentale e sonde diagnostiche. La documentazione sorgente specifica che questi stream sono passivi rispetto alla navigazione: un errore di telemetria non deve modificare la decisione del controllore.
A.8 — Limiti fisici dell'optical flow
La velocità dell'immagine dipende dalla combinazione tra moto della camera, struttura tridimensionale e parametri ottici. In un modello pinhole, per una traslazione pura compaiono termini inversamente proporzionali alla profondità Z; per questo, a parità di condizioni, gli oggetti vicini tendono a generare velocità angolari maggiori.
Ma rotazioni della camera, assenza di texture, saturazione, variazioni di illuminazione, oggetti autonomamente in movimento e aperture locali ambigue possono alterare questa relazione. Per questo RETINA combina più indizi e conserva la possibilità di verificare offline l'intero campo vettoriale.
A small robot that doesn't try to recognize the world: it watches how the world moves and uses that movement to avoid crashing into it.
When driving a car, if we look at a distant pole, it appears almost stationary. A guardrail just half a meter from the window, however, whizzes past us like a bullet. RETINA stems essentially from this observation: the apparent speed of objects contains information about their position relative to us.
RETINA does not ask the camera: «What object is that?»
The question is much simpler: «How is the thing in front of me moving within the image?»
It is a difference that is small only in appearance. A conventional vision system might attempt to recognize a chair, a wall, a person, or a door. RETINA, on the other hand, can almost completely disregard the meaning of the objects. If a region of the image produces movement consistent with something coming too close to the robot's path, that region is of interest. As far as navigation is concerned, the rest need not even have a name.
1. A small map of movement emerges from two images.
The camera continuously captures images of the scene. RETINA compares the current image with the previous one and divides the field of view into small zones. For each zone, it attempts to determine the direction and magnitude of the content's movement.
The result is not a new photograph. It is a vector map: numerous small arrows distributed across the image. The direction of the arrow indicates the direction of the apparent movement, while its length represents the magnitude of the displacement.
previous image current image flow field
┌──────────┐ ┌──────────┐ ↖ ↑ ↑ ↗│ │ │ │ ← · · →│ ▓ │ → │ ▓ │→ ← · · →│ │ │ │ ↙ ↓ ↓ ↘└──────────┘ └──────────┘
In the current project, this map consists of 23 × 15 vectors: 345 small motion observers. It is not a three-dimensional reconstruction of the scene, yet it is rich enough to reveal very interesting structures. Appendix A.1
2. Why are vectors so useful?
We could reduce everything to a single number: «obstacle yes / no obstacle.» It would be simpler, but we would throw away a huge amount of information.
A vector map tells us simultaneously:
- where movement is most intense;
- whether the movement is organized or random;
- if a component towards the right, left, up, or down prevails;
- if the field appears to expand from a zone;
- if a region near the robot's path behaves differently from the rest of the scene;
- if the robot is actually translating when the motors indicate it should be doing so.
Behind the scenesThe firmware also stores the raw optical flow map. Horizontal and vertical components are saved as signed values, without imposing any subsequent reinterpretation during acquisition. This allows for the offline re-examination of the same information the robot encountered during the run.
3. Near and far: note that it is not a rangefinder.
An important clarification is needed here. A long vector does not automatically mean a "nearby object." It means that a specific part of the image has shifted significantly between two frames.
However, if the robot is moving forward and the scene is reasonably static, this displacement becomes an excellent geometric cue. Given the same camera motion, nearby objects tend to produce greater angular motion than distant ones.
The most common pitfallMeasurement depends on the robot's movement, camera orientation, focal length, scene structure, and even the presence of textureless surfaces. RETINA does not naively convert the length of an arrow into centimeters.This is also why camera positioning is crucial. If the camera points too high, the floor—one of the most valuable geometric references—virtually disappears. If it points too low, the system sees exactly what is right in front of it but loses foresight. Consequently, the firmware incorporates a perspective geometry model based on camera height, focal length, tilt, and the robot's physical dimensions. Appendix A.4
4. Not all arrows deserve trust.
Imagine a perfectly uniform white wall. We shift the camera a few centimeters. Which point on the wall in the second image corresponds to a specific point in the first? We cannot tell: they all look the same.
The same problem arises in areas that are saturated, too dark, or devoid of detail. Conversely, edges, grain patterns, text, tile grout lines, and subtle contrasts provide useful reference points.
That is why RETINA does not simply ask how long the vectors are. it also seeks to determine how consistent the movement is. Many arrows telling the same story are far more valuable than many arrows pointing in random directions. Appendix A.2
A simple analogyIf ten people in a square all run to the right, something is likely happening to the left. If ten people each walk in a different direction, we cannot derive a common direction from the group. The coherence of the motion field works, conceptually, in the same way.
5. The robot does not need a map of the world.
RETINA does not necessarily construct a spatial map to decide on the next fraction of a second. In normal operation, its primary concern is determining whether the corridor ahead remains compatible with the passage of its own body.
This is an important distinction: I do not need to know that there is a box in front of me. It suffices to know that a part of the scene encroaching on my future path is generating a motion field incompatible with smooth forward movement.
Camera Camera Map Coherence + Movement
frame n frame n+1 23×15 perspective request
vectors zone
At this point, the vision problem transforms into a control problem: proceed, exercise caution, deviate, stop, or execute an evasive maneuver.
6. When something goes wrong, a few rules take charge.
One of the project's most interesting features is that the escape component does not attempt to be “intelligent.” It is deliberately small, deterministic, and difficult to contradict.
When a danger is detected, RETINA initiates a simple sequence:
┌─────────┐
│ FORWARD │
└────┬────┘
│ danger
▼
┌─────────────────┐
│ ESCAPE_REVERSE │ it really falls back
└────────┬────────┘
▼
┌─────────────────┐
│ ESCAPE_TURN │ steer away from the side
└────────┬────────┘ dangerous
▼
┌─────────────────┐
│ ESCAPE_CLEAR │ verify that one has freed oneself
└────────┬────────┘
▼
┌───────────┐
│ REFERENCE │ renews the time reference
└─────┬─────┘
▼
FORWARD
The philosophy is almost mechanical: a newly detected danger cannot be followed by a forward command; an escape maneuver must begin with actual backward movement; the turn takes place away from the side identified as dangerous; and during the exit, that side remains temporarily “off-limits.” Appendix A.5
8. There is also a final mechanical “whisker”
A camera can make mistakes. A scene can be impossible to interpret. Lighting conditions can be terrible. And above all, no algorithm should convince itself that it is infallible.
RETINA therefore retains an independent physical front-facing input, serving as a last line of defense. If contact occurs, the escape maneuver takes precedence, regardless of what the vision system was processing.
A good rule of robotics:The more important a function is for preventing damage, the less elegant it is to entrust it to a single sensor and a single line of reasoning.
9. A retina that can be re-examined later
During an experiment, the robot collects far more data than is strictly necessary to turn its wheels. It records events, its behavioral path, complete optical flow maps, inertial data, and other diagnostic metrics.
Crucially, this telemetry system is designed as a passive observer: its purpose is to understand what happened after the fact, not to secretly alter the decisions made by the main controller.
In other words, we can run the robot, return to the PC, and ask it questions such as:
- What did you see just before stopping?
- Was the flow coherent or noisy?
- Was the left side becoming more critical than the right?
- Were you actually translating?
- Did the gyroscope confirm the rotation?
This is where the choice to retain the actual vectors, rather than making a simple binary decision, becomes particularly valuable.
10. What about insects?
Nature has been utilizing apparent motion for hundreds of millions of years. Flies, bees, and other animals exploit phenomena linked to optical flow to stabilize their flight, navigate gaps, react to approaching objects, and maintain distances.
However, it would be a mistake to imagine a fly executing the same algorithm we do. In a compound eye, various spatial directions are physically sampled by distinct receptors, and the nervous system possesses specialized circuits that respond to the temporal correlations of motion.
We, on the other hand, start with a standard two-dimensional image and must numerically reconstruct what biological architecture has partially embedded into its hardware. RETINA, however, shares an interesting principle with that approach: to avoid an obstacle, it is not always necessary to know what that obstacle is.
11. What RETINA is not
RETINA is not a universal autonomous driving system; it does not “understand” a scene, does not promise perfect metric depth measurement, and does not render all optical conditions harmless.
Instead, it is a very concrete experiment: to verify the extent to which a small embedded system can navigate by relying primarily on the structure of visual motion, while keeping its behavior understandable, measurable, and reproducible.
Perhaps the most interesting question is not “how intelligent is RETINA?” but the opposite: how little does it need to know about the world to still manage to move around?
12. Single-page architecture
- Camera – Captures successive pairs of the same scene.
- Blackfin motion estimator – Calculates the best local displacement and generates the vector map.
- 23×15 map – Compact representation of motion within the field of view.
- Coherence metrics – Distinguish organized motion from random or unreliable matches.
- Perspective zones – Focus attention on the volume the robot's body will traverse.
- Minimal controller – Determines forward movement and deterministic escape sequences.
- IMU / gyroscope – Confirms and measures body rotations.
- Frontal contact – Final physical safety measure.
- Passive telemetry – Records vectors, events, and status for offline analysis.
Appendice tecnica
This section gathers technical details that would have disrupted the narrative flow of the main text. The values listed refer to the source code provided with the project archive; naturally, some constants may change in subsequent revisions.
A.1 — Motion field and macroblocks
The motion estimator compares a target image with a reference image. The active area is organized into 16-pixel macroblocks and, in the documented configuration, produces a logical grid:
Nx = 23, Ny = 15, N = 345 vectors
Each vector contains two signed components:
vi = (vx,i, vy,i)
The components generated by the assembly routine are expressed in half-pixel units. The firmware stores the horizontal and vertical components separately as signed 8-bit values.
A.2 — Directional coherence
A useful measure is not merely the sum of the vectors, but the ratio between the magnitude of the vector sum and the sum of the magnitudes. Conceptually:
C = 100 · |Σ vi| / Σ |vi|
If the vectors have random directions, the sum tends to cancel out and coherence decreases. If they predominantly point in the same direction, the resultant remains large and coherence increases. The firmware calculates similar metrics for global and local zones, as well as a radial coherence measure.
A.3 — Radial component and expansion
For each vector, one can consider the direction connecting the optical center to its position in the image. Denoting this direction as ri, a quantity proportional to the radial component is:
qi = vi · ri
The signed sum of the radial components and their coherence provide an indication of the extent to which the field exhibits an expansion or contraction structure relative to the optical center. In the code, this information is used in conjunction with other metrics; it is not treated as a standalone, infallible measure of distance.
A.4 — Perspective geometry of the robot corridor
The design defines a fixed perspective geometry linking the image to physical dimensions. The analyzed source code includes, among others, the following nominal values:
- Logical map width: 368 px
- Macroblock: 16 px
- Optical center used by the model: x ≈ 188 px, y ≈ 120 px
- Equivalent focal length in the model: ≈ 300 px
- Camera height: ≈ 135 mm
- Safety corridor: ≈ 200 mm
- Body safety height: ≈ 160 mm
A basic perspective projection employs relationships such as:
x' = f X / Z, y' = f Y / Z
Based on camera height, tilt, focal length, and body dimensions, it is therefore possible to determine—line by line—the image intervals corresponding to the future volume occupied by the robot. The firmware maintains separate limits for path control and height control.
A.5 — Minimal state machine
The main states defined in the controller are:
RETINA3_FORWARDRETINA3_ESCAPE_REVERSERETINA3_ESCAPE_TURNRETINA3_ESCAPE_CLEARRETINA3_REFERENCERETINA3_FAULT
The choice is deliberately fixed during an escape maneuver: new evidence of danger may reinforce or intensify the escape, but it must not allow another module to arbitrarily cancel it.
Certain design invariants are also encoded in the source code: no newly detected danger can be followed by a FORWARD command; every escape begins with an actual reversing phase; rotation occurs away from the side where the danger was detected; and that side remains temporarily excluded during the clearance phase.
A.6 — Motion verification and rotation control
The controller also uses the data stream to monitor chassis movement. During forward motion, a persistent lack of translation may lead to a progressive increase in the PWM signal, provided there is no simultaneous evidence of an obstacle. Once motion is verified again, the command can ease back toward the cruising value.
For rotation, the MPU9250 IMU provides gyroscopic feedback. The conceptual integration of angular velocity is:
θ(t) = ∫ ω(t) dt
The software incorporates thresholds, timeouts, and a degraded mode for use when gyroscope feedback lacks sufficient reliability.
A.7 — Scientific telemetry
For each complete map, the telemetry format stores 345 horizontal and 345 vertical components, along with metadata such as activity, the number of non-zero vectors, global coherence, terrain coherence, radial component, PWM, exposure, gain, controller status, and gyroscope data.
The design also includes separate streams for events, trajectory, IMU data, behavioral odometry, and diagnostic probes. Source documentation specifies that these streams are passive with respect to navigation: a telemetry error must not alter the controller's decision.
A.8 — Physical limits of optical flow
Image velocity depends on the combination of camera motion, 3D structure, and optical parameters. In a pinhole model, pure translation introduces terms inversely proportional to depth (Z); consequently, all else being equal, nearby objects tend to generate higher angular velocities.
However, camera rotations, a lack of texture, saturation, lighting variations, independently moving objects, and ambiguous local apertures can alter this relationship. For this reason, RETINA combines multiple cues and retains the ability to verify the entire vector field offline.
Below is a video created by RETINA, showing the frames that document the reason for a STOP event. The image has been processed using false colors because an IR LED was actually used as the illuminator in this instance; note the heavy pixelation resulting from the processing method and 2x2 binning.