Tello无人机SDK使用Python封装+简单示例

import socketimport threadingimport timeimport traceback

class Tello: """Wrapper to simply interactions with the Ryze Tello drone."""
def __init__(self, local_ip, local_port, imperial=True, command_timeout=.3, tello_ip='192.168.10.1', tello_port=8889): """Binds to the local IP/port and puts the Tello into command mode. Args: local_ip (str): 要绑定的本地 IP 地址. local_port (int): Local port to bind,本地端口. imperial (bool): 如果为 True, 速度是 Mph, 距离是英尺 如果 False,速度为 KPH,距离为米 command_timeout (int|float):等待响应命令的秒数. tello_ip (str): Tello IP. tello_port (int): Tello port. Raises: RuntimeError: If the Tello rejects the attempt to enter command mode. """
self.abort_flag = False self.command_timeout = command_timeout self.imperial = imperial self.response = None
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建一个UDP的连接 # socket这个是插座的意思,其实有点像 self.tello_address = (tello_ip, tello_port) # 元组传递ip+端口
self.socket.bind((local_ip, local_port))
self.receive_thread = threading.Thread(target=self._receive_thread) self.receive_thread.daemon = True # 守护线程
self.receive_thread.start() 开始一个线程
if self.send_command('command') != 'OK': raise RuntimeError('Tello 被拒绝尝试进入命令模式')
def __del__(self): """关闭Tello端口.""" self.socket.close()
def _receive_thread(self): """Listens for responses from the Tello. Runs as a thread, sets self.response to whatever the Tello last returned. """ while True: try: self.response, ip = self.socket.recvfrom(256) except Exception: break
def flip(self, direction): """Flips. Args: direction (str): Direction to flip, 'l', 'r', 'f', 'b', 'lb', 'lf', 'rb' or 'rf'. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.send_command('flip %s' % direction)
def get_battery(self): """Returns percent battery life remaining. Returns: int: Percent battery life remaining. """
battery = self.send_command('battery?')
try: battery = int(battery) except: pass
return battery
def get_flight_time(self): """Returns the number of seconds elapsed during flight. Returns: int: Seconds elapsed during flight. """
flight_time = self.send_command('time?')
try: flight_time = int(flight_time) except: pass
return flight_time
def get_speed(self): """Returns the current speed. Returns: int: Current speed in KPH or MPH. """
speed = self.send_command('speed?')
try: speed = float(speed)
if self.imperial is True: speed = round((speed / 44.704), 1) else: speed = round((speed / 27.7778), 1) except: pass
return speed
def land(self): """Initiates landing. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.send_command('land')
def move(self, direction, distance): """Moves in a direction for a distance. This method expects meters or feet. The Tello API expects distances from 20 to 500 centimeters. Metric: .1 to 5 meters Imperial: .7 to 16.4 feet Args: direction (str): Direction to move, 'forward', 'back', 'right' or 'left'. distance (int|float): Distance to move. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
distance = float(distance)
if self.imperial is True: distance = int(round(distance * 30.48)) else: distance = int(round(distance * 100))
return self.send_command('%s %s' % (direction, distance))
def move_backward(self, distance): """Moves backward for a distance. See comments for Tello.move(). Args: distance (int): Distance to move. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.move('back', distance)
def move_down(self, distance): """Moves down for a distance. See comments for Tello.move(). Args: distance (int): Distance to move. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.move('down', distance)
def move_forward(self, distance): """Moves forward for a distance. See comments for Tello.move(). Args: distance (int): Distance to move. Returns: str: Response from Tello, 'OK' or 'FALSE'. """ return self.move('forward', distance)
def move_left(self, distance): """Moves left for a distance. See comments for Tello.move(). Args: distance (int): Distance to move. Returns: str: Response from Tello, 'OK' or 'FALSE'. """ return self.move('left', distance)
def move_right(self, distance): """Moves right for a distance. See comments for Tello.move(). Args: distance (int): Distance to move. """ return self.move('right', distance)
def move_up(self, distance): """Moves up for a distance. See comments for Tello.move(). Args: distance (int): Distance to move. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.move('up', distance)
def send_command(self, command): """Sends a command to the Tello and waits for a response. If self.command_timeout is exceeded before a response is received, a RuntimeError exception is raised. Args: command (str): Command to send. Returns: str: Response from Tello. Raises: RuntimeError: If no response is received within self.timeout seconds. """
self.abort_flag = False timer = threading.Timer(self.command_timeout, self.set_abort_flag)
self.socket.sendto(command.encode('utf-8'), self.tello_address)
timer.start()
while self.response is None: if self.abort_flag is True: raise RuntimeError('No response to command')
timer.cancel()
response = self.response.decode('utf-8') self.response = None
return response
def set_abort_flag(self): """Sets self.abort_flag to True. Used by the timer in Tello.send_command() to indicate to that a response timeout has occurred. """
self.abort_flag = True
def set_speed(self, speed): """Sets speed. This method expects KPH or MPH. The Tello API expects speeds from 1 to 100 centimeters/second. Metric: .1 to 3.6 KPH Imperial: .1 to 2.2 MPH Args: speed (int|float): Speed. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
speed = float(speed)
if self.imperial is True: speed = int(round(speed * 44.704)) else: speed = int(round(speed * 27.7778))
return self.send_command('speed %s' % speed)
def takeoff(self): """Initiates take-off. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.send_command('takeoff')
def rotate_cw(self, degrees): """Rotates clockwise. Args: degrees (int): Degrees to rotate, 1 to 360. Returns: str: Response from Tello, 'OK' or 'FALSE'. """
return self.send_command('cw %s' % degrees)
def rotate_ccw(self, degrees): """Rotates counter-clockwise. Args: degrees (int): Degrees to rotate, 1 to 360. Returns: str: Response from Tello, 'OK' or 'FALSE'. """ return self.send_command('ccw %s' % degrees)

先直接放主要的代码一段

import Telloimport time
drone = tello.Tello('192.168.10.2', 8888)drone.takeoff()time.sleep(5)
drone.set_speed(2)time.sleep(1)
drone.move_up(3)time.sleep(5)
drone.move_forward(10)time.sleep(10)
drone.rotate_cw(180)time.sleep(5)
drone.move_forward(10)time.sleep(10)
drone.land()
print('Flight time: %s' % drone.get_flight_time())

再放一段简单的demo

demo因为封装的好,所以就是函数传参加逻辑控制的模式了~

这样放置使用


对于代码来说,照着SDK写的,按说是没有什么大问题.但是我也没有单元测试过,毕竟也没有人给我工资~而且里面的网络编程,多线程,都是我过年现学的,我还会一点GUI,但是写出来好丑呀~就不放了.

https://docs.python.org/3/search.html?q=traceback&check_keywords=yes&area=default

为了方便debug引入这个库

该模块提供了一个标准接口来提取、格式化和打印 Python 程序的堆栈跟踪结果。它完全模仿Python 解释器在打印堆栈跟踪结果时的行为。当您想要在程序控制下打印堆栈跟踪结果时,例如在“封装”解释器时,这是非常有用的。

这个模块使用 traceback 对象 —— 这是存储在 sys.last_traceback 中的对象类型变量,并作为 sys.exc_info() 的第三项被返回。

可以方便的看这个模块的api

最终就是用了这么多的库

def __init__(self, local_ip, local_port, imperial=True, command_timeout=.3, tello_ip='192.168.10.1', tello_port=8889): """Binds to the local IP/port and puts the Tello into command mode. Args: local_ip (str): 要绑定的本地 IP 地址. local_port (int): Local port to bind,本地端口. imperial (bool): 如果为 True, 速度是 Mph, 距离是英尺 如果 False,速度为 KPH,距离为米 command_timeout (int|float):等待响应命令的秒数. tello_ip (str): Tello IP. tello_port (int): Tello port. Raises: RuntimeError: If the Tello rejects the attempt to enter command mode. """
self.abort_flag = False self.command_timeout = command_timeout self.imperial = imperial self.response = None
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建一个UDP的连接 # socket这个是插座的意思,其实有点像 self.tello_address = (tello_ip, tello_port) # 元组传递ip+端口
self.socket.bind((local_ip, local_port))
self.receive_thread = threading.Thread(target=self._receive_thread) self.receive_thread.daemon = True # 守护线程
self.receive_thread.start() 开始一个线程
if self.send_command('command') != 'OK': raise RuntimeError('Tello 被拒绝尝试进入命令模式')

这个是一个构造函数,对于与飞机的连接,通信,信息处理都是至关重要的

这段是建立一个IPv4的UDP套接字

注意是元组传参

多线程的知识建议自己去看,我有空写教程

接收的话,也是用一个线程来写,接收256字节的数据,因为就是个控制而已

翻滚的函数,没有难度,直接传参数,发送到飞机

电量

再封装这个函数的时候,考虑到了单位

这个函数可以说是很重要啦,是一个发送函数

self.socket.sendto(command.encode('utf-8'), self.tello_address)

sendto函数是把数据按照接收时候的地址,原路发回去

timer.start() while self.response is None: if self.abort_flag is True: raise RuntimeError('No response to command') timer.cancel()

为了提高代码的健壮性,这个地方做了大量的判断,确保发送成功


剩下就没有上面难点了,感兴趣的可以看注释~

(0)

相关推荐

  • 使paramiko库执行命令时,在给定的时间强制退出

    原因: 使用paramiko库ssh连接到远端云主机上时,非常偶现卡死现象,连接无法退出(可以是执行命令时云主机重启等造成).需要给定一段时间,不管命令执行是否卡住,都退出连接,显示命令执行超时错误. ...

  • ML之HierarchicalClustering:自定义HierarchicalClustering层次聚类算法

    ML之HierarchicalClustering:自定义HierarchicalClustering层次聚类算法 输出结果 更新-- 实现代码 # -*- encoding=utf-8 -*- f ...

  • appium+python自动化52-多点触控MultiAction

    前言 MultiAction是针对多点触控操作的,是TouchAction的一个补充模块 TouchAction用法参考前面的一篇:appium+python自动化33-解锁九宫格(TouchActi ...

  • Python生成简单3D管道

    笔者最近研究了一下通过python生成简单3D管道的方法.主要通过空间坐标旋转平移的方法,得到管道起止点的圆截面(正多边形顶点--其法线向量与起止点向量相同),根据顶点构建管道面.并保存为obj文件. ...

  • 用 python 编写简单的证书域名到期报警脚本

    将脚本放在服务器的计划任务内,定时检测,证书到期不足60天发送报警邮件及钉钉提醒. 在服务器上需要提前安装好 requests 库. pip install requests 钉钉机器人 https: ...

  • Web前端和Python哪个简单?Python学习!

    Web前端和Python都比较简单,适合零基础的人员学习,但两者之间就业方向不同.前景不同,所以很多人在选择上犯了难,不知道学习Web前端好还是Python好,接下来为大家分析一下. 其实Web前端和 ...

  • 将旋转运动转换为线性运动的简单示例 #机械设计 #机械原理

    将旋转运动转换为线性运动的简单示例 #机械设计 #机械原理

  • Python语言简单介绍及安装

    到目前为止,我已经学习过不少语言了,C.C++.Java甚至C#我也曾看过一两本书,但仍旧没找到一种最适合我的,或者说是我最适合的(哎,太不专一不说,还都只学到皮毛 ). 最近受新老板的影响,要用py ...

  • java学习——46、图形用户界面简单示例

    Java的图形用户界面使用图形的方式借助菜单.编辑框.按钮等标准界面元素和键盘.鼠标操作,提供应用程序与用户进行数据交流的界面,实现人机交互. Java图形用户界面的组件和事件由Java.awt和Ja ...

  • 算法创作 | 用python解决简单的数学运算

    前言朴实无华的基础练习却能为自身的学习奠定无限可能问题描述使用while函数完成:输出1到100之间的偶(奇)数输出1-2+3-4+...+99-100的和用python的math工具结合if:解决一 ...

  • Python|关于简单插入排序的奥秘

    前言 相信大家在生活中经常会遇到排序的问题,比如,如果你是超市工作人员,看到货架上的货品被顾客弄乱了,你一定会重新给货品排序,基本上是按从小到大.从矮到高的顺序摆放.在家里面,你也一定会给家里的物品按 ...

  • Python做简单爬虫(urllib.request怎么抓取https以及伪装浏览器访问的方法)

    一:抓取简单的页面: 用Python来做爬虫抓取网站这个功能很强大,今天试着抓取了一下百度的首页,很成功,来看一下步骤吧 首先需要准备工具: 1.python:自己比较喜欢用新的东西,所以用的是Pyt ...