
sra-romi
Dependencies: BufferedSerial Matrix
Revision 4:1defb279922a, committed 2021-05-11
- Comitter:
- joaopsousa99
- Date:
- Tue May 11 18:10:22 2021 +0000
- Parent:
- 3:0a718d139ed1
- Commit message:
- as.djvblaskdvj
Changed in this revision
diff -r 0a718d139ed1 -r 1defb279922a Matrix.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Matrix.lib Tue May 11 18:10:22 2021 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/Yo_Robot/code/Matrix/#a4014ab0a8cf
diff -r 0a718d139ed1 -r 1defb279922a Robot.cpp --- a/Robot.cpp Wed Apr 24 16:00:07 2019 +0000 +++ b/Robot.cpp Tue May 11 18:10:22 2021 +0000 @@ -1,12 +1,27 @@ +#include <math.h> #include "Robot.h" #include "mbed.h" +#include "control.h" +#include "I2C.h" -I2C i2c(I2C_SDA, I2C_SCL ); +I2C i2c(PB_9, PB_8); const int addr8bit = 20 << 1; // 7bit I2C address is 20; 8bit I2C address is 40 (decimal). +const int16_t COUNTS_PER_ROTATION = 1440; // ticks dos encoders por volta do motor +const int16_t WHEEL_DIAMETER = 7; // diâmetro das rodas, em centímetros +const int16_t WHEEL_DISTANCE = 14; +const float MAX_LIN_VEL = 20; +const float MIN_LIN_VEL = -20; +const float MIN_SET_SPEEDS = -100; +const float MAX_SET_SPEEDS = 100; + int16_t countsLeft = 0; int16_t countsRight = 0; +float poseX = 0; +float poseY = 50; +float poseTheta = 0; + void setSpeeds(int16_t leftSpeed, int16_t rightSpeed) { char buffer[5]; @@ -60,4 +75,43 @@ 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])); +} + +float mapSpeeds(float value){ + value = (value - MIN_LIN_VEL) * (MAX_SET_SPEEDS - MIN_SET_SPEEDS)/(MAX_LIN_VEL - MIN_LIN_VEL) + MIN_SET_SPEEDS; + + if(value < 35 && value > 0) + value = 35; + if(value > -35 && value < 0) + value = -35; + if(value > 150) + value = 150; + if(value < -150) + value = -150; + + return value; +} + +void updatePose(){ + //printf("início do updatePose; "); + getCountsAndReset(); + + float Dl = (2 * 3.14 * countsLeft) * (WHEEL_DIAMETER / 2) / COUNTS_PER_ROTATION; + + float Dr = (2 * 3.14 * countsRight) * (WHEEL_DIAMETER / 2) / COUNTS_PER_ROTATION; + + float D = (Dl + Dr) / 2; + + float deltaTheta = (Dr - Dl) / WHEEL_DISTANCE; + + poseX = poseX + D * cos(poseTheta + deltaTheta / 2); + poseY = poseY + D * sin(poseTheta + deltaTheta / 2); + poseTheta = poseTheta + deltaTheta; + poseTheta = atan2(sin(poseTheta), cos(poseTheta)); + //printf("fim do updatePose; "); +} + +void robotVel2wheelVel(float v, float w, float *wheelSpeeds){ + wheelSpeeds[0] = (v - (WHEEL_DISTANCE / 2) * w) / (WHEEL_DIAMETER / 2); + wheelSpeeds[1] = (v + (WHEEL_DISTANCE / 2) * w) / (WHEEL_DIAMETER / 2); } \ No newline at end of file
diff -r 0a718d139ed1 -r 1defb279922a Robot.h --- a/Robot.h Wed Apr 24 16:00:07 2019 +0000 +++ b/Robot.h Tue May 11 18:10:22 2021 +0000 @@ -3,10 +3,23 @@ #define ROBOT_H_ #include "mbed.h" +#include <cstdint> + +extern const int16_t COUNTS_PER_ROTATION; +extern const int16_t WHEEL_DIAMETER; +extern const int16_t WHEEL_DISTANCE; +extern const float MAX_LIN_VEL; +extern const float MIN_LIN_VEL; +extern const float MIN_SET_SPEEDS; +extern const float MAX_SET_SPEEDS; extern int16_t countsLeft; extern int16_t countsRight; +extern float poseX; +extern float poseY; +extern float poseTheta; + /** \brief Sets the speed for both motors. * * \param leftSpeed A number from -300 to 300 representing the speed and @@ -46,4 +59,10 @@ * not have to worry about the count overflowing. */ void getCountsAndReset(); +void updatePose(); + +void robotVel2wheelVel(float v, float w, float *wheelSpeeds); + +float mapSpeeds(float value); + #endif /* ROBOT_H_ */ \ No newline at end of file
diff -r 0a718d139ed1 -r 1defb279922a control.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/control.cpp Tue May 11 18:10:22 2021 +0000 @@ -0,0 +1,249 @@ +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <math.h> +#include "Communication.h" +#include "control.h" +#include "mbed.h" +#include "Robot.h" +#include "Matrix.h" + +const float TIMESTEP = 0.05; +const float CELL_SIZE = 5; +const int MAP_SIZE = 100; +const int GRID_SIZE = int(MAP_SIZE/CELL_SIZE); +const int WINDOW_SIZE = int(45/CELL_SIZE); +const float PI = 3.1415926; + +Matrix create_occupation_grid(){ + Matrix occupationGrid = Matrix(GRID_SIZE,GRID_SIZE); + for(int i = 1; i <= 20; i++) + for(int j = 1;j <= 20; j++) + if (i > 8 && i < 12 && j > 8 && j < 12) + occupationGrid.add(i,j,1); + + return occupationGrid; +} +/*int occupationGrid[GRID_SIZE][GRID_SIZE] = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};*/ +/*int occupationGrid[GRID_SIZE][GRID_SIZE] = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};*/ + +void moveToPoint(float xObj, float yObj){ + float kv = 0.2; + float kw = 10; + + float d = sqrt((xObj - poseX)*(xObj - poseX) + (yObj - poseY)*(yObj - poseY)); + float angleError = atan2(yObj - poseY, xObj - poseX); + //printf("ANGLE ERROR: %.1f ", angleError*180/PI); + angleError = atan2(sin(angleError - poseTheta), cos(angleError - poseTheta)); // equivalente a wrapToPi() + + float wheelSpeeds[2]; + + robotVel2wheelVel(kv*d, kw*angleError, wheelSpeeds); + + wheelSpeeds[0] = mapSpeeds(wheelSpeeds[0]); + wheelSpeeds[1] = mapSpeeds(wheelSpeeds[1]); + + //printf("wheel speeds: [%.0f, %.0f]\t", wheelSpeeds[0], wheelSpeeds[1]); + + setSpeeds(wheelSpeeds[0], wheelSpeeds[1]); +} + +float vff(Matrix occupationGrid, int *xactive, int *yactive, int lenx, int leny, float *objCellCenter, Serial pc){ + //printf("i vff; "); + float Fcr = 35; + float Fca = 1.5; + + // não se sabe quantas células estão ocupadas então aloca-se espaço para todas para mais + // à frente guardar apenas as ocupadas e apagar estes arrays + //int *auxRows, *auxCols; + + //auxRows = (int *)calloc(lenx*leny, sizeof(int)); + //auxCols = (int *)calloc(lenx*leny, sizeof(int)); + + //int occupiedCounter = 0; + //int auxCounter = 0; + + // pesquisa a grelha de ocupação e guarda os índices da janela ativa que correspondem a + // células ocupadas + float Frx = 0; + float Fry = 0; + + float xCell, yCell; + float value; + + for(int i = 0; i < lenx; i++){ + for(int j = 0; j < leny; j++){ + // necessario somar 1 porque os indices na matriz comecam em 1 + value = occupationGrid(xactive[i]+1,yactive[j]+1); + //printf("occupationGrid(%d, %d): %.0f", xactive[i]+1, yactive[j]+1, value); + if(value == 1){ + //auxRows[auxCounter] = xactive[i]; + //auxCols[auxCounter] = yactive[j]; + //occupiedCounter++; + + xCell = xactive[i]*CELL_SIZE + CELL_SIZE/2; + yCell = yactive[i]*CELL_SIZE + CELL_SIZE/2; + Frx += Fcr*(xCell - poseX)/pow(sqrt(pow(xCell - poseX, 2) + pow(yCell - poseY, 2)), 3); + Fry += Fcr*(yCell - poseY)/pow(sqrt(pow(xCell - poseX, 2) + pow(yCell - poseY, 2)), 3); + } + else{ + continue; + //auxRows[auxCounter] = -1; + //auxCols[auxCounter] = -1; + } + //auxCounter++; + } + } + //pc.printf("Fr = [%.1f, %.1f] ", Frx, Fry); + float Fax = Fca*(objCellCenter[0] - poseX)/(sqrt(pow(objCellCenter[0] - poseX, 2) + pow(objCellCenter[1] - poseY, 2))); + float Fay = Fca*(objCellCenter[1] - poseY)/(sqrt(pow(objCellCenter[0] - poseX, 2) + pow(objCellCenter[1] - poseY, 2))); + //pc.printf("Fa = [%.1f, %.1f] ", Fax, Fay); + + /*if(occupiedCounter == 0){ + float F[2] = {Fax, Fay}; + printf("f vff; "); + return atan2(F[1], F[0]); + }*/ + + /*int *xOccupied, *yOccupied; + xOccupied = (int *)calloc(occupiedCounter, sizeof(int)); + yOccupied = (int *)calloc(occupiedCounter, sizeof(int)); + + occupiedCounter = 0; + + for(int i = 0; i < lenx*leny; i++){ + if(auxRows[i] != -1){ + xOccupied[occupiedCounter] = auxRows[i]; + yOccupied[occupiedCounter] = auxCols[i]; + occupiedCounter++; + } + } + + for (int i = 0; i < occupiedCounter; i++) { + xCell = xOccupied[i]*CELL_SIZE + CELL_SIZE/2; + yCell = yOccupied[i]*CELL_SIZE + CELL_SIZE/2; + + Frx += Fcr*(xCell - poseX)/pow(sqrt(pow(xCell - poseX, 2) + pow(yCell - poseY, 2)), 3); + Fry += Fcr*(yCell - poseY)/pow(sqrt(pow(xCell - poseX, 2) + pow(yCell - poseY, 2)), 3); + } + + free(auxCols); + free(auxRows); + free(xOccupied); + free(yOccupied);*/ + + float F[2] = {Fax - Frx, Fay - Fry}; + //printf("f vff; "); + return atan2(F[1], F[0]); +} + +void followPath(float &objAheadX, float &objAheadY, float &intError, float *objCellCenter, Matrix occupationGrid, Serial pc){ + //printf("i followPath; "); + float kv = 0.3; + float ki = 0.2; + float kw = 10; + int vObj = 7; // temos de fazer experiências para afinar isto + float vffAngle = poseTheta; + int dObj = 3; + + float xmax = floor(static_cast<float>(poseX/CELL_SIZE)) + floor(static_cast<float>(WINDOW_SIZE/2)); + float xmin = floor(static_cast<float>(poseX/CELL_SIZE)) - floor(static_cast<float>(WINDOW_SIZE/2)); + float ymax = floor(static_cast<float>(poseY/CELL_SIZE)) + floor(static_cast<float>(WINDOW_SIZE/2)); + float ymin = floor(static_cast<float>(poseY/CELL_SIZE)) - floor(static_cast<float>(WINDOW_SIZE/2)); + + if(xmin < 0) + xmin = 0; + if(xmax >= GRID_SIZE) + xmax = GRID_SIZE - 1; + if(ymin < 0) + ymin = 0; + if(ymax >= GRID_SIZE) + ymax = GRID_SIZE - 1; + + int lenx = xmax - xmin + 1; + int leny = ymax - ymin + 1; + + // pre alocacao de espaco + int *xactive, *yactive; + xactive = (int *)calloc(lenx, sizeof(int)); + yactive = (int *)calloc(leny, sizeof(int)); + + // linspace do matlab + for(int j = 0; j < lenx; j++) + xactive[j] = xmin + j; + + for(int i = 0; i < leny; i++) + yactive[i] = ymin + i; + + // repmat do matlab + //int *xactive = repeat_matrix2(x, lenx, leny); + //int *yactive = repeat_matrix(y, leny, lenx); + + //int activeSize = lenx*leny; + + vffAngle = vff(occupationGrid, xactive, yactive, lenx, leny, objCellCenter, pc); + + objAheadX = objAheadX + TIMESTEP * vObj * cos(vffAngle); + objAheadY = objAheadY + TIMESTEP * vObj * sin(vffAngle); + + float distError = sqrt(pow(objAheadY - poseY, 2) + pow(objAheadX - poseX, 2)) - dObj; + + intError = intError + distError * TIMESTEP; + + float v = kv * distError + ki * intError; + float phiObj = atan2(objAheadY - poseY, objAheadX - poseX); + float w = kw*atan2(sin(phiObj - poseTheta), cos(phiObj - poseTheta)); + float *wheelSpeeds; + wheelSpeeds = (float *)calloc(2, sizeof(float)); + + robotVel2wheelVel(v, w, wheelSpeeds); + + wheelSpeeds[0] = mapSpeeds(wheelSpeeds[0]); + wheelSpeeds[1] = mapSpeeds(wheelSpeeds[1]); + + setSpeeds((int)wheelSpeeds[0], (int)wheelSpeeds[1]); + + free(wheelSpeeds); + free(xactive); + free(yactive); + + //printf("f followPath; "); +} \ No newline at end of file
diff -r 0a718d139ed1 -r 1defb279922a control.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/control.h Tue May 11 18:10:22 2021 +0000 @@ -0,0 +1,17 @@ +#ifndef CONTROL_H_ +#define CONTROL_H_ + +#include "mbed.h" +#include "Matrix.h" + +extern const float TIMESTEP; +extern const float PI; +extern const float CELL_SIZE; +extern const int GRID_SIZE; + +void moveToPoint(float xObj, float yObj); +void followPath(float &objAheadX, float &objAheadY, float &intError, float *objCellCenter, Matrix occupationGrid, Serial pc); +float vff(Matrix occupationGrid, int *xactive, int *yactive, int activeSize, float *objCellCenter, Serial pc); +Matrix create_occupation_grid(); + +#endif \ No newline at end of file
diff -r 0a718d139ed1 -r 1defb279922a main.cpp --- a/main.cpp Wed Apr 24 16:00:07 2019 +0000 +++ b/main.cpp Tue May 11 18:10:22 2021 +0000 @@ -1,38 +1,34 @@ -// Coded by Luís Afonso 11-04-2019 #include "mbed.h" -#include "BufferedSerial.h" -#include "rplidar.h" #include "Robot.h" #include "Communication.h" - -Serial pc(SERIAL_TX, SERIAL_RX); -RPLidar lidar; -BufferedSerial se_lidar(PA_9, PA_10); -PwmOut rplidar_motor(D3); +#include "control.h" +//#include <Serial.h> -int main() -{ - float odomX, odomY, odomTheta; - struct RPLidarMeasurement data; - - pc.baud(115200); - init_communication(&pc); +Serial pc(USBTX, USBRX); +//PwmOut rplidar_motor(D3); - // Lidar initialization - rplidar_motor.period(0.001f); - lidar.begin(se_lidar); - lidar.setAngle(0,360); +int main() { + //pc.baud(115200); + //init_communication(&pc); + Matrix occupationGrid; + occupationGrid = create_occupation_grid(); + float xObj = 99.9; + float yObj = poseY; + float error = 0; + float intError = 0; + float objAheadX = poseX; + float objAheadY = poseY; + float objCellCenter[2] = {floor(xObj / CELL_SIZE) * CELL_SIZE + (CELL_SIZE / 2), + floor(yObj / CELL_SIZE) * CELL_SIZE + (CELL_SIZE / 2)}; - pc.printf("Program started.\n"); - - lidar.startThreadScan(); - - while(1) { - // poll for measurements. Returns -1 if no new measurements are available. returns 0 if found one. - if(lidar.pollSensorData(&data) == 0) - { - pc.printf("%f\t%f\t%d\t%c\n", data.distance, data.angle, data.quality, data.startBit); // Prints one lidar measurement. - } - wait(0.01); - } + do{ + updatePose(); + followPath(objAheadX, objAheadY, intError, objCellCenter, occupationGrid, pc); + error = sqrt((xObj - poseX)*(xObj - poseX) + (yObj - poseY)*(yObj - poseY)); + //printf("error = %f ", error); + printf("pose = [%.1f, %.1f]\n", poseX, poseY); + wait_us(TIMESTEP*1000000); + } while(error > CELL_SIZE); + + setSpeeds(0, 0); } \ No newline at end of file