Lidar Neato XV11: primo approccio

Standard

Con questo articolo vorrei condividere l’esperienza che io e Marco D’Ambrosio abbiamo fatto nello sperimentare il piccolo gioiello di sensore Lidar: Neato XV11.

  1. Introduzione
  2. Caratteristiche tecniche del dispositivo
  3. Test funzionamento
  4. Facciamo sul serio: primo test con vPython
  5. Controllo del motore
  6. Prospettive future
  7. Ringraziamenti
 
 
Introduzione
 
Molto spesso in ambito di navigazione robotica si sente parlare di sistemi laser/ottici per la rilevazione del perimetro di un ambiente.

Sistemi molto conosciuti per questo scopo sono ad esempio la Kinect o la Asus Xtion, che utilizzano dei veri e propri sensori ottici (telecamera, infrarossi) molto sofisticati per rilevare com’è fatto l’ambiente in cui sono immersi: in pratica consentono di ricostruire un vero e proprio ambiente in 3d, ecco un esempio:

rtabmap

[Fonte/Credits: youtube.com/watch?v=AMLwjo80WzI Progetto: rtabmap]

Esiste poi una tecnologia molto interessante e talvolta costosa: il Lidar, spesso trovato sotto l’acronimo di LDS – Laser Distance Sensor.
Questo tipo di sensore è molto costoso (circa 1200 euro , eg: Hokuyo URG-04LX): ma attenzione, dipende dall’uso che se ne fà! Ad esempio i sensori che vengono utilizzati da google per le sue auto a guida autonoma possono costare anche 80.000$ (Velodyne HDL-64E – tenete d’occhio questa azienda: è leader nella produzione di sensori ottici per veicoli a guida autonoma).
Da tempo una società californiana produttrice di aspirapolvere robotici ha realizzato un Lidar very very cheap da installare sui suoi dispositivi. La società è la Neato, ed il modello a cui faremo riferimento è l’ XV11. Il costo dell’intero aspirapolvere si aggirava (e si aggira ancora oggi, in versioni più recenti) intorno all cifra di 400 euro.
Il 15 novembre 2011 è stato lanciato un concorsotweet con cui Wlliam Cox [@gallamine] ha lanciato il contest – con un premio di $1000 (con la partecipazione di varie persone) per chi avesse hackato il protocollo del Neato: capirete che con “soli” 400 euro, avere un sensore lidar sarebbe stato un affare abbastanza interessante: il lavoro è stato svolto da alcune persone, e contributi molto interessanti li hanno dati gli utenti Xevel e Hash69. Il 25 novembre 2010 Hash69 ha pubblicato un dump della comunicazione, ed in alcuni post successivi ha dato anche una interpretazione valida ai dati rilevati dal Lidar. Vincitore: Hash69, con la pubblicazione di questo post (ma è davvero un peccato che il blog originale su cui Hash69 ha postato i log di tutte le sue analisi sia stato rimosso da blogspot).
Da un pò di tempo a questa parte, è possibile trovare il solo sensore anche su ebay a prezzi molto interessanti (<150 euro con tasse di dazio & co incluse).

Qual’è la differenza tra questo dispositivo ed i più complessi sistemi ottici? la prima grossa differenza riguarda il fatto che il sensore lavora in piano: cioè effettua una scansione in parallelo al suolo, mostrando il perimetro dell’area “in cui è immerso” all’altezza “in cui viene posto” , ecco un risultato di tale scansione:

scansione_lidar_normale

Scansione di un sensore LIDAR su un piano dimensionale.

Mentre i device ottici possono riuscire ad elaborare un ambiente reale molto più complesso, ricostruendolo in 3d (vedi scansione rtabmap precedente).
Che differenza c’è tra questo lidar ed i modelli più costosi? Anche in questo caso la differenza sostanziale è nel tipo di scansione effettuata dal dispositivo: i lidar più costosi riescono ad effettuare una scansione sia orizzontale che verticale, ecco un esempio:
 
wannacott_piccola

[Fonte/Credits: youtube.com/watch?v=wR9Fl6oEvfw Realizzato da: Dereck Wonnacott]

 
 
Caratteristiche tecniche del dispositivo
 
I tecnici Neato che hanno realizzato questo dispositivo hanno preso spunto da questo white paper presentato ad una conferenza IEEE nel 2008. Il documento è molto interessante da leggere, anche per capire a fondo il funzionamento del dispositivo.
Vengono elencate anche le sue caratteristiche:
 
1. Eye-safe (Class I or II).
2. Works under standard indoor lighting conditions, and some outdoor conditions.
3. Measures a full 360 degree planar scan.
4. Has a range from 0.2m to 6m.
5. High resolution: range error < 3 cm at 6 m, angular resolution of 1 degree.
6. 4000 readings per second (scans up to 10 Hz)
7. Small size, low power (< 2W)
8. Standard, commercially-available components.
9. Low cost: $30 cost to build.
 
 

Effettivamente il lidar smontato mostra componenti di semplice reperibilità, ecco come si presenta “sotto la scorza”:

lidar_XV11_detail_1_reduced

Neato XV11 sotto la scorza.

Facendo alcune riflessioni, si nota che l’unico parametro non corretto sono i 10 Hz della lettura, che per quanto fisicamente sia possibile per via del lettore, risulta essere poi impossibile utilizzarle per due motivi:
  1. primo: la velocità di trasmissione dati e la lunghezza del pacchetto, 1980 byte, da solo limita a non oltre 5.8 Hz (avendo il limite di velocità della connessione seriale a 115200 bps)
  2. secondo: per la velocità massima ammessa dallo slip ring (LPM04-B) che è di 300 rpm, 5 Hz esatti.
Il fotoarray lineare utilizzato per rilevare il laser è il Panavision DLIS-2K (quì i dettagli su come è stato analizzato a fonto il sensore), 2080 pixel di risoluzione per 4 righe e molto veloce (permetterebbe di lavorare a circa ~2000 fps), mentre il processore è il TMS320F2802 di TI, un micro 32 bit con core DSP che funziona a 100 MHz.
Concludendo, il punto debole è proprio la parte meccanica che è affidata ad uno slip ring (LPM04-B) e al motore, tutti e due hanno una durata in ore e sono soggetti ad usura: è possibile verificare sul datasheet dello slip ring che ha un mtbf di circa 2700 ore facendolo girare a 300 rpm (massima velocità ammessa, ossia circa ossia circa 50.000.000 giri): ma di solito queste considerazioni vengono fatte in condizioni ideali, per cui sarebbe meglio considerare il 50% di tale valore. Nello specifico, si considera quindi un mbtf di oltre 1000 ore.
 
Test funzionamento
 
Appena tolto il sensore dalla scatola, per poter verificare se funzioni o meno, la prima cosa da testare è che almeno all’accensione dal sensore si riesca a leggere versione e numero seriale.
Consiglio subito di montare dei distanziali al di sotto del lidar nei quattro fori che ne consentono il fissaggio, così da tenerlo parallelo al piano di appoggio su cui lo andrete a posizionare:

 

lidar_XV11_detail_3_reduced

Distanziali per rendere operativo al meglio il sensore.

Per configurare il sensore, basta seguire il seguente schema:
 
lidar_test_connections_reduced

Connessioni al sensore.

L’alimentazione del device deve essere di 5V (o almeno quella che verificherete stampigliata a capo del cavo rosso sul circuito del neato -vedi prossima nota-).
Nota 1: esistono diversi modelli di Neato XV11, e la differenza sostanziale tra i modelli meno recenti e quelli più recenti è che è diverso il voltaggio per l’alimentazione della scheda. Per avere la certezza assoluta di quale sia l’alimentazione supportata dalla scheda è quello di svitare le 4 viti sul coperchio, e verificare quale sia il valore del filo rosso del connettore a 4 poli:
 
lidar_XV11_detail_2_reduced

Connessioni alimentazione.

lidar_XV11_detail_2_1_reduced

Dettaglio connessioni alimentazione.

A questo punto, diventa facile capire quale sia l’alimentazione da collegare al dispositivo: nei miei test ho utilizzato la 5V max 1A che è possibile recuperare dalla alimentazione usb (che sia di un pc o di un qualsiasi alimentatore per smartphone).
Nota 2: come potete osservare dallo schema, il motore è alimentato da una fonte, mentre il sensore viene alimentato da un’altra fonte: questa modalità di configurazione si rende necessaria per il corretto uso del sensore, vedremo nei prossimi paragrafi.
Nota 3: anche se nel dettaglio della immagine precedente vedete che il cavo marrone è TX mentre il cavo arancione è RX, i cavi sono a logica invertita: ci possono essere varie ipotesi sul perchè abbiano stampato in quel modo l’ordine dei cavi, ma la versione corretta è:
  • cavo arancione: TX
  • cavo marrone: RX
Le informazioni su come alimentare il motore sono contrastanti, c’è chi dice che funziona a 3.3 V, chi dice a 5V e chi a 12V.
In una prima fase, consiglio caldamente di alimentare i motori ad una tensione non superiore a 3V (un alimentatore stabilizzato sarebbe ottimo: consente di tenere sotto controllo la potenza erogata).
Il livello di tensione del segnale sulla uscita seriale sarà a 3.3V, e la configurazione è a 115200 bps / 8 bits / No parity / 1 bit stop.
Una volta collegati i fili, e alimentato il sensore collegato alla seriale, ciò che dovrebbe essere mostrato è una cosa molto simile a questa:

se ruotate a mano il sensore dalla seriale verrà fuori una stringa di testo come la seguente:

I comandi da poter utilizzare sono disponibili ed elencati quì:

Per verificare il firmware installato (vengono elencati qui in dettaglio) basta leggere la riga evidenziata in rosso nella prima nota: vi consiglio di verificare che la versione del firmware sia almeno la 2.5.x, per avere la possibilità di poter utilizzare al meglio il sensore.
 
 
Facciamo sul serio: primo test con vPython
 
Il lavoro di Xevel lo ha portato a realizzare una interfaccia in vPython che consente di visualizzare graficamente i risultati delle letture del sensore lidar (quì il repository github con le risorse di Xevel da cui: [XV-11_test_python/XV-11_test.py]).
Un altro utente, Profmason, ha ottimizzato l’interfaccia iniziale di Xevel correggendone alcuni bug: dalla risorsa del suo sito, selezionare lidar.zip.
Per poter procedere alla esecuzione dello script vPython, è necessario installare vpython e pyserial.
Prima di far partire il codice di test, verificare quale sia la porta seriale correttamente connessa la pc, ed impostarla correttamente alla riga 8 del codice (variabile “com_port”).

Ho testato il tutto inserendo il tutto in uno scatolo di scarpe capiente: in questo modo è possibile testare in maniera precisa e determinata le caratteristiche del lidar. Adesso collegate l’alimentazione del motore: comincerà a girare: fate partire il lidar!

Verrà mostrata in vpython la seguente traccia:
 
lidar_test-20141111-ok_reduced

Il sensore chiuso in una scatola.

Potrete notare da subito che ci sono una serie di punti che danno alcune informazioni:
  1. ogni puntino rappresenta una lettura della distanza visualizzata;
  2. il puntino rosso centrale rappresenta idealmente il centro del nostro dispositivo;
  3. il cerchio descritto subito dopo il centro del nostro sensore ha un raggio di 100mm: è regolabile, e rappresenta la soglia minima oltre il quale la lettura dei dati non è determinata con precisione assoluta (si veda ad esempio il caso in cui si monti il sensore su una base robot del diametro di 200mm);
  4. i puntini verdi rappresentano le letture che hanno dato un riscontro positivo: ed infatti nel nostro esperimento rappresentano il bordo della scatola in cui abbiamo “immerso” il sensore;
  5. i puntini gialli rappresentano l’errore calcolato sul tempo di risposta del dispositivo;
  6. in questo esempio non se ne vedono, ma se per caso ci fossero stati errori di lettura (angoli morti o punti non raggiungibili direttamente) allora questi sarebbero stati rappresentati con dei puntini rossi.
 
 
Controllo del motore
 
Fino ad ora abbiamo solo impostato il dispositivo per garantire il suo funzionamento: perchè tutto funzioni correttamente, è indispensabile il controllo ad anello chiuso del motore, il lidar fornisce in uscita l’informazione sulla velocità di rotazione, quasi sicuramente ha un sensore index (magnetino e sensore hall) che fornisce un impulso ad ogni rotazione, in base a questo può calcolare il periodo di rotazione e regolare il pwm sul motore.
Il grosso problema è che il motore deve girare a velocità il più possibile costante e non deve andare troppo veloce: anche alimentando il motore con un alimentatore stabilizzato da laboratorio, variando la tensione è possibile regolare la velocità: ma per fare le cose fatte bene è indispensabile il controllo ad anello chiuso.
All’interno del lidar c’è un encoder, che ad una determinata cadenza radiale effettua una lettura.
Il primo a trovare una soluzione con arduino è stato chenglung: sul forum di trossenRobotics, al termine del contest hanno continuato ad analizzare il protocollo, ed in questo post chenglung ha proposto il seguente schema:
 
ArduinoMega XV-11 LDS Adapter Schematic_reduced

Driver proposto da chenglung.

Il blog su cui chenglung ha pubblicato questa soluzione con i riferimenti al suo repository ed ulteriori dettagli sullo schema comprensivo del codice da utilizzare per programmare arduino è quì.
La cosa importante, è far girare a 300 giri al minuto (RPM) il motore del lidar: per fare ciò, dovete scegliere l’alimentazione giusta del lidar (e quì ci agganciamo alla nota in cui veniva chiesto di partire ad alimentare il lidar con 3V: per tenerlo intorno ai 300RPM bisogna regolare l’alimentazione del circuito perchè raggiunga il valore giusto).
Ecco quindi la soluzione (lasciatemi passare la grandissima approssimazione nella realizzazione vi prego!) implementata su una demoboard attaccata ad un arduino 2560:
 

lidar_test-20141208-_anello_chiuso_2_(reduced) L’output mostrato in vPython sul codice di Xevel è questo:

scansione_lidar_normaleCome potete notare, si riesce ad essere stabili intorno ai 300 rpm in maniera abbastanza precisa.

 

Prospettive future

Analizzato il circuito e la tecnologia, si è scoperto un modo nuovo di valutare l’ambiente circostante in ambito di una potenziale navigazione autonoma di un robot.
Utilizzare questo sensore per applicazioni a basso livello potrebbe essere complesso, ma se venisse utilizzato un qualcosa in più alto livello, allora tutto potrebbe essere non così complesso: ROS può sicuramente aiutare ad utilizzare al meglio questo stupendo strumento.
il LIDAR analizzato in questa pagina sicuramente è ottimo per gli ambienti indoor, ma in ambienti irradiati da luce solare può causare delle imprecisioni, ed in tal caso è consigliato dirottare gli sforzi su sensori di tipo ottico.
In cantiere avrei la composizione di una scheda che a bordo abbia un arduino vero e proprio (che consenta una facile programmazioni e prototipazione) che includa la circuiteria necessaria ad essere installato sotto al Neato, un pò come ha fatto RoboPeak), ma open source.
Per concludere elenco di seguito i pro e contro del NEATO XV11:
 
PRO:
  • sensore poco costoso;
  • non richiede approfondite conoscenze di elettronica;
  • con pochissimi componenti ed un semplice arduino è possibile costruire il controllo ad anello chiuso del sensore;
  • supportato da ROS;
  • molto seguito nelle varie comunità di robotica;
  • anche se non leggerissimo, con alcuni accorgimenti può essere usato anche sui droni;
CONTRO:
  • troppo sensibile alla luce solare;
  • range in ambienti indoor che potrebbe non soddisfare le richieste dei più esigenti;
  • sensore legato a componenti meccaniche soggette ad usura (slip ring): anche se a onor del vero, sono parametri che per un uso amatoriale/semi professionale non dovrebbero essere un problema, e che dovrebbero essere presi in considerazioni per applicazioni professionali in cui è richiesto moltissimo tempo di esercizio;
 
 
Ringraziamenti
 
Si ringraziano le persone che hanno permesso di ottenere così grandi risultati:
  • Neato per aver realizzato un così gran bel pezzo di hardware;
  • Xevel, chenglung e Hash69 che hanno lavorato moltissimo sul sensore grazie alla idea del contest partita da gallamine, robotAtlas e Matt Trossen;
  • profmason per aver lavorato ad un raffinamento della interfaccia di vPython;
  • Marco D’Ambrosio per il grandissimo aiuto che mi ha fornito nei primi step per configurare il dispositivo.