torsdag den 14. oktober 2010

Lego lab lesson 6 - Robot Race

The Race

The purpose of the exercise is to start from the bottom of the track, drive up to the top, turn around and get to the bottom again. The numbers shown in the following diagram are used as references to track 1, 2 and 3 in the rest of the document and the code. At the end of each track we call it plateau 1, 2 and 3.


Robot construction

The first consideration to take for the race was how to construct the robot car. Which wheels to mount, and how many and which sensors to use.
The robot was constructed as in the first lab session for the line follower exercise. The wheels where changed to bigger ones, being able to get higher speed (and so higher chances to win the race!).
But no additional sensor was added. To make the robot and the control routine simple, only the light sensor and the taco counter provided by the motors have been used. If more sensors were used, the control routine would need more threads listening and reacting to those sensors, and that would probably make the control slower and more complicated. That means, of course, that there is not much information available from the environment. But using it correctly, it should be enough to complete the race.


Following the line

In lab 5, a routine was developed for following a line with the robot using a PID control [3]. The same routine was used in this case, but the different constants were recalculated because the size of the wheels was different. We go back to the fact that the physical environment is very important and affects the software inside.
public void run ()
{
    int count = 0;
    while (true)
    {
      try  {
        lightValue = sensor.light();
    pidCalculate(lightValue);
    
    if (!pause)
    {
    if (stop)
    Car.stop();
        else
    if (rightTurn)
    Car.forward(powerA, powerC);
    else
    Car.forward(powerC, powerA);
    
    // After a pause starts at reduced speed
    if (++count == 5)
    {
    // Accelerate to full speed
    if (Tp < Tp_saved) Tp = Tp + 1;
    count = 0;
    }
    }
    else
    count = 0;
   
    Thread.sleep(dT);  
      } catch (InterruptedException ie)  {   
      }   
    }     
  }



The pause variable’s purpose is to stop following the line and start again. It is used when the robot is changing direction in the corners of the track, since there is more than one line to follow and the robot does not know which one to follow.
When starting following the line again, it does not do it at full speed from the start, but it accelerates slowly. In the beginning it was returning to full speed after being stopped, but the robot had some difficulties on following the line after such an abrupt change of speed. After adding this slower acceleration, everything ran more smoothly.


Strategy

The overall strategy is to use the PID controlled line follower. This line controller will be running in a separate thread being responsible to follow the line on each of the 3 tracks on the Alishan train track. A state machine is defined to keep track on where we are on the Alishan train track. This state controller is running in another separate thread. At each plateau the state machine will take over turning the robot car in the right direction. That means we have chosen a mixture of a sequential and reactive control strategy as described by Fred G. Martin [5].

The UML class diagram illustrates the structure of the program. The StateController threads is scheduled with a periodicity of 10 ms and the LineFollowerPID with a periodicity of 5 ms. The main thread in the RoboRace is updating the LCD screen each second with light and time information. It also implements functions to increase/decrease the speed and pause the line follower thread manually. These function has only been used for testing.


The PID controlled line follower is a reactive controller with a closed loop feedback using the light sensor to control the power of the motor, keeping it following the black line on one side of the line (See states 1, 10, 20). The state machine is keeping track on where we are. It turns the robot car at the plateaus without using the light sensor. Turing is a open loop operation without any feedback only using time to decide on when the turn is completed (See state 2, 11, 21). When time is expired the state machine starts looking for the black line again and telling the line follower thread which side of the line we expect to be (State 3, 12). At the top of the Alishan train track we turn the robot car 180 degrees, decreases the speed and starts on the way down.


Below is listed the first 3 states of the StateController.
private void handelStates() throws InterruptedException
   {
dist = Car.updateTachoCounter();

LCD.drawString("Tacho ", 0, 7);
LCD.drawInt((int)(dist),4,10,7);
   
    switch (state)
    {
    case 1: // Moving up first time track 1
    if (lookForThreshold(dist, 2100)) // Track 1 2100
    {
       lineFollower.pause(true);
       time = 0;
       state = 2;
    }
   break;
    case 2: // At plateau no. 1
    if (time > 150)
    {
       state = 3;
    }
    else
       Car.forward(60, 37); // Turn on plateau no. 1
    break;
    case 3:
    if (lineFollower.sensor.black())
    {
       Car.resetTachoCounter();
       lineFollower.pause(false);
       time = 0;
       state = 10;    
    }
    else
    Car.forward(40, 30); // Turn on plateau no. 1
    break;

[...] //Rest of the states
}
[...]
}


Impediments / challenges

Battery level and power applied to the motor
After using many hours fine tuning the parameters in the routine and being very close to having a robot that could go through the track, the robot started reacting strangely... the batteries had much less power than in the start! And the methods used for controlling the motors were not taking into account, since when you apply a certain power to a motor, the speed is dependant of the power available in the batteries. Instead, the setSpeed method should have been used for more precision and less dependency on the battery power. [4]

Friction between the wheels and the floor
The wheels collected dust after being used in different tracks, modifying the friction of the robot with the surface. This was altering the calibration of the constants in the control routine.

Video recording
http://www.youtube.com/watch?v=H05ODk-qB5o

Source Code
http://code.google.com/p/josemariakim/source/browse/#svn/trunk/lab6/RoboRace

References

[1] LegoLab assignment - http://www.legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/Lesson.html
[2] Original Rules - http://www.legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/alishan_timber_loader.doc
[3] Lab 5 report - http://josemariakim.blogspot.com/2010/10/lab-session-5-line-follower.html
[4] Controlling motors - http://lejos.sourceforge.net/nxt/nxj/tutorial/MotorTutorial/ControllingMotors.htm
[5] Fred G. Martin, Robotic Explorations

Ingen kommentarer:

Send en kommentar