domenica 5 febbraio 2012

Move app su SDCard

Per poter spostare, una volta installata, una applicazione sulla SD e' aggiungere nel file Manifest la scritta installLocation="auto"
-------------------------------------------------------------------------------------------------------------

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.gpstest"
    android:versionCode="1"
    android:versionName="1.0" android:installLocation="auto">

-------------------------------------------------------------------------------------------------------------

altrimenti in modo automatico da dentro Eclipse si puo' usare il menu




giovedì 2 febbraio 2012

Magnetometro come misuratore di distanza

Ho provato ad usare il magnetometro contenuto nel telefono come sensore di distanza. Il sistema prevede l'impiego di una calamita, del telefono Android e dello script riportato di seguito
-----------------------------------------------------------------------------------------

import android, time
droid = android.Android()
droid.startSensingTimed(1, 250)
time.sleep(1)


f = open('/sdcard/magnete00.txt','w')


while True:
s5 = droid.sensorsReadMagnetometer().result
f.write(str(s5[0])+";"+str(s5[1])+";"+str(s5[2])+"\n")
print str(s5[0])+" "+str(s5[1])+" "+str(s5[2])
droid.stopSensing()
-----------------------------------------------------------------------------------------
Il sistema puo' avere impieghi piu' disparati dal realizzare un sistema di allarme (mettendo il magnete su uno stipite di una porta ed il sensore dall'altra) a misuratori di distanza a corto raggio.

La prova e' stata effettuando allontanando il magnete dal telefono e registrando il valore medio ad ogni distanza
Come si puo' vedere dal grafico sottostante
Misure magnetometro Distanza-Intensita'
il comportamento del sensore e' ottimale nonostante lo scarso campionamento del convertitore ADC con un errore pari a circa qualche punto percentuale. Con questo sistema e' quindi possibile sicuramente misurare spostamenti dell'ordine di 2mm ma credo sia possibile scendere anche a sensibilita' pari ad 1mm di spostamento

Da notare che le unita' di misura del magnetometro non sembrano essere unita' fisiche. A seguito di una calibrazione con la app Stato GPS i valori sono passati da circa 30 unita' a 15 unita'

DGPS Test 2

Il metodo del GPS Differenziale prevede una correzione basato sul cacolo delle effemeridi dei satelliti e degli errori degli orologi atomici. L'idea sarebbe quella di effettuare un sistema DGPS usando due GPS di due telefoni senza la pretesa di scendere alla precisione del centimetro ma quanto meno di migliore l'errore di posizionamento di un singolo telefono.

Se i due telefoni sono ragionevolmente vicini (nel raggio di qualche chilometro l'uno dall'altro) e condividono la stessa elettronica saranno ragionevolmente affetti dagli stessi errori sistematici che si possono annullare mantenendone uno fisso

Per il secondo test di GPS differenziale mi sono dotato di due telefoni identici (due Huawei 8150 Ideos Vodafone) con montato il medesimo programma utilizzato  per il primo test. I due telefoni sono stati posti uno vicino all'altro (pochi centimetri) fissato il punto in modo simultaneo e messi in registrazione in simultanea

Lo script del test 1 e' stato leggermente modificato in modo da scrivere anche il tempo e data ripresi dall'orologio del telefono ed tempo ripreso dal satellite GPS (loc.getTime())
In particolare e' interessante il secondo valore (espresso in millisecondi a partire dalla data del 1 gennaio 1970 00:00:00) perche' puo' essere utilizzato come sincronizzatore tra le due serie di misure. Questa funzione e' quella impiegata dalla app  GPS Time  (Market Android). Per passare dallo Unix time in millisecondi al formato data/ora in formato leggibile da un umano si puo' usare in Openoffice Calc la formula
A1/86400000+DATA(1970;1;1) e poi formattando la cella come data/ora (supponendo che il dato da convertire sia nella cella A1)
--------------------------------------------------------------------------------------------------------

package com.test.gpstest;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.widget.Toast;


public class GpsTestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        /* Use the LocationManager class to obtain GPS locations */
        LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        LocationListener mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    }
    public class MyLocationListener implements LocationListener
    {
    @Override
    public void onLocationChanged(Location loc)
    {
    loc.getLatitude();
    loc.getLongitude();
    loc.getAccuracy();
    String Text = "My current location is: " + "Latitud = " + loc.getLatitude() +"Longitud = " + loc.getLongitude()+" Accuracy = " + loc.getAccuracy();
    Toast.makeText( getApplicationContext(),Text,Toast.LENGTH_SHORT).show();
    // scrive i dati sul file
    try {
        File root = Environment.getExternalStorageDirectory();
        if (root.canWrite()){
            File gpxfile = new File(root, "dati_gps.txt");
            FileWriter gpxwriter = new FileWriter(gpxfile,true);
            BufferedWriter out = new BufferedWriter(gpxwriter);
            //String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
            String currentTimeString = new SimpleDateFormat("HH:mm:ss").format(new Date());
            out.write(currentTimeString+";"+loc.getTime()+";"+loc.getLatitude()+";"+loc.getLongitude()+";"+loc.getAccuracy()+"\n");
            out.close();
        }
    } catch (IOException e) {
   
    }


    }




    @Override
    public void onProviderDisabled(String provider)
    {
    Toast.makeText( getApplicationContext(),"Gps Disabled",Toast.LENGTH_SHORT ).show();
    }




    @Override
    public void onProviderEnabled(String provider)
    {
    Toast.makeText( getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show();
    }




    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {


    }


    }/* End of Class MyLocationListener */
    
}

--------------------------------------------------------------------------------------------------------
Dati non elaborati
 Come si osserva nei primi istanti l'errore di posizionamento e' alto ma decresce rapidamente fino a 2 metri dichiarati. La distanza relativa tra i due punti e' stata calcolata usando il valore medio di latitudine e longitudine (eliminando i primi punti con HDOP troppo elevata) ed e' risultata di circa 1.2 m

Calcolando la differenza di ogni latitudine e longitudine rispetto al valore medio per i due GPS si osserva una certa correlazione sulla longitudine ma non sulla latitudine
Differenze di longitudine rispetto alla media 

Differenze di latitudine rispetto alla media 
Effettuando una correzione utilizzando i delta di differenza tra i due GPS non si hanno significativi miglioramenti della distanza reciproca tra i sensori
Distanza tra sensori con valori corretti sulla base del valore medio

Usando un altro approccio ovvero correlando a coppie le varie posizioni GPS allo stesso tempo si osserva una correlazione decisamente piu' stringente

Utilizzando le correlazioni precedenti per correggere i valori delle posizioni GPS le nuove tracce GPS sono le seguenti. Si osserva chiaramente il miglioramento e la sostanziale coincidenza dei dati misurati
Dati corretti da retta di calibrazione
Calcolo della distanza corretta
La distanza tra i due GPS e' calcolata con il metodo correlatao in circa 4 cm che e' sostanzialmente la reale distanza presente tra i due sensori al momento delle acquisizioni

Questa prova si e' rivelata sostanzialmente un successo che ha comunque necessita' di conferme


martedì 31 gennaio 2012

HP-97

Tempo fa mi e' stato donato la calcolatrice programmabile nelle foto


Calcolatrice

Memoria esterna

Purtroppo chi mi ha dato l'oggetto mi ha detto che era funzionante ma non ha menzionato il fatto che funzionasse a 110 Volts..per cui quando ho cercato di dare corrente il calcolatore e' esploso (nel vero senso della parola....una volta aperto ho trovato un paio di componenti elettronici completamente distrutti) per cui adesso assolve alla funzione di soprammobile




lunedì 30 gennaio 2012

Sign an app

Per poter distribuire una applicazione Android e' necessario firmarla in modo digitale (vedere qui). Il certificato digitale non e' necessario che sia validato da una autorita' esterna.
Per poter firmare una applicazione da dentro Eclipse si puo' cliccare con il tasto destro sul progetto di cui si vuole rilasciare l'apk e scegliere Android Tool/Export Signed Application Package.
Si apre una finestra nel quale si sceglie il nome dell'applicazione e poi si puo' scegliere una firma digitale gia' creata oppure una gia' pronta

Prima schermata
Seconda Schermata

Definizione di una nuova chiave

Per quanta riguarda le versioni di debug queste sono firmate con una speciale chiave che puo' essere usata sull'emulatore o sul telefono di test ma non funziona su altri sistemi

DGPS Test

Mettendo insieme i vari pezzi di codice precedenti e' stata effettuata una prova usando sia  il sensore GPS Bluetooth che il sensore GPS Android.
I due sensori sono stati posti in acquisizione per tre minuti ad una distanza di pochi centimetri l'uno dall'altra e sincronizzati in modo empirico,

Calcolata la posizione media derivate dai due sensori sono stati calcolati e plottati i delta rispetto al valore medio
Grafico delle fluttuazioni GPS 

Si nota immediatamente come i due sensori lavorino in modo molto differente. Il sensore Bluetooth risente di fluttuazioni piu' ampie mentre il sensore Android si stabilizza rapidamente su una HDOP prossima ai 2 m. Riportando in pianta i dati si vede inoltre che la fluttuazione GPS ha un andamento completamente differente

Fluttuazioni in pianta del segnale GPS

Dettaglio della fluttuazione GPS per i due sensori
Al termine i punti medi dei due GPS risultano distanti 5 m mentre nella realta' si trovavano a pochi centimetri di distanza quindi il test e' stato un insuccesso... ma perche'????
Il sensore GPS del Bluetooth fornisce dati in formato DD MM.dd (gradi minuti.decimi minuto) il che vuole dire che la minima distanza apprezzata vale un centesimo di minuto
Prendiamo per esempio due punti entrambi a latitudine 45°N e longitudine 11°45,32' e 11°45,33' (ovvero distanti di 0.01 primi) che equivalgono a 11°45'19,19'' e 11°45'19,79''. La distanza tra queste
due posizioni risulta essere di circa 13 m. Quindi in linea di principio la colpa e' da attribuire nella scarsa sensibilita' del sensore GPS


Track GPS su Android Java

Ho fatto qualche tentativo di utilizzare Python per registrare i dati del GPS mediante il semplice script



--------------------------------------------------------------------------------------------------------------
import android,time
droid = android.Android()


droid.startLocating()
time.sleep(15)
while True:
loc = droid.readLocation().result
if loc == {}:
loc = getLastKnownLocation().result
if loc != {}:
try:
n = loc['gps']
except KeyError:
n = loc['network']
la = n['latitude']
lo = n['longitude']
print la,lo

--------------------------------------------------------------------------------------------------------------
ma dopo pochi secondi di utilizzo l'icona del GPS si spenge e viene visualizzato sempre lo stesso valore di latitudine e longitudine nonostante le normali fluttuazioni che affliggono tutti i sensori GPS.
Francamente non ho chiaro se il problema derivi dal mio hardware o dalle modifiche al firmware software del telefono (dato che il medesimo script ad altre persone funziona)
In ogni caso l'unica soluzione e' stata quella di convertire il progetto in Java

Manifest.xml (da notare le modifiche alle uses-permission ed all'icona personalizzata)

--------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.gpstest"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <activity
            android:name=".GpsTestActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


--------------------------------------------------------------------------------------------------------------


GpsTestActivity.java
In questo codice viene acquisita la posizione, l'accuratezza e l'ora, dati che poi vengono scritti sulla SD card su un file cvs dati_gps_android.txt
--------------------------------------------------------------------------------------------------------------

package com.test.gpstest;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.widget.Toast;


public class GpsTestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        /* Use the LocationManager class to obtain GPS locations */
        LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        LocationListener mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    }
    public class MyLocationListener implements LocationListener
    {
    @Override
    public void onLocationChanged(Location loc)
    {
    loc.getLatitude();
    loc.getLongitude();
    loc.getAccuracy();
    String Text = "My current location is: " + "Latitud = " + loc.getLatitude() +"Longitud = " + loc.getLongitude()+" Accuracy = " + loc.getAccuracy();
    Toast.makeText( getApplicationContext(),Text,Toast.LENGTH_SHORT).show();
    // scrive i dati sul file
    try {
        File root = Environment.getExternalStorageDirectory();
        if (root.canWrite()){
            File gpxfile = new File(root, "dati_gps_android.txt");
            FileWriter gpxwriter = new FileWriter(gpxfile,true);
            BufferedWriter out = new BufferedWriter(gpxwriter);
            //String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
            String currentTimeString = new SimpleDateFormat("HH:mm:ss").format(new Date());
            out.write(currentTimeString+";"+loc.getLatitude()+";"+loc.getLongitude()+";"+loc.getAccuracy()+"\n");
            out.close();
        }
    } catch (IOException e) {
   
    }


    }




    @Override
    public void onProviderDisabled(String provider)
    {
    Toast.makeText( getApplicationContext(),"Gps Disabled",Toast.LENGTH_SHORT ).show();
    }




    @Override
    public void onProviderEnabled(String provider)
    {
    Toast.makeText( getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show();
    }




    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {


    }


    }/* End of Class MyLocationListener */
    
}

--------------------------------------------------------------------------------------------------------------

Rispetto al test precedente effettuato con un senbsore bluetooth esterno le condizioni di visibilita' del cielo erano decisamente migliori per cui l'errore di posizione e' risultato inferiore ai 5 m



Feature Matching OpenCv

Il problema e' il seguente: trovare le differenze tra le due foto. Le due immagini sono state riprese a distanza di oltre un anno ed il ...