Ubuntu Weekly Recipe

第589回M5StickVの開発用にMaixPy IDEをUbuntuで動かす

第587回ではRISC-Vベースの⁠AIoTカメラ⁠であるM5StickVの使い方を紹介しました。今回はM5StickV向けアプリケーションを開発する上で、あると便利なIDEの使い方を紹介しましょう。

MaixPy IDEとは

第587回でも紹介したように、M5StickVはFreeRTOSの上でPythonが動いています。このPythonの実装が、MicroPythonベースのMaixPyです。MaixPyにはM5StickVのハードウェア関連のライブラリも取り込まれていますので、開発者は原則としてMaixPy/Pythonを用いてアプリケーションを作ることになります。

一般的な開発者であれば「自分の好みのエディター・開発環境」があるはずです[1]⁠。Pythonである以上、どのエディターでも問題にはならないでしょう。もちろん「公式が推奨するIDE」といった抽象的な選択肢もまた、⁠自分の好み」の範疇です。ただし普通のテキストエディターをテキストエディットの機能だけ使うのであれば、M5StickVの開発は若干手間がかかるかもしれません。なぜなら作ったコードをテストしようとしたら、microSDカードに保存し、M5StickVに接続し、M5StickVをリセットする必要があるためです。

ひとつの解は第587回の最後に紹介したMircopython-Editorを使う方法です。要するにM5StickVの実行環境上でテキストエディターを動かし、シリアルコンソール経由でエディットする方法です。実行環境上のファイルをちょっと変更したい場合は便利ですが、より本格的に開発しようとなるといろいろ機能不足な感は否めません。

そこで出てくるのが、今回紹介するMaixPy IDEです。GUIベースのIDEには、Pythonスクリプトの編集・実行機能、簡易的なコード保管機能、シリアルコンソールの取得に加えて、実行時カメラのライブ映像やカラーヒストグラムの表示まで備わっています。

図1 カメラの映像まで表示してくれる
画像

もともとはカメラ搭載マイコン「OpenMV」向け開発環境OpenMV IDEを、M5StickVをはじめとするSiPEED製品用に作り直したものです。OpenMV IDE自身はQtCreatorがベースになっているようです[2]⁠。

MaixPy IDEのダウンロードと実行

MaixPy IDEはM5StickV Quick Startの「MaixPy IDE」からインストーラーバイナリをダウンロードできます。2019年10月5日時点での最新版は「v0.2.4」です。プルダウンメニューから「linux-x86_64-0.2.4.run」を選択してダウンロードしてください。ちなみに120MBほどあります。

ダウンロードしたら実行権限を付けて実行しましょう。端末を開いて次のように実行します。

$ cd ~/ダウンロード
$ chmod +x maixpy-ide-linux-x86_64-0.2.4.run
$ ./maixpy-ide-linux-x86_64-0.2.4.run

GUIのみで行いたい場合はファイルブラウザーから該当ファイルを右クリックし、プロパティの「アクセス権」タブにある「プログラムとして実行可能」にチェックを入れて閉じます。再び右クリックすると「実行」が表示されるので、それを選択してください。

インストール手順自体は単に「次へ」を押していくだけです。

図2 インストールウィザードの開始
画像
図3 インストール先の設定(500MB程度の空きが必要)
画像

表示上は390MBになっていましたが、インストール後にduコマンドで見ると521MBでした。

図4 使用許諾への同意
画像
図5 インストールの開始
画像
図6 進捗状態の表示
画像
図7 インストールの完了とMaixPy IDEの起動
画像

インストールが完了したらMaixPy IDEを起動します。ちなみにMaixPy IDEの中からM5StickVのシリアルコンソールに接続するため、実行者の権限で/dev/ttyUSB0などへのアクセス権が必要です。たとえば第587回で紹介しているようにdialoutグループに所属しておいてください。

端末から直にMaixPy IDEを起動するなら、次のように実行します。

$ ~/maixpyide/bin/maixpyide

うまく起動できるようなら第433回のように.desktopファイルを作っておくとよいでしょう。

MaixPy自体は非常にシンプルな画面です。ファイルを選択して、それを編集し、実機上で実行する、それだけです。

図8 MaixPy IDEの基本画面
画像

初回起動時はあらかじめターゲットボードを選択しておいてください。⁠ツール」「Select Board」から「M5StickV」を選びます。

図9 ターゲットボードの選択
画像

次にM5StickVをPCに接続し、MaixPy IDEから操作できるよう接続します。具体的には画面左下の緑色の鎖アイコンをクリックしてください。うまく行けば赤色のアイコンに変わるはずです。

図10 ターゲットボードの接続
画像

選択しているPythonスクリプトを実行するには、画面左下の再生ボタンを押します。うまく動作すればカメラの映像が「フレームバッファ」に表示され、さらにカメラの映像に合わせてヒストグラムが変化するはずです。

図11 スクリプトの実行

画像

画面中のスクリプトはprint(clock.fps())とFPSの値を標準出力に表示しています。画面下の「シリアルターミナル」を選択すると、標準出力の内容を表示するウィンドウが現れます。

図12 シリアルターミナルの表示
画像

これでMaixPy IDEによる開発環境が整いました。あとは「いい感じ」のPythonスクリプトを書くだけですね。

シリアルコンソールが必要なGUIアプリをLXDで動かす

MaixPy IDEはインストーラー・実行環境ともにバイナリでのみ提供されているように見えます[3]⁠。どのようにビルドされたか不明なバイナリを、ホスト上で直接実行することに、そこはかとない不安を感じる人もいるかもしれません。

そこで今回は、MaixPy IDEをLXDコンテナ上で動かす方法も紹介しましょう。LXD上でGUIアプリケーションを動かす方法はこれまでにも、Scratch 2.0をLXD上で動かした第416回VivaldiをLXD上で動かした第420回Windows版のKindleをLXD上のWineで動かした第433回で紹介してきました。これらはいずれも「X転送 over SSH」を利用して実現しています。今回はより効率的なX用のUnixドメインソケット/tmp/.X11-unix/X0をホストとコンテナで共有する方法を解説します。

さらにM5StickVのようなホットプラグ可能なUSBシリアルコンソールをコンテナと共有する方法も合わせて紹介します。

あらかじめ次のようにMaixPy IDE用のコンテナを「maixpy」の名前で作成しておきます。LXDそのもののインストールや使い方については第521回を参照してください[4]⁠。

$ lxc launch ubuntu:18.04 maixpy
Creating maixpy
Starting maixpy

GUIコンテナを作成する

今回の記事でいう、⁠GUIコンテナ」とはホストとコンテナでX Window SystemのUnixドメインソケットを共有するコンテナを意味します。つまりホスト上ではXサーバーが動作していることが前提となります。さらにコンテナの中で動かせるのはX Window Systemに対応したアプリケーションのみです。Waylandオンリーなアプリケーションは今回の方法だけでは動作しませんので注意してください。GPUデバイスは共有しますので、コンテナに関連ライブラリーさえインストールされていれば、GPUアクセラレーションは機能します。

X Window SystemのUnixドメインソケット/tmp/.X11-unix/X0はディスプレイマネージャーでログインした際のアカウントで作成されます。よってホストとコンテナでこのUinxドメインソケットを共有する場合は、コンテナの内外で同じUIDである必要があります。

$ ls -l /tmp/.X11-unix/X0
srwxrwxrwx 1 shibata shibata 0 10月  5 15:25 /tmp/.X11-unix/X0

ホストとコンテナの間でUIDを一致させる方法は第479回に記載しています。とりあえずUbuntuコンテナ上の初期ユーザー「ubuntu」のUIDとGIDをそれぞれホストのインストール時に作成したユーザーのUID・GIDと同じ1000に設定したい場合は、次のコマンドを実行してください。

$ lxc config set maixpy raw.idmap 'both 1000 1000'

これはコンテナの再起動後から反映されます。しかしながら他にも設定項目があるので、先にそれを行ってしまいましょう。

Xアプリケーションを動かすためには、環境変数DISPLAYが設定されている必要があります。これは通常はGUIログイン時に自動的に設定されるものです。LXDのGUIコンテナの場合、GUIログインはしないので明示的に指定する必要があります。普通に目の前のPCに自分自身のみがログインしているケースだとDISPLAYには:0が設定されているはずなのでハードコードしてしまいましょう。

$ lxc config set maixpy environment.DISPLAY ':0'

次にホスト上の/tmp/.X11-unix/X0をコンテナからもアクセスできるようにします。ちなみにこのX0の部分もログイン状態で変わりえます。LXDの文脈で言うdiskデバイスタイプで追加すると、コンテナからもアクセスできるようになります。

$ lxc config device add maixpy X0 disk path=/tmp/.X11-unix/X0 source=/tmp/.X11-unix/X0

コンテナのgpuデバイスタイプを利用すると、ホストのGPUデバイスにコンテナからもアクセスできます。GPUのアクセラレーション機能を使いたいなら必須です。これも追加しておきましょう。

$ lxc config device add maixpy gpu gpu

さらにX Window Systemアプリケーションを動かすために、必要なライブラリー群をインストールします。

$ lxc exec maixpy apt update
$ lxc exec maixpy -- apt install -y x11-apps x11-xserver-utils mesa-utils

最後にUIDとGIDのマッピングを反映させるために、インスタンスを再起動しておきます。

$ lxc restart maixpy

シリアルコンソールデバイスファイル名を固定化する

次にシリアルコンソールのデバイスファイル名を固定化します。LXDではホスト上のデバイスファイルをそのままコンテナに見せることが可能です。その際、デバイスファイル名を指定するのですが、シリアルコンソールデバイスはその認識順によって自動的に名前が割り振られます。このためM5StickVのようなUSBシリアルケーブルを使う場合、ケーブルをPCに繋いだタイミングによって/dev/ttyUSB0だったり/dev/ttyUSB1だったりと最後の数字が変わってしまうのです。

毎回違うファイル名になってしまうのは不便なので、固定的なデバイスファイル名を付けてしまいましょう。それには第555回で紹介したudevが役に立ちます。

試しにM5StickVを繋いだ状態で、次のコマンドを入力し、USBデバイスの属性を表示させてみてください。この例のttyUSB0も、他のUSBシリアルコンソールが接続されている場合は別の名前になるので注意してください。

$ udevadm test-builtin usb_id /sys/class/tty/ttyUSB0
Load module index
Parsed configuration file /usr/lib/systemd/network/99-default.link
Created link configuration context.
ID_VENDOR=Kongou_Hikari
ID_VENDOR_ENC=Kongou\x20Hikari
ID_VENDOR_ID=0403
ID_MODEL=M5Stack_Intf
ID_MODEL_ENC=M5Stack\x20Intf
ID_MODEL_ID=6001
ID_REVISION=0400
ID_SERIAL=Kongou_Hikari_M5Stack_Intf_9952499745
ID_SERIAL_SHORT=9952499745
ID_TYPE=generic
ID_BUS=usb
ID_USB_INTERFACES=:ffffff:
ID_USB_INTERFACE_NUM=00
ID_USB_DRIVER=ftdi_sio
Unload module index
Unloaded link configuration context.

「Kongou Hikari」とはなんぞやというのが気になるところではありますが、今回使うのはID_SERIAL_SHORT=9952499745です。

一般的にUSBデバイスを特定する際は、ID_VENDOR_IDID_MODEL_IDなどを利用します。しかしながら上記の0403:6001はFTDIの「FT232 Serial (UART) IC」として登録されているIDです。つまりID_VENDOR_IDID_MODEL_IDで確認すると、他のFTDI製チップを搭載したUSBシリアルデバイスまでマッチしてしまいます。

よってここではID_SERIAL_SHORT=9952499745を用いて確実に特定のデバイスのみをマッチングさせることにしましょう。この値は、各M5StickVで異なるはずですので、それぞれ上記コマンドで確認した値に読み替えてください。

実際に作るデバイスファイルは/dev/ttyUSBxへのシンボリックリンクとなる/dev/ttyM5STICKVです。複数のM5StickVを同時に繋ぐのなら、シリアル番号ごとに名前を変更してください。udevの設定を行うために、ホスト上で次のコマンドを実行します。

cat <<EOF | sudo tee -a /etc/udev/rules.d/68-m5stick.rules
## For M5StickV
ACTION=="add", SUBSYSTEM=="tty", \\
    ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \\
    ATTRS{serial}=="9952499745", SYMLINK+="ttyM5STICKV"
EOF

この状態でM5StickVを接続すると、次のようなファイルが作られるはずです。

$ ls -l /dev/ttyM5STICKV
lrwxrwxrwx 1 root root 7 10月  6 21:13 /dev/ttyM5STICKV -> ttyUSB0

シリアルコンソールデバイスをコンテナから見えるようにする

M5StickVの接続によって自動的に作成されるようになった/dev/ttyM5STICKVをコンテナから見えるように設定しましょう。

$ lxc config device add maixpy ttyM5STICKV unix-char \
  source=/dev/ttyM5STICKV path=/dev/ttyUSB0 \
  required=false uid=1000 gid=1000
Device ttyM5STICKV added to maixpy

シリアルコンソールデバイスはキャラクターデバイスとして作られるためunix-charを指定しています。また、コンテナから見える名前は/dev/ttyUSB0にしています。これはMaixPy IDEがどうやら/dev/ttyUSBxしか見ていないような振る舞いをしているためです。

required=falseはUSBデバイスのようなホットプラグ可能なデバイス向けのオプションです。つまりコンテナ起動時に指定したデバイスが存在しなくてもエラーにしないための設定となります。UIDやGIDを設定しているのは、コンテナ内の一般ユーザーがシリアルコンソールを読み書きできるための対応です。

設定後の再起動は不要です。最後に実際にM5StickVを接続した状態で、コンテナ内部から/dev/ttyM5STICKVが見えるか確認しておきましょう。

$ lxc exec maixpy ls /dev/ttyM5STICKV
/dev/ttyM5STICKV

MaixPy IDEのインストール

ここまででようやくMaixPy IDEの準備は整いました。あとはホストと同じようにインストーラーを実行するだけです。

ダウンロード済みのインストーラーイメージをコンテナの中にコピーして、lxc execコマンドで実行しましょう。ポイントはsudoコマンドを使って一般ユーザー、Ubuntuコンテナをそのまま使っているなら「ubuntu」で実行していることです。

$ lxc file push ~/ダウンロード/maixpy-ide-linux-x86_64-0.2.4.run maixpy/home/ubuntu/
$ lxc exec maixpy -- sudo -i -u ubuntu ./maixpyide/bin/maixpyide

GUIコンテナとして正しく設定できていれば、ホスト上のディスプレイにインストーラーのダイアログが表示されます。もしうまく起動しない場合は、たとえばlddコマンドで必要なライブラリーがコンテナ上に揃っているか確認してください。また、インストール後は~/maixpyide/bin/maixpyidelxc execしましょう。M5StickV上でのスクリプトの実行も含めてきちんと動作することを確認したら、第433回のように.desktopファイルを作ると良いでしょう。

おすすめ記事

記事・ニュース一覧