Thursday 13 November 2008

NXT Programming, Lesson 9



Data: 14 11 2007
Duration of activity: 3 hours
Group members participating: all group members



1. The Goal

The goal of this lab session is to build and program a robot which is able to navigate in the environment using TachoNavigator, and perhaps experiment a bit.

2. The Plan

  • Build a robot whose construction is suitable for a navigation task [1].

  • Try "Blightbot" [1], which moves between different positions in a Cartesian coordinate system.

  • Discuss how the robot should navigate while avoiding obstacles.

  • Try and evaluate upon the robot's navigational skills while it is using the HiTechnic compass.



3. The results

  • The first thing in this lab session was to rebuild the robot. The idea of the new build-up is for the robot to be able to efficiently turn around on the dime--- that is, without moving forward in any direction. Read more in 3.1. Robot building.

  • Once the robot was built, we could try out how the robot navigates using TachoNavigator. Read more about the implementation and the test in 3.2. Using TachoNavigator.

  • The idea of driving from one coordinate to another seems like little challenge. It may be worth thinking about more complex situations---avoiding obstacles while driving from one point to another. Read our ideas in 3.3. Discussion about obstacles.

  • The last thing in the lab session was to try out navigation using a compass. Although it wasn't suggested to do in the lab description, we were curious if our robot would be able to find the finish point more precisely. Read about this in 3.4. Using compass.


3.1. Robot building

Without too hard thought, we built a robot using instructions from B. Bagnall's book [1]. Now the robot looks like that in the picture of that book. There is just one difference: There is a long pole mounted with a compass, which we used in the last part of the lab session.

This is our robot:


3.2. Using TachoNavigator

The source code for this phase was taken verbatim from B.Bagnall's book [1]. The idea behind the code is very simple: Set up a TachoNavigator and (with goTo()) set the coordinates that the robot has to go to.

There are two very important variables that the TachoNavigator takes as constructor parameters: The tire diameter and track width. These two parameters determine the precision of the robot by a large degree. Concerning tire diameter, we weren't concerned, since it is printed on the rubber of the LEGO tire. However, the track width was a different story: The wheels that were mounted onto the axis weren't too tight, and as a consequence, we could easily move the wheels a bit both inward and outward. It might not seem signficant, but this rattling troubles the precision. The track width measured, in its extremes, could vary from 15.7cm to 16.4cm, which is not preferable. Having this situation in mind, we continuously added rigids during the lab session, so it would be more stable. (Note that this didn't affect the parameters of the system by much, since the strengthening only added weight---it specifically didn't alter the track diameter.)

Up next, the test, which we set up in the way it is described in the book [1]. At first we tried to use coins as markers, but that proved too imprecise, since we only had a 30cm ruler to measure distance. To make things work a little better, we set up a coordinate system on the flour using some kind of paper-tape. This gave us an opportunity to exactly see how precise the robot was.

We have observed the behavior of the robot many times. The thing is that the robot is pretty precise when going from (0,0) to (200,0) and then from(200,0) to (100,100). Later it seemed to be more and more imprecise. And from theory we know that this is because all the littlte errors add up to some major that is called a drift. In the results that a book suggests, the robot comes to the final goal within 30 centimeters. The observations that we had provided us with very similar results.

This is an example that represents couple of our test runs:


3.3. Discussion about obstacles

To avoid obstacles and still navigate, certain proposals could be used:

  • A behavior-based (confer the relevant lab session) approach comes to mind: Two behaviors, one trying to take the robot to the current destination point, another to guide the robot away from any seen obstacles, with the latter overruling the prior.

  • A simple check-for-obstacles back-off

  • Changing the Navigator code to take callback object as parameter, and make the Navigator call the callback in case an obstacle has been seen (as per some metric)

  • Complex algoritms, see below


Whatever one chooses, it must be integrated with the Navigator in such a way that the avoidance algorithm affects the coordinates the Navigator uses for its pathfinding.

3.3.1. Complex algorithms
Given that the coordinate subsystem is in play, it would make sense to use that for obstacle avoidance. This, however, is almost inevitably more intricate than simple ``go away'' algorithms---hence the heading.

This amounts to generating some model of the real world (assumably a two-dimensional one similar to the coordinate system the Navigator uses) and of the obstacles (which could simply be a fixed number of points in the cartesian coordinate system that are known to be inaccessible). The routing algorithm would then have to avoid such trouble spots.

One can argue whether the Navigator is supposed to handle such situations. It essentially could be forced to follow a de-tour in order to get from A to B, and---at present---it is not doing anything but trying its best to follow a straight line, so one could conclude that exactly that is its intended area of responsibility, and obstacle avoidance is outside the responsibilities of Navigator implementations. But that's a software architecture discussion---ironically enough, targeted at a platform that supports very few mechanisms for implementing such.

3.4. Using compass

As in Brian Bagnal[1] we also tried to build the Blighbot with a compass. Instead of using a TachoNavigator, we used a CompassNavigator. The CompassNavigator still takes the wheel diameter and track width as parameters, which shows that the compass only can be used to determine the robots heading, and not e.g. how far it has driven. Using the compass instead of only the tacho-counter should be a drop-in replacement, but we encountered many unforeseen problems.

In Brian Bagnal's example the compass needs to be calibrated. This is done fairly manually with a CompassSensor-object. First the calibration is started with startCalibration(), the robot is then programmed (by us) to turn around two times, and the calibration is stopped with stopCalibration(). Accordingly to the documentation, a CompassNavigator-object should have a more high-lvl calibration method available. The method calibrateCompass() should calibrate automatically, but we couldn't get this method to work. When we tried to use this the robot just stood still.

After we had calibrated the compass, we had hoped we were good to go. But instead our robot started to act weird. Accelerate forward at times, but mostly turn around in-place. To us, in completely random patterns. And we had done minimal changes to our code, so it seemed unlikely the problem were to be found there.

In the Brighbot-tacho version the code for making a navigator looks like this:
TachoNavigator robot = new TachoNavigator(5.6F, 14.1F, Motor.C, Motor.B, false);

and the code for the Brighbot-compass looked like this:

CompassPilot pilot = new CompassPilot(cps, 5.6F, 14.1F, Motor.C, Motor.B, false);
CompassNavigator robot = new CompassNavigator(pilot);


We had a hard time figuring out why the robot all of the sudden wouldn't drive the course. In the end we figured out that the parameters for a TachoNavigator() and CompassNavigator()---allthough virtually the same---have a different understanding of what is the left wheel and what is the right. As soon as we interchanged the wires of the motors our robot started to be able to complete the course. This leads to the hypothesis that the robot stood in-place trying to get its directions, but the algorithm couldn't make sense of its actions: It would try to corrigate in its intended direction, but the readings from the compass only got more off.

After changing the boolean value ``reverse'' in the constructor-call our robot was back on track, with the wires connected as intended:

CompassPilot pilot = new CompassPilot(cps, 5.6F, 14.1F, Motor.C, Motor.B, true);
CompassNavigator robot = new CompassNavigator(pilot);


Now we were at a point where we could start to compare the tacho-counting and the compass versions' performance. Our hypothesis was that the compass version would preform better, because every turn the robot takes doesn't add to the drift. But our results turned out not to be so straight-forward.

We now had the problem that our robot couldn't even follow a straight line. In the first long stretch from (0,0) to (200,0) the robot drifted to the left, but then corrected along the way, before it to ended up at the desired point. Then, in (200,0), where the robot is supposed to turn to the right, the robot turned to the left. The robot ended up completing an inverted version of the course. For some unknown reason, the compass sensor has to be up-side down on the robot, for it not to invert its directions --- but it seems likely that this has to do with the fact that our robot's setup had its problems with inversion, before.

In the end we got the compass sensor up and running, and we were able to produce a better result with the CompassNavigator-class. But it was not a straight-forward conversion.
As a last remark on the compass-sensor, it is also very sensitive to magnetic fields. In its manual, it says the sensor has to be connected at least 15cm aways from the motors. It turned out to be more like 30cm. We instantly got a much better result after extending the antenna of our robot further away from the motors (from around 10-15cm to the position on the images -- about 30cm away). But the motors aren't the only thing emitting a magnetic field. All around us in the Zuse building is possible sources of interference. Power-outlets, laptops and other electronics. At one point we let the robot drive by a power-outlet and when it came close enough, it started to turn, as if confused.

All in all, the compass sensor seems to have a lot of potential, but one needs to remember what the environment of the robot is. A environment can easily be too contaminated by other magnetic fields for the sensor to be reliable.
4. Conclusion

This was a productive lab session. We experimented with tacho-counting-only's precision, and found it to be poor. We also played around with a compass-based approach and found it even more so (because of the flux (pun intended) of the Zuse building's environment).

A compass is a brittle instrument, and it is easily led off course by even minute magnetic interference. This is especially true when driving in a wire-full environment. Also, the robot's own magnetic sources interfere, and meassures (confer the large mast on the robot) must be taken to minimize those.

We didn't get around to implementing any obstacle-avoidance algorithms, but we did discuss them---and the possibilities for implementing them.

References

[1], Brian Bagnall, Maximum Lego NXTBuilding Robots with Java Brains, Chapter 12, Localization, p.285 - p.302

The code we wrote/altered for this lab session


No comments: