openFrameworksでTelloドローン動画ストリーミング


はじめに

前回の記事で,openFrameworksからTelloドローン操縦するを投稿しました.
この記事ではTelloドローンのストリーミング機能をopenFrameworksで実装する方法を紹介します.

OpenCvのVideoCaptuerを使う

Telloのストリーミングについて色々と調べていたらPythonを使った記事が一番多く,やはりOpwenCvを使ってストリーミングをしているようです.公式が出しているPythonのサンプルコードも参考になります.

詰まった点

最初「openCVでできるなら楽やな〜,ofxOpenCvから生のopencv触れるし〜」と思っていたのですが,どうやらofxOpenCvではVideoCaptuerなどの動画を扱うクラスは,他のoFの動画を扱うクラスとの混同を避けるためにコンパイルされていない機能があるそうで,addonを使わずにopencvをインクルードしなければなりませんでした.

OpenCvのインストールとパスの設定

この作業が一番めんどくさかったです.OpenCvのインストールとパスの設定はすでに多くの方がやり方をあげてくれているので,それらを参考にしました.
参考サイト
- http://kzm42.blog24.fc2.com/blog-entry-25.html
- http://kzm42.blog24.fc2.com/blog-entry-25.html
- https://qiita.com/Atsu30/items/5a76d159b5a79d7d7769

OpenCvをインストールしoFでインクルード出来たらOKです.

実装

前回の記事でTelloのアドオン,ofxTelloを紹介しました.これも使って実装します.

ofApp.hpp
#pragma once
#include "ofMain.h"
#include "ofxTello.h"
#include "opencv2/opencv.hpp"

using namespace cv;
class ofApp : public ofBaseApp{
public:
    void setup();
    void update();
    void draw();
    void exit();
    void keyPressed(int key);

    ofxTello tello;
    VideoCapture cap;
    Mat bgrFrame, rgbFrame;
    ofImage img;
    int distance, angle, speed;
};

ofApp.cpp
#include "ofApp.h"

using namespace cv;
//--------------------------------------------------------------
void ofApp::setup(){
    tello.connect();
    tello.streamon();
    cap = cv::VideoCapture("udp://@0.0.0.0:11111");
    distance = 50;
    angle = 45;
    speed = 50;
}
//--------------------------------------------------------------
void ofApp::update(){
    if (cap.isOpened()){
        cap.read(bgrFrame);
        cvtColor(bgrFrame, rgbFrame, COLOR_BGR2RGB);
        img.setFromPixels(rgbFrame.data, rgbFrame.cols, rgbFrame.rows, OF_IMAGE_COLOR);
    }
    img.update();
}
//--------------------------------------------------------------
void ofApp::draw(){
    img.draw(0,0);
}
//--------------------------------------------------------------
void ofApp::exit(){
    tello.streamoff();
    tello.close();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if(key == 't'){
        tello.takeoff();
    } else if(key == 'l'){
        tello.land();
    } else if(key == 'w'){
        tello.foward(distance);
    } else if(key == 's'){
        tello.back(distance);
    } else if(key == 'a'){
        tello.left(distance);
    } else if(key == 'd'){
        tello.right(distance);
    } else if(key == OF_KEY_UP){
        tello.up(distance);
    } else if(key == OF_KEY_DOWN){
        tello.down(distance);
    } else if(key == OF_KEY_RIGHT){
        tello.cw(angle);
    } else if(key == OF_KEY_LEFT){
        tello.ccw(angle);
    }
}

こんな感じで飛ばしながら動画ストリーミングをやることが出来ました.
まだofxTelloの方には組み込んでいないのですが,今後実装していこうと思ってます.