Drone Part Two

Source Code for Drone

Part one of the drone covers most of the non-technical details. In this part, I’ll talk about the technical details of the project.

Project Structure

I broke the project into four directories: labels, model, src, and tests.

model and labels are a bit self-explanatory. TensorFlow reads in a model from model and a label set from labels.

Most of the project started in tests where I would write simple programs to test the GPIO buttons to make sure I could interact with the Pi while it was attached to the drone. I also based the main loop after this example from Google’s TensorFlow Lite Github which was extremely helpful in creating this project. The src directory is mainly what this blog post will focus on.

Theses are the files in the src. detect_picamera.py is a modified version of the TensorFlow Lite example from above.

run.sh allows the Pi to run real time object detection automatically when it boots up. You add it to your rc.local file and pass arguments to detect_picamera.py to fit your needs though the defaults are reasonable. Run python3 picamera_detect.py --help to see a whole list of arguments you can pass. Alternatively you can just look at the source code for args.py to see all the options. In order for run.sh to work you need to cd into the directory that contains run.sh. In my case /home/pi/Drone/src/, so I then activated the Python environment venv and then ran python3 detect_picamera.py &. It should look something like this: rc.local (cd into src directory and execute run.sh which basically activates the venv environment):

cd /home/pi/Drone/src
./run.sh

run.sh:

. ../venv/bin/activate
python3 detect_picamera.py &
exit

Next is the main loop of the program: detect_picamera.py. The loop uses the PiCamera to look for objects in real time. I removed a great deal of code and added my own to fit my needs for the project. For example, originally detect_picamera.py included a few methods that would create a GUI that would draw a square around an object and try and label that square in real time. Since I didn’t need a GUI, I completely removed this code.

Next I altered the code to search for people. Since the program searched for a wide array of objects ranging from umbrellas to dogs to parking meters and everything in between, I added some code to specifically log the GPS coordinates and send a text message only when a person is detected.

Next I added imported my arguments from args.py to make the program more flexible. You can pass args.py your own model, label, detection threshold, height and width resolution, and pin numbers for start, stop, and kill. I also used a great library called gpiozero so that I could control the Pi using three buttons to 1) start detecting objects 2) stop detecting objects and 3) end the program. I also used a program called flite to speak text back to me. This was useful to ensure that when I pressed one of the three buttons, the Pi would speak back to me affirming my actions (“Searching…”, “Stopping camera”, and “Killing process now”).

Lastly there logger.py and sms.py which go hand in hand. sms.py contains a class called SMS which reads in Twilio credentials passed in as environment variables for its __init__ method. It’s only other method sends a text message with GPS coordinates that are passed to it from detect_picamera.py. logger.py connects to the SIM7600 via pyserial, sends it an AT command to request the GPS location, and logs the GPS coordinates if they have not already been recorded as a pair. The logging sleeps for about 5 seconds thereafter to help ensure that if there are other people logged, they are further away from the previous spot. Logger sanitizes the input and stores the GPS coordinates as longtitude and latitude variables that are added to the sets longitude_history and latitude_history respectively. The log file is recorded as <timestamp>.txt in the directory called logs.