All the lab works are here!
Dependencies: ISR_Mini-explorer mbed
Fork of VirtualForces by
Diff: main.cpp
- Revision:
- 51:b863fad80574
- Parent:
- 50:a970cf7889d3
- Child:
- 52:54b3fe68a4f2
--- a/main.cpp Tue May 30 17:18:55 2017 +0000 +++ b/main.cpp Wed Jun 07 16:25:54 2017 +0000 @@ -4,6 +4,12 @@ using namespace std; +//update angularLeft and angularRight +float get_error_angles(float x, float y,float theta); +void test_procedure_Lab_2(); +void procedure_Lab_3(); +void procedure_Lab_2(); +void turn_to_target(float angleToTarget); void initialise_parameters(); //fill initialLogValues with the values we already know (here the bordurs) void fill_initial_log_values(); @@ -13,6 +19,8 @@ void do_half_flip(); //go the the given position while updating the map void go_to_point_with_angle(float target_x, float target_y, float target_angle); +void compute_angles_and_distance(float target_x, float target_y, float target_angle); +void compute_linear_angular_velocities(); //Updates sonar values void update_sonar_values(float leftMm, float frontMm, float rightMm); //function that check if a cell A(x,y) is in the range of the front sonar S(xs,ys) (with an angle depending on the sonar used, front 0, left pi/3, right -pi/3) returns the probability it's occupied/empty [0;1] @@ -53,10 +61,6 @@ float robot_sonar_left_y_in_orthonormal_y(); float estimated_width_indice_in_orthonormal_x(int i); float estimated_height_indice_in_orthonormal_y(int j); -//update angleError,distanceFromTarget,d2, beta -void compute_angles_and_distance(float target_x, float target_y, float target_angle,float dt,float* angleError,float* distanceFromTarget,float* d2,float* beta); -//update angularLeft and angularRight -void compute_linear_angular_velocities(float angleError,float distanceFromTarget,float beta, float* angularLeft, float* angularRight); //update foceX and forceY if necessary void update_force(int widthIndice, int heightIndice, float range, float* forceX, float* forceY, float xRobotOrtho, float yRobotOrtho ); //compute the X and Y force @@ -70,6 +74,7 @@ //set target in ortho space, in reference to the robot (so if the robot is in the middle, you want to him to go 10cm down and 15 right, set_target_to(15,-10) void set_target_to(float x, float y); void try_to_reach_target(); +void test_map_sonar(); //those target are in comparaison to the robot (for exemple a robot in 50,50 with a taget of 0,0 would not need to move) float targetX;//this is in the robot space top left @@ -103,12 +108,12 @@ const float DISTANCE_SONAR_FRONT_Y=5; //TODO adjust the size of the map for computation time (25*25?) -const float WIDTH_ARENA=120;//cm -const float HEIGHT_ARENA=90;//cm +const float WIDTH_ARENA=200;//cm +const float HEIGHT_ARENA=200;//cm //const int SIZE_MAP=25; -const int NB_CELL_WIDTH=24; -const int NB_CELL_HEIGHT=18; +const int NB_CELL_WIDTH=20; +const int NB_CELL_HEIGHT=20; //used to create the map 250 represent the 250cm of the square where the robot is tested //float sizeCell=250/(float)SIZE_MAP; @@ -124,25 +129,38 @@ //position and orientation of the robot when put on the map (ODOMETRY doesn't know those) it's in the robot space //this configuration suppose that the robot is in the middle of the arena facing up (to be sure you can use print_final_map_with_robot_position -const float DEFAULT_X=HEIGHT_ARENA/2; +const float DEFAULT_X=20; const float DEFAULT_Y=WIDTH_ARENA/2; //const float DEFAULT_X=20;//lower right //const float DEFAULT_Y=20;//lower right const float DEFAULT_THETA=0; -const int MAX_SPEED=200;//TODO TWEAK THE SPEED SO IT DOES NOT FUCK UP +const int MAX_SPEED=50;//TODO TWEAK THE SPEED SO IT DOES NOT FUCK UP const float KRHO=12, KA=30, KB=-13, KV=200, KH=200; //Kappa values //CONSTANT FORCE FIELD -const float FORCE_CONSTANT_REPULSION=50;//TODO tweak it -const float FORCE_CONSTANT_ATTRACTION=25;//TODO tweak it -const float RANGE_FORCE=50;//TODO tweak it +const float FORCE_CONSTANT_REPULSION=10000;//TODO tweak it +const float FORCE_CONSTANT_ATTRACTION=1;//TODO tweak it +const float RANGE_FORCE=30;//TODO tweak it + +float alpha; //angle error +float rho; //distance from target +float beta; +float linear, angular, angular_left, angular_right; +float dt=0.5; +float temp; +float d2; +Timer t; int main(){ initialise_parameters(); - //try to reach the target - set_target_to(50,-50);// + procedure_Lab_3(); +} + +void procedure_Lab_3(){ + //try to reach the target is ortho space + set_target_to(0,80);// print_final_map_with_robot_position_and_target(); try_to_reach_target(); //set_target_to(0,20);//lower right @@ -157,21 +175,62 @@ } } +void test_map_sonar(){ + float leftMm; + float frontMm; + float rightMm; + X=20; + Y=WIDTH_ARENA/2; + theta=0; + while(1){ + leftMm = get_distance_left_sensor(); + frontMm = get_distance_front_sensor(); + rightMm = get_distance_right_sensor(); + pc.printf("%f, %f, %f",leftMm,frontMm,rightMm); + //update the probabilities values + update_sonar_values(leftMm, frontMm, rightMm); + print_final_map(); + } +} + +void test_procedure_Lab_2(){ + X=HEIGHT_ARENA/2; + Y=WIDTH_ARENA/2; + set_target_to(-100,50); + print_final_map_with_robot_position_and_target(); + go_to_point_with_angle(targetX, targetY, pi/2); + print_final_map_with_robot_position_and_target(); + +} +void procedure_Lab_2(){ + for(int i=0;i<25;i++){ + randomize_and_map(); + print_final_map_with_robot_position(); + wait(2); + } +} + + void try_to_reach_target(){ + //atan2 gives the angle beetween pi and -pi + float angleToTarget=atan2(targetYOrhtoNotMap,targetXOrhtoNotMap); + turn_to_target(angleToTarget); bool reached=false; int print=0; while (!reached) { vff(&reached); //test_got_to_line(&reached); - if(print==30){ + if(print==10){ leftMotor(1,0); rightMotor(1,0); + /* pc.printf("\r\n theta=%f", theta); pc.printf("\r\n IN ORTHO:"); pc.printf("\r\n X Robot=%f", robot_center_x_in_orthonormal_x()); pc.printf("\r\n Y Robot=%f", robot_center_y_in_orthonormal_y()); pc.printf("\r\n X Target=%f", targetXOrhto); pc.printf("\r\n Y Target=%f", targetYOrhto); + */ print_final_map_with_robot_position_and_target(); print=0; }else @@ -225,10 +284,20 @@ //generate a position randomly and makes the robot go there while updating the map void randomize_and_map() { //TODO check that it's aurelien's work - float target_x = (rand()%(int)(HEIGHT_ARENA*10))/10;//for decimal precision - float target_y = (rand()%(int)(WIDTH_ARENA*10))/10; + float movementOnX=rand()%(int)(WIDTH_ARENA/2); + float movementOnY=rand()%(int)(HEIGHT_ARENA/2); + + float signOfX=rand()%2; + if(signOfX < 1) + signOfX=-1; + float signOfY=rand()%2; + if(signOfY < 1) + signOfY=-1; + + float x = movementOnX*signOfX; + float y = movementOnY*signOfY; float target_angle = 2*((float)(rand()%31416)-15708)/10000.0; - + set_target_to(x,y); go_to_point_with_angle(targetX, targetY, target_angle); } @@ -248,106 +317,6 @@ rightMotor(1,0); } -//go the the given position while updating the map -//TODO clean this procedure it's ugly as hell and too long -void go_to_point_with_angle(float target_x, float target_y, float target_angle) { - set_target_to(target_x,target_y); - Odometria(); - float angleError = atan2((target_y-Y),(target_x-X))-theta; - angleError = atan(sin(angleError)/cos(angleError)); - float distanceFromTarget = dist(robot_center_x_in_orthonormal_x(),robot_center_y_in_orthonormal_y(),targetXOrhto,targetYOrhto); - float beta = -angleError-theta+target_angle; - //beta = atan(sin(beta)/cos(beta)); - bool keep_going=true; - float leftMm; - float frontMm; - float rightMm; - float angularLeft=0; - float angularRight=0; - Timer t; - float dt=0.5;//TODO better name please - float d2;//TODO better name please - do { - //Timer stuff - dt = t.read(); - t.reset(); - t.start(); - - //Updating X,Y and theta with the odometry values - Odometria(); - leftMm = get_distance_left_sensor(); - frontMm = get_distance_front_sensor(); - rightMm = get_distance_right_sensor(); - - //pc.printf("\n\r leftMm=%f", leftMm); - //pc.printf("\n\r frontMm=%f", frontMm); - //pc.printf("\n\r rightMm=%f", rightMm); - - //if in dangerzone - if(frontMm < 120 || leftMm <120 || rightMm <120){ - leftMotor(1,0); - rightMotor(1,0); - update_sonar_values(leftMm, frontMm, rightMm); - //TODO Giorgos maybe you can also test the do_half_flip() function - Odometria(); - //do a flip TODO - keep_going=false; - do_half_flip(); - }else{ - //if not in danger zone continue as usual - update_sonar_values(leftMm, frontMm, rightMm); - compute_angles_and_distance(target_x, target_y, target_angle,dt,&angleError,&distanceFromTarget,&d2,&beta);//Compute the angles and the distance from target - compute_linear_angular_velocities(angleError,distanceFromTarget,beta,&angularLeft,&angularRight); //Using the angles and distance, compute the velocities needed (linear & angular) - - //pc.printf("\n\r X=%f", X); - //pc.printf("\n\r Y=%f", Y); - - //pc.printf("\n\r a_r=%f", angularRight); - //pc.printf("\n\r a_l=%f", angularLeft); - - //Updating motor velocities - leftMotor(sign2(angularLeft),abs(angularLeft)); - rightMotor(sign2(angularRight),abs(angularRight)); - - wait(0.2); - //Timer stuff - t.stop(); - } - } while(d2>1 && (abs(target_angle-theta)>0.01) && keep_going); - - //Stop at the end - leftMotor(1,0); - rightMotor(1,0); -} - -//Updates sonar values -void update_sonar_values(float leftMm, float frontMm, float rightMm){ - float currProba; - float i_in_orthonormal; - float j_in_orthonormal; - for(int i=0;i<NB_CELL_WIDTH;i++){ - for(int j=0;j<NB_CELL_HEIGHT;j++){ - //check if the point A(x,y) in the world space is within the range of the sonar (which has the coordinates xs, ys in the world space) - //check that again - //compute for front sonar - i_in_orthonormal=estimated_width_indice_in_orthonormal_x(i); - j_in_orthonormal=estimated_height_indice_in_orthonormal_y(j); - - currProba=compute_probability_t(i_in_orthonormal,j_in_orthonormal,robot_sonar_front_x_in_orthonormal_x(),robot_sonar_front_y_in_orthonormal_y(),ANGLE_FRONT_TO_FRONT,frontMm/10); - if(currProba!=0.5) - map[i][j]=map[i][j]+proba_to_log(currProba)+initialLogValues[i][j];//map is filled as map[0][0] get the data for the point closest to the origin - //compute for right sonar - currProba=compute_probability_t(i_in_orthonormal,j_in_orthonormal,robot_sonar_right_x_in_orthonormal_x(),robot_sonar_right_y_in_orthonormal_y(),ANGLE_FRONT_TO_RIGHT,rightMm/10); - if(currProba!=0.5) - map[i][j]=map[i][j]+proba_to_log(currProba)+initialLogValues[i][j]; - //compute for left sonar - currProba=compute_probability_t(i_in_orthonormal,j_in_orthonormal,robot_sonar_left_x_in_orthonormal_x(),robot_sonar_left_y_in_orthonormal_y(),ANGLE_FRONT_TO_LEFT,leftMm/10); - if(currProba!=0.5) - map[i][j]=map[i][j]+proba_to_log(currProba)+initialLogValues[i][j]; - } - } -} - //ODOMETRIA MUST HAVE BEEN CALLED //function that check if a cell A(x,y) is in the range of the front sonar S(xs,ys) (with an angle depending on the sonar used, front 0, left pi/3, right -pi/3) returns the probability it's occupied/empty [0;1] float compute_probability_t(float x, float y,float xs,float ys, float angleFromSonarPosition, float distanceObstacleDetected){ @@ -510,6 +479,7 @@ /**********************************************************************/ //Distance computation function float dist(float robot_x, float robot_y, float target_x, float target_y){ + //pc.printf("%f, %f, %f, %f",robot_x,robot_y,target_x,target_y); return sqrt(pow(target_y-robot_y,2) + pow(target_x-robot_x,2)); } @@ -542,7 +512,6 @@ return inAngle; } -// //returns the angle between the vectors (x,y) and (xs,ys) float compute_angle_between_vectors(float x, float y,float xs,float ys){ //alpha angle between ->x and ->SA @@ -560,9 +529,24 @@ else return acos(cosAlpha); } -/* + +//return 1 if positiv, -1 if negativ +float sign1(float value){ + if(value>=0) + return 1; + else + return -1; +} +//return 1 if positiv, 0 if negativ +int sign2(float value){ + if(value>=0) + return 1; + else + return 0; +} +/* Robot space: orthonormal space: ^ ^ |x |y @@ -615,53 +599,6 @@ return sizeCellHeight/2+j*sizeCellHeight; } -//update angleError,distanceFromTarget,d2, beta -void compute_angles_and_distance(float target_x, float target_y, float target_angle,float dt,float* angleError,float* distanceFromTarget,float* d2,float* beta){ - *angleError = atan2((target_y-Y),(target_x-X))-theta; - *angleError = atan(sin(*angleError)/cos(*angleError)); - *distanceFromTarget = dist(robot_center_x_in_orthonormal_x(),robot_center_y_in_orthonormal_y(),targetXOrhto,targetYOrhto); - *d2 = *distanceFromTarget; - *beta = -*angleError-theta+target_angle; - - //Computing angle error and distance towards the target value - *distanceFromTarget += dt*(-KRHO*cos(*angleError)**distanceFromTarget); - float temp = *angleError; - *angleError += dt*(KRHO*sin(*angleError)-KA**angleError-KB**beta); - *beta += dt*(-KRHO*sin(temp)); - //pc.printf("\n\r d2=%f", d2); - //pc.printf("\n\r dt=%f", dt); -} - -//update angularLeft and angularRight -void compute_linear_angular_velocities(float angleError,float distanceFromTarget,float beta,float* angularLeft, float* angularRight){ - //Computing linear and angular velocities - float linear; - float angular; - if(angleError>=-1.5708 && angleError<=1.5708){ - linear=KRHO*distanceFromTarget; - angular=KA*angleError+KB*beta; - } - else{ - linear=-KRHO*distanceFromTarget; - angular=-KA*angleError-KB*beta; - } - //TODO check those signs - *angularLeft=(linear-0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; - *angularRight=(linear+0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; - - float aL=*angularLeft; - float aR=*angularRight; - //Normalize speed for motors - if(abs(*angularLeft)>abs(*angularRight)) { - *angularRight=MAX_SPEED*abs(aR/aL)*sign1(aR); - *angularLeft=MAX_SPEED*sign1(aL); - } - else { - *angularLeft=MAX_SPEED*abs(aL/aR)*sign1(aL); - *angularRight=MAX_SPEED*sign1(aR); - } -} - void update_force(int widthIndice, int heightIndice, float range, float* forceX, float* forceY, float xRobotOrtho, float yRobotOrtho ){ //get the coordonate of the map and the robot in the ortonormal space float xCenterCell=estimated_width_indice_in_orthonormal_x(widthIndice); @@ -670,40 +607,17 @@ float distanceCellToRobot=sqrt(pow(xCenterCell-xRobotOrtho,2)+pow(yCenterCell-yRobotOrtho,2)); //check if the cell is in range if(distanceCellToRobot <= range) { - float probaCell=log_to_proba(map[widthIndice][heightIndice]); - float xForceComputed=FORCE_CONSTANT_REPULSION*probaCell*(xCenterCell-xRobotOrtho)/pow(distanceCellToRobot,3); - float yForceComputed=FORCE_CONSTANT_REPULSION*probaCell*(yCenterCell-yRobotOrtho)/pow(distanceCellToRobot,3); - *forceX+=xForceComputed; - *forceY+=yForceComputed; - } -} - -//compute the force on X and Y -void compute_forceX_and_forceY(float* forceX, float* forceY){ - //we put the position of the robot in an orthonormal space - float xRobotOrtho=robot_center_x_in_orthonormal_x(); - float yRobotOrtho=robot_center_y_in_orthonormal_y(); - - float forceRepulsionComputedX=0; - float forceRepulsionComputedY=0; - //for each cell of the map we compute a force of repulsion - for(int i=0;i<NB_CELL_WIDTH;i++){ - for(int j=0;j<NB_CELL_HEIGHT;j++){ - update_force(i,j,RANGE_FORCE,&forceRepulsionComputedX,&forceRepulsionComputedY,xRobotOrtho,yRobotOrtho); - } - } - //update with attraction force - *forceX=-forceRepulsionComputedX; - *forceY=-forceRepulsionComputedY; - float distanceTargetRobot=sqrt(pow(targetXOrhto-xRobotOrtho,2)+pow(targetYOrhto-yRobotOrtho,2)); - if(distanceTargetRobot != 0){ - *forceX+=FORCE_CONSTANT_ATTRACTION*(targetXOrhto-xRobotOrtho)/distanceTargetRobot; - *forceY+=FORCE_CONSTANT_ATTRACTION*(targetYOrhto-yRobotOrtho)/distanceTargetRobot; - } - float amplitude=sqrt(pow(*forceX,2)+pow(*forceY,2)); - if(amplitude!=0){//avoid division by 0 if forceX and forceY == 0 - *forceX=*forceX/amplitude; - *forceY=*forceY/amplitude; + /*float anglePointToRobot=compute_angle_between_vectors(xCenterCell,yCenterCell,xRobotOrtho,yRobotOrtho);//angle beetween the point and the sonar + float alphaBeforeAdjustment=anglePointToRobot-theta; + anglePointToRobot=rad_angle_check(alphaBeforeAdjustment); + if(anglePointToRobot <= pi/2 || anglePointToRobot >= rad_angle_check(-pi/2)){ + */ + float probaCell=log_to_proba(map[widthIndice][heightIndice]); + float xForceComputed=FORCE_CONSTANT_REPULSION*probaCell*(xCenterCell-xRobotOrtho)/pow(distanceCellToRobot,3); + float yForceComputed=FORCE_CONSTANT_REPULSION*probaCell*(yCenterCell-yRobotOrtho)/pow(distanceCellToRobot,3); + *forceX+=xForceComputed; + *forceY+=yForceComputed; + //} } } @@ -763,105 +677,6 @@ *reached=true; } -//return 1 if positiv, -1 if negativ -float sign1(float value){ - if(value>=0) - return 1; - else - return -1; -} - -//return 1 if positiv, 0 if negativ -int sign2(float value){ - if(value>=0) - return 1; - else - return 0; -} - -//currently line_c is not used -void go_to_line(float* angularLeft,float* angularRight,float line_a, float line_b, float line_c){ - float lineAngle; - float angleError; - float linear; - float angular; - - bool inFront=true; - //atan2 gives the angle beetween pi and -pi - float angleToTarget=atan2(targetYOrhtoNotMap,targetXOrhtoNotMap); - //pc.printf("angleToTarget=%f",angleToTarget); - if(angleToTarget < 0)//the target is in front - inFront=false; - - bool direction=true; - - if(theta > 0){ - //the robot is oriented to the left - if(theta > pi/2){ - //the robot is oriented lower left - if(inFront) - direction=false;//robot and target not oriented the same way - }else{ - //the robot is oriented upper left - if(!inFront) - direction=false;//robot and target not oriented the same way - } - }else{ - //the robot is oriented to the right - if(theta < -pi/2){ - //the robot is oriented lower right - if(inFront) - direction=false;//robot and target not oriented the same way - }else{ - //the robot is oriented upper right - if(!inFront) - direction=false;//robot and target not oriented the same way - } - } - - if(line_b!=0){ - if(!direction) - lineAngle=atan(-line_a/line_b); - else - lineAngle=atan(line_a/-line_b); - } - else{ - lineAngle=1.5708; - } - - /* - if(line_b!=0){ - lineAngle=atan(-line_a/line_b); - } - else{ - lineAngle=1.5708; - } - */ - //Computing angle error - angleError = lineAngle-theta; - angleError = atan(sin(angleError)/cos(angleError)); - - //Calculating velocities - linear=KV*(3.1416); - angular=KH*angleError; - //TODO if we put it like the poly says it fails, if we switch the plus and minus it works ... - *angularLeft=(linear-0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; - *angularRight=(linear+0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; - - float aL=*angularLeft; - float aR=*angularRight; - //Normalize speed for motors - if(abs(*angularLeft)>abs(*angularRight)) { - *angularRight=MAX_SPEED*abs(aR/aL)*sign1(aR); - *angularLeft=MAX_SPEED*sign1(aL); - } - else { - *angularLeft=MAX_SPEED*abs(aL/aR)*sign1(aL); - *angularRight=MAX_SPEED*sign1(aR); - } - pc.printf("\r\n line: %f x + %f y + %f =0 , X=%f; Y=%f", line_a, line_b, line_c,robot_center_x_in_orthonormal_x(),robot_center_y_in_orthonormal_y()); -} - //robotX and robotY are from Odometria, calculate line_a, line_b and line_c void calculate_line(float forceX, float forceY, float robotX, float robotY,float *line_a, float *line_b, float *line_c){ /* @@ -888,4 +703,287 @@ //float yRobotOrtho=robot_center_y_in_orthonormal_y(); //*line_c=forceX*yRobotOrtho+forceY*xRobotOrtho; *line_c=0; +} + +/*angleToTarget is obtained through atan2 so it s: +< 0 if the angle is bettween pi and 2pi on a trigo circle +> 0 if it is between 0 and pi +*/ +void turn_to_target(float angleToTarget){ + Odometria(); + float theta_plus_h_pi=theta+pi/2;//theta is between -pi and pi + if(theta_plus_h_pi > pi) + theta_plus_h_pi=-(2*pi-theta_plus_h_pi); + if(angleToTarget>0){ + leftMotor(0,1); + rightMotor(1,1); + }else{ + leftMotor(1,1); + rightMotor(0,1); + } + while(abs(angleToTarget-theta_plus_h_pi)>0.05){ + Odometria(); + theta_plus_h_pi=theta+pi/2;//theta is between -pi and pi + if(theta_plus_h_pi > pi) + theta_plus_h_pi=-(2*pi-theta_plus_h_pi); + //pc.printf("\n\r diff=%f", abs(angleToTarget-theta_plus_h_pi)); + } + leftMotor(1,0); + rightMotor(1,0); +} + +//currently line_c is not used +void go_to_line(float* angularLeft,float* angularRight,float line_a, float line_b, float line_c){ + float lineAngle; + float angleError; + float linear; + float angular; + + bool direction=true; + + float angleToTarget=atan2(targetYOrhtoNotMap,targetXOrhtoNotMap); + bool inFront=true; + if(angleToTarget < 0)//the target is in front + inFront=false; + + if(theta > 0){ + //the robot is oriented to the left + if(theta > pi/2){ + //the robot is oriented lower left + if(inFront) + direction=false;//robot and target not oriented the same way + }else{ + //the robot is oriented upper left + if(!inFront) + direction=false;//robot and target not oriented the same way + } + }else{ + //the robot is oriented to the right + if(theta < -pi/2){ + //the robot is oriented lower right + if(inFront) + direction=false;//robot and target not oriented the same way + }else{ + //the robot is oriented upper right + if(!inFront) + direction=false;//robot and target not oriented the same way + } + } + //pc.printf("\r\n Target is in front"); + + if(line_b!=0){ + if(!direction) + lineAngle=atan(-line_a/line_b); + else + lineAngle=atan(line_a/-line_b); + } + else{ + lineAngle=1.5708; + } + + //Computing angle error + angleError = lineAngle-theta; + angleError = atan(sin(angleError)/cos(angleError)); + + //Calculating velocities + linear=KV*(3.1416); + angular=KH*angleError; + + *angularLeft=(linear-0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; + *angularRight=(linear+0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; + + float aL=*angularLeft; + float aR=*angularRight; + //Normalize speed for motors + if(abs(*angularLeft)>abs(*angularRight)) { + *angularRight=MAX_SPEED*abs(aR/aL)*sign1(aR); + *angularLeft=MAX_SPEED*sign1(aL); + } + else { + *angularLeft=MAX_SPEED*abs(aL/aR)*sign1(aL); + *angularRight=MAX_SPEED*sign1(aR); + } + pc.printf("\r\n X=%f; Y=%f", robot_center_x_in_orthonormal_x(),robot_center_y_in_orthonormal_y()); +} + +//compute the force on X and Y +void compute_forceX_and_forceY(float* forceX, float* forceY){ + //we put the position of the robot in an orthonormal space + float xRobotOrtho=robot_center_x_in_orthonormal_x(); + float yRobotOrtho=robot_center_y_in_orthonormal_y(); + + float forceRepulsionComputedX=0; + float forceRepulsionComputedY=0; + //for each cell of the map we compute a force of repulsion + for(int i=0;i<NB_CELL_WIDTH;i++){ + for(int j=0;j<NB_CELL_HEIGHT;j++){ + update_force(i,j,RANGE_FORCE,&forceRepulsionComputedX,&forceRepulsionComputedY,xRobotOrtho,yRobotOrtho); + } + } + //update with attraction force + *forceX=+forceRepulsionComputedX; + *forceY=+forceRepulsionComputedY; + float distanceTargetRobot=sqrt(pow(targetXOrhto-xRobotOrtho,2)+pow(targetYOrhto-yRobotOrtho,2)); + if(distanceTargetRobot != 0){ + *forceX-=FORCE_CONSTANT_ATTRACTION*(targetXOrhto-xRobotOrtho)/distanceTargetRobot; + *forceY-=FORCE_CONSTANT_ATTRACTION*(targetYOrhto-yRobotOrtho)/distanceTargetRobot; + } + float amplitude=sqrt(pow(*forceX,2)+pow(*forceY,2)); + if(amplitude!=0){//avoid division by 0 if forceX and forceY == 0 + *forceX=*forceX/amplitude; + *forceY=*forceY/amplitude; + } +} + +//x and y passed are TargetNotMap +float get_error_angles(float x, float y,float theta){ + float angleBeetweenRobotAndTarget=atan2(y,x); + if(y > 0){ + if(angleBeetweenRobotAndTarget < pi/2)//up right + angleBeetweenRobotAndTarget=-pi/2+angleBeetweenRobotAndTarget; + else//up right + angleBeetweenRobotAndTarget=angleBeetweenRobotAndTarget-pi/2; + }else{ + if(angleBeetweenRobotAndTarget > -pi/2)//lower right + angleBeetweenRobotAndTarget=angleBeetweenRobotAndTarget-pi/2; + else//lower left + angleBeetweenRobotAndTarget=2*pi+angleBeetweenRobotAndTarget-pi/2; + } + return angleBeetweenRobotAndTarget-theta; +} + +void compute_angles_and_distance(float target_x, float target_y, float target_angle){ + alpha = atan2((target_y-Y),(target_x-X))-theta; + alpha = atan(sin(alpha)/cos(alpha)); + rho = dist(X, Y, target_x, target_y); + d2 = rho; + beta = -alpha-theta+target_angle; + + //Computing angle error and distance towards the target value + rho += dt*(-KRHO*cos(alpha)*rho); + temp = alpha; + alpha += dt*(KRHO*sin(alpha)-KA*alpha-KB*beta); + beta += dt*(-KRHO*sin(temp)); + //pc.printf("\n\r d2=%f", d2); + //pc.printf("\n\r dt=%f", dt); +} + +void compute_linear_angular_velocities(){ + //Computing linear and angular velocities + if(alpha>=-1.5708 && alpha<=1.5708){ + linear=KRHO*rho; + angular=KA*alpha+KB*beta; + } + else{ + linear=-KRHO*rho; + angular=-KA*alpha-KB*beta; + } + angular_left=(linear-0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; + angular_right=(linear+0.5*DISTANCE_WHEELS*angular)/RADIUS_WHEELS; + + //Normalize speed for motors + if(angular_left>angular_right) { + angular_right=MAX_SPEED*angular_right/angular_left; + angular_left=MAX_SPEED; + } else { + angular_left=MAX_SPEED*angular_left/angular_right; + angular_right=MAX_SPEED; + } +} + +//go the the given position while updating the map +void go_to_point_with_angle(float target_x, float target_y, float target_angle) { + Odometria(); + alpha = atan2((target_y-Y),(target_x-X))-theta; + alpha = atan(sin(alpha)/cos(alpha)); + rho = dist(X, Y, target_x, target_y); + beta = -alpha-theta+target_angle; + //beta = atan(sin(beta)/cos(beta)); + bool keep_going=true; + float leftMm; + float frontMm; + float rightMm; + do { + //Timer stuff + dt = t.read(); + t.reset(); + t.start(); + + //Updating X,Y and theta with the odometry values + Odometria(); + leftMm = get_distance_left_sensor(); + frontMm = get_distance_front_sensor(); + rightMm = get_distance_right_sensor(); + + //pc.printf("\n\r leftMm=%f", leftMm); + //pc.printf("\n\r frontMm=%f", frontMm); + //pc.printf("\n\r rightMm=%f", rightMm); + + //if in dangerzone + if((frontMm < 150 && frontMm > 0)|| (leftMm <150 && leftMm > 0) || (rightMm <150 && rightMm > 0) ){ + leftMotor(1,0); + rightMotor(1,0); + update_sonar_values(leftMm, frontMm, rightMm); + //TODO Giorgos maybe you can also test the do_half_flip() function + Odometria(); + //do a flip TODO + keep_going=false; + do_half_flip(); + }else{ + //if not in danger zone continue as usual + update_sonar_values(leftMm, frontMm, rightMm); + compute_angles_and_distance(target_x, target_y, target_angle); //Compute the angles and the distance from target + compute_linear_angular_velocities(); //Using the angles and distance, compute the velocities needed (linear & angular) + + //pc.printf("\n\r X=%f", X); + //pc.printf("\n\r Y=%f", Y); + + //pc.printf("\n\r a_r=%f", angular_right); + //pc.printf("\n\r a_l=%f", angular_left); + + //Updating motor velocities + leftMotor(1,angular_left); + rightMotor(1,angular_right); + + wait(0.2); + //Timer stuff + t.stop(); + pc.printf("\n\r dist to target= %f",d2); + } + } while(d2>1 && (abs(target_angle-theta)>0.01) && keep_going); + + //Stop at the end + leftMotor(1,0); + rightMotor(1,0); +} + +//Updates sonar values +void update_sonar_values(float leftMm, float frontMm, float rightMm){ + if(leftMm==0) + pc.printf("\n\r leftMm==0"); + if(frontMm==0) + pc.printf("\n\r frontMm==0"); + if(rightMm==0) + pc.printf("\n\r rightMm==0"); + float currProba; + float i_in_orthonormal; + float j_in_orthonormal; + for(int i=0;i<NB_CELL_WIDTH;i++){ + for(int j=0;j<NB_CELL_HEIGHT;j++){ + //check if the point A(x,y) in the world space is within the range of the sonar (which has the coordinates xs, ys in the world space) + //check that again + //compute for front sonar + i_in_orthonormal=estimated_width_indice_in_orthonormal_x(i); + j_in_orthonormal=estimated_height_indice_in_orthonormal_y(j); + + currProba=compute_probability_t(i_in_orthonormal,j_in_orthonormal,robot_sonar_front_x_in_orthonormal_x(),robot_sonar_front_y_in_orthonormal_y(),ANGLE_FRONT_TO_FRONT,frontMm/10); + map[i][j]=map[i][j]+proba_to_log(currProba)+initialLogValues[i][j];//map is filled as map[0][0] get the data for the point closest to the origin + //compute for right sonar + currProba=compute_probability_t(i_in_orthonormal,j_in_orthonormal,robot_sonar_right_x_in_orthonormal_x(),robot_sonar_right_y_in_orthonormal_y(),ANGLE_FRONT_TO_RIGHT,rightMm/10); + map[i][j]=map[i][j]+proba_to_log(currProba)+initialLogValues[i][j]; + //compute for left sonar + currProba=compute_probability_t(i_in_orthonormal,j_in_orthonormal,robot_sonar_left_x_in_orthonormal_x(),robot_sonar_left_y_in_orthonormal_y(),ANGLE_FRONT_TO_LEFT,leftMm/10); + map[i][j]=map[i][j]+proba_to_log(currProba)+initialLogValues[i][j]; + } + } } \ No newline at end of file