venerdì 18 aprile 2014
Problemi di Ubuntu 14.04 con Virtualbox
Cercando di dare un'occhiata alle novita' di Ubuntu 14.04, ho provato ad installare Ubuntu 14.04 in Virtualbox. Di solito non ci sono problemi tra Virtualbox ed Ubuntu ma in questo caso il risultato finale e' quello in immagine, ovvero una finestra microscopica
Installare le estensioni di Virtualbox non ha migliorato la situazione
Ho risolto il problema facendo l'upgrade di Virtualbox (alla versione 4.3.10) e reinstallando ex-novo le estensioni di Virtualbox. In ogni caso per far girare decentemente Ubuntu 14.04 ho dovuto assegnare meta' della Ram (1.4 Gb) ed abilitare 128Mb di Ram video con accelerazione 3D
martedì 15 aprile 2014
Accelerometro su Kinect
Kinect e' fornita di un accelerometro a 3 assi che secondo quando riportato da IFixIt dovrebbe essere un modello KXSD9 di Kionix
Per leggere i dati dell'accelorometro in Python si puo' usare il seguente script (ripreso da qui)
Attenzione: per funzionare e' necessario utilizzare PyUsb alla versione unstable 1.0 e non quella stable 0.4 che normalmente e' pacchettizzata per Linux
Prima e' quindi necessario scaricare il pacchetto unstable da GitHub
(installarea con il classico python setup.py install)
Lo script e' un demo anche per muovere il motore di tilt del Kinect
------------------------------------------------------
import usb.core
import usb.util
import sys
import time
# find our device
dev = usb.core.find(idVendor=0x045e, idProduct=0x02B0)
# was it found?
if dev is None:
raise ValueError('Device not found')
for cfg in dev:
sys.stdout.write("Configuration #"+str(cfg.bConfigurationValue) + '\n')
for intf in cfg:
sys.stdout.write('\tInterface #' + \
str(intf.bInterfaceNumber) + \
'\t, Alternate setting ' + \
str(intf.bAlternateSetting) + \
'\n')
sys.stdout.write("\tEndpoints:\n")
for ep in intf:
sys.stdout.write('\t\t' + \
str(ep.bEndpointAddress) + \
'\n')
# set the active configuration. With no arguments, the first
# configuration will be the active one
dev.set_configuration()
# (bmRequestType, bmRequestType, bmRequest, wValue, wIndex, nBytes)
ret = dev.ctrl_transfer(0xC0, 0x10, 0x0, 0x0, 1)
print hex(ret[0]) # should return 0x22 but dont know why ?
# ???
ret = dev.ctrl_transfer(0x40, 0x6, 0x1, 0x0, [])
time.sleep(1.5)
# head up!
ret = dev.ctrl_transfer(0x40, 0x31, 0xfff0, 0x0, [])
time.sleep(1.5)
# bring head down
ret = dev.ctrl_transfer(0x40, 0x31, 0xffd0, 0x0, [])
time.sleep(1.5)
# up!
ret = dev.ctrl_transfer(0x40, 0x31, 0xfff0, 0x0, [])
time.sleep(1.5)
# down!
ret = dev.ctrl_transfer(0x40, 0x31, 0xffd0, 0x0, [])
time.sleep(1.5)
# up!
ret = dev.ctrl_transfer(0x40, 0x31, 0xfff0, 0x0, [])
while True:
# Get accel data
ret = dev.ctrl_transfer(0xC0, 0x32, 0x0, 0x0, 10)
#print map(hex, ret)
# bytes 0 & 1 are always zero
x = (ret[2] << 8) | ret[3]
x = (x + 2**15) % 2**16 - 2**15 # convert to signed 16b
y = (ret[4] << 8) | ret[5]
y = (y + 2**15) % 2**16 - 2**15 # convert to signed 16b
z = (ret[6] << 8) | ret[7]
z = (z + 2**15) % 2**16 - 2**15 # convert to signed 16b
print x, "\t", y, "\t", z
time.sleep(0.5)
------------------------------------------------------
(attenzione l'asse x dello script in Python coincide con l'asse Z della codifica Microsoft mentre l'asse z dello script in Python corrisponde con quello X della codifica Microsoft)
L'asse Z Microsoft mostra la rotazione destra/sinistra (mettendo di fronte al kinect appoggiato sul tavolo) e ruotando di 90° verso sinistra mostra valori positivi di 858 unita' mentre ruotando a destra di -797 unita'
L'asse X mostra la rotazione con valori di +779 unita' per posizione a 90° con i sensori che guardano lo zenith mentre di -865 unita' con i sensori che guardano nadir
Se si continua la rotazione oltre i 90° i valori tornano a decrescere verso il valore 0. Per capire se il sensore sta guardando avanti od indietro (ovvero se e' appoggiato alla sua basetta od e' appeso alla sua basetta) vengono usati i valori dell'asse Y Microsoft (y Python) che sono positivi se il Kinect guarda avanti e negativi se guarda indietro
Sembra quindi che i valori letti debbano essere confinati tra 0 ed 819 mentre le mie letture eccedono questo valore. Se si calcola il valore medio tra la misura maggiore e minore si ha che
asse Z (858+797)/2 = 827
asse X (779+865)/2=822
quindi considerando l'incertezza (vedi sotto) c'e' solo da calcolare un piccolo offset dello zero ed i valori coincidono con quelli di fabbrica
Mantenendo fermo il kinect ho effettuato oltre 14200 misure ed ho ottenuto una deviazione standard dei dati nei vari assi come segue
Per leggere i dati dell'accelorometro in Python si puo' usare il seguente script (ripreso da qui)
Attenzione: per funzionare e' necessario utilizzare PyUsb alla versione unstable 1.0 e non quella stable 0.4 che normalmente e' pacchettizzata per Linux
Prima e' quindi necessario scaricare il pacchetto unstable da GitHub
(installarea con il classico python setup.py install)
Lo script e' un demo anche per muovere il motore di tilt del Kinect
------------------------------------------------------
import usb.core
import usb.util
import sys
import time
# find our device
dev = usb.core.find(idVendor=0x045e, idProduct=0x02B0)
# was it found?
if dev is None:
raise ValueError('Device not found')
for cfg in dev:
sys.stdout.write("Configuration #"+str(cfg.bConfigurationValue) + '\n')
for intf in cfg:
sys.stdout.write('\tInterface #' + \
str(intf.bInterfaceNumber) + \
'\t, Alternate setting ' + \
str(intf.bAlternateSetting) + \
'\n')
sys.stdout.write("\tEndpoints:\n")
for ep in intf:
sys.stdout.write('\t\t' + \
str(ep.bEndpointAddress) + \
'\n')
# set the active configuration. With no arguments, the first
# configuration will be the active one
dev.set_configuration()
# (bmRequestType, bmRequestType, bmRequest, wValue, wIndex, nBytes)
ret = dev.ctrl_transfer(0xC0, 0x10, 0x0, 0x0, 1)
print hex(ret[0]) # should return 0x22 but dont know why ?
# ???
ret = dev.ctrl_transfer(0x40, 0x6, 0x1, 0x0, [])
time.sleep(1.5)
# head up!
ret = dev.ctrl_transfer(0x40, 0x31, 0xfff0, 0x0, [])
time.sleep(1.5)
# bring head down
ret = dev.ctrl_transfer(0x40, 0x31, 0xffd0, 0x0, [])
time.sleep(1.5)
# up!
ret = dev.ctrl_transfer(0x40, 0x31, 0xfff0, 0x0, [])
time.sleep(1.5)
# down!
ret = dev.ctrl_transfer(0x40, 0x31, 0xffd0, 0x0, [])
time.sleep(1.5)
# up!
ret = dev.ctrl_transfer(0x40, 0x31, 0xfff0, 0x0, [])
while True:
# Get accel data
ret = dev.ctrl_transfer(0xC0, 0x32, 0x0, 0x0, 10)
#print map(hex, ret)
# bytes 0 & 1 are always zero
x = (ret[2] << 8) | ret[3]
x = (x + 2**15) % 2**16 - 2**15 # convert to signed 16b
y = (ret[4] << 8) | ret[5]
y = (y + 2**15) % 2**16 - 2**15 # convert to signed 16b
z = (ret[6] << 8) | ret[7]
z = (z + 2**15) % 2**16 - 2**15 # convert to signed 16b
print x, "\t", y, "\t", z
time.sleep(0.5)
------------------------------------------------------
(attenzione l'asse x dello script in Python coincide con l'asse Z della codifica Microsoft mentre l'asse z dello script in Python corrisponde con quello X della codifica Microsoft)
Leggendo i dati si ha che non e' presente un sensore di azimuth per cui non e' possibile avere una orientazione nello spazio kinect. In pratica non e' possibile distinguere la rotazione sull'asse Y
Sito Microsoft |
L'asse Z Microsoft mostra la rotazione destra/sinistra (mettendo di fronte al kinect appoggiato sul tavolo) e ruotando di 90° verso sinistra mostra valori positivi di 858 unita' mentre ruotando a destra di -797 unita'
L'asse X mostra la rotazione con valori di +779 unita' per posizione a 90° con i sensori che guardano lo zenith mentre di -865 unita' con i sensori che guardano nadir
Se si continua la rotazione oltre i 90° i valori tornano a decrescere verso il valore 0. Per capire se il sensore sta guardando avanti od indietro (ovvero se e' appoggiato alla sua basetta od e' appeso alla sua basetta) vengono usati i valori dell'asse Y Microsoft (y Python) che sono positivi se il Kinect guarda avanti e negativi se guarda indietro
i valori riportati sono espressi come accelerazioni in funzione dell'accelerazione di gravita'
Per calcolare l'accelerazione reale misurata la regola sembra essere
(misura/819)*9.18 m/sec*sec
Sembra quindi che i valori letti debbano essere confinati tra 0 ed 819 mentre le mie letture eccedono questo valore. Se si calcola il valore medio tra la misura maggiore e minore si ha che
asse Z (858+797)/2 = 827
asse X (779+865)/2=822
quindi considerando l'incertezza (vedi sotto) c'e' solo da calcolare un piccolo offset dello zero ed i valori coincidono con quelli di fabbrica
Mantenendo fermo il kinect ho effettuato oltre 14200 misure ed ho ottenuto una deviazione standard dei dati nei vari assi come segue
x = +/- 6.9 unita'
y = +/- 7.45 unita'
z = +/- 21.7 unita'
Per riportare i valori di inclinazione in gradi si puo' usare il seguente calcolo
-------------------------------------------------------------------------
pitch = math.atan2(y,x)*(180/3.1415926)
roll = math.atan2(y,math.sqrt((x*x)+(z*z)))*(180/3.1415926)
if (z <0):
roll = 90+(90-roll)
-------------------------------------------------------------------------
Di seguito una immagine con l'orientazione ed il valore degli angoli in relazione a diverse orientazioni
Per riportare i valori di inclinazione in gradi si puo' usare il seguente calcolo
-------------------------------------------------------------------------
pitch = math.atan2(y,x)*(180/3.1415926)
roll = math.atan2(y,math.sqrt((x*x)+(z*z)))*(180/3.1415926)
if (z <0):
roll = 90+(90-roll)
-------------------------------------------------------------------------
Di seguito una immagine con l'orientazione ed il valore degli angoli in relazione a diverse orientazioni
RGB con PyOpenNi Kinect
Non si tratta di una funzione molto bene documentata (anche perche' non presente nella cartella degli esempi) ma con PyOpenNi e' possibile acquisire immagini RBG da Kinect
il codice di riferimento (sostanzialmente autoesplicativo) e' il seguente
----------------------------------------------
from openni import *
from PIL import Image
ctx = Context()
ctx.init()
depth = DepthGenerator()
rgb = ImageGenerator()
depth.create(ctx)
rgb.create(ctx)
depth.set_resolution_preset(RES_VGA)
depth.fps = 30
rgb.set_resolution_preset(RES_VGA)
rgb.fps = 30
ctx.start_generating_all()
ctx.wait_one_update_all(rgb)
im = Image.fromstring('RGB',(640,480),rgb.get_raw_image_map())
im.save("rgb.jpg")
ctx.wait_one_update_all(depth)
de = Image.fromstring('L',(640,480),depth.get_raw_depth_map_8())
de.save("depth.jpg")
il codice di riferimento (sostanzialmente autoesplicativo) e' il seguente
----------------------------------------------
from openni import *
from PIL import Image
ctx = Context()
ctx.init()
depth = DepthGenerator()
rgb = ImageGenerator()
depth.create(ctx)
rgb.create(ctx)
depth.set_resolution_preset(RES_VGA)
depth.fps = 30
rgb.set_resolution_preset(RES_VGA)
rgb.fps = 30
ctx.start_generating_all()
ctx.wait_one_update_all(rgb)
im = Image.fromstring('RGB',(640,480),rgb.get_raw_image_map())
im.save("rgb.jpg")
ctx.wait_one_update_all(depth)
de = Image.fromstring('L',(640,480),depth.get_raw_depth_map_8())
de.save("depth.jpg")
Kinect con SimpleCV
Un metodo alternatico a PyOpenNi per interagire con Kinect da Python e' utilizzare SimpleCV
sudo apt-get install libopencv-*
sudo apt-get isntall python-opencv
sudo apt-get install python-numpy
sudo apt-get install python-pygame
sudo apt-get install python-setuptools
si scarica la libreria Simple CV di GitHub al seguente link e si installa com
python setup.py installse tutto e' andato a buon fine sono sufficiente le poche righe sottostanti per avere l'acquisizione dell'immagine RGB e di profondita' da Kinect
------------------------------------------------------
from SimpleCV import *
cam=Kinect()
depth = cam.getDepth()
depth.save('depth.jpg')
rgb = cam.getImage()
rgb.save('rgb.jpg')
Allineamento RGB/IR su Kinect
Sovrapponendo le immagini RGB e di profondita' di Kinect si vede chiaramente, indipendentemente se l'oggetto e' in primo piano o sullo sfondo
Leggendo questo link, si osserva che i parametri di calibrazioni delle camere sono codificate (e diversi) all'interno di ogni Kinect in funzione di come sono state montate e calibrate in fabbrica
Usando la versione completa di OpenNi (o l'SDK Microsoft) sono presenti specifiche funzioni che effettuano la fusione delle immagini dai due sensori come depth.GetAlternativeViewPointCap().SetViewPoint(image);
Leggendo questo link, si osserva che i parametri di calibrazioni delle camere sono codificate (e diversi) all'interno di ogni Kinect in funzione di come sono state montate e calibrate in fabbrica
Usando la versione completa di OpenNi (o l'SDK Microsoft) sono presenti specifiche funzioni che effettuano la fusione delle immagini dai due sensori come depth.GetAlternativeViewPointCap().SetViewPoint(image);
lunedì 14 aprile 2014
Controllo remoto su Linux con TeamViewer
Di solito quando installo software di controllo remoto su Windows uso LogMeIn ma in questo caso dovevo utilizzare un client Linux e la procedura di uso di Hamachi per LogMeIn non e' proprio lineare, cosi' ho provato ad utilizzare TeamViewer
Il software si scarica direttamente in formato .deb dall'indirizzo
http://www.teamviewer.com/it/download/linux.aspx
e si installa con il solito dpkg -i nome.deb
A questo punto da linea di comando si lancia il comando
./teamview
viene richiesto un account (che corrisponde ad una e-mail ed una password)
in seguito si imposta la password specifica per il computer client. Sono previsti codici che consentire il controllo remote anche ad altri utenti
La cosa carina e' che al successivo riavvio Teamview viene caricato automaticamente senza modificare nessun script di boot
Per controllare la macchina Linux ho scelto di usare un Mac. La procedura di installazione e' semplicissima e l'interfaccia grafica e' identica a quella per Linux
Una volta loggati vengono mostrate le macchine client accese e facendo doppio clic ci si collega
A differenza di LogMeIn non si utilizza il browser (almeno non in modo esplicito) e non e' richiesta l'installazione di nessun plugin dato che il lavoro viene fatto tutto dall'applicazione scaricata all'inizio
E' anche disponibile un client Android anche se la sua usabilita' non e' molto buona
venerdì 11 aprile 2014
3D Scanner con Kinect
Per completare i testi con il Kinect ho provato a creare uno scanner 3D.
L'oggetto e' stata la caffettiera sotto riportata il cui centro di rotazione e' stato posto a 65 cm dal Kinect ed e' stato ripreso da 4 fotogrammi ruotando ogni volta l'oggetto di 90°
Ovviamente e' stata una prova casalinga e ci sono forti errori di allineamento tra il sensore Kinect e l'asse di rotazione.
Per l'acquisizione e' stato usato il seguente script
-------------------------------------------------
from openni import *
import time
import pickle
import numpy as np
import Image
import scipy
ctx = Context()
ctx.init()
# Create a depth generator
depth = DepthGenerator()
depth.create(ctx)
# Set it to VGA maps at 30 FPS
depth.set_resolution_preset(RES_VGA)
depth.fps = 30
# Start generating
ctx.start_generating_all()
# Update to next frame
nRetVal = ctx.wait_one_update_all(depth)
depthMap = depth.map
depthMap2 = np.array(depthMap)
f = open("ca_2700.txt","w+b")
pickle.dump(depthMap2,f)
f.close()
-------------------------------------------------
i vari file salvati con pickle sono stati poi trattati con i seguenti programmi (uno ogni 90°, di fatto l'immagine viene centrata e vengono filtrati solo i dati > 0 ed inferiori a 70 cm)
--------------------------------
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_000.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(x-320)+","+str(y-240)+","+str(660-data[t])
t = t + 1
--------------------------------
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_180.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(x-320)+","+str(y-240)+","+str(-(660-data[t]))
t = t + 1
L'oggetto e' stata la caffettiera sotto riportata il cui centro di rotazione e' stato posto a 65 cm dal Kinect ed e' stato ripreso da 4 fotogrammi ruotando ogni volta l'oggetto di 90°
Ovviamente e' stata una prova casalinga e ci sono forti errori di allineamento tra il sensore Kinect e l'asse di rotazione.
L'oggetto reale |
La sua scansione (da notare che era posto sopra una scatola)
-------------------------------------------------
from openni import *
import time
import pickle
import numpy as np
import Image
import scipy
ctx = Context()
ctx.init()
# Create a depth generator
depth = DepthGenerator()
depth.create(ctx)
# Set it to VGA maps at 30 FPS
depth.set_resolution_preset(RES_VGA)
depth.fps = 30
# Start generating
ctx.start_generating_all()
# Update to next frame
nRetVal = ctx.wait_one_update_all(depth)
depthMap = depth.map
depthMap2 = np.array(depthMap)
f = open("ca_2700.txt","w+b")
pickle.dump(depthMap2,f)
f.close()
-------------------------------------------------
i vari file salvati con pickle sono stati poi trattati con i seguenti programmi (uno ogni 90°, di fatto l'immagine viene centrata e vengono filtrati solo i dati > 0 ed inferiori a 70 cm)
--------------------------------
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_000.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(x-320)+","+str(y-240)+","+str(660-data[t])
t = t + 1
--------------------------------
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_180.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(x-320)+","+str(y-240)+","+str(-(660-data[t]))
t = t + 1
--------------------------------
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_090.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(660-data[t]) + "," + str(y-240) + "," + str(x-320) #non funziona
t = t + 1
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_090.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(660-data[t]) + "," + str(y-240) + "," + str(x-320) #non funziona
t = t + 1
--------------------------------
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_090.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(-(660-data[t])) + "," + str(y-240) + "," + str(x-320)
t = t + 1
#!/usr/bin/python
import pickle
import numpy as np
import Image
f = open("ca_090.txt")
data = pickle.load(f)
f.close()
t = 0
for y in range(0,480):
for x in range (0,640):
if ((data[t] < 700) and (data[t]>0)):
print str(-(660-data[t])) + "," + str(y-240) + "," + str(x-320)
t = t + 1
--------------------------------
L'output e' stato dirottato su file testo che poi sono importati in Meshlab.
Iscriviti a:
Post (Atom)
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...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...