Visualizzazione post con etichetta Tango. Mostra tutti i post
Visualizzazione post con etichetta Tango. Mostra tutti i post

sabato 7 novembre 2020

PCL e Tango tablet

Ho ritirato fuori il mio tablet Google Yellowstone Tango per provare il trattamento dati delle nuvole dei punti con PCL

I dati reali sono stati presi presso la cava di Maiano (Fiesole) che e' la palestra di geologia per numerose generazioni di geologi fiorentini 

Ho ripreso con lo scanner del tablet questo dettaglio 


in particolare volevo vedere se riuscivo a misurare l'angolo tra i due piani indicati nella foto sottostante


(quello in blu e' il piano del fronte di scavo, quello in rosso e' relativo ad una frattura)

Usando la app Clino Fieldmove e Innstereo 


a posteriori la scelta delle superfici non e' stata felicissima perche' sono tutte ad alto angolo e si distinguono poco sullo stereoplot

Con il tablet la distanza massima a cui era possibile avere risposta dallo scanner era di circa 3 m. Per prova la superficie e' stata bagnata per vedere se il laser infrarosso era influenzato dall'umidita' della parete ma non si verifiche significative tra superficie asciutta e bagnata

I dati sono stati salvati in PLY e sono stati elaborati con PCL in QtCreator




Il programma dopo aver caricato il file PLY fa un sottocampionamento dei dati con VoxelGrid (passando da oltre 200.000 superfici a poco oltre 50 superfici) e calcola le  normali. I dati sono visualizzati con il visualizzatore interno a PLC

leggermente modificato da https://github.com/jeffdelmerico/pointcloud_tutorial


========================================

cmake_minimum_required(VERSION 3.5)

project(maiano LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(PCL 1.3 REQUIRED COMPONENTS common io features visualization)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable(maiano main.cpp)

target_link_libraries(maiano ${PCL_LIBRARIES})

========================================

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/ply_io.h>

#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>


using namespace std;

void
downsample (pcl::PointCloud<pcl::PointXYZRGB>::Ptr &points, float leaf_size,
            pcl::PointCloud<pcl::PointXYZRGB>::Ptr &downsampled_out)
{
    cout << "PointCloud before filtering: " << points->width * points->height
           << " data points (" << pcl::getFieldsList (*points) << ")." << std::endl;

  pcl::VoxelGrid<pcl::PointXYZRGB> vox_grid;
  vox_grid.setLeafSize (leaf_size, leaf_size, leaf_size);
  vox_grid.setInputCloud (points);
  vox_grid.filter (*downsampled_out);
  cout << "PointCloud after filtering: " << downsampled_out->width * downsampled_out->height
         << " data points (" << pcl::getFieldsList (*downsampled_out) << ")." << std::endl;

}

void compute_surface_normals (pcl::PointCloud<pcl::PointXYZRGB>::Ptr &points, float normal_radius,
                                    pcl::PointCloud<pcl::Normal>::Ptr &normals_out)
{
  pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> norm_est;

  // Use a FLANN-based KdTree to perform neighborhood searches
  norm_est.setSearchMethod (pcl::search::KdTree<pcl::PointXYZRGB>::Ptr
                            (new pcl::search::KdTree<pcl::PointXYZRGB>));

  // Specify the size of the local neighborhood to use when computing the surface normals
  norm_est.setRadiusSearch (normal_radius);

  // Set the input points
  norm_est.setInputCloud (points);

  // Estimate the surface normals and store the result in "normals_out"
  norm_est.compute (*normals_out);
}

void visualize_normals (const pcl::PointCloud<pcl::PointXYZRGB>::Ptr points,
                        const pcl::PointCloud<pcl::PointXYZRGB>::Ptr normal_points,
                        const pcl::PointCloud<pcl::Normal>::Ptr normals)
{
  // Add the points and normals to the vizualizer
  pcl::visualization::PCLVisualizer viz;
  viz.addPointCloud (points, "points");
  viz.addPointCloud (normal_points, "normal_points");

  viz.addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal> (normal_points, normals, 1, 0.01, "normals");

  // Give control over to the visualizer
  viz.spin ();
}


int main (int argc, char** argv)
{
    // Load data from pcd
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
    //if (pcl::io::loadPCDFile<pcl::PointXYZRGB> ("../data/robot1.pcd", *cloud) == -1) //* load the file
    if (pcl::io::loadPLYFile<pcl::PointXYZRGB> ("maiano.ply", *cloud) == -1) //* load the file

    {
        PCL_ERROR ("Couldn't read file robot1.pcd \n");
        return (-1);
    }

    // Point Clouds to hold output
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr downsampled (new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);

    // Downsample the cloud
    const float voxel_grid_leaf_size = 1.0;
    downsample (cloud, voxel_grid_leaf_size, downsampled);

    // Compute surface normals
    const float normal_radius = 1.0;
    compute_surface_normals (downsampled, normal_radius, normals);

    visualize_normals(cloud, downsampled, normals);

    int i = 0;
    for (pcl::Normal n : *normals) {
        std::cout << n.normal_x << "," << n.normal_y << "," << n.normal_z <<"\n";
        i++;
    }

    return(0);
}

========================================

Plottando le normali si ha questo risultato



Al di la' dell'orientamento verso il Nord (che lo scanner non registra in quanto non calibra i dati con la bussola) il programma estra sia le suprfici ad alto angolo che alcun suborizzontali.. non so quanto i dati alla fine siano corretti....i dati delle normali vengono forniti come componenti x,y,z di un versore con origine 0,0,0....non so se ho fatto qualche sbaglio nella conversione in strike e dip



mercoledì 11 aprile 2018

Tango Tablet vs Kinect

Ho provato a mettere alla prova il Tablet di Project Tango con il Kinect sulle Mura Etrusche a Fiesole gia' utilizzate come bersaglio in questo post


Pur ammettendo una giornata piovosa la prova con il tablet Tango e' stata disastrosa. Il sensore di profondita' e' riuscito ad acquisire al massimo 1100 punti da una distanza compresa tra 1.0 e 1.5 m; allontanandosi non veniva effettuata nessuna acquisizione mediante il software ParaView.

L'idea che mi sono fatto e' che il sensore di profondita' del tablet Tango non risulta avere una potenza di emissione cosi' elevata da avere riflessioni significative su superfici non omogenee e poco riflettenti.

In buona sostanza non e' possibile farne un utilizzo "in campagna" per scopi geologici. Il suo mondo e' il rilevamento di interni

martedì 10 aprile 2018

Esperimenti Tango : ParaView

Continuano gli esperimenti con Tango Tablet. La applicazione RTAB-MAP e' decisamente completa ma a me serviva una soluzione semplice per esportare la nuvola dei punti di una singola acquisizione ed ho trovato ParaView in versione Android per l'acquisizione e Desktop per la successiva visualizzazione

IMPORTANTE : non si devono aggiornare le applicazioni originali del tablet. Sia Tango Core che le GApps danno continuamente errore se aggiornate




I fotogrammi vengono acquisiti circa ogni 200 millisecondi.
Il massimo di numero di punti acquisiti e' intorno a 11.000-12.000.
Ad una distanza di 2 m da un muro la visione laterale e' +/- 1.0 m circa sull'asse X (orizzontale) e circa +/- 0.6 m sull'asse verticale. La FOV stimata e' di circa 53°x33°


I dati dello snapshot della app Android vengono salvate in formato .vtk. Dalla versione desktop i dati  possono essere esportati in csv in formato testo da File/Save Data/*.csv

sabato 7 aprile 2018

Test di Project Tango Tablet per la geologia

Scansioni 3D effettuate con Tablet Project Tango ed RTAB-MAP con visualizzazione in MeshLab

L'aspetto interessante di utilizzare RTAB-MAP e' che non e' necessario utilizzare una ripresa statica da cavelletto ma si puo' muovere la camera perche' viene gestito il motion tracking. Questo permette di riprendere anche zone che possono risultare "in ombra" da una ripresa frontale

Prova 1 







Prova 2







giovedì 5 aprile 2018

Project Tango

Visto che il Progetto Tango di Google e' stato dismesso a Marzo 2018 i prezzi dei dispositivi Tango sono scesi ad un livello umano e mi sono preso un Project Tango Tablet Development Kit. In estrema sintesi si tratta di una tablet Android NVidia con processore Tegra K1 e 128 Giga di memoria dotato di sensori simili a quelli del Kinect per il calcolo della distanza degli oggetti inquadrati


Il nome in codice del tablet e' Yellowstone altrimenti conosciuto con la sigla NX-74751 (in Star Trek la nave USS Yellowstone ha il codice NX-74751) ed e' stato sviluppato internamente da Google presso Google's ATAP (Advanced Technology and Projects). Per sapere quale hardware c'e' dentro si rimanda a questo link

Attualmente la documentazione delle API di Tango sono sparite dal sito sviluppatori di Google ma sono sempre recuperabili su Archive.org mentre il codice di esempio e' stato spostato qui. Al momento non sono riuscito a trovare una immagine del firmware da poter scaricare
Il sensore di profondita' e' un OV4682 con una matrice di 320x180 pixels (risoluzione molto lontana dal Kinect) ed ha funzione anche di camera RGB. Ci sono inoltre una camera standard da 4 Megapixels piu' una camera fisheye da 120° ed una da 180° (in totale di sono 4 camere)

OSAndroid™ 4.4 (KitKat®)
Screen7.02” 1920x1200 HD IPS display (323 ppi)
Scratch-resistant Corning® glass
Camera1 MP front facing, fixed focus
4 MP 2µm RGB-IR pixel sensor
Size119.77 x 196.33 x 15.36 mm
Weight0.82 lbs (370 g)
Battery4960 mAH cell (2 x 2480 cells)
ProcessorNVIDIA Tegra K1 with 192 CUDA cores
Network/Wireless4G LTE¹
Dual-band Wi-Fi (2.4GHz/5GHz) WiFi 802.11 a/b/g/n
Bluetooth 4.0
NFC (reader and peer to peer modes)
Memory128 GB internal storage (actual formatted capacity will be less)
4 GB RAM
ConnectivityMicro HDMI
USB 3.0 host via dock connector²
Micro SD card
Nano SIM slot
SensorsMotion tracking camera
3D depth sensing
Accelerometer
Ambient light
Barometer
Compass
aGPS
Gyroscope
Audio OutputDual stereo speakers
3.5 mm audio connector (OMTP)

Viene riportato che il sensore della bussola non sia funzionante

Il tablet viene fornito con un dock che funziona da ricarica ed ha una porta USB. La porta USB serve solo per connettere eventuali USB drive o simili, non funziona come canale Adb. Inoltre il tablet e' talmente assetato di risorse che se si connette il solo cavo USB (e non l'alimentazione del dock, 12V 2A con connettore positivo al centro del jack) il dispositivo si scarica invece di caricarsi)

Alcune applicazioni gia' pronte risultano essere
  • App Discovery Project Tango 
  • Room Scanner
  • RTAB-Map (permette esportazione in ply)
  • Tango Scan View (converte i file OBJ in PLY)
  • ADF Tools
  • Tango Explorer
  • Java Point Cloud Example (dagli esempi Java)
Scansione con RTAB-Map visualizzata con MeshLab

E' possibile ancora ricompilare gli esempi ma non sono riuscito a ricompilare questo progetto


Per ottenere i permessi di root si usa TangoRoot e ChainFireSU (io non sono riuscito ad eseguire il root perche' Android continua a dire che e' TangoRoot e' una applicazione pericolosa e non la mette in esecuzione)

I dati delle immagini di profondita' vengono immagazzinati di default in formato super compresso binario proprietario ADF che risulta poco documentato. In ogni caso ci sono applicazione di terze parti che esportano in formati piu' comuni come PLY. La directory di salvataggio dei file ADF e' mutata nel tempo ma in ogni caso sembra richiedere i permessi di root


Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...