algoritmo logica difusa sensores navegacion

Dependencies:   GPS MODI2C SRF05 mbed HMC5883

main.cpp

Committer:
arturocontreras
Date:
2014-07-19
Revision:
0:1c15748ff0e1

File content as of revision 0:1c15748ff0e1:

#include "mbed.h"       // Standard Library
#include "HMC5883.h"    // Comp (Compass)
#include "GPS.h"
#include "SRF05.h"

#define PI             3.1415926535897932384626433832795
DigitalOut myled(LED1);
I2C I2CBus(p9, p10);
Timer GlobalTime;

SRF05 Ult1(p5, p6);
SRF05 Ult2(p7, p8);
SRF05 Ult3(p11, p12);
SRF05 Ult4(p16, p15);

Serial pc(USBTX, USBRX);
HMC5883     Mag(I2CBus, GlobalTime);
GPS gps(p13, p14);

float longitud,latitud,ul1,ul2,ul3,ul4;
int orientacion;


void GPfuzzy(float P[],int n,float v,float GP[],int mf[]);         
float min(float a,float b);
float Sugeno(int v1,int v2,float P[],int n);
float Centroide(int v1,int v2,float P[],int n);
void GPIfuzzy(float P[],int n,int gx,float GP,float x[]);
void EntradaU(float F[],float O[],int ultrasonico,float tetha,float entrada[],float gp[],int mf[]);
int  reglas(int mf[],int mfrueda[],float gpin[],float gprueda[]);
void desfuzzy(float Pm[],int n,int mfrueda[],float gprueda[],int size,float dutty[]);


int HMC5883_getAngle(float x, float y)
{
float heading = atan2((float)y,(float)x); 
// Your mrad result / 1000.00 (to turn it into radians).
  float declinationAngle = 21.18  / 1000.0;
  // If you have an EAST declination, use += declinationAngle, if you have a WEST declination, use -= declinationAngle
  heading += declinationAngle;  
if(heading < 0)  heading += 2*PI;// Correct for when signs are reversed.
if(heading > 2*PI)   heading -= 2*PI; // Check for wrap due to addition of declination.
return(heading * 180/PI); // Convert radians to degrees for readability.
}

int main() { // main programm for initialisation and debug output
      // pc.baud(9600);
  
    I2CBus.frequency(400000);
    GlobalTime.start();

    Mag.Init();
    #if 1
        Mag.AutoCalibration= 1;                     //In Echtzeit kalibrieren
    #else
        short MagRawMin[3]= {-400, -400, -400};     //Gespeicherte Werte
        short MagRawMax[3]= {400, 400, 400};
        Mag.Calibrate(MagRawMin, MagRawMax);
    #endif
    
   int size,n=5,ultrasonico=3,mfs[4],mfrueda[4];
   float dutty[2],entrada[2],tetha,gradosp[4],gprueda[4];
   float Pm[5]={0,25,50,75,100};//RANGO DE DUTTY PARA MOTORES (p.e. de 0 a 100)
    
    while(1) { 
    
    Mag.Update();
       
    printf("grader = %i \n",HMC5883_getAngle(Mag.Mag[0],Mag.Mag[1])); 
    wait_ms(20);
    
 
    if(gps.sample()) {
    myled = 1;//indica si el GPS esta enviando valores buenos
    latitud=gps.latitude;
    longitud=gps.longitude;
    } 
    

    orientacion=HMC5883_getAngle(Mag.Mag[0],Mag.Mag[1]);
    
  //  beta=atan((F[0]-O[0])/(F[1]-O[1]))*57.29582790879777;
    

   
//CONFIGURACION DE ENTRADAS A LA LOGICA FUZZY********************************************
   
   float O[]={0,0};//POSICION INICIAL SEGUN GPS, EN EL PLANO
   float F[]={3,4};//OBJETIVO O POSICION FINAL
   tetha=orientacion;//en sexagesimales, ang de la brujula medido desde el eje NORTE sentido horario(positivo)
   ultrasonico=1;
//fin de CONFIG DE ENTRADAS******************************************************

 
    EntradaU(F,O,ultrasonico,tetha,entrada,gradosp,mfs);//hace la fuzzyfication

   size=reglas(mfs,mfrueda,gradosp,gprueda);//esta funcion bota los vectores mfrueda y sus gprueda

    desfuzzy(Pm,n,mfrueda,gprueda,size,dutty);
    printf("\fdutty1 %f \ndutty2 %f",dutty[0],dutty[1]);
    //wait_ms(100);
    
    
    }
}
//*****************DESARROLLO DE FUNCIONES**************************
void GPfuzzy(float P[],int n,float v,float GP[],int mf[]){//v==> valor eje x
    int i;
    for( i=0;i<n;i++){//
        if(P[i]<=v && v<=P[i+1]){
            GP[0]=1.0-(v-P[i])*1.3333/(P[i+1]-P[i]);
            GP[1]=1.0+1.33333*(v-P[i+1])/(P[i+1]-P[i]);
            if(GP[1]<0){GP[1]=0;}
            if(GP[0]<0){GP[0]=0;}
            mf[0]=i+1;
            mf[1]=i+2;
            break;
        }
    }
}
float min(float a,float b){
    if(a<=b)return a;
    else return b;
}
float max(float a,float b){
    if(a>=b)return a;
    else return b;
}
float Sugeno(int v1,int v2,float P[],int n){//bota el centroide
    int i;
    float a,GP1[3],GP2[3],num=0,area=0,mf[3];
    for(i=1;i<=(v2-v1);i++){
      /*  GPfuzzy(P,n,v1+i-1,GP1,mf);
        GPfuzzy(P,n,v1+i,GP2,mf);*/
        a=(max(GP1[0],GP1[1])+max(GP2[0],GP2[1]))/2;
        num=num+a*max(GP1[0],GP1[1])/2;
        area=area+a;
    }

    return num/area;
}

float Centroide(int v1,int v2,float P[],int n){//bota el centroide
    int i,L=50;
    float a,GP1[3],GP2[3],num=0,area=0;
    for(i=1;i<=L;i++){
        //GPfuzzy(P,n,v1+i-1,GP1,mf);
        //GPfuzzy(P,n,v1+i,GP2,mf);
        a=(max(GP1[0],GP1[1])+max(GP2[0],GP2[1]))/2;
        num=num+a*max(GP1[0],GP1[1])/2;
        area=area+a;
    }
    return num/area;
}


void GPIfuzzy(float P[],int n,int gx,float GP,float x[]){//1<=gx<=n ,, 0<=GP<=1
    
    if(gx==1){
        x[0]=P[0];
        x[1]=(1-GP)*(P[1]-P[0])/1.33333+P[0];
    }
    else{
        if(gx<n){
        x[0]=(GP-1)*(P[gx-1]-P[gx-2])/1.333333+P[gx-1];
        x[1]=(1-GP)*(P[gx]-P[gx-1])/1.333333+P[gx-1];
        }
        if(gx==n){
        x[0]=(GP-1)*(P[gx-1]-P[gx-2])/1.333333+P[gx-1];
        x[1]=P[n-1];
        }

    }
}


void EntradaU(float F[],float O[],int ultrasonico,float tetha,float entrada[],float gp[],int mf[]){
    //        ex_izq  muy_izqu  izqui  frente  dere  muy_der  ex_dere
    //salidau   1        2        3      4      5      6         7
    // entrada[0]==> entrada  fuzzy phi brujula
    // entrada[1] ==> entrada fuzzy ultrasonico
    //para el phi brujula
    float gradop[2] = {0.0,0.0};
    int mfi[2]={0,0};
    float P[5]={-180,-90,0,90,180};//es decir entre -180 y 180
   float beta;
   beta=atan((F[0]-O[0])/(F[1]-O[1]))*57.29582790879777;
    entrada[0]=beta-tetha;//degrees  phi
    switch(ultrasonico){
        case 0:{
        if(entrada[0]>0)entrada[1]=7;//entrada[1] de ultrasonico
        if(entrada[0]<0)entrada[1]=1;
        break;}
        case 2:{
        if(entrada[0]>0)entrada[1]=7;
        if(entrada[0]<0)entrada[1]=1;
        break;}
        case 5:{
        if(entrada[0]>0)entrada[1]=6;
        if(entrada[0]<0)entrada[1]=2;
        break;}
        case 1:{entrada[1]=6;
        break;}
        case 3:{entrada[1]=5;
        break;}
        case 7:{if(entrada[0]>0)entrada[1]=6;//entrada[1] de ultrasonico
            if(entrada[0]<0)entrada[1]=2;//*cambie orden 7 con  1
            break;}
        case 6:{entrada[1]=3;
        break;}
        case 4:{entrada[1]=2;
        break;}
    }
    /*//para el phi brujula
    float gradop[2] = {0.0,0.0};
    int mfi[2]={0,0};
    float P[5]={-144,-72,0,72,144};//es decir entre -180 y 180*/
    //printf("\nentrada[0]%f\n",entrada[0]);
    GPfuzzy(P,5,entrada[0],gradop,mfi);
    gp[0]=gradop[0];  mf[0]=mfi[0];
    gp[1]=gradop[1];  mf[1]=mfi[1];

    //para el ultrasonico
    //GPfuzzy(P,5,entrada[1],gradop,mf);
    gp[2]=1;  mf[2]=entrada[1];
    gp[3]=0.5;  mf[3]=entrada[1]+1;
}


//reglas fuzzy
int  reglas(int mf[],int mfrueda[],float gpin[],float gprueda[]){
    //mf[0]==>mf      phi brujula
    //mf[1]==>mf sgte brujula
    //mf[2] mf ultrasonico
    //mf[3]  mf sgte ultra
    //gpin[0]  brujula primer grado de pertenencia
    //gpin[1]  brujula segundo grado de pertencia
    //gpin[2]  ultrasonico pro=imer gp
    //gpin[3]  ultrasonico segundo gp
    //rueda[0]==>rueda1
    //rueda[1]==>rueda2

    //mfgps[0]==>latitud
    //mfgps[1]==>longtud
    //k==> ultimo elem: gprueda[k+1]
    int i,j;
    int k=0;
    //printf("\ngpin[]phi %f %f\n",gpin[0],gpin[1]);
    //printf("\ngpin[]ultrasonico %f %f\n",gpin[2],gpin[3]);
    //printf("\nmf[] %d %d %d %d\n",mf[0],mf[1],mf[2],mf[3]);
    //mfrueda[6]=7;
    //mfrueda[5]=7;

//falta ve lo de la interrupcion del gps XD
    //if((mfgps[0]==1)&&(mfgps[1]==1)){gprueda[0]=gpgps(0);gprueda[1]=gpgps[1];}//a parte del phi y el ultrasonico
    if(mf[0]==3||mf[1]==3){i=1;if(mf[0]==3)i=0;
        if(mf[2]==1||mf[3]==1){j=2;if(mf[3]==1)j=3;mfrueda[k]=1;mfrueda[k+1]=4;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==2||mf[3]==2){j=2;if(mf[3]==2)j=3;mfrueda[k]=1;mfrueda[k+1]=4;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==3||mf[3]==3){j=2;if(mf[3]==3)j=3;mfrueda[k]=2;mfrueda[k+1]=3;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==7||mf[3]==7){j=2;if(mf[3]==7)j=3;mfrueda[k]=3;mfrueda[k+1]=1;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==6||mf[3]==6){j=2;if(mf[3]==6)j=3;mfrueda[k]=2;mfrueda[k+1]=1;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==5||mf[3]==5){j=2;if(mf[3]==5)j=3;mfrueda[k]=3;mfrueda[k+1]=2;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==4||mf[3]==4){j=2;if(mf[3]==4)j=3;mfrueda[k]=3;mfrueda[k+1]=3;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
    }
//printf("\n1gprueda[]phi %f %f\n",gpin[0],gpin[1]);

    if(mf[0]==4||mf[1]==4){i=1;if(mf[0]==4)i=0;//si brujula es POS
        if(mf[2]==1||mf[3]==1){j=2;if(mf[3]==1)j=3;mfrueda[k]=1;mfrueda[k+1]=4;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==3||mf[3]==3){j=2;if(mf[3]==3)j=3;mfrueda[k]=1;mfrueda[k+1]=3;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==3||mf[3]==3){j=2;if(mf[3]==3)j=3;mfrueda[k]=4;mfrueda[k+1]=1;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==5||mf[3]==5){j=2;if(mf[3]==5)j=3;mfrueda[k]=3;mfrueda[k+1]=1;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==4||mf[3]==4){j=2;if(mf[3]==4)j=3;mfrueda[k]=1;mfrueda[k+1]=3;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
    }

    if(mf[0]==5||mf[1]==5){i=1;if(mf[0]==5)i=0;//si brujula es APOS
        if(mf[2]==3||mf[3]==3){j=2;if(mf[3]==3)j=3;mfrueda[k]=1;mfrueda[k+1]=5;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==5||mf[3]==5){j=2;if(mf[3]==5)j=3;mfrueda[k]=5;mfrueda[k+1]=1;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
        if(mf[2]==4||mf[3]==4){j=2;if(mf[3]==4)j=3;mfrueda[k]=1;mfrueda[k+1]=5;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
    }
    if(mf[0]==2||mf[1]==2){i=1;if(mf[0]==2)i=0;//si brujula es NEG
        if(mf[2]==4||mf[3]==4){j=2;if(mf[3]==4)j=3;mfrueda[k]=1;mfrueda[k+1]=5;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
    }
    if(mf[0]==1||mf[1]==1){i=1;if(mf[0]==1)i=0;//si brujula es ANEG
        if(mf[2]==4||mf[3]==4){j=2;if(mf[3]==4)j=3;mfrueda[k]=5;mfrueda[k+1]=1;gprueda[k]=min(gpin[i],gpin[j]);gprueda[k+1]=min(gpin[i],gpin[j]);k=k+2;}
    }//llega hasta gprueda[k+1]
return k;//size de mf y gprueda[]
}
//desfuzzyfication
void desfuzzy(float Pm[],int n,int mfrueda[],float gprueda[],int size,float dutty[]){
      //rueda1*********************************
    float x[3],ar=0,num=0,x1,area=0,area1,x2,area2;
    int a,b,i,mfmin,mfmax=1;
   mfmin=n;
//el sgte for fue modificado para casos de mfmax y mfmin q se repiten despues de las reglas
    for(i=0;i<size;i=i+2){//ojo desde i=0
        if(mfrueda[i]<=mfmin){if(mfrueda[i]<mfmin){mfmin=mfrueda[i];a=i;}
                                if(mfrueda[i]=mfmin)b=i;}
        if(mfrueda[i]>mfmax){mfmax=mfrueda[i];b=i;}
    }

    
    //hallar %dutty de rueda1
        //centroide de area1
    GPIfuzzy(Pm,n,mfmin,gprueda[a],x);

    for(i=0;i<gprueda[a]*100;i++){//*ojo con gprueda[a]*100
        ar=0.01*(Pm[mfmin-1]-(i*0.01-1)/1.3333*(Pm[mfmin]-Pm[mfmin-1])-x[0]);
        area=area+ar;
        num=num+(ar*100/2+x[0])*ar;//ahhhhhhhhhhhhhhhhhhh
    }
    if(area!=0)x1=num/area;
   else x1=0;
    area1=area;

        //centroide de area2
    ar=0,num=0,area=0;
    GPIfuzzy(Pm,n,mfmax,gprueda[b],x);

    for(i=0;i<gprueda[b]*100;i++){
        ar=0.01*(x[1]-(Pm[mfmax-1]+(i*0.01-1)/1.333333*(Pm[mfmax-1]-Pm[mfmax-2])));
        area=area+ar;
       num=num+(100*ar/2+ (x[1]-ar*100)   )*ar;
    }
    if(area!=0)x2=num/area;else x2=0;
    area2=area;

   dutty[0]=(x1*area1+x2*area2)/(area1+area2);

    //rueda2************************************************

   
    mfmin=n,mfmax=1;ar=0,area=0,num=0;
//el sgte for fue modificado para casos de mfmax y mfmin q se repiten despues de las reglas
     for(i=1;i<size;i=i+2){//ojo desde i=1
        if(mfrueda[i]<=mfmin){if(mfrueda[i]<mfmin){mfmin=mfrueda[i];a=i;}
                                if(mfrueda[i]=mfmin)b=i;}
        if(mfrueda[i]>mfmax){mfmax=mfrueda[i];b=i;}
    }
  
    //hallar %dutty de rueda2
        //centroide de area1
    GPIfuzzy(Pm,n,mfmin,gprueda[a],x);
    for(i=0;i<gprueda[a]*100;i++){//*ojo con gprueda[a]*100
        ar=0.01*(Pm[mfmin-1]-(i*0.01-1)/1.3333*(Pm[mfmin]-Pm[mfmin-1])-x[0]);
        area=area+ar;
        num=num+(ar*100/2+x[0])*ar;//ahhhhhhhhhhhhhhhhhhh
    }
    if(area!=0) x1=num/area;
   else x1=0;
    area1=area;
        //centroide de area2
    ar=0,num=0,area=0;
    GPIfuzzy(Pm,n,mfmax,gprueda[b],x);
    for(i=0;i<gprueda[b]*100;i++){
       ar=0.01*(x[1]-(Pm[mfmax-1]+(i*0.01-1)/1.333333*(Pm[mfmax-1]-Pm[mfmax-2])));
        area=area+ar;
       num=num+(100*ar/2+ (x[1]-ar*100)   )*ar;//ahhhhhhhhhh
    }
    if(area!=0)x2=num/area;
   else x2=0;
    area2=area;

    dutty[1]=(x1*area1+x2*area2)/(area1+area2);
}