Help us understand the problem. What is going on with this article?

多様な入力デバイス(HID)からTHETAを操れるようにする

お知らせ

2019/07/05

お待たせいたしました!
この記事で作成したプラグインが THETAプラグインストアに公開されました!
画像をクリックしていただくか、画像したのURLをクリックして頂くとストアへ行けます!

決定アイコン.png

https://pluginstore.theta360.com/plugins/skunkworks.hid/

このTHETAプラグインは「RICOH Plug-ins」というRICOH公式プラグインではなく、「Partner Plug-ins」という一般の皆様と同じカテゴリにて提供しています。
私たちのチーム名を「SKUNK WORKS」といたしました。
「SKUNK WORKS」では、ちょっと荒削りな段階であっても実験的なこころみのプラグインを提供していきたいとおもっています。
今後ともよろしくお願いいたします!

はじめに

リコーの @KA-2 です。

弊社ではRICOH THETAという全周囲360度撮れるカメラを出しています。
RICOH THETA Vは、OSにAndroidを採用しています。Androidアプリを作る感覚でTHETAをカスタマイズすることもでき、そのカスタマイズ機能を「プラグイン」と呼んでいます(詳細は本記事の末尾を参照)。

RICOH THETA Vは前述のようなシステム構成ですので、OSにAndroidを使用しているスマートフォン/タブレット/ボードコンピューターなどと同様に、キーボードやマウスに代表されるHID(Human Interface Device)を接続して使用することができます。

01_タイトル画像.jpg

※動作させている様子などを動画にしました。画像をクリックするとyoutubeへ飛びます。
Twitterより詳しい動画です!

HIDには有線・無線を問わず多様なものが世の中に出回っています。
それらの中には、「フィンガープレゼンター」などと呼ばれる 指輪のように小型で、ボタン数が少ないキーボードがいくつか存在し、比較的お安く購入できます。
パソコンに接続してスライドのページを送ったり戻したりするリモコン的な道具なのですが、これが自撮棒のグリップにピッタリ取り付けられたのが今回紹介するプラグインを作成したきっかけです。

02_フィンガープレゼンター.jpg

このような小型の入力装置でもボタンが複数ありますので、

  • 撮影だけでなく、撮影に便利そうな複数の振る舞いを用意する。
  • ユーザーがお好みのボタンにお好み振る舞いを割り当てられる。
    (≒1つのプラグインで多種類の機器に対応できる)

という要素も盛り込み。
さらに、THETA本体の各ボタンも内部ではHIDと同列に扱えるようになっているということも考慮しまして、

  • 接続した外部入力装置だけでなく、本体ボタンの役割も変えられる。

というようなプラグインに仕立ててみました。
“RICOH THETAのAndroidみ”を感じて頂けるのではないかと思います。
(Androidなのに"Androidみ"・・・というのもなんなのですけれども)

1つの仕組み(1つのプラグイン)から多様な応用が利いたため、長編記事となっています。
事例を複数試したので、類似のことを異なるHIDで行う際、みなさまが出会うであろう小さなトラブルを一通り網羅できたのではないかと思われます。トラブルシュート的にもご利用いただけると幸いです。

HIDについてちょっと補足(今回の適用範囲)

HIDには「USB Host(USBポート)」に物理的に接続するもの、「Bluetooth」や「BLE」で本体と無線接続するものがありますが、今回はUSB Hostに接続するHIDに限定します。

USB Hostに接続するHIDにも、有線でダイレクトに接続するものだけでなく、USBドングルタイプのレシーバーを接続する無線タイプのものがあり、これらはまるっとどちらも対象としていますのでご安心を。
USBドングルタイプのレシーバーを取り付けた姿はこんな感じです。こちらで紹介したようなUSBホストケーブルだけでなく、小型のUSB OTG対応アダプタもありますので、レシーバーの写りこみもありませんし、ペアリングのわずらわしさもありません。エクステンションアダプター TE-1との相性も良いです。

03_レシーバー接続.jpg

上記よりも小さなUSB OTG対応アダプタもあります。TypeAコネクタの中に埋まってしまう!

03_レシーバー接続2.jpg

「Bluetooth」や「BLE」の"HIDについては"、2019年2月時点 RICOH THETA Vが対応していないため対象外としています。(スマートフォン用にSDKなどが公開されているBLE機器は取り扱えます)

余談となりますが、HIDは、同じようにUSB Hostに接続する「シリアル通信」で生じたようなパーミッションの諸事情がありません。今回作成したプラグインを、開発者ではない一般の皆様にもお使いいただけるよう、プラグインストアへ公開準備中です。
→ ストア公開いたしました! お知らせ 2019/07/05をご参照ください。

キーに割り当て可能としたTHETA側の振る舞い

「はじめに」の章で「撮影に便利そうな複数の振る舞いを用意」と記載していましたが、具体的にどのような振る舞いを用意したのかを説明しておきます。
以下7種類の動作が基本です。

  1. 撮影(静止画モード:takePicture, 動画モード:録画の開始/停止)
  2. 無線LANの切り替え(OFF/AP mode/CL mode)
  3. 静止画/動画モードの切り替え
  4. タイマーの設定
  5. 露出補正の設定
  6. 通常通知音の音量設定
  7. 発話音量の設定

「1.」「2.」「3.」については、プラグインを使わない状態と同じ動作を行えるようにするために実装しました。特に「1.」について、THETAプラグインSDKと共に公開されているサンプルコードでは静止画に限定した撮影トリガしかかけられません(静止画撮影後に画像処理を行うケースで便利な雛型としたため)。今回作成した動画モードにも対応した撮影トリガー特化の処理は、他のプラグインを作成する際の部品としての需要があるかもしれないという配慮もあります。

「4.」「5.」については、スマートフォンなしでリモート撮影するにあたり、便利そうな機能となるのですが、操作に応じて状態が変わったことを本体LEDなどで視覚的にお知らせする術がありません(プラグイン起動中は、カメラ状態ランプが白に維持されるためタイマーの状態もわかりません)。
HIDでのリモート操作は、過去に作成したシリアル通信のリモート操作とは異なり、THETA本体からのフィードバックが得られず、指示を一方的に送りつけるだけなので、HID側でなにかを表示させることも不可能です。
そこで、「THETAプラグインでマイクを使って録音する」の記事を参考にして設定値を読み上げてユーザーにお知らせすることにしました。本当は、「THETA をおしゃべりにする」の記事のようにText To Speachで実装するほうが、沢山の音声ファイルを用意する必要もなく便利なのですが・・・ライブラリを使う際の技術的ではない諸事情を避けさせて頂きました。

「6.」についてはプリセットされている音(動画記録開始とおなじピコという音)を鳴らしてお知らせします。
「7.」については、前述の理由により発話によるユーザーインターフェースを用意したので、それにあわせて音量の選択肢を設けてみました。「発話音量 変更」というサンプルを鳴らして、音量変更結果を確認できるようにしています。

これらはユーザーによって、

  • 1ボタン操作したら必ず、対応した状態になって欲しい場合
  • ボタン数に限りがあるので1つのボタンを押すたびに状態をトグルさせたい場合
  • 操作する度に値を1段階増やしたり減らしたりしたい場合

と好みがわかれるであろうことも考慮して、操作ボタンに対応する振る舞い(アクション)を以下27通りから選び設定することができるようにしました。

No. アクションの名称 説明 Simple View Advanced View
0 NOP 無処理(割り当てを無くすときに使用します) 選択可 選択可
1 EXEC_SHUTTER 静止画モード時:撮影:動画モード時:開始/停止 選択可 選択可
2 TGGLE_WLAN wlanの状態を off->APモード->CLモードでトグルさせます 選択可 選択可
3 TGGLE_CAPTURE_MODE 撮影モードを 静止画<->動画 でトグルさせます 選択可 選択可
4 TGGLE_EXP_DELAY タイマーを OFF<->OFF以外の最終設定値 でトグルさせます 選択可 選択可
5 TGGLE_CAMERA_VOL 各種カメラ音量を OFF->中->大 とトグルさせます 選択可 選択可
6 TGGLE_SPEECH_VOL 発話音量を OFF->中->大 とトグルさせます 選択可 選択可
7 SET_EV_ZERO 露出補正値をゼロにします 選択可 選択可
8 SET_EV_PLUS 露出補正値を現在の値から+0.3します 選択可 選択可
9 SET_EV_MINUS 露出補正値を現在の値から-0.3します 選択可 選択可
10 SET_EXP_DELAY_OFF タイマーをOFFにします 選択可 選択可
11 SET_EXP_DELAY_1 タイマーを1秒にします - 選択可
12 SET_EXP_DELAY_2 タイマーを2秒にします - 選択可
13 SET_EXP_DELAY_3 タイマーを3秒にします - 選択可
14 SET_EXP_DELAY_4 タイマーを4秒にします - 選択可
15 SET_EXP_DELAY_5 タイマーを5秒にします - 選択可
16 SET_EXP_DELAY_6 タイマーを6秒にします - 選択可
17 SET_EXP_DELAY_7 タイマーを7秒にします - 選択可
18 SET_EXP_DELAY_8 タイマーを8秒にします - 選択可
19 SET_EXP_DELAY_9 タイマーを9秒にします - 選択可
20 SET_EXP_DELAY_10 タイマーを10秒にします - 選択可
21 SET_CAP_MODE_IMAGE 撮影モードを 静止画 にします - 選択可
22 SET_CAP_MODE_VIDEO 撮影モードを 動画 にします - 選択可
23 SET_CAMERA_VOL_PLUS 各種カメラ音量を 1段階(10/100)大きくします - 選択可
24 SET_CAMERA_VOL_MINUS 各種カメラ音量を 1段階(10/100)小さくします - 選択可
25 SET_SPEECH_VOL_PLUS 発話音量を 1段階(20/100)大きくします - 選択可
26 SET_SPEECH_VOL_MINUS 発話音量を 1段階(20/100)小さくします - 選択可

「アクションの種類が足りない」「違うアクションが欲しい」という場合には、是非ともカスタマイズにチャレンジして頂きたいです。

表の右側2列「Simple View」と「Advanced View」というのは、次章で説明する「キーに対してアクションを紐付けするユーザーインターフェース」の画面のことです。
11番以降のアクションは、「Advanced View」にしないと設定できない仕様として、難しい設定が苦手な方向けの配慮をしています。その他にも、めんどくさそうな設定を楽にする仕掛けをいれていますので、次章へとお話をすすめます。

キーに対するアクションの紐付け(webUI)

操作ボタンとアクションの紐付けはwebUIで行います。
webUIは、プラグインが動作している状態で基本アプリを起動したあと、数回タップの簡単操作で起動することができます。

webUIの起動_small.gif

webUIを最初に表示すると、既にデモンストレーション用の設定がなされています。

webUI_00_画面上部.png

画面上部にあるwebUIのボタンは以下のような振る舞いをします。

webUI ボタン名称 説明
Save 現在表示している内容を保存します
New History 操作履歴の表示を更新します
Clear History 操作履歴を消去します
Clear settings 設定をすべて消去します
Factory settings デモンストレーション用設定にします
Advanced View/Simple View 「簡単表示」と「詳細表示」の切り替えを行います

デモンストレーション用と類似の機器ですと、設定を変えずに使用することもできますが、
お好みの設定にする場合、まず「Clear settings」ボタンを押して現時点の設定を全てクリアすることから始めます。「Factory settings」ボタンで初期状態に戻すことは簡単にできますので、安心して色々とお試しください。

webUI_00_設定クリア.png

その後は、何がしかのキー操作を行った後「New History」を押すと、これまでキー操作をしたことがあるキーコードと対応するセレクトボックスがwebUIに表示されます。最後に操作をしたキーコードは、文字の背景が赤くなります。沢山キーコードが並んでも設定すべきキーコードを見失うことがないと思います。

キー設定2_small.gif

あとは、設定したいキーコードのセレクトボックスからアクションを紐付けるだけです。以下アニメーションGIFは、ゲームパッド十字キーの上ボタンに「EXEC_SHUTTER」を割り当て、動作をさせた例です。

キー設定3_small.gif

ブラウザの画面からセレクトボックスを選んだだけでは、HID側のボタンを操作しても選んだアクションが実行されません。「New History」を押すと、その時点の設定でHIDの動作を確認できるようになります。
お好みの設定が確定したら、最後に「Save」ボタンを押すことを忘れずに行ってください。Saveしない場合、プラグインを立ち上げなおすと元の設定のまま振舞います。
(ちょっとした実験にはSaveをしないのがちょうどよいかと思います。)

慣れると、まとめてHID側の操作をしてからアクションを設定をしたり、継ぎ足しの設定(キーコードが被らない別の機器の設定を途中から追加する)なども行えます。

個別の使用例

デモンストレーション用として初期設定してある各機器の特徴やハマった点(他のHIDを扱う際に参考になりそうな点)などを紹介していきます。

本体ボタンのみで使用する

THETA Vのボタンの中でプラグインが認識できるのは「シャッターボタン」「無線ボタン」「モードボタン」です。それぞれのボタンについて「短押し」「長押し」の識別も可能なのですが、

  • モードボタンの長押しはプラグイン終了に使われている
  • シャッターボタンの長押しはめったなことでは使わないであろう

ということから、以下の操作についてアクションを自由に決められるようにしています。
webUIの画面を切り出し、デモ用の初期値とともに貼っておきます。

04_本体設定.png

少々余談となりますが、
HIDの中には、機器側で「短押し」「長押し」を識別して異なるキーコードを本体に送りつけるものもあるため、「短押し」だけに対応させています。「長押し」は本体ボタンだけの対応とさせて頂きました。
表記についても、本体ボタンの場合キーコード名称だとわかりにくいので「Key operation」としています。
THETA本体の各ボタンはAndroidにおけるキーコードの以下に対応しています(具体的な数値はこちらのドキュメントの「Receiving Button Events」にも記されています)。

ボタン キーコード
シャッターボタン KEYCODE_CAMERA
無線ボタン KEYCODE_WLAN_ON_OFF
モードボタン KEYCODE_MEDIA_RECORD

これらのキーコードと同じコードを出力するHIDを使用するときにはご注意ください。

フィンガープレゼンターその1(Inateck WP2002)

今回のプラグインと共に使うのをお勧めするHIDの1つです。

05_Inateck.jpg

2019年2月現在の実売価格が2000円くらい。ケーブルスイッチCA-3の実売価格の半額ほど。
「充電式であること」「消費電流少なさ(GPS/GNSSレシーバより少ない)」は次に説明するKOKUYO ELA-FP1 黒曜石より個人的な好みでした。
操作により出力されるキーコードの種類が豊富なことも特徴かと思います。

ボタン 操作 出力されるキーコード
"□"ボタン 短押し KEYCODE_TAB
長押し(運用で禁止を) KEYCODE_ALT_LEFT + KEYCODE_PICTSYMBOLS
ダブルクリック KEYCODE_ENTER
">"ボタン 短押し KEYCODE_PAGE_DOWN
長押し KEYCODE_B
"<"ボタン 短押し KEYCODE_PAGE_UP
長押し(運用で禁止を) KEYCODE_F5 + KEYCODE_MUSIC

ただし、赤字にしたキーコードについては、本記事後半「OSに直接作用するキーコード」にて詳しく説明する事情があり、このキーコードが発生するとTHETAがハングアップしたかのような状態となってしまいます(開発者の方はVysorを使うと直ぐにわかるのですが、THETA内部でダイアログ系の画面が表示されており、タッチパネルがないTHETAではその画面に応答できない状態になっています)。これらは「ユーザーが該当する操作をしない」という使い方でトラブルを避けていただくようお願いいたします。
なお、電源ボタン短押しでTHETAをスリープさせたあと、再び電源ボタンを短押ししてTHETAを復帰させると、この状態を解消することができます。

フィンガープレゼンターその2(KOKUYO ELA-FP1 黒曜石)

こちらも、上で紹介したInateck WP2002と同じくらい、本プラグインと共に使うことをお勧めするHIDです。

06_KOKUYO.jpg

2019年2月時点の実売価格は3000円近辺のようです。
指用(大きめ)と細いレーザーポインタ用(小さめ)の2種類の固定具が含まれていて、取り付けに便利そうです。指用が自撮り棒にぴったりでした。
レシーバーにもLEDがあり、操作が受付られたのか視覚的に確認できたりもします。そのぶんTHETAからレシーバーへ供給する電力が他のHIDより多めです。送信機はLR43のボタン電池で駆動します。運用コスト面や電池の入手性にご注意ください(日本のコンビニであれば大抵購入できます)。

操作により出力されるキーコードは以下のようになっていました。取扱説明書と照らし合わせるとWindows用の説明とほぼ一致しています。

ボタン 操作 出力されるキーコード
BLACK OUT(左) 短押し KEYCODE_B
長押し KEYCODE_Bが繰り返される
NEXT(中央) 短押し KEYCODE_PAGE_DOWN
長押し KEYCODE_F5が繰り返される
BACK(右) 短押し KEYCODE_PAGE_UP
長押し KEYCODE_ESCAPE+KEYCODE_BACK

THETA本体内部でダイアログが出たままになるようなキーコードが出力されないところが安心。
Inateck WP2002と同じキーコードを出すボタンが多いです(どちらもプレゼンテーション用のツールですから当然ですね)。本プラグインのデモンストレーション用設定はInateck WP2002よりになっていますので、この機器を使用する方は初期値から設定を変更したほうが使いやすいと思います。

ゲームパッド(BUFFALO GAMEPAD BSGP815GY)

Android対応のゲームパッドです。
他にこちらのAndroid対応していないゲームパッドも試してはみたのですが、THETA VやAndroidスマートフォンではひとつもキーコードを拾うことができませんでした・・・(汗
ゲームパッドのたぐいは、Android対応のものを使ったほうがよいようです。

こちらの製品の、A、B、X、Yボタンは1つの操作で2つのキーコードが出力されます。
webUIの「New History」「Clear History」を使うと、以下のように、うまいことキーコード解析が行えます。
(いつの間にかキーコード解析プラグインをつくってしまったようだ・・・)

キーコード解析_small.gif

このような場合は、1つのキーコードにのみ アクションを割り当てるようにしてください。
ボタンの押し方でキーコードが変わるような振る舞いはありませんでしたが、「TURBO」「CLEAR」ボタンでそれぞれのボタンを連射モードにするか解除するかを切り替えることができます。 「TURBO」「CLEAR」を操作してもTHETA側にはキーコードは送られません。

これらを踏まえてボタンとキーコードの対応をまとめると以下となっています。

ボタン 出力されるキーコード
A KEYCODE_BUTTON_A + KEYCODE_DPAD_CENTER
B KEYCODE_BUTTON_B + KEYCODE_BACK
X KEYCODE_BUTTON_X + KEYCODE_DEL
Y KEYCODE_BUTTON_Y + KEYCODE_SPACE
L KEYCODE_BUTTON_L2
R KEYCODE_BUTTON_R2
SELECT KEYCODE_BUTTON_L1
START KEYCODE_BUTTON_R1
十字キー上 KEYCODE_DPAD_UP
十字キー下 KEYCODE_DPAD_DOWN
十字キー左 KEYCODE_DPAD_LEFT
十字キー右 KEYCODE_DPAD_RIGHT

キーボード(RAPOO E2700)

たまたま所持していたAndroid対応の無線のキーボードで動かしてみました。
他にWindowsやMac用のUSB接続するキーボードや、10キーのみのキーボードなどなど、様々なキーボードでも本プラグインは動作します。色々と試してみてください。

今回使用したキーボードの特徴は「Android対応」であったことです。
以下のような特殊なキーがあります。

10_Android由来のキー.jpg

Inateck WP2002で少し触れたように、THETA V内部でダイアログが出たままになってしまうようなキーコードや、THETA V自体がスリープに入ってしまうようなキーコードがあることに気づけました。気になったのでadbコマンドでも一通りのキーコードを実行して動作を確認した結果が以下となります。HIDをTHETAで利用するときの大切な情報としてお役にたてば幸いです。
THETA Vで新たなHIDを使用する時には、事前にAndroidスマートフォンに接続して動作確認をしたり、THETA Vを開発者モードにした方は、Vysor画面を見ながら動作確認してから本運用をするとよいと思います。

注意点:OSに直接作用するキーコード

KeyCode名称 本プラグインで使用(操作)禁止とする理由
KEYCODE_HOME HOMEボタンと等価でプラグインが終了します
KEYCODE_ENDCALL THETAがsleepしてしまいます
KEYCODE_POWER THETAがsleepしてしまいます
KEYCODE_SYM "select keybord"のダイアログが出たままになります
KEYCODE_ENVELOPE E-Mailアプリ初期設定ダイアログが出たままになります
KEYCODE_SYSRQ screenshotが撮られonKeyDownイベントが発生しません
KEYCODE_PICTSYMBOLS 絵文字入力画面が表示されます
KEYCODE_APP_SWITCH Multitaskメニューが表示される(プラグイン終了と等価な状態です)
KEYCODE_LANGUAGE_SWITCH "tggle keybord"のダイアログが出たままになります
KEYCODE_CONTACTS onKeyDownイベントが発生しません
KEYCODE_CALENDAR onKeyDownイベントが発生しません
KEYCODE_MUSIC MUSICアプリ初期設定ダイアログが出たままになります
KEYCODE_CALENDAR onKeyDownイベントが発生しません
KEYCODE_ASSIST onKeyDownとonKeyUpイベントが発生しません
KEYCODE_BRIGHTNESS_DOWN プラグインが終了します
KEYCODE_BRIGHTNESS_UP プラグインが終了します
KEYCODE_SLEEP THETAがsleepしてしまいます
KEYCODE_WAKEUP onKeyDownとonKeyUpイベントが発生しません
KEYCODE_SOFT_SLEEP THETAがsleepしてしまいます
KEYCODE_SYSTEM_NAVIGATION_UP onKeyDownとonKeyUpイベントが発生しません
KEYCODE_SYSTEM_NAVIGATION_DOWN onKeyDownとonKeyUpイベントが発生しません
KEYCODE_SYSTEM_NAVIGATION_LEFT onKeyDownとonKeyUpイベントが発生しません
KEYCODE_SYSTEM_NAVIGATION_RIGHT onKeyDownとonKeyUpイベントが発生しません

マウス(logicool M235)

実際に動かしたものは、たまたまWindows PCで普段から使用していた無線マウスでしたが、有線・無線問わず様々なマウスが対応しているはずです。
THETA Vが対応しているポインティングデバイスのキーコードは以下の通りです。

07_PointingDevices.png

多数ボタンがあるようなマウスでどうなるかは試せておりませんが
一般的な左右クリックと真ん中にホイールがあるWindows用マウスの場合

マウス操作 出力されるコード
左クリック BUTTON_PRIMARY
右クリック BUTTON_SECONDARY
中央ホイールの押し込み BUTTON_TERTIARY

のようになります。

ポインティングデバイスをTHETAに接続するにあたり1点だけ注意点があります。Vysorを使っている開発者の方は、THETAプラグインにもスマートフォンアプリのような画面があることをご存知かと思います。以下は今回作成したプラグインの画面です。

08_HidRemoteVysor画面.png

このような画面の上部(ステータスバー部分)にマウスカーソルがあるとき、クリック操作を行うと通知シェードにクイック設定がでてきたり、プラグインのタイトルが記載されているエリアにカーソルがあるとイベントが発生しません。また、プラグインが起動していないときにマウス操作をすると何が起こるかわかりません。
(ディスプレイなしでパソコンをマウス操作をするようなものですので当然ですね)

デモンストレーション用にマウスも利用可能としてみましたが、よい子のみなさんには接続自体をお勧めできません。そこで「Advanced View」でしか表示されない事項とさせて頂きました。
すでに紹介済みの「フィンガープレゼンター」と類似製品に、こちらのようなマウス由来のツールもあるのですが、上記理由により、THETA Vでの使用はあまりお勧めできせん。

その他のポインティングデバイスとして、ボタン付のスタイラスペンなどもあるようですが試せていません。スタイラスならカーソルが勝手に動くことはなさそうなので便利かもしれません。どなたか実験して頂けるとたすかります。(でもUSBドングルのレシーバーがあるタイプはなかなか無いかもしれません)

自作キーボード(Aruduino ProMicro[Leonardo])

電子工作界隈で有名なAruduinoシリーズの中でも「ATmega 32u4」というマイコンを利用したシリーズは簡単にHIDを作ることができます。詳しくはこちらのようなQiita記事をご参照ください。

今回 1000円ちょっとで買える小さなボードに、タクトスイッチをくくりつけただけの1キーキーボードを作って動かしてみました。もはや半田付けすらしていません。
こんな状態ですがPCに接続しても動作します。

09_自作キーボード例1.jpg

ソースコードは本プラグインのファイル一式と共に「arduino_hid_sample」フォルダへ置いてありますが、こんな短いソースコード1ファイルで動きます。

arduino_hid_sample.ino
#include "Keyboard.h"

#define BUTTON1    3

void setup() {
  Keyboard.begin();
  pinMode(BUTTON1, INPUT_PULLUP);
}

void loop() {
  if(digitalRead(BUTTON1) == LOW){
    Keyboard.press(KEY_RETURN);
    delay(100);
    while(digitalRead(BUTTON1) == LOW);
    Keyboard.release(KEY_RETURN);
  }

  delay(100);
}

ボタン操作をして出力されるキーコードはENTARキーと同じ(KEYCODE_ENTER)にしてみました。この辺りはお好みで自由自在です。
先に紹介したinateck WP2002に習って、短押し・長押し・ダブルクリックなどで異なるキーコードを送信するようなプログラムに書き換えれば1キーでもかなりのことができます。

電力はTHETAから供給されます。先に少し触れたケーブルスイッチCA-3のように電池が必要ありません。「ケーブルスイッチCA-3より、もう少しできることが多い有線のリモートコントローラーで撮影がしたい」というご要望をけっこう受けることがあります。3Dプリンタなども扱える方は自撮り棒に取り付けられるケースなどと共に作ると便利そうです。キーの数も必要に応じて増やすことができます。

このような「自作キーボードの世界」は盛り上がりつつあるようでして、秋葉原にある遊舎工房さんから、こんなかわいい4つしかキーがない自作キーボードキットも販売されています。

他にも、こんな1キーキーボードキットがあったり、過去には、イヤリング型1キーキーボードというのもあったようです。

自作キーボードの世界・・・奥が深い・・・
THETA用の1キーキーボードキット(ケースつき)とか、どなたか作ってくれないだろうか。

自作キーボードではないですが、クラウドファンディングで少量づつ販売をしているこちらのようなキーボードも本プラグインと相性がよさそうです。
(手の中に納まるサイズで、フルキーキーボード+マウスのキーコードが出力できるって凄い)

USBハブを介してHIDを複数同時に動かしてみた

あくまでデモンストレーションとして、USBハブを介して複数のHIDを同時に動かしてみました。

USBハブで複数同時small.gif

複数同時に動かすとTHETAの消費電力が増えます(USBハブ+接続した機器が同時に電力を使います)
THETA本体の電池残量が少なくなると正常な動作が行えなくなったりする点(プラグインが起動できなかったりします)はご了承ください。あくまでデモンストレーションとして行っています。

その他の注意点や制約

本プラグインを使用するにあたっての注意点や制約などをまとめておきます。
「こんな動作をしたけど正常/異常どっちなの?」のような迷いが生じた場合にご参照ください。

  • 発話中は「Live」のLEDを点灯させています(THETA Vのみ)。
  • 静止画モードからプラグイン起動をさせたとき、意図的に一瞬動画モードにしあと静止画モードにしています。
  • webUIで設定をするプラグインでることから、プラグイン起動時にAPモードに切り替えます。他のモード(OFFやCLモード)にしたい場合は何らかのボタンにTGGLE_WLANを割り当てプラグインを起動したあとに切り替えてください。
  • 静止画撮影直後から画像保存が終わるまでに行われた操作はスルーされます。
  • 画像保存が終わった直後に何らかの設定を行った場合、音声だけ再生され値が反映されなていない場合があります。(既知の問題点。解析中です。プラグイン側の問題点だとおもっており後々修正するかもしれません)
  • プラグインを起動しなおした場合、webUIも開きなおしてください。ブラウザのキャッシュに残った画面から操作をすると、意図通りの設定が行えない場合があります。
  • webUIのSimple/Advancedの表示状態はSAVE操作に影響されず、プラグイン終了時点の値を記憶します。
  • 発話音量は、SAVE操作に影響されずプラグイン終了時点の値を記憶します。
  • 操作履歴は、SAVE操作した時点の未設定キーも覚えています。あとはプラグイン起動を基点に操作されたことがある未設定のキーコードが表示されます。
  • HIDはプラグインが起動していないときに接続してください。プラグイン起動中にUSBポートに機材を刺すとプラグインが終了します。(THETAプラグインの制約事項となります)

(2019/05/24 追記:以下はTHETA V ファームウェア Ver. 3.00.1 で修正されています)
- USBポートにHIDを接続したまま、完全電源OFFからの電源ONを行わないでください。USBポートに機材を刺したまま完全電源OFFからのON操作をするとTHETAが操作を受け付けなくなることがあります。(エラーダイアログが出ているという THETA V 本体FWの問題でした。次回のTHETA Vファームウェアアップデートで修正される予定です)
- TGGLE_WLANで無線LANのモード切り替えをしても反応が鈍いです。無線ランプの表示が切り替わるのを待ってから次の操作を行ってください。(THETA V本体FWの問題でした。次回のTHETA Vファームアップデートで改善される予定です)

プログラムの説明

今回作成したプラグインのファイル一式をこちらにおいておきます。

複数のキーコードに応じて静止画の撮影をするだけなら、ベースとしたTHETAプラグインSDK MainActivity.java の以下部分を

MainActivity.java
            public void onKeyDown(int keyCode, KeyEvent event) {
                if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
                    /*
                     * To take a static picture, use the takePicture method.
                     * You can receive a fileUrl of the static picture in the callback.
                     */
                    new TakePictureTask(mTakePictureTaskCallback).execute();
                }
            }

以下のように書き換えるだけでもよいわけですが・・・

MainActivity.java
            public void onKeyDown(int keyCode, KeyEvent event) {
                switch (keyCode) {
                    case KeyReceiver.KEYCODE_CAMERA:
                    case KeyEvent.KEYCODE_PAGE_DOWN:
                    case KeyEvent.KEYCODE_PAGE_UP:
                    case KeyEvent.KEYCODE_F5:
                                 
                     対応させたいキーコードを羅列する
                                 
                    case KeyEvent.KEYCODE_TAB:
                        new TakePictureTask(mTakePictureTaskCallback).execute();
                        break;
                    default:
                        break;
                }
            }

いろいろと凝った仕様としましたので、事細かに説明するのではなく、コード全体を読み解くときの道しるべになる情報や、カスタマイズに必要そうな情報を記載しておきます。

全体説明

THETAプラグインSDKをベースに
~\app\src\main\java\com\theta360\pluginapplication 配下の以下ファイルしか弄ってないのが基本です。

ファイル 説明
MainActivity.java 沢山手を加えています
network/HttpConnector.java こちらの記事で説明済みの汎用webAPI実行処理「httpExec()」を追加しただけです。
task/配下のファイル TakePictureTask.javaは不要なので消しています。7ファイル全てが新規のファイルです。

その他は、マウスの章で既に登場していますが、デバッグ用にプラグインの画面をつくっています。プラグインが最後に認識できたキーコードが表示されるだけですので無視してしまって問題ありません。

~\app\src\main\res\raw 配下に発話用の音声ファイルがあります。
「音声処理の色々」で詳しく説明するので、今はファイルのありかだけを記しておきます。

メイン処理(MainActivity.java)

既存の雛形部分(キーコード解釈部)

基本的には、受け取ったkeyCodeに対応するアクションを以下コードで実行するだけです。

MainActivity.java
execKeyProcess(keyCode2KeyProcess(keyCode));

本体ボタンはonKeyUp()で短押し処理を、onKeyLongPress()で長押し処理をさせたり、プラグイン起動のキーイベントで無駄な処理実行をしないよう、いくらかの細工がしてあります。

そして、onResume()にはプラグイン起動時の処理、onPause()にはプラグイン終了時の処理をまとめてあります。

ポインティングデバイスのイベントを受け取る部分

ポインティングデバイスは通常では座標情報が必要となることから、onKeyDown(),onKeyUp(),onKeyLongPress()とは異なる以下のメソッドでイベントを受け取ります。

MainActivity.java
    @Override
    public boolean onTouchEvent(MotionEvent event) {
      省略
    }

大枠の仕掛けはkeyCode処理と同じです。

各種配列とそれに伴う処理色々

本プラグインで最も重要な配列が以下となります。

MainActivity.java
    private static final int KEYCODE_LIST_MAX_NUM = 300;
    private ArrayList<Integer> keyCode2ProcessList = new ArrayList<Integer>();

Androidでは、こちらのドキュメントの通り0~283までのキーコードが定義されており、THETA Vでは、それらにKEYCODE_WLAN_ON_OFF(=284)というキーコードが加えられています。
この配列は、入力があったkeyCodeに対してどの番号の処理をしたら良いかを保持しておくテーブルです。将来、使用されるキーコードが増えても、しばしプログラム修正せずに耐えられるよう、0番~299番の300通りまで冗長な長さを用意しておきました。

ポインティングデバイスについては以下が同じ役割を果たします。

MainActivity.java
    private int listMotionEvent2Process[] = {

操作履歴(キー入力の有無)を覚えるためにも利用していたりします。
あとは、プラグイン終了時にこの値を保存したり、プラグイン起動時に保存されている値を読み込んだり、webUIからの色々な操作に対応したりするメソッドがずらずらと並んでいるだけです。
わりとドタバタと書き足していったままの状態です。クラスに分けるなどしたほうが良かったのですが、このまま公開してしまいスミマセン!

タスク化しなかった処理実行部

MainActivity.java
private void changeWlanMode() {

こちらは無線LANの切り替え処理です。当たり前ですがwebAPIで無線LANの操作はできませんので・・・

MainActivity.java
private void changeSpeechVolume() {

こちらは発話音量の変更処理です。内部的に保持している数値書き換えだけなのでタスク化していません。

webUI関連

MainActivity.javaの以下コメントからファイル末尾までが web UI の処理です。

MainActivity.java
    //=====================================================
    //<<< web server processings >>>
    //=====================================================

長いですが、状態や画面操作に合わせたwebUIの表示を作っているだけです。
「THETAプラグインのWeb UIの実装方法」の記事を参考に読み解いていただければと思います。

各種アクションの実行部

「task」フォルダ配下の処理は、基本的にwebAPIを実行する処理をタスクに分割したものです。
SoundManagerTask.javaだけは特別なので後に別途説明します。

ファイル名 処理内容
ChangeCaptureModeTask.java 静止画/動画モードの切り替え
ChangeEvTask.java 露出補正値の変更
ChangeExposureDelayTask.java タイマーの変更
ChangeVolumeTask.java 通常通知音の音量変更
ShutterButtonTask.java 撮影(静止画モード:takePicture, 動画モード:録画の開始/停止)
CheckApListTask.java CLモードのリスト有無をチェックします。プラグイン起動時にしか実行されません。

共通点は、webAPIで現在の状態を一度獲得してから値を変更する処理であるため、
doInBackground() をsynchronizedとしています。

音を鳴らす処理がある場合は、onPostExecute()で実行しており、操作を素早くできることを重視して排他をかけていません。
急いだ操作をすると音声再生が重なりますが、内部の状態がおかしくなることはありません。
「THETA をおしゃべりにする」記事のように先に再生中の音を止めるようにカスタマイズしたほうが良いかもしれません。この例では、コードが煩雑になりそうなので現状の振る舞いとしました。

音声処理の色々(SoundManagerTask.java)

音声再生の方法と音量

「THETAプラグインでマイクを使って録音する」の記事では、THETA本体のスピーカーから大きな音を鳴らすには、「再生時のStreamTypeをSTREAM_RINGまたはSTREAM_ALARMにする」という回避策をお伝えしていました。
今回、本件について新たな追加情報がわかりましたのでお知らせしておきます。

STREAM_RINGから音を鳴らす場合、STREAM_RINGの音量をひとたび0にすると、Androidシステムとしては「マナーモードにした」という扱いになってしまい、プラグインから音量が戻せなくなります。音量が戻せないばかりか、音量操作を試みたり音を鳴らした時点でプラグイン落ちてしまいます。
音量操作ができるHIDはけっこう沢山あり(今回動作確認をしたAndroid対応のキーボードも該当します)、その実態はSTREAM_RINGの音量を変更しています。そういったものを接続していると、プラグインが与り知らない所でSTREAM_RINGの音量を0にできてしまうので、予想もしていないところでプラグインが落ちるというトラブルになりかねません。

一方、STREAM_ALARMから音を鳴らす場合には上記全ての問題を回避できます。

したがいまして、プラグインから音を鳴らす場合「再生時のStreamTypeをSTREAM_ALARMにする」ようお願いいたします。

音声を日本語のみにした理由

最初はこちらのスマートフォンアプリで生成した英語の音声ファイルで実験をしていたのですが・・・
出力した音声ファイルの再配布もOKな英語版TTSがみつからず、多言語化を断念しました。
(生声を録音という手はあったのですけれども。。。それに手を染めるにはまだ早いですね。
 本件に関してなにか情報をおもちの方はTwitterTHETAプラグイン開発コミュニティ(Slack)などでお知らせ頂けるとうれしいです。)

個人が楽しむ範疇であれば上記手段で音声ファイルを利用しても問題ありませんし、他にも多くのTTSがあり、お好みの声を選び放題かと思います。
その際には、「~\app\src\main\res\raw 」配下の音声ファイルを変更してプラグインをビルドしなおすことでカスタマイズが行えます。(ファイル名を変更した場合には、対応するソースコードも修正してください)

今回使用した日本語の音声については、以下ライセンス表記をすることで、TTSが出力した音声ファイルの再配布までもがOKになります。発話の制約(ナがヌになる等)もありません。
便利に使わせていただいております!ありがとうございます!

音声データのライセンスについて

本プログラムで使用した音声データは以下サイトで作成しています。
https://note.cman.jp/other/voice/

上記サイトで作成された音声についても以下ライセンス表記が必要です。
Creative Commons Attribution (CC-BY) 3.0 license
HTS Voice "Mei(Normal)" Copyright (c) 2009-2013 Nagoya Institute of Technology

音声データのライセンス詳細はこちらhttp://www.mmdagent.jp/を参照ください。

まとめ

シンプルがウリのTHETAシリーズですが、「操作ボタンが少ない」「リモコンの選択肢が少ない」というようなことをHIDでリカバーできたのではないかと思います。
「表示(ユーザーへの通知)手段が少ない」という点も音によってある程度リカバーできたのかと思います。

今回の事例では、HIDを撮影操作拡張に利用しましたが、「画像処理の種類を切り替えたい」「内部メモリのバックアップ先を切り替えたい」「ネットワークへのアップロード先を切り替えたい」「自動認識撮影の振る舞いを切り替えたい」などなど、「プラグインで追加した処理を快適に操作するための手段」としても利用できると思われます。(THETA据え置き+画像処理や認識+ネットワークで色々とできることもありそうですし)

そして2019年2月25日、ついに新型最上位機の「RICOH THETA Z1」が発表されました!
こちらはレンズ・センサー・外装が一新されているだけではなく、OLED表示器がついたりFnボタンが増えたりとUIも拡張されています。本プラグインは、現状のままでもRICOH THETA Z1で動作しますが、「Fnボタンの長押し」に対応したり、「OLED表示のコードを書いていないのでプラグイン動作中に静止画/動画モードマークが表示されない」というRICOH THETA Z1固有の仕様にも対応しなくてはなりません(取り急ぎは音声で通知しようかな・・・)。
プラグインストアへの公開に向けてそれらの対応も入れられればよいなと思っております。

12_Z1deHIDRemote.jpg

RICOH THETAプラグインパートナープログラムについて

THETAプラグインをご存じない方はこちらをご覧ください。
パートナープログラムへの登録方法はこちらにもまとめてあります。
興味を持たれた方はTwitterのフォローとTHETAプラグイン開発コミュニティ(Slack)への参加もよろしくおねがいします。

KA-2
普段は星空のある風景写真(なにかの表紙なったりもするレベル)を撮っているようです。 電子工作なんかも少しします。 ファーム屋(RTOS/制御屋/システム屋)、商品企画、星景写真撮影者(ASPJ正会員)、 肩書き色々。。。
theta-plugin
株式会社リコーの技術者有志による、RICOH THETAプラグイン技術情報の提供を目的としたコミュニティです。
https://api.ricoh/products/theta-plugin/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away