Projet

Général

Profil

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "trame.h"
#include <math.h>
#define R 6370
#define PI 3.14159265

typedef struct {
float lat;
float lon;
}position;

typedef struct {
position rpos;
float vitmax;
}zone;

zone zones[] = {
{{44.7887762, -3.012}, 50},
{{44.7891220, -3.013}, 70},
{{45.750000, 3.216700}, 110}, // zone route limit?e ? 110km/h vers Cournon d'Auvergne
};

char * t[]={"$GPGGA,141914.00,4545.0000,N,00306.6036,E,1,05,3.4,499.3,M,,M,,*7D"};

position p1, p2, p3, p4, p5, p6, p7;
float d;

//Trames de tests ? modifier si n?cessaire.
char * trames[]= {"$GPGSV,3,2,10,15,03,077,,18,04,041,42,19,85,271,,20,08,214,*7C",
"$GPGSV,3,3,10,22,39,053,50,28,15,320,*7E",
"$GPRMC,141914.00,A,4545.6424,N,00306.6036,E,0.4,99.4,010206,,*0C",
"$GPGLL,4545.6424,N,00306.6036,E,141914.00,A*0E",
"$GPGGA,141914.00,4545.0000,N,00306.6036,E,1,05,3.4,499.3,M,,M,,*7D",
"$GPGSA,A,3,,03,,22,14,,01,,18,,,,3.9,3.4,1.9*39",
"$GPVTG,99.4,T,,M,0.4,N,0.7,K*57",
"$GPZDA,141914.00,01,02,2006,00,00*69",
0};

int decode_int(char c)
{
if((c-48<0)||(c-48>9)) // v?rifie si le caract?re est un chiffre entre 0 et 9
return -1;
else
return c-48;
}

int decode_nombre(char *ch,int i,int n) // converti un nombre type cha?ne de caract?re en type entier
{
int res=0;
int j;
for(j=i;j<i+n;j++)
res=(res*10)+decode_int(ch[j]);
return res;
}

float latitude(char *ch)
{
float r, r1, r2, r3;
r1 = decode_nombre(ch,17,2); //d?code les degr?s en sexagesimal dans la trame
r2 = decode_nombre(ch,19,2); //d?code les minutes en sexagesimal dans la trame
r3 = decode_nombre(ch,22,4); //d?code les secondes en sexagesimal dans la trame
r = r1 + (r2 + r3/10000)/60; //conversion sexagesimal ? degr?s
if(ch[27]=='S') //identifie la polarit? de la latitude
r = -r;
return r;
}

float longitude(char *ch)
{
float r, r1, r2, r3;
r1 = decode_nombre(ch,29,3); //d?code les degr?s en sexagesimal dans la trame
r2 = decode_nombre(ch,32,2); //d?code les minutes en sexagesimal dans la trame
r3 = decode_nombre(ch,35,4); //d?code les secondes en sexagesimal dans la trame
r = r1 + (r2 + r3/10000)/60;
if(ch[40]=='W')
r = -r;
return r;
}

float decode_trame_latitude(char *ch) // une position est donn?e par deux fonctions : decode_trame_latitude() et decode_trame_longitude()
{
position p1;
p1.lat = latitude(ch);
return p1.lat;
}

float decode_trame_longitude(char *ch) // une position est donn?e par deux fonctions : decode_trame_latitude() et decode_trame_longitude()
{
position p1;
p1.lon = longitude(ch);
return p1.lon;
}


float calcul_distance(position p1, position p2) // Etablie une distance en km entre deux positions
{
float a;
a = sqrt(pow((p2.lat-p1.lat)*PI*R/180.0,2)+pow(((p2.lon-p1.lon)*(cos(((p2.lat+p1.lat)/2.0)*PI/180.0)*PI*R/180.0)),2));
//a=R*sqrt(pow(p1.lat*PI/180-p2.lat*PI/180,2)+pow(sin(p1.lat*PI/180-p2.lat*PI/180),2)*pow(p1.lon*PI/180-p2.lon*PI/180,2));
return a;
}

float calcul_vitesse(position p1, position p2) // Etablie une vitesse en km/h entre deux positions en prenant en compte 1 seconde comme fr?quence d'?chantillonage des trames
{
float v;
v=calcul_distance(p1,p2)*3600;
return v;
}

int trame_cmp(char * trame,char * type) // Verification du format GPGGA d'une trame GPS
{
int i;
for (i=0;i<5;i++)
if (trame[i+1] != type[i])
return 0;
return 1;
}

int distance_a_la_plus_proche_zone(position p, zone r[], int nb_zones, float *d) // Renvoie l'indice de la zone la plus proche dans le tableau zones connu ? l'avance ? partir d'une position
{
int i,j=0;
float min = calcul_distance(p,r[0].rpos);
for (i=0;i<nb_zones;i++)
{
if (calcul_distance(p,r[i].rpos) <= min)
{
min = calcul_distance(p,r[i].rpos);
j=i;
}
}
return j;
}

void afficher_alarme(int alarme)
{
if (alarme == 1)
printf("Alarme : ON\n"); // l'alarme s'active lorsque la fonction alarme() renvoie 1
else // sinon renvoie 0 elle ne s'active pas
printf("Alarme : OFF\n");
}

int alarme(char *trame) // On veut activer l'alarme lorsque la distance est inf?rieur ? seuil = 0.1km et v > vmax correspondant au tableau zones
{
static int i=0;
int a,j, alarme;
float v, vmax, d, seuil = 0.1; // seuil d?fini ? 0.1km arbitrairement
position p1, p2;
p1.lat = decode_trame_latitude(trame); // r?cup?re la position de la premi?re trame re?u
p1.lon = decode_trame_longitude(trame);
p2.lat = decode_trame_latitude(&t); // r?cup?re la position de la trame re?u juste apr?s
p2.lon = decode_trame_longitude(&t);
v = calcul_vitesse(p1,p2); // r?cup?re la vitesse maximale autoris?e dans une zone dangereuse
vmax = zones[i].vitmax;
j=distance_a_la_plus_proche_zone(p2,zones,3,&d); // r?cup?re l'indice de la zone dangereuse la plus proche
d=calcul_distance(p2,zones[j].rpos);
i++;
if ((d < seuil) && (v > vmax)) // si on est trop proche de la zone avec une vitesse au-del? de la limitation l'alarme s'active (?tat 1);
alarme = 1;
else
alarme = 0; // sinon l'alarme ne s'active pas (?tat 0)
return alarme;
}



//Fonction ? modifier !!!!!
void traitement(char * trame)
{
static int cpt=0, k=0;
cpt++;
if(trame_cmp(trame,"GPGGA")==1)//verifie le bon format de la trame
{
printf("> %s\n",trame);
printf("La latitude est %f.\nLa longitude est %f.\n",decode_trame_latitude(trame),decode_trame_longitude(trame));
t[k+1]=trame; // on stock dans un tableau t les trames re?u pour pouvoir prendre 2 trames cons?cutives et faire les calculs
k++;
afficher_alarme(alarme(trame));
}
}


//Ajoutez vos tests unitaires dans cette fonction.
void tests_unitaires(void){
if (5!=5)
{
printf ("Erreur Test unitaire basique.\n");
exit(-1);
}
if (trame_cmp("$GPGGA suite chaine","GPGGA")!=1)
{
printf ("Erreur Test unitaire trame_cmp.\n");
exit(-1);
}
if (trame_cmp("$GPRMC suite chaine","GPGGA")!=0)
{
printf ("Erreur Test unitaire trame_cmp.\n");
exit(-1);
}
if(decode_int('0')!=0)
{
printf ("Erreur Test unitaire decode int.\n");
exit(-1);
}
if(decode_nombre("7558",0,2)!=75)
{
printf ("Erreur Test unitaire decode nombre.\n");
exit(-1);
}
if(decode_nombre("7558",3,1)!=8)
{
printf ("Erreur Test unitaire decode nombre.\n");
exit(-1);
}
// pr?cise ? 10e-6 pr?s car 2 floattants ne peuvent pas ?tre compar?s directement
if(fabs(latitude("$GPGGA,141914.00,4545.0000,N,00306.6036,E,1,05,3.4,499.3,M,,M,,*7D")-45.75) > 1e-6)
{
printf ("Erreur Test unitaire latitude.\n");
exit(-1);
}
if(fabs(longitude("$GPGGA,141914.00,4545.0000,N,00306.6036,E,1,05,3.4,499.3,M,,M,,*7D")-3.11006) > 10e-6)
{
printf ("Erreur Test unitaire longitude.\n");
exit(-1);
}
p1.lat = 48.856614; // Paris
p1.lon = 2.352221;
p2.lat = 43.296482; // Marseille
p2.lon = 5.369780;
p3.lat = 45.774838; // Clermont
p3.lon = 3.084583;
p4.lat = 45.762011; // Lyon
p4.lon = 4.834542;
p5.lat = 47.3215806; // dijon
p5.lon = 5.0414701;
p6.lat = 45.750000; // trame ?nonc? (pr?paration s?ance 2 question 6)
p6.lon = 3.110060;
p7.lat = 45.750403; // trame ?nonc? (pr?paration s?ance 2 question 6)
p7.lon = 3.110065;
if (calcul_distance(p1,p2)<=660 && calcul_distance(p1,p2)>= 661) // Test distance Paris - Marseille qui doit ?tre 660,X km.
{
printf("Erreur test unitaire calcul_distance1");
exit(-1);
}
if (calcul_distance(p3,p5)<=227 && calcul_distance(p3,p5)>= 228) // Test distance Clermont - Dijon qui doit ?tre de 227,X km.
{
printf("Erreur test unitaire calcul_distance2");
exit(-1);
}
if (calcul_distance(p3,p4)<=135 && calcul_distance(p3,p4)>= 136) // Test distance Lyon - Clermont-Ferrand qui doit ?tre de 135,X km.
{
printf("Erreur test unitaire calcul_distance3");
exit(-1);
}
if (calcul_distance(p6,p7)<=0.0500 && calcul_distance(p6,p7)>= 0.0499) // Test distance entre les deux trames de l'?nonc? qui doit ?tre de 44,9XX m?tres
{
printf("Erreur test unitaire calcul_distance4");
exit(-1);
}
if (calcul_vitesse(p6,p7)<=161 && calcul_vitesse(p6,p7)>= 162) // Test calcul vitesse des trames de l'?nonce qui doit ?tre de 161,XXX km/h
{
printf("Erreur test unitaire calcul_vitesse");
exit(-1);
}
if (distance_a_la_plus_proche_zone(p7,zones,3,&d)!=2) // La 3?me zone doit ?tre la plus proche.
{
printf("Erreur test unitaire calcul_distance_a_la_plus_proche_zone");
exit(-1);
}
}




// Ne pas modifier cette fonction
int main(int argc,char ** argv)
{
tests_unitaires();
// Affichage des trames definies dans la table trames.
printf ("Trames de tests tableau trames:\n");
int i=0;
while (trames[i])
traitement(trames[i++]);
if (!trame_init())
exit(-1);
// Affichage des trames du fichier gps.log
char *trame;
printf ("Trames de tests du fichier gps.log\n");
while ((trame = trame_suivante()))
traitement(trame);
return 0;
}


(2-2/5)