pepe

Dependencies:   mbed Matrix

Robot.cpp

Committer:
PedroMartins96
Date:
2019-03-13
Revision:
0:a7324f51348d
Child:
1:2716ea33958b

File content as of revision 0:a7324f51348d:

#include "Robot.h"
#include "mbed.h"

Serial PC(SERIAL_TX, SERIAL_RX);
I2C i2c(I2C_SDA, I2C_SCL );
const int addr8bit = 20 << 1; // 7bit I2C address is 20; 8bit I2C address is 40 (decimal).

int16_t countsLeft = 0;
int16_t countsRight = 0;
float De=0, Dd=0, pi=3.141529, Ldis=14.2, r=6.95/2, theta=0, teta=0, x=50, y=10, D=0, Wee=0, Wdd=0, v=0, w=0;


////////////////////////////////////////
// Movimento para uma pose arbitrária //
////////////////////////////////////////
void to_pos(float x2,float y2,float phi2)
{
    while(1){
    float alfa,beta,a=33,b=30;
    float Kp=0.7,Ka=5,Kb=-2;
    while(abs(x)<abs(x2)-1 || abs(y)<abs(y2)-1 || teta<=(phi2-0.05) || teta>=(phi2+0.05)) {// Condição de paragem
        // Controlo linear
        v=Kp*(sqrt(((x2-x)*(x2-x)+(y2-y)*(y2-y))));
        
        alfa=-teta+atan2(y2-y,x2-x);
        
        if(abs(v)<1){ 
            alfa=0;
            a=0;
            b=0;
        }
        // Verifica se o alpha pertence ao limite entre [-pi/2; pi/2], se não adiciona/remove pi e inverte a velocidade
        if(alfa<-pi/2){
            alfa=alfa+pi;
            v=-v;
        }
        else if(alfa>pi/2){
            alfa=alfa-pi;
            v=-v;
        }
        
        beta=-teta-alfa+phi2;
        w=Ka*alfa+Kb*beta;
        
        if(alfa==0){
             w=w+abs(w)/w*4;
             Kb=3;
        }

        motion();
        setSpeeds(Wee+a*abs(v)/v,Wdd+b*abs(v)/v);

        //PC.printf("v=%f w=%f alfa=%f beta=%f teta=%f phi2=%f x=%f y=%f\n", v,w,alfa,beta,teta,phi2,x,y);
        PC.printf("%f %f\n", x,y);
        }
        setSpeeds(0,0); // A condição de paragem verifica-se e para-se o robo
    }
}


/////////////////////////////////
// Movimento segundo uma linha //
/////////////////////////////////
void to_line(float a,float b,float c)
{
    float d=0,alfad=0,phi1=0,alfah=0;
    float Kd=0.45,Kh=15;
    while(1){
        while((abs(x) < 200)&&(abs(y)<200)) {
            v=100;
            d=(a*x+b*y+c)/sqrt(a*a+b*b);

            //Controlo proporcional que roda a plataforma na direção da linha
            alfad=(-Kd)*d;
            if (abs(alfad)<0.3) alfad=alfad*3;
            phi1=atan2(-a,b);
            
            //Controlo proporcional que ajusta o ângulo de direcionamento
            alfah=Kh*(phi1-teta);
            
            w=alfad+alfah;
            
            if(w > 12) w = 12;
            else if(w<-12) w = -12;

            motion();
            setSpeeds(Wee,Wdd);
            //PC.printf("v=%f w=%f alfad=%f alfah=%f teta=%f x=%f y=%f\n", v,w,alfad,alfah,teta,x,y);
            PC.printf("%f %f\n", x,y);
        }
        setSpeeds(0,0);
    }
}


/////////////////////////////
// Movimento para um ponto //
/////////////////////////////
void to_point(float x1,float y1)
{
    while(1) {
        float phi1=0,aux=0;
        float Kv=1.5,Ks=30;
        while((abs(x)<abs(x1)-1)||(abs(y)<abs(y1)-1)||(abs(x)>abs(x1)+1)||(abs(y)>abs(y1)+1)) {
            v=Kv*(sqrt(((x1-x)*(x1-x)+((y1-y)*(y1-y))))); //Controlo de velocidade -- Quanto mais próximo do ponto objetivo, menor vai ser a velocidade
            
            phi1=atan2((y1-y),(x1-x)); // Ângulo entre a posição final e a posição atual
            
            aux=phi1-teta;
            //Verifica se a diferença dos angulos pertence ao limite entre [-pi;pi]
            if(aux<-pi){
                aux=aux+2*pi;
            }
            else if(aux>pi){
                aux=aux-2*pi;
            }
            
            //Controlo proporcional
            w=Ks*(aux);
            
            if(w > 12) w = 12;
            else if(w<-12) w = -12;

            motion();
            setSpeeds(Wee+28,Wdd+25);
            //PC.printf("v=%f w=%f phi1=%f x=%f y=%f teta=%f\n", v,w,phi1,x,y,teta);
            PC.printf("%f %f %f %f\n", x,y,teta, w);
        }
        setSpeeds(0,0);
    }

}

///////////////
// Odometria //
///////////////
void motion()
{
    getCountsAndReset();
    De=((2*pi*r)*countsLeft)/1440;
    Dd=((2*pi*r)*countsRight)/1440;
    theta=(Dd-De)/Ldis;
    
    D=(De+Dd)/2;
    
    if(theta==0) {
        x=x+D*cos(teta);
        y=y+D*sin(teta);
        teta=teta;
    } else {
        x = x + D*((sin(theta/2)/(theta/2))*cos(teta+theta/2));
        y = y + D*((sin(theta/2)/(theta/2))*sin(teta+theta/2));
        teta=teta+theta;
    }
    
    //Limite entre [-2pi; 2pi]
    if (teta>=(2*pi)) {
        teta=teta-2*pi;
    }
    if (teta<=(-2*pi)) {
        teta=teta+2*pi;
    }

    Wee=(v-(Ldis/2)*w);
    Wdd=(v+(Ldis/2)*w);
    //PC.printf("phi1=%f D=%f x=%f y=%f teta=%f\n", w,theta,x,y,teta);
}

void setSpeeds(int16_t leftSpeed, int16_t rightSpeed)
{
    char buffer[5];

    buffer[0] = 0xA1;
    memcpy(&buffer[1], &leftSpeed, sizeof(leftSpeed));
    memcpy(&buffer[3], &rightSpeed, sizeof(rightSpeed));

    i2c.write(addr8bit, buffer, 5); // 5 bytes
}

void setLeftSpeed(int16_t speed)
{
    char buffer[3];

    buffer[0] = 0xA2;
    memcpy(&buffer[1], &speed, sizeof(speed));

    i2c.write(addr8bit, buffer, 3); // 3 bytes
}

void setRightSpeed(int16_t speed)
{
    char buffer[3];

    buffer[0] = 0xA3;
    memcpy(&buffer[1], &speed, sizeof(speed));

    i2c.write(addr8bit, buffer, 3); // 3 bytes
}

void getCounts()
{
    char write_buffer[2];
    char read_buffer[4];

    write_buffer[0] = 0xA0;
    i2c.write(addr8bit, write_buffer, 1);
    wait_us(100);
    i2c.read( addr8bit, read_buffer, 4);
    countsLeft = (int16_t((read_buffer[0]<<8)|read_buffer[1]));
    countsRight = (int16_t((read_buffer[2]<<8)|read_buffer[3]));
}

void getCountsAndReset()
{
    char write_buffer[2];
    char read_buffer[4];

    write_buffer[0] = 0xA4;
    i2c.write(addr8bit, write_buffer, 1);
    wait_us(100);
    i2c.read( addr8bit, read_buffer, 4);
    countsLeft = (int16_t((read_buffer[0]<<8)|read_buffer[1]));
    countsRight = (int16_t((read_buffer[2]<<8)|read_buffer[3]));
}