LoginSignup
13
2

More than 1 year has passed since last update.

左手デバイス「Orbital2」の秘めたる力

Last updated at Posted at 2021-10-22

バーチャルSNS「cluster」主催のGAMEJAMに応募した作品が、デジタルハリウッド大学賞を受賞しました。
デジタルハリウッド大学様のご厚意により「Orbital2」を賞品として頂いたので、感想を書き連ねていこうと思います。

目次

Orbital2とは

Orbital2は、株式会社BRAIN MAGIC (Blackmagicじゃないよ) が開発した左手デバイスです。
詳細は公式サイトまで。

o2_lt.png
出典:「クリエイターを科学するミライの左手デバイス「Orbital2(オービタルツー)」

フラットリングと呼ばれる8つのスイッチや、ジョイスティックを倒す・回す・押す動作を組み合わせて色々できるみたいですね。

1658万色に輝くグロウリングも、ゲーマーにとっては嬉しいポイントです。

画像には書かれていませんが、振動によるフィードバック機能もあります。

Orbital2の感想

Orbital2の使い方・導入方法は公式サイトに掲載されているので省略します。
Orbital2の使い方・導入 for Windows
Orbital2の使い方・導入 for Mac

まずは、作業の様子を御覧ください
operate.gif
画面だけでは何をやっているのかわかりにくいですね。

ジョイスティックを傾けるとパイメニューが出てくるので、そのままダイヤルを回転させてショートカットを実行しています。

物理的にダイヤルを増やすデバイスが多い中、ジョイスティックを傾けてダイヤルの動作を選択する仕組みは洗練されていて気に入りました。

ショートカット名は画面にオーバーレイ表示されるので、どこに何の機能を登録したか一目瞭然です。

ポップアップとして、リスト形式のメニューを使用することも出来ます。

listmenu_lt.png

質感について

つや消し加工のさらさらした質感は、HTC VIVEを彷彿とさせます。

ダイヤルにはクリックタイプのロータリーエンコーダが採用されており1、コトコトとした静かな回し心地です。

o2andvive.jpg


Orbital2への要望

Orbital2の開発チームは、要望、バグ報告をTwitterGitHubで受け付けています。

私も以前、Orbital2 Coreソフトウェアの誤字を報告したのですが、わずか一週間ほどで修正ビルドが上がってきました2
この対応の速さは素晴らしいです。

しかし、当たり前ではありますが、すべての要望が対応されるわけではありません。
この章では、2021年10月21日現在の、個人的なOrbital2への要望を挙げていきます。

プロファイルを自動で切り替えたい

Orbital2 Coreには、アクティブなアプリケーションを検出して自動でプロファイルを切り替える機能がありません。

「ひとつのアプリにつき複数のプロファイルを使用することを想定している3」とのことですが、オプションで欲しい機能ではあります。

BlenderのShiftキーについて

標準のBlenderのビューポートは、Shiftキーを押すことで視点を操作します。

ところが、Orbital2のボタンにShiftキーを割り当てると、Blenderの視点操作に想定外の挙動がみられます。

この問題は、2年以上前から指摘されていますが、未だ修正されずにいます。

Linuxで使いたい

個人的に、作業をUbuntuで行うことが多いので、Linuxがサポートされると嬉しいです。ただ、ディスプレイサーバやディストーションは星の数ほどありますので、対応の手間を考えるとサポートが難しいのは理解できます。

Orbital2の振る舞いを観察する

ハードウェアを確認する

前置きが長くなりましたが、前述の問題を解決すべくOrbital2の振る舞いを観察していきます。
まずはじめに、Orbital2をLinuxに接続し、dmesgコマンドでデバイスがどのように扱われたかを確認します。

$ dmesg
[ 4040.701637] usb 5-2: USB disconnect, device number 6
[ 4040.701837] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
[ 4040.701853] cp210x 5-2:1.0: device disconnected
[ 4043.033322] usb 5-2: new full-speed USB device number 8 using xhci_hcd
[ 4043.197246] usb 5-2: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice = 1.00
[ 4043.197253] usb 5-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 4043.197255] usb 5-2: Product: CP2103 USB to UART Bridge Controller
[ 4043.197257] usb 5-2: Manufacturer: Silicon Labs
[ 4043.197258] usb 5-2: SerialNumber: 0005
[ 4043.202251] cp210x 5-2:1.0: cp210x converter detected
[ 4043.205256] usb 5-2: cp210x converter now attached to ttyUSB0

どうやらSilicon Labs製のUSBシリアル「CP2103」が使われているようです。
また、コンバータがttyUSB0に割り当てられていることも確認できました。

これからttyUSB0の通信を眺めていきます。

シリアル通信を読む

シリアル通信を解析するツールはたくさんありますが、私はArduino IDEを使いました。
ポートがbusyになることを防ぐため、モニタリングする前にOrbital2 Coreの接続を切りましょう。

WSL2はシリアルやUSBデバイスがサポートされていないので注意

シリアルモニタを開いて、適当にOrbital2を操作してみます。


J S X <8b> Y ニ ; J S X <8b> Y テ ; J S X <87> Y テ ; S W 8 = 1 ; J S X <87> Y セ ; J S X <83> Y セ ; J S X <80> Y サ ; R E - R ; J S X { Y キ ; J S X x Y イ ; J S X u Y ョ ; S W 6 = 1 ; J S X u Y ォ ; J S X r Y ォ ; J S X r Y ッ ; J S X u Y エ ; J S X u Y ク ; J S X u Y ス ; J S X x Y チ ; S W 6 = 0 ; J S X x Y ナ ; J S X ~ Y ナ ; J S X <81> Y ナ ; S W 6 = 0 ; J S X <85> Y ナ ; J S X <89> Y ハ ; S W 6 = 0 ; S W 6 = 0 ;

改行されていないため、非常に見辛いですね。ボタンを一つずつ押して確認していきます。

ダイヤル右回転

ダイヤル右回転
R E - R ;

ダイヤル左回転

ダイヤル左回転
R E - L ;

フラットリングの手前のボタン (押した後離さない)

フラットリングの手前のボタン(押した後離さない)
S W 7 = 1 ;

S W 7 = 1 ;が1回だけ流れてきました。
連続して1が流れてくるわけではないみたいです。

フラットリングの手前のボタン (クリック)

フラットリングの手前のボタン(クリック)
S W 7 = 1 ; S W 7 = 0 ; S W 7 = 0 ; S W 7 = 0 ; S W 7 = 0 ;

クリックするたびに、1,0,0,0,0 のセットが流れてきます。

フラットリングの手前のボタン (長押し)

フラットリングの手前のボタン(長押し)
S W 7 = 1 ; S W 7 = 0 ; S W 7 = 0 ; S W 7 = 0 ; S W 7 = 0 ;

ボタンを押し込むとS W 7 = 1 ;が1回流れ、離すとS W 7 = 0 ;が4回流れます。

オービタルエンジンの頂点押し込み

オービタルエンジンの頂点押し込み
R C 4 = 1 ; R C 4 = 0 ; R C 4 = 0 ; R C 4 = 0 ; R C 4 = 0 ;

オービタルエンジンの頂点押し込みも、フラットリングのボタンと同じ挙動です。

ジョイスティック

ジョイスティック(テキスト変換)
J S X { Y <81> ; J S X x Y <81> ; J S X u Y <81> ; J S X u Y <84> ; J S X r Y <84> ; J S X r Y <87> ; J S X n Y <87> ; J S X n Y <8a> ; J S X n Y <8d> ; J S X k Y <8d> ; J S X k Y <90> ; J S X h Y <90> ; J S X h Y <93> ; J S X h Y <96> ; J S X e Y <96> ; J S X e Y <99> ; J S X b Y <99> ; J S X b Y <9e> ; J S X _ Y <9e> ; J S X _ Y 「 ; J S X \ Y 「 ; J S X \ Y ・ ; J S X \ Y ゥ ; J S X Y Y ュ ; J S X Y Y ー ; J S X Y Y ウ ; J S X Y Y キ ; J S X Y Y コ ; J S X Y Y ソ ; J S X Y Y ツ ; J S X \ Y ナ ; J S X _ Y ナ ; J S X b Y ナ ; J S X b Y ネ ; J S X e Y ネ ; J S X h Y ネ ; J S X l Y ネ ; J S X l Y ヒ ; J S X o Y ヒ ; J S X r Y ホ ; J S X v Y ム ; J S X z Y ム ; J S X z Y ヤ ; J S X ~ Y ヤ ; J S X ~ Y ミ ; J S X <83> Y ミ ; J S X <87> Y ヘ ; ...

JS,X,Yなどの文字が見えます。16進数でも確かめてみましょう。

ジョイスティック(16進数)
4a 53 58 7b 59 81 3b 4a 53 58 78 59 81 3b 4a 53 58 75 59 81 3b 4a 53 58 75 59 84 3b 4a 53 58 72 59 84 3b 4a 53 58 72 59 87 3b 4a 53 58 6e 59 87 3b 4a 53 58 6e 59 8a 3b 4a 53 58 6e 59 8d 3b 4a 53 58 6b 59 8d 3b 4a 53 58 6b 59 90 3b 4a 53 58 68 59 90 3b 4a 53 58 68 59 93 3b 4a 53 58 68 59 96 3b 4a 53 58 65 59 96 3b 4a 53 58 65 59 99 3b 4a 53 58 62 59 99 3b 4a 53 58 62 59 9e 3b 4a 53 58 5f 59 9e 3b 4a 53 58 5f 59 a2 3b 4a 53 58 5c 59 a2 3b 4a 53 58 5c 59 a5 3b 4a 53 58 5c 59 a9 3b 4a 53 58 59 59 ad 3b 4a 53 58 59 59 b0 3b ...

以下の図は、4a 53JS, 58X, 59Y, 3b;へ置き換えた様子です。

16_lt.png

ジョイスティックの読み取りはチームメンバーのおにさわさんからご助言いただきました。ありがとうございます。

Pythonで制御する

ざっくりとシリアル通信が読めたので、Pythonを使ってOrbital2 Coreの代替スクリプトを書いていきましょう。(Python 3.10.0で検証)
Pythonでシリアル通信するために、pySerialというライブラリを使います。

$ pip install pyserial
test.py
import serial
import time

ser = serial.Serial('接続しているポート番号','9600',timeout=0.05)
time.sleep(1)

while True:
    SR = (ser.readline())
    SRstr = str(SR)

    if "RC4=1" in SRstr:
        print('exit')
        ser.close()
        exit()

    elif "SW7=1" in SRstr:
        print('Key7が押されました')

フラットリングの手前のボタンを押すと、コンソールに「Key7が押されました」と表示されるはずです。
オービタルエンジンの頂点を押すことで、スクリプトの実行を終了します。

import serialが通らない場合は、serialとpySerialが競合していないか確認しましょう

シリアル通信をするスクリプトだからといって、スクリプト名を「serial.py」にするのはやめましょう

キーボードとマウスを操る

Pythonでキーボードとマウスを操るには、PyAutoGUIというライブラリが便利です。

$ pip install pyautogui
import pyautogui

pyautogui.press('space')

キーボードのSpaceを押すだけのスクリプトです。先程書いたシリアル通信のスクリプトといい感じに組み合わせてみてください。
長押ししたい場合は
SW7=1のときにpyautogui.keyDown('space')して、
SW7=0のときにpyautogui.keyUp('space')すると良いでしょう。

PyAutoGUIの詳しい使い方はドキュメントをご確認ください。画像認識もできるので、ショートカットキーの登録ができないアプリケーションも力技でなんとかすることができます。

BlenderのShiftキーに対応する

PyAutoGUIが送信する仮想キーコードでは、Shiftキーによる視点操作ができません。
対応策として、PyDirectInputを使用します。

$ pip install pydirectinput
import pyautogui
import pydirectinput

pydirectinput.keyDown('shift')
pydirectinput.keyUp('shift')

これで、BlenderのShiftキーでの視点操作が正しく機能するはずです。

アプリごとに自動でプロファイルを切り替える

アプリごとに自動でプロファイルを切り替えるには、アクティブウィンドウの情報を取得する必要があります。

詳しい方法は、きむら しのぶ (@mix_dvd) さんの記事に記載されています。
Pythonを使ってWindowsやMacを監視し、操作中のアプリの情報を収集してみる

取得したログの例
Firefox Developer Edition
TweetDeck at DuckDuckGo — Firefox Developer Edition
TweetDeck — Firefox Developer Edition
Spotify Premium
山口百恵 - 横須賀ストーリー
Opening - Excel
Microsoft Excel
サンプル.xlsx - Excel
sample.py - Visual Studio Code

アプリ名だけでなく、様々な情報が取得できました。この情報をもとに条件分岐させましょう。

ジョイスティックの読み取り

前章でジョイスティックの信号を読み取りました。

16_lt.png

PythonでジョイスティックのXY座標を取得するには、以下のコードを記述します。

if "JS" in SRstr:
    x = ord(SR[3:4])-128
    y = ord(SR[5:6])-128
    print("X",x,"Y",y)

リストメニュー

Orbital2 Coreのリストメニューが便利だったので、似たようなものを作ります。
(長くなるので割愛)
GUIのフレームワークは何でも良いと思いますが、生成するウィンドウのlocationにはPyAutoGUIで取得したマウス座標を指定するのが良いでしょう。

window = PySimpleGUI.Window('ListMenu', layout, location=pyautogui.position())

tw.png

グロウリングについて

左手デバイスには、実用器としての価値と、鑑賞品の両面があるということを知らねばなりません。

大衆実用器として生まれたものには、往々、極めて低級な美を盛るに過ぎない大量的なものが多く、芸術的価値に富んで世間に騒がれているものは、その数こそ少ないですが、眼高の士の心をゆさぶるもの、即ち思想的個性の発露になるものが多いのでありまして、この両者を明確に区別してかかることが肝要であります。

実際、優れた左手デバイスに接しますと、名巌のような、松樹のような、琅玕竹のような、梅花のような、その美しさに打たれるものであって、それがどんな素材で出来ているとか、どういうふうにして作られたかというようなことは、第一義的には念頭に浮んで来ないのであって、立派な絵や建築を見る場合と少しも違わないのであります。第二義的には機能に渉り様々吟味もしますが……。

その中でもOrbital2などは日常自分でも使用して、あるいは愛玩したり、なんとなく親しみも生じて手にとって見たり、ダイヤルを廻してみたり、様々に変化のあるグロウリングの具合など賞めそやしたりして鑑賞の対象となり、嬉しさを感ずるのであります。

(改変元 : 陶器鑑賞について 北大路魯山人)


かようにして、独自のスクリプトからグロウリングのLEDの色を操ることは、刻下の急務であろうと考えられます。

正規のOrbital2 Coreソフトウェアからグロウリングへ向かう信号を解析することも考えましたが、生憎なことに、Orbital2 Coreソフトウェアの利用規約第4条は、プロトコルの解析を禁じているのです。

それならばLEDの操作は諦めるべきであろうか。どうしたものであろうか……なぞと、思案に暮れておりましたところへ、BRAIN MAGICの方から
「できる範囲ではありますが、Orbital2について何か提供などご協力ができればと存じます」と言う旨の連絡が来ました。

このような機会以外に、私がグロウリングのLEDを操る術を得ることは、将来、滅多に来ないような気がしましたから、「グロウリングのシリアル通信について教えてほしい」と言う意味のメールを出しましたところ、一週間程経ったあとに、「LEDの色を変更するには0x54, 0x00, red, 0x00, green, 0x00, blue, 0x00, 0x3b, 0x00(red, green, blueは0x00〜0xFFまでのRGB)を送信すればよい」との返事を受け取りました。

正直のところを云うと「お答えできかねます」と追い返されるのが関の山だろうと考えておりましたので、その返事の予想外なのに、また寛容であることに驚いたものでありました。

LEDを水色(#58b6d2)に
ser.write(b"T,\x58,\xb6,\xd2,; ")
LED消灯
ser.write(b"T,\x00,\x00,\x00,; ")

music.gif

これで、特定の曲が流れたときに色が変わるような芸当ができますね。

psutilでCPUやメモリの使用率を取得し、それをもとに色変更するのも楽しそうです。

バイブレーションについて

バイブレーションを動かすためのコマンドついては聞きそびれてしまいましたが、LEDのコマンドからある程度推測出来ます。

総当りしてみたところ、0x4d, 0xff, 0x3b, 0x00というコマンドを送信することで、Orbital2が振動することがわかりました。

バイブレーション
ser.write(b"M,\xff,; ")

Blenderで活用する

Blender内蔵のPythonでも、Orbital2とシリアル通信することができます。

詳しくは、Checkered Bugによるチュートリアルや、しましまさんの記事にて解説されています。

BlenderにOrbital2を召喚する

このツイートは、

① 現実世界のジョイスティックのXY座標を、Blender上のEmptyのXY座標へ割り当て
② Emptyの動きに合わせて、Blender上のジョイスティックオブジェクトが傾くよう、ドライバで紐付ける

ことにより実現しています。

driver_lt.png

Emptyを動かす
import bpy
import serial

ser = serial.Serial('COM3','9600',timeout=0.0)
obj = bpy.data.objects["Empty"]

while True:

    SR = (ser.readline())
    SRstr = str(SR)
    if "RC4=1" in SRstr:
        obj.location = (0,0,0)
        ser.close()

    elif "JS" in SRstr:
        x = (ord(SR[3:4])-128) / 100
        y = (ord(SR[5:6])-128) / 100
        print("X",x,"Y",y)
        obj.location.x = x
        obj.location.y = y
        bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)

おわりに

改めまして、GAMEJAMを企画し開催して下さったcluster様、
スポンサー賞に「田んぼのある生活」を選んで下さったデジタルハリウッド大学様、
当記事の公開を許可して下さったBRAIN MAGIC様に厚く御礼申し上げます。


チーム「おにさわランド」の「田んぼのある生活」をどうぞよろしくお願いします!

13
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
2