legacy:
Infatti tu hai pensato subito alle quadratiche pure, iterative magari (lente per definizione di convergenza), l'ho capito al volo da come hai risposto
No io ho pensato a una lut full table che è il modo più rapido in assoluto per fare i calcoli, però costa molto a livello di memoria, nel caso specifico ben 720 MegaByte esatti per tabellare i 90000000 di seni/coseni precalcolati a 64 bit, poi è lo stesso valore angolare, convertito come long int, a fare da indice per la tabella, una manciata di cicli macchina e hai il valore pronto senza dover fare nessun calcolo reale.
Comunque non vedo per quale motivo devo complicarmi la vita per fare un calcolo complesso su una piccola mcu 8 bit, che a stento arriva a 10 mips medi reali e non ha nessun supporto matematico, quando con un paio di Euro in più posso avere un Cortex M3 , o M4, che non ha problemi per fare calcoli a 64 bit e tutto il conteggio lo fa in meno di 200 microsecondi (a 64 bit), se poi aggiungo ancora un Euro ci metto un Cortex M4 con FPU ed ecco che il conto richiede meno di 50 us.
Distanza e angolo li trovi con uno dei vari calcolatori online che fanno il calcolo oppure ti diverti con la calcolatrice scientifica e te li fai da solo, se ne hai una programmabile ti puoi pure divertire a scrivere il programmino che ti fa il conto in automatico
Ho fatto un test al volo con un modulo mBed, rammento che usa un core Cortex M3 @96 MHz, tutto il calcolo della distanza e dell'angolo a 64 bit richiede circa 280 us, i valori ottenuti sono distanza 171.89 metri e angolo 55.73°, esattamente gli stessi che ottengo con un programma in C sul desktop.
Il programma di test usato è il seguente, è in C ANSI e salvo le funzioni di inizializzazione dell'ambiente hardware e quelle di stampa sulla seriale, specifiche per l'mBed, è utilizzabile direttamente con qualunque altro micro e compilatore C.
/*
TEST distanza e bearing tra coordinate GPS
mBed Cortex M3 @ 96MHz
*/
// declarations
#include "mbed.h"
#define RADS 57.2957795131
#define Metri_Per_Rad 6366692,0724
double a,b,c;
double Lat1,Lat2,Lon1,Lon2;
// servono per inizializzare i quattro led di stato del modulo, non fanno parte dei pin a disposizione.
DigitalOut LD1(LED1);
DigitalOut LD2(LED2);
DigitalOut LD3(LED3);
DigitalOut LD4(LED4);
// inizializza la Vcom USB integrata sul modulo
Serial pc(USBTX, USBRX); // tx, rx
// Inizializza una seriale hardware per collegarci il GPS, per il momento non utilizzata
// Serial gps(p9,p10);// tx, rx
int main() {
pc.baud(115200);
pc.printf("Start TEST\n");
LD1 = 1;
Lat1 = 42.857818;
Lon1 = 12.563545;
Lat2 = 42.858689;
Lon2 = 12.561801;
while (1)
{
LD2 = 1; // accende il led 2, viene usato per misurare la velocità di esecuzione tramite DSO
a = acos(sin(Lat1/RADS)*sin(Lat2/RADS) + cos(Lat1/RADS)*cos(Lat2/RADS)*cos((Lon1-Lon2)/RADS));
b = a * Metri_Per_Rad;
c = acos((sin(Lat2/RADS) - sin(Lat1/RADS)* cos(a)) / (cos(Lat1/RADS) * sin(a)));
c *= RADS;
LD2 = 0; // spegne il led 2
pc.printf("Distanza : %3.2f \n",b);
pc.printf("Angolo : %3.2f \n",c);
}
}
stavo pensando: se il GPS funzona a 10Hz (ed è tanto), abbiamo 100ms per elaborare input e tutto prima che sia "vecchio".
Se noi scompoiniamo il calcolo in modo tale che ogni loop eseguiamo solo un'operazione sin/cos/atan, il tempo di elaborazione complessiva magari sale a 10 ms, ma almeno non blocchiamo il loop, anzi sfruttiamo i tempi morti causati dalla frequenza massima di lavoro dei giroscopi.
Sicuramente puoi pure scomporre il conto in operazioni singole da fare durante i vari cicli in modo da non gravare troppo, però non è che una volta che hai la distanza e l'angolo hai finito, devi usarli per correggere la rotta, e questo comporta altro lavoro per la cpu, comunque c'è sempre il piccolo problema della matematica a 64 bit che non hai a disposizione.
nei miei test a 32bit è qulla che più si è avvicinata al risultato corretto (errore di 3 gradi se ricordo bene, contro gli oltre 10 degli altri 2 metodi)
se invece vuoi seguire la strada per la distanza, almeno usa il codice per la distanza che ho postato "a prova di virgola mobile"
edit: questa:
//i dati sono già in radianti
da = sin((lat1-lat2)/2);
db = cos(lat1)cos(lat2)(sin((lon1-lon2)/2));
d=2asin(sqrt( dada+db*db )); //distanza in radianti
lesto:
se invece vuoi seguire la strada per la distanza, almeno usa il codice per la distanza che ho postato "a prova di virgola mobile"
Non puoi gestire calcoli trigonometrici con valori angolari a sei cifre decimali con i float a 32 bit senza perdere tantissima risoluzione/precisione.
Qui si parla di apprezzare variazioni di non più di un metro di percorso, ovvero poco meno di 10 milionesimi di grado inteso come distanza angolare sulla sfera terrestre.
Le tue formule le ho provate, forniscono risultati totalmente sbagliati sulla distanza se applicate a 32 bit, non le ho provate a 64 bit, l'angolo è meno critico da calcolare e forse si riesce a farlo pure a 32 bit, ma senza la distanza non serve a nulla.
finalmente un pò di tempo libero, e mi son dedicato alla programmazione della IMU.
ecco alcuni dati:
allora, ho i due sensori ADXL345 e ITG3200, con cui comunico senza problemi.
ora, con la libreria wire "normale", ovvero TWI_FREQ = 100000L, leggo i sensori a queste velocità:
solo giro ~ 1kHz
solo acc ~ 1kHz
giro + acc ~ 0.5kHz
come potete notare il problema grosso è la banda disponibile di comunicazione, dato che il giroscopio è settato per campionare a 8kHz e l'accelerometro a 3.2kHz.
allora, dato che entrambi i sensori lo supportano, ho usato il fast wire, alzando il TWI_FREQ = 400000L
risultati:
solo giro ~ 2.8kHz
solo acc ~ 2.8kHz
giro + acc ~ 1.2kHz
che dire? l'i2c da questo punto di vista fa alquanto pena. (edit: bisogna passare a SPI, ma non c'è sulla breakout che uso)
ecco i dati raw che ho usato:
colonna 1: numero di update del gyro, colonna2: numero di update consecutivi con differenti valori (per testare la velocità di campionamento), colenna 3 e 4 stessa cosa ma dell'accelerometro, colonna 5 numero di millis di raccolta dati (1 secondo)
edit2: bisognerebbe iniziare a fare una board che usa SPI...
ma mi sono accorto che il giroscopio NON supporta lo SPI... com'è possibile? cioè, allora a che serve la capacita di campionare a più di 3kHz?
Cerco consiglio! Vorrei aggiungere il barometro Possiedo una IMU 9 DOF Drotek, e ho visto che potrei aggiungere barometro bma per 10e o quello piu' bello MS5611 per 17. Pero' nell'ottica di spendere il giusto per avere una cosa della quale non possa pentirmi dopo (spazio, semplicità) pensavo che potrei provare a smerciare la mia 9dof per acquistarne una 10dof. Penso che almeno a dati di targa quest'ultimo barometro con il chip 6050 dovrebbero avere prestazioni migliori...
A sto punto, penso che la FreeIMU al momento monti l'equipaggiamento migliore, 84 euro.
MPU6050 gyro & accelerometer + HMC5883L magnetometer + MS5611 altimeter + LLC
Mentre la analoga Drotek, SENZA LLC viene 65. LLC che al momento non possiedo ma penso sarebbe ottimale utilizzando un arduino 5v. Nel config pero' di questa IMU loro la collegherebbero bella bella al 5v senza farsi problemi: http://www.drotek.fr/shop/en/62-imu-10dof-mpu6050-hmc5883-ms5611.html
Rinnovando il consiglio che cerco nel post precedente (anche se ho letto sul sito di varesano che l' LLC e' una cosa che non serve se il codice e' fatto bene) aggiungo una domanda.
Necessità da risolvere: sapere a terra quanta batteria mi rimane
Idea che mi e' venuta per ora, ma vorrei vedere se voi ne avete altre, aggiungere un secondo arduino, buttare in Analog le celle della lipo (3 celle 3 analog read) e trasmettere a terra via xbee. A terra avere un arduino con un lcd alimentato a pile dove leggo i valori.
Alternativamente, col partitore di tensione usare la funzione batteria di multiwii e trasmettere via bt sul cellulare, se mai prima o poi l'autore di multiwiiconfig per android aggiungera' la lettura dello stato della batteria.
Oppure ancora spendere un pacco di soldi per avere la telemetria sulla radio...
Adesso mi ingegno e vediamo su quale soluzione posso puntare.
Nel frattempo nei prossimi giorni mi dedichero' con mio fratello al sonar e alla scrittura del codice per far girare un sonar analogico che possiedo...
vai su baronerosso.it, sul forum multirotori troverai una bella discussione su un progetto simile.
il problema più grande sono i motori, probabilmente fatti su misura, e il pacco batterie