Team Eight/Paper
From Maslab 2006
| Maslab teams |
|---|
| Team 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 · 11 · 12 · 13 · 15 |
| Team Eight's Journal · Paper |
The Good, the Bad, and the Straight-up Cool Things About Team DLB and "Unknown Orientation"
Maslab Robotics Competition Final Paper
IAP 2006
Contents |
Our Team
Team 8, AKA "The DLB," is a team whose members come from varying backgrounds, both in major and robotics experience. Sean Torrez, a Junior in Course 16, took Maslab for the second time this year. His experiences from last year proved invaluable to the team. Jayant Krishnamurthy, a Sophomore in Course 6, took part in several robotics competitions in high school, giving more valuable experience to the team. Jonathan Grimm (that's me!), a Junior in Course 6, was the only team member without robotics experience, but having taken 6.170 and other Course 6 classes hopefully lent some organizational help to the team. As a team, we came into Maslab with, perhaps, a slightly different goal than many other teams. Though we certainly wanted to win the competition, we wanted to do it the "right way." We did not want to throw together a poorly designed and poorly constructed robot, and then have that robot run a random walking routine to hopefully knock some balls into a goal. On the mechanical side we wanted to build a solid, well-designed robot that would help us implement a winning strategy while hopefully taking away some coding complexity introduced by bad design choices (i.e. square robots, completely passive ball collection mechanisms). On the software side, we wanted to build a robot that actually knew what it was doing. We wanted to have an intelligent robot that could make good decisions based on a large amount of accurate data. These philosophies led us to the strategies we implemented, or intended to implement, for our Maslab robot "Unknown Orientation."
Our Mechanical Strategy
We kept the same design throughout, having come up with it at the beginning of Maslab. Our major goals with the design we chose were to avoid becoming stuck, since it can be very time-consuming to get unstuck, and to have precision and repreatability in collecting balls. We wanted a very precise robot. To this end, we made it round, so that it had no sharp edges, and three-wheeled, so that it was not possible for the robot to achieve a position from which it could not escape.
Mechanical Design and Sensors
I felt that the robot should be stiff and durable, because I knew that it was likely to have many collisions with the walls during the testing and contest. I also knew that I was going to be making a lot of holes in the baseplate of the robot, since we wanted to go with a single-level design. For these two reasons, I made the main baseplate of the robot out of Aluminum. It did, indeed make things easier to machine, especially because in our robot, many tolerances needed to be very precise for things to work. The only reason I regret using Aluminum is that it gave us motor difficulties, because our motors were grounded to their cases. I think Aluminum is, in general, a very good material to work with. The arm in particular was difficult and precise, but very rewarding to work on. I spent a great deal of time with the linear bearings making sure they fit just right and were at the exact right height for the arm to perform. This involved milling them to the exact same sizes, cutting a precision mounting platform for them, aligning them perfectly (for this I used paper shims--the thickness of a piece of paper is less than .005"). I modified a standard servo by replacing the potentiometer inside, which is a three-quarter turn type, with a ten-turn precision wire-wound potentiometer. This required modification to the case of the servo, to fit the bigger pot, and modification to the pot, so that it fit into the small servo gears properly. This worked quite well, and we were able to make the arm move through very precise distances, linearly. I also spent a great deal of time on the camera, which was mounted on a servo and geared up so that it was able to turn in a full circle. It was very difficult to get the servo to turn without binding, because the tolerances necessary in the axle turned out to be very tight. I tried first just putting a long bolt through concentric holes on the mount, but the threads of the steel bolt caught on the Aluminum mount. Then I tried concentric brass sleeves, which worked better. I soon learned, however, that in a sleeve fit, the materials must be dissinilar for a low-friction fit, and this also proved to be unacceptable. Finally, I broke down and used a bearing block to fit the bolt through. This provided very smooth and easy rotation. I wish I had done that first thing, instead of trying to do things the quick and dirty way.
Our Software Strategy
The strategy we intended to follow on contest day was very different from the one we actually used. A day before the robots were impounded, we had to make the very difficult decision that our advanced and ambitious mapping plan would not be completed in time. We had to then switch to a much simplified plan that we were able to implement in time for the contest. This strategy ended up working surprisingly well for being implemented in the final hours of the class.
Mapping
First I will describe the strategy we proposed at the beginning of the month and worked on for most of Maslab. Though this strategy was not actually used, it is much more interesting and also could be used as a building block for future teams. As a result of the changed rules for this year’s contest, we believed that mapping was the winning strategy for Maslab, even more so than in the past. The ability to accurately remember goal positions would help a team split up the balls it collected and so score more points per ball than otherwise. We decided to create a full metrical map of the playing field, including balls, goals, barcodes, and walls. This was a very ambitious plan, but had it worked our team would have had a large advantage over non-mapping teams. The “map” itself was built of two main structures. First we had a list of all the objects in the field. These objects contained different kinds of information based on their object type, but they all contained their absolute position on the field. Absolute, in this case, was an x-y coordinate system based on the robots original position and orientation. The second main piece of the map was a two-dimensional array (actually implemented as an image object) containing data about occupancy of different areas of the robot world. The absolute position of an object corresponded to its position in this image. The image format was chosen because it was a convenient way to store occupancy information, but also because it was then immediately available for viewing by us as we were developing the software, allowing us to see both problems and progress quickly. All our strategy was based on this map. When we would need to get to a certain location, we would use the map image to find a path around any objects in the way using an implementation of the A* search. This ability would have been very useful when returning to a goal with balls and especially useful when trying to score the power ball in the power goal. Of course, none of this is useful if the map is not accurate or duplicate objects are created. To help with this problem, we used a Kalman filter. Walls, goals, and barcodes were added to the filter. We chose not to add balls as they were very mobile objects and duplicate objects could easily be created if we bumped a ball accidentally. This filter helped us to maintain ellipses of location uncertainty around the field objects. Finding accurate locations of objects is discussed more in the vision section. Unfortunately, we were not able to complete this mapping goal. By my best estimation we had 90% of the accuracy we needed to produce a realistic strategy based on map information. That last 10% would have been difficult to achieve, as at that point we would have had to refine significantly our distance estimation algorithms. As is discussed in the vision section, walls were particularly problematic for us. Not only were the end points and corners difficult to find, but it was also difficult to try to merge walls from different images into the single wall they physically were. As a result of this, we often had gaps in our maps that caused bad results to be produced.
Non-mapping strategy
On contest day, we used a strategy very different from the one described above. Without a working map upon which to base our movements, a day before the contest we did not even have a good wandering routine. Our last-minute challenge to ourselves was to create a very simple wandering and scoring strategy that could be implemented in only hours. To deal with this challenge, we turned to one of the strong points of our robot - it’s odometry. Our use of an optical mouse had made our robot able to very accurately keep track of its current position. So, we decided to leave a trail of “breadcrumbs” behind our robot as it moved. The breadcrumbs were dropped whenever the robot was exploring. These markers would help us wander by forcing us to move into areas we had not yet been. We implemented this by computing the vector sum of all the vectors from the markers to the robot, with the vector magnitude being a function of the distance of the marker from the robot. The robot would go in the direction of this resultant vector, which was the direction towards the least traveled-in location. This strategy worked very well at the competition. Our robot was able to explore more of the playing field than most of the others, despite being a product of only a few hours work. We would recommend a refined version of this approach to anyone who does not want to implement a full map
Vision
We initially approached vision in much the same way as presented in the image processing tutorial: we used a set of thresholds to identify colored blobs in the image. We also wrote a simple class that used some basic trigonometry to convert pixel locations in an image into actual physical locations with respect to the robot. As it turns out, however, we weren't able to identify the locations of walls, nor were we able to find the other objects accurately enough with our blob-based strategy to make a reliable map from them, so we decided to research and pursue other methods of detecting objects in images. After searching the Internet and reading several articles on edge detection and Hough transforms, we decided to give them a shot. We implemented the Sobel edge detection algorithm, which seemed simple yet robust enough for our purposes. The Sobel algorithm is based on a very simple principle: edges are locations in an image where colors change very rapidly. Therefore, you should be able to find edges by taking the derivative (or gradient, in the case of a non-grayscale image) with respect to color of each pixel in the image, and thresholding that value. This was fairly simple to implement, all we had to do was use a matrix mask to approximate the value of the gradient at each pixel in the image, then test it a few times to come up with a good threshold value. While this worked well, it had a hard time dealing with the carpet and would often find imaginary edges in the carpet. Our next edge filter was a Canny edge filter, which is based on the same principle as the Sobel edge filter, except with a few more advanced tricks. Initially, the Canny filter uses a Gaussian blur to smooth away noise from the image. The Canny edge filter then uses two thresholds to determine if a pixel is an edge or not. It searches the gradients of the all pixels for local maxima and thresholds those against the higher of the two thresholds to determine whether or not they correspond to an edge. It then marks any pixel above the lower threshold value as an edge if there is a path (an edge) between the current pixel and a local maxima. This hysteresis between the two threshold values allows the Canny edge filter to find smooth, continuous edges where the Sobel filter would find a series discontinuous points. We found an implementation of this on the Internet and used it as we had already wasted a lot of time implementing the Sobel algorithm, and didn't want to do so again. The Canny algorithm worked extremely well for us, and we decided to use it for all our image processing. One of the major reasons why we went through all this trouble was we couldn't come up with a good way of detecting walls in our images. The carpet appears to be about the same color to the computer, and thus we were unable to use color thresholds to identify them. Both edge detection algorithms could find the edge between the wall and the carpet, but we still needed a way to relate the set of edge points to the dominant lines in an image. We were able to accomplish this by using a Hough transform and searching the set of returned lines for lines that intersected close to the center of the image (the horizon). Using all of these methods, we were able to detect the locations of objects with a fair degree of accuracy, yet we unfortunately ran out of time to integrate all of this information into a coherent map. For the final competition, we searched for red balls by finding the edges in an image, then searching for red pixels and using the edges close to the red areas in an image to determine the location of the ball. We also searched for goals by using a simple yellow blob method.
Contest Day
On the day of the competition, we had a big problem. As soon as we were allowed into 26-100, we checked our color thresholds to make sure they would work under the different lighting conditions. Construction delays and a lack of foresight caused us to not have good thresholds for 26-100. We discovered our thresholds were not working under the current conditions. After trying to calculate them for a few minutes, we realized we would not finish in time. At that time, we asked another team for their thresholds, and, very graciously, that team did give them to us (Thank you team 3!). We put the new thresholds into our MaslabColor class and recompiled it directly on the robot. We lacked the time to test these thresholds and so we simply had to hope they would work. They did not. Throughout the entire round, our robot did not recognize a single ball or goal. It was very frustrating to watch our robot wander past these objects without taking notice. After the competition, we tried outputting all of the images our robot took to BotClient, hoping to manually calibrate the thresholds from the image data for an exhibition round. We went through the same routine of editing and compiling the code on the robot itself. When we ran our program again, these images were not published to BotClient. This in and of itself is not important, but it might point to the problem with our color thresholds. It is possible that we did not correctly compile the new versions of either of these classes and that the robot was using the old version, including our old thresholds. This would explain why the team that gave us the new thresholds seemed to get good results from them, while we could not recognize anything. Sadly, our robot did not perform as we would have liked on the day of the competition. All of us wish we could have had just a couple more days to implement our map, or even just a few more minutes to correctly form our color thresholds. However, this did not happen and we have to accept the results. To anyone reading this in a future Maslab class, be sure to obtain and test 26-100 color thresholds before the day of the contest.
Lessons learned
After working exhausting hours over the last month (~300), we certainly have not come away from the Maslab competition without learning a few things. At this point, our turn is over, but hopefully we can pass on a few lessons to future Maslabbers and help them avoid some of the errors we committed.
Do's
•The three wheeled robot design was an excellent idea, as it made it virtually impossible for us to get stuck on an obstacle, plus it was fairly simple to get working. •The vision algorithms that we were using were robust and worked well. Despite being rather slow (a problem we dealt with by creating “fast” and “slow” image processing modes), they are definitely accurate enough to be used to create a map. They are also really nifty and fun to implement, definitely recommended for any team using the camera to map. •The optical mouse we used for our odometry was accurate and easy to implement. It avoided all of the problems of optical encoders (i.e. wheel slippage), and since it directly returned x/y translation of the robot, it was nice to work with.
Don'ts
•The claw was a poor choice of ball possession mechanisms. It was designed to avoid the problems of most passive systems, namely not knowing how many balls you have and the very real possibility of getting jammed. Despite all that, our claw had a margin of error that was too small to be reliable. We think that a large arm that rotated down from the top of the robot and swept balls into a containment area might be a better design. •We happened to make a really stupid choice of coordinate systems for our robot which lead to a lot of random programming bugs. Basically, we decided that the arm would be along the Y-axis of the robot, and angles would be measured from that axis in the clockwise direction in degrees. Instead, we should have stuck with something more traditional and mathematically consistent with Java's built in trigonometry functions (basically the exact opposite of what we specified). •A full metrical map wasn't exactly a bad idea, but it was a stretch considering all of our other goals, especially our radical robot design. Mapping takes a lot of work and a lot of debugging. Since we were unable to test out a lot of our software until the very end of the month, we were unable to get it working, however with some more time it would have been possible. (I maintain that a full metrical map is the only way to build a robot that can play the game intelligently.)
