Jetson NanoでFPVラジコンを作る(10)
この記事のコードは以下のGitリポジトリに公開している。(リポジトリ名変更済)
前回まででJetsonへの入出力に関するコードは書いたので、あとはこのように結合するだけである。
class RCCarServer : public RCCarControllerListener { public: RCCarServer() : controller("/dev/input/event2", *this, stop_controller_thread){} ~RCCarServer() = default; int start() { return controller.listen(); } void on_connect() override { std::cout << "controller connected" << std::endl; }; void on_change_steering(float value) override { driver.steer(value); } void on_change_accel(float value) override { if(is_going_back) { driver.back(value * 0.3f); } else { driver.go(value * 0.2f); } } void on_change_back(int value) override { if(value) { is_going_back = true; } else { is_going_back = false; } } void on_close() override { std::cout << "controller disconnected" << std::endl; } private: RCCarDriver driver; RCCarController controller; bool is_going_back = false; };
のようなクラスを作って以下のように使用するだけ。
int main(int argc, const char *argv[]) { //snip RCCarServer server; std::cout << "starting server..." << std::endl; server.start(); std::cout << "server started" << std::endl; pause(); std::cout << "terminating server..." << std::endl; return 0; }
ちなみにコントローラの入力値をそのまま駆動モーターに伝えてしまうと速度が出過ぎるので、ゲインは適当に下げてある。
ということでめでたくタミヤのラジコンがFPVで操作できるようになった。
のだが、実際に操作してみるとやはり画角が狭い。(下の動画は以前撮影したもの)
実はmomoで以下の広角ラズパイカメラを認識しなかったため、今までは仕方なくWebカメラを使用していた。
改めて調べてみたところ以下のツイートが見つかった。
mobile.twitter.comjetsonでCSIカメラをmomoで使うには、
— alarky (@alarky1) May 6, 2020
gstreamerでRG10→NV12→I420に変換して仮想L4V2デバイスに流しながら、
momoでは仮想側のデバイスを読めば使えた
情報を辿っていくとやり方がここに書いてあった。
ラズパイカメラはRG10というピクセルフォーマットを使用しているが、momoはこのピクセルフォーマットに対応していない。
そこでv4l2loopbackというkernel moduleを使用して仮想ビデオデバイスを作成し、このデバイスにRG10から変換したI420の映像を流し込むことでmomoが認識するらしい。
まず、ラズパイカメラをラジコンに取り付ける。
以前使用した1.7mmの透明プラバンと、東急ハンズで調達したL字のアクリル棒を加工してカメラ固定用のプレートを作成し、このプレート経由でカメラをベースプレートに固定した。車体にきちんと収めるための位置決めと、カメラ固定用プレートにフレキケーブルを通すための長方形の穴を加工するのに難儀した。
ボディを取り付けてもきちんと収まっている。
次にソフトウェア側の作業をする。
まずv4l2loopbackのビルド・インストール・有効化を行う。
$ git clone https://github.com/umlaeute/v4l2loopback.git $ cd v4l2loopback $ make && sudo make install $ sudo depmod -a $ sudo modprobe v4l2loopback exclusive_caps=1
これでまず仮想ビデオデバイスが見えるようになる。
$ ls /dev/video* /dev/video0 /dev/video1
video0
というのがラズパイカメラで、v4l2loopbackによりvideo1
という仮想ビデオデバイスが追加されている。
ここで上記の情報の通りgstreamerのコマンドを実行し、ラズパイカメラの映像をRG10->I420に変換し、/dev/video1
に流し込む*1。ついでに解像度を落として画面を180°回転*2させている。
$ sudo /usr/bin/gst-launch-1.0 -v nvarguscamerasrc ! 'video/x-raw(memory:NVMM), format=NV12, width=1280, height=720, framerate=30/1' ! nvvidconv flip-method=2 ! identity drop-allocation=1 ! 'video/x-raw, width=1280, height=720, format=I420, framerate=30/1' ! v4l2sink device=/dev/video1
こうすると、/dev/video1
がI420(YU12)の入力デバイスとして見えるようになる。
$ v4l2-ctl -d 1 --all Driver Info (not using libv4l2): Driver name : v4l2 loopback Card type : Dummy video device (0x0000) Bus info : platform:v4l2loopback-000 Driver version: 4.9.201 Capabilities : 0x85208003 Video Capture Video Output Video Memory-to-Memory Read/Write Streaming Extended Pix Format Device Capabilities Device Caps : 0x05208003 Video Capture Video Output Video Memory-to-Memory Read/Write Streaming Extended Pix Format Priority: 2 Video input : 0 (loopback: ok) Video output: 0 (loopback in) Format Video Capture: Width/Height : 1280/720 Pixel Format : 'YU12' Field : None Bytes per Line : 1280 Size Image : 1382400 Colorspace : sRGB Transfer Function : sRGB YCbCr/HSV Encoding: ITU-R 601 Quantization : Limited Range Flags : Format Video Output: Width/Height : 1280/720 Pixel Format : 'YU12' Field : None Bytes per Line : 1280 Size Image : 1382400 Colorspace : sRGB Transfer Function : sRGB YCbCr/HSV Encoding: ITU-R 601 Quantization : Limited Range Flags : Streaming Parameters Video Capture: Frames per second: 30.000 (30/1) Read buffers : 2 Streaming Parameters Video Output: Frames per second: 30.000 (30/1) Write buffers : 2 User Controls keep_format 0x0098f900 (bool) : default=0 value=0 sustain_framerate 0x0098f901 (bool) : default=0 value=0 timeout 0x0098f902 (int) : min=0 max=100000 step=1 default=0 value=0 timeout_image_io 0x0098f903 (bool) : default=0 value=0
ここでmomoを以下のパラメーターで起動すると、めでたくmomo経由で映像が見えるようになる。
$ sudo /opt/lunchjet/momo/momo --hw-mjpeg-decoder=false --video-device /dev/video1 --no-audio-device test
ハマったのは--hw-mjpeg-decoder=false
という部分で、これがないとエラーでmomoが立ち上がらない。
原因がわからずに結局momoのソースまで確認したのだが、最近のmomoのJetson用ビルドではデフォルトで--hw-mjpeg-decoder=true
となっており、この場合には対応ピクセルフォーマットがJPEGかMJPEGのみとなるようだ。
これでめでたくシステムの全機能が開通した。 システム構成は以下になった。
ゲームパッドでラジコンを操作している様子は以下。
少しアクセルの遊びが大きい気もするが、特に問題はない。
実際に走行させてみた。
しばらく運転して遊んでみたが、やはり視野が広い(視野角160°)ので運転しやすい。
レーサータイプのラジコンに比べおそらく視点がだいぶ高いせいか、思ったよりスピード感はない気もした。
というわけで、「Jetson NanoでFPVラジコンを作る」シリーズはこれでおしまい。
次回以降は改題して自動運転にぼちぼち取り組むつもりである。
前回までの記事
Jetson NanoでFPVラジコンを作る(1) - 自由課題
Jetson NanoでFPVラジコンを作る(2) - 自由課題
Jetson NanoでFPVラジコンを作る(3) - 自由課題
Jetson Nanoを使ってFPVラジコンを作る(4) - 自由課題
Jetson Nanoを使ってFPVラジコンを作る(5) - 自由課題
Jetson Nanoを使ってFPVラジコンを作る(6) - 自由課題
Jetson Nanoを使ってFPVラジコンを作る(7) - 自由課題
Jetson NanoでFPVラジコンを作る(8) - 自由課題
Jetson NanoでFPVラジコンを作る(9) - 自由課題