lab robotic coimbra

Dependencies:   ISR_Mini-explorer mbed

Files at this revision

API Documentation at this revision

Comitter:
Ludwigfr
Date:
Mon Jun 26 12:05:20 2017 +0000
Commit message:
this version should work, though it would be nice to test all the lab demo; there's also some code on the 4th lab at the end of MiniExplorerCoimbra.cpp

Changed in this revision

ISR_Mini-explorer.lib Show annotated file Show diff for this revision Revisions of this file
Map.cpp Show annotated file Show diff for this revision Revisions of this file
Map.hpp Show annotated file Show diff for this revision Revisions of this file
MiniExplorerCoimbra.cpp Show annotated file Show diff for this revision Revisions of this file
MiniExplorerCoimbra.hpp Show annotated file Show diff for this revision Revisions of this file
Sonar.cpp Show annotated file Show diff for this revision Revisions of this file
Sonar.hpp 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/ISR_Mini-explorer.lib	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/ISR/code/ISR_Mini-explorer/#15a30802e719
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Map.cpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,177 @@
+#include "Map.hpp"
+
+Map::Map(float widthRealMap, float heightRealMap, int nbCellWidth, int nbCellHeight){
+	this->widthRealMap=widthRealMap;
+	this->heightRealMap=heightRealMap;
+	this->nbCellWidth=nbCellWidth;
+	this->nbCellHeight=nbCellHeight;
+	this->sizeCellWidth=widthRealMap/(float)nbCellWidth;
+	this->sizeCellHeight=heightRealMap/(float)nbCellHeight;
+	
+	this->cellsLogValues= new float*[nbCellWidth];
+	for(int i = 0; i < nbCellWidth; ++i)
+    	this->cellsLogValues[i] = new float[nbCellHeight];
+    	
+	this->initialLogValues= new float*[nbCellWidth];
+	for(int i = 0; i < nbCellWidth; ++i)
+    	this->initialLogValues[i] = new float[nbCellHeight];
+    	
+	this->fill_initialLogValues();
+}
+
+//fill initialLogValues with the values we already know (here the bordurs)
+void Map::fill_initialLogValues(){
+    //Fill map, we know the border are occupied
+    for (int i = 0; i<this->nbCellWidth; i++) {
+        for (int j = 0; j<this->nbCellHeight; j++) {
+            if(j==0 || j==this->nbCellHeight-1 || i==0 || i==this->nbCellWidth-1)
+                this->initialLogValues[i][j] = this->proba_to_log(1);
+            else
+                this->initialLogValues[i][j] = this->proba_to_log(0.5);
+        }
+    }
+}
+
+void Map::fill_map_with_initial(){
+	for (int i = 0; i<this->nbCellWidth; i++) {
+        for (int j = 0; j<this->nbCellHeight; j++) {
+            this->cellsLogValues[i][j] = initialLogValues[i][j];
+        }
+    }
+}
+
+//returns the probability [0,1] that the cell is occupied from the log valAue lt
+float Map::log_to_proba(float lt){
+    return 1-1/(1+exp(lt));
+}
+
+void Map::update_cell_value(int widthIndice,int heightIndice ,float proba){
+    this->cellsLogValues[widthIndice][heightIndice]=this->cellsLogValues[widthIndice][heightIndice]+this->proba_to_log(proba)+this->initialLogValues[widthIndice][heightIndice];//map is filled as map[0][0] get the data for the point closest to the origin
+}
+
+float Map::cell_width_coordinate_to_world(int i){
+	return this->sizeCellWidth/2+i*this->sizeCellWidth;
+}
+
+float Map::cell_height_coordinate_to_world(int j){
+	return this->sizeCellHeight/2+j*this->sizeCellHeight;
+}
+
+float Map::get_proba_cell(int widthIndice, int heightIndice){
+	return  this->log_to_proba(this->cellsLogValues[widthIndice][heightIndice]);
+}
+
+//returns the log value that the cell is occupied from the probability value [0,1]
+float Map::proba_to_log(float p){
+    return log(p/(1-p));
+}
+
+/*
+
+float Map::robot_x_coordinate_in_world(float robot_x, float robot_y){
+    return this->nbCellWidth*this->sizeCellWidth-robot_y;
+}
+
+float Map::robot_y_coordinate_in_world(float robot_x, float robot_y){
+    return robot_x;
+}
+
+
+void MiniExplorerCoimbra::print_final_map() {
+    float currProba;
+    pc.printf("\n\r");
+    for (int y = this->nbCellHeight -1; y>-1; y--) {
+        for (int x= 0; x<this->nbCellWidth; x++) {
+                currProba=this->log_to_proba(this->cellsLogValues[x][y]);
+            if ( currProba < 0.5) {
+                pc.printf("   ");
+            } else {
+                if(currProba==0.5)
+                    pc.printf(" . ");
+                else
+                    pc.printf(" X ");
+            }
+        }
+        pc.printf("\n\r");
+    }
+}
+
+
+void Map::print_final_map_with_robot_position(float robot_x,float robot_y) {
+    float currProba;
+    float Xrobot=this->robot_x_coordinate_in_world(robot_x,robot_y);
+    float Yrobot=this->robot_y_coordinate_in_world(robot_x,robot_y);
+    
+    float heightIndiceInOrthonormal;
+    float widthIndiceInOrthonormal;
+    
+    float widthMalus=-(3*sizeCellWidth/2);
+    float widthBonus=sizeCellWidth/2;
+    
+    float heightMalus=-(3*sizeCellHeight/2);
+    float heightBonus=sizeCellHeight/2;
+
+    pc.printf("\n\r");
+    for (int y = this->nbCellHeight -1; y>-1; y--) {
+        for (int x= 0; x<this->nbCellWidth; x++) {
+            heightIndiceInOrthonormal=this->cell_height_coordinate_to_world(y);
+            widthIndiceInOrthonormal=this->cell_width_coordinate_to_world(x);
+            if(Yrobot >= (heightIndiceInOrthonormal+heightMalus) && Yrobot <= (heightIndiceInOrthonormal+heightBonus) && Xrobot >= (widthIndiceInOrthonormal+widthMalus) && Xrobot <= (widthIndiceInOrthonormal+widthBonus))                    
+                pc.printf(" R ");
+            else{
+                currProba=this->log_to_proba(this->cellsLogValues[x][y]);
+                if ( currProba < 0.5)
+                    pc.printf("   ");
+                else{
+                    if(currProba==0.5)
+                        pc.printf(" . ");
+                    else
+                        pc.printf(" X ");
+                } 
+            }
+        }
+        pc.printf("\n\r");
+    }
+}
+
+void Map::print_final_map_with_robot_position_and_target(float robot_x,float robot_y,float targetXWorld, float targetYWorld) {
+    float currProba;
+    float Xrobot=this->robot_x_coordinate_in_world(robot_x,robot_y);
+    float Yrobot=this->robot_y_coordinate_in_world(robot_x,robot_y);
+    
+    float heightIndiceInOrthonormal;
+    float widthIndiceInOrthonormal;
+    
+    float widthMalus=-(3*sizeCellWidth/2);
+    float widthBonus=sizeCellWidth/2;
+    
+    float heightMalus=-(3*sizeCellHeight/2);
+    float heightBonus=sizeCellHeight/2;
+
+    pc.printf("\n\r");
+    for (int y = this->nbCellHeight -1; y>-1; y--) {
+        for (int x= 0; x<this->nbCellWidth; x++) {
+            heightIndiceInOrthonormal=this->cell_height_coordinate_to_world(y);
+            widthIndiceInOrthonormal=this->cell_width_coordinate_to_world(x);
+            if(Yrobot >= (heightIndiceInOrthonormal+heightMalus) && Yrobot <= (heightIndiceInOrthonormal+heightBonus) && Xrobot >= (widthIndiceInOrthonormal+widthMalus) && Xrobot <= (widthIndiceInOrthonormal+widthBonus))
+                pc.printf(" R ");
+            else{
+                if(targetYWorld >= (heightIndiceInOrthonormal+heightMalus) && targetYWorld <= (heightIndiceInOrthonormal+heightBonus) && targetXWorld >= (widthIndiceInOrthonormal+widthMalus) && targetXWorld <= (widthIndiceInOrthonormal+widthBonus))                    
+                    pc.printf(" T ");
+                else{
+                    currProba=this->log_to_proba(this->cellsLogValues[x][y]);
+                    if ( currProba < 0.5)
+                        pc.printf("   ");
+                    else{
+                        if(currProba==0.5)
+                            pc.printf(" . ");
+                        else
+                            pc.printf(" X ");
+                    } 
+                }
+            }
+        }
+        pc.printf("\n\r");
+    }
+}
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Map.hpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,80 @@
+#ifndef MAP_HPP
+#define MAP_HPP
+
+#include<math.h>
+
+/*
+Robot coordinate system:      World coordinate system:
+      ^                                 ^
+      |x                                |y
+   <--R                                 O-->
+    y                                    x
+
+Screen coordinate system
+   x
+ O--->
+y|
+ v
+ 
+how the float[2] arrays stock the position 
+Start at 0,0 end top right
+^
+|heightIndice
+|
+_____>
+widthIndice
+*/
+
+
+class Map {
+
+public:
+    float widthRealMap;
+    float heightRealMap;
+    int nbCellWidth;
+    int nbCellHeight;
+    float sizeCellWidth;
+    float sizeCellHeight;
+    float** cellsLogValues;
+    float** initialLogValues;
+
+    Map(float widthRealMap, float heightRealMap, int nbCellWidth, int nbCellHeight);
+    
+    float cell_width_coordinate_to_world(int i);
+
+    float cell_height_coordinate_to_world(int j);
+    
+    float get_proba_cell(int widthIndice, int heightIndice);
+    
+    void fill_map_with_initial();
+    
+    //Updates map value
+    void update_cell_value(int widthIndice,int heightIndice ,float proba);
+        
+    //returns the probability [0,1] that the cell is occupied from the log valAue lt
+    float log_to_proba(float lt);
+
+    //returns the log value that the cell is occupied from the probability value [0,1]
+    float proba_to_log(float p);
+    
+    private:
+    
+    //fill initialLogValues with the values we already know (here the bordurs)
+    void fill_initialLogValues();
+    
+    /*
+    
+    float robot_x_coordinate_in_world(float robot_x, float robot_y);
+
+    float robot_y_coordinate_in_world(float robot_x, float robot_y);
+    
+    void print_final_map();
+
+    void print_final_map_with_robot_position(float robot_x,float robot_y);
+
+    void print_final_map_with_robot_position_and_target(float robot_x,float robot_y,float targetXWolrd, float targetYWorld);
+    */
+}; 
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MiniExplorerCoimbra.cpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,1016 @@
+#include "MiniExplorerCoimbra.hpp"
+#include "robot.h"
+
+#define PI 3.14159
+
+MiniExplorerCoimbra::MiniExplorerCoimbra(float defaultXWorld, float defaultYWorld, float defaultThetaWorld):map(200,200,20,20),sonarLeft(10*PI/36,-4,4),sonarFront(0,0,5),sonarRight(-10*PI/36,4,4){
+    i2c1.frequency(100000);
+    initRobot(); //Initializing the robot
+    pc.baud(9600); // baud for the pc communication
+
+    measure_always_on();//TODO check if needed
+
+    this->setXYThetaAndXYThetaWorld(defaultXWorld,defaultYWorld,defaultThetaWorld);
+    this->radiusWheels=3.25;
+    this->distanceWheels=7.2; 
+    
+    this->khro=12;
+    this->ka=30;
+    this->kb=-13;
+    this->kv=200;
+    this->kh=200;
+
+    this->rangeForce=30;
+    this->attractionConstantForce=10000;
+    this->repulsionConstantForce=1;
+} 
+
+void MiniExplorerCoimbra::setXYThetaAndXYThetaWorld(float defaultXWorld, float defaultYWorld, float defaultThetaWorld){
+    this->xWorld=defaultXWorld;
+    this->yWorld=defaultYWorld;
+    this->thetaWorld=defaultThetaWorld;
+    X=defaultYWorld;
+    Y=-defaultXWorld;
+	if(defaultThetaWorld < -PI/2)
+		theta=PI/2+PI-defaultThetaWorld;
+	else
+		theta=defaultThetaWorld-PI/2;
+}
+
+void MiniExplorerCoimbra::myOdometria(){
+	Odometria();
+	this->xWorld=-Y;
+	this->yWorld=X;
+	if(theta >PI/2)
+		this->thetaWorld=-PI+(theta-PI/2);
+	else
+		this->thetaWorld=theta+PI/2;
+}
+
+//generate a position randomly and makes the robot go there while updating the map
+void MiniExplorerCoimbra::randomize_and_map() {
+    //TODO check that it's aurelien's work
+    float movementOnX=rand()%(int)(this->map.widthRealMap/2);
+    float movementOnY=rand()%(int)(this->map.heightRealMap/2);
+    
+    float signOfX=rand()%2;
+    if(signOfX < 1)
+        signOfX=-1;
+    float signOfY=rand()%2;
+    if(signOfY  < 1)
+        signOfY=-1;
+        
+    float targetXWorld = movementOnX*signOfX;
+    float targetYWorld = movementOnY*signOfY;
+    float targetAngleWorld = 2*((float)(rand()%31416)-15708)/10000.0;
+    this->go_to_point_with_angle(targetXWorld, targetYWorld, targetAngleWorld);
+}
+
+//move of targetXWorld and targetYWorld ending in a targetAngleWorld
+void MiniExplorerCoimbra::go_to_point_with_angle(float targetXWorld, float targetYWorld, float targetAngleWorld) {
+    bool keepGoing=true;
+    float leftMm;
+    float frontMm; 
+    float rightMm;
+    float dt;
+    Timer t;
+    float distanceToTarget;
+    do {
+        //Timer stuff
+        dt = t.read();
+        t.reset();
+        t.start();
+        
+        //Updating X,Y and theta with the odometry values
+        this->myOdometria();
+       	leftMm = get_distance_left_sensor();
+    	frontMm = get_distance_front_sensor();
+    	rightMm = get_distance_right_sensor();
+
+        //if in dangerzone 
+        if((frontMm < 150 && frontMm > 0)|| (leftMm <150 && leftMm > 0) || (rightMm <150 && rightMm > 0) ){
+            leftMotor(1,0);
+            rightMotor(1,0);
+            this->update_sonar_values(leftMm, frontMm, rightMm);
+            //TODO Giorgos maybe you can also test the do_half_flip() function
+            this->myOdometria();
+            //do a flip TODO
+            keepGoing=false;
+            this->do_half_flip();   
+        }else{
+            //if not in danger zone continue as usual
+            this->update_sonar_values(leftMm, frontMm, rightMm);
+
+        	//Updating motor velocities
+            distanceToTarget=this->update_angular_speed_wheels_go_to_point_with_angle(targetXWorld,targetYWorld,targetAngleWorld,dt);
+    
+            wait(0.2);
+            //Timer stuff
+            t.stop();
+            pc.printf("\n\r dist to target= %f",distanceToTarget);
+        }
+    } while(distanceToTarget>1 && (abs(targetAngleWorld-this->thetaWorld)>0.01) && keepGoing);
+
+    //Stop at the end
+    leftMotor(1,0);
+    rightMotor(1,0);
+}
+
+float MiniExplorerCoimbra::update_angular_speed_wheels_go_to_point_with_angle(float targetXWorld, float targetYWorld, float targetAngleWorld, float dt){
+    //compute_angles_and_distance
+    //atan2 take the deplacement on x and the deplacement on y as parameters
+    float angleToPoint = atan2((targetYWorld-this->yWorld),(targetXWorld-this->xWorld))-this->thetaWorld;
+    angleToPoint = atan(sin(angleToPoint)/cos(angleToPoint));
+    //rho is the distance to the point of arrival
+    float rho = dist(targetXWorld,targetYWorld,this->xWorld,this->yWorld);
+    float distanceToTarget = rho;
+    //TODO check that
+    float beta = targetAngleWorld-angleToPoint-this->thetaWorld;        
+    
+    //Computing angle error and distance towards the target value
+    rho += dt*(-this->khro*cos(angleToPoint)*rho);
+    float temp = angleToPoint;
+    angleToPoint += dt*(this->khro*sin(angleToPoint)-this->ka*angleToPoint-this->kb*beta);
+    beta += dt*(-this->khro*sin(temp));
+
+    //Computing linear and angular velocities
+    float linear;
+    float angular;
+    if(angleToPoint>=-1.5708 && angleToPoint<=1.5708){
+        linear=this->khro*rho;
+        angular=this->ka*angleToPoint+this->kb*beta;
+    }
+    else{
+        linear=-this->khro*rho;
+        angular=-this->ka*angleToPoint-this->kb*beta;
+    }
+    float angular_left=(linear-0.5*this->distanceWheels*angular)/this->radiusWheels;
+    float angular_right=(linear+0.5*this->distanceWheels*angular)/this->radiusWheels;
+    
+    //Normalize speed for motors
+    if(angular_left>angular_right) {
+        angular_right=this->speed*angular_right/angular_left;
+        angular_left=this->speed;
+    } else {
+        angular_left=this->speed*angular_left/angular_right;
+        angular_right=this->speed;
+    }
+
+    //compute_linear_angular_velocities 
+    leftMotor(1,angular_left);
+    rightMotor(1,angular_right);
+    
+    return distanceToTarget;
+}
+
+void MiniExplorerCoimbra::update_sonar_values(float leftMm,float frontMm,float rightMm){
+    float xWorldCell;
+    float yWorldCell;
+    for(int i=0;i<this->map.nbCellWidth;i++){
+        for(int j=0;j<this->map.nbCellHeight;j++){
+        	xWorldCell=this->map.cell_width_coordinate_to_world(i);
+            yWorldCell=this->map.cell_height_coordinate_to_world(j);
+        	this->map.update_cell_value(i,j,this->sonarRight.compute_probability_t(rightMm/10,xWorldCell,yWorldCell,this->xWorld,this->yWorld,this->thetaWorld));
+        	this->map.update_cell_value(i,j,this->sonarLeft.compute_probability_t(leftMm/10,xWorldCell,yWorldCell,this->xWorld,this->yWorld,this->thetaWorld));
+        	this->map.update_cell_value(i,j,this->sonarFront.compute_probability_t(frontMm/10,xWorldCell,yWorldCell,this->xWorld,this->yWorld,this->thetaWorld));
+
+       	}
+    }
+}
+
+void MiniExplorerCoimbra::do_half_flip(){
+    this->myOdometria();
+    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);
+    leftMotor(0,100);
+    rightMotor(1,100);
+    while(abs(theta_plus_h_pi-theta)>0.05){
+        this->myOdometria();
+       // pc.printf("\n\r diff=%f", abs(theta_plus_pi-theta));
+    }
+    leftMotor(1,0);
+    rightMotor(1,0);    
+}
+
+//Distance computation function
+float MiniExplorerCoimbra::dist(float x1, float y1, float x2, float y2){
+    return sqrt(pow(y2-y1,2) + pow(x2-x1,2));
+}
+
+//use virtual force field
+void MiniExplorerCoimbra::try_to_reach_target(float targetXWorld,float targetYWorld){
+    //atan2 gives the angle beetween PI and -PI
+    this->myOdometria();
+    /*
+    float deplacementOnXWorld=targetXWorld-this->xWorld;
+    float deplacementOnYWorld=targetYWorld-this->yWorld;
+    */
+    float angleToTarget=atan2(targetYWorld-this->yWorld,targetXWorld-this->xWorld);
+    turn_to_target(angleToTarget);
+    bool reached=false;
+    int print=0;
+    while (!reached) {
+        this->vff(&reached,targetXWorld,targetYWorld);
+        //test_got_to_line(&reached);
+        if(print==10){
+            leftMotor(1,0);
+            rightMotor(1,0);
+            this->print_map_with_robot_position_and_target(targetXWorld,targetYWorld);
+            print=0;
+        }else
+            print+=1;
+    }
+    //Stop at the end
+    leftMotor(1,0);
+    rightMotor(1,0);
+    pc.printf("\r\n target reached");
+    wait(3);//
+}
+
+void MiniExplorerCoimbra::vff(bool* reached, float targetXWorld, float targetYWorld){
+    float line_a;
+    float line_b;
+    float line_c;
+    //Updating X,Y and theta with the odometry values
+    float forceXWorld=0;
+    float forceYWorld=0;
+    //we update the odometrie
+    this->myOdometria();
+    //we check the sensors
+    float leftMm = get_distance_left_sensor();
+    float frontMm = get_distance_front_sensor();
+    float rightMm = get_distance_right_sensor();
+    //update the probabilities values 
+    this->update_sonar_values(leftMm, frontMm, rightMm);
+    //we compute the force on X and Y
+    this->compute_forceX_and_forceY(&forceXWorld, &forceYWorld,targetXWorld,targetYWorld);
+    //we compute a new ine
+    this->calculate_line(forceXWorld, forceYWorld, &line_a,&line_b,&line_c);
+    //Updating motor velocities
+    this->go_to_line(line_a,line_b,line_c,targetXWorld,targetYWorld);
+
+    //wait(0.1);
+    this->myOdometria();
+    if(dist(this->xWorld,this->yWorld,targetXWorld,targetYWorld)<10)
+        *reached=true;
+}
+
+/*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 MiniExplorerCoimbra::turn_to_target(float angleToTarget){
+    this->myOdometria();
+    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){
+        this->myOdometria();
+        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);    
+}
+
+
+void MiniExplorerCoimbra::print_map_with_robot_position_and_target(float targetXWorld, float targetYWorld) {
+    float currProba;
+    
+    float heightIndiceInOrthonormal;
+    float widthIndiceInOrthonormal;
+    
+    float widthMalus=-(3*this->map.sizeCellWidth/2);
+    float widthBonus=this->map.sizeCellWidth/2;
+    
+    float heightMalus=-(3*this->map.sizeCellHeight/2);
+    float heightBonus=this->map.sizeCellHeight/2;
+
+    pc.printf("\n\r");
+    for (int y = this->map.nbCellHeight -1; y>-1; y--) {
+        for (int x= 0; x<this->map.nbCellWidth; x++) {
+            heightIndiceInOrthonormal=this->map.cell_height_coordinate_to_world(y);
+            widthIndiceInOrthonormal=this->map.cell_width_coordinate_to_world(x);
+            if(this->yWorld >= (heightIndiceInOrthonormal+heightMalus) && this->yWorld <= (heightIndiceInOrthonormal+heightBonus) && this->xWorld >= (widthIndiceInOrthonormal+widthMalus) && this->xWorld <= (widthIndiceInOrthonormal+widthBonus))
+                pc.printf(" R ");
+            else{
+                if(targetYWorld >= (heightIndiceInOrthonormal+heightMalus) && targetYWorld <= (heightIndiceInOrthonormal+heightBonus) && targetXWorld >= (widthIndiceInOrthonormal+widthMalus) && targetXWorld <= (widthIndiceInOrthonormal+widthBonus))                    
+                    pc.printf(" T ");
+                else{
+                    currProba=this->map.log_to_proba(this->map.cellsLogValues[x][y]);
+                    if ( currProba < 0.5)
+                        pc.printf("   ");
+                    else{
+                        if(currProba==0.5)
+                            pc.printf(" . ");
+                        else
+                            pc.printf(" X ");
+                    } 
+                }
+            }
+        }
+        pc.printf("\n\r");
+    }
+}
+
+
+//robotX and robotY are from this->myOdometria(), calculate line_a, line_b and line_c
+void MiniExplorerCoimbra::calculate_line(float forceX, float forceY, float *line_a, float *line_b, float *line_c){
+    /*
+    in the teachers maths it is 
+    
+    *line_a=forceY;
+    *line_b=-forceX;
+    
+    because a*x+b*y+c=0
+    a impact the vertical and b the horizontal
+    and he has to put them like this because
+    Robot space:      World space:
+      ^                 ^
+      |x                |y
+   <- R                 O ->
+    y                     x
+    but since our forceX, forceY are already computed in the orthonormal space I m not sure we need to 
+    */
+    *line_a=forceX;
+    *line_b=forceY;
+    //because the line computed always pass by the robot center we dont need lince_c
+    //*line_c=forceX*this->yWorld+forceY*this->xWorld;    
+    *line_c=0;
+}
+//compute the force on X and Y
+void MiniExplorerCoimbra::compute_forceX_and_forceY(float* forceXWorld, float* forceYWorld, float targetXWorld, float targetYWorld){
+	float forceRepulsionComputedX=0;
+	float forceRepulsionComputedY=0;
+	     for(int i=0;i<this->map.nbCellWidth;i++){	//for each cell of the map we compute a force of repulsion
+        for(int j=0;j<this->map.nbCellHeight;j++){
+            this->update_force(i,j,&forceRepulsionComputedX,&forceRepulsionComputedY);
+        }
+    }
+    //update with attraction force
+    *forceXWorld=+forceRepulsionComputedX;
+    *forceYWorld=+forceRepulsionComputedY;
+    float distanceTargetRobot=sqrt(pow(targetXWorld-this->xWorld,2)+pow(targetYWorld-this->yWorld,2));
+    if(distanceTargetRobot != 0){
+        *forceXWorld-=this->attractionConstantForce*(targetXWorld-this->xWorld)/distanceTargetRobot;
+        *forceYWorld-=this->attractionConstantForce*(targetYWorld-this->yWorld)/distanceTargetRobot;
+    }
+    float amplitude=sqrt(pow(*forceXWorld,2)+pow(*forceYWorld,2));
+    if(amplitude!=0){//avoid division by 0 if forceX and forceY  == 0
+        *forceXWorld=*forceXWorld/amplitude;
+        *forceYWorld=*forceYWorld/amplitude;
+    }
+}
+
+//currently line_c is not used
+void MiniExplorerCoimbra::go_to_line(float line_a, float line_b, float line_c,float targetXWorld, float targetYWorld){
+    float lineAngle;
+    float angleError;
+    float linear;
+    float angular; 
+    
+    //atan2 use the deplacement on X and the deplacement on Y
+    float angleToTarget=atan2(targetYWorld-this->yWorld,targetXWorld-this->xWorld);
+    bool aligned=false;
+    
+    //this condition is passed if the target is in the same direction as the robot orientation
+   	if((angleToTarget>0 && this->thetaWorld > 0) || (angleToTarget<0 && this->thetaWorld <0))
+    	aligned=true;
+    
+    //line angle is beetween pi/2 and -pi/2
+    /*
+    ax+by+c=0 (here c==0)
+    y=x*-a/b
+    if a*b > 0, the robot is going down
+    if a*b <0, the robot is going up
+    */	
+     if(line_b!=0){
+        if(!aligned)
+            lineAngle=atan(-line_a/line_b);
+        else
+            lineAngle=atan(line_a/-line_b);
+    }
+    else{
+        lineAngle=1.5708;
+    }
+    
+    //Computing angle error
+    angleError = lineAngle-this->thetaWorld;//TODO that I m not sure
+    angleError = atan(sin(angleError)/cos(angleError));
+
+    //Calculating velocities
+    linear=this->kv*(3.1416);
+    angular=this->kh*angleError;
+
+    float angularLeft=(linear-0.5*this->distanceWheels*angular)/this->radiusWheels;
+    float angularRight=(linear+0.5*this->distanceWheels*angular)/this->radiusWheels;
+    
+    //Normalize speed for motors
+    if(abs(angularLeft)>abs(angularRight)) {  
+        angularRight=this->speed*abs(angularRight/angularLeft)*this->sign1(angularRight);
+        angularLeft=this->speed*this->sign1(angularLeft);
+    }
+    else {
+        angularLeft=this->speed*abs(angularLeft/angularRight)*this->sign1(angularLeft);
+        angularRight=this->speed*this->sign1(angularRight);
+    }
+    leftMotor(this->sign2(angularLeft),abs(angularLeft));
+    rightMotor(this->sign2(angularRight),abs(angularRight));
+}
+
+void MiniExplorerCoimbra::update_force(int widthIndice, int heightIndice, float* forceRepulsionComputedX, float* forceRepulsionComputedY ){
+    //get the coordonate of the map and the robot in the ortonormal space
+    float xWorldCell=this->map.cell_width_coordinate_to_world(widthIndice);
+    float yWorldCell=this->map.cell_height_coordinate_to_world(heightIndice);
+    //compute the distance beetween the cell and the robot
+    float distanceCellToRobot=sqrt(pow(xWorldCell-this->xWorld,2)+pow(yWorldCell-this->yWorld,2));
+    //check if the cell is in range
+    if(distanceCellToRobot <= this->rangeForce) {
+        float probaCell=this->map.get_proba_cell(widthIndice,heightIndice);
+        *forceRepulsionComputedX+=this->repulsionConstantForce*probaCell*(xWorldCell-this->xWorld)/pow(distanceCellToRobot,3);
+        *forceRepulsionComputedY+=this->repulsionConstantForce*probaCell*(yWorldCell-this->yWorld)/pow(distanceCellToRobot,3);
+    }
+}
+
+//return 1 if positiv, -1 if negativ
+float MiniExplorerCoimbra::sign1(float value){
+    if(value>=0) 
+        return 1;
+    else 
+        return -1;
+}
+
+//return 1 if positiv, 0 if negativ
+int MiniExplorerCoimbra::sign2(float value){
+    if(value>=0) 
+        return 1;
+    else 
+        return 0;
+}
+
+/*
+void MiniExplorerCoimbra::test_procedure_lab_4(){
+    this->map.fill_map_with_initial();
+    float xEstimatedK=this->xWorld;
+    float yEstimatedK=this->yWorld;
+    float thetaWorldEstimatedK = this->thetaWorld;
+    float distanceMoved;
+    float angleMoved;
+    float PreviousCovarianceOdometricPositionEstimate[3][3];
+    PreviousCovarianceOdometricPositionEstimate[0][0]=0;
+    PreviousCovarianceOdometricPositionEstimate[0][1]=0;
+    PreviousCovarianceOdometricPositionEstimate[0][2]=0;
+    PreviousCovarianceOdometricPositionEstimate[1][0]=0;
+    PreviousCovarianceOdometricPositionEstimate[1][1]=0;
+    PreviousCovarianceOdometricPositionEstimate[1][2]=0;
+    PreviousCovarianceOdometricPositionEstimate[2][0]=0;
+    PreviousCovarianceOdometricPositionEstimate[2][1]=0;
+    PreviousCovarianceOdometricPositionEstimate[2][2]=0;
+    while(1){
+        distanceMoved=50;
+        angleMoved=0;
+        this->go_straight_line(50);
+        wait(1);
+        procedure_lab_4(xEstimatedK,yEstimatedK,thetaWorldEstimatedK,distanceMoved,angleMoved,PreviousCovarianceOdometricPositionEstimate);
+        pc.printf("\n\r x:%f,y:%f,theta:%f",this->xWorld,this->yWorld,this->thetaWorld);
+        pc.printf("\n\r xEstim:%f,yEstim:%f,thetaEstim:%f",xEstimatedK,yEstimatedK,thetaWorldEstimatedK);
+        this->turn_to_target(PI/2);
+        distanceMoved=0;
+        angleMoved=PI/2;
+        procedure_lab_4(xEstimatedK,yEstimatedK,thetaWorldEstimatedK,distanceMoved,angleMoved,PreviousCovarianceOdometricPositionEstimate);
+        pc.printf("\n\r x:%f,y:%f,theta:%f",this->xWorld,this->yWorld,this->thetaWorld);
+        pc.printf("\n\r xEstim:%f,yEstim:%f,thetaEstim:%f",xEstimatedK,yEstimatedK,thetaWorldEstimatedK);
+    }
+}
+
+void MiniExplorerCoimbra::go_straight_line(float distanceCm){
+	leftMotor(1,1);
+	rightMotor(1,1);
+	float xEstimated=this->xWorld+distanceCm*cos(this->thetaWorld);
+    float yEstimated=this->yWorld+distanceCm*sin(this->thetaWorld);
+	while(1){
+		this->myOdometria();
+		if(abs(xEstimated-this->xWorld) < 0.1 && abs(yEstimated-this->yWorld) < 0.1)
+			break;
+	}
+	leftMotor(1,0);
+	rightMotor(1,0);
+}
+
+//compute predicted localisation (assume movements are either straight lines or pure rotation), update PreviousCovarianceOdometricPositionEstimate
+//TODO tweak constant rewritte it good
+void MiniExplorerCoimbra::procedure_lab_4(float xEstimatedK,float yEstimatedK, float thetaWorldEstimatedK, float distanceMoved, float angleMoved, float PreviousCovarianceOdometricPositionEstimate[3][3]){
+
+    float distanceMovedByLeftWheel=distanceMoved/2;
+    float distanceMovedByRightWheel=distanceMoved/2;
+    if(angleMoved !=0){
+        //TODO check that not sure
+        distanceMovedByLeftWheel=-angleMoved/(2*this->distanceWheels);
+        distanceMovedByRightWheel=angleMoved/(2*this->distanceWheels);
+    }else{
+        distanceMovedByLeftWheel=distanceMoved/2;
+        distanceMovedByRightWheel=distanceMoved/2;
+    }
+        
+    float xEstimatedKNext=xEstimatedK+distanceMoved*cos(angleMoved);
+    float yEstimatedKNext=yEstimatedK+distanceMoved*sin(angleMoved);
+    float thetaWorldEstimatedKNext=thetaWorldEstimatedK+angleMoved;
+    
+    float kRight=0.1;//error constant 
+    float kLeft=0.1;//error constant 
+    float motionIncrementCovarianceMatrix[2][2];
+    motionIncrementCovarianceMatrix[0][0]=kRight*abs(distanceMovedByRightWheel);
+    motionIncrementCovarianceMatrix[0][1]=0;
+    motionIncrementCovarianceMatrix[1][0]=0;
+    motionIncrementCovarianceMatrix[1][1]=kLeft*abs(distanceMovedByLeftWheel);
+    
+    float jacobianFp[3][3];
+    jacobianFp[0][0]=1;
+    jacobianFp[0][1]=0;
+    jacobianFp[0][2]=-distanceMoved*sin(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFp[1][0]=0;
+    jacobianFp[1][1]=1;
+    jacobianFp[1][2]=distanceMoved*cos(thetaWorldEstimatedK+angleMoved/2);;
+    jacobianFp[2][0]=0;
+    jacobianFp[2][1]=0;
+    jacobianFp[2][2]=1;
+    
+    float jacobianFpTranspose[3][3];
+    jacobianFpTranspose[0][0]=1;
+    jacobianFpTranspose[0][1]=0;
+    jacobianFpTranspose[0][2]=0;
+    jacobianFpTranspose[1][0]=0;
+    jacobianFpTranspose[1][1]=1;
+    jacobianFpTranspose[1][2]=0;
+    jacobianFpTranspose[2][0]=-distanceMoved*sin(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFpTranspose[2][1]=distanceMoved*cos(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFpTranspose[2][2]=1;
+    
+    float jacobianFDeltarl[3][2];
+    jacobianFDeltarl[0][0]=(1/2)*cos(thetaWorldEstimatedK+angleMoved/2)-(distanceMoved/(2*this->distanceWheels))*sin(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarl[0][1]=(1/2)*cos(thetaWorldEstimatedK+angleMoved/2)+(distanceMoved/(2*this->distanceWheels))*sin(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarl[1][0]=(1/2)*sin(thetaWorldEstimatedK+angleMoved/2)+(distanceMoved/(2*this->distanceWheels))*cos(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarl[1][1]=(1/2)*sin(thetaWorldEstimatedK+angleMoved/2)-(distanceMoved/(2*this->distanceWheels))*cos(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarl[2][0]=1/this->distanceWheels;
+    jacobianFDeltarl[2][1]=-1/this->distanceWheels;
+    
+    float jacobianFDeltarlTranspose[2][3];//1,3,5;2,4,6
+    jacobianFDeltarlTranspose[0][0]=(1/2)*cos(thetaWorldEstimatedK+angleMoved/2)-(distanceMoved/(2*this->distanceWheels))*sin(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarlTranspose[0][1]=(1/2)*sin(thetaWorldEstimatedK+angleMoved/2)+(distanceMoved/(2*this->distanceWheels))*cos(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarlTranspose[0][2]=1/this->distanceWheels;
+    jacobianFDeltarlTranspose[1][0]=(1/2)*cos(thetaWorldEstimatedK+angleMoved/2)+(distanceMoved/(2*this->distanceWheels))*sin(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarlTranspose[1][1]=(1/2)*sin(thetaWorldEstimatedK+angleMoved/2)-(distanceMoved/(2*this->distanceWheels))*cos(thetaWorldEstimatedK+angleMoved/2);
+    jacobianFDeltarlTranspose[1][2]=-1/this->distanceWheels;
+    
+    float tempMatrix3_3[3][3];
+    int i;
+    int j;
+    int k;
+    for( i = 0; i < 3; ++i){//mult 3*3, 3*3
+        for(j = 0; j < 3; ++j){
+            for(k = 0; k < 3; ++k){
+                tempMatrix3_3[i][j] += jacobianFp[i][k] * PreviousCovarianceOdometricPositionEstimate[k][j];
+            }
+        }
+    }
+    float sndTempMatrix3_3[3][3];
+    for(i = 0; i < 3; ++i){//mult 3*3, 3*3
+        for(j = 0; j < 3; ++j){
+            for(k = 0; k < 3; ++k){
+                sndTempMatrix3_3[i][j] += tempMatrix3_3[i][k] * jacobianFpTranspose[k][j];
+            }
+        }
+    }
+    float tempMatrix3_2[3][2];
+    for(i = 0; i < 3; ++i){//mult 3*2 , 2,2
+        for(j = 0; j < 2; ++j){
+            for(k = 0; k < 2; ++k){
+                tempMatrix3_2[i][j] += jacobianFDeltarl[i][k] * motionIncrementCovarianceMatrix[k][j];
+            }
+        }
+    }
+    float thrdTempMatrix3_3[3][3];
+    for(i = 0; i < 3; ++i){//mult 3*2 , 2,3
+        for(j = 0; j < 3; ++j){
+            for(k = 0; k < 2; ++k){
+                thrdTempMatrix3_3[i][j] += tempMatrix3_2[i][k] * jacobianFDeltarlTranspose[k][j];
+            }
+        }
+    }
+    float newCovarianceOdometricPositionEstimate[3][3];
+    for(i = 0; i < 3; ++i){//add 3*3 , 3*3
+        for(j = 0; j < 3; ++j){
+            newCovarianceOdometricPositionEstimate[i][j]=sndTempMatrix3_3[i][j]+thrdTempMatrix3_3[i][j];
+        }
+    }
+    
+    //check measurements from sonars, see if they passed the validation gate
+    float leftCm = get_distance_left_sensor()/10;
+    float frontCm = get_distance_front_sensor()/10;
+    float rightCm = get_distance_right_sensor()/10;
+    //if superior to sonar range, put the value to sonar max range + 1
+    if(leftCm > this->sonarLeft.maxRange)
+        leftCm=this->sonarLeft.maxRange;
+    if(frontCm > this->sonarFront.maxRange)
+        frontCm=this->sonarFront.maxRange;
+    if(rightCm > this->sonarRight.maxRange)
+        rightCm=this->sonarRight.maxRange;
+    //get the estimated measure we should have according to our knowledge of the map and the previously computed localisation
+    float leftCmEstimated=this->sonarLeft.maxRange;
+    float frontCmEstimated=this->sonarFront.maxRange;
+    float rightCmEstimated=this->sonarRight.maxRange;
+    float xWorldCell;
+    float yWorldCell;
+    float currDistance;
+    float xClosestCellLeft;
+    float yClosestCellLeft;
+    float xClosestCellFront;
+    float yClosestCellFront;
+    float xClosestCellRight;
+    float yClosestCellRight;
+    for(int i=0;i<this->map.nbCellWidth;i++){
+        for(int j=0;j<this->map.nbCellHeight;j++){
+            //check if occupied, if not discard
+            if(this->map.get_proba_cell(i,j)==1){
+                //check if in sonar range
+                xWorldCell=this->map.cell_width_coordinate_to_world(i);
+                yWorldCell=this->map.cell_height_coordinate_to_world(j);
+                //check left
+                currDistance=this->sonarLeft.isInRange(xWorldCell,yWorldCell,xEstimatedKNext,yEstimatedKNext,thetaWorldEstimatedKNext);           
+                if((currDistance < this->sonarLeft.maxRange) && currDistance!=-1){
+                    //check if distance is lower than previous, update lowest if so
+                    if(currDistance < leftCmEstimated){
+                        leftCmEstimated= currDistance;
+                        xClosestCellLeft=xWorldCell;
+                        yClosestCellLeft=yWorldCell;
+                    }
+            	}
+                //check front
+                currDistance=this->sonarFront.isInRange(xWorldCell,yWorldCell,xEstimatedKNext,yEstimatedKNext,thetaWorldEstimatedKNext);           
+                if((currDistance < this->sonarFront.maxRange) && currDistance!=-1){
+                    //check if distance is lower than previous, update lowest if so
+                    if(currDistance < frontCmEstimated){
+                        frontCmEstimated= currDistance;
+                        xClosestCellFront=xWorldCell;
+                        yClosestCellFront=yWorldCell;
+                    }
+                }
+                //check right
+                currDistance=this->sonarRight.isInRange(xWorldCell,yWorldCell,xEstimatedKNext,yEstimatedKNext,thetaWorldEstimatedKNext);              
+                if((currDistance < this->sonarRight.maxRange) && currDistance!=-1){
+                    //check if distance is lower than previous, update lowest if so
+                    if(currDistance < rightCmEstimated){
+                        rightCmEstimated= currDistance;
+                        xClosestCellRight=xWorldCell;
+                        yClosestCellRight=yWorldCell;
+                    }
+                }
+            }
+        }
+    }
+    //get the innoncation: the value of the difference between the actual measure and what we anticipated
+    float innovationLeft=leftCm-leftCmEstimated;
+    float innovationFront=frontCm-frontCmEstimated;
+    float innovationRight=-rightCm-rightCmEstimated;
+    //compute jacobian of observation
+    float jacobianOfObservationLeft[3];
+    float jacobianOfObservationRight[3];
+    float jacobianOfObservationFront[3];
+    float xSonarLeft=xEstimatedKNext+this->sonarLeft.distanceX;
+    float ySonarLeft=yEstimatedKNext+this->sonarLeft.distanceY;
+    //left
+    jacobianOfObservationLeft[0]=(xSonarLeft-xClosestCellLeft)/leftCmEstimated;
+    jacobianOfObservationLeft[1]=(ySonarLeft-yClosestCellLeft)/leftCmEstimated;
+    jacobianOfObservationLeft[2]=(xClosestCellLeft-xSonarLeft)*(xSonarLeft*sin(thetaWorldEstimatedKNext)+ySonarLeft*cos(thetaWorldEstimatedKNext))+(yClosestCellLeft-ySonarLeft)*(-xSonarLeft*cos(thetaWorldEstimatedKNext)+ySonarLeft*sin(thetaWorldEstimatedKNext));
+    //front
+    float xSonarFront=xEstimatedKNext+this->sonarFront.distanceX;
+    float ySonarFront=yEstimatedKNext+this->sonarFront.distanceY;
+    jacobianOfObservationFront[0]=(xSonarFront-xClosestCellFront)/frontCmEstimated;
+    jacobianOfObservationFront[1]=(ySonarFront-yClosestCellFront)/frontCmEstimated;
+    jacobianOfObservationFront[2]=(xClosestCellFront-xSonarFront)*(xSonarFront*sin(thetaWorldEstimatedKNext)+ySonarFront*cos(thetaWorldEstimatedKNext))+(yClosestCellFront-ySonarFront)*(-xSonarFront*cos(thetaWorldEstimatedKNext)+ySonarFront*sin(thetaWorldEstimatedKNext));
+    //right
+    float xSonarRight=xEstimatedKNext+this->sonarRight.distanceX;
+    float ySonarRight=yEstimatedKNext+this->sonarRight.distanceY;
+    jacobianOfObservationRight[0]=(xSonarRight-xClosestCellRight)/rightCmEstimated;
+    jacobianOfObservationRight[1]=(ySonarRight-yClosestCellRight)/rightCmEstimated;
+    jacobianOfObservationRight[2]=(xClosestCellRight-xSonarRight)*(xSonarRight*sin(thetaWorldEstimatedKNext)+ySonarRight*cos(thetaWorldEstimatedKNext))+(yClosestCellRight-ySonarRight)*(-xSonarRight*cos(thetaWorldEstimatedKNext)+ySonarRight*sin(thetaWorldEstimatedKNext));
+
+    //left
+    float TempMatrix3_3InnovationLeft[3];
+    TempMatrix3_3InnovationLeft[0]=jacobianOfObservationLeft[0]*newCovarianceOdometricPositionEstimate[0][0]+jacobianOfObservationLeft[1]*newCovarianceOdometricPositionEstimate[1][0]+jacobianOfObservationLeft[2]*newCovarianceOdometricPositionEstimate[2][0];
+    TempMatrix3_3InnovationLeft[1]=jacobianOfObservationLeft[0]*newCovarianceOdometricPositionEstimate[0][1]+jacobianOfObservationLeft[1]*newCovarianceOdometricPositionEstimate[1][1]+jacobianOfObservationLeft[2]*newCovarianceOdometricPositionEstimate[2][1];
+    TempMatrix3_3InnovationLeft[2]=jacobianOfObservationLeft[0]*newCovarianceOdometricPositionEstimate[0][2]+jacobianOfObservationLeft[1]*newCovarianceOdometricPositionEstimate[1][2]+jacobianOfObservationLeft[2]*newCovarianceOdometricPositionEstimate[2][2];
+    float innovationConvarianceLeft=TempMatrix3_3InnovationLeft[0]*jacobianOfObservationLeft[0]+TempMatrix3_3InnovationLeft[1]*jacobianOfObservationLeft[1]+TempMatrix3_3InnovationLeft[2]*jacobianOfObservationLeft[2];
+    //front
+    float TempMatrix3_3InnovationFront[3];
+    TempMatrix3_3InnovationFront[0]=jacobianOfObservationFront[0]*newCovarianceOdometricPositionEstimate[0][0]+jacobianOfObservationFront[1]*newCovarianceOdometricPositionEstimate[1][0]+jacobianOfObservationFront[2]*newCovarianceOdometricPositionEstimate[2][0];
+    TempMatrix3_3InnovationFront[1]=jacobianOfObservationFront[0]*newCovarianceOdometricPositionEstimate[0][1]+jacobianOfObservationFront[1]*newCovarianceOdometricPositionEstimate[1][1]+jacobianOfObservationFront[2]*newCovarianceOdometricPositionEstimate[2][1];
+    TempMatrix3_3InnovationFront[2]=jacobianOfObservationFront[0]*newCovarianceOdometricPositionEstimate[0][2]+jacobianOfObservationFront[1]*newCovarianceOdometricPositionEstimate[1][2]+jacobianOfObservationFront[2]*newCovarianceOdometricPositionEstimate[2][2];
+    float innovationConvarianceFront=TempMatrix3_3InnovationFront[0]*jacobianOfObservationFront[0]+TempMatrix3_3InnovationFront[1]*jacobianOfObservationFront[1]+TempMatrix3_3InnovationFront[2]*jacobianOfObservationFront[2];
+    //right
+    float TempMatrix3_3InnovationRight[3];
+    TempMatrix3_3InnovationRight[0]=jacobianOfObservationRight[0]*newCovarianceOdometricPositionEstimate[0][0]+jacobianOfObservationRight[1]*newCovarianceOdometricPositionEstimate[1][0]+jacobianOfObservationRight[2]*newCovarianceOdometricPositionEstimate[2][0];
+    TempMatrix3_3InnovationRight[1]=jacobianOfObservationRight[0]*newCovarianceOdometricPositionEstimate[0][1]+jacobianOfObservationRight[1]*newCovarianceOdometricPositionEstimate[1][1]+jacobianOfObservationRight[2]*newCovarianceOdometricPositionEstimate[2][1];
+    TempMatrix3_3InnovationRight[2]=jacobianOfObservationRight[0]*newCovarianceOdometricPositionEstimate[0][2]+jacobianOfObservationRight[1]*newCovarianceOdometricPositionEstimate[1][2]+jacobianOfObservationRight[2]*newCovarianceOdometricPositionEstimate[2][2];
+    float innovationConvarianceRight=TempMatrix3_3InnovationRight[0]*jacobianOfObservationRight[0]+TempMatrix3_3InnovationRight[1]*jacobianOfObservationRight[1]+TempMatrix3_3InnovationRight[2]*jacobianOfObservationRight[2];
+    
+    //check if it pass the validation gate 
+    float gateScoreLeft=innovationLeft*innovationLeft/innovationConvarianceLeft;
+    float gateScoreFront=innovationFront*innovationFront/innovationConvarianceFront;
+    float gateScoreRight=innovationRight*innovationRight/innovationConvarianceRight;
+    int leftPassed=0;
+    int frontPassed=0;
+    int rightPassed=0;
+    int e=10;//constant 
+    if(gateScoreLeft < e)
+        leftPassed=1;
+    if(gateScoreFront < e)
+        frontPassed=10;
+    if(gateScoreRight < e)
+        rightPassed=100;
+    //for those who passed
+    //compute composite innovation
+    float compositeInnovation[3];
+    int nbPassed=leftPassed+frontPassed+rightPassed;
+    switch(nbPassed){
+        case 0://none
+            compositeInnovation[0]=0;
+            compositeInnovation[1]=0;
+            compositeInnovation[2]=0;
+            break;
+        case 1://left
+            compositeInnovation[0]=innovationLeft;
+            compositeInnovation[1]=0;
+            compositeInnovation[2]=0;
+            break;
+        case 10://front
+            compositeInnovation[0]=0;
+            compositeInnovation[1]=innovationFront;
+            compositeInnovation[2]=0;
+            break;
+        case 11://left and front
+            compositeInnovation[0]=innovationLeft;
+            compositeInnovation[1]=innovationFront;
+            compositeInnovation[2]=0;
+            break;
+        case 100://right
+            compositeInnovation[0]=0;
+            compositeInnovation[1]=0;
+            compositeInnovation[2]=innovationRight;
+            break;
+        case 101://right and left
+            compositeInnovation[0]=innovationLeft;
+            compositeInnovation[1]=0;
+            compositeInnovation[2]=innovationRight;
+            break;
+        case 110://right and front
+            compositeInnovation[0]=0;
+            compositeInnovation[1]=innovationFront;
+            compositeInnovation[2]=innovationRight;
+            break;
+        case 111://right front and left
+            compositeInnovation[0]=innovationLeft;
+            compositeInnovation[1]=innovationFront;
+            compositeInnovation[2]=innovationRight;
+            break;
+    }
+    //compute composite measurement Jacobian
+    float *compositeMeasurementJacobian;
+    switch(nbPassed){
+        case 0://none
+            break;
+        case 1://left
+            //compositeMeasurementJacobian = jacobianOfObservationLeft
+            break;
+        case 10://front
+            //compositeMeasurementJacobian = jacobianOfObservationFront
+            break;
+        case 11://left and front
+            compositeMeasurementJacobian=new float[6];
+            compositeMeasurementJacobian[0]= jacobianOfObservationLeft[0];
+            compositeMeasurementJacobian[1]= jacobianOfObservationLeft[1];
+            compositeMeasurementJacobian[2]= jacobianOfObservationLeft[2];
+            compositeMeasurementJacobian[3]= jacobianOfObservationFront[0];
+            compositeMeasurementJacobian[4]= jacobianOfObservationFront[1];
+            compositeMeasurementJacobian[5]= jacobianOfObservationFront[2];
+            break;
+        case 100://right
+            //compositeMeasurementJacobian = jacobianOfObservationRight
+            break;
+        case 101://right and left
+            compositeMeasurementJacobian=new float[6];
+            compositeMeasurementJacobian[0]= jacobianOfObservationLeft[0];
+            compositeMeasurementJacobian[1]= jacobianOfObservationLeft[1];
+            compositeMeasurementJacobian[2]= jacobianOfObservationLeft[2];
+            compositeMeasurementJacobian[3]= jacobianOfObservationRight[0];
+            compositeMeasurementJacobian[4]= jacobianOfObservationRight[1];
+            compositeMeasurementJacobian[5]= jacobianOfObservationRight[2];
+    
+            break;
+        case 110://right and front
+            compositeMeasurementJacobian=new float[6];
+            compositeMeasurementJacobian[0]= jacobianOfObservationFront[0];
+            compositeMeasurementJacobian[1]= jacobianOfObservationFront[1];
+            compositeMeasurementJacobian[2]= jacobianOfObservationFront[2];
+            compositeMeasurementJacobian[3]= jacobianOfObservationRight[0];
+            compositeMeasurementJacobian[4]= jacobianOfObservationRight[1];
+            compositeMeasurementJacobian[5]= jacobianOfObservationRight[2];
+    
+            break;
+        case 111://right front and left
+            compositeMeasurementJacobian=new float[9];
+            compositeMeasurementJacobian[0]= jacobianOfObservationLeft[0];
+            compositeMeasurementJacobian[1]= jacobianOfObservationLeft[1];
+            compositeMeasurementJacobian[2]= jacobianOfObservationLeft[2];
+            compositeMeasurementJacobian[3]= jacobianOfObservationFront[0];
+            compositeMeasurementJacobian[4]= jacobianOfObservationFront[1];
+            compositeMeasurementJacobian[5]= jacobianOfObservationFront[2];
+            compositeMeasurementJacobian[6]= jacobianOfObservationRight[0];
+            compositeMeasurementJacobian[7]= jacobianOfObservationRight[1];
+            compositeMeasurementJacobian[8]= jacobianOfObservationRight[2];
+            break;
+    }
+    //compute composite innovation covariance TODO dont have time, I assume you can just multiply them, can also simply all this easily
+    float compositeInnovationCovariance;
+    switch(nbPassed){
+        case 0://none
+            compositeInnovationCovariance=1;
+            break;
+        case 1://left
+            compositeInnovationCovariance = innovationConvarianceLeft;
+            
+            break;
+        case 10://front
+            compositeInnovationCovariance = innovationConvarianceFront;
+            break;
+        case 11://left and front
+            compositeInnovationCovariance=innovationConvarianceLeft*innovationConvarianceFront;
+    
+            break;
+        case 100://right
+            compositeInnovationCovariance = innovationConvarianceRight;
+            break;
+        case 101://right and left
+            compositeInnovationCovariance=innovationConvarianceLeft*innovationConvarianceRight;
+            break;
+        case 110://right and front
+            compositeInnovationCovariance=innovationConvarianceFront*innovationConvarianceRight;
+    
+    
+            break;
+        case 111://right front and left
+            compositeInnovationCovariance=innovationConvarianceLeft*innovationConvarianceFront*innovationConvarianceRight;
+      
+            break;
+    }
+    
+    //compute kalman gain
+    float kalmanGain[3][3];
+    switch(nbPassed){
+        //mult nbSonarPassed*3 , 3*3
+        case 0://none
+            break;
+        case 1://left
+            
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*1
+                for(j = 0; j < 1; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k];
+                    }
+                }
+            }
+            
+            break;
+        case 10://front
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*1
+                for(j = 0; j < 1; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k];
+                    }
+                }
+            }
+            break;
+        case 11://left and front
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*2
+                for(j = 0; j < 2; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k+j*3];
+                    }
+                }
+            }
+    
+            break;
+        case 100://right
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*1
+                for(j = 0; j < 1; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k];
+                    }
+                }
+            }
+            break;
+        case 101://right and left
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*2
+                for(j = 0; j < 2; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k+j*3];
+                    }
+                }
+            }
+    
+            break;
+        case 110://right and front
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*2
+                for(j = 0; j < 2; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k+j*3];
+                    }
+                }
+            }
+    
+    
+            break;
+        case 111://right front and left
+            for(i = 0; i < 3; ++i){//mult 3*3, 3*3
+                for(j = 0; j < 3; ++j){
+                    for(k = 0; k < 3; ++k){
+                        kalmanGain[i][j] += newCovarianceOdometricPositionEstimate[i][k] * compositeInnovationCovariance[k+j*3];
+                    }
+                }
+            }
+      
+            break;
+    }
+    
+    for(i = 0; i < 3; ++i){//mult 3*3, 3*3
+        for(j = 0; j < 3; ++j){
+            kalmanGain[i][j] = kalmanGain[i][j]/compositeInnovationCovariance;
+        }
+    }
+    //compute kalman gain * composite innovation
+    //mult 3*3 , 3*1
+    float result3_1[3];
+    for(i = 0; i < 3; ++i){//mult 3*3, 3*1
+        for(k = 0; k < 3; ++k){
+            result3_1[i] += kalmanGain[i][k] * compositeInnovation[k];
+        }
+    }
+    //compute updated robot position estimate
+    float xEstimatedKLast=xEstimatedKNext+result3_1[0];
+    float yEstimatedKLast=yEstimatedKNext+result3_1[1];
+    float thetaWorldEstimatedKLast=thetaWorldEstimatedKNext+result3_1[2];
+    //store the resultant covariance for next estimation
+
+    float kalmanGainTranspose[3][3];
+    kalmanGainTranspose[0][0]=kalmanGain[0][0];
+    kalmanGainTranspose[0][1]=kalmanGain[1][0];
+    kalmanGainTranspose[0][2]=kalmanGain[2][0];
+    kalmanGainTranspose[1][0]=kalmanGain[0][1];
+    kalmanGainTranspose[1][1]=kalmanGain[1][1];
+    kalmanGainTranspose[1][2]=kalmanGain[2][1];
+    kalmanGainTranspose[2][0]=kalmanGain[0][2];
+    kalmanGainTranspose[2][1]=kalmanGain[1][2];
+    kalmanGainTranspose[2][2]=kalmanGain[2][2];
+    
+    //mult 3*3 , 3*3
+    float fithTempMatrix3_3[3][3];
+    for(i = 0; i < 3; ++i){//mult 3*3 , 3*3
+        for(j = 0; j < 3; ++j){
+            for(k = 0; k < 3; ++k){
+                fithTempMatrix3_3[i][j] += kalmanGain[i][k] * kalmanGainTranspose[k][j];
+            }
+        }
+    }
+    for(i = 0; i < 3; ++i){//add 3*3 , 3*3
+        for(j = 0; j < 3; ++j){
+            fithTempMatrix3_3[i][j]=fithTempMatrix3_3[i][j]*compositeInnovationCovariance;
+        }
+    }
+    float covariancePositionEsimatedLast[3][3];
+    for(i = 0; i < 3; ++i){//add 3*3 , 3*3
+        for(j = 0; j < 3; ++j){
+            covariancePositionEsimatedLast[i][j]=fithTempMatrix3_3[i][j]+newCovarianceOdometricPositionEstimate[i][j];
+        }
+    }
+    //update PreviousCovarianceOdometricPositionEstimate
+    for(i = 0; i < 3; ++i){
+        for(j = 0; j < 3; ++j){
+            PreviousCovarianceOdometricPositionEstimate[i][j]=covariancePositionEsimatedLast[i][j];
+        }
+    }
+    
+    xEstimatedK=xEstimatedKLast;
+    yEstimatedK=yEstimatedKLast;
+    thetaWorldEstimatedK=thetaWorldEstimatedKLast;
+}
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MiniExplorerCoimbra.hpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,107 @@
+#ifndef MINIEXPLORERCOIMBRA_HPP
+#define MINIEXPLORERCOIMBRA_HPP
+
+#include "Map.hpp"
+#include "Sonar.hpp"
+#include<math.h>
+
+	/*
+Robot coordinate system:      			World coordinate system:
+      ^                 							^
+      |x                							|y
+   <--R                 							O-->
+    y                     							x
+    
+angles from pi/2 to 3pi/2->0 to pi              angles from 0 to pi->0 to pi 
+angles from pi/2 to -pi/2->0 to -pi				angles from pi to 2pi-> -pi to 0
+
+	The idea is that for every command to the robot we use to world coodinate system 
+*/
+
+class MiniExplorerCoimbra {
+	
+	public:
+	float xWorld;
+	float yWorld;
+	float thetaWorld;
+	Map map;
+	Sonar sonarLeft;
+	Sonar sonarFront;
+	Sonar sonarRight;
+	float speed;
+	float radiusWheels;
+	float distanceWheels; 
+	float khro;
+	float ka;
+	float kb;
+	float kv;
+	float kh;
+
+	float rangeForce;
+	float attractionConstantForce;
+	float repulsionConstantForce;
+
+	MiniExplorerCoimbra(float defaultXWorld, float defaultYWorld, float defaultThetaWorld);
+	
+	//generate a position randomly and makes the robot go there while updating the map
+	void randomize_and_map();
+	
+	//move of targetXWorld and targetYWorld ending in a targetAngleWorld
+	void go_to_point_with_angle(float targetXWorld, float targetYWorld, float targetAngleWorld);
+	
+	//use virtual force field
+	void try_to_reach_target(float targetXWorld,float targetYWorld);
+	
+	
+	void test_procedure_lab_4();
+	
+	private:
+	
+	void myOdometria();
+	
+	void setXYThetaAndXYThetaWorld(float defaultXWorld, float defaultYWorld, float defaultThetaWorld);
+	
+	float update_angular_speed_wheels_go_to_point_with_angle(float targetXWorld, float targetYWorld, float targetAngleWorld, float dt);
+	
+	void update_sonar_values(float leftMm,float frontMm,float rightMm);
+	
+	void do_half_flip();
+	
+	//Distance computation function
+	float dist(float x1, float y1, float x2, float y2);
+	
+	/*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);
+	
+	void print_map_with_robot_position_and_target(float targetXWorld, float targetYWorld);
+	
+	void vff(bool* reached, float targetXWorld, float targetYWorld);
+	
+	//compute the force on X and Y
+	void compute_forceX_and_forceY(float* forceXWorld, float* forceYWorld, float targetXWorld, float targetYWorld);
+	
+	void calculate_line(float forceX, float forceY, float *line_a, float *line_b, float *line_c);
+	
+	//currently line_c is not used
+	void go_to_line(float line_a, float line_b, float line_c,float targetXWorld, float targetYWorld);
+	
+	void update_force(int widthIndice, int heightIndice, float* forceRepulsionComputedX, float* forceRepulsionComputedY );
+
+	//return 1 if positiv, -1 if negativ
+	float sign1(float value);
+	
+	//return 1 if positiv, 0 if negativ
+	int sign2(float value);
+	
+	void go_straight_line(float distanceCm);
+	
+	void procedure_lab_4(float xEstimatedK,float yEstimatedK, float thetaWorldEstimatedK, float distanceMoved, float angleMoved, float PreviousCovarianceOdometricPositionEstimate[3][3]);
+
+};
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sonar.cpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,129 @@
+#include "Sonar.hpp"
+
+#define PI 3.14159
+
+Sonar::Sonar(float angleFromCenter, float distanceXFromRobotCenter, float distanceYFromRobotCenter ){
+	this->angleFromCenter=angleFromCenter;
+	this->distanceX=distanceXFromRobotCenter;
+	this->distanceY=distanceYFromRobotCenter;
+	this->maxRange=50;//cm
+	this->minRange=10;//Rmin cm
+	this->incertitudeRange=10;//cm
+	this->angleRange=3.14159/3;//Omega rad
+}
+
+//return distance sonar to cell if in range, -1 if not
+float Sonar::isInRange(float xCell, float yCell, float xRobotWorld, float yRobotWorld, float thetaWorld){
+	float xSonar=xRobotWorld+this->distanceX;
+	float ySonar=yRobotWorld+this->distanceY;	
+	float distanceCellToSonar=sqrt(pow(xCell-xSonar,2)+pow(yCell-ySonar,2));
+	
+	//check if the distance between the cell and the robot is within the circle of range RADIUS_WHEELS
+    if( distanceCellToSonar < this->maxRange){
+        //float anglePointToSonar=this->compute_angle_between_vectors(xCell,yCell,xSonar,ySonar);//angle beetween the point and the sonar beam
+        float angleCellToSonar=atan2(yCell-yRobotWorld,xCell-xRobotWorld);//like world system
+        
+       	       	float angleOriginToMidleOfBeam=thetaWorld+this->angleFromCenter;//
+
+        float angleDifference=angleCellToSonar-angleOriginToMidleOfBeam;
+        if(angleDifference > PI)
+            angleDifference=angleDifference-2*PI;
+        if(angleDifference < -PI)
+            angleDifference=angleDifference+2*PI;
+        //check if absolute difference between the angles is no more than Omega/2
+        if(angleDifference > 0 && angleDifference <= this->angleRange/2 ||angleDifference < 0 && angleDifference >= -this->angleRange/2 ){
+        	return distanceCellToSonar;
+        }
+    }
+    return -1;
+}
+
+//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 Sonar::compute_probability_t(float distanceObstacleDetected, float xCell, float yCell, float xRobotWorld, float yRobotWorld, float thetaWorld){
+	float xSonar=xRobotWorld+this->distanceX;
+	float ySonar=yRobotWorld+this->distanceY;
+    float distancePointToSonar=sqrt(pow(xCell-xSonar,2)+pow(yCell-ySonar,2));
+    //check if the distance between the cell and the robot is within the circle of range RADIUS_WHEELS
+    if( distancePointToSonar < this->maxRange){
+        //float anglePointToSonar=this->compute_angle_between_vectors(xCell,yCell,xSonar,ySonar);//angle beetween the point and the sonar beam
+        float anglePointToSonar=atan2(yCell-yRobotWorld,xCell-xRobotWorld);//like world system
+        
+       	       	float angleOriginToMidleOfBeam=thetaWorld+this->angleFromCenter;//
+
+        float angleDifference=anglePointToSonar-angleOriginToMidleOfBeam;
+        if(angleDifference > PI)
+            angleDifference=angleDifference-2*PI;
+        if(angleDifference < -PI)
+            angleDifference=angleDifference+2*PI;
+        //check if absolute difference between the angles is no more than Omega/2
+        if(angleDifference > 0 && angleDifference <= this->angleRange/2 ||angleDifference < 0 && angleDifference >= -this->angleRange/2 ){
+
+            if( distancePointToSonar < (distanceObstacleDetected - this->incertitudeRange)){
+            //point before obstacle, probably empty
+            /*****************************************************************************/
+                float Ea=1.f-pow((2*angleDifference)/this->angleRange,2);
+                float Er;
+                if(distancePointToSonar < this->minRange){
+                    //point before minimum sonar range
+                    Er=0.f;
+                }else{
+                    //point after minimum sonar range
+                    Er=1.f-pow((distancePointToSonar-this->minRange)/(distanceObstacleDetected-this->incertitudeRange-this->minRange),2);
+                }
+             /*****************************************************************************/
+                //if((1.f-Er*Ea)/2.f >1 || (1.f-Er*Ea)/2.f < 0)
+                //    pc.printf("\n\r return value=%f,Er=%f,Ea=%f,angleDifference=%f",(1.f-Er*Ea)/2.f,Er,Ea,angleDifference);
+                return (1.f-Er*Ea)/2.f;
+            }else{
+                //probably occuPIed
+            /*****************************************************************************/
+                float Oa=1.f-pow((2*angleDifference)/this->angleRange,2);
+                float Or;
+                if( distancePointToSonar <= (distanceObstacleDetected + this->incertitudeRange)){
+                    //point between distanceObstacleDetected +- INCERTITUDE_SONAR
+                    Or=1-pow((distancePointToSonar-distanceObstacleDetected)/(this->incertitudeRange),2);
+                }else{
+                    //point after in range of the sonar but after the zone detected
+                    Or=0;
+                }
+            /*****************************************************************************/
+                //if((1+Or*Oa)/2 >1 || (1+Or*Oa)/2 < 0)
+                //    pc.printf("\n\r return value=%f,Er=%f,Ea=%f,angleDifference=%f",(1+Or*Oa)/2,Or,Oa,angleDifference);
+                return (1+Or*Oa)/2;
+            }
+        }   
+    }
+    //not checked by the sonar
+    return 0.5;
+}
+
+//returns the angle between the vectors (x,y) and (xs,ys)
+float Sonar::compute_angle_between_vectors(float x, float y,float xs,float ys){
+    //alpha angle between ->x and ->SA
+    //vector S to A ->SA
+    float vSAx=x-xs;
+    float vSAy=y-ys;
+    //norme SA
+    float normeSA=sqrt(pow(vSAx,2)+pow(vSAy,2));
+    //vector ->x (1,0)
+    float cosAlpha=1*vSAy/*+0*vSAx*//normeSA;;
+    //vector ->y (0,1)
+    float sinAlpha=/*0*vSAy+*/1*vSAx/normeSA;//+0*vSAx;
+    if (sinAlpha < 0)
+        return -acos(cosAlpha);
+    else
+        return acos(cosAlpha);
+}
+
+//makes the angle inAngle between 0 and 2PI
+float Sonar::rad_angle_check(float inAngle){
+    if(inAngle > 0){
+        while(inAngle > (2*PI))
+            inAngle-=2*PI;
+    }else{
+        while(inAngle < 0)
+            inAngle+=2*PI;
+    }
+    return inAngle;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sonar.hpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,36 @@
+#ifndef SONAR_HPP
+#define SONAR_HPP
+
+#include<math.h>
+
+class Sonar {
+
+	public:
+	float maxRange;//cm
+	float minRange;//Rmin cm
+	float incertitudeRange;//cm
+	float angleRange;//Omega rad
+	float angleFromCenter;
+	float distanceX;
+	float distanceY;
+	
+	//the distance are in the world coordinates
+	Sonar(float angleFromCenter, float distanceXFromRobotCenter, float distanceYFromRobotCenter );
+
+	float compute_probability_t(float distanceObstacleDetected, float xCell, float yCell, float xRobotWorld, float yRobotWorld, float theta);
+	
+	//return distance sonar to cell if in range, -1 if not
+	float isInRange(float xCell, float yCell, float xRobotWorld, float yRobotWorld, float thetaWorld);
+	
+	private:
+	
+	//returns the angle between the vectors (x,y) and (xs,ys)
+	float compute_angle_between_vectors(float x, float y,float xs,float ys);
+
+	//makes the angle inAngle between 0 and 2pi
+	float rad_angle_check(float inAngle);
+
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,11 @@
+#include "MiniExplorerCoimbra.hpp"
+
+int main(){ 
+    MiniExplorerCoimbra myRobot(0,0,0);
+    //test lab2
+    //myRobot.randomize_and_map();
+    //test lab3
+    //myRobot.try_to_reach_target(50,30);
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Jun 26 12:05:20 2017 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/mbed_official/code/mbed/builds/64910690c574
\ No newline at end of file