Noah SchwartzRyan UngerCharles Robson
Published © GPL3+

Drone on a Leash

A BeagleBone Blue powered drone that will follow you around on a leash.

AdvancedFull instructions provided20 hours9,991
Drone on a Leash

Things used in this project

Hardware components

BeagleBone Blue
BeagleBoard.org BeagleBone Blue
The autopilot and companion computer for the drone.
×1
HobbyKing™ SMACK 300 Premium FPV Ready Folding Drone Frame (KIT)
Lightweight and small frame to mount everything on.
×1
Emax 4pc RS2205 2600KV Brushless Motor
High powered motors that will provide more than enough thrust to fly our drone and the leash.
×1
Night Flying Propeller 5x3 Clear (CW/CCW) (4pcs)
Cheap and light weight propellers that are compatible with the motors and the frame. Definitely get more than one set in case you break one.
×2
Turnigy MultiStar 30A BLHeli-S Rev16 V3 ESC 2~4S (Opto)
Electronic speed controllers that drive the motors. The pwm input comes from the beaglebone.
×4
1500 mAh 4S 100C Lipo Battery
Plenty of other battery options. Just make sure the capacity is high enough, without being too heavy. The motors/ESCs are meant to go with a 4S battery. We recommend getting more than one so it can charge while the other is flying.
×2
LiPo voltage alarm
Very loud, but very important. We accidentally killed the capacity of one of our batteries by having it discharge too much. This item solves that.
×1
2.4Ghz A-FHSS Compatible 8CH Receiver (Hitec Minima compatible)
PPM compatible receiver, the beaglebone blue uses PPM for the RC controller.
×1
Aurora 9 - 9 Channel 2.4GHz Aircraft Computer Radio
Discontinued, but any transmitter receiver combo that outputs PPM should work fine.
×1
Analog joystick (Generic)
We used one from Adafruit. https://www.adafruit.com/product/512 While it is now out of stock, practically any 2 axis analog voltage divider joystick with a decent range of motion would work.
×1
Dog Leash 26
The longest dog leash I could find online. Anything would work here, even strong rope.
×1
Power Distribution Board
Battery output to the ESCs and Beaglebone Blue. As simple as some heavy gauge wire, or a power distribution board with all the wire soldered to it.
×1
JST Jumper Bundle for the BeagleBone Blue
Renaissance Robotics JST Jumper Bundle for the BeagleBone Blue
We didn't have this, but it would have saved a lot of trouble. You need one 4 wire and one 6 wire. https://github.com/beagleboard/beaglebone-blue/wiki/Accessories
×1
Turnigy MultiStar 32Bit ESC Program Card
Technically optional, but it will be much easier to program the ESCs with this, rather than using timed RC commands.
×1

Story

Read more

Code

leash.py

Python
This code samples the joystick position, runs it through a PID controller, and reacts to the position by trying to get it back to the setpoint.
#!/usr/bin/env python3

import sys
import time
import Adafruit_BBIO.ADC as ADC
import math
from dronekit import connect, VehicleMode

"""
##Set up these values before flying!!!!
"""
run = 1
setpoint_x = 50
setpoint_y = 0
setpoint = [setpoint_x, setpoint_y]
Kp = 0.1
Ki = 0
Kd = 0
integral = [0.0, 0.0]
error_prior = [0.0, 0.0]
iteration_time = .1
current = [0, 0]
bias = 0
hover_thrust = 0.5

try:
	ADC.setup()
except:
	print("ADC Setup")

tcp_link = 'tcp:127.0.0.1:12345'

try:
	vehicle = connect(tcp_link)
	print("mavlink connection successful! tcp link: " + tcp_link)
	run = 1
except:
	print(" \n \nmavlink connection failed! \n \n")
	run = 0

# wait for vehicle attitude information to become available
while vehicle.attitude.yaw is None:
	time.sleep(.5)
# save initial yaw to use as target
target_yaw = math.degrees(vehicle.attitude.yaw)

# convert euler angles to quaternion to send over mavlink
# credit dronekit example: https://github.com/dronekit/dronekit-python/blob/master/examples/set_attitude_target/set_attitude_target.py
def to_quaternion(roll = 0.0, pitch = 0.0, yaw = 0.0):
	t0 = math.cos(math.radians(yaw * 0.5))
	t1 = math.sin(math.radians(yaw * 0.5))
	t2 = math.cos(math.radians(roll * 0.5))
	t3 = math.sin(math.radians(roll * 0.5))
	t4 = math.cos(math.radians(pitch * 0.5))
	t5 = math.sin(math.radians(pitch * 0.5))

	w = t0 * t2 * t4 + t1 * t3 * t5
	x = t0 * t3 * t4 - t1 * t2 * t5
	y = t0 * t2 * t5 + t1 * t3 * t4
	z = t1 * t2 * t4 - t0 * t3 * t5
	return [w, x, y, z]

try:
	while run:
		# read joystick values 0-100
		try:
			x_val = 100*ADC.read("AIN1")
			y_val = 100*ADC.read("AIN3")
			current = [x_val, y_val]
		except:
			print("ADC Values not Found!")
		print(current)
		
		# calculate PID
		error = [a_i - b_i for a_i, b_i in zip(setpoint, current)]
		integral = [a_i + (b_i * iteration_time) for a_i, b_i in zip(integral, error)]
		derivative = [(a_i - b_i) / iteration_time for a_i, b_i in zip(error, error_prior)]
		output = [Kp*a_i + Ki*b_i + Kd*c_i + bias for a_i, b_i, c_i in zip(error, integral, derivative)]
		
		# generate mavlink message to send attitude setpoint
		new_quat = to_quaternion(output[0], output[1], target_yaw)
		# http://ardupilot.org/dev/docs/copter-commands-in-guided-mode.html#copter-commands-in-guided-mode-set-attitude-target
		msg = vehicle.message_factory.set_attitude_target_encode(
			0, # time_boot_ms
			1, # target system
			1, # target component
			0b00000100,
			new_quat, # attitude (quaternion)
			0, # roll rate
			0, # pitch rate
			0, # yaw rate
			hover_thrust  # thrust (0-1 where 0.5 is no vertical velocity)
		)
		vehicle.send_mavlink(msg)

		time.sleep(iteration_time)
except KeyboardInterrupt:
	print('exiting')
	pass

vehicle.close()

Credits

Noah Schwartz

Noah Schwartz

1 project • 1 follower
Ryan Unger

Ryan Unger

1 project • 1 follower
Charles Robson

Charles Robson

0 projects • 0 followers

Comments