Date: 03 10 2008
Duration of activity: 3 hours
Group members participating: all group members
1. The Goal
The goal of this lesson is to build a line follower again, and this time, make the robot recognize three different colors: White, black and blue. The idea is that the robot has to follow a black line until it reaches a blue rectangular place (the finish area) where it has to stop.
2. The Plan
- Build a robot that is able to follow a line and mount it with a light sensor
- Take the readings of the light sensor while detecting white, black and blue
- Make the robot follow the line
- Try calibrating thresholds before the run
- Make the robot stop at the finish square
3. The Results
- Firstly, Thomas was rebuilt to be a line follower robot. Our group decided not to follow the approach of a three wheeled robot, instead, we used a sliding approach from www.nxtprograms.com/line_follower. Read more in 3.1. The construction of the robot
- Secondly, as the robot was ready, we wanted to see the exact readings we were dealing with. It was necessary to distinguish precisely between white, black and blue. Read more in 3.2. The readings of the sensor
- Thirdly, the hardest part of our work: Code writing. To make the code work reasonably, we had to ask ourselves many questions: Is it important to calibrate or is it enough to hardwire the thresholds? How should we make the comparison with the thresholds and how precise intervals should we use? And many other such questions. Read more in 3.3. Code writing.
3.1. The construction of the robot
As already mentioned, the robot we constructed is based on sliding on its back skids instead of having a third wheel. This approach seemed more reasonable: When using a third wheel, at each turn, some power had to be given away to the third wheel to change its heading, which also has as impact on the timeliness of corrective actions.
The idea is to place as much weight as possible on top of the drive wheels, and just enough weight over the sliding part to keep the robot stable and avoid tipping over. If there is too much over the sliding part, the robot would struggle to turn, and if not enough, the robot would be too jumpy and might fall on its back.
Having all that in mind, here is new sliding Thomas:
As one might notice, our Thomas has bigger wheels than the one from the example referenced above. There is a big reason for that: We have made some experiments with this robot. On the given track in the Zuse building, the version of this robot with smaller and thicker wheels it takes 1 minute to go around the track. With big wheels (the ones in the picture) it 13 seconds less to go around (47 seconds). That is a big improvement. In conjunction with this experiment, we tried to push mass center a bit away from the sliding part, but that didn't give any improvement but made the robot a bit jumpy.
For future improvements, Thomas was mounted with two more light sensors. These two were mounted on each side. The purpose is for the robot to be able to "see" a broader spectrum of the environment:
We haven't made any use of these, as of yet, but a seemingly effective approach is to use the sensor which lastly saw the line as an indication of which way to go to get back on track.
3.2. The readings of the sensor
There is one of the snapshots of the light sensor readings. The values correspond to white, blue and black. As it can be seen, blue and black color ranges actually are relatively close to each other.
3.3. Code writing
The code for this instance took its start from the suggested code in LineFollowerCal.java. That code is limited by its inability to determine whether it's over the blue goal area (it uses a BlackWhiteSensor), and by its lack of precision -- it's using the
readValue()method on LightSensor, rather than its
readNormalizedValue()method, which emits data with the whole 10-bit spectrum as range.
For our work, LineFollowerCal was forked into LineFollower and BlackWhiteSensor was forked into ColorSensor.
In ColorSensor, the value read is compared with three values: A lower bound for the predicate
white, an upper bound for the predicate
black, and a (midpoint,radius) pair for
blue. This latter requirement stems from the fact that the empirically established values for blue showed that blue lies well away from the mean of black and white (confer with the plot). It thus needs to be established in another way as the naïve if-it's-neither-black-nor-white-it-must-be-blue approach.
This also means that our ColorSensor does not satisfy the invariant that at least one of
A lot of work from thereon concentrated on getting the code to work. In one way or another. Foremost, there was a (very) annoying issue with a
Another issue -- which still stands unresolved -- is the speed at which motor speeds propagate. It is as if we make multiple corrective measures (that is, multiple runs of the main while loop), and only one of them will have effect on the motor speeds. Or the actual PWM values to the motors are only set in a deferred manner.
3.3.1 Power-saving blinking floodlight
In an attempt to be clever, the floodlight was turned on immediately before use, the sensor read, and the floodlight turned off again. This is a basic method of conserving battery power. And it's a method that had worked for the programmer before. But -- and this is the insight -- the lejos firmware is rumored to not do what it's supposed to do: It polls the sensorports every 3 milliseconds (for some value of 3), and non-blockingly returns the most recently read value, when a measurement is requested. This of course is in conflict with our blinking the floodlight.
3.3.2 Accuracy-enhancing blinking floodlight
Another perhaps worthwhile idea is that of blinking the floodlight in a clever way:
- Turn off the floodlight
- Read value v1
- Turn on the floodlight
- Read value v2
- Turn off the floodlight
- Return (v2-v1)
This expresses the way that a recent value (v1) for the ambient lighting is subtracted from the ambient-and-reflective read value (v2) in an effort to isolate the reflection component.
This approach is not possible with the current platform (without excessive waiting, or hacking of lejos -- since there's this each-3-milliseconds polling). But we didn't explore this because we decided that the environment that the robot would race in was very statical and controllable. This is in spite of LED's (as the floodlight is based on) are almost immediate in their switching.
We only did a minimal implementation of the exercise (and we've given up hopes of medals). Our best time yet is 43 seconds, with a bang-bang control program.
The code writing again proved the most difficult part to surmount. It's still annoyingly sequential work -- only one group member can program the device, and the others can only watch. If one changes the physical characteristics of the robot, the programming (or at least, the tuned parameters) go down the drain.