Autore Topic: Calcolo dislivello tra 2 posizioni  (Letto 725 volte)

Offline crc_error

  • Utente junior
  • **
  • Post: 85
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    LG-P500
  • Sistema operativo:
    Windows 8, Ubuntu 12
Calcolo dislivello tra 2 posizioni
« il: 25 Luglio 2013, 10:07:35 CEST »
0
Ciao a tutti, non so se è la sezione giusta in cui postare il 3d...

Come da titolo il mio problema è il calcolo del dislivello tra 2 posizioni. Per test sto creando un logger di posizioni GPS e tra i vari valori registrati ci sono anche il dislivello in salita, in discesa e totale.

Sulla carta sembra una stupidata, prendi l'altitudine della Location fornita dal location listener e la sottrai all'ultima posizione "buona" memorizzata. Se il valore è positivo il dislivello è in salita viceversa è in discesa.
Semplice no?

no...

Per qualche strana ragione se faccio così mi vengono dislivelli anche di 12km su un giro che normalmente ne prevede 500mt al massimo...
E non so perchè... Sono giorni che ci perdo la testa sopra e non vedo la luce..

Così mi sono inventato un paio di array (uno per il dislivello in su e uno in giù), butto dentro i valori e se la lunghezza è di 5 faccio la media e ritorno il dislivello.

Ma neanche così funziona, sul giro di ieri ho un dislivello in salita di 341 m mentre il Garmin mi da 268 m..


Codice (Java): [Seleziona]
//Questo è il codice che elabora la Location fornita dal listener sul GPS

        // DISLIVELLO =================================================================
        // DISLIVELLO PARZIALE ====================================================
        dislivelloParziale = (loc.getAltitude() - lastPosValida.getAltitude());
        CalcolaDis calcolaDis = new CalcolaDis(dislivelloParziale);
        Future<Double> fuDis = elaboraPosizione.submit(calcolaDis);
        double dislivello = fuDis.get();

        if (dislivelloParziale > 0)
                trkDisUp += dislivello;
        else if (dislivelloParziale < 0)
                trkDisDw += dislivello;


        // DISLIVELLO TOTALE =======================================================
        if (dislivelloParziale < 0 || dislivelloParziale > 0)
                trkDisTo = trkDisUp + trkDisDw;                

Questo invece è il calcolo per la media sulle posizioni

Codice (Java): [Seleziona]
        private static class CalcolaDis implements Callable<Double> {
               
                double dis;
               
                private CalcolaDis(double dislivello) {
                        this.dis = dislivello;
                }
               
                @Override
                public Double call() throws Exception {
                        double d = 0;
                       
                        if(Double.isInfinite(this.dis) || Double.isNaN(this.dis))
                                return d;
                       
                        if(this.dis > 0) {
                                if(listDisUp.size() < 5) {
                                        listDisUp.add(this.dis);
                                }
                                else {
                                        d = calcolaDouble(listDisUp);
                                        listDisUp.clear();
                                }
                        } else if(this.dis < 0) {
                                if(listDisDw.size() < 5) {
                                        listDisDw.add(Math.abs(this.dis));
                                }
                                else {
                                        d = calcolaDouble(listDisDw);
                                        listDisDw.clear();
                                }                              
                        }

                        return d;
                }              
        }
       
        private static double calcolaDouble(ArrayList<Double> valore) {
                double totV = 0, toRet = 0f;
               
                for(double v : valore)
                        totV += v;
               
                if(valore.size() > 0 && totV > 0)
                        toRet = totV / valore.size();
               
                if(Double.isNaN(toRet) || Double.isInfinite(toRet))
                        return 0;
               
                return toRet;
        }

Questo invece è il codice all'avvio del servizio

Codice (Java): [Seleziona]
        private static ExecutorService elaboraPosizione;
        private static ArrayList<Double> listDisUp = new ArrayList<Double>();
        private static ArrayList<Double> listDisDw = new ArrayList<Double>();

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
               
                // servizio inizializzato =================================================================
                elaboraPosizione = Executors.newSingleThreadExecutor();
                setGpsReceiverEnable();  // attivo il listener sul GPS         
       
                return START_STICKY;
        }


Come posso risolvere? Perchè "sbarella" così.. Dov'è che sbaglio?

Grazie mille ;)

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:Calcolo dislivello tra 2 posizioni
« Risposta #1 il: 25 Luglio 2013, 10:42:13 CEST »
0
l'altitudine dei GPS negli smartphone non è per nulla precisa, ti dovresti affidare a qualche servizio online
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline crc_error

  • Utente junior
  • **
  • Post: 85
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    LG-P500
  • Sistema operativo:
    Windows 8, Ubuntu 12
Re:Calcolo dislivello tra 2 posizioni
« Risposta #2 il: 25 Luglio 2013, 11:00:27 CEST »
0
Lo so, ma il valore vorrei averlo in tempo reale e per farlo dovrei fare una richiesta ad ogni posizione...
Inoltre alcune zone il GSM non prende.. Senza contare i costi e il consumo extra della batteria per le richieste.. :(


Nella tabella dove salvo le posizioni però ho notato che non ci sono brusche variazioni, l'altitudine scende e sale in maniera progressiva. Non capisco perchè sbarelli così tanto..


Son giorni che ci guardo e oramai ho finito le idee..

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Calcolo dislivello tra 2 posizioni
« Risposta #3 il: 25 Luglio 2013, 15:30:32 CEST »
0
L'errore molto alto sull'altitudine è normale col solo uso del GPS. E' per questo motivo che alcuni GPS costosi e alcuni telefoni Android di fascia alta hanno tra i sensori anche il barometro. Il barometro riporta una stima più corretta e in tempi inferiori rispetto al solo uso del GPS dell'altitudine vera.
adb logcat | tee /tmp/logcat | grep TAG

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Calcolo dislivello tra 2 posizioni
« Risposta #4 il: 25 Luglio 2013, 19:13:22 CEST »
0
Hai citato un Garmin. Occhio, dipende da qual'è l'oggetto a cui ti stai riferendo, ma potrebbe recuperare le informazioni di altitudine dalla mappa e non dal GPS.

Riguardo la precisione del GPS, l'accuratezza teorica (cioè con un ricevitore GPS perfetto) è circa +/- 25 metri. Metti in conto un ricevitore GPS meno che perfetto e vedi che se cumuli un errore di +/- 25 metri ad ogni lettura, è facile arrivare alle cifre di cui parli.

Fossi in te eviterei di memorizzare ad ogni lettura solo il DELTA, ma memorizzerei l'altezza assoluta, così facendo non cumuli gli errori di ogni lettura, ma sottraendo ultima lettura e prima lettura, l'errore ce l'hai solo due volte (uno per lettura). Poi potresti pensare di fare letture più fitte, passare i dati dentro un filtro a soglia (butti via il valore più alto e il valore più basso, poi fai la media, come nei tuffi alle olimpiadi) ed memorizzare ogni volta solo il valore mediato. Ma quale sia alla fine il modo che più fa al caso tuo lo puoi scoprire mettendo una bella tabella di acquisizioni raw dentro excel e provando vari approcci numerici per rimuovere il rumore e gli errori.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store