Team Six/Final Paper
From Maslab 2007
Contents |
Strategy
Our team name is "Worse is Better", which is a term coined by Richard P. Gabriel in his paper Lisp: Good News, Bad News, How to Win Big. Essentially, it describes a software development philosophy in which implementation simplicity is valued over perfect correctness. We felt that given the time frame of four weeks it was important to limit failure points and to keep our robot's behavior easy to understand. We especially wanted to keep the mechanical design simple since we're math majors who don't know that much about building things.
We set upon building our robot with a simple philosophy: build a simple robust frame, simple modular software, and build several fast easy drafts rather than plan it all out in advance and be locked into a particular design. We would have liked to build a lifting mechanism, which would have allowed for good speed and accuracy of ball delivery. Unfortunately, we were technically unable to build anything robust enough, and settled on a circular robot which collected balls, held them, and finally released tehm, all at the ground level.
Mechanical Design
Ball Capture
Our ball capture mechanism was based on a simple device: the one way gate. We built our robot in two layers – a bottom layer for holding balls and a top layer for holding the computer/orcboard, and other hardware. We cut the bottom layer so as to maximize the number of balls we could hold – in the end, we could hold 7 balls at once. This way, where the goals were placed in the fireld would not be a constraint. We also built the one way gate in a bit of a complicated manner – rather than make the gate a solid slab, we built it as a series of metal pins hanging off of a rod. Each pin could articulate individually, and hence more balls could fit – when a ball entered, only the pins directly touching the ball would move, and so we could utilize what would otherwise be the “swing radius” of the gate as ball holding space.
Ball Release
The gate was one way because a bar sat in front of the pins, slightly below the main bar. Hence the pins could swing inward but not outward. However, to allow the balls to come out when we came to a gate, we had to be able to reverse that. So we attatched a servo to the main rod, as well as a second bar slightly above the main rod. When the robot came to a goal, it would align with the goal. Then the servo would turn, causing the bar above the main rod to come down behind the pins. Hence the pins could now only swing outward but not inward. The robot would back up, let the balls out, and then ram them into the goal. (theoretically.)
Sensors
To sense the world around it, we relied almost exclusively on the camera and five IR sensors. We used encoders on the wheels just to check if we were stuck, and did not use gyros or bump sensors at all. We aimed simply to stay away from walls, and our main navigation relied on using the camera to see open spaces to go to, and then the IR sensors to gently modify the basic direction to smoothly stay as far away from walls as possible. It turned out to be very useful to use two long range IR sensors in addition to the three short range IR sensors we started with – the long range sensors were more useful in overall navigation planning, rather than simply reacting.
Lifting Mechanism
We tried for most of a week to build a lifting mechanism. We started by trying to build a corkscrew mechanism. We got some strong but pliable metal tubing and could build good helices out of it, but failed to solve the problem of how to get balls initially loaded onto the corkscrew. Then we considered a paddle or roller rotating and pushing the balls up a slope, but at that point it seemed easier and more reliable to just leave the balls on the floor, which is what we did.
Software
The software was divided into three main parts: the Robot class, which was responsible for providing a convenient interface to the motors and sensors, the ImageProcessor class, which told the robot what objects were in a given picture, and the RobotState interface, whose implementations interpreted data from the sensors and image processor and told the robot how to act.
Our software used only a single thread because we didn't have a compelling reason to use more. The main loop of the program works as follows. First, the AvoidObstacles function is called, which uses data from the IR sensors and quadrophase encoders to determine whether the robot is stuck and if so controls the robot until it becomes unstuck. The robot then takes a picture and processes it. Finally, it checks whether it should change state (e. g. wandering to tracking ball if it sees a ball) and then performs whatever action is appropriate for that state. Most of our robot's behaviors are adaptive in the sense that they will allow the loop to run as often as possible so that they can use the data to make corrections to the robot's trajectory.
The robot thinks it is stuck if the distance recorded by one of the short range IR sensors is below a certain threshold, the distances recorded by all three short range IR sensors haven't changed significantly in the last second, or the quadrophase encoders have not detected any wheel movement in the last second. Once the robot knows it is stuck, it backs up while steering to the left or the right depending on the distances reported by the left and right IR sensors.
The wandering state uses four different behaviors - DriveForward, FollowGap, LookAround and Spin. Instead of wandering by following walls, we designed our robot to wander by exploring open spaces for various reasons. First of all, if the playing field is not simply connected (i.e. has "holes" in it), and if the robot chooses to follow the wrong wall, it would get stuck in a loop. Secondly, exploring open spaces seemed more efficient and safer (for not getting stuck) than wall following.
When the robot starts in the wandering state, it starts its LookAround behavior in which it spins for x seconds in a random direction, spins for 2x seconds in the opposite direction and so on until a timeout is reached. While scanning the field in this way, it looks for open spaces by calculating the center of mass of the carpet area it sees. If it finds sufficient carpet area in some direction, it identifies it as a gap and tracks the gap (invoking the FollowGap behavior) in the same way as it tracks the balls. If it loses sight of the gap for some reason, it again enters the LookAround behavior to look for gaps. The Spin and DriveForward behaviors help the LookAround and FollowGap behaviors.
Although tracking gaps is implemented in essentially the same way as tracking balls, the FollowGap behavior gives priority to staying away from walls than keeping the center of mass of the carpet in the center of the image to avoid bumping into walls. To achieve this, we add an IR correction of c*(L-R)/(L+R)*sqrt(1/(1+f)) to one of the wheel speeds to steer the robot away from the walls. Here L,R and f are distances from the left, right and front walls and c is a constant. Notice that the correction vanishes if L=R and increases (in magnitude) as the difference L-R increases. Also, it increases as f approaches zero, making the robot turn sharply if it is about to bump into a wall.
The tracking ball state is simple. The robot moves in an arc with curvature proportional to the horizontal displacement of the ball. We found that the robot would sometimes see a ball while wandering and then lose track of it before it had a chance to stop wandering, so we made the robot slow down and reverse direction when this happens. If it does not see the ball again within a few seconds, then it gives up. If the ball is low enough in the image, then the robot drives straight forward a second (it calls sleep so that AvoidObstacles or another state won't override the behavior) and assumes it caught the ball.
When tracking the goal, the robot needs not only to have the goal in the center of its field of vision but also to be facing perpendicular to the goal. The robot therefore tries to make it so that the horizontal displacement of the center of the goal equals a constant factor times the slope of the bottom of the goal. We chose the bottom rather than the top because the height of the camera is closer to the height of the top of the goal than the height of the bottom, so the slope at the bottom is larger. If the robot does not see both the left and right side of the goal, then it attempts to turn so that it will. When the top of the goal is above a certain height in the image, the robot decides to ram the balls.
When ramming balls, the robot first comes closer to the goal. We try to make it so that the wheels continue spinning for a little while after the robot hits the wall so that it becomes more perpendicular to the goal. Once it stops, the one way gate is reversed, and the robot backs up and drives forward again to push the balls into the goal. Once the ramming procedure starts, it does not return execution flow to the main loop until it ends, so AvoidObstacles cannot interrupt it.
We save all of the images captured by the camera to disk. We also save a log file that contains data from the other sensors, the list of objects found by the image processor, and information about the robot's state. We created a C++ program called RobotReplay that plays video of what the robot saw. When the video is paused, the program also displays the log file data from that frame.
Results
Our robot didn't do quite as well in the competition as we had hoped. It got stuck in a place where the maze narrowed and eventually went back the way it came. At the end of the run, it got stuck in the same place again. As a result, our robot only saw three balls. It also had a problem with docking with the goal. It approached the goal more or less straight on, but when it backed up the motors didn't quite start at the same time and the alignment ended up being off. None of the balls ended up in the goal. Since they weren't in the goal, the robot tried picking them up again, thought it succeeded, and tried ramming again. The robot finally left the goal area with two of the three balls on the porch and none on the goal.
Although our robot could have done better, we are glad that everything worked at least some of the time.
Advice for Future Teams
We didn't get to test the robot as much as we would have liked. It would have been beneficial if we had a fully functional robot by the beginning of the final week.
Temporarily securing things with tape isn't a very good idea. The tape fails often and it gets annoying having to re-tape everything again and again.
It can sometimes be useful to have GNU screen installed on your robot (apt-get install screen).

