|
|
|
# Group 8
|
|
|
|
|
|
|
|
## Lab Notebook 7
|
|
|
|
|
|
|
|
**Date:** 21/4 - 2015
|
|
|
|
|
|
|
|
**Duration:** 8-12 hours
|
|
|
|
|
|
|
|
**Participants:**
|
|
|
|
|
|
|
|
- Frederik Jerløv
|
|
|
|
- Casper Christensen
|
|
|
|
- Mark Sejr Gottenborg
|
|
|
|
- Peder Detlefsen
|
|
|
|
|
|
|
|
## Goal
|
|
|
|
The goal is to further build on the Braitenberg vehicles from Lab 6 [1] in order to executing the exercises given to us in lab 7 [2].
|
|
|
|
|
|
|
|
## Plan
|
|
|
|
Our plan is to follow the exercises exactly as described, testing the the different build descriptions, with different settings and external influences.
|
|
|
|
|
|
|
|
## Results
|
|
|
|
|
|
|
|
### LEGO vehicle that exhibits a single behavior
|
|
|
|
|
|
|
|
We first build the robot with a bumper, an ultrasonic sensor and a light sensor. The construction can be seen in Figure 1. We then ran the program AvoidFigure9_3.java [3], which were given to us in the exercisers, the robots behaviour is to avoid obstacles using the ultrasonic sensor.
|
|
|
|
The robot does this by measuring the distance to the obstacles in front of it. if the distance value goes below a threshold (in this case 30) meaning that the robot senses an obstacle immediately in front of it. it checks for an alternate route by first turning left measuring the distance to obstacles in that direction and then turning right, past its original position and measuring the distance to obstacles to that side, it will then move to the side which have the largest distance, as that would be the better option.
|
|
|
|
|
|
|
|
![The robot we built for this exercise. At the bottom you see the bumper connected to the two touch sensors. Above it are the light sensor on the left and the ultrasonic sensor on the right.](http://i.imgur.com/8W0lOMJl.jpg)
|
|
|
|
|
|
|
|
Should the robot be in a situation where the measured values are still under the threshold the robot will immediately do the same behavior again measuring left and right and choosing the greatest distance, this can potentially lead to a situation where the robot is stuck moving back and forth between left and right, but we did not experience this behavior.
|
|
|
|
|
|
|
|
We then modified the program to drive back when all the three distances were below `stopThreshold`. Below is the snippet of code[4] we used in order to get the described behavior to work.
|
|
|
|
|
|
|
|
```Java
|
|
|
|
// Drive backwards and spin 180 degrees if everything is too close.
|
|
|
|
if (leftDistance < stopThreshold && rightDistance < stopThreshold) {
|
|
|
|
car.forward(0, power);
|
|
|
|
Delay.msDelay(750);
|
|
|
|
car.backward(power, power);
|
|
|
|
Delay.msDelay(ms*3);
|
|
|
|
car.forward(-power, power);
|
|
|
|
Delay.msDelay(1750);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
For the delay we have used some experimented numbers. This means that the values given was the once that worked the best for our robot. Below is a link to a video of the robot doing the described behavior.
|
|
|
|
|
|
|
|
[Video link of Robot backing and turning 180 degree.](https://www.youtube.com/watch?v=lRW77bRqaFs)[5]
|
|
|
|
|
|
|
|
### Behaviors as concurrent threads
|
|
|
|
For this section the goal was to experiment with and observe the behavior of the robot while running the program $RobotFigure9_9.java$. This program implements the Avoid, Follow and Cruise behaviors along with an arbitration mechanism which are all based on suggestions from [6]. We have used two touch sensors, an ultrasonic sensor and a light sensor with our robot, which is a bit different than the build in [6] as they use an IR detector instead an ultrasonic sensor, though they both serve the same purpose.
|
|
|
|
|
|
|
|
When running the program we observed the car’s behavior and what conditions triggered them. The first thing we noticed was that the car drove straight ahead if no obstacles were in its way. If an obstacle got in its way the car would look to both sides and go towards the side with the most room left. The final behaviour we observed was that the car would go towards bright light by again looking left and right and continue towards the side with the brightest light.
|
|
|
|
|
|
|
|
Moving on to the conditions that triggered those behaviors we will start Avoid. Based on our observations this behavior was triggered when the car moved within a certain distance to an obstacle. The condition resulting in the Follow behavior was a more difficult to determine just by observing the car. Sometimes the behavior would never happen when using the car in a uniformly lit environment. Based on that we concluded that the car would have to spot an increase in light to trigger the behavior. The Cruise behavior was simply a fallback for when none of the other conditions were met.
|
|
|
|
|
|
|
|
To get to know the exact triggers for each behavior we looked into the three classes $Avoid.java$, $Follow.java$ and $Cruise.java$.
|
|
|
|
The Avoid class implements the same behavior as in the previous program $AvoidFigure9_3.java$ where the car will stop when reading a distance less than or equal to a fixed threshold of 30 cm. Next it will turn left, measure the distance, turn right and then measure again to determine which direction have the most space. If the left side had the most space then the car will turn towards the left side again otherwise it will keep pointing to the right before the next iteration of the control loop.
|
|
|
|
The Follow class uses the light sensor to measure an initial light threshold which is used throughout the entire running time of the program to determine if the car should follow the light or not. As long as the light readings are less than or equal to the threshold then no actions is taken. This is why the car could drive around a room without ever performing the Follow behaviour. If a reading is above the threshold, the car will stop, turn left and measure the light then turn to the right and measure again. The difference between those values are then used to control the power levels of the motors to make the car move in the direction of the light for a while.
|
|
|
|
The Cruise class have no triggers as it simply drives forward at a fixed speed forever.
|
|
|
|
|
|
|
|
### Add an Escape behavior
|
|
|
|
In this exercise we have implemented the escape behavior based on the implementation on page 305 of [6]. Below is the code for our implemented escape[7].
|
|
|
|
|
|
|
|
```Java
|
|
|
|
while (true) {
|
|
|
|
// Front bump
|
|
|
|
if(left.isPressed() && right.isPressed()) {
|
|
|
|
car.backward(power, power);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
// Either turn right or left (50/50)
|
|
|
|
if(r.nextBoolean()) {
|
|
|
|
car.forward(0, power);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
} else {
|
|
|
|
car.forward(power, 0);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Left bump
|
|
|
|
else if(left.isPressed()) {
|
|
|
|
car.backward(power, power);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
car.forward(power, 0);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
}
|
|
|
|
// Right bump
|
|
|
|
else if(right.isPressed()) {
|
|
|
|
car.backward(power, power);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
car.forward(0, power);
|
|
|
|
Delay.msDelay(ms);
|
|
|
|
} else {
|
|
|
|
car.noCommand();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The first scenario is that if both `TouchSensors` is pressed, we register it as a `front` bump. What we then do is that we move back for 500 ms. Then we by a fifty fifty chance we turn left or right.
|
|
|
|
The next scenario is that only the left `TouchSensor` is pressed. Then we move back a bit and then turn right.
|
|
|
|
The last scenario is like the one above, instead when we hit the right `TouchSensor` we then turn left instead. If nothing happen we call the `car.noCommand()` in order to check for other behavior. Below is a link to a video, showing the escape behavior.
|
|
|
|
|
|
|
|
[Video of robot with escape + cruise, without avoid + follow to demonstrate escape behavior](https://www.youtube.com/watch?v=Pqq4j9tIe5E)[8]
|
|
|
|
|
|
|
|
### Add a third motor to turn the light sensor
|
|
|
|
|
|
|
|
For this part the goal was to mount a third motor on top of the robot which would then be used to turn the light sensor without having to turn the entire robot. It was very simply to make the light sensor turn instead of the robot and here is the new code segment used in $NewFollow.java$[10]:
|
|
|
|
|
|
|
|
```Java
|
|
|
|
// Stop the car while reading values.
|
|
|
|
car.stop();
|
|
|
|
|
|
|
|
// Get the light to the left
|
|
|
|
rotator.controlMotor(power, MotorPort.FORWARD);
|
|
|
|
Delay.msDelay(rotorMs);
|
|
|
|
leftLight = light.getLightValue();
|
|
|
|
|
|
|
|
// Get the light to the right
|
|
|
|
rotator.controlMotor(power, MotorPort.BACKWARD);
|
|
|
|
Delay.msDelay(rotorMs*2);
|
|
|
|
rightLight = light.getLightValue();
|
|
|
|
|
|
|
|
// Turn back to start position
|
|
|
|
rotator.controlMotor(power, MotorPort.FORWARD);
|
|
|
|
Delay.msDelay(rotorMs);
|
|
|
|
rotator.controlMotor(0, MotorPort.STOP);
|
|
|
|
```
|
|
|
|
|
|
|
|
As seen in the code snippet above we simply turn the motor mounted on top of the robot to measure the left and right light values.
|
|
|
|
|
|
|
|
### The classes SharedCar and Arbiter
|
|
|
|
The SharedCar is a class that allows different threads (e.g. Avoid, Cruise, Follow, Escape) to send commands to the car. The arbiter then goes through all the `SharedCar`'s assigned to a thread and runs their command, if they have one ready.
|
|
|
|
Fred Martin [9], instead, uses a prioritization algorithm for controlling the car. In this method a process is given a priority and contains the left and right motor speed and a enabled or disabled state. The algorithm cycles through the enabled processes and copies the motor speeds from the highest process with the highest priority.
|
|
|
|
|
|
|
|
## Conclusion
|
|
|
|
We have built upon the robot the last lab session [1] and implemented a control-network with an custom `Escape` thread. We have also extended the Follow behaviour with a moving light-sensor to easier capture the surrounding lights. In all this has led to a deeper understanding of the SharedCar and Arbiter classes.
|
|
|
|
|
|
|
|
## References
|
|
|
|
[1], Exercise material lab 6 (http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/Lesson.html)
|
|
|
|
|
|
|
|
[2], Exercise material lab 7 (http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Lesson.html)
|
|
|
|
|
|
|
|
[3], Code: AvoidFigure9_3.java (http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Programs/ AvoidFigure9_3.java)
|
|
|
|
|
|
|
|
[4], Code: AvoidFigure9_3.java modified (https://gitlab.au.dk/lego-group-8/lego/blob/master/lesson7/AvoidFigure9_3.java)
|
|
|
|
|
|
|
|
[5], Video link of Robot backing and turning 180 degree. (https://www.youtube.com/watch?v=lRW77bRqaFs)
|
|
|
|
|
|
|
|
[6], Jones, Flynn, and Seiger, "Mobile Robots, Inspiration to Implementation", Second Edition, 1999. (http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/11128_Mobile _Robots_Inspiration_to_Implementation-Flynn_and_Jones.pdf)
|
|
|
|
|
|
|
|
[7],Code: Escape behavior (https://gitlab.au.dk/lego-group-8/lego/blob/master/lesson7/Escape.java)
|
|
|
|
|
|
|
|
[8], Video of robot with escape + cruise, without avoid + follow to demonstrate escape behavior (https://www.youtube.com/watch?v=Pqq4j9tIe5E)
|
|
|
|
|
|
|
|
[9], Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001.
|
|
|
|
|
|
|
|
[10], Code: NewFollow.java (https://gitlab.au.dk/lego-group-8/lego/blob/master/lesson7/ NewFollow.java) |