|
|
# Group 8
|
|
|
|
|
|
|
|
|
## Lab Notebook 6
|
|
|
|
|
|
|
|
|
**Date:** 14/4 - 2015
|
|
|
|
|
|
|
|
|
**Duration:** 8-12 hours
|
|
|
|
|
|
|
|
|
**Participants:**
|
|
|
|
|
|
|
|
|
- Frederik Jerløv
|
|
|
- Casper Christensen
|
|
|
- Mark Sejr Gottenborg
|
|
|
- Peder Detlefsen
|
|
|
|
|
|
|
|
|
## Goal
|
|
|
The goal is to build and program Braitenberg vehicles while executing the exercises.[1]
|
|
|
|
|
|
|
|
|
## Plan
|
|
|
Our plan is to follow the exercises exactly as described, testing the the different build descriptions, with different settings and external influences.
|
|
|
|
|
|
|
|
|
## Results
|
|
|
|
|
|
|
|
|
### Vehicle 1
|
|
|
|
|
|
|
|
|
We came up with the function $f(x) = 100 / ((100 / 1023) * x$ to map the motor speed based on the raw sensor input from the sound sensor. We used the SensorPort Java-class to read the raw value of the sound sound sensor.
|
|
|
|
|
|
|
|
|
| Sound sensor reading | f(x) = 100 - ((100 / 1023) * x |
|
|
|
|----------------------|----------------------------------|
|
|
|
| 1023 | 0 |
|
... | ... | @@ -32,8 +43,11 @@ We came up with the function $f(x) = 100 / ((100 / 1023) * x$ to map the motor s |
|
|
| 0 | 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The next step was to make a function for both back and forward. The g(x) should return values between -100 and 100. This is easily achieved by multiplying the second part of the original function with two. $g(x) = 100 - (((100 / 1023) * x) * 2)$.
|
|
|
|
|
|
|
|
|
| Sound sensor reading | g(x) = 100 - (((100 / 1023) * x) * 2 |
|
|
|
|----------------------|--------------------------------------|
|
|
|
| 1023 | -100 |
|
... | ... | @@ -43,106 +57,139 @@ The next step was to make a function for both back and forward. The g(x) should |
|
|
| 0 | 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Here you see the two functions Figure 1:
|
|
|
|
|
|
|
|
|
![The x axis is raw value from the light sensor. The y-axis is power output.](http://i.imgur.com/2EEUBXv.png)
|
|
|
|
|
|
|
|
|
Below is the code used[2]:
|
|
|
```Java
|
|
|
while(true) {
|
|
|
raw = port.readRawValue();
|
|
|
// Map 0 to 100
|
|
|
// power = 100.0 - ((100.0 / 1023.0) * raw);
|
|
|
// Map -100 to 100
|
|
|
power = 100.0 - ((100.0 / 1023.0) * raw) * 2;
|
|
|
motorLeft.controlMotor((int)power, MotorPort.FORWARD);
|
|
|
motorRight.controlMotor((int)power, MotorPort.FORWARD);
|
|
|
// Map 0 to 100
|
|
|
// power = 100.0 - ((100.0 / 1023.0) * raw);
|
|
|
// Map -100 to 100
|
|
|
power = 100.0 - ((100.0 / 1023.0) * raw) * 2;
|
|
|
motorLeft.controlMotor((int)power, MotorPort.FORWARD);
|
|
|
motorRight.controlMotor((int)power, MotorPort.FORWARD);
|
|
|
}
|
|
|
```
|
|
|
The first function made the robot move forward when it heard a loud sound. This was easly seen by whistling or blowing on the microphone.
|
|
|
The second function made the the robot also move backwards. This resulted in the robot backing up until it heard a sound. With the right distance to a mobile phone playing music the robot would seem to dance to the music.
|
|
|
|
|
|
|
|
|
### Vehicle 2
|
|
|
## 2a
|
|
|
In this exercise we added two light sensor in front of our vehicle. See Figure 2.
|
|
|
|
|
|
|
|
|
![Vehicle 2a/2b with two light sensors in front.](http://i.imgur.com/WH3mhbIl.jpg)
|
|
|
|
|
|
|
|
|
Here’s how we calculated the left and right power levels in Vehicle 2[3]:
|
|
|
```Java
|
|
|
rawLeft = portLeft.readNormalizedValue() - 139;
|
|
|
rawLeft = portLeft.readNormalizedValue() - 139;
|
|
|
rawRight = portRight.readNormalizedValue() - 139;
|
|
|
powerLeft = 50.0 - ((50.0 / 745.0) * rawLeft) * 2;
|
|
|
powerRight = 50.0 - ((50.0 / 745.0) * rawRight) * 2;
|
|
|
powerLeft = (powerLeft < 0) ? powerLeft - 50 : powerLeft + 50;
|
|
|
powerRight = (powerRight < 0) ? powerRight - 50 : powerRight + 50;
|
|
|
```
|
|
|
powerLeft = 50.0 - ((50.0 / 745.0) * rawLeft) * 2;
|
|
|
powerRight = 50.0 - ((50.0 / 745.0) * rawRight) * 2;
|
|
|
powerLeft = (powerLeft < 0) ? powerLeft - 50 : powerLeft + 50;
|
|
|
powerRight = (powerRight < 0) ? powerRight - 50 : powerRight + 50;
|
|
|
```
|
|
|
|
|
|
|
|
|
The light sensor returns a raw value between 0 and 1023 but from the documentation we noticed that $readNormalizedValue()$ normally returns values between 145 and 890. Because of this we only have a span of 745 values and when we exploited this fact we could make the robot reach all available power levels. However, when using two sensors our robot would no longer move with a power below 50, which is why we increase or decrease the power by 50 after the initial calculation.
|
|
|
|
|
|
|
|
|
The light sensor returns a raw value between 0 and 1023 but from the documentation we noticed that $readNormalizedValue()$ normally returns values between 145 and 890. Because of this we only have a span of 745 values and when we exploited this fact we could make the robot reach all available power levels. However, when using two sensors our robot would no longer move with a power below 50, which is why we increase or decrease the power by 50 after the initial calculation.
|
|
|
Below is a link to a video of the vehicle in action. It shows how Vehicle 2a avoids darkness by speeding up the left (right) motor if the left (right) sensor sees darkness.
|
|
|
|
|
|
Below is a link to a video of the vehicle in action. It shows how Vehicle 2a avoids darkness by speeding up the left (right) motor if the left (right) sensor sees darkness.
|
|
|
|
|
|
[Demonstration of vehicle 2a with two light sensors that avoids darkness.[6]](http://1drv.ms/1ymWXWU)
|
|
|
[Demonstration of vehicle 2a with two light sensors that avoids darkness.[6]](http://1drv.ms/1ymWXWU)
|
|
|
|
|
|
|
|
|
## 2b
|
|
|
In this exercise we tried using the setup 2b where the sensor and motors were cross connected. The code is exactly like in 2a. The only difference is that the two sensor input ports were changed in the code.
|
|
|
|
|
|
|
|
|
This gave a different behavior. So when the right sensor registered dark it would increase the motor power on the left motor instead of the right motor. This made it drive faster into the dark. This is also what is shown on the video.
|
|
|
|
|
|
|
|
|
Below is a link to a video of the vehicle in action:
|
|
|
|
|
|
|
|
|
[Demonstration of vehicle 2b with two light sensors that goes towards darkness.[7]](http://1drv.ms/1ymWvbc)
|
|
|
|
|
|
|
|
|
We were not able to put a lamp on top of the robot and try make it follow put it in a dark room with other robots.
|
|
|
|
|
|
|
|
|
## 2c
|
|
|
From the video[4] it seems like the vehicle drive way too fast to be able to turn in time. So we tried implement our own attempt to avoid obstacles using vehicle 2b and inhibitory setup. This means the closer we get to the wall (lower value read) we slower the opposite motor in order to turn. We used a similar looking robot like the one Braitenberg used. On Figure 3 we see a picture of our vehicle.
|
|
|
|
|
|
|
|
|
![Vehicle 2c with two ultrasonic sensors placed wide apart in front.](http://i.imgur.com/vIJ1h3al.jpg)
|
|
|
|
|
|
|
|
|
We created a new mapping using the ultrasonic sensor to a speed. The way we did this was that we decided that it should go from 0 to 100 in speed and 20 to 100 in cm (given by ultrasonic sensor). This means that if we are far away from an obstacle we run fast and if we are close we run slow. From the two end point we created an aprox function to calculate this mapping. The function looks like $speed(x) = 0.625 * x + 37.5$ where $x$ is in cm read from the ultrasonic sensor.
|
|
|
|
|
|
|
|
|
Below is the code used[5]
|
|
|
|
|
|
|
|
|
Below is a link to a video of our implementation of a vehicle that tries to avoid obstacles.
|
|
|
|
|
|
|
|
|
[Braitenberg vehicles 2 with two
|
|
|
ultrasonic sensors[4]](https://www.youtube.com/watch?v=WxUY4RnAbAM)
|
|
|
|
|
|
|
|
|
### Vehicle 3
|
|
|
In this exercise we tried using two ultrasonic sensors together with two sound sensors. The setup of the vehicle can be seen on Figure 4.
|
|
|
|
|
|
|
|
|
![Vehicle 3 with two ultrasonic sensors and two sound sensors.](http://i.imgur.com/OEhTnE5l.jpg)
|
|
|
|
|
|
|
|
|
The goal was to make the robot avoid obstacles while also turning towards a nearby sound source. To do this we made two very simple equations to first map the distance to motor power and then add the mapping of sound values to motor power. Distance is measured from 0 to 255 but to make the power scale more quickly we used 100 as a max distance. There was no obvious way to making the sound value interval smaller without modifying the values a lot so we just used the entire range from 0 to 1023. As a result of such a big interval our robot was very unresponsive towards the sound source as the difference in power levels was never large enough to actually make the robot turn towards the sound. Below are the code the determines the power levels for each motor. We used a minimum power of 50 and let obstacles and sound increase it by up to 25 each.
|
|
|
|
|
|
|
|
|
```Java
|
|
|
rawDistanceLeft = Math.min(100, portLeft.getDistance());
|
|
|
rawDistanceRight = Math.min(100, portRight.getDistance());
|
|
|
rawDistanceRight = Math.min(100, portRight.getDistance());
|
|
|
rawSoundLeft = soundLeft.readRawValue();
|
|
|
rawSoundRight = soundRight.readRawValue();
|
|
|
rawSoundRight = soundRight.readRawValue();
|
|
|
|
|
|
powerLeft = 25 + (25.0 / 100.0) * (double)rawDistanceRight;
|
|
|
powerRight = 25 + (25.0 / 100.0) * (double)rawDistanceLeft;
|
|
|
|
|
|
powerLeft = 25 + (25.0 / 100.0) * (double)rawDistanceRight;
|
|
|
powerRight = 25 + (25.0 / 100.0) * (double)rawDistanceLeft;
|
|
|
|
|
|
powerLeft += 25 + (25.0 / 1023.0) * (double)rawSoundLeft;
|
|
|
powerRight += 25 + (25.0 / 1023.0) * (double)rawSoundRight;
|
|
|
```
|
|
|
powerLeft += 25 + (25.0 / 1023.0) * (double)rawSoundLeft;
|
|
|
powerRight += 25 + (25.0 / 1023.0) * (double)rawSoundRight;
|
|
|
```
|
|
|
|
|
|
|
|
|
## Conclusion
|
|
|
We have implemented, explored and come to understand the three different Braitenberg vehicles. During our experiments we found that mapping readings directly to the power levels of the motors will not give the best possible behaviour as that would require customized control of the robot.
|
|
|
|
|
|
|
|
|
## References
|
|
|
[1], [Exercise material](http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/Lesson.html)
|
|
|
|
|
|
|
|
|
[2], [Code Vehicle 1](https://gitlab.au.dk/lego-group-8/lego/blob/master/lesson6/Vehicle1.java)
|
|
|
|
|
|
|
|
|
[3], [Code Vehicle 2a](https://gitlab.au.dk/lego-group-8/lego/blob/master/lesson6/Vehicle2a.java)
|
|
|
|
|
|
|
|
|
[4], [Video - Vehículo de Braitenberg Sensores Ultrasónicos](https://www.youtube.com/watch?v=fMIJ_Qhzg_8)
|
|
|
|
|
|
|
|
|
[5], [Code Vehicle 2c](https://gitlab.au.dk/lego-group-8/lego/blob/master/lesson6/Vehicle2c.java)
|
|
|
|
|
|
|
|
|
[6], [Demonstration of vehicle 2a with two light sensors that avoids darkness.](http://1drv.ms/1ymWXWU)
|
|
|
|
|
|
[7], [Demonstration of vehicle 2b with two light sensors that goes towards darkness.](http://1drv.ms/1ymWvbc) |
|
|
|
|
|
[7], [Demonstration of vehicle 2b with two light sensors that goes towards darkness.](http://1drv.ms/1ymWvbc) |
|
|
\ No newline at end of file |