The Follow Me example moves a vehicle to track your position, using location information from a USB GPS attached to your (Linux) laptop.
The source code is a good starting point for your own applications. It can be extended to use other python language features and libraries (OpenCV, classes, lots of packages etc…)
Note
This example can only run on a Linux computer, because it depends on the Linux-only gpsd service.
Warning
Run this example with caution - be ready to exit follow-me mode by switching the flight mode switch on your RC radio.
DroneKit (for Linux) and the vehicle should be set up as described in Installing DroneKit.
Once you’ve done that:
Install the gpsd service (as shown for Ubuntu Linux below):
sudo apt-get install gpsd gpsd-clients
You can then plug in a USB GPS and run the “xgps” client to confirm that it is working.
Note
If you do not have a USB GPS you can use simulated data by running dronekit-python/examples/follow_me/run-fake-gps.sh (in a separate terminal from where you’re running DroneKit-Python). This approach simulates a single location, and so is really only useful for verifying that the script is working correctly.
Get the DroneKit-Python example source code onto your local machine. The easiest way to do this is to clone the dronekit-python repository from Github. On the command prompt enter:
git clone http://github.com/dronekit/dronekit-python.git
Navigate to the example folder as shown:
cd dronekit-python/examples/follow_me/
You can run the example against a simulator (DroneKit-SITL) by specifying the Python script without any arguments. The example will download SITL binaries (if needed), start the simulator, and then connect to it:
python follow_me.py
On the command prompt you should see (something like):
Starting copter simulator (SITL)
SITL already Downloaded.
Connecting to vehicle on: tcp:127.0.0.1:5760
>>> APM:Copter V3.4-dev (e0810c2e)
>>> Frame: QUAD
Link timeout, no heartbeat in last 5 seconds
Basic pre-arm checks
Waiting for GPS...: None
...
Waiting for GPS...: None
Taking off!
Altitude: 0.019999999553
...
Altitude: 4.76000022888
Reached target altitude
Going to: Location:lat=50.616468333,lon=7.131903333,alt=30,is_relative=True
...
Going to: Location:lat=50.616468333,lon=7.131903333,alt=30,is_relative=True
Going to: Location:lat=50.616468333,lon=7.131903333,alt=30,is_relative=True
User has changed flight modes - aborting follow-me
Close vehicle object
Completed
Note
The terminal output above was created using simulated GPS data (which is why the same target location is returned every time).
To stop follow-me you can change the vehicle mode or do Ctrl+C (on a real flight you can just change the mode switch on your RC transmitter).
You can run the example against a specific connection (simulated or otherwise) by passing the connection string for your vehicle in the --connect
parameter.
For example, to connect to SITL running on UDP port 14550 on your local computer:
python follow_me.py --connect 127.0.0.1:14550
Most of the example should be fairly familiar as it uses the same code as other examples for connecting to the vehicle, taking off, and closing the vehicle object.
The example-specific code is shown below. All this does is attempt to get a gps socket and read the location in a two second loop. If it is successful it
reports the value and uses Vehicle.simple_goto
to move to the new position. The loop exits when
the mode is changed.
import gps
import socket
...
try:
# Use the python gps package to access the laptop GPS
gpsd = gps.gps(mode=gps.WATCH_ENABLE)
#Arm and take off to an altitude of 5 meters
arm_and_takeoff(5)
while True:
if vehicle.mode.name != "GUIDED":
print "User has changed flight modes - aborting follow-me"
break
# Read the GPS state from the laptop
gpsd.next()
# Once we have a valid location (see gpsd documentation) we can start moving our vehicle around
if (gpsd.valid & gps.LATLON_SET) != 0:
altitude = 30 # in meters
dest = LocationGlobalRelative(gpsd.fix.latitude, gpsd.fix.longitude, altitude)
print "Going to: %s" % dest
# A better implementation would only send new waypoints if the position had changed significantly
vehicle.simple_goto(dest)
# Send a new target every two seconds
# For a complete implementation of follow me you'd want adjust this delay
time.sleep(2)
except socket.error:
print "Error: gpsd service does not seem to be running, plug in USB GPS or run run-fake-gps.sh"
sys.exit(1)
The full source code at documentation build-time is listed below (current version on github):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
© Copyright 2015-2016, 3D Robotics.
followme - Tracks GPS position of your computer (Linux only).
This example uses the python gps package to read positions from a GPS attached to your
laptop and sends a new vehicle.simple_goto command every two seconds to move the
vehicle to the current point.
When you want to stop follow-me, either change vehicle modes or type Ctrl+C to exit the script.
Example documentation: http://python.dronekit.io/examples/follow_me.html
"""
from __future__ import print_function
from dronekit import connect, VehicleMode, LocationGlobalRelative
import gps
import socket
import time
import sys
#Set up option parsing to get connection string
import argparse
parser = argparse.ArgumentParser(description='Tracks GPS position of your computer (Linux only).')
parser.add_argument('--connect',
help="vehicle connection target string. If not specified, SITL automatically started and used.")
args = parser.parse_args()
connection_string = args.connect
sitl = None
#Start SITL if no connection string specified
if not connection_string:
import dronekit_sitl
sitl = dronekit_sitl.start_default()
connection_string = sitl.connection_string()
# Connect to the Vehicle
print('Connecting to vehicle on: %s' % connection_string)
vehicle = connect(connection_string, wait_ready=True, timeout=300)
def arm_and_takeoff(aTargetAltitude):
"""
Arms vehicle and fly to aTargetAltitude.
"""
print("Basic pre-arm checks")
# Don't let the user try to arm until autopilot is ready
while not vehicle.is_armable:
print(" Waiting for vehicle to initialise...")
time.sleep(1)
print("Arming motors")
# Copter should arm in GUIDED mode
vehicle.mode = VehicleMode("GUIDED")
vehicle.armed = True
while not vehicle.armed:
print(" Waiting for arming...")
time.sleep(1)
print("Taking off!")
vehicle.simple_takeoff(aTargetAltitude) # Take off to target altitude
# Wait until the vehicle reaches a safe height before processing the goto (otherwise the command
# after Vehicle.simple_takeoff will execute immediately).
while True:
print(" Altitude: ", vehicle.location.global_relative_frame.alt)
if vehicle.location.global_relative_frame.alt>=aTargetAltitude*0.95: #Trigger just below target alt.
print("Reached target altitude")
break
time.sleep(1)
try:
# Use the python gps package to access the laptop GPS
gpsd = gps.gps(mode=gps.WATCH_ENABLE)
#Arm and take off to altitude of 5 meters
arm_and_takeoff(5)
while True:
if vehicle.mode.name != "GUIDED":
print("User has changed flight modes - aborting follow-me")
break
# Read the GPS state from the laptop
next(gpsd)
# Once we have a valid location (see gpsd documentation) we can start moving our vehicle around
if (gpsd.valid & gps.LATLON_SET) != 0:
altitude = 30 # in meters
dest = LocationGlobalRelative(gpsd.fix.latitude, gpsd.fix.longitude, altitude)
print("Going to: %s" % dest)
# A better implementation would only send new waypoints if the position had changed significantly
vehicle.simple_goto(dest)
# Send a new target every two seconds
# For a complete implementation of follow me you'd want adjust this delay
time.sleep(2)
except socket.error:
print("Error: gpsd service does not seem to be running, plug in USB GPS or run run-fake-gps.sh")
sys.exit(1)
#Close vehicle object before exiting script
print("Close vehicle object")
vehicle.close()
# Shut down simulator if it was started.
if sitl is not None:
sitl.stop()
print("Completed")