환경 세팅

TelloPy

tellopy는 pip 설치가 돼 있다면 터미널에서 아래 명령을 쳐서 쉽게 받을 수 있다.

pip3 install tellopy

설치 뒤에는 import tellopy를 통해 패키지를 사용할 수 있다.

VSC에서 다음과 같이 tello 프로젝트를 진행할 폴더를 생성하자.

필자는 TelloProjects라고 이름을 지어서 폴더를 생성해주었다.

여기서 위 과정을 따라 tellopy 라이브러리를 설치하고 import tellopy를 했음에도 불구하고 라이브러리를 사용할 수 없는 경우에는 tellopy를 직접 빌드하여 설치하는 해결 방법이 있다.

git clone <https://github.com/hanyazou/TelloPy.git>
cd TelloPy
python setup.py bdist_wheel
pip install dist/tellopy-*.dev*.whl

위 명령어를 통해 깃허브에서 클론을 받으면 아래와 같은 파일들이 디렉토리(TelloProjects) 내부에 생성된다.

examples 디렉토리에 우리가 tello 조종을 위해 직접적으로 사용할 예제 파일들이 저장되어 있다.

  • joystick_and_video.py: 조이스틱 조종기와 비디오 예제
  • keyboard_and_video.py: 키보드 활용 조종기와 비디오 예제
  • record_log.py: log 데이터 저장 예제
  • simple_takeoff.py: 간단한 이착륙 하는 예제
  • video_effect.py: tello가 촬영하고 있는 비디오를 pc에서 스트리밍 하는 예제

여기서 simple_takeoff.py와 video_effect.py에 작성된 예제들이 앞으로 우리가 사용할 Python으로 Tello를 조작하는 방법론에 대한 시발점이다. 따라서 이번 메뉴얼에서는 이 두 파일을 집중적으로 공부해보자.


 

Python으로 Tello 조종하기

1) simple_takeoff.py

[간단한 이착륙 코드]

from time import sleep
import sys
sys.path.append("/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages")
import tellopy

def handler(event, sender, data, **args):
    drone = sender
    if event is drone.EVENT_FLIGHT_DATA:
        print(data)

def test():
    drone = tellopy.Tello()
    try:
        drone.subscribe(drone.EVENT_FLIGHT_DATA, handler)

        drone.connect()
        drone.wait_for_connection(60.0)
        drone.takeoff()
        sleep(5)
        drone.down(50)
        sleep(5)
        drone.land()
        sleep(5)
    except Exception as ex:
        print(ex)
    finally:
        drone.quit()

if __name__ == '__main__':
    test()
  • drone = tellopy.Tello()
  • tellopy 내부에 정의 되어있는 Tello를 drone이라는 객체로 선언한다.
  • drone.connect
  • 선언한 drone 객체의 connect 메소드를 활용하여 tello에 connection을 요청한다.
  • drone.takeoff
  • takeoff 메소드를 통해 이륙 명령을 내린다.
  • drone.land
  • land 메소드를 통해 착륙 명령을 내린다.
  • sleep
  • 몇 초동안 기다리게 하는 함수이다.

2. video_effect.py

해당 코드를 사용하기 위해서는 ac, opencv, image 패키지를 다운 받아야 한다.

[패키지 다운로드 명령어]

pip install av
pip install opencv-python
pip install image
python -m tellopy.examples.video_effect
  • av: python으로 오디오 및 비디오 파일 CRUD를 위한 라이브러리이다.
    • open: 비디오 or 비디오 파일 열기
    • av 라이브러리를 사용하기 위해서는 FFmpeg 설치 필수
  • opencv: 이미지 및 비디오 처리, 컴퓨터 비전 작업, 기계 학습 등에 사용되는 오픈 소스 컴퓨터 비전 라이브러리이다. 실시간 컴퓨터 비전 애플리케이션 개발에 널리 활용된다.

[Tello-비디오 스트림 출력 코드]

import sys
import traceback
import tellopy
import av
import cv2  # for avoidance of pylint error
import numpy
import time

def main():
    drone = tellopy.Tello()

    try:
        drone.connect()
        drone.wait_for_connection(60.0)

        retry = 3
        container = None
        while container is None and 0 < retry:
            retry -= 1
            try:
                container = av.open(drone.get_video_stream())
            except av.AVError as ave:
                print(ave)
                print('retry...')

        # skip first 300 frames
        frame_skip = 300
        while True:
            for frame in container.decode(video=0):
                if 0 < frame_skip:
                    frame_skip = frame_skip - 1
                    continue
                start_time = time.time()
                image = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR)
                cv2.imshow('Original', image)
                cv2.imshow('Canny', cv2.Canny(image, 100, 200))
                cv2.waitKey(1)
                if frame.time_base < 1.0/60:
                    time_base = 1.0/60
                else:
                    time_base = frame.time_base
                frame_skip = int((time.time() - start_time)/time_base)
                    

    except Exception as ex:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback)
        print(ex)
    finally:
        drone.quit()
        cv2.destroyAllWindows()

if __name__ == '__main__':
    main()
  • container = av.open(drone.get_video_stream()) : 비디오 스트림을 저장하기 위한 AVContainer 변수를 선언한다. av.open 메소드를 통해 해당 파일을 연다.
  • #skip first 300 frames 코드를 살펴보자.frame_skip은 비디오 프레임을 건너뛸 횟수를 나타내는 변수이다. 이 변수를 300으로 초기화하여 처음 300 개의 프레임을 건너뛴다. 초기 스트림의 시작 부분에는 보통 초기화되는 노이즈 또는 불안정한 프레임이 포함될 수 있으므로 시작 300 부분을 건너뛰고, 정상적인 비디오 프레임부터 처리하기 위해 처리해주는 코드이다.
  • # skip first 300 frames frame_skip = 300 while True: for frame in container.decode(video=0): if 0 < frame_skip: frame_skip = frame_skip - 1 continue
  • 비디오 처리를 위한 무한 루프
  • 위 코드는 while 루프 내에서 OpenCV를 사용하여 비디오 프레임을 처리하고 화면에 표시하는 방식으로 영상 프레임을 조작한다. 비디오는 정적 이미지의 연속된 파일이라고 생각하면 되기에 정적 이미지를 연속적으로 처리하기 위해 무한 루프를 사용한다.
  • image = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR): Tello에서 받아온 프레임을 이미지로 변환한 후, 이미지를 Numpy(파이썬 라이브러리) 배열로 변환한다. 이후 cv2.cvtColort 메소드를 사용하여 이미지의 컬러 채널 순서를 RGB → BGR로 변경하는 역할을 한다.
  • numpy.array로 변환한 이미지는 기본적으로 RGB 컬러 순서를 가지고 있지만, OpenCV에서는 기본적으로 BGR 컬러 순서를 사용하기 때문에 cv2.COLOR_RGB2BGR로 컬러 채널 순서를 변경해준다.
  • cv2.imshow(’Original’, image): 받아온 이미지를 화면에 띄우는 메소드이다. Original은 영상을 띄울 창의 이름이고 image는 띄울 이미지(ndarray)이다.

 

sebinChu