Wall tracking robot

 July 2008

 

This project uses the synchronous drive chassis I developed to locate a wall and then drive alongside the wall in parallel. The idea is that the robot uses the radar to compute the angle to the wall, and then adjusts its steering to set the wheels pointing parallel to the wall. Of course the robot has to take periodic measurements to ensure that it is not deviating from the chosen course!


Theory


The basic idea is to take three radar measurements facing the wall and from the distances returned determine whether the robot is parallel to the wall, or turned to the left or right relative to the wall face. For this we’ll use some trigonometry to solve for the angle between the robot and the wall. First off, the angle we are looking for is given as the letter A in the figure below. If the robot is facing the wall straight on then A = 90 degrees.


To solve for A I used the Law of Cosines and the Law of Sines using the measurements obtained from the DISt-Nx sensor. To begin, we measure the distances from the robot face to the wall as follows:

 

Programming


Here is the sample program that runs this algorithm:


task main() {


  int d1, d2, d3;

  int line;

  float c, angleToWall, sinA;

  float fd1, fd2, fd3;


initialiseRobot();


sayHello();


  // Algorithm

// Start with radar and wheels pointing straight ahead (set this manually for now)

// Drive forward to find a wall

// Stop

// Turn radar right by 45 degrees

// Measure d1

// Turn radar left by 45 degrees

// Measure d2

// Turn radar left by 45 degrees

// Measure d3


line = 2;


// drive straight forward until we reach a wall

d1 = GetDistance();

while(d1 >= kDistToWallThreshold) {

motor[driveMotor] = kGoForwardFullSpeed;

wait10Msec(10);

d1 = GetDistance();

}


motor[driveMotor] = 0;


d1 = d2 = d3 = 0;


turnRadarBy(45, -1);

do {

  d1 = GetDistance();

  } while(d1 == 0);


turnRadarBy(45, +1);

  do {

  d2 = GetDistance();

  } while(d2 == 0);


turnRadarBy(45, 1);

do {

d3 = GetDistance();

} while(d3 == 0);


// and reset

turnRadarBy(45, -1);


if( (d1 >= d2) && (d2 <= d3) ) {

nxtDisplayTextLine(line++, "Straight on");

} else


if( (d1 <= d2) && (d2 <= d3) ) {

nxtDisplayTextLine(line++, "Turned left");

} else


if( (d1 >= d2) && (d2 >= d3) ) {

nxtDisplayTextLine(line++, "Turned right");

} else {

  nxtDisplayTextLine(line++, "Unknown");

}

nxtDisplayTextLine(line++, "d1 = %d", d1);

nxtDisplayTextLine(line++, "d2 = %d", d2);

nxtDisplayTextLine(line++, "d3 = %d", d3);


// now compute the angle of the robot to the wall

// Step 1: use law of Cosines to compute distance c

// c^2 = d1^2 + d2^2 - 2*d1*d2* cos 45

//

// scale back the measurements

fd1 = d1/10.0;

fd2 = d2/10.0;

fd3 = d3/10.0;


c = (fd1*fd1) + (fd2*fd2) - (2 * fd1 * fd2 * kCos45);

c = sqrt(c);


// now use the law of sines to compute the angle of the robot

// sin A = (d1 * sin 45) / c

sinA = (fd1 * kSin45) / c;

angleToWall = asin(sinA); // radians

angleToWall = radiansToDegrees(angleToWall);


nxtDisplayTextLine(line++, "Angle=%f", angleToWall);


// turn wheels parallel to wall angle

setWheelsToHeading(angleToWall);


// and off we go

motor[driveMotor] = kGoForwardFullSpeed;

wait10Msec(200);

motor[driveMotor] = 0;


while(1) {}

}

Last updated 3 September, 2008


All content © 2008 Mark Crosbie  mark@mastincrosbie.com


LEGO® is a trademark of the LEGO Group of companies which does not sponsor, authorize or endorse this site. This site, its owner and contents are in no way affiliated with or endorsed by the LEGO Group. For more please read the LEGO Fair Play policy.