Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
xaficz
Date:
Thu May 13 15:19:19 2021 +0000
Commit message:
vfh

Changed in this revision

Robot.cpp Show annotated file Show diff for this revision Revisions of this file
Robot.h Show annotated file Show diff for this revision Revisions of this file
funcs.cpp Show annotated file Show diff for this revision Revisions of this file
funcs.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Robot.cpp	Thu May 13 15:19:19 2021 +0000
@@ -0,0 +1,63 @@
+#include "Robot.h"
+#include "mbed.h"
+
+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;
+
+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]));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Robot.h	Thu May 13 15:19:19 2021 +0000
@@ -0,0 +1,49 @@
+/** @file */
+#ifndef ROBOT_H_
+#define ROBOT_H_
+
+#include "mbed.h"
+
+extern int16_t countsLeft;
+extern int16_t countsRight;
+
+/** \brief Sets the speed for both motors.
+ *
+ * \param leftSpeed A number from -300 to 300 representing the speed and
+ * direction of the left motor. Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward.
+ * \param rightSpeed A number from -300 to 300 representing the speed and
+ * direction of the right motor. Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward. */
+void setSpeeds(int16_t leftSpeed, int16_t rightSpeed);
+
+/** \brief Sets the speed for the left motor.
+ *
+ * \param speed A number from -300 to 300 representing the speed and
+ * direction of the left motor.  Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward. */
+void setLeftSpeed(int16_t speed);
+
+/** \brief Sets the speed for the right motor.
+ *
+ * \param speed A number from -300 to 300 representing the speed and
+ * direction of the right motor. Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward. */
+void setRightSpeed(int16_t speed);
+
+/*! Returns the number of counts that have been detected from the both
+ * encoders.  These counts start at 0.  Positive counts correspond to forward
+ * movement of the wheel of the Romi, while negative counts correspond
+ * to backwards movement.
+ *
+ * The count is returned as a signed 16-bit integer.  When the count goes
+ * over 32767, it will overflow down to -32768.  When the count goes below
+ * -32768, it will overflow up to 32767. */
+void getCounts();
+
+/*! This function is just like getCounts() except it also clears the
+ *  counts before returning.  If you call this frequently enough, you will
+ *  not have to worry about the count overflowing. */
+void getCountsAndReset();
+
+#endif /* ROBOT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/funcs.cpp	Thu May 13 15:19:19 2021 +0000
@@ -0,0 +1,225 @@
+#include "mbed.h"
+#include "math.h"
+#include <stdio.h>
+#include "funcs.h"
+
+static const double pi = 3.14159265358;
+
+Serial pc1(SERIAL_TX, SERIAL_RX);
+
+
+//Funcao para criar um mapa simples com um quadrado no meio
+void read_map1(int Map_Matrix[80][80]){
+    for(int i = 0; i < 80; i++){
+        for(int j = 0; j < 80; j++){
+            Map_Matrix[i][j] = 0;  
+            
+            if((i >= 30 || j >= 30) || (i >= 5 && j >=5 && i <= 10 && j <= 10) || (i >= 5 && j >= 20 && i <= 10  && j <= 25)){
+                Map_Matrix[i][j] = 1;
+            } 
+        }
+    } 
+}
+
+//Funcao para obter as matrizes de Seccoes e Amplitudes
+void get_Sector_Matrix(int Sector_Matrix_Sections[15][15], double Sector_Matrix_Abs[15][15]){
+    double division_angle = 2*pi/24;
+    double Aux_Angle_Matrix[15][15];
+    double a = sqrt((double)2)*7;
+    double b = 1;
+    int i;
+    
+    //Atribui angulos aos varios pontos da matriz
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            Aux_Angle_Matrix[x][y] = atan2((double)(y-7),(double)(x-7));
+        }
+    }
+    
+    //Colocar a matriz de seccoes toda a 0
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            Sector_Matrix_Sections[x][y] = 0;
+        }
+    }    
+    
+    //Atribuir o indice da seccao em funcao dos angulos obtidos anteriormente
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            i = 0;
+            for(double ca = division_angle-pi; ca < pi; ca = ca+division_angle){ 
+                if(Sector_Matrix_Sections[x][y] == 0 && (Aux_Angle_Matrix[x][y] <= ca || Aux_Angle_Matrix[x][y] == pi) && Aux_Angle_Matrix[x][y] >= ca-division_angle){
+                    Sector_Matrix_Sections[x][y] = i;      
+                }
+                i = i+1;
+            }
+        }
+    }
+    
+    
+    //Atribuir a amplitude a cada elemento da matriz
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            Sector_Matrix_Abs[x][y] = a-b*sqrt((double)((7-y)*(7-y) + (7-x)*(7-x)));
+            }
+    }
+    /*
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            pc1.printf("%d,",Sector_Matrix_Sections[x][y]);        
+        }
+        pc1.printf("\n");
+    } 
+    */
+}
+
+//Funcao para obter a matriz das redondezas do robo 
+void get_Surroundings_Matrix(int Surroundings_Matrix[15][15], double actual_position_x, double actual_position_y, int Map_Matrix[80][80]){
+    int map_position_x = floor(actual_position_x/50);
+    int map_position_y = floor(actual_position_y/50);
+    
+    int i = 0;
+    int j = 0;
+    for(int x = map_position_x-8; x < map_position_x+8; x++){
+        for(int y = map_position_y-8; y < map_position_y+8; y++){
+            if(x < 0 || x > 79 || y < 0 || y > 79){
+                Surroundings_Matrix[i][j] = 1;
+            }    
+            else{
+                Surroundings_Matrix[i][j] = Map_Matrix[x][y];
+            }
+            j = j + 1;
+        }
+        i = i + 1;
+        j = 0;
+    }
+    pc1.printf("matriz surroundings:\n");
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            pc1.printf("%d,", Surroundings_Matrix[x][y]);
+        } 
+        pc1.printf("\n");       
+    }  
+    
+}
+
+//Funcao auxiliar de get_orientation_angle para encontrar os indices do histograma
+void find_index(int given_index, int l, int out_index[9]){
+    int n = 0;
+    for(int i = given_index-l; i <= given_index+l; i++){
+        if(i < 0){
+            out_index[n] = 22 + i;
+            n++;
+        }
+        else{  
+            if(i > 22){
+                    out_index[n] = i - 23;
+                    n++;
+            }
+            else{
+                    out_index[n] = i;
+                    n++;
+            }    
+        }
+    }
+    
+}
+
+//Funcao para obter o angulo de orientacao seguinte 
+double get_orientation_angle(double actual_position_x, double actual_position_y, double end_position_x, double end_position_y, int Surroundings_Matrix[15][15], int Sector_Matrix_Sections[15][15], double Sector_Matrix_Abs[15][15], double threshold){
+    double Sector_Sum_Vector[23] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    double Sector_Sum_Vector_Filtered[23];
+    double auxiliar_angle[23];
+    double angle_difference_end[23];
+    double section_angle = 2*pi/23;
+    double end_angle;
+    int index = 0;
+    int out_index[23];
+    int ind;
+    int l = 4;
+    
+    double Surroundings_Matrix_Aux[15][15];
+    
+    //Atribuimos os valores de amplitudes aos pontos da matriz das redondezas
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            Surroundings_Matrix_Aux[x][y] = Surroundings_Matrix[x][y]*Sector_Matrix_Abs[x][y];
+        }
+    }    
+    /*
+    pc1.printf("matriz abs:\n");
+    for(int x = 0; x < 15; x++){
+        for(int y = 0; y < 15; y++){
+            pc1.printf("%f,", Surroundings_Matrix_Aux[x][y]);
+        } 
+        pc1.printf("\n");       
+    }  
+    */
+    
+    //Criamos o vetor do histograma das seccoes
+    for(int x = 0; x < 15; x++){  
+        for(int y = 0; y < 15; y++){   
+            index = Sector_Matrix_Sections[x][y];
+            
+            Sector_Sum_Vector[index] = Sector_Sum_Vector[index] + Surroundings_Matrix_Aux[x][y];
+        }
+    } 
+    
+    /* 
+    pc1.printf("tabela s filtro:\n");
+    for(int n = 0; n < 23; n++){
+        pc1.printf("%f\n", Sector_Sum_Vector[n]);    
+    } 
+    */ 
+   
+    //Filtramos o histograma
+    for(int i = 0; i < 23; i++){  
+        find_index(i,l,out_index);
+        
+        for(int c = 0; c < l; c++){
+            ind = out_index[c];
+            Sector_Sum_Vector_Filtered[i] = Sector_Sum_Vector_Filtered[i] + (c+1)*Sector_Sum_Vector[ind];
+        }
+        
+        Sector_Sum_Vector_Filtered[i] = Sector_Sum_Vector_Filtered[i] + (l+1)*Sector_Sum_Vector[l];
+
+        for(int c = 0; c < l; c++){
+            ind = out_index[c+l+1];
+            Sector_Sum_Vector_Filtered[i] = Sector_Sum_Vector_Filtered[i] + (l-c)*Sector_Sum_Vector[ind];
+        }
+            
+        Sector_Sum_Vector_Filtered[i] = Sector_Sum_Vector_Filtered[i]/(2*l+1);
+    }
+    
+    /*
+    pc1.printf("\ntabela c f:\n");
+    for(int n = 0; n < 23; n++){
+        pc1.printf("%f\n", Sector_Sum_Vector_Filtered[n]);    
+    }   
+    */
+    
+    for(int i = 0; i < 23; i++){
+        if(Sector_Sum_Vector_Filtered[i] < threshold){
+            auxiliar_angle[i] = i*section_angle - pi; // subtraimos o pi 
+        }                                           // para que os angulos rodem 180 graus
+        else{
+            auxiliar_angle[i] = 0;      //  trajectoria negada
+        }    
+    }
+    
+    end_angle = atan2((double)(end_position_y-actual_position_y),(double)(end_position_x-actual_position_x));
+    
+    //Escolhemos a secccao disponivel cujo angulo e mais proximo do angulo final
+    for(int i = 0; i < 23; i++){
+        angle_difference_end[i] = sqrt((double)(auxiliar_angle[i] - end_angle)*(auxiliar_angle[i] - end_angle));  
+    }    
+    
+    ind = 0;
+    for(int i = 0; i < 23; i++){
+        if(angle_difference_end[i] < angle_difference_end[ind]){
+            ind = i;
+        }      
+    } 
+          
+    return(auxiliar_angle[ind]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/funcs.h	Thu May 13 15:19:19 2021 +0000
@@ -0,0 +1,9 @@
+void read_map1(int Map_Matrix[80][80]);
+
+void get_Sector_Matrix(int Sector_Matrix_Sections[15][15], double Sector_Matrix_Abs[15][15]);
+
+void get_Surroundings_Matrix(int Surroundings_Matrix[15][15], double actual_position_x, double actual_position_y, int Map_Matrix[80][80]);
+
+void find_index(int given_index, int l, int out_index[23]);
+
+double get_orientation_angle(double actual_position_x, double actual_position_y, double end_position_x, double end_position_y, int Surroundings_Matrix[15][15], int Sector_Matrix_Sections[15][15], double Sector_Matrix_Abs[15][15], double threshold);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu May 13 15:19:19 2021 +0000
@@ -0,0 +1,100 @@
+#include "mbed.h"
+#include "Robot.h"
+#include "funcs.h"
+
+static const double pi = 3.14159265358;
+DigitalIn Button(USER_BUTTON);
+Serial pc(SERIAL_TX, SERIAL_RX);
+
+
+int main() {
+    //Espera que o botao seja premido
+    while (Button == 1) {}
+    wait(1);
+    
+    //Matrizes de mapeamento
+    int Map_Matrix[80][80];             //Matriz do mapa
+    int Sector_Matrix_Sections[15][15]; //Matriz com os indices das seccoes
+    double Sector_Matrix_Abs[15][15];   //Matriz com as amplitudes 
+    int Surroundings_Matrix[15][15];    //Matriz das redondezas do bot
+    
+    //Ganhos
+    double k = 3.3;                       //ganho angular
+    
+    //Variaveis de posicao
+    double x = 150;                     //x inicial
+    double y = 150;                     //y inicial
+    double phi = 0.01;                  //phi inicial
+    double end_position_x = 1200;       //x final
+    double end_position_y = 1200;       //y final
+    double next_phi;                    //phi seguinte
+    
+    //Variaveis de estimacao de posicao
+    double var_l;                       //contagens do encoder esquerdas
+    double var_r;                       //contagens do encoder direitas
+    double var_d;                       //variacao linear entre iteracoes
+    double var_phi;                     //variacao angular entre iteracoes
+    double L = 150;                     //distancia entre rodas
+    double r = 35;                      //raio da roda
+    
+    //Variaveis de comando as rodas
+    double w;                           //velociade angular do robo
+    double w_left;                      //velocidade roda esquerda
+    double w_right;                     //velocidade roda direita
+    double v = 2400;                    //velocidade linear do robo
+      
+    //Funcao de obtencao do Mapa  
+    read_map1(Map_Matrix);             
+ 
+    //Funcao para obter a matriz com os indices das seccoes assim como as amplitudes
+    get_Sector_Matrix(Sector_Matrix_Sections, Sector_Matrix_Abs);
+    
+    //Distancia ao ponto objetivo
+    double dist = sqrt((double)((x-end_position_x)*(x-end_position_x) + (y-end_position_y)*(y-end_position_y)));
+    
+    while(dist > 150){
+        //Obter as contagens dos encoders
+        getCountsAndReset();
+    
+        //Estimacao de pose
+        var_l = (2*pi*r*countsLeft/1440);
+        var_r = (2*pi*r*countsRight/1440);
+        var_d = (var_l+var_r)/2;
+        var_phi= (var_r-var_l)/L;
+
+        if(var_phi == 0){
+            x = x + var_d*cos(phi);
+            y = y + var_d*sin(phi);
+        } 
+        else{
+            x = x + (var_d)*((sin(phi/2)/(phi/2))*cos(phi + var_phi/2));
+            y = y + (var_d)*((sin(phi/2)/(phi/2))*sin(phi + var_phi/2));
+            phi = phi + var_phi;
+        }
+        
+        pc.printf("x_atual = %f, y_atual = %f\n",x,y);
+        //Distancia ao ponto objetivo
+        dist = sqrt((double)(x-end_position_x)*(x-end_position_x) + (y-end_position_y)*(y-end_position_y));
+        pc.printf("\ndist = %f\n", dist);
+        
+        //Funcao para obter o mapa das redondezas do robo
+        get_Surroundings_Matrix(Surroundings_Matrix, x, y, Map_Matrix);
+        
+        //Funcao para obter a direcao que o robo deve tomar em funcao da sua posicao atual e das suas redondezas    
+        // defenimos como o limiar 31 !!
+        next_phi = get_orientation_angle(x, y, end_position_x, end_position_y, Surroundings_Matrix, Sector_Matrix_Sections, Sector_Matrix_Abs, 31);
+        pc.printf("\n\n next phi = %f\n\n", next_phi);
+        
+        //Controlo proporcional da direcao
+        w = k*atan2(sin(next_phi-phi),cos(next_phi-phi));
+        
+        //Enviar os comandos de velocidades para as rodas
+        w_left=(v-(L/2)*w)/r;
+        w_right=(v+(L/2)*w)/r;
+        setSpeeds(w_left,w_right);    
+    }    
+    
+    setSpeeds(0,0);
+    return(0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu May 13 15:19:19 2021 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file