Piano Drone Thumbnail

Piano-Drone: How I 'Hacked' a Drone With a Piano

Also known as: Hacking a Drone with a Piano

By: Kenny Blake

Published: October 22, 2024 at 9:07 PM EST

Inspiration

This project was an interesting challenge I gave myself back in 2020. I had just watched Michael Reeves' "Hacking a Drone with a Child's Toy" video, and thought "Hey! I can do that!" But didn't want to copy him directly. I also was really starting to get into Sockets, GUIs, Linux, and, most importantly, comedy. This project gave me the perfect excuse to use all of those!

A Horrible, Expensive, Time-Consuming Idea is Born

The idea was pretty simple. Take a drone, make a MIDI interface which sends commands over a network using PyARDrone based on what key is pressed, record the video off the drone using OpenCV, and record piano keypresses using PyGame, and sync those two together to make a movie, that said movie's soundtrack being, you guessed it, the piano track!

Yea. Simple.

Technologies Used:

Obviously, this won't cover absolutely EVERYTHING, just the stuff I used personally.

  • Python 3: The programming language used for this project.
  • Pygame & Pygame.midi: Used to make the GUI, AND used to get the piano key presses.
  • PyArDrone: Used for sending drone commands over a network. HUGE shoutout to the author of this open-source library. Without this, the whole project would have been impossible.
  • OpenCV (cv2): Manages video recording and processing from the drone's camera.
  • MIDIUtil: Used for creating the midi file of the keyboard presses.
  • Ubuntu: Used to actually connect, and send, commands to the drone. Windows firewall rules are terribnle, so I just dualbooted my pc for the sake of this project. Work Smarter, not Harder. (Fun Fact: I am actually full time on Fedora Linux for about a year now. It's FOSS!)

Let's put it together now:

Architecture:

Piano-Drone is structured into three primary Python scripts, each playing it's own role.

  • Piano.py: Controls anything having to do with the piano. It's primary functions being the MIDI keyboard interface, capturing key presses/releases, displaying visual feedback, and sending corresponding commands to the drone.
  • Drone.py: Controls drone/video. Sends comands to drone based on key presses from the Piano class, managing video recording.
  • Driver.py: Entry point to the program. Just creates a piano object and runs it.

How it all worked:

  1. Initialization:

    Piano.py kicks off the show by initializing Pygame and Pygame.midi to handle graphical display and MIDI input. It sets up the MIDI input/output devices and loads visual assets representing key states. Meanwhile, Drone.py initializes the AR.Drone object, sets up video recording parameters, and prepares threading for handling video streams.

  2. MIDI Input Handling:

    As your fingers waltz across the MIDI keyboard, playing beautiful symphonies that would make Mozart jealous, Piano.py detects these graceful (or clumsy) movements. Each key corresponds to a specific drone command (e.g., takeoff, move forward, rotate). The script updates the visual display to reflect the current state of each key, giving you real-time feedback that your drone is both listening and watching. At the same time, MIDIUtil is recording all of your beautiful keystrokes, ensuring they can be played back later.

  3. Drone Command Execution:

    Piano.py sends interpreted commands to Drone.py, which then processes these commands, translating them into actions using the PyArDrone library. For example, pressing the "Takeoff" key sends a takeoff command to the drone, while pressing directional keys moves the drone accordingly. I did this by setting up a dictionary of all the keypresses' MIDI identifier commands, as well as their "value", or how much to tell the drone to do them. Like, rotate left a small amount, or go up a large amount.

  4. Video Recording:

    When you decide to capture your performance, Drone.py starts recording video from the drone's camera using OpenCV. Video recording runs on a separate thread to ensure it doesn't interfere with real-time drone control. Recorded footage is saved with timestamped filenames for easy organization—perfect for sharing your aerial concerts on social media. I made the video recording function on the daemon, which in retrospect, was probably not a good idea.

  5. Emergency Controls:

    An emergency key can be pressed multiple times to trigger an immediate drone shutdown, killing all rotors immediately. This key was more for the protection of everything else around the drone. Not the drone itself.

Challenges:

  1. Real-Time Command Processing:

    Ensuring that MIDI inputs are captured and translated into drone commands without noticeable lag was crucial. This was achieved by optimizing the event loop and using efficient threading for video recording. The system I created wasn't perfect. I think I utilized threading well, even though Python's threading isn't real threading. I think if I had to re-do this project, I would have written it in something a little quicker, like C#.

  2. Synchronization of Visual Feedback:

    This system was pretty simple. Every time I got a MIDI event through Pygame.midi, I blitted a square onto whatever key was pressed, then, on release, blitted a square of the opposite color (same color as the key) over wherever the previous key was placed. For the actual assets, I made a small square in Photoshop. This square would appear over top of whatever key you were currently pressing. If it was a black key, a white square would show up, and vice-versa.

  3. Video Recording Stability:

    Managing continuous video streams from the drone's camera without affecting the drone's responsiveness involved implementing multi-threading and handling potential frame loss scenarios. This once again wasn't perfect. The drone was bad. Like really bad. It was the last one in stock on the east coast, and I bought it from a random Barnes & Noble 1.5 hours away from where I lived at the time. The box was destroyed and it was kind of a disaster. Even worse was the video quality. I ended up having to speed-ramp it in Premiere Pro when it came time to actually export it. If you check out the video, you can see what I'm talking about. I wish I still had that saved somewhere, but alas.

  4. Emergency Control Implementation:

    The emergency control was another consideration of mine. I knew I was going to be flying this at random friends' houses, (or even in public,) so I had to ensure there was a way to minimize the amount of damage as quickly as possible.

Conclusion:

Piano-Drone was one of my favorite, if not my favorite, projects to date. Creating it and bringing it along to my friends' houses was something I was very proud of at the time, and they all had a blast playing with it.

I think projects like these, where there isn't always a real purpose, but instead you're just enjoying what you love, and sharing it with your friends, and sometimes random people online, are truly what passions are built out of.

I had a blast making this project. Even though it's nearly 4 years later now, I still look back on the time I was writing the initial code for it with nothing but positivity. It was a great ride, and I'm glad I spent the money I did on it.

If you gain something from this little rambling blog post, it's that you should sometimes take a big jump on a crazy idea, even if it's guaranteed to be a money pit. Sometimes, you need to spend time on something that's gonna make you happy. Not something that's gonna make you money.

I hope you enjoyed reading this. I'm more than willing to answer any questions anyone may have about this project. Please feel free to send me an email: kennyblake@kennyblake.com

-Kenny