A fish is a low-maintenance, yet boring pet. We built a vehicle consisting of a fishtank mounted on a motorized chassis that moves according to the orientation of a fish inside the tank. Think of a "hamster ball" for a fish. To accomplish this, we mounted a webcam above the fishtank and tracked the fish's position in the tank using image processing. The fish's orientation istranslated into motor signals. This was all done in 24 hours during HackPrinceton Spring 2015 and we managed to pull off first place!
Ankush Gola, Joseph Bolling, Ted Brundage
We probably look and sound tired because we had just pulled an all-nighter :)
Photo of Finished Product
Brief Technical Overview
We used a BeagleBone Black (powered with a power-regulated battery pack) for our processing and I/O. We also used a pair of motor controllers, a Logitech C210 webcam for video capture, and a modified RC car chassis.
Tracking the Fish
A BeagleBone Black embedded linux computer runs an image processing algorithm on a video feed of the fishtank. To get the computation to be reasonably fast, we had to play with both the framerate and video dimensions.
FishTracker class in
fish_tracker.py implements the logic for tracking the position of the fish in the tank. The idea is to segment out the background using HSV masking, perform morphological operations to de-noise the mask, find the centroid of the the mask to obtain a rough (x,y) position in pixel coordinates, and low pass and median filter the position to eliminate "jumpy" readings. The result of fish tracking is an (x,y) position of the fish in pixel coordinates. (See the
detect_fish function in
FishTracker). We made extensive use of the python OpenCV library.
Moving The Vehicle
Our motorized chassis consisted of a hacked RC car with a 3 motors: front, rear, and steering. We used a pair of Sparkfun motor controllers for our H-bridges. We interfaced with the motors using the Adafruit BeagleBone IO libraries for python (
Adafruit_BBIO.PWM) and made a simple
Motor class in
fish_control.py to set the speed and direction of each motor. The speed was set by designating the PWM output value and direction was set by flipping the appropriate GPIO pins to the motor controllers.
After receiving the pixel coordinates of the fish from the fish tracking code (see above), the coordinates are thresholded to fit into one of nine zones (forward right, forward straight, forward left, center right, ... , back left). It took us some playing around with PWM values to get the thrust and steering just right. The main driver function is
The code should be pretty self-explanatory (although definitely not perfect because it's hackathon code!) If you have any questions or comments, feel free to email me!