mercoledì 15 novembre 2017

Nexus 9 / RTKLIB/ Geo++ / DPGS

Dopo la prova del precedente post ho provato ad usare l'applicazione Geo++ su Nexus 9 con RTKLIB in postprocessing per vedere se era possibile ottenere una correzione DGPS



Il punto trigonometrico di riferimento e' sempre il solito visto qui . La novita' e' che l'antenna GPS della Provincia di Firenze che usavo come antenna base per la correzione DGPS non fornisce piu' dati probabilmente a seguito della dismissione della Provincia stessa. Un sostituto e' stato trovato nell'antenna base dell'IGM posta in via Baracca a Firenze i cui dati possono essere scaricati a questo link

http://www.epncb.oma.be/_networkdata/siteinfo4onestation.php?station=IGMI00ITA

e piu' in dettaglio qui (la sigla della stazione e' igmi. i dati sono ordinati per cartelle del giorno dell'anno progressivo e dell'ora di acquisizione. I dati del giorno 311 per esempio ora T avranno un nome file del tipo igmi311t.17d.Z)

ftp://igs.bkg.bund.de/EUREF/nrt/

I dati relativi dalla scheda del punto topografico indicano una posizione di riferimento
43.83304783 11.30706278 203.3
I dati post processati con RTKLib vengono indicate le seguenti coordinate
43.833068271 11.307051667 184.74

La cosa che mi disturba e' che RTKLib non fornisce l'errore di posizionamento

I dati post processati dalla ditta che fornisce Geo ++ forniscono un punto (nessun errore di posizionamento fornito)
43,833042 11,307012 171.7541

Gli stessi dati processati con Leica GeoOffice di Leica portano una posizione completamente differente, in particolare e' completamente sballato il dato di quota
11° 22' 52".68555 -43° 49' 59".11283 1023.8346

considerando che le differenze nella posizione si trovano nella quinta posizione decimale dopo la virgola non sembra proprio male (lasciando perdere la quota che pero' non e' di mio interesse)

mercoledì 8 novembre 2017

Precise Point Positioning con Nexus 9 ed Android 7.1.1

Con l'introduzione delle API di misura Raw Gnss avevo gia' provato qualche tempo fa la applicazione di test fornita da Google, ovvero GnssLogger, ma senza un programma per gestire il file di log l'esperimento non era andato molto in la'

Adesso ho trovato su questo link uno script in Python che converte il file di log in un formato Rinex che puo' essere dato in pasto ad RTKLib per il post processing dei dati 

Attenzione: lo script funziona su Python 3.x e non su Python 2.x

Per la prova ho usato un tablet Nexus 9 (senza supporto cellulare) che come riportato da questo link e'
uno dei pochi dispositivi certificati per funzionare con le API Raw Gnss (anzi e' uno dei pochi con la piena funzionalita')

Si usa quindi GnssLogger (vedi link per l'apk) per l'acquisizione dei dati, lo script android_to_rinex.py per la conversione in Rinex ed RTKPost in modalita' PPP per il post processing


Il risultato finale non e' niente male perche' l'errore si riduce a circa 1 m sui tre assi ed i dati riescono a convergere in meno di un minuto

GNSS Android 8

Tempo fa avevo provato l'applicazione demo delle nuovi API per GNSS di Android. Adesso e' disponibile una applicazione per verificare i dati salvati nel file dati (link). La applicazione Linux e' scaricabile da qui

https://github.com/google/gps-measurement-tools/releases/download/2.4.0.0/GnssAnalysisLinuxV2.4.0.0.zip

Per installare la applicazione si usa un web installer che permette di installare anche il runtime di Matlab senza la necessita' di avere una licenza

La applicazione e' installata di default in

/usr/local/Desktop/GnssAnalysisFiles/application

per lanciare l'applicazione si usa

./run_GnssAnalysisApp.sh ../../../MATLAB/MATLAB_Runtime/v901/

A questo punto si importa il file derivante da Android. In questo caso il file deriva da un Nexus 9 e quindi sono disponibili anche i dati GLONASS



 
Per usare Analyze and Plot si deve essere collegati ad Internet perche' devono essere scaricati in automatico i file delle effemeridi dei satelliti.

Al termine si puo' cliccare sull'icona del robottino verde per ottenere un report in formato HTML

Dalla lettura del file si vedono i test riusciti e quelli falliti. Per esempio


 

The GPS reference threshold is set to 38 dBHz. Well built phones, 
in open sky, have GPS satellites stronger than this threshold. 
GLONASS threshold is 2.5dB lower, since GLO signal is 2.5dB weaker, 
(see GPS and GLONASS ICDs).

For your log file the C/No results are:
GPS, mean of strongest 4 median C/No = 35.6 dBHz
Pass/fail reference threshold = 38.0 dBHz
Errors. Signals -2.4 dB compared to reference
FAIL BECAUSE OF WEAK SIGNALS
GLO, mean of strongest 4 median C/No = 36.0 dBHz
Pass/fail reference threshold = 35.5 dBHz
PASS








Come output si hanno anche i file .mat, .nmea e .derived 

martedì 7 novembre 2017

Motore acceso??

Il problema e' questo : e' possibile determinare se una macchina ferma ha il motore acceso o meno usando un telefono Android??

Si tratta di un problema per una app che dovevo fare ma che poi non ha mai visto la luce e la risposta e' si'....usando la FFT sui dati dell'accelerometro

Il primo grafico e' relativo ad una misura di 30 secondi a macchina ferma e spenta, il secondo sempre su una acquisizione di 30 secondi a macchina ferma ed accesa al minimo del motore



E' abbastanza evidente una frequenza di risonanza della macchina su tutti e tre gli assi intorno ai 40 Hz (il motore girava intorno ai 900 rpm ma quello che si registra e' la vibrazione di tutta la struttura)

venerdì 20 ottobre 2017

Foto ed imageview su Android

Aggiornamento: facendo delle prove con Nexus 5x e Nexus 9 ho scoperto che l'immagine risulta ruotata di 90° nonostante non ci siano modifiche nel codice
A questo link viene descritto il medesimo problema

Un sistema per una app che scatta una foto e mette il risultato in una imageview ed effettua il salvataggio (gestione dei permessi di scrittura non gestita..vedi post precedenti)



-----------------------------------------------
package com.example.lucainnocenti.photonotation;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;


public class MainActivity extends AppCompatActivity {
    private static final int CAMERA_REQUEST = 1888;
    private ImageView foto;
    private Bitmap ff;


    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        foto = (ImageView) findViewById(R.id.imageView);
        Button scatto = (Button) findViewById(R.id.button);


        scatto.setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View view) {
                Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(camera, CAMERA_REQUEST);
            }
        });


    }
    protected void onActivityResult(int requestCode,int resultCode, Intent data)
    {
        if (requestCode== CAMERA_REQUEST && resultCode == Activity.RESULT_OK){
            ff = (Bitmap) data.getExtras().get("data");
            foto.setImageBitmap(ff);
            foto.setImageURI(data.getData());
            Bitmap bm=((BitmapDrawable)foto.getDrawable()).getBitmap();
            saveImageFile(bm);
        }

    }

    public String saveImageFile(Bitmap bitmap) {
        FileOutputStream out = null;
        String filename = getFilename();
        try {
            out = new FileOutputStream(filename);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.d("luca22","Errore");
        }
        return filename;
    }

    private String getFilename() {
        File file = new File(Environment.getExternalStorageDirectory()
                .getPath(), "TestFolder");
        if (!file.exists()) {
            file.mkdirs();
        }
        String uriSting = (file.getAbsolutePath() + "/"                + System.currentTimeMillis() + ".jpg");
        Log.d("luca22",uriSting);
        return uriSting;
    }
}

Azimuth Pitch e Roll su Android N

Gestione dei sensori con RotationMatrix su Android



--------------------------------------------------------------
package com.example.lucainnocenti.sensori;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity implements SensorEventListener{

    private SensorManager mSensorManager;
    private final float[] mAccelerometerReading = new float[3];
    private final float[] mMagnetometerReading = new float[3];

    private final float[] mRotationMatrix = new float[9];
    private final float[] mOrientationAngles = new float[3];
    private Sensor mAccelerometer;
    private Sensor mMagnetometer;

    private double az;
    private double pi;
    private double ro;


    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);


    }

    @Override    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    @Override    protected void onResume() {
        super.onResume();

        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
        mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);

    }

    @Override    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    @Override    public void onSensorChanged(SensorEvent event) {

        if (event.sensor == mAccelerometer) {
            System.arraycopy(event.values, 0, mAccelerometerReading, 0, mAccelerometerReading.length);
        }
        else if (event.sensor == mMagnetometer) {
            System.arraycopy(event.values, 0, mMagnetometerReading, 0, mMagnetometerReading.length);
        }
        updateOrientationAngles();
    }


    public void updateOrientationAngles() {
        mSensorManager.getRotationMatrix(mRotationMatrix, null, mAccelerometerReading, mMagnetometerReading);
        mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles);
        az = Math.toDegrees(mOrientationAngles[0]);
        pi = Math.toDegrees(mOrientationAngles[1]);
        ro = Math.toDegrees(mOrientationAngles[2]);
        Log.d("orienta", "Az:"+String.valueOf(az)+" Pi:"+String.valueOf(pi)+" Ro:"+String.valueOf(ro));

    }
}

GPS su Android N

Un esempio di uso del GPS su Android N con getione dei permessi. Evidenziate in giallo le parti di codice di gestione dei permessi


---------------------------------------------------
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.lucainnocenti.gpstest">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>
---------------------------------------------------



---------------------------------------------------
package com.example.lucainnocenti.gpstest;

import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity implements LocationListener{

    LocationManager locationManager;
    String provider;
    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        provider = locationManager.getBestProvider(new Criteria(), false);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            checkLocationPermission();
            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);

        if (location != null) {

            Log.i("Location Info", "Location achieved!");

        } else {

            Log.i("Location Info", "No location :(");

        }
    }

    @Override    protected void onResume() {
        super.onResume();

        if (checkLocationPermission()) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                locationManager.requestLocationUpdates(provider, 400, 1, this);
            }
        }

    }

    @Override    protected void onPause() {
        super.onPause();

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            checkLocationPermission();
            return;
        }
        locationManager.removeUpdates(this);

    }

    @Override    public void onLocationChanged(Location location) {

        Double lat = location.getLatitude();
        Double lng = location.getLongitude();

        Log.i("Location info: Lat", lat.toString());
        Log.i("Location info: Lng", lng.toString());

    }

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

    }

    @Override    public void onProviderEnabled(String provider) {

    }

    @Override    public void onProviderDisabled(String provider) {

    }

    public void getLocation(View view) {

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);

        onLocationChanged(location);


    }

    public boolean checkLocationPermission() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)) {


                new AlertDialog.Builder(this)
                        .setTitle("Permesso GPS")
                        .setMessage("Permesso GPS")
                        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override                            public void onClick(DialogInterface dialogInterface, int i) {
                                //Prompt the user once explanation has been shown                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .create()
                        .show();


            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);
            }
            return false;
        } else {
            return true;
        }
    }

    @Override    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                        locationManager.requestLocationUpdates(provider, 400, 1, this);
                    }

                } else {

                    // permission denied,

                }
                return;
            }

        }
    }
}

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...