diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c34988 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/venv +tello.pyc diff --git a/README.md b/README.md index 1ed686e..d8737dd 100644 --- a/README.md +++ b/README.md @@ -1,99 +1,97 @@ -DISCLAIMER -I do not own a Tello. This code and documentation is based on the Tello SDK -documentation as of 3/19/2018. +# A Python interface for the Ryze Tello drone. -WHAT THE BLEEP IS THIS +##### inital fork date: 9 February 2019 -A Python interface for the Ryze Tello drone. +##### This code and documentation is based on the Tello SDK documentation as of 3/19/2018. The tello module provides a Tello class, which interacts with the Tello API. -The Tello has an IP of 192.168.10.1. The device sending commands must be -connected to the Tello WiFi network and have an IP in the 192.168.10.0/24 -range. +The Tello has an IP of 192.168.10.1. The device sending commands must be connected to the Tello WiFi network and have an IP in the 192.168.10.0/24 range. -CREATE A MAGIC TELLO OBJECT +### Tello Object -Tello objects require a minimum of 2 parameters to initialize, the local IP -address and port to bind. +Tello objects require a minimum of 2 parameters to initialize, the local IP address and port to bind. -Ex. drone = tello.Tello('192.168.10.2', 8888) +`drone = tello.Tello('192.168.10.2', 8888)` Methods that require distance or speed parameters expect feet or MPH. Include parameter imperial=False for meters and KPH. -Ex. drone = tello.Tello('192.168.10.2', 8888, imperial=False) +`drone = tello.Tello('192.168.10.2', 8888, imperial=False)` -If you send a command to the Tello and it doesn't respond within .3 seconds, a -RuntimeError is raised. You may specify the number of seconds to wait with the -timeout parameter. +If you send a command to the Tello and it doesn't respond within .3 seconds, a `RuntimeError` is raised. You may specify the number of seconds to wait with the timeout parameter. -Ex. drone = tello.Tello('192.168.10.2', 8888, imperial=False, timeout=.5) +`drone = tello.Tello('192.168.10.2', 8888, imperial=False, timeout=.5)` -When you initialize a Tello object, it attempts to connect to the Tello and -enter command mode. If this fails, a RuntimeError is raised. +When you initialize a Tello object, it attempts to connect to the Tello and enter command mode. If this fails, a `RuntimeError` is raised. -DO VARIOUS THINGS +Once initialized, a number of methods are available to send commands to the Tello. It will respond with `OK`, `FALSE` or a numeric value, which the methods return. -Once initialized, a number of methods are available to send commands to the -Tello. It will respond with 'OK', 'FALSE' or a numeric value, which the methods -return. - -These methods do what you'd expect. Responses are 'OK' or 'FALSE'. +These methods do what you'd expect. Responses are `OK` or `FALSE`. +``` Tello.takeoff() Tello.land() +``` -Methods that perform vertical or horizontal movements require a single -parameter, distance. Responses are 'OK' or 'FALSE'. +Methods that perform vertical or horizontal movements require a single parameter, distance. Responses are `OK` or `FALSE`. -The unit of distance is feet or meters. The SDK accepts distances of 1 to 500 -centimeters. Realistically, this translates to .1 - 5 meters or .7 - 16.4 feet. +The unit of distance is feet or meters. The SDK accepts distances of 1 to 500 centimeters. Realistically, this translates to .1 - 5 meters or .7 - 16.4 feet. +``` Tello.move_forward(distance) Tello.move_backward(distance) Tello.move_right(distance) Tello.move_left(distance) Tello.move_up(distance) Tello.move_down(distance) +``` Methods that rotate require a single parameter, degrees. The SDK accepts values -from 1 to 360. Responses are 'OK' or 'FALSE'. +from 1 to 360. Responses are `OK` or `FALSE`. +``` Tello.rotate_cw(degrees) Tello.rotate_ccw(degrees) +``` -The method to set speed requires a single parameter, speed. Responses are 'OK' -or 'FALSE'. +The method to set speed requires a single parameter, speed. Responses are `OK` or `FALSE`. -The unit of speed is KPH or MPH. The SDK accepts speeds from 1 to 100 -centimeters/second. Realistically, this translates to .1 to 3.6 KPH or .1 to -2.2 MPH. +The unit of speed is KPH or MPH. The SDK accepts speeds from 1 to 100 centimeters/second. Realistically, this translates to .1 to 3.6 KPH or .1 to 2.2 MPH. +``` Tello.set_speed(speed) +``` -The method to flip requires a single parameter, direction. The SDK accepts 'l', -'r', 'f', 'b', 'lf', 'lb', 'rf' or 'rb'. Responses are 'OK' or 'FALSE'. +The method to flip requires a single parameter, direction. The SDK accepts `l`, +`r`, `f`, `b`, `lf`, `lb`, `rf` or `rb`. Responses are `OK` or `FALSE`. +``` Tello.flip(direction) +``` Methods that retrieve information from the Tello take no parameters. Responses are numeric values. Get current speed in KPH or MPH: +``` Tello.get_speed() +``` Get percent battery life remaining: +``` Tello.get_battery() +``` Get elapsed flight time in seconds: +``` Tello.get_flight_time() +``` -DO THE HOKEY POKEY - -Put it all together, and you might do something like this. +Example `main.py` +``` import tello import time @@ -120,3 +118,4 @@ time.sleep(10) drone.land() print 'Flight time: %s' % drone.get_flight_time() +``` diff --git a/examples/example_one.py b/examples/example_one.py new file mode 100644 index 0000000..a3be8d3 --- /dev/null +++ b/examples/example_one.py @@ -0,0 +1,14 @@ +import tello +import time + +print 'Example One: take off, pause 10 sec, land' + +drone = tello.Tello('192.168.10.2', 8888) + +drone.takeoff() + +time.sleep(10) + +drone.land() + +print 'Flight time: %s' % drone.get_flight_time() diff --git a/main.py b/main.py new file mode 100644 index 0000000..92125b9 --- /dev/null +++ b/main.py @@ -0,0 +1,50 @@ +import sys +import termios +import contextlib +import tello +import time + + +@contextlib.contextmanager +def raw_mode(file): + old_attrs = termios.tcgetattr(file.fileno()) + new_attrs = old_attrs[:] + new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON) + try: + termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs) + yield + finally: + termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs) + + +def main(): + drone = tello.Tello('192.168.10.2', 8888, False) + print 'exit with ^C or ^D' + with raw_mode(sys.stdin): + try: + while True: + ch = sys.stdin.read(1) + if not ch or ch == chr(4): + break + + if ch == 'z': + drone.takeoff() + + if ch == 'x': + drone.land() + + if ch == 'd': + drone.rotate_cw(30) + + if ch == 'a': + drone.rotate_ccw(30) + + if ch == 'c': + drone.get_battery() + + except (KeyboardInterrupt, EOFError): + pass + + +if __name__ == '__main__': + main() diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 0000000..1b86ffa --- /dev/null +++ b/testing/README.md @@ -0,0 +1,16 @@ + +# Testing Individual Commands + +Run `python ` to test each command. + +The try statement holds the code for establishing a connection to the drone followed by the command. + +Catch socket errors and display error message. + +# Needs improvements + +1. Importing tello module via `sys.path.append(os.path.join(os.path.dirname(__file__), '..'))` could be replaced. + +# Contributing + +Simply fork this repo and make a pull request. \ No newline at end of file diff --git a/testing/flip.py b/testing/flip.py new file mode 100644 index 0000000..0e525cd --- /dev/null +++ b/testing/flip.py @@ -0,0 +1,23 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Flipping (l)..." + + drone.flip('l') + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file diff --git a/testing/get_battery.py b/testing/get_battery.py new file mode 100644 index 0000000..98feb16 --- /dev/null +++ b/testing/get_battery.py @@ -0,0 +1,25 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + + + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Reading battery information..." + + print "There is %d percent battery remaining." % drone.get_battery() + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file diff --git a/testing/get_speed.py b/testing/get_speed.py new file mode 100644 index 0000000..5d24dbc --- /dev/null +++ b/testing/get_speed.py @@ -0,0 +1,23 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Reading speed information..." + + print "The drone is moving at a speed of %d kmph" % drone.get_speed() + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file diff --git a/testing/land.py b/testing/land.py new file mode 100644 index 0000000..b645d4b --- /dev/null +++ b/testing/land.py @@ -0,0 +1,23 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Landing..." + + drone.land() + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file diff --git a/testing/move_forward.py b/testing/move_forward.py new file mode 100644 index 0000000..40bc5e0 --- /dev/null +++ b/testing/move_forward.py @@ -0,0 +1,23 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Moving forward..." + + drone.move_forward(10) + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file diff --git a/testing/set_speed.py b/testing/set_speed.py new file mode 100644 index 0000000..e4d7ebc --- /dev/null +++ b/testing/set_speed.py @@ -0,0 +1,23 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Setting the speed to 2 kmph..." + + drone.set_speed(2) + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file diff --git a/testing/takeoff.py b/testing/takeoff.py new file mode 100644 index 0000000..b8d2719 --- /dev/null +++ b/testing/takeoff.py @@ -0,0 +1,23 @@ +import sys +import os +import socket + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import tello + +print "Connecting to Tello drone..." + +try: + drone = tello.Tello('192.168.10.2', 8888, False) + + print "Connected to Tello successfully." + + print "Taking off..." + + drone.takeoff() + + print "Success." + +except socket.error: + print "Could not connect to Tello drone." \ No newline at end of file