For this assignment, we were told to build a robot that can sense an obstacle in front of it and stop to avoid collision. The robot should be able to do this through normal drive and through proportional control. Finally, bonus points would be awarded for a robot that could reverse away from the wall if it was too close.
To accomplish the objectives above, we first constructed the physical robot. Using only the Lego kit provided, we built a semi-sturdy robot which moved on tank-treads driven by two motor modules. The distance from potential obstacles was sensed using an ultrasonic range finder, mounted on the forward face of the robot, approximately 2 inches above the ground.
We encountered some problems constructing a sturdy robot as the weight of the CPU tended to cause the middle of the robot to sag. This would not have been much of a problem if it had not caused the treads to become misaligned, driving the robot off course. We remedied the problem with a few extra linkages connecting the motors to the CPU in a second location. Our robot is now quite sturdy!
The programming of the robot was quite simple, and came in two different flavors. The simpler version drives the motors forward at a constant speed, 75% of their full drive capability, until the robot comes within a certain distance of the wall. The more complex code incorporates a proportional controller, which slows the robot’s forward motion as it gets closer to the obstacle.
Normal Drive Code:
Proportional Controller Drive Code:
Both versions begin by obtaining a distance reading from the ultrasonic range finder and storing this value in a variable called Distance. The values recorded to Distance did not appear to be of any known unit of length, rather some unscaled sensor output that ranged from 0 to 25.5. Through trial and error, we determined a good Distance value at which to stop the robot would be between 4 and 6, which corresponded to between 1 and 2 feet away from an obstacle.
Once a value was recorded to Distance, that value was passed to an if statement, which evaluated whether the robot was too close to continue. If Distance was less than 4, the Robot would not only stop moving forwards, but reverse direction to back away from the wall. An Else If ruled that if Distance was between 4 and 6, the robot would stop moving entirely. Finally, if Distance was greater than 6, the robot continued moving with a speed of MotorSpeed.
MotorSpeed is where the two flavors of robot code diverged. In the simpler code, MotorSpeed was always set to 75% of the highest possible speed, while in the proportional control code, it was a function of the distance from the object. This was accomplished by setting MotorSpeed equal to Distance times a constant. The constant (4) was a value that could scale the limited range of Distance to output all the way from 0 to 100 (or 0 to 1050) to drive the motors. Finally, in order to ensure no out of bounds values were passed to MotorSpeed, it was constrained to between 0-100 (later changed to 0-50 for testing in a small room).
All this code ran endlessly in a never-ending while loop.
In testing, both versions of robot programming were able to stop the robot at the correct distance from the wall, and reverse accordingly if the robot was placed intentionally too close. The proportional controller steadily slows the robot to a crawl as it gets closer and closer to its stopping threshold. The robot does still tend to veer slightly off of a straight line when driving, though we feel this is likely due to shaking the robot experiences at what appears to be a resonant frequency at some low speeds. This could probably be corrected by building a robot with a lower center of mass and shorter linkages connecting all components. Overall, however, our project was a resounding success.
Video of Normal Drive Robot: https://drive.google.com/open?id=1ROg2jWHoH2i4wECjFqIAdq6w6FZl0lH5
Video of Proportional Control Robot: https://drive.google.com/open?id=1KnJCxotErx5oTipOcEdLxKCzqd4XFGaL