Telloからビデオストリーム受信して、デコードして表示とローカルファイルに格納、同時にコマンドファイルからコマンド読み出して並行に実行させるバージョンです。
Telloにコマンド送って時間待ち5秒は冗長だろうしスマートでもないから改善余地ありです。
コードはこちら、
https://github.com/chateight/c_plus_video
ctello_stream.cppが今回のソースです。
admin

la vie libre
Telloからビデオストリーム受信して、デコードして表示とローカルファイルに格納、同時にコマンドファイルからコマンド読み出して並行に実行させるバージョンです。
Telloにコマンド送って時間待ち5秒は冗長だろうしスマートでもないから改善余地ありです。
コードはこちら、
https://github.com/chateight/c_plus_video
ctello_stream.cppが今回のソースです。
admin
Ctelloでspdlogが必須だったので、触ってみました。
spdlogはc++用のログツール、c++に標準で存在しないのは不思議な気もしますが。
本家
https://github.com/gabime/spdlog
使用例も豊富です。
<インストール>
① 以下のヘッダーファイルをコピー
https://github.com/gabime/spdlog/tree/v1.x/include/spdlog
② おすすめは、
“Compiled version (recommended – much faster compile times)”
と言ってますが、macだとbrewが一番簡単でしょう。
% brew install spdlog
% brew list --version|grep spdlog
spdlog 1.10.0_1
<サンプルコード>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
int main()
{
spdlog::info("infromaion!");
spdlog::warn("warning!");
spdlog::error("error!");
std::string test_message = "OK";
spdlog::info("Test result is {}", test_message);
int number_int = 10;
float number_float = 12.345;
spdlog::info("number_int is {:03d}", number_int);
// set log level which also affects to the file log
spdlog::set_level(spdlog::level::warn);
spdlog::info("number_float is {:03.2f}", number_float);
// logging to the log file
auto log_file = spdlog::basic_logger_mt("logger", "log/basic.txt");
log_file -> info("hello!");
spdlog::set_default_logger(log_file);
spdlog::warn("warning! write to the log file");
}
<使い方(cmakeファイル)>
https://github.com/gabime/spdlog/blob/v1.x/example/CMakeLists.txt
から以下のmakefileで、
cmake_minimum_required(VERSION 3.14)
project(SpdProject)
set(CMAKE_CXX_STANDARD 14)
if(NOT TARGET spdlog)
# Stand-alone build
find_package(spdlog REQUIRED)
endif()
# ---------------------------------------------------------------------------------------
# Example of using pre-compiled library
# ---------------------------------------------------------------------------------------
add_executable(spdlogTest src/spdlog_t.cpp)
target_link_libraries(spdlogTest PRIVATE spdlog::spdlog)
<実行結果>
・コンソール
% ./build/spdlogTest
[2022-11-06 18:49:01.191] [info] infromaion!
[2022-11-06 18:49:01.192] [warning] warning!
[2022-11-06 18:49:01.192] [error] error!
[2022-11-06 18:49:01.192] [info] Test result is OK
[2022-11-06 18:49:01.192] [info] number_int is 010・ログファイル(basic.txt)
実行の都度追記されます。
[2022-11-06 18:34:16.437] [logger] [warning] warning! write to the log file
[2022-11-06 18:49:01.192] [logger] [warning] warning! write to the log file
<ソース他>
ソースコード他は、以下に置いてあります。
https://github.com/chateight/spdlog_ex
admin
Pythonからc++のライブラリ呼ぶのは、ライブラリのビルド条件が複雑なので、いっそ全てをc++で作りあげるのが良さそうです。opencvもc++用が存在してるわけだから。
SDK 1.3に記述ある通り、UDPの送信とステータスの受信ポートが違うことは要注意です。
https://dl-cdn.ryzerobotics.com/downloads/tello/20180910/Tello%20SDK%20Documentation%20EN_1.3.pdf
やっていることはPython版と同じく、外部のテキストファイルに記述されたコマンドを順次telloに送ってステータスを受信しているだけです。
実は、コマンドの実行結果を受け取る前に次々にコマンド送ってるから、スプールされてしまっているようだから、作りが変だとは思う。
コードはこちら、
https://github.com/chateight/c_plus_video
ソケット通信の基本の解説は、
https://qiita.com/Michinosuke/items/0778a5344bdf81488114
通信サンプルは、
https://qiita.com/srs/items/c9286b5cff99e741b993
c++での制御は、すでに先駆者がいるから、この先はこれを使った方がいいでしょう。
https://github.com/carlospzlz/ctello
P.S. 2022/11/5
これはTello EDU用でした、違いを修正してもいいかもしれないけど。
動作は他の手段で動かすのと同じ。
admin
これも今更感ですが、
<やりたいこと>
デスクトップにファイルを作って、それをダブルクリックしたらpythonのコマンドを実行するようにしたい。
<手順>
tello.commandを作成、拡張子commandが重要
<tello.commandの中身>
先頭にシェルを指定、それ以下に実行させたいコマンドを記述、
#!/bin/bash
/Users/xxx/opt/anaconda3/envs/tello-p/bin/python /Users/xxx/Desktop/Tello-Python/PY3_Tello_videop/main.py
カレントディレクトリの保証がないので、フルパスで記述しています。
<ファイルに実行権を付与>
% chmod u+x tello.commandこれでデスクトップ上のファイルをダブルクリックすれば実行されます。
admin
ほぼ一年前に拡張(クラッシュ対応)してましたが、ディスク使用率が8割近くになったので再度の拡張。
https://isehara-3lv.sakura.ne.jp/blog/2021/09/27/ubuntuクラッシュとパーティション拡張/
VMwareの”仮想マシン” -> ”設定” -> “取り外し可能デバイス” -> “ハードディスク”を選んで、スライドバーで容量増やします。バスタイプSCSIになってますが、これでも問題無いようです、仮想だから?
Ubuntuのメニューで領域拡張。
これで使用率が3割になったので、おそらくのMac寿命まで持つんじゃないか。仮想ディレクトリはcondaのデフォルトになってます。
admin
以下の記事中で、
https://isehara-3lv.sakura.ne.jp/blog/2022/10/28/telloで画像転送python-h-264共用ライブラリ/
c++のライブラリをPythonから呼び出すためにpybind11のインストールが指定されていますが、c++ライブラリのラッパーファイル(h264decoder_python.cpp)を見てみると、pybind11ではなくてBOOST_PYTHONが使われているからpybind11は不要だよねと思いました。
BOOST_PYTHON_MODULE(libh264decoder)試しに、仮想環境(v_python)からpybind11をpip uninstall pybind11しても動作はするから、やはり不要らしい。
Boost.Pythonをpybind11と比較するとサイズが巨大らしい。pybind11の方が後発だから、恐らく機能的には優っているだろうしユーザーも多いのではないかと思います。
P.S. 2022/10/31
H.264 decoderのビルドのためのCMakeLists.txtを見てみるとpybind11を探して、もし存在しなければ持ってきてるからビルドには必要とされているようです、何故だろう?
find_package(pybind11)
if(pybind11_FOUND)
message("Using existing pybind11 v${pybind11_VERSION}")
else()
message("Fetching pybind11")
include(FetchContent)
FetchContent_Declare(
pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11
GIT_TAG v2.5.0)
FetchContent_MakeAvailable(pybind11)
endif()P.S. 2022/11/7
今更ながらですが、改めて見るとpybind11使ってました。じゃ最初のソースは何見たんだろう?とりあえずすっきりはしましたが、
PYBIND11_MODULE(h264decoder, m)
{
PyEval_InitThreads(); // need for release of the GIL (http://stackoverflow.com/questions/8009613/boost-python-not-supporting-parallelism)
py::class_(m, "H264Decoder")
.def(py::init<>())
.def("decode_frame", &PyH264Decoder::decode_frame)
.def("decode", &PyH264Decoder::decode);
m.def("disable_logging", disable_logging);
}
admin
以下でコマンドは送信できましたが、画像の受信には追加の手段が必要になります。
https://isehara-3lv.sakura.ne.jp/blog/2022/10/26/dji-telloはudpでテキストコマンド送れば制御できる/
コマンド/レスポンスと画像転送はポートが分かれています、ある意味当然。
DJIのリンクにもH.264デコーダーは掲載されてますが古すぎて(四年前)動かない、そもそもがPython2.x系用だし。
で、環境に合わせてビルド必要ですが、以下のサイトがよくまとまっています。
Windws/Linux/Mac(intel/mx)と全てのプラットホームが解説されています。
https://take6shin-tech-diary.com/tello-video-python3/
<動作環境>
・intel Mac ventura
・Python3.9(環境はAnacondaで構築)
ビルドされたライブラリのディレクトリは、
c++をMacのPythonから呼び出すという情報が名称に含まれています。
<動作させてみる>
ドローンは飛行させなくても、画像は送られてくるので最初の画像はTelloの梱包箱。
UIもPythonのライブラリ(tkinter)使って作られます。
次はopencv使って、画像認識らしいことをやらせてみることでしょう。
admin
condaが挙動不審、
conda installを実行すると、
% conda install anaconda-clean
# >>>>>>>>>>>>>>>>>>>>>> ERROR REPORT <<<<<<<<<<<<<<<<<<<<<<
Traceback (most recent call last):
File "/Users/usamiryuuichi/miniforge3/lib/python3.10/site-packages/conda/exceptions.py", line 1129, in __call__
return func(*args, **kwargs)
以下省略〜〜と言われて実質何もできなくなったから。仮想ディレクトリでも同じだし、そもそも中身を変更するようなコマンドは全滅で、新しい仮想ディレクトリも作れないからデッドロック状態。
それゆえNASのTimemachineバックアップから、
miniforge3ディレクトリを復元したらとりあえず復旧したようです。ディレクトリ復元だけではうまくいかない場合もあるでしょうが、今回は問題なくということでしょう。
原因は恐らくbasicディレクトリでpipインストールしたからの可能性が一番高い。
admin
TelloにはDJIの提供する標準のアプリもありますが、Tello自体はテキストコマンドで制御できる、つまり専用のドライバなどは不要、ということで簡単にカスタムアプリができます。
UDP/ポート8889でソケット接続すれば、ドライバ不要でテキストモードでコマンド送信とレスポンス受信ができます。
<コマンド一覧>
SDK
The Tello SDK connects to the aircraft through a Wi-Fi UDP port, allowing users to control the drone with text commands
https://alfredo-reyes-montero.gitbook.io/tello-dji/sdk
<サンプル>
以下のサンプルプログラムを持ってきて、
https://github.com/dji-sdk/Tello-Python
Python2.7なので一部3形に書き換え必要なので書き換えて、
https://github.com/chateight/tello_python
に置いてあります、Python3への変換(except文とprint文)は機械的にできます。
コマンドはテキストファイル(以下ではcommand.txt)で一番単純であろうコマンドを定義して、
command
takeoff
delay 1
land
最初のcommand文はAPIモードに入る宣言として必要です。
<実行結果>
コマンドの引数でコマンドファイル(command.txt)を指定します。
% python tello_test.py command.txt
sending command: command to 192.168.10.1
from ('192.168.10.1', 8889): b'ok'
Done!!! sent command: command to 192.168.10.1
sending command: takeoff to 192.168.10.1
from ('192.168.10.1', 8889): b'ok'
Done!!! sent command: takeoff to 192.168.10.1
delay 1.0
sending command: land to 192.168.10.1
from ('192.168.10.1', 8889): b'ok'
Done!!! sent command: land to 192.168.10.1
Traceback (most recent call last):
File "/Users/xxxxxx/github/tello_python/tello_test.py", line 28, in
out = open('log/' + start_time + '.txt', 'w')
FileNotFoundError: [Errno 2] No such file or directory: 'log/2022-10-26 13:06:37.254305.txt'
ログファイルができてないと言われてますが、それはlogディレクトリ作成してないからで、logディレクトリ作成するときちんとログが取れました。
id: 0
command: command
response: b'ok'
start time: 2022-10-26 14:27:31.283580
end_time: 2022-10-26 14:27:31.309985
duration: 0.026405
id: 1
command: takeoff
response: b'ok'
start time: 2022-10-26 14:27:31.310001
end_time: 2022-10-26 14:27:38.808229
duration: 7.498228
id: 2
command: land
response: b'ok'
start time: 2022-10-26 14:27:39.813307
end_time: 2022-10-26 14:27:42.531767
duration: 2.71846
ソケットで接続すれば良いだけなので、言語はPythonに限らず今時の言語ならなんでもつながるということになるので、ライブラリ次第で使い分けでしょう。
例えば、ScratchのTello拡張だと、Node.js使ってソケット接続しています。
TelloのEDUモデル(編隊飛行だけでなく)だとクライアントモードでつながるので、クラウドサービス(例えばGoogle TM)を使った画像認識とかもできますね。EDUモード買えばよかった。
admin