DroneKit-Python 2.0 has undergone a significant architectural evolution when compared to version 1.x (the library changed from a MAVProxy extension to a standalone Python module). The API itself remains similar, with the most important difference being that you now need to specify the vehicle target address inside the script.
The sections below outline the main migration areas.
Note
DroneKit-Python version 1.5 has now been superseded (see these links for legacy documentation and examples).
DKPY 2.0 is now installed from pip on all platforms - see Installing DroneKit for more information.
Installation is generally simpler than on DK 1.x because there are far fewer dependencies (both MAVProxy and numpy are no longer needed).
Note
DroneKit-Python 2.0 apps are run from an ordinary Python command prompt. For example:
some_python_script.py # or `python some_python_script.py`
Note
This contrasts with DKPY 1.x scripts, which were run from within MAVProxy using the command:
api start some_python_script.py
This section outlines the changes you will need to make to your DroneKit-Python scripts.
You must specify the target vehicle address in your script (in DKPY 1.x this was done when you launched MAVProxy).
The code fragment below shows how you import the connect()
method and use it to return a
connected Vehicle
object. The address string passed to connect()
takes the same
values as were passed to MAVProxy when setting up a connection in DKPY 1.x (in this case, a SITL instance running on the same computer).
from dronekit import connect
# Connect to the Vehicle (in this case a UDP endpoint)
vehicle = connect('127.0.0.1:14550', wait_ready=True)
Note
The wait_ready=True
parameter ensures that connect()
won’t return until
Vehicle.parameters
and most other default attributes have been
populated with values from the vehicle. Check out Vehicle.wait_ready()
for more
information (this method is used by the connect()
implementation).
connect()
also has arguments for setting the baud rate,
returning your own custom vehicle classes and setting the length of the connection timeout.
After connecting, the returned vehicle
can be used in exactly the same way as in DKPY 1.x.
Note
The above code replaces DKPY 1.x code to get the Vehicle (similar to the example below):
# Get an instance of the API endpoint
api = local_connect()
# Get the connected vehicle (currently only one vehicle can be returned).
vehicle = api.get_vehicles()[0]
DroneKit no longer runs in MAVProxy so scripts don’t need to monitor and act on external thread shutdown commands.
Remove code that checks the api.exit
status (note that the api.exit
call below is commented out).
while not vehicle.armed # and not api.exit:
print " Waiting for arming..."
time.sleep(1)
Note
In fact you should delete all references to APIConnection
class and its methods (get_vehicles()
, exit()
and stop()
).
Examples that might possibly have outstanding messages should call Vehicle.close()
before exiting to ensure that all messages have flushed before the script completes:
# About to exit script
vehicle.close()
Remove any code that uses the local_arguments
array to get script-local command line arguments (via MAVProxy).
From DKPY 2.0 command line arguments are passed to sys.argv
as with any other script. The examples use the
argparse module for argument parsing, but you can
use whatever method you like.
Note
In DKPY 1.x the script’s sys.argv
values were the values passed to MAVProxy when it was
started. To access arguments passed to the script from MAVProxy you used the local_arguments
array.
For example if you started a script as shown below:
api start my_script.py 101
Then you would read the integer in your code using
my_argument = int(local_arguments[0])
DroneKit-Python v1.x passed a global property load_path
to any executed file containing the
directory in which the script was running. This is no longer needed in version 2 and has been removed.
Instead, use normal Python methods for getting file system information:
import os.path
full_directory_path_of_current_script = os.path.dirname(os.path.abspath(__file__))
DroneKit-Python v1.x had a Vehicle.location
attribute which provided latitude and longitude information in the
global frame, and altitude either relative to sea-level or the home location (depending on the value of its is_relative
member).
DKPY2.0 uses and attribute with the same name to provide location in global, global-relative and local (NED) frames:
print "Global Location: %s" % vehicle.location.global_frame
print "Global Location (relative altitude): %s" % vehicle.location.global_relative_frame
print "Local Location: %s" % vehicle.location.local_frame
For more information see: Vehicle.location
,
Vehicle.location.global_frame
,
Vehicle.location.global_relative_frame
,
Vehicle.location.local_frame
, and Vehicle State and Settings.
DroneKit-Python v1.x provided guided mode takeoff and movement methods Vehicle.commands.takeoff()
and Vehicle.commands.goto()
.
DKPY2.0 instead provides Vehicle.simple_takeoff
and
Vehicle.simple_goto
. These are the same as the old methods
except that simple_goto
allows you to optionally set the default target groundspeed and airspeed.
Vehicle.airspeed
and
Vehicle.groundspeed
are now settable values. Call these to
set the default target speed used when moving with Vehicle.simple_goto
(or other position-based movement commands).
DroneKit-Python 1.x code retrieved the home location from the first element in Vehicle.commands
.
This code must be replaced with the DroneKit-Python 2.x Vehicle.home_location
attribute.
Tip
Even though the home location is no longer returned as the first waypoint in Vehicle.commands
,
you will still need to download the commands in order to populate the value of
Vehicle.home_location
.
The API for working with missions has been improved and made significantly more robust.
One of the major changes is that the Vehicle.commands
list no
longer includes the home location waypoint in the 0th
index. Another change is that we now wait for command download to complete using
Vehicle.commands.wait_ready()
.
All the known bugs have been fixed. It is now much easier to download, clear, and add items to the mission because there is no need to work around race conditions and other issues with the API.
For more information see Missions (AUTO Mode).
The DroneKit-Python 1.x observer function vehicle.add_attribute_observer
has been replaced by
Vehicle.add_attribute_listener()
or
Vehicle.on_attribute()
in DKYP2.x, and Vehicle.remove_attribute_observer
has been repaced by remove_attribute_listener()
.
The main difference is that the callback function now takes three arguments (the vehicle object, attribute name, attribute value) rather than just the attribute name. This allows you to more easily write callbacks that support attribute-specific and vehicle-specific handling and means that you can get the new value from the callback attribute rather than by re-querying the vehicle.
Note
The difference between Vehicle.add_attribute_listener()
and
Vehicle.on_attribute()
is that attribute listeners added using
Vehicle.on_attribute()
cannot be removed (while on_attribute()
has a more elegant syntax).
A few attributes have been modified so that they only notify when the value changes:
Vehicle.system_status
,
Vehicle.armed
, and
Vehicle.mode
. Users no longer need to add caching code
for these attributes in their listeners.
Attributes that provide “streams” of information (i.e. sensor output) remain unchanged.
Note
If you’re creating your own attributes this caching is trivially
provided using the cache=True
argument to
Vehicle.notify_attribute_listeners()
.
See Observing attribute changes for more information.
In DKPY2 you can now observe parameters in order to
be notified of changes, and also iterate
Vehicle.parameters
to get a list of off the supported
values in the connected vehicle.
In addition, the code to download parameters and keep information in sync with the vehicle is now a lot more robust.
DroneKit-Python 1.x used Vehicle.set_mavlink_callback()
and Vehicle.unset_mavlink_callback
to set/unset a callback function that was invoked for every single mavlink message.
In DKPY2 this has been replaced by the Vehicle.on_message()
decorator, which allows you to specify a callback function that will be invoked for a single message
(or all messages, by specifying the message name as the wildcard string ‘*
’).
Tip
Vehicle.on_message()
is used in core DroneKit code for
message capture and to create Vehicle
attributes.
The API also adds Vehicle.add_message_listener()
and Vehicle.remove_message_listener()
.
These can be used instead of Vehicle.on_message()
when you need to be
able to remove an added listener. Typically you won’t need to!
See MAVLink Messages for more information.
In addition to the home_location,
a few more attributes have been added, including:
Vehicle.system_status
,
Vehicle.heading
,
Vehicle.mount_status
,
Vehicle.ekf_ok
,
Vehicle.is_armable
,
Vehicle.last_heartbeat
.
Warning
Channel overrides (a.k.a “RC overrides”) are highly discommended (they are primarily implemented for simulating user input and when implementing certain types of joystick control).
DKPY v2 replaces the vehicle.channel_readback
attribute with
Vehicle.channels
(and the Channels
class) and the vehicle.channel_override
attribute with
Vehicle.channels.overrides
(and the ChannelsOverrides
class).
Documentation and example code for how to use the new API are provided in Example: Channels and Channel Overrides.
DroneKit-Python 1.x scripts were run in the context of a MAVProxy. This made them difficult to debug because you had to instrument your code in order to launch the debugger, and debug messages were interleaved with MAVProxy output.
Debugging on DroneKit-Python 2.x is much easier. Apps are now just standalone scripts, and can be debugged using standard Python methods (including the debugger/IDE of your choice).