fredag den 27. april 2012

Lab 10


Date:
25/04/2012 & 01/05/2012
Duration:
3 hours & 2 hours
Attendants:
Stefan Ravnholt, Thomas S. Sylvest & Jeppe Hansen
Goal:
Complete exercises for this week’s lab session.
Plan:
Make BumperCar run on an NXT

This was archived first by constructing the following robot.

Then we made sure that all sensors and actuators were connected to the same ports as required by the program BumperCar.java. In the end we uploaded the BumperCar.java program without any changes to the NXT and it ran successfully.



Press the touch sensor and keep it pressed. What happens? Explain.
The robot reverses and drives a bit against the clock. It is the same behavior that happens when the sonic sensor detects something in the way.

Implement a third behavior, Exit. This behavior should react to the ESCAPE button and call System.Exit(0) if ESCAPE is pressed. Exit should be the highest priority behavior. Try to press ESCAPE both when DriveForward is active and when DetectWall is active. Is the Exit behavior activated immediately?
When DriveForward is active and the ESCAPE button is pressed the robot exists pretty much immediately, however when the DetectWall behavior is active, the robot did ignore many of our button presses before finally exiting.

Both DriveForward and DetectWall have a method takeControl that are called in the Arbitrator. Investigate the source code for the Arbitrator and figure out if takeControl of DriveForward is called when the triggering condition of DetectWall is true.

for
(int i = maxPriority; i >= 0; i--)
{
  if (_behavior[i].takeControl())
  {
    _highestPriority = i;
    break;
   }
}

The code above is taken from the private class Monitor that the Arbitrator class uses to find out which is the behavior with the highest priority that also wants to take control. As one can see the Monitor class calls the takeControl method one by one from the highest priority to the lowest. When it finds a prority that wants to take control the program breaks out of the loop. This means that DriveForward’s takeControl method will not be called when DetectWall wants to control the actuators.



The takeControl method of DetectWall contains a call to the ultrasonic sensor method getDistance that includes a delay. This means that the call of takeControl for the other behaviors is delayed and the reaction to an event is not immidiate. In [1] it is recommende that takeControl "should return quickly, not perform a long calculation." To avoid the pause in the takeControl method of DetectWall a local thread in DetectWall could be implemented that sample the ultrasonic sensor e.g. every 20 msec and stores the result in a variable distance accessible to takeControl. Try that.
We have implemented the local thread that continuously samples the distance in the following way:


class SonicDetect extends Thread{
  private UltrasonicSensor sonar = new UltrasonicSensor(SensorPort.S3);
  private int distance;
  public synchronized int getDistance(){
    return distance;
  }
  public synchronized void setDistance(int newdist) {
    this.distance = newdist;
}
           
public void run() {
  while(true){
    setDistance(sonar.getDistance());
    try {
      Thread.sleep(20);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
 }
}
           
}

This way the DetectWall object can get the sonic distance instantly.



Try to implement the behavior DetectWall so the actions taken also involve to move backwards for 1 sec before turning & t
ry to implement the behavior DetectWall so it can be interrupted and started again e.g. if the touch sensor is pressed again while turning.



The resulted behavior of the robot, after implementing a part of the takeControl method as a thread, was that the Exit function of the robot became much more responsive. We were now able to turn off the robot, at any given time, and not at specific intervals.


After expanding the code for DetectWall, so it now drives backwards for 1 second, when it detects an obstacle, the car now drives backwards for one second when we put something in front of the sensor.


We added a new class Action, which is a thread that can be interrupted when the taskeControl method is called and the criteria are met:


    boolean a = touch.isPressed() || sony.getDistance() < 25;
    if (a) {
    action.interrupt();
    action = new Action();
    }


Now the robot continues to go backward as long as something is in front of it.


Implement motivation functions.
We have studied and understood the given code in Behavior.java, Arbitrator.java and BumperCar.java and have no suggested changes to the code.

tirsdag den 24. april 2012

Lab 9

Goal
Navigation
1. Record how accurate the car returns to its origional position

Navigation while avoiding objects
2. Figure out how to make the car move from place to place by means of the leJOS navigation system while the car avoids objects in front of it

Improved Navigation
3. Discuss the difference between update formula in [2] and [5]
4. Try to figure out what is the most accurate update formula
5. Try to figure out how leJOS updates the position and direction


Plan

  • Robot is already built.
  • Start solving tasks outlined in the goal section
  • Jeppe will program robot, and perform tests, Thomas and Stefan writes report.

Opgave 1



Opgave 2
Vi kan undgå at støde ind i forhindringer foran os, ved at påmontere en sonicSensor, som peger fremad. Denne sensor vil gøre os i stand til at måle om vi er ved at køre ind i noget.

Opgave 3
I [2] bliver der benyttet en teknik der hedder dead reckoning til at bestemme robottens position.
Dette går ud på at robotten kører i små "intervaller", hvor vi kender hvilken vinkel robotten bevæger sig, samt hvor langt den kører.
På denne måde kan vi ved hjælp af trigonomitri bestemme hvor i et 2-dimensionelt koordinatsystem robotten befinder sig.
deltaX = deltaDistance * cos(heading)
deltaY = deltaDistance * sin(heading)
Hvor deltaX er robottens bevægelse på x-aksen, mens deltaY er robottens bevægelse på Y-aksen.
For hvert interval bliver de nye målinger af x og y, så lagt til de forrige, for på den måde at få robottens nuværende position.
Dette bliver alt sammen overvåget af motorerne tacko counter.

I [5], navigerer man som i [2] ud fra et 2-dimensionelt koordinatsystem, her bliver den tilbagelagte afstand blot taget ud fra hjulenes hastighed, i stedet for ved hjælp af tacko-counteren.

Opgave 4
I vores forrige projekt, hvor vi skulle bygge en robot der kunne gennemføre banen til robotRace, prøvede vi både med robotter der blot brugte motorernes anslåede hastighed, samt en robot der benyttede tacko-counter.
Her viste det sig, at man ved hjælp at tacko-counter får et meget mere nøjagtigt resultat, idet motorerne altid er forskellige i hvor hurtigt de kører, på trods af at de får identiske indstillinger.
Dette vil selvfølgelig være mere udpræget jo hurtigere motorerne kører.

tirsdag den 17. april 2012

Lab 8, Robot Race


Date(s): 12-04-2012, 14-04-2012, 15-04-2012, 16-04-2012,
Duration of activity: 30 hours
Group members participating: Jeppe, Stefan, Thomas

Goal

Solve the Robot Race challenge.
The main goal is to just complete the track.

Plan

We wanted to try out a few ideas:
1) A simple robot that will just make it on the track.
2) The standard robot
3) A robot that navigates using a joint in the middle.
4) An other simple robot that will follow a more or less static path using only tacho counts.

Video record one of the robots that actually made it to the top and down again.

Results

1) The Simple Robot
The initial idea was to hardcode a robot that only by using controlMotor(...) and Thread.sleep(...), would be able to complete the track.
To test this we quickly made some simple code for the default robot (build after the booklet, 9797), which made us capable of reaching plateau two on the track. This convinced us that the general concept was durable and we started building a faster robot.
This new robot was given a gearing, which made it capable of driving much faster than the default robot. However, this made us aware that we did not have two motors which were equally fast.
This ment that our robot was turning slightly to the left when both motors had the same amount of power. Thus we went away from this kind of hardcoding of the robot, it would have to be a bit more advanced.

2) The standard robot
We returned to the default robot with some bigger wheels mounted. We also mounted two light sensors in front of it, such that it could follow the black line.
We wanted to add a gyroscope on the robot such that we could read if the robot was on the plateau where it was supposed to turn 180 degrees, or if it was on the ramp where it should just follow the line.
Since we did not have a gyroscope, we tried mounting a distance sensor (sonic sensor) on each side of the robot such that we could tell if we had reached a plateau or not.
We coded a simple line follower which could follow the straight line and stop when the robot reached the first plateau.




3) The Snake Robot
The robot would navigate by following the black line on the straight parts of the track. On the horizontal plateaus the robot would switch to a static 180 degree turn procedure after which the line follow program would take over.
The car has two engines. One that drives the car forward and one that is responsible for the navigation. See the sketch.



Two touch sensors are used to detect when the robot is at a horizontal plateau. Two arms (one on each side of the robot) sweeps close to the track, when the ground changes from the sliding part to the horizontal part, either the right arm or the left arm will push in the touch sensor. If the car is on the first plateau (turning right) the left arm will push in the touch sensor and vice versa.
Two light sensors are used to follow the black line.

The navigation is done using a PD controller. Where the error is modelled as the difference of measurement between the two light sensors, the error is translated as "for how long should the navigation motor spin in order to make the robot go in the right direction".

We programmed the robot to climb to the top plateau quite safely and at a "medium speed". We decided to give up the robot at that point since it was too big and slow.



4) Mr. Suicide
The Mr. Suicide robot (the video will explain the name) is "hardcoded" to make it all the way to the top without using any sensors other than the tacho counter in the motors.
The navigation relies on the fact that the robot can go on a straight line and turns the right amount of degrees on each plateau. This is achieved by looking at the difference of tacho count between the two motors. The P-controller looks as follows:


int error = MotorPort.B.getTachoCount() - MotorPort.A.getTachoCount();
MotorPort.A.controlMotor(speedA + error, forward);
MotorPort.B.controlMotor(speedB - error, forward);

This made the robot go on a straight line thus being reliable.
At the turns, the robot turned until a certain tacho count for each motor was reached.
After a long time of adjusting parameters, the robot was some what reliable and could complete the track in about every second or third tryout.

We discovered that the tacho count is best for going straight, when it comes to turning the robot around at the plaetaus, we relie on the fact that at certain number of degrees rotated by each motor will actually physically rotate the car - exactly - 180 degrees. This is not always true. This is very dependent of the battery state of the car!

However after a short while it became clear exactly which parameters are the most critical ones:
1) Number of degrees for motor A to rotate at plateau 1.
2) Number of degrees for motor B to rotate at plateau 2.

Thus calibrating could be done in a matter of a few minutes no matter the state of the battery.

Since the main goal of the competition was to get back to the green starting pad as fast as possible, we decided to make a small shortcut, by just plunging the robot down from the second plateau on to the green start field.
To avoid smashing the robot or the equipment, we mounted a lot of rubber tires on to the robot.
The tires was mounted in such a way that the robot would not bounce off the track, but stay in the geen start area when it falls down.

We managed to complete the track many times and video recorded 7 of them.
The most perfect (and fast) execution was completed in 28 seconds, as seen in the video:
http://daimi.au.dk/~u061245/Perfect7.mov

These was the results for the executions:

Perfect run 1: 32 sec.
Perfect run 2: 31 sec.
Perfect run 3: 30 sec.
Perfect run 4: 31 sec.
Perfect run 5: 34 sec.
Imperfect run 6: 27 sec.   Car bounced off the green area
Perfect run 7: 28 sec.



Conclusion


We tried out a few possible solutions before we finally reached the conclusion that the most simple robot would do the job.

The Mr. Suicide robot only needs calibration from the battery of the robot and not from the environment. It is very dependent of the start position, but also surprisingly successful considering that it was not always placed exactly on the same spot.
The Suicide robot took one afternoon to code and another afternoon to optimize. Using a static approach turned out to be very simple due to the nature of the track.



References
[1], Lesson 8, Robot Race,
http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson8.dir/Lesson.html