# djl tello 無人機控制學習 ### 實機演示 [點這](https://youtu.be/N_-LxrJo0W8) ### 主要程式碼 ```python= from djitellopy import tello import keyboardpress as kp # 命名為kp import time import cv2 a = 0 b = 1 # a為輸入除錯用 b為影像畫面除錯用 global img kp.init() # 初始化 me = tello.Tello() me.connect() #與tello連線 print(me.get_battery()) if b == 1: me.streamon() # 打開tello鏡頭 ####按鍵函式#### def getKeyboardInput(): speed = 30 lr, fb, ud, yaw = 0, 0, 0, 0 # 左右 if kp.getKey('a'): #kp.getKey()另外拉出來寫 if a == 1: print("a") # 測試輸入 else: lr = -speed # a==1時代表不連接tello測試 ###以下同理### elif kp.getKey('d'): if a == 1: print("d") else: lr = speed #前後 if kp.getKey('s'): if a == 1: print("s") else: fb = -speed elif kp.getKey('w'): if a == 1: print("w") else: fb = speed #上下 if kp.getKey('DOWN'): if a == 1: print("DOWN") else: ud = -speed elif kp.getKey('UP'): if a == 1: print("UP") else: ud = speed #旋轉 if kp.getKey('LEFT'): if a == 1: print("LEFT") else: yaw = -speed elif kp.getKey('RIGHT'): if a == 1: print("RIGHT") else: yaw = speed return [lr, fb, ud, yaw] # 回傳左右上下前後旋轉的速度 while True: ### 起降翻轉拍照 與getKeyboardInput()相同 ### if kp.getKey('l'): if a == 1: print("land") else: me.land() if kp.getKey('t'): if a == 1: print("take off") else: me.takeoff() if kp.getKey('f'): if a == 1: print("flip") else: me.flip("l") ##向左翻轉 if kp.getKey('p'): cv2.imwrite(f'Resources/Images/{time.time()}.jpg', img) # f-string 可以在字串裡面透過{}加入自定變數或是函式 #time()可生成完全不重複的檔名 time.sleep(0.5) # 停頓使擷取照片張數減少 vals = getKeyboardInput() if a != 1: me.send_rc_control(vals[0], vals[1], vals[2], vals[3]) # 傳送控制速度的訊號 if b == 1: # 測試影像是否正常出來 img = me.get_frame_read().frame # 循環得到每幀影像 img = cv2.resize(img, (360, 240)) # 改變視窗大小 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA) # 無人機本身預設BGR 把畫面更改成RGB cv2.imshow('Image', img) # cv2.waitKey(10) #等待10毫秒 ``` ### 說明 1. djitellopy、pygame、cv2皆為pycharm的模組,在這邊的作用分別是控制tello、輸入、影像呈現。 2. 在學習完基本動作後,首先影片先教了如何呈現tello的影像在電腦上: ```python= from djitellopy import tello import cv2 me = tello.Tello() me.connect() print(me.get_battery()) me.streamon() while True: img = me.get_frame_read().frame img = cv2.resize(img, (360, 240)) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA) # 更改RGB順序 cv2.imshow('Image', img) cv2.waitKey(1) ``` 實際操作時出了問題,是在更改RGB順序前,影像的顏色有類似負片(?)效果,上網搜尋發現是tello預設的色彩訊號(原本是BGR)和電腦不一樣,將訊號改回RGB就變正常了。 3. 再來是鍵盤控制keyboardpress,getKey()就在這裡: ```python= import pygame def init(): pygame.init()# 初始化 win = pygame.display.set_mode((400, 400)) # 生成視窗 def getKey(keyName): # 按下按鍵後要回傳ture ans = False for event in pygame.event.get(): pass # 不停讀取訊息,pass是因為不需要做任何事 KeyInput = pygame.key.get_pressed() # 偵測鍵盤事件(Ture or False) myKey = getattr(pygame, 'K_{}'.format(keyName)) # 回傳訊號 if KeyInput[myKey]: # 如果偵測到按下指定按鍵 ans = True return ans pygame.display.update() # pygame的視窗更新,應該是為影片後續課程打底 ``` 在這邊最困難的地方是理解程式碼含意,像是 pygame.key.get_pressed()是回傳布林值、getattr()是回傳物件中的某屬性值等,這些都需要上網爬文才知道。 5. 將第2、3點融合,2負責影像,3負責無人機移動。在測試的時候發現鍵盤怎麼輸入都會有問題,最後發現是在執行程式碼的那一刻,電腦會自動切換成預設輸入法(中文),導致原本按下的"t"在電腦那邊是"ㄔ",只要把電腦預設輸入法改成英文就好了。 6. 最後是增加拍照功能,只要先建立資料夾後使用cv2.imwrite()將照片寫入資料夾就好,這邊我去google了路徑前用f的原因,白話來講加了f就可以讓後面的字串變得不固定,達到每張照片的名字都不同,可以確保照片不複寫。