以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
初めにMesh 101にあらかじめ設定されているビジュアルスクリプトを確認します。
3.3 - Teleportオブジェクト配下にあるTeleportToWindTurbinButtonオブジェクトのビジュアルスクリプトを編集していきます。
本オブジェクトにはボタン押下時にTrue/Falseが通知されるノードが既に設定されています。
ここにボタン押下時にテレポートを行うノードを追加していきます。
テレポート先となるトラベルポイントを設定します。
HierarchyのTravelオブジェクト配下に右クリックから[Create Empty]で空オブジェクトを追加します。
オブジェクト名をTeleportLocationWindTurbineに変更し、Travel Pointコンポーネントを追加します。
オブジェクトのTransformを以下の値に設定します。
これで風車の台座の位置にトラベルポイントが設定されます。
シーン再生時はこのトラベルポイントを無効化しておきます。
オブジェクトのチェックを外して無効化することで、トラベルポイントを無効化できます。
Meshでは複数のトラベルポイントが有効である場合、テレポート先をランダムに選択します。
シーン起動時はTeleportLocationChapter3のトラベルポイントから開始したいため、これを唯一有効なトラベルポイントに設定しておく必要があります。
次にボタン押下時に追加したトラベルポイントにテレポートする処理を追加します。
TeleportToWindTurbinButtonオブジェクトのビジュアルスクリプトを開き、IFノードのTrueポートにSetActiveノードを接続します。
SetActiveノードの参照にTeleportLocationWindTurbineのトラベルポイントを指定して、[Value]にチェックを入れます。
これでボタン押下時にトラベルポイントが有効化されます。
SetActiveノードから更にTravel Point: Travel to Pointノードを接続します。
本ノードがテレポートを行うノードになります。
ノードのスクリプト参照項目にある丸ボタンをクリックすると、TravelPointを持つオブジェクトへの参照の一覧が表示されます。
先ほど作成したTeleportLocationWindTurbineオブジェクトの参照を設定します。これでテレポートの設定は完了です。
シーンを再生して動作を確認します。
TeleportToWindTurbinButtonオブジェクトのボタンをクリックします。
以下のように風車の台座にテレポートできれば成功です。
次回はMesh Interactable Setupを使ってオブジェクトを掴む設定を行います。
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
WithExtraScopesToConsent関数を利用すると、AcquireTokenInteractiveによるユーザ認証時に複数リソースのスコープの認可を得ることができます。
認証の結果、取得されるアクセストークンはAcquireTokenInteractiveの引数で指定したスコープに対するアクセストークンになります。
認証完了後、AcquireTokenSilentを使って指定のスコープのアクセストークンが取得できます。
learn.microsoft.com
// Interactiveで取得するアクセストークンのスコープ string[] scopes = { "https://graph.microsoft.com/User.Read.All" }; // 合わせて認可を得る別のリソースのスコープ string[] extraScopes = { "https://microsoft.sharepoint-df.com/AllSites.Read" }; AuthenticationResult result; result = await app.AcquireTokenInteractive(scopes) .WithExtraScopesToConsent(extraScope) .ExecuteAsync();
前回記事で作成したサンプルスクリプトに以下の処理を追加しました。
認証を行うと、一度の認証操作で異なる2つのリソースのアクセストークンを取得できるようになります。
・AzureMsalTest.cs
// Interactiveで取得するアクセストークンのスコープ string[] scopes = { "https://graph.microsoft.com/User.Read.All" }; // 合わせて認可を得る別のリソースのスコープ string[] extraScopes = { "https://microsoft.sharepoint-df.com/AllSites.Read" }; var app = PublicClientApplicationBuilder .Create(applicationID) .WithAuthority(AzureCloudInstance.AzurePublic, directoryID) .WithRedirectUri("http://localhost:50000/") .Build(); // ユーザー名を指定してログインする string username = loginUsername.text; // ユーザ認証を行う AuthenticationResult result; result = await app.AcquireTokenInteractive(scopes) .WithLoginHint(username) .WithExtraScopesToConsent(extraScope) .ExecuteAsync(); // アクセストークンを取得する var accessToken = result.AccessToken; // キャッシュを利用して異なるスコープのトークンを取得する var continuedAccount = accounts.FirstOrDefault(a => a.Username == username); result = await app.AcquireTokenSilent(extraScopes, continuedAccount) .ExecuteAsync(); // アクセストークンを取得する var extraAccessToken = result.AccessToken;
AcquireTokenSilentで正常にアクセストークンを取得できない場合があります。
以下のエラーが原因である可能性があるのでこちらの記事の対処を実施してみてください。
bluebirdofoz.hatenablog.com
MSALの利用手順については以下の記事を参照ください。
bluebirdofoz.hatenablog.com
AcquireTokenSilent関数を使ってキャッシュを利用してアクセストークンを取得しようとしたところ、以下のエラーが発生しました。
object reference not set to an instance
MSALを利用するアプリをUnityでビルドしたとき、コードストリッピング(最適化)により一部のソースコードが含まれないことが原因です。
learn.microsoft.com
Assetsフォルダ配下に以下のlink.xmlを作成することで、問題を回避できます。
<linker> <assembly fullname="Microsoft.Identity.Client" preserve="all" /> <assembly fullname="System" preserve="all" /> <assembly fullname="System.Core" preserve="all" /> </linker>
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
今回はアバターがボタンを押したとき、そのアバターのみに情報ダイアログを表示します。
3.2-InfoDialogオブジェクト配下にあるInfoButtonWrapperオブジェクトをボタンとして利用します。
前回と異なり、Local Script Scopeコンポーネントの[Share visual script variables on this Game Object]にチェックはいれません。
今回はシーン内の全てのアバターにイベントを共有する必要はないためです。
ボタン押下で情報ダイアログを表示するスクリプトを作成します。
[Edit Graph]ボタンをクリックしてビジュアルスクリプトの編集画面を開きます。
既にボタン押下時にIFノードからTrueまたはFalseを通知するフローが作成されています。
IFノードのTrueポートをクリックドラッグしてNodeメニューを表示し、Show Dialogノードを選択して追加します。
2つ目の項目でダイアログの形式を選択できます。
今回は[Continue]ボタンの表示形式を選択します。
1つ目の項目でダイアログに表示するメッセージを変更できます。
今回は以下のメッセージを入力しました。
世界最大の風力タービンにはサッカー場よりも長いブレードがあることを知っていましたか
シーンを再生して動作を確認します。
シーン中央のInfoボタンをクリックします。
以下のようなダイアログが表示されれば成功です。
次回はビジュアルスクリプトを使ってテレポートを行います。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
Mesh 101ではビデオオブジェクトと画像オブジェクトを切り替えることでビデオの再生/停止を実現します。
VideoPlayerオブジェクト配下のVideoオブジェクトがビデオの再生オブジェクト、VideoStillオブジェクトが画像オブジェクトです。
VideoオブジェクトにはVideo Playerコンポーネントが設定されており、オブジェクトが有効になるとビデオの再生が始まります。
デフォルトではオブジェクト自体が無効化されています。
VideoStillオブジェクトには画像が設定されており、ビデオのサムネイルを表示しています。
デフォルトではこちらのオブジェクトが有効化されています。
再生状態(isPlaying)の変数の切り替りに応じて、このオブジェクトの有効/無効を切り替えてビデオの再生を実行します。
再びPlayVideoButtonオブジェクトの[Script Graph]画面を開きます。
初めに再生状態(isPlaying)が再生(True)に切り替わった場合のフローを作成します。
IFノードのTrueポートをクリックドラッグしてNodeメニューを表示し、Set Activeノードを選択して追加します。
Set Activeノードは対象オブジェクトの有効/無効を切り替えます。
今回はVideoオブジェクトを対象にしたいので、HierarchyからVideoオブジェクトをドラッグして参照を設定します。
更にVideoオブジェクトはここで有効化したいので[Value]にチェックを入れます。
次に再生中VideoStillオブジェクトは不要になるので、もう1つSet Activeノードを接続してVideoStillオブジェクトの参照を設定します。
こちらはオブジェクトを無効化したいので[Value]にチェックを外しておきます。
これでボタン押下と共にビデオが再生されるようになりました。
ビデオ再生中、ボタンはビデオの停止ボタンになるので再生中はボタンの文言が[Stop]になる処理を追加します。
ビデオ再生時のフローに[Text Mesh Pro: Set Text]ノードを追加します。
Hierarchyから変更対象のLabelオブジェクトをドラッグして参照を設定します。
テキストフィールドにStopと入力します。
これでビデオ再生中にボタンの文言が[Stop]に変わるようになりました。
次に再生状態(isPlaying)が停止(False)に切り替わった場合のフローを作成します。
IFノードのFalseポートから先ほどとは逆の処理を行うフローを作成します。
Videoオブジェクトを無効化し、VideoStillオブジェクトを有効化し、ボタンの文言を[Play]に変える以下のフローを作成します。
イベントをトリガーするアバターのみにイベントを体験させたい場合や、トリガーするとシーン内の全てのユーザにイベントを体験させたい場合があります。
これはLocal Script Scopeコンポーネントを設定して制御します。
Script Machineコンポーネントを設定したPlayVideoButtonオブジェクトにLocal Script Scopeコンポーネントを追加します。
シーン内の全てのユーザにイベントの体験を共有させたい場合は[Share visual script variables on this Game Object]のチェックを入れます。
これで再生状態(isPlaying)が共有され、イベントのトリガーが共有されるようになります。
ビデオの再生/停止が正常に実行できるか、イベントの体験が共有されるか確認を行います。
複数人の共有を確認したい場合はMesh Emulator Setupオブジェクトの[Initial Screen Count]を2以上に設定してシーンを再生します。
一方のアバターでボタン押下してビデオを再生/停止し、もう一方のアバターでも同様にビデオが再生/停止されていることを確認します。
次回は情報ダイアログを表示してみます。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
今回作成するボタンはビデオ停止時にボタンを押すとビデオの再生され、ビデオ再生時にボタンを押すとビデオが停止するようにします。
ボタン押下時にOn State ChangedからTrueが出力され、ボタン押下が終わるとFalseが出力されます。
初めに押下時のTrueのときのみビデオの操作を行うようにフローを制御します。
On State Changedの出力ポートをクリックドラッグしてNodeメニューを表示します。
IFノードを選択して追加します。
IFノードが追加されたらOn State ChangedのOut 0ノードとIFノードの入力ノードを接続します。
これでIFノードの出力ノードから入力された値を判定できるようになります。
IFノードのTrue出力ポートをクリックドラッグしてNodeメニューを表示します。
Set Object Variableノードを選択して追加します。
次にボタン押下時のビデオ状態に合わせて再生と停止を切り替えるため、再生状態を保持する変数を作成します。
[Blackboard]パネル内の[Object]タブを開き、isPlayingという名前の変数を[+]ボタンで追加します。
ビデオの再生(True)/停止(False)状態を保持するため、作成された変数の[Type]を[Boolean]に設定します。
[Value]にチェックを入れず、初期値がFalseになるようにします。
ノードの編集画面に戻り、先ほど作成したSet Object Variableノードのプルダウンを開きます。
作成したisPalyingの変数を選択します。これでisPlayingの変数を変更する準備ができました。
isPalyingの変数はボタン押下ごとに再生(True)/停止(False)を切り替える必要があります。
その時点のisPlayingの状態を取得するため、グラフ内で右クリックからGet Object Variableノードを選択します。
ボタン押下ごとにisPlayingの状態を反転してisPlayingに反映することで、再生->停止、停止->再生の状態を切り替えます。
Get Object VariableノードにもisPlayingを指定し、その出力ノードにNegateノードを設定します。
最後にNegateノードの出力ポートをSet Object Variableノードの入力ポートに接続します。
これでボタン押下が発生するごとに、isPlayingの再生->停止、停止->再生の状態切り替えが行われるようになりました。
次に再生状態(isPlaying)の変数の切り替りを検知するフローを作成します。
グラフ内で右クリックからGet Object Variableノードを選択します。
Get Object VariableノードにisPlayingを指定し、その出力ノードにOn State Changedノードを設定します。
更に先ほどのボタン押下と同様にIFノードを接続し、その出力を受け渡すようにします。
これで再生状態(isPlaying)の変数の値の切り替わりを検知して状態のTrue/Falseを判定するフローが作成できました。
次回はこのIFノードを使って再生(True)に切り替わったときにビデオを再生し、停止(False)に切り替わったときにビデオを停止する処理を記述します。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
Starting Point.unityのシーンではビデオの再生用オブジェクトが予め設定されています。
Videoオブジェクトにはビデオクリップを指定したVideoPlayerコンポーネントが設定されていますが、初期状態ではオブジェクトが無効化されています。
ここからシーンにボタンを追加し、ボタンを押すとVideoが有効化されてビデオが再生される仕組みを作り込んでいきます。
Assetsフォルダの[In Package]から以下のButtonBase.prefabを検索し、シーンの3.1--Videoオブジェクト配下に配置します。
ButtonBaseオブジェクトを配置したらTransformをPosition X:0, Y:1, Z:0に調整し、ビデオ画面の真下にボタンを移動します。
ボタンのオブジェクト名を分かりやすい名前に変更します。今回はPlayVideoButtonとします。
更にボタンの表示テキストを Play に変更します。
オブジェクトを展開してLabelオブジェクトの[TextMeshPro-Text]コンポーネントの[Label]に Play を入力してテキストを変更します。
次にボタン押下時に実行されるビジュアルスクリプトを作成します。
再びPlayVideoButtonオブジェクトを選択し、Inspectorビューから[Script Machine]コンポーネントを追加します。
追加された[Script Machine]コンポーネントの[Source]で[Emded(埋め込み)]を選択します。
Embedは中間オブジェクト変数なしにノードを直接編集可能です。
[Title]と[Summary]にスクリプトの名前と説明を入力します。
Script Machineの[Source]オプションによる機能の違いは以下のページを参照ください。
docs.unity3d.com
[Edit Graph]をクリックして[Script Graph]画面が表示します。
ここでビジュアルスクリプトの編集を行います。
デフォルトでは[OnStart]ノードと[OnUpdate]ノードが生成されていますが、これらのノードは利用しません。
ノードを右クリックして[Delete]を実行して削除します。
ボタン押下時のビジュアルスクリプトでは以下の機能を実装します。
1.ボタンのクリックを検出する
2.クリックと同時にビデオを再生する
3.再生中に再びクリックされた場合はビデオを停止する
初めにボタンの押下を検知できるようにします。
PlayVideoButtonオブジェクト配下のButtonオブジェクトをスクリプト画面にドラッグします。
Nodeメニューが開くので[Button]を選択します。
すると[Button]の参照を持ったGameObjectノードが追加されます。
Buttonオブジェクトには MeshInteractableSetup オブジェクトが設定されており、これを利用して操作を検知できます。
ボタン押下時の操作を検知するにはGameObjectノードのアウトポートをクリックドラッグしてNodeメニューを表示します。
[Mesh Interactable Body: IsSelected]ノードがボタン押下の検知ノードなのでこれを選択します。
Mesh Interactable Body: IsSelectedはボタンが押下状態のときに True を、そうでないときに False を出力し続けます。
状態が変化した瞬間のみを検知するため、さらに[Microsoft Mesh: On State Changed]ノードを接続します。
[Microsoft Mesh: On State Changed]ノードは受け取る値が変化したタイミングのみ、その結果を出力します。
これにより、Buttonオブジェクトが押下状態に切り替わったときに True が通知され、押下状態が終了したときに False が通知されるノードのフローが作成できました。
次回はビジュアルスクリプトでこのノードから更にビデオを再生する処理を記述していきます。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
Meshアバターは以下の移動制限のもと、コライダーが設定された床の上を歩行できます。
最大歩行可能勾配: <45度 最大ステップ高さ: 0.3 アバター カプセルの半径: 0.3 アバター カプセルの高さ: 2 アバターの高さ: 1.8
このほか、テレポート機能を利用してMeshアバターは任意の遠距離の床に直接移動することができます。
ただしテレポートを利用するには対象の床に適切なレイヤー設定がなされている必要があります。
learn.microsoft.com
テレポートを利用するには対象の床にGroundCollisionレイヤーが設定されている必要があります。
Starting Point.unityの初期状態では開始地点の床オブジェクトのレイヤーが[GroundCollision]に設定されています。
シーンを再生してテレポート機能を試してみます。
エディター上ではマウスの右クリックを押したまま左クリックを行うとポインターした場所にテレポートすることができます。
試しに床オブジェクトのレイヤーを[Default]に変更してみます。
この状態でシーンを再生してテレポート機能を試してみます。
テレポートを試そうとするとポインターが赤色表示になり、レイヤーが[Default]の床にはテレポートが利用できないことが分かります。
次回はビジュアルスクリプトを使って動画を再生するボタンを作成します。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
Finished Project.unityのシーンを開きます。
初めにシミュレーション環境の構築を行ってみます。
エディター上で環境の動作確認を行いたい場合はMeshEmulatorSetup [NoUpload].prefabがシーンに配置されている必要があります。
Packages/Microsoft Mesh Toolkit/mesh.toolkit.emulator/Prefabs/MeshEmulatorSetup [NoUpload].prefab
[initial Screen Count]の変数でシミュレーションする接続人数を指定できます。
1 を指定すると単独のアバターで動作確認を行います。
複数人でシーンの同期を確認したい場合には 2 以上を指定して別のアバターには環境がどのように同期されるかを確認することもできます。
サムネイルカメラを設定すると、環境をMeshページにアップロードした際に自動でサムネイル画像を生成してくれます。
Hierarchy上で右クリックから[Mesh Toolkit -> Thumbnail Camera]を選択してカメラオブジェクトを作成します。
追加されたMeshThumbnailCameraオブジェクトを選択すると、Scene画面にプレビューが表示されます。
例えば風力タービンを映したサムネイルを生成したい場合は以下の通りTransformを設定します。
Position X:8.3, Y:64.7, Z:44.2 Rotation X:22.8, Y:-37.3, Z:3.1
これでシミュレーション環境の構築とサムネイルカメラの設定は完了です。
次回はアバターがワープ可能な床の設定を行います。
bluebirdofoz.hatenablog.com
Mesh 101 チュートリアルはUnityプロジェクトでMesh環境を構築する方法を学ぶためのチュートリアルです。
Meshへの相互作用の追加や物理演算、ビジュアルスクリプトの設定などの機能について理解できます。
learn.microsoft.com
以下のGitHubプロジェクトをクローンして取得するか、Zipファイルでプロジェクトをダウンロードします。
今回は[Download ZIP]からzipファイルをダウンロードしました。
github.com
ダウンロードしたMesh-Toolkit-Unity-main.zipファイルを適当なフォルダに展開します。
解凍フォルダ直下に、フォルダ毎にサンプルシーンが分けられています。
今回はMesh 101を利用します。
MeshサンプルはUnity 2022.3.7f1で作成されています。該当バージョンのUnityのインストールが必要です。
以下のアーカイブページからインストールを実行してください。
unity.com
PC向けとQuest向けのシーンをビルドするため、インストール時に以下のモジュールを選択します。
・Android Build Support
・Windows Build Support (IL2CPP)
UnityHubを起動し、Meshサンプルを開きます。
[Add project from disk]から先ほど展開したフォルダを指定してプロジェクトを開きます。
プロジェクトが開いたらシーンを開いてサンプルを確認します。Mesh 101では以下のシーンファイルが用意されています。
Assets/Scenes/Starting Point.unity:チュートリアル用の一部構成が未了になっているシーン Assets/Scenes/Finished Project.unity:正確な完成のシーン
Finished Project.unityのシーンを開いてエディターの[再生]ボタンを押すと、完成版のイベント会場を歩き回って動作を確認できます。
次回からはStarting Point.unityのシーンを用いてMesh環境を構築する方法を学んでいきます。
次の記事はシミュレーション環境の構築とサムネイルカメラの設定です。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
イベント会場をアップロードするにはあらかじめMeshポータルでコレクションを作成する必要があります。
以下のMeshポータルにログインして[コレクション]タブを開きます。
mesh.cloud.microsoft
コレクション画面が開くので[コレクションの作成]ボタンをクリックします。
作成するコレクションの名前とプライバシー設定を設定して[コレクションの作成]を実行します。
コレクションはイベント会場の環境やテンプレートを保存しておく枠組みになります。
これでコレクションが作成できました。
メニューから[Mesh Toolkit -> Environments]を開きます。
先ほどコレクションを作成したMSアカウントで[Sign in]を行います。
新しいイベント会場をアップロードする場合、初めに[Create Environment]タブを開きます。
入力欄から以下の項目を入力して[Create Environment]をクリックします。
・Internal Name:会場名
・Description:説明文
・Environment collection:追加先のコレクション
・Capacity:入場可能人数
完了後、[Update Environment]タブを開くとイベント会場の情報が追加されています。
[Select a scene]をクリックし、会場として利用するシーンファイルを指定します。
次にビルドターゲットを指定します。PC向けまたはAndroid(Quest)向け、あるいはその両方が指定できます。
設定が完了したら[Build & Publish]ボタンを押すと、会場のビルドとアップロードが開始されます。
処理が完了すると以下の結果ダイアログが表示されます。これで会場のアップロードは完了です。
Meshポータルから作成したコレクションを確認すると、[環境]一覧でアップロードした会場が確認できます。
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
以下のような会場のベースとなるシーンを基本オブジェクトの組み合わせで作成しました。
トラベルポイントはイベントに参加するアバターが配置される場所を定義します。
MeshToolkitをインポートしていると、Hierarchy上で右クリックから[Mesh Toolkit -> Travel Point Group]を選択できます。
TravelPointGroupオブジェクトが作成されます。
アバターをスポーンさせたい位置に子オブジェクトの TravelPoint を移動します。
トラベルポイントを設定していない場合はシーンの原点(X:0,Y:0,Z:0)にアバターがスポーンすることになります。
またGroupは複数作成することができ、この場合は特定のGroupをデフォルトのスポーングループとして指定する必要があります。
learn.microsoft.com
サムネイルカメラを設定すると、会場をアップロードするたびに自動でサムネイル画像を生成してくれます。
Hierarchy上で右クリックから[Mesh Toolkit -> Thumbnail Camera]を選択してカメラオブジェクトを作成します。
[Scene]画面を開き、カメラオブジェクトを選択するとプレビューを確認できます。
Transformを調整して任意の位置にします。
サムネイルカメラを設定していない場合は原点(X:0,Y:0,Z:0)からの視点がサムネイルとして撮影されます。
learn.microsoft.com
エミュレーションモードを利用すると、エディター上でシーンの動作確認を行うことができます。
エディターの[再生]ボタンをクリックします。
シーンにエミュレーションモードの設定がされていない場合、以下のセットアップダイアログが表示されます。
[Add MeshEmulatorSetup prefab]をクリックするとエミュレーションモードの設定が行われます。
エミュレーションモードではWASDキーの操作でシーンの中を歩き回ったり、コンテンツを試すことができます。
一度セットアップを行うとHierarchyに[MeshEmulatorSetup]オブジェクトが追加され、以降は[再生]すると自動でエミュレーションモードが利用できます。
セットアップダイアログで[Add dummy ...]の方を選択するとダミーオブジェクトが追加されます。
この場合、エミュレーションモードは有効にならず、また以降のセットアップダイアログの表示も行われなくなります。
learn.microsoft.com
次回は環境のアップロードの手順です。
bluebirdofoz.hatenablog.com
MeshToolkitパッケージを利用すると新しいプロジェクトからMeshのイベント会場を構築することができます。
環境の開発、イテレーション、パフォーマンスの最適化、公開を制御できるほか、環境に対話型コンテンツを追加したり、ロジックを挿入することもできます。
learn.microsoft.com
[3D (URP)]のテンプレートを使用し、[Create Project]で新しいUnityプロジェクトを作成します。
生成されたUnityプロジェクトの[Global Volume]オブジェクトを右クリックから[Delete]で削除します。
シーンは任意の名前で保存します。
PackageManagerでMeshToolkitパッケージをインポートします。
メニューから[Edit -> Project Settings]を開き、Project Settingsダイアログの[Pakcage Manager]タブを開きます。
[Scoped Registries]に以下の参照を追加して[Save]します。
Name:任意の名前 URL:https://registry.npmjs.org Scope:com.microsoft
次にメニューから[Window -> Package Manager]を開きます。
[Packages]のプルダウンを開き、[My Registries]を選択します。
一覧に[Microsoft Mesh Toolkit]が表示されるので、これを選択して[Install]します。
MeshToolkitをインポートすると、以下のMesh向けプロジェクト設定を行うダイアログが表示されます。
[Apply Project Settings]を選択して設定を反映します。
本設定を行うと以下の設定が行われます。
・PCまたはAndroidの[XR Plugi-in]で[OpenXR]が選択される
・TextMeshProがインポートされる
PackageManagerの一覧に表示されるMicrosoft Mesh Toolkit(Preview)パッケージの方は開発者向けのプレビュービルドです。
安定バージョンのMicrosoft Mesh Toolkitと互換性がないため、使用する際は注意が必要です。
次回はシーンの基本構築の手順です。
bluebirdofoz.hatenablog.com
Unity glTFastはglTF形式のファイルをサポートするためのパッケージです。
元々OSSで開発されていたパッケージですが、現在はUnity公式パッケージとしてサポートされるようになりました。
docs.unity3d.com
glTFastを利用するにはPackageManagerから取得する必要があります。
メニューから[Window -> Package Manager]を開きます。
Package Managerダイアログの[+]ボタンのプルダウンを開き、[Add package by name...]を選択します。
パッケージ名の入力欄に以下のパッケージ名を指定し、[Add]を実行します。
com.unity.cloud.gltfast
これでUnity glTFastのインポートは完了です。
Unity glTFastをインポートしていればAssetsフォルダにglbファイルをドラッグするだけで3Dモデルをプロジェクトに取り込むことができます。
取り込んだ3Dモデルはそのまま[Hierarchy]にドラッグしてシーンに配置することができます。
Unity glTFastをインポートしていればGameObjectをglbファイルとして書き出すことができます。
AssetsフォルダのPrefabファイルを右クリックして[Export glTF -> glTF-Binary (.glb)]を実行します。
出力したglbファイルをBlenderで確認すると以下の通り3Dモデルを確認できます。
エクスポートはシーン再生中の[Hierarcy]にも対応しています。
以下のようなシーンを再生するとCubeが落下するシーンを作成しました。
シーンを再生し、出力したい[Hierarchy]上のGameObjectを任意のタイミングで右クリックして[Export glTF -> glTF-Binary (.glb)]を実行します。
すると以下の通り、出力したタイミングの状態でglbファイルが出力されます。
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
以下のWebページにアクセスしてMSアカウントでログインします。
mesh.cloud.microsoft
ページ左側の[イベント]ボタンをクリックします。
[イベント]ページが開きます。
新規にイベントを作成する場合は画面右上の[イベントを作成]をクリックします。
[イベントの詳細]ページが開くのでイベントの詳細情報を設定します。
[イベント名]、[開始/終了時刻]のみ必須の入力項目になります。
3D空間のベースを選択します。
今回はアップロードした会場を基に新規作成したいので[環境から開始する]を選択し、[次へ]をクリックしました。
[コレクションから]のプルダウンを開き、会場を登録したコレクションを選択します。
前回コレクションにアップロードした会場を一覧から選択して[次へ]をクリックします。
次にこの会議に招待するユーザを入力します。
[イベントを作成]をクリックするとイベントが作成され、招待ユーザにイベントが通知されます。
イベントを作成すると、イベントページに表示されるようになります。
[イベントの詳細]から詳細を確認できます。
PCまたはQuestからイマーシブスペースに参加する手順は以下を参照ください。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com
以下の通り、登録した会場のイベントに参加できました。
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
イベント会場をアップロードするにはあらかじめMeshポータルでコレクションを作成する必要があります。
以下のMeshポータルにログインして[コレクション]タブを開きます。
mesh.cloud.microsoft
コレクション画面が開くので[コレクションの作成]ボタンをクリックします。
作成するコレクションの名前とプライバシー設定を設定して[コレクションの作成]を実行します。
コレクションはイベント会場の環境やテンプレートを保存しておく枠組みになります。
これでコレクションが作成できました。
作成したコレクションにMeshサンプルのイベント会場をアップロードします。
初めにメニューから[Mesh Toolkit -> Configure -> Apply Project Settins]を実行してMesh向けのプロジェクト設定を構成します。
メニューから[Mesh Toolkit -> Environments]を開きます。
[Mesh Environments]ダイアログが開くので先ほどコレクションを作成したMSアカウントで[Sign in]を行います。
新しいイベント会場をアップロードする場合、初めに[Create Environment]タブを開きます。
入力欄から以下の項目を入力して[Create Environment]をクリックします。
・Internal Name:会場名
・Description:説明文
・Environment collection:追加先のコレクション
・Capacity:入場可能人数
コレクションが存在しない場合、以下のように[Environment collection]欄に No Environment... が表示されて[Create Environment]が実行できません。
前述のコレクション作成を実施するか[Refresh Environment collections]ボタンで情報の再読み込みを試してみてください。
[Update Environment]タブを開くと、イベント会場の情報が追加されています。
[Select a scene]をクリックし、会場として利用するシーンファイルを指定します。
次にビルドターゲットを指定します。PC向けまたはAndroid(Quest)向け、あるいはその両方が指定できます。
[Build & Publish]ボタンを押すと、会場のビルドとアップロードが開始されます。
処理が完了すると以下の結果ダイアログが表示されます。これで会場のアップロードは完了です。
Meshポータルから作成したコレクションを確認すると、[環境]一覧でアップロードした会場が確認できます。
次回は作成した会場を使ってイベントを開催する手順です。
MeshサンプルはMicrosoftMeshで作成できる様々な種類の体験を学習するためのサンプルプロジェクトです。
以下の5種類のサンプルシーンが含まれています。
・Mesh 101
・Toybox
・Physics Effects Gallery
・Dart Room
・Science Building
learn.microsoft.com
今回はこのうちのScience Buildingを使って、イベント会場を作成する手順を試します。
以下のGitHubプロジェクトをクローンして取得するか、Zipファイルでプロジェクトをダウンロードします。
今回は[Download ZIP]からzipファイルをダウンロードしました。
github.com
ダウンロードしたMesh-Toolkit-Unity-main.zipファイルを適当なフォルダに展開します。
解凍フォルダ直下に、フォルダ毎にサンプルシーンが分けられています。
今回はScience Buildingを利用します。
MeshサンプルはUnity 2022.3.7f1で作成されています。該当バージョンのUnityのインストールが必要です。
以下のアーカイブページからインストールを実行してください。
unity.com
PC向けとQuest向けのシーンをビルドするため、インストール時に以下のモジュールを選択します。
・Android Build Support
・Windows Build Support (IL2CPP)
UnityHubを起動し、Meshサンプルを開きます。
[Add project from disk]から先ほど展開したフォルダを指定してプロジェクトを開きます。
プロジェクトが開いたらシーンを開いてサンプルを確認します。
Science Buildingでは以下のシーンファイルを開いてイベント会場を確認できます。
Assets/Scenes/ScienceBuilding.unity
エディターの[再生]ボタンを押すと、イベント会場を歩き回って動作を確認できます。
次回はイベント会場のアップロードの手順です。
bluebirdofoz.hatenablog.com
確認したいワークスペースのタブを開きます。
ファイル基準でログを確認したい場合、[View all files]にチェックを入れます。
これでGitで管理されている全てのファイルがTree形式で表示されます。
検索欄に確認したいファイル名を入力します。
ファイルを選択するとFileView画面が表示されるので、[History]ボタンをクリックします。
これで選択したファイルに関連するGitログを確認できます。
更に特定行の変更履歴を確認したい場合は、FileView をスクロールして変更履歴を確認したい行の左側のアイコンをクリックします。
その行が変更されたコミットに移動するので[DiffView]に切り替えます。
これで特定ファイルの特定行の変更履歴を確認することができました。
NuGetは.NET開発向けのパッケージマネージャーです。
NuGet Galleryはパッケージ作成者と使用者のための中央パッケージリポジトリです。
www.nuget.org
VisualStudioプロジェクトでNuGet Galleryからパッケージを取得するにはメニューから[プロジェクト -> NuGetパッケージの管理]を選択します。
[NuGet]画面が開くので[参照]タブを開き、欲しいパッケージ名を検索欄に入力します。
一覧から目的のパッケージを選択し、[インストール]ボタンをクリックするとパッケージのインストールが開始します。
インストール済みのパッケージは[インストール済み]タブから確認できます。
メニューで[NuGetパッケージの管理]が表示されない場合はVisualStudioInstallerからコンポーネントがインストールされているか確認します。
VisualStudioInstallerを起動し、[変更]ボタンをクリックします。
変更ダイアログが開くので[個別のコンポーネント]タブを開きます。
[コードツール -> NuGet パッケージマネージャー]を確認し、インストールされていない場合はインストールを実行します。
UnityでNuGetを利用してパッケージを取得したい場合配下の記事を参照ください。
bluebirdofoz.hatenablog.com
Microsoft MeshのイマーシブスペースはTeamsで利用可能な会議用の3Dデジタル空間です。
利用者はTeams会議の空間オプションを選択するだけで簡単に利用することができます。
learn.microsoft.com
Teamsのイマーシブスペースを利用するには以下のいずれかのライセンスを持ったMicrosoftアカウントが必要です。
・Teams Essentials
・Microsoft 365 Business Basic
・Microsoft 365 Business Standard
・Microsoft 365 Business Premium
・Microsoft 365 E3/E5
・Office 365 E1/E3/E5
今回のイベント作成手順に関する公式のドキュメントページは以下になります。
本記事ではこちらの手順を試しています。
learn.microsoft.com
以下のWebページにアクセスしてMSアカウントでログインします。
mesh.cloud.microsoft
ページ左側の[イベント]ボタンをクリックします。
[イベント]ページが開きます。
新規にイベントを作成する場合は画面右上の[イベントを作成]をクリックします。
[イベントの詳細]ページが開くのでイベントの詳細情報を設定します。
[イベント名]、[開始/終了時刻]のみ必須の入力項目になります。
3D空間をカスタマイズする場合、開催の30分前に全ての設定を完了することが推奨されています。
今回はデフォルトの3D空間を利用したので直前の設定でも問題ありませんでした。
learn.microsoft.com
3D空間のベースを選択します。[テンプレート]では自由にカスタマイズした3D空間をテンプレートとして残しておくことができます。
今回はデフォルトの[環境から開始する]を選択し、[次へ]をクリックしました。
デフォルトで提供されている環境から利用したい3D空間を選択し、[次へ]をクリックします。
次にこの会議に招待するユーザを入力します。
[イベントを作成]をクリックするとイベントが作成され、招待ユーザにイベントが通知されます。
イベントを作成すると、イベントページに表示されるようになります。
[イベントの詳細]から詳細を確認できます。
PCまたはQuestからイマーシブスペースに参加する手順は以下を参照ください。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com
Microsoft MeshのイマーシブスペースはTeamsで利用可能な会議用の3Dデジタル空間です。
PC、Meta Quest 2、Meta Quest 3、および Meta Quest Pro デバイスで利用可能です。
learn.microsoft.com
Teamsのイマーシブスペースを利用するには以下のいずれかのライセンスを持ったMicrosoftアカウントが必要です。
・Teams Essentials
・Microsoft 365 Business Basic
・Microsoft 365 Business Standard
・Microsoft 365 Business Premium
・Microsoft 365 E3/E5
・Office 365 E1/E3/E5
MicrosoftMeshは[Microsoft Store]からインストールできます。
検索欄で[Microsoft Mesh]を検索すると、MicrosoftMeshアプリが見つかります。
MicrosoftMeshのページが開くので[入手する]ボタンを押下してインストールを開始します。
インストールが完了したらそのままアプリを[スタート]します。
初回設定ではMicrosoftアカウントの「サインイン」を行います。
(著者環境では文字化けが発生しましたが、左側が「サインイン」右側が「終了」ボタンになります)
サインインが完了すると、使用許諾契約の確認ダイアログが表示されるので[同意して続行]をタップします。
サインインしたアカウントで参加可能な会議スケジュールが表示されます。
任意の会議を選択して[参加]をタップします。
これでイマーシブスペースに参加できます。
通常のTeamsアプリからもイマーシブスペースに参加することができます。
会議画面で[表示]メニューから[イマーシブ スペース (3D)]を選択します。
アバターの設定を行い、[今すぐ入る]を選択します。
これでTeamsアプリからイマーシブスペースに入室できました。
Quest3でイマーシブスペースを利用する手順については以下の記事を参照ください。
bluebirdofoz.hatenablog.com
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
RemoveAsync関数を利用するとアカウントを指定してアプリケーション内に保存されているユーザー・トークンのキャッシュを削除できます。
あらかじめGetAccountsAsync関数で全てのアカウントの参照を取得することで、保存されている全てのキャッシュを削除できます。
learn.microsoft.com
var app = PublicClientApplicationBuilder.Create(clientId).Build(); // 利用可能なユーザー・トークンのリストを取得する var accounts = await app.GetAccountsAsync(); // アカウント情報を削除する foreach (var account in accounts) { await app.RemoveAsync(account); }
前回記事で作成したサンプルスクリプトに以下の処理を追加しました。
Removeボタンを押下すると、キャッシュされているトークンを全て削除します。
・AzureMsalTest.cs
[SerializeField] private Interactable removeButton; ~~~ 中略 ~~~ removeButton.OnClick.AddListener(async () => { var argTenantId = tenantId; var argClientId = clientId; var argScopes = scopes; var argLoginHint = loginHint; #if WINDOWS_UWP string[] scopeList = { "openid", "profile", "offline_access", argScopes }; try { var app = Microsoft.Identity.Client .PublicClientApplicationBuilder .Create(argClientId) .WithAuthority( Microsoft.Identity.Client.AzureCloudInstance.AzurePublic, argTenantId) .WithRedirectUri("http://localhost:50000/") .Build(); var accounts = await app.GetAccountsAsync(); // 全てのアカウント情報をパネルに表示する string logTextString = "GetAccountsAsync" + Environment.NewLine; foreach (var account in accounts) { logTextString += $"{account.Username},{account.HomeAccountId},{account.Environment}" + Environment.NewLine; } // アカウント情報を削除する foreach (var account in accounts) { await app.RemoveAsync(account); } var resultAccounts = await app.GetAccountsAsync(); logTextString += "RemoveAsync" + Environment.NewLine; // 全てのアカウント情報をパネルに表示する foreach (var resultAccount in resultAccounts) { logTextString += $"{resultAccount.Username},{resultAccount.HomeAccountId},{resultAccount.Environment}" + Environment.NewLine; } logText.text = logTextString; } catch (Exception e) { logText.text = "Remove error"; } #endif });
プロジェクトを再ビルドしてHoloLens2にデプロイします。
Removeボタンを押すと、アプリ内にキャッシュされている全てのトークンを削除できました。
Gmailでは1つのアカウントで複数のメールアドレスを作成して使い分けることができます。
生成可能なメールアドレスは「(元のメールアドレス)+(任意の文字列)@Gmail.com」になります。
Gmailを開き、画面右上の[歯車]アイコンをクリックします。
[クイック設定]が開くので[全ての設定を表示]をクリックします。
これで詳細設定の画面が開きます。
[アカウントとインポート]タブを選択し、[他のメールアドレスを追加]をクリックします。
メールアドレスの追加ダイアログが表示されます。
以下のフォーマットの[メールアドレス]を指定すると新しいメールアドレスが作成されます。
(元のメールアドレス)+(任意の文字列)@Gmail.com
作成に成功すると以下の通り、追加されたメールアドレスが表示されます。
[メールアドレス]で外部のメールアドレスを指定すると以下のダイアログが表示され、入力したメールアドレスに確認メールが送信されます。
外部のメールアドレス側で確認メールのチェックを完了すると、外部のメールアドレスの追加が行えます。
また新しいメールアドレスを作成したいのに上記のダイアログが表示される場合は前述のフォーマットに従ったメールアドレスを入力できていない可能性があります。
デフォルトではそれぞれのメールアドレスに届くメールは全て同じ受信トレイに保存されます。
メールアドレスごとに受信メールを分別したい場合はフィルタを設定します。
初めに分別用のラベルを作成します。
左側の一覧の[もっと見る]をクリックします。
[新しいラベルを作成]をクリックします。
メール分別用のラベル名を入力してラベルを[作成]します。
次にラベルにフィルタを設定して指定のメールアドレスに届いたメールだけ保存するようにします。
[ラベルの管理]をクリックします。
フィルタの設定パネルが表示されるので[To]欄に分別したいメールアドレスを入力します。
これで[フィルタを作成]します。
更に設定パネルが表示されるので以下の設定を有効にします。
・受信トレイをスキップ(アーカイブする):本設定を有効にするとラベルに保存されたメールは受信トレイ側に残りません
・ラベルを付ける:フィルタを利用するラベルを指定します。ここでは先ほど作成したラベルを指定します。
これで指定のメールアドレスの受信メールが作成したラベルに分別されるようになりました。
以下のGoogleページの[ログイン]ボタンをクリックしてログイン画面を表示します。
www.google.co.jp
新規アカウントを作成したい場合は[アカウントを作成]をクリックし、作成アカウントの用途を選択します。
今回は[個人で使用]を選択しました。
アカウントで使用する姓名を入力します。
デフォルトの設定ではここで設定した名前は公開情報になるので注意してください。後からニックネームを設定することも可能です。
生年月日を入力します。生年月日はデフォルトでは非公開情報になります。
Gmailのアドレスを設定します。デフォルトで名前の入力を基に利用可能なアドレス候補が表示されます。
既存のメールアドレスを利用してGoogleアカウントを作成したい場合は[既存のメールアドレスを使用する]を選択してください。
今回は新しいメールアドレスを作成したいので[自分でGmailアドレスを作成]を選択しました。
任意のメールアドレスを入力して[次へ]をクリックします。
パスワードを設定します。任意のパスワードを入力して[次へ]をクリックします。
再設定用のメールアドレスの追加ページが開きます。本設定はスキップ可能です。
メールアドレスを設定しておけばアカウントが利用できなくなった場合などにアカウントの再設定ができます。
アカウント情報の確認ページが表示されます。
アカウントの名前とメールアドレスが表示されるので確認して[次へ]をクリックします。
利用規約の確認画面が表示されます。確認の上、ページ下部の[同意する]をクリックします。
MicrosoftMeshは3D仮想空間で会議やイベント空間を提供します。
PC、Meta Quest 2、Meta Quest 3、および Meta Quest Pro デバイスで利用可能です。
www.meta.com
MicrosoftMeshを使って仮想空間を利用するには以下のいずれかのライセンスを持ったMicrosoftアカウントが必要です。
・Teams Essentials
・Microsoft 365 Business Basic
・Microsoft 365 Business Standard
・Microsoft 365 Business Premium
・Microsoft 365 E3/E5
・Office 365 E1/E3/E5
MicrosoftMeshは[ストア]からインストールできます。
検索欄で[mesh]を検索すると、MicrosoftMeshアプリが見つかります。
MicrosoftMeshのページが開くので[入手する]ボタンを押下してインストールを開始します。
インストールが完了したらそのままアプリを[スタート]します。
初回設定ではMicrosoftアカウントのログインを行います。
以下の通り、ログインURLとアクティブコードが表示されます。
本記事では以下の記事で作成したシーンモデルの使用を有効にした Unity プロジェクトを基に設定を行います。
bluebirdofoz.hatenablog.com
シーンモデルのメッシュを参照してマテリアルなどを設定するには前回のシーンモデルの利用設定に加えて以下の作業が必要になります。
・シーンモデルのメッシュ設定を上書きするプレハブを作成する
・OVRSceneManagerにプレハブを指定する
初めにシーンモデルのメッシュ設定を上書きするプレハブを作成します。
Hierarchy上で右クリックから[Create Empty]でプレハブのベースオブジェクトを作成します。
作成したオブジェクトに以下のコンポーネントを設定します。
・OVRSceneAnchor
・OVRSceneVolume
・OVRSceneVolumeMeshFilter
・MeshCollider
・MeshRenderer
・MeshFilter
MeshRendererのMaterialsに任意のマテリアルを設定します。
ここで設定したマテリアルでシーンモデルのメッシュが表示されるようになります。
今回は以下のサンプルマテリアルを使用しました。
PackageCache\Meta MR Utility Kit\Editor\BuildingBlocks\BlockData\RoomModel\Volume.mat
作成したゲームオブジェクトをAssetsにドラッグしてプレハブを作成します。シーン上のプレハブは削除します。
次に作成したプレハブがシーンモデルのメッシュに利用するよう設定を行います。
OVRSceneManagerコンポーネントの[Prefab Overrides]の[+]ボタンをクリックします。
追加した要素を[GLOBAL_MESH]に指定します。
これでシーンモデルのメッシュに対して指定したプレハブが利用されます。
[Prefab]に先ほど作成したプレハブを指定します。
これで設定は完了です。
以下の記事を参考にプロジェクトのビルドとQuest3へのデプロイを実行してください。
bluebirdofoz.hatenablog.com
MetaQuest3でデプロイしたアプリを起動します。
アプリが起動すると指定したマテリアルが設定された物理空間のメッシュが表示されます。
Quest3では現実の部屋の形状をスキャンして「スペース」として保存することができます。
スペースは複合現実アプリケーションで利用され、仮想オブジェクトに現実の物体が作用する複合現実の体験が可能になります。
「スペース」は「プレイエリア」とは異なる情報である点に注意が必要です。
歩行モードのプレイエリアを設定していても「スペース」が設定されていない場合があります。
Quest3のホーム画面を表示して[クイック設定]画面を開き、右上の[設定]ボタンをクリックして設定画面を開きます。
設定から[物理空間]タブを開きます。
[スペースの設定]タブを開き、スペースの設定欄の[設定]を実行します。
以下のスペース設定のダイアログが表示されるので[次へ]をタップします。
するとQuest3のセンサを利用した現実空間のスキャンが始まります。
案内に従い、部屋を歩き回り部屋の形状をスキャンしていきます。
一定の範囲を歩き回り、十分にスキャンを行うと以下の完了ダイアログが表示されるので[次へ]をタップします。
スキャンした形状から部屋の壁と認識する箇所の位置調整が求められます。
調整が完了したら[次へ]をタップします。
スキャンしたスペースを識別するための名前を選択します。
ここで選択した名前は[スペースの管理]一覧で表示されます。
これでスペースで最低限必要なスキャンは[完了]できます。
[家具を追加]をタップして、更に追加で机、ドア、窓などの設定を行うこともできます。
例えばドアを設定する場合は、壁面をタップして長方形の範囲を指定して[ドア]を選択します。
これで指定した範囲をドアとして登録できます。
家具の指定を完了したらダイアログの[すべてのオブジェクトの輪郭を完成]をタップしてスペースの設定作業を[完了]できます。
作成したスペースは[スペースを管理]の一覧で確認できます。
スペースの再設定を行ったり、不要になったスペースを削除することができます。
WriteAllTextは新しいファイルを作成し、文字列を書き込みます。
書き込み時に文字列のエンコーディングを引数で指定することができます。
learn.microsoft.com
System.IO.File.WriteAllText(filePath, text, encoding);
ReadAllTextは指定のファイルを開き、内容を文字列として読み込みます。
読み込み時に文字列のエンコーディングを引数で指定することができます。
learn.microsoft.com
string text = System.IO.File.ReadAllText(filePath, encoding);
以下の通り、エンコーディングを指定せずWriteAllText/ReadAllTextで入出力を行う関数と、エンコーディングを指定してWriteAllText/ReadAllTextで入出力を行う関数を持つサンプルスクリプトを用意しました。
それぞれの処理結果と出力されたテキストファイルを確認します。実行環境はWindowsPC上のUnityEditorです。
・TextEncodeFileTest.cs
using TMPro; using UnityEngine; public class TextEncodeFileTest : MonoBehaviour { [SerializeField] private TMP_Text _TMPtext; [ContextMenu("EncodingDefaultTest")] public void EncodingDefaultTest() { // デフォルトの文字コードのテキストファイルを出力する WriteDefaultTextFile(); // デフォルトの文字コードのテキストファイルを読み込む ReadDefaultTextFile(); } private void WriteDefaultTextFile() { // テキストファイルに入力する文字列 string text = "Defaultはろーわーるど"; // 文字列をデフォルトの文字コードのテキストファイルとして出力する string filePath = Application.streamingAssetsPath + "/test_default.txt"; System.IO.File.WriteAllText(filePath, text); } private void ReadDefaultTextFile() { // デフォルトの文字コードを指定してテキストファイルから文字列を読み込む string filePath = Application.streamingAssetsPath + "/test_default.txt"; string utf8Text = System.IO.File.ReadAllText(filePath); _TMPtext.text = utf8Text; } [ContextMenu("EncodingShiftJISTest")] public void EncodingShiftJISTest() { // Shift-JISの文字コードのテキストファイルを出力する WriteShiftJISTextFile(); // Shift-JISの文字コードのテキストファイルを読み込む ReadShiftJISTextFile(); } private void WriteShiftJISTextFile() { // テキストファイルに入力する文字列 string text = "ShiftJISはろーわーるど"; // 文字列をShift-JISの文字コードのテキストファイルとして出力する string filePath = Application.streamingAssetsPath + "/test_shiftJIS.txt"; System.IO.File.WriteAllText(filePath, text, System.Text.Encoding.GetEncoding("Shift-JIS")); } private void ReadShiftJISTextFile() { // Shift-JISの文字コードを指定してテキストファイルから文字列を読み込む string filePath = Application.streamingAssetsPath + "/test_shiftJIS.txt"; string text = System.IO.File.ReadAllText(filePath, System.Text.Encoding.GetEncoding("Shift-JIS")); _TMPtext.text = text; } }
JetBrains RiderでのGithub Copilotの利用手順配下の記事を参照ください。
bluebirdofoz.hatenablog.com
RiderでGithub Copilotが動作しない場合、画面下部の Copilot アイコンにマウスオーバーするとエラー内容を確認できます。
今回は以下のエラーメッセージが表示されていました。
Error: Your editor's Copilot extension is out of date. Please install a newer version to access this service. You may need to update your editor to install the newest extension version.
本エラーは GitHub Copilot Plugin のバージョンが古いことが原因です。
以下の手順でプラグインのアップデートを実施して対処します。
エディター右上の歯車ボタンのプルダウンを開き、[ダウンロード]項目を選択します。
[JetBrains Riderおよびプラグインのアップデート]ダイアログが開きます。
アップロード可能なプラグインの一覧が表示されるので[GitHub Copilot]を選択して[アップデート]を実行します。
プラグインのアップデートが完了するとRiderの再起動が求められるので、[再起動]を実行します。
以下の通り、プラグインが最新になりGithub Copilotが正常に動作するようになりました。
因みに現在インストール中のプラグインのバージョンは[歯車アイコン -> Plugins]を開き、[installed]タブで確認できます。
「HoloLab Conference」はホロラボとともに新しい技術をいち早く使いこなす企業様と、それを支えるエンジニアの経験を広く共有し繋がり、より多くの人たちがこれらの技術を体験できるようにすることを目的とした「場」です。
各企業様とホロラボが取り組みを進めてきたMixed Realityの実⽤に向けた取り組みや、BIM/3D CAD/3D CG/点群のような3Dデータ活用に向けた取り組み、GPS/VPS(Visual Positioning System)/PLATEAUのような空間情報技術活⽤に向けた取り組みの事例共有の場として「HoloLab Conference 2024」を開催します。
オンライン一般参加をご希望される方は、下記ページよりお申込みください。 https://connpass.com/event/311388
オンライン一般参加では、Zoomでのリアルタイムセッション視聴/質疑応答が可能です。
※当日のセッション視聴方法についてはお申し込みいただいた方に別途ご案内させていただきます。
実用に向けた取り組みをされている各社様とホロラボ合同の事例セッションと、基盤技術や技術調査などについての技術セッションの2種類のセッションを実施します。セッションは2タイムテーブルの進行で合計で最大15セッション程度を予定しています。
また、後日セッションをアーカイブ動画として公開する予定ですが、映像や音声へ編集が入る場合や一部セッションについては公開無しになる場合があります。ぜひリアルタイムでご参加ください。
株式会社ホロラボ イベント窓口:event@hololab.co.jp
]]>
弊社依頼時のクオリティサンプルとしてお手元でぜひご確認ください!
本手法によって作成される3D樹木モデルは実測に基づいており、かつ、樹木の点群データから3Dモデル化を行うためのアルゴリズムの使用により、実物に近い樹形の再現性を可能としております。
また、季節ごとの差分モデルによって、同じ樹木でも季節による違いを視覚的に確認することができます。
今回の樹木モデルをはじめ、空間スキャンやフォトグラメトリ・デジタルアーカイブ、デジタル空間&体験デザインなどの空間情報技術に特化したメンバーが在籍しています。
撮影からデータ整備、コンテンツ制作までを一貫して担当することができますので、ご興味ある方は下記よりお問い合わせください。
]]>このたび、Unityで手軽に使える画像認識パッケージのHoloLab DNN Packagesを公開しましたのでご紹介いたします。
HoloLab DNN Packagesは以下のリポジトリで公開されています。
HoloLab DNN PackagesはUnity Sentisをベースにディープラーニングによる画像認識を実装したパッケージ集です。
本パッケージには以下の特徴があります。
HoloLab DNN Packagesをセットアップする方法を紹介します。
HoloLab DNN Packagesはベースとなる1つのパッケージと画像認識のタスクが実装されたいくつかのパッケージで構成されています。
それぞれのタスクのパッケージはベースのパッケージに依存するので、ベースのパッケージとセットでインポートしてください。
パッケージのURLはそれぞれのパッケージのREADMEを参照してください。
HoloLab DNN Packagesのそれぞれのタスクのパッケージには直ぐに実行できる簡単なサンプルが含まれています。
ここでは、サンプルの実行方法を簡単に紹介します。
UnityのProjectウィンドウのSamplesフォルダにサンプルがインポートされます。
Scenesフォルダに含まれているシーンに切り替え、Unityの[Play]ボタンを押して実行してください。
サンプルは画像とボタンが1つずつ配置されたシンプルな画面になっています。
画像の下にある[Inference]ボタンを押すと推論が実行されて結果が表示されます。
(初期化があるので初回の実行のみ少し時間が掛かる可能性があります。)
基本的に以下の流れで画像認識を実装できるようになっています。
名前空間を参照する
using Unity.Sentis;
using HoloLab.DNN.Classification;
クラスのインスタンスを作成する
[SerializeField] private ModelAsset weights;
var model = new ClassificationModel(weights);
利用する学習済みモデルに合わせてパラメータを設定する
model.SetApplySoftmax(true);
メソッドに画像や閾値を渡して実行する
(var class_id, var score) = model.Classify(texture);
このように、HoloLab DNN Packagesを利用することで、ユーザーはわずか数行の記述で目的の画像認識を実装することができます。
スクリプトからの詳しい利用方法は、それぞれのサンプルのソースコードを参照してください。
Unityで手軽に使える画像認識パッケージのHoloLab DNN Packagesを紹介しました。
HoloLab DNN Packagesを利用してアプリに画像認識を組み込んでみてください。
CEOの中村です。
そろそろ Apple Vision Pro の米国発売から一週間経ちます。ホロラボもハワイにて Apple Vision Pro を無事に購入できました。
バックアップ及び空間共有機能のテストを含めてとりあえず2台。
ハワイ Ala MoanaのApple Storeにて受け取り。予定が16:30だったのですが、店員さんと会話して10:00に前倒し。
受け取りして同じくハワイに購入に来ていたジャーナリストの西田さんのところにお邪魔して場所を借りつつ開封の儀。
粛々とセットアップを行なっていました。
色々アンボックスしてる人々 pic.twitter.com/tC700dCgXT
— Munechika Nishida (@mnishi41) 2024年2月3日
単体のハードウェアとしての出来上がりは流石のApple品質。というところで、体験や操作をしてて「あれ?」というような引っかかりもなく、とても良いものと感じています。
ディスプレイ性能もよくコンテンツはドットも見ない高品質に表示され、ビデオシースルーも歪みやズレも少なくApple Vision Proを装着したまま室内の移動やスマートフォンの操作などができるほどです。
操作についても目で選択して、指のタップで選択。という他のデバイスに近い操作体系で特に迷うこともなく。
初見の方の場合は「目の操作」、「指でタップ」は慣れるまで難しいので、少し練習が必要です。ここはHoloLens 2などと同じですね。
アプリは現状では米国で公開されているアプリのみになりますが、 Apple Vision Pro 専用アプリのみならず、iOS/iPad OSのアプリとして公開されているものも(パブリッシャーの指定があれば)インストールしての利用が可能です。
左(最初)の画像が Apple Vision Pro専用アプリ、右(次)が iOS/iPad OS 互換アプリになります。
XやCatGPTなどの2Dで十分なアプリは、今までのアプリをそのまま利用可能になり、最初のアプリ数の壁を超えています。
仕事の環境として。という意味では、Microsoft TeamsやPower Point、 Excel、WordといったOfficeアプリはApple Vision Proのネイティブアプリとして公開されています。Outlook、OneNoteはiOS/iPad OS互換アプリとしてストアからインストールできます。
Bluetoothキーボードの接続もできるので、Apple Vision Proを装着しながら外部キーボードと合わせて業務が可能ですね。
Apple Vision Pro には外側にもディスプレイが付いており、自分の目の周辺を表示できます。
「ペルソナ」という機能でこのようにApple Vision Pro を持って自分で自分の顔をスキャンします。
賛否それぞれの感想を見ますが、個人的にはEyeSight は好きです。
Meta Quest 3など、今までのビデオシースルーでの経験で、HMD(Head Mounted Display)を装着している方は相手の表情が見えるけど、装着してない方は相手(装着している方)の表情が見えない関係だったので、力技にせよ同じような見え方になるのはより現実のコミュニケーションに近づくと考えています。
Apple Vision Proはハードウェア単体でも高品質なデバイスですが、Appleの製品ということでAppleのハードウェア、ソフトウェアの中に入ってこそ本領発揮だと考えています。
最初にApple Vision Proで体験している光景を共有したり、他の方が体験している様子を見たい時には、Apple Vision Proがら見えている様子をどこかに表示させたくなります。
いきなりここでAppleのいままでの流れと同じことができ、AirPlayにてApple TVでの表示が可能です。iOS/iPad OS 17以降ではiPhone/iPadをAirPlayレシーバーとして設定する機能もありますので、Apple TVがない場合でも、iPhone/iPadで表示が可能です。
Apple Vision Proの画面をiPadに転送している様子(Apple Vision Proで見ている光景(iPadやアプリ)がiPad上にも表示されている)
また、いままでのデバイスで意外と手間がかかっていたファイルの共有についてはAirDropでの転送が可能です。
AirDropはApple Vision Pro, iPhone, iPad, Mac間でそれぞれファイルの転送が可能で、これを利用すると下記のようにiPhoneでスキャンしたデータをすぐさまApple Vision Proに転送して利用する。ということが可能になります。
iPhoneLiDARでスキャンした モデルをそのままVision Proに。
— 中村 薫 (@kaorun55) 2024年2月4日
AirDropですぐに転送できるのがでがるで良い。
この動画はVision Proで撮ったものをAirDropでiPhoneに送ってアップしてる。#AppleVisionPro pic.twitter.com/M7FGMQjGAp
ここからの派生として、Appleデバイス間で共通の「USDZ」という3Dを表現するファイル形式があります。
元々映画制作のPixerが定義したUSDというフォーマットで、Apple製品ではこの派生フォーマットであるUSDZをOSで扱うことができます。
iOS/iPad OSではAR Quick LookとしてモデルビューアーやARにて表示できます。
Apple VIsion ProでももちろんUSDZがサポートされており、先ほどのようにiPhoneのLiDARで3Dスキャンした3DモデルをUSDZでAirDropでApple Vision Proに転送することにより、すぐさま実寸でモデルの確認ができます。
最初にも書いた通り、ディスプレイはとてもキレイですので、高品質な3Dモデルが高品質なまま閲覧体験が可能です。
先日公開した沖本家住宅も綺麗に出せる。
— 中村 薫 (@kaorun55) 2024年2月4日
#AppleVisionPro pic.twitter.com/uA1HxXxT79
AirPods Proとの連携も強力で、AirPods Proでは外音を遮断できます。飛行機の中でも飛行音が聞こえなくなるほどです。
Apple Vision Proは視覚を遮断できるデバイスです。カメラから映像を中のディスプレイに表示するビデオシースルーという方式のため、ディスプレイの映像をカメラではなくコンピューターで作成した空間にすることで、視覚の外界との接点を切ることができます。
この2つを組み合わせることで、視覚と聴覚を外界から切り離し、体験に没入することが可能になります。
この体験には「Mindfulness」というアプリがおすすめです。
Apple Vision Proで視覚と聴覚のノイズキャンセリングだとMindfulnessアプリがオススメ。
— 中村 薫 (@kaorun55) 2024年2月10日
最初は外が見えていて途中から真っ暗になって視界が遮断される。
AirPods Proで聴覚も遮断すると、ほぼ外界から断絶した環境にできる。 pic.twitter.com/8iXLWqs7cQ
このほかにもMacをApple Vision Proに接続してディスプレイにできる「Mac Virtual Display」により、MacをApple Vision Pro内で使うことができます。
Apple Vision Pro単体では対応していないアプリや作業などはMacを併用することでApple Vision Pro内で完結することができます。
このようにApple Vision Proはハードウェア単体でも、Appleエコシステムの中でもいままでとは違った使い方、体験ができるデバイスと考えています。
今後日本で発売された後はそれぞれの環境に合わせた使い方が可能です。
Apple製品を多数お持ちの方はAppleハードウェアエコシステムの恩恵を受けながら。
Apple製品をあまりお持ちでない方はApple Vision Proから。
Apple Vision Proからの場合は、キーボード、Magic TrackPad、AirPods Proを合わせて持っておくと、Apple VIsion Proで完結する環境ができて良いでしょう。
ホロラボでももちろんApple Vision Proのアプリ開発に取り組みます。
最初のアプリとして「Spatial Paint」という空間ペイントのアプリケーションを米国App Storeにて公開しました。
apps.apple.comこのアプリは文字通り空間にお絵かきができるアプリで、VRアーティストのせきぐちあいみさんとコラボレーションを進めていきます。
もちろんApple VIsion Proをお持ちの全ての方に使っていただけますので、ぜひインストールしてください。
Spatial painting with #AppleVisionPro https://t.co/QZ3t944ntM pic.twitter.com/L0gLuKyzAM
— Aimi Sekiguchi🌐ايمي (@sekiguchiaimi) 2024年2月8日
「Spatial Paint」はいままでのホロラボの取り組みと異なるとようにも見えますが、HoloLensでペイントアプリ作ってせきぐちさんとコラボレーションしてるメンバーがいて、これをApple Vision Proに合わせてアプリリリースをする。という経緯です。
Apple Vision Pro自体もコンシューマーに向いており、これを機に空間の中でコンピューター扱うというユーザーが増えると考えています。
その中で空間で「絵を描く」というシンプルですが、わかりやすいテーマでのアプリ。としています。
また、Apple Vision Proはデバイス単体ではなく、コミュニケーションを重視していると考えていますので、描いたモデルはUSDZで出力し、共有することが可能です。
これによって、ユーザーは自分が描いたモデルを共有し、お互いに楽しむことができます。もちろんiOS/iPad OSの方もそこに加われます。
描いたものを空間に置いていく pic.twitter.com/xCDmM5WWQA
— 中村 薫 (@kaorun55) 2024年2月4日
いままでのサービスの延長もあります。
ホロラボにて提供しているBIM/CAD向けサービスであるmixpaceのApple Vision Pro版を日本発売に向けて準備を進めています。
Apple Vision Proでの高品質なディスプレイにより、いままでとは違った体験になりますので、登場をお待ちください。
空間コンピューティングの自分なりの解釈として、空間とコンピューターが日常世界で共存する世界、Apple Vision Proを日常から使い続ける世界に変わっていくと、いままでの生活スタイルも少しずつ変わっていくのかなと考えています。
技適特例申請も提出したので、この範囲内で試していきます。
]]>
基本は公式マニュアルの通りではありますが、ところどころ躓くところもあったので備忘録としてスクショ多めで。
Unityで制作できるアプリのタイプの名称について一旦整理。
要件はこちら。
まずはXcode 15.2を入れる。
visionOSにチェック入れる。
Unityのバージョンは2022.3.18f1以降。
2023は現時点ではLTSではないので2022を使う。
テンプレートは2022.3.18f1なので同じバージョンをインストールする。
Appleシリコン版の方をインストールする。
モジュールはvisonOSとiOSの両方を入れる。
パススルーを用いたMixed Reality(PolySpatial MR)のコンテンツを作成する場合の手順です。
VR(Fully Immersive)のコンテンツの場合については次項。
このマニュアルに従って作成する。
まずUnity2022.3.18f1で新規プロジェクト作成。
ビルトインシェーダーでも動作はするがMRのサンプルコンテンツはURPで作られているので特別な理由がなければURPで作るのが良さそう
Project SettingsでXR Plugin Managementをインストーする。
Apple visionOS
を有効にする。
XR Plug-in ManagementのApple visionOSを開きMixed Reality
を選択する。
このMixed Realityを選択したことで以下の3つのパッケージがインストールされた。
com.unity.polyspatial
com.unity.polyspatial.visionos
com.unity.polyspatial.xr
Usage Descriptionに適当な文章を記入する。
例)
Use hands tracking
Use world sensing
環境構築は以上だが、サンプルシーンを使う場合は Packages > PolyStatial > Sample からインポートする。
インポートしたシーンはこちらにある。
各サンプルシーンの概要はこちら。
プロジェクトの作成は以上。
続いてvisionOSシミュレーター「Play to Device」を設定する手順は記事の後半に記しました。
Fully Immersiveのプロジェクト。
つまりMRは使用しない、完全没入のVRのプロジェクトを作成する場合。
こちらのマニュアルに従って進める。
XR Plug-in ManagementのApple visionOSを開くところまでは前項目のMRのときと同様の手順。
Fully Immersiveの場合はここでVirtual Reality
の方を選択する。
前項目はUnityプロジェクトを1から構築する場合だったが、ここではテンプレートを使用する場合について。
テンプレートのzipを解答しUnityで開く。
(テンプレートを使った場合はXR Plug-in ManagementのApple visionOSのチェックは既に入っている
(必要なパッケージも既に入っている
メニュー > Tutorial > Show Tutorials を選択。
表示されたウィンドウ内にある各ボタンをクリックすると、VRコンテンツを制作するためのチュートリアルが開始される。
visionOSのシミュレーターの設定。
こちらのマニュアルを参考に進める。
ディスカッションページはこちら。
PlayToDeviceHost-1.0.3.zipをダウンロードする。
zipを解凍する。
Xcodeを起動しSimulatorを起動する。(またはComannd+SpaceからSimulatorを実行)
ここでiPhoneのシミュレーターが立ち上がってしまった場合は、アプリ上のメニューからApple Vision Pro
を選択する。
ダウンロードしたPlayToDeviceHost.app
をシミュレーター画面内にドラッグ&ドロップする。
visionOSのシミュレーターでPlay To Device Hostアプリを起動する。
この状態でUnityでPlayするとシミュレーター側に表示される。
以上。
通常通りのビルドでOKだが、私の環境では以下のエラーが出てしまった。
Building Library/Bee/artifacts/iOS/AsyncPluginsFromLinker failed with output:
UnityEditor.Build.BuildFailedException: Burst compiler (1.8.12) failed running
stdout:
Internal burstc error:
Burst.Compiler.IL.Aot.AotLinkerException: Failed to determine xcode installation path - "xcode-select -p" is XCode installed? xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
こちらの記事を参考に対応しました。
ターミナルに以下のコマンドを実行です。
sudo xcode-select --switch /Applications/Xcode.app
これでエラーなくビルドできるようになりました。
以上!
]]>このたび、ホロラボの有志で技術同人誌「ホロらぼん Vol.2」を制作し、技術書典15で頒布しました。
イベントは終わりましたが、引き続きこちらのURLで無料で頒布していますので、 よろしければご一読ください。 メンバーそれぞれが今興味がある技術について書いたごった煮な技術同人誌となっています。
目次
M5 AtomS3でp-duckを愛でる M5 AtomS3という小さなデバイスでp-duckをSlackにスタンプするデバイスを作りました。
みんなで街並みをスキャンする 街並みスキャンのスキャンソンについて。 イベント紹介やスキャンのコツなどを解説。
C#でBSONデータを扱ってみよう C#でBSONシリアライズ形式を使うときのTipsなど。
よろしくお願いします。
]]>UE記事一発目、UEでのMVVMについて触れていこうかと思います。 過去、お仕事でUnityにおいてC#でMVPパターンにて設計を行ったことがあるのですが、特に継続性のあるプロジェクトや複数デバイス/プラットフォームでの実装などを見越している場合では、かなりの効果を発揮すると実感しています。 今回、MVPではなくMVVMパターンに焦点を当てていきますが、UEでの設計の勉強の一つとして書いていきます。
今回、alweiさんのMVVMの記事を前提とします。 - UE5 UMG ViewModelを利用してBPオンリーのMVVMをしてみる https://unrealengine.hatenablog.com/entry/2023/09/28/233801
まず記事を書こうと思った動機としては、View-ViewModel側やModel側にバリエーションを持たせたとき、実際にどう作っていくのがよいかと疑問に思ったためです。
alweiさんの参考記事の場合、最終的には図のようにゲージが減少していくLevelが作成できます。
この場合、View, ViewModelおよびModelの関係性の概念図としては下図のようになります。
この応用として、まずModel層側のもう一つのパターンとして、ゲージを減少させるのではなく増加させるパターンを作ります。さらに、View層のもう一つのパターンとして、円形のゲージを扱うパターンを作成します。
すなわち、今回行いたいことを先ほどの概念図に追記すると、下図のようになります。
今回、Model側でのパターン作成はシンプルなものになります。まず、参考記事におけるThirdPersonCharactorをRenameし、「BP_ReduceLifeThirdPersonCharacter」とします。次に、「BP_ReduceLifeThirdPersonCharacter」をCopyし、「BP_IncreaseLifeThirdPersonCharacter」と名前を付けます。
BP_ReduceLifeThirdPersonCharacterにおけるEventTick内での処理は、図のようになっているはずです。
なので、増加させるパターンの場合、図のようにノードを組み替えれば「BP_IncreaseLifeThirdPersonCharacter」が作成できたことになります。
最後に、ContentsBrowserのModel層のファイルは図の二つになっています。これで、Model層での準備は完了です。
次に、View側で円形ゲージのパターンを作ります。円形ゲージ用の「M_CircleGauge」を作成します。(下記記事を参考にしています。)
また、「M_CircleGauge」のMaterialGraphはこのようになります。
そして、「M_CircleGauge」を親としたMaterialInstanceである「M_CircleGauge_Inst」を作成しておきます。
参考記事におけるWBP_LifeGaugeをRenameし、「WBP_LifeGauge_Straight」とします。次に、新しくWidgetBlueprintを作成し、「WBP_LifeGauge_Circle」と名前を付けます。そして、下図の状態になるように「WBP_LifeGauge_Circle」の状態を設定していきます。
最後に、ViewBindeingsビューにて、図のようにBP_ViewModelのSetLifePercent関数を、Image_LifeのSetOpacityにBindします。最終的に、ContentsBrowserのView層のファイルは図のようにになっています。これで、View層での準備は完了です。
では、動かしてみましょう。まず、NewLevelからBasicを選択し、新しいLevel「SampleMap」を作成します。そして、原点位置にPlayerStartを配置します。
次に、このLevelのLevelBlueprintを編集していきます。編集結果として、図のようなLevelBluePrintを組んでください。
また、WorldSettingsビューにて、DesualtPawnClassに対し、LevelBlueprintでの実装と同じCharactorクラスを割り当ててください(この場合、「BP_ReduceLifeThirdPersonCharacter」を割り当ててください)
今回はLife量は減少、ゲージは円形、といった形になります。実行すると、図のような動きになるはずです。
ここで少しLevelBlueprintについて解説してきます。まず、Construct BPViewModelノードにて、BP_ViewModelのインスタンスを作成します。
次に、Model層のCharactorクラスの取得と、ViewModelへのアタッチを行います。この際、下記図のように減少させる場合と増加させる場合の両パターンについてノードを組んでおき、切り替えられるようにしておきます。
そして、WidgetBlueprintのインスタンスを作成することで、これをBP_ViewModelに紐づくViewとします。 ここで、下図のように、WidgetBlueprintを「WBP_LifeGauge_Straight」か「WBP_LifeGauge_Circle」かを切り替えることで、円形ゲージか直線ゲージかを切り替えられる形になります。
一つ別の組み合わせとして、Life量が増加していき、直線ゲージの場合、動かすと下図のようになります。
また、そのときのLelevBluePrintは下記のようになります。
以上で、MVVMについて、UMG ViewModelによるViewとModelのパターンの拡張と切り替えを行ってみました。 この先としては、Charactor以外のModel層の例や、ViewやModelにInterfaceを使う形でDI (Dependency Injection)をする形について模索するところかなと思いますが、まぁ気が向いたらってことになりそうです。
また、サンプルのプロジェクトをgithubに公開しています。 github.com
]]>今年は開発面だけでなく、より営業/PM面に踏み込むということをしてきました。 その中で、社外とのやり取りだけでなく、社内的にもどうしていくか、といった面に対して、自分の能力の課題が見つかりました。
また、今後はどう効率的に物事をこなしていくか(もちろん質は下げずに)、そこがテーマになってくるような気がしています。
幸せなことに、わりと研究よりのお仕事に携わることが多く、以前より自分の興味領域でお仕事をさせてもらっています。 ただアカデミック的な活動はどうかというと、あまりできていない面があります。こちらの時間も作っていかないとというのが正直な気持ちです。
家族内に大きなことが発覚し、色々と大変ではありますが、なんとかやっていかなければという所存です。
まぁ今年もなんとか生きていきますw
]]>詳細はさくらサイエンスプログラムの活動報告レポートをご覧ください。
第34号:芝浦工業大学|2023年活動レポート:過去の実績を紹介|さくらサイエンスプログラム(JST)
2023年7月26日から8月4日にかけて、エチオピアのアディス・アベバ大学EiABC(Ethiopian Institute of Architecture, Building Construction and City Development)の教員2名と学生9名、計11名が芝浦工業大学建築学部建築学科を訪問し、東京デジタル・ヘリテージ・ワークショップが開催されました。芝浦工業大学からは教員2名と学生21名が参加し、企業や研究者の方々にも訪問していただきました。レクチャー、演習、体験、ディスカッション等を通じて、建築遺産における3Dデジタルアーカイブについての知識を深め、将来の活用方法について議論が行われました。(さくらサイエンスプログラムの報告記事から引用)
ホロラボからは中村薫、山田沙知氏の両名からAR技術を使用したまちづくりプロジェクトの事例紹介を行いました。
テーブルの上に敷かれた地図上にあるQRコードをHoloLensやiPadを通して見るとARの建物が浮かび上がるなど、市民参加型まちづくりの新たな手法を展示しました。 プロジェクトについては関連記事などをご覧ください。
展示依頼や登壇、講師依頼は随時受け付けていますので、HPより気軽にお問い合わせください。
]]>各イベント・展示会の詳細についてはお問い合わせください。
]]>清水寺の参道「産寧坂」「二年坂」「八坂通」の町並みや食べ物をフォトグラメトリによりデジタルアーカイブ。
生成したデジタルツイン空間をVR化&メタバースプラットフォームへ移植しました。
下記リンクより体験いただけます。
詳しいメイキングは追って更新予定。ざっくりな殴り書き状態ですが一旦公開。
今回は一眼カメラは基本使用していないのです。
八坂の塔だけは一眼使ったのですが、町並みは全て360度カメラの動画。
なぜ一眼ではないのかというと、世界各国から観光客がやってくるような場所なので撮影できる時間が限られ、一眼では時間がかかりすぎて間に合わないからでした。
夏至の時期を狙い朝4:30から撮影開始したけれど、それでもちらほら人がいる。さすが京都随一の名所スポット。
なのでガチフォトグラメトリ品質ではないのは少々心残り。
下記の通りレーザースキャンも行ったが今回は活かしきれなかったか。
レーザースキャナRTC360でレーザースキャンしたのが2022年11月。
Insta360 One RS 1-inchで動画撮影したのが2023年7月。
というわけで現地の状況が結構変わってしまい。
本来はレーザースキャンデータとInsta360のデータを併用してメッシュ生成する予定でしたがだいぶおかしなメッシュになってしまったので、アライメントまではRTC360を利用していますがメッシュ生成以降は使用していません。
アライメントではレーザースキャンデータを使用しているので地理的な意味では結構な精度で一致。今回は約600mのエリアを生成しましたが地図ともしっかり合致。
今回も生成にはRealityCaptureを使用。
読み込ませた画像の総数は、
たべものスキャンは鮮度が命!?
現地で購入した饅頭やきんつば等、京都から関東の自宅まで持って帰ってくると形も崩れてしまうので、食物はすべて宿泊先の部屋でフォトグラメトリ撮影しました。
持っていける機材も限られていたので、百均で買ったビニール袋ラックとテグスを組み合わせて。
ひとまず箇条書きで。
せっかく京都なんだしガチなフォトグラメトリもしたいところだったわ。
レーザースキャンと一眼をフルに使った本気バージョンやりたい。
また京都行こ。
京都をVR化してみた!
スマホでも体験いただけます。清水寺への参道を丸ごと再現。
実際の現地の町並みや和菓子をフォトグラメトリによりデジタルアーカイブ。バーチャル食べ歩き観光できちゃいます〜
VRの起動は続きから。 pic.twitter.com/TmvwTMn6bZ— 龍 lilea (@lileaLab) September 28, 2023
Togetterにまとめました!
https://togetter.com/li/2232605
京都VRを取り上げていただきました!
「MoguLive」様
https://www.moguravr.com/kyoto-vr/
「メタカル最前線」様
https://metacul-frontier.com/?p=7884
手順はGitHubのREADMEにもありますが、こうした環境構築に慣れてない自分は結構てこづったので、必要な手順を細かくまとめました。
記事の最後にその手順をまとめました。
データをDLして専用ビューワーで開くのみです。
環境構築や自前のデータを用意せず3D Gaussian Splattingがどんなものか触ってみたい人向け。
環境構築手順はこちらの方もまとめられているので、うまくいかない場合はこちらも合わせて参考にしてみてください。
・The NeRF Guru氏 – YouTube
・Alex Carlier氏 – ブログ
・ft-lab氏 – ブログ
上記サイトでは3D Gaussian Splattingを使ううえでその他の便利な機能の導入も紹介されていますが、以下にまとめた手順は純粋にGaussian Splattingのみを使うためのものです。
前提としてHardware Requirementsをクリアしてる必要があります。
(VRAMは24GB推奨ですが足りなくとも処理自体は可能 詳しくはFAQ参照)
ハードがOKであれば、Software Requirements に書かれている必要なソフトを用意します。
Software Requirements
・Conda (recommended for easy setup)
・C++ Compiler for PyTorch extensions (we used Visual Studio 2019 for Windows)
・CUDA SDK 11 for PyTorch extensions, install after Visual Studio (we used 11.8, known issues with 11.6)
・C++ Compiler and CUDA SDK must be compatible
具体的には以下に順に説明します。
・C++ Compiler for PyTorch extensions (we used Visual Studio 2019 for Windows)
Visual Studio 2019 をインストールする。
インストール出来たらVisual Studio Installerを立ち上げる。
「C++ によるデスクトップ開発」が必要なのでこれを有効にする。
・CUDA SDK 11 for PyTorch extensions, install after Visual Studio (we used 11.8, known issues with 11.6)
CUDA Toolkit 11.8が必要なのでインストールする。
(私の環境には元々CUDA 11.7が入ってたのでそのまま進めたが、だめだった。ちゃんと11.8を入れる)
インストーラーは ここ からDL。
インストールしたら、システム環境変数
を確認する。
CUDA_PATH
の値がインストールしたCUDA11.8のバージョンになっていることを確認する。
別のバージョンになっていた場合は11.8のパスを指定する。
環境変数
のPath
も以下の通り追加する。
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\libnvvp
後の手順でcl.exeへの参照があるので、事前に
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
のバッチファイルをダブルクリックで実行し環境変数を設定する。
実行すると一瞬黒いコマンドプロンプトの画面が立ち上がりすぐ消える。
GitHubからクローンするのでGitをインストールする。
https://git-scm.com/
Gitのインストールが必要なのは、GitHubからはzipファイルのダウンロードではなくクローンするため。
zipダウンロードだとサブモジュールが読み込まれないので注意。
Gitをインストールしたら、コマンドプロンプトを起動する。
GitHubからクローンするのでクローン先のディレクトリを作成し、そこへ移動する。
例 cd E:\Git\lileaLab\GaussianSplatting
クローンする。
git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive
末尾にある --recusive
はサブモジュールもインストールするためのオプション。
・Conda (recommended for easy setup)
Pythonの仮想環境を使うため、Anacondaをインストールする。https://www.anaconda.com/
インストールできたら、Anaconda Promptを起動する。
SET DISTUTILS_USE_SDK=1
を実行する。
※DISTUTILS_USE_SDKとは こちら を参考
クローンしたディレクトリに移動する。
例 cd E:\Git\lileaLab\GaussianSplatting/gaussian-splatting
conda env create --file environment.yml
コマンドで仮想環境を作成する。
ここでエラーになる場合は、前手順で用意したソフトのバージョンや環境変数の設定に誤りがないか見直しましょう。
環境構築は以上。
独自データの作成ではCOLMAPが使われるのでGitHubからDLしインストールしておく。
https://github.com/colmap/colmap/releases
独自の画像データを用意したら、一つのフォルダにまとめる。
ここでは仮にData
とする。Dataフォルダ内にinput
フォルダを作成し、その中に画像を一式入れる。
Data
└input
. ├image0001.jpg
. ├image0002.jpg
. ├image0003.jpg
. ︙
独自データの作成にはクローンしたデータ内にあるconvert.py
を使う。
オプションでCOLMAP.batの場所と、独自データを保存したフォルダを指定する。
例 python convert.py --colmap_executable "D:\GoogleDrive\ProgramFiles\Colmap\COLMAP.bat" -s E:\Git\lileaLab\GaussianSplatting\Data
しばらくするとCOLMAPデータが出来上がる。
(写真の枚数や解像度によってそこそこ時間かかる)
トレーニングの実行にはtrain.py
を使用する。
前手順で作成したCOLMAPデータのフォルダを指定する。
例: python train.py -s E:\Git\lileaLab\GaussianSplatting\Data
写真の枚数によってそれなりに時間かかる。
トレーニングが完了すると gaussian-splatting > output フォルダ内に「123456ab-1」の様なランダムな文字列のフォルダが作成されている。
このフォルダを次の手順で用意するビューワーで読み込む。
ビューワーを使用してトレーニング済みデータを読み込む。
ビューワーは こちら にビルド済みの実行ファイルがあるのでこれをDLし解凍する。
コマンドプロンプトでviewersフォルダへ移動し、オプションに上記手順で作成したトレーニング済みデータのフォルダを指定して実行する。
例: E:\Git\lileaLab\GaussianSplatting\viewer\bin\SIBR_gaussianViewer_app -m output\123456ab-1
操作方法は少し特殊。
移動はWASDQEだけど、視点の回転はマウスではなくUIOJKLキーになっている。
両手で操作する感じ。詳しくはこちら。
マウス操作で見たい場合は、Yキーを押すとトラックボールモードになりマウスで画面操作できるようになる。
以上!
こりゃ次世代の自由視点映像だ。#GaussianSplatting
60fps出るからドローン映像かのような滑らかさ。
NeRFと比べかなり鮮明で軽快。独自写真データでの生成手順、使い方もブログにまとめました!https://t.co/cscf2CyHkN pic.twitter.com/btV1Oj1XIl
— 龍 lilea (@lileaLab) September 4, 2023
環境構築や独自データの用意はせず、Gaussian Splattingがどんなものなのかとサンプルだけ実行してみたい場合の手順です。
(トレーニング済みデータをビューワーで閲覧する)
README の初めにあるリンク「Pre-trained Models」からトレーニング済みサンプルデータをDLする。
同じくその隣にある「Viewers for Windows」からビューワーをDLする。
DLしたらコマンドプロンプトでビューワーの実行ファイルを指定し、オプションで開きたいサンプルデータセットのフォルダをオプションを指定する。
それぞれDドライブ直下に解凍した場合の例: D:\viewers\bin\SIBR_gaussianViewer_app.exe -m D:\models\bicycle
ビューワーの操作は前項目で書いたものと同様。
以上!
]]>fatal: Cannot determine the organization name for this ‘dev.azure.com’ remote URL. Ensure the ‘credential.useHttpPath’ configuration value is set, or set the organization name ase the user in the remote URL ‘{org}@dev.azure.com’.
error: (以下省略)
Visual Studioを開きメニューのGit
から設定
を開く。
Gitグローバル設定
の資格情報ヘルパー
をGCM Core
に変更する。
以上。
これで再びプッシュできるようになった。
調べるたびにメモしていたものですが、ソースをメモしそびれいたので随時ソースのリンクも足していこうかなと。
そのソフトウェアやサービスの公式の情報が簡単に見つからなかったものは、スクショを検索してそこに写る座標から判断しています。
もし間違っているところあったらご指摘ください。
左手 | 右手 | |
---|---|---|
Y-up | Unity | Maya |
LightWave | modo | |
Zbrush | Substance Designer / Painter | |
Cinema4D | Houdini | |
Quixel Mixer | Godot | |
DirectX | Mine craft | |
Metal | Softimage | |
Motionbuilder | ||
KATANA | ||
Nuke | ||
Fusion 360 | ||
After Effects | ||
Dimension | ||
3D-Coat | ||
TouchDesigner | ||
Shade3D | ||
Metasequoia | ||
Xismo | ||
Xenko | ||
Roblox Studio | ||
Buildbox | ||
OpenGL | ||
Vulkan | ||
Marvelous Designer | ||
Solidworks | ||
Inventor | ||
iCAD | ||
CloudCompare | ||
AzureRemoteRendering | ||
ARKit | ||
Vision Pro | ||
Z-up | UnrealEngine | 3dsMax |
blender | ||
SketchUp | ||
Souce | ||
AutoCAD | ||
Photoshop | ||
Stingray | ||
Lumberyard | ||
CryENGINE | ||
Rhinoceros | ||
Civile 3D | ||
Vectorworks | ||
NX | ||
Revit | ||
ARCHICAD | ||
formZ | ||
Catia | ||
Rebro | ||
Parasolid | ||
InfiPoints | ||
RealityCapture | ||
Twinmotion |
こちらのURLで無料で頒布していますので、 よろしければご一読ください。
メンバーそれぞれが今興味がある技術について書いたごった煮な技術同人誌となっています。
国土交通省が主導する3D都市モデルオープンデータPLATEAUをランタイムロードする仕組みを構築しました。
路地、その魅惑の空間へのいざない。路地入門から3Dスキャンの方法を紹介します。
LumaAIという写真や動画からの3D再構築サービスのAPIを使ってみました。
Ready Player Meという3DアバターサービスをUnityに組み込んでみました。
Unity Cloud Buildをなんとか使いやすく。実案件で培ったノウハウとツールを紹介します。
よろしくお願いします。
]]>参考までに公式の情報。ここでは割愛。
・Google blog – Create immersive 3D map experiences with Photorealistic 3D Tiles
・Google ドキュメント – Photorealistic 3D Tiles
以下のCesiumのサイトにある説明をなぞった備忘録です。
Cesium – Google Maps Platform Photorealistic 3D Tiles
今回はUnityを使うので「PHOTOREALISTIC 3D TILES IN CESIUM FOR UNITY」の記事をもとに進めたもの。
※APIキーを取得せずとりあえずサンプル動かしてみる場合は当記事一番最後にその方法を記載した
APIキーを取得するために記事中にある here
のリンクよりGoogleのサイトへ飛ぶ。
here : https://developers.google.com/maps/documentation/embed/get-api-key?hl=ja
名前とIDを設定する。
続いて、上部の検索欄から Map Tiles API
を検索する。
(公式の説明だとここが省略されている(設定されている前提になってる?)ので注意)
ここの手順のとおり進める。
Unityプロジェクトを新規作成する。
ここではCesium for UnityのGitHubにあるサンプルプロジェクトと同じ 2021.3.10f1 のバージョンで作成した。
URPまたはHDRPで作成する。built inは非対応。
Package ManagerのScoped Registriesを設定する。
名称:Cesium
URL: https://unity.pkg.cesium.com
スコープ: com.cesium.unity
Package ManagerからCesium for Unityをインストールする。
Cesiumウィンドウを開く。
Cesium3DTileset
というGameObjectが作成されるので、Inspectorから Tileset Sorce
をFrom Url
に設定する。
URLには https://tile.googleapis.com/v1/3dtiles/root.json?key=◯◯
を指定する。
〇〇の部分は上記手順で取得したAPIキーを入れる。
Show Credits On Screen
にもチェックを入れる。
Google マップの利用規約に準拠するには必須。
URLを指定すると自動でSceneにモデルが表示される。
(Gameを実行せずとも表示される)
表示されない場合はUnityを再起動する。
以上。
さあ地球で遊ぼう!
Cesium for UnityのGitHubからUnityプロジェクトをクローンする。
07_CesiumGoogleMapsTiles
のシーンを開いて実行。
以上!
]]>
「HoloLab Conference」はホロラボとともに新しい技術をいち早く使いこなす企業様と、それを支えるエンジニアの経験を広く共有し繋がり、より多くの人たちがこれらの技術を体験できるようにすることを目的とした「場」です。
各企業様とホロラボが取り組みを進めてきたMixed Realityの実⽤に向けた取り組みや、BIM/3D CAD/3D CG/点群のような3Dデータ活用に向けた取り組み、GPS/VPS(Visual Positioning System)/PLATEAUのような空間情報技術活⽤に向けた取り組みの事例共有の場として「HoloLab Conference 2023」を開催します。
昨年も「HoloLab Conference 2022」を実施し、参加された企業様からのフィードバックや開催後のアーカイブ動画など、⾮常に盛況に終えることができました。
オンライン一般参加をご希望される方は、下記ページよりお申込みください。 https://hololab.connpass.com/event/276961
オンライン一般参加では、Zoomでのリアルタイムセッション視聴/質疑応答が可能です。
※当日のセッション視聴方法についてはお申し込みいただいた方に別途ご案内させていただきます。
実用に向けた取り組みをされている各社様とホロラボ合同の事例セッションと、基盤技術や技術調査などについての技術セッションの2種類のセッションを実施します。セッションは2タイムテーブルの進行で合計で最大15セッション程度を予定しています。
また、後日セッションはアーカイブとして公開する予定ですが、映像や音声の編集や一部セッションが非公開になる場合があります。ぜひリアルタイムでご参加ください。
会場施設と連携し各種ガイドラインを遵守とした感染対策の実施を予定しています。
・東京都様式「イベント開催時のチェックリスト」の公表
Holoconf23_東京都様式_イベント開催時のチェックリスト.pdf - Google ドライブ
株式会社ホロラボ イベント窓口:event@hololab.co.jp
※本記事に記載されている会社名および製品・サービス名は、各社の登録商標または商標です。
]]>
観光で訪れた際に撮影した360度動画と一眼写真から生成。
旅行がてら撮影した趣味作品なので、仕事品質ではないのはご容赦くださいな。
「とある場所」から夜景のうだつの町並みにも行けちゃいます。
行燈に照らされた町並みは現地でもとても素敵空間だった…
気になった方はぜひリアル観光も!
・cluster版は こちら
cluster版はモバイルでも体験できます。
※モバイル対応のため下記VRChat版よりもテクスチャの品質を下げています
・VRChat版は こちら
これまで作成したこちらの作品もどうぞ~。
Togetterにまとめました!
(執筆中 随時更新~)
]]>#うだつVR メイキング。
趣味作品なのでクリーニングはざっくりなのですが、この技が便利だった。空マスク作りに初トライ。
超大変な屋根と空の切り離し作業をしなくていいのは最高!ノーベルチョコさんがやってた手法がやっと出来た。#Photogrammetry #RealityCapturehttps://t.co/AlxbSgao5V pic.twitter.com/WO8SbNYK4B
— 龍 lilea / Ryo Fujiwara (@lileaLab) January 16, 2023
6年目の年末が終わりました。 ホロラボも6期目が終わり、7期目に入りました。
引き続きアウトプットを出しつつも、少しずつ変化が出始めた年になったと思います。 スライドはこちら。
過去のふりかえりはこちら
全体の状況としては、コロナ禍は継続しつつも現場が戻ってきており、2022年の後半は出張も増えてきました。一方で、物理空間とデジタル空間をつなげる取り組みも引き続き続いています。
アプリ開発については、デバイスを使いつつも、それを広げるためのWebシステムやデータ準備の重要度が上がってきました。 後でも紹介しますが、Webアプリを主業務とするエンジニアに新たに加入、社内でロールチェンジしてもらい、いままでのメンバーと合わせてが10人になりました。 データについても新設したSIAR(サイアー : 空間情報技術)チームが1年を通して忙しくするほどにお引き合いをいただきました。 これによって、クライアント・デバイスアプリで使うための下地(Webシステム)とそこを通すデータがそろう形になります。
引き続きの注力分野であるクライアント・デバイスアプリについては、実運用を見据えて具体的な取り組みが増えています。
これらが、メンバーのロールやアウトプットの変化につながっています。
売上については堅調に推移しています。 ここには出していませんが、この2年くらいで業務体制の改定をしており、利益については大幅に改善をしています。
2022年も15人の方に新しく入社いただきました。 2021年も15人の方が入社、現在60人のため、この2年で倍の人数になりました。
概要でも書きましたが、特筆すべきはロールとしてWebのエンジニアが大幅に増えています。 2022年は5人の方にWebエンジニアとして入社いただき、3人の方がデバイス系のアプリエンジニアからWebエンジニアにロールが変わっています。 いままでWebエンジニアとして活躍していた2人と合わせて、計10人の体制となっています。
居住地については変わらず全国各地にメンバーがいる状況です。継続してフルリモートでの業務になり、それをメリットとして転職される方も多くいます。
2022年も多くのアウトプットを出すことができました。 関わっているメンバーや快く事例公開をしてくれるお客様に感謝です。
大きな仕事の一つとしては、NTTドコモ社/NTTコノキュー社のXR Cityの開発パートナーとしてサービスのリリースに関われたことです。 世界的にも類を見ない大きなサービスに関われリリースにたどり着けたことは非常に大きな経験だと感じています。
自社サービスの中心であるmixpaceは、粛々と開発を進めつつ、リコー社のバーチャルワークプレイスとの連携のリリースを行うことができました。 mixpaceはBIMやCADなどの3Dデータを即座にARなどで閲覧できる形式に変換します。これをVRに持っていくことでVRでの遠隔コミュニケーションに利用することが可能になりました。
変換については、さまざまなデータ形式への対応、同じデータ形式でも作り方によって変換結果が変わるため、リリースより積み重ねてきた知識と経験のなせる技だと自負しています。
2022年の新しい取り組みとして建設に特化したAECチームと、3Dスキャンやフォトグラメトリに特化したSIAR(サイアー : 空間情報技術)チームを新設しました。 こちらもおかげ様で好評で、多くの依頼をいただいています。
アウトプットできた取り組みとしては、日建設計社とCyber-Physical Workplaceの取り組み。
東京メトロ社と総合研修訓練センターの3Dスキャン・フォトグラメトリが挙げられます。
このほかにもさまざまな取り組みを行いました。
昨年から広がっている広域の取り組みでは、国土交通省のProject PLATEAUで2つのプロジェクトに参画しています。 一つは東京都八王子市での街づくりへの適用、もう一つは静岡県沼津市でのモビリティへの適用です。
HoloLensで部屋から始まった取り組みが、都市まで広がってきた一年でした。
これらの取り組みのいくつかは「HoloLab Conference 2022」としてお客様と一緒に事例の公開をしています。
HoloLab Conference 2022 - Program Schedule | ConfEngine - Conference Platform
これらの取り組みは個別の案件である一方で、会社全体としてみると繋がっている中での活動になっています。 HoloLensのアプリ開発から始まったホロラボですが、いまでは「3Dを扱う」ということが共通項になっています。
デバイスはもちろんのこと、それを扱うインフラ、データと広げています。
2023年も引き続きご愛顧・ご注目のほどよろしくお願いいたします。
]]>というわけで、もう少し具体的に振り返ろうかなと思います。
今年は開発面において、コーディングもやりますが、開発管理であったりお客様と話すことが多くなりました。 ある意味で裁量も増えている認識です。 あとは技術の範囲も多岐にわたっています。GNSS系だったりNeRFなどの機械学習だったり。 広く浅く、みたいになってますが、深く突っ込んでいかないととも思いつつ。
あとUnrealEngine始めました。んー、ちゃんと開発面でのセオリーだったりを学ぶ必要があるなぁと感じています。 例えばどういったときにBPで書いて、とどういったときにC++で書いて、という分け方。 BPよくわからんのでC++で書いていましたが、この辺結構明確に決めて開発しないとーとは思います。
IDW'22というWorkshopで発表してきました。現地開催(福岡)ということで、コロナ禍で英語力も上げないとなー、という悩みも出てきました。 どんどん学会発表も多くしていきたいし、そのための研究としてアウトプットを出していきたい所存です。
150kg -> 120kg程までダイエットできました!ダイエットというか、筋トレ+食事の見直し、そして徹底。 筋トレが楽しくなってきたので、来年も続けて一旦90kgくらいまでを目標として続けたいと思います。
来年も頑張っていきますw
]]>メタボリズムの名建築『中銀カプセルタワービル』が解体へ…
名建築が失われてしまう前に、フォトグラメトリにより3Dデジタルアーカイブしました!
gluon主宰のプロジェクトです。詳しくはこちら
一眼カメラ、ドローン、レーザースキャンのデータからデジタルツインを構築。
そしてメタバースプラットフォームへも移植…!
下記リンクから体験いただけます。
・VRChat版は こちら
・cluster版は こちら
解体の進む「中銀カプセルタワービル」を丸ごとスキャンしたワールドを公開しました!
地下から塔屋、カプセル内まで巡れちゃいます。
続きからVR起動できます。#中銀カプセルタワービルVR#Photogrammetry pic.twitter.com/p7kKPrZ7v8— 龍 lilea (@lileaLab) August 7, 2022
クラウドファンディングのリターンとしてご体験いただけます!
3D Digital Archive Project /
建築『中銀カプセルタワービル』を3次元スキャンで記録に残したい。
スライドを公開しました。
中銀カプセルタワービルの屋外、屋内、地下から塔屋まで全域をフォトグラメトリしたその撮影方法や、RealityCaptureによるフォトグラメトリ処理、VR制作のTIPS等、フォトグラメトリコンテンツの作り方をご紹介。
UnrealEngine(以下UE)のpreviewバージョンの最新版、preview5.1が公開されましたね。
このバージョンではなんと、VRでLumenやNaniteが動作します。
パブリックロードマップはこちら。
Preview版ということでまだ不安定(※1)なところはありますが、.exeパッケージを作成できましたので触って頂けましたら幸いです。
まえArchiVizDiveでつかったコンテンツをLumenVRでパッケージ化できた。
— moz (@momomo_moz) 2022年10月20日
さすがにハードウェアレイトレは無理やった。
でもマシンスペックさえ用意できればPCVR爆速構築できるようになったのは凄すぎる。#UE5#LumenVR pic.twitter.com/E77cPcKjAh
動作検証環境は下記のとおりです、ぜひ他環境でのフィードバックもいただけるとありがたいです。 ・Meta Quest 2 + Oculus Link ・RTX3080Ti
今回のサンプルははUEの標準VRテンプレートをLumen対応にして、モデルデータのみをインポートしただけです。
標準のVRテンプレートのMoveArea設定はNaviMeshで行われています。 MoveAreaとしたいStaticMeshのCollision設定をし、NaviMeshVolumeと詳細設定を行うだけでLumenVRが体験できます。
以前はNaviMeshで複数階や吹き抜けのある空間のムーブメントを行う場合はVRpawn内のテレポートレーザーのBPの編集を行う必要がありましたが(法線がマイナスになる部分をテレポートレーザーが認識しないようにする)、 最新のVRテンプレートならNaviMeshのサイズや位置、Detailの編集のみで立体的な空間のMoveAreaの設定が行えます。
※1.今回遭遇したのはQuiexl Bridgeのプラグインが使用できない状況
]]>この夏、ホロラボが参画している国土交通省Project PLATEAU 2022度プロジェクトの一環で、東京都立大学饗庭伸研究室と協力し、3D都市モデルとXR技術を活用した市民参加型都市開発ワークショップを開催します。
ひとつでも当てはまる方、ワークショップへのご参加を心よりお待ちしております。
お申し込みはこちらから forms.gle
]]>
macにCocoaPodsをインストールしている場合「Unity-iPhone.xcworkspace」が生成されるが、Xcodeでプロジェクトを開く際にこの「Unity-iPhone.xcworkspace」ではなく「Unity-iPhone.xcodepro」の方を開いてしまっている。
「Unity-iPhone.xcworkspace」の方を開く。
]]>
Windowsを開発者モードにする。
以上。
]]>
ホロラボのmixpaceというサービスを牽引するエンジニアの一人、山中大輔。 ほとんどコードを書いたことがなかった山中が、HoloLensに出会い、安定の大企業からホロラボに転職するまでの軌跡を追いました!
ーーさて、、、山中さんは、どうしていつもニコニコしているんですか? (インタビュー中のトップ画像の通り、ほんとうにいつもニコやかです。)
え…?何かな…?処世術かな…?w 学生時代は、ドラッグストアでバイトしてたりとか、個別学習形式の塾でバイトしてたりして、割と人と話す機会が多かったから、自然とその場でも笑いを絶やさないことがルーツかもしれません。w
ーーなるほどw では、簡単な経歴から教えてもらえますか?
神奈川県横浜市で生まれました。親が転勤族で、東京→京都→東京に行ったりで、栃木県で中学・高校時代を過ごしました。その後に横浜の大学に通うために上京して、そのまま関東で就職して、通信系の大手SIerに入社しました。大学は情報処理系の学部でした。
(写真1:自宅にて奥様が撮った写真。後ろに飾ってあるお子様が描いた絵がほほえましいです。手前に映っているのがHoloLens 2。)
ーー昔からITなどに興味はあったんですか?
いやぁ、特になかったですね。ゲームばっかりやっていたし。高校時代にホームページを作ったことがあったぐらいかな。
ーー大学は何故、情報系に?
ホームページを作ってたりしていたから興味がないわけでもないし、世間的にITが流行ってるぞ、っていう理由ぐらいですね。
ーー大学ではバリバリとコードを書いて…?
いや、あんまり書いてないですね。w C言語が難しくて、あんまり書きたくなかったですね。w
ーーえ?w じゃあ、新卒で就職した会社は何故選んだんですか?
大きいし、安定してそうだな、と。よくある大企業志向というか。俗にいう、安定志向というか。
ーーえ~。w そしたら、志向が今と真逆ですね~。この後のお話が楽しみです。 前職の大手SIerでは、どんな仕事をしてきたんですか?
最初はセキュリティ系の事業をやっているところに配属されました。最初の2年間はそこでシステム運営オペレーターみたいな仕事をやりましたね。あんまり技術的なことはやった記憶がないです。
ーーなるほど。ここでもまだ技術的なことはしてないんですね。
そうですね。そのあと出向を命じられて、セキュリティ・テスター(Webサイトの脆弱性診断)をやっている子会社があったんで、そこで3年間仕事をしました。
ーーそこでいよいよ技術的な仕事を?
いえ。でも、そこは割とインパクトが大きい3年間でしたね。 前職は本体(親会社)に3万人ぐらい社員がいるんです。でも、子会社は500人ぐらい。その中で更にチームに分かれていて、こじんまりしていたんです。 それに、出向先の人から見ると(自分は)中途採用みたいなもんだから、年次とかが考慮されないというか、割と大きな単位の仕事をやらせてもらったのが、よかったんです。
ーーなるほど、技術うんぬんよりも、仕事の仕方みたいなところでインパクトがあったんですね。
そうですね。でも、出向が終わって本体に戻ると、また若手として仕事のスケールが小さくなるという感じでした。それが転職したいと思うようになったきっかけですね。
ーーそういう経験が転職のきっかけになっていったんですね。 VR、AR、MRの分野は、どうやって知ったんですか?
出向から戻ってきて、つまんないなーと思いだして、異動希望を出したんです。とにかく他のところに行ってみたくて、スマートグラスをやっている人たちが楽しそうだったので、その部署を希望して、異動しました。 自分の意志で、自分がいる環境を捨てて、外に出たいと言ったのはこれが初めてでした。
ーーここで、いよいよ技術的な仕事を…?
いえ。サービスのプロトタイプをお客さんのところに持って行って、お客さんの実証実験にお付き合いしたりしていてました。サービスは面白いけど、紹介業って感じで、仕事としてはあんまり楽しくなかったですね。 (写真2:2017年7月。右手前が、前職の在職中にホロラボメンバーと一緒にいる山中。山中の後ろにいる3人は現職のホロラボメンバーでもあります。右上に「4年前」とあるのは、CEO 中村がFacebookから「あの頃」としてリマインドされた写真を転用したため。)
ーーHoloLensとはどうやって出会ったんですか?
異動した先の仕事の関係もあって、自然とHoloLensのニュースを見たりしていました。日本でも、海外から輸入して使った人がブログを書いていたりして、スゴそうとは思っていましたね。 それで、ある会社の人に体験させてもらう機会があって、面白いかなと思って買ったんです。30万円ちょっとの高いデバイスだけど。
ーー確か、その時点でお子様が2人…。30万円のデバイスを、よく買えましたね?w
うちは、家計や貯蓄計画は全部僕がやってるんで、割と決済額はいかようにもできたんです。w 後は、あの頃は家を買うために割とちゃんと貯金はしていたので、買っちゃっても人生計画には支障はないと思って。w
で、そこから、前職の会社が開いたイベントでホロラボのメンバーとも出会い、Tokyo HoloLens ミートアップとかにも出るようになって、自分でデモアプリを作ったりするようになったんです。
ーーなるほど。興味のある方向に進みながら、プログラミングをするようになっていったんですね。 デモアプリへの周囲の反応はどうでしたか?
みんな、「面白い、面白い」と言ってましたね。 自分も、少しプログラミングをできるようになっていました。
(写真3:山中が開発したHoloLensのアプリケーションを公開したTwitterの投稿。こちらのリンクから動画が見れます!)
ーー転職はどうやって決めていったんですか?
何社か話は聞いたんだけれど、どうせ転職するなら、デカくて仕組みがあるところよりも、ホロラボみたいに小さくて出来立てホヤホヤのほうが面白いかな、と思ったんです。 それで、中村さん(CEO)に転職できませんか?って話をしました。
ーーとは言え、安定した大企業からの転職は悩みませんでしたか?
揺れ動いていましたね。安定を手放してもいいのかな、と。 でも、最終的には「楽しくないな」って考えるのはつらくなったんです。それで、奥さんも働いているし、なんとかなるなって考えるようになりました。
ーー奥さんからの反対はありませんでしたか?
奥さんは最初はネガティブって感じだったんです。そこで、奥さんに気持ちよく送り出してもらうために、半分演技、半分本心で、思い詰めた感じを出していたら、「そこまで(思い詰めてるん)だったら、いいよ」となりました。w
ーー「嫁ブロック」への対策が秀逸ですね。w ホロラボでは、どんな仕事をしてきましたか?
入社当初は、Unity(2D・3Dによって開発できるゲームエンジン)から始まりました。HoloLensを使って機械の修理手順を表示するようなアプリを2件と、未来の車をシミュレートするような開発案件を1件ほど担当しました。 その後に、mixpaceというサービスのWebエンジニアが必要だけれど、社内にいないし、募集も難しいから誰かいないか?という話があって、手を挙げました。 今は、mixpaceチームで、Webのフロントエンド、裏側のWebアプリケーション(APIサーバー)の実装と、CAD・BIMデータを変換するコンバータープログラム、Azureのクラウドインフラの構築を行っています。あとは、実際に動いているシステムのメンテナンスですね。
ーー今までコードをほとんど書いてきてないのに、Unityを経験し、Webエンジニアに転向?! どうやって学習したんですか?!
ん~どうやってかぁ。難しいなぁ。経験はなかったんですけど、じゃあ、血のにじむような努力は?って言うと、しなかったなぁ。あとは、そうだなぁ、新しいことを学習するコツっていうのは、前職で教わった気がします。前職はプログラムは書かなかったけど、プロジェクトをどうドライブしていくかっていう指導を受けたんで、学習にも活かせたんじゃないかなとは思いますね。 これは必要だっていうのを見定めて、それを深く掘っていくということですかね。
ーーその学習力、キャッチアップ力がすさまじいですね。
ーーさて、ここからホロラボの話に移りましょう。ホロラボってどういうところがいいですか?
フルリモートは自分のライフスタイルに合ってますね。それまでは、共働きなのに、奥さんに家事も育児も頼っていたんです。フルリモートになってから、子どもの送り迎えとかもできるようになって、奥さんも大分気持ちが楽になって、家庭が円満になった気がします。それはすごく感謝してます。 (※ちなみに、山中はコロナ前は週に1回程度の出社。コロナ後は出社ゼロです。)
ーーコロナが発生する以前から、フルリモートでしたもんね。
あとは、なんか、あんまりイケイケじゃないところが肌に合っていますね。w キラキラしていないというか、はしゃぎすぎていないところというか。イケイケのベンチャーみたいな雰囲気じゃなくて、おっさん臭いところが合ってますね。w 上昇志向がないわけじゃないけど、チョー意識高いわけでもなく、地に足のついた人が多いという感じがします。コミュニケーションでそんなにストレスを感じないっていところもいいですね。
ーー確かに落ち着いた人が多い印象ですね。 今、Webエンジニアを募集していますが、どんな人に入ってきてほしいですか?
技術的には、Webをやってきて、3Dのアプリケーションに興味がある人に来てほしいですね。逆に3Dをやっていて、Webをやってみたいっていう人もWelcomeです。 あとは、喋りながら進められる人がいいですかね。最近はできるだけコミュニケーションしながら作ることを実践するようにしているんです。ペアプログラミングとかをやってたことがある、やってみたい、人と話すのが苦じゃないっていう人が来てくれると嬉しいなと思います。
ーーずばりホロラボのおすすめポイントは?
技術的好奇心が高い人がいっぱいいるんで、日常的に技術の会話ができますね。今の仕事をする中であんまりそういう会話ができていないって人にはいいと思います。職業エンジニアの集まりが嫌だって人にはオススメですね。
ーーホロラボは「つよつよ」で技術大好きなエンジニア集団という感じがしますよね! 今日はありがとうございました!
ありがとうございました。 (了)
]]>白木が大手SIerのプロジェクトマネジャー(PM)からホロラボに転職したのは2018年、38才のとき。 「転職は35才まで」などと囁かれることもありますが、白木はどんな考えでホロラボに入ったのか?そして、どんな仕事をしているのか?を聞いてみました。
ーーまず、、、白木さんはどうして髭を生やしているんでしょうか?w
ホロラボに入ったら、ちょんまげの人が二人いたんですね。それで差別化しようと思って。w それと営業(PM)として、お客さんに顔を覚えてもらえます。w ちなみに前職では、「髭を生やしたらダメ、辞めろ」と言われてました。
ーーなるほどw では、前職までの簡単なプロフィールをお願いできますか?
生まれは山口県下松市です。高校まで地元で、福岡大学に進学しました。 卒業後に、大手電機メーカーF社の九州にあるシステム系子会社に入り、10年ぐらいして親会社の方に出向して、東京に来たんですね。そこで病院向けの電子カルテのPMをやりながら5年ぐらい経って、「(九州には)帰りたくない」ってゴネたんです。で、そのまま東京勤務を3~4年ぐらい続けて、ホロラボに転職しました。
ーーえ?どうして九州に帰りたくなかったんですか?w
福岡、九州の人って地元が好きだけど、自分はそこまでの地元愛は持っていなくて。それと東京の方が色々と楽しいことがたくさんある。
(写真1:メンバーと談話する様子。机の端にある、四角いデバイスはMicrosoft Kinect。)
ーー楽しいことって、具体的には何ですか?
2016年ぐらいにOculusというVRゴーグルを知ったんですね。それでなんとなく買ったんです。で、アプリを作ってTwitterとかでつながっているコミュニティがあって、積極的に参加していっていたんですよ。地方だとそういうこと自体が難しいので、参加もできなくなっちゃうし。
ーーなるほど。それで、そこから、xRの分野に興味を持っていくんですね。 どんなことをしてたんですか?
例えば、Kinectで自分の骨格を検出して、自分の好きなアニメキャラクターをVR空間に出して、自分と同じ動きをさせたりしてました。w 自分が作った動画が2万リツイートされたこともありました。
ーー2万リツイートってすごいですね! そのあたりから転職を考えるようになったんですか?
いや、その頃は転職なんてみじんも考えてなかったんですよ。 VR、Kinect、Unityってベースが自分にできてきて、次にHoloLensが出たんです。日本では買えなかったんですけど、たまたま知り合いのつてで買えたんですよ。40万円ぐらいで。 今までは(VRだと)コンピュータ空間に入っていたんだけど、これは現実の空間に情報を重畳できる。 これはすごいな、マウスとディスプレイが必要なくなる時代が来るなと思った。
ーーHoloLensに大きな可能性を感じたんですね。
で、会社の中で仕事にできないかと思って、上司に見せたり、お医者さんに見せたりしていたが、あまり反応がなかったんです。 あと、新しいビジネスをやっていこうというお題目のグループがあったんですけど、予算が出るわけじゃないし、不満がある人のガス抜きの場みたいになっていた。 それで、大きな会社では事業以外のことはできないんだろうなと思ったんですよ。 で、電子カルテもあまり興味のある範囲じゃなかったし、実際に転職するかどうかは別として、転職活動を始めてみたんです。
(写真2:HoloLensを操作中。白木から見えている景色がモニターに映し出されています。)
ーー転職活動って、まずは始めてみるっていうのは大事ですよね。 ホロラボとはどうやって出会ったんですか?
Tokyo HoloLensミートアップというコミュニティに行ったときに、ホロラボメンバーの1人が「PMを探している」ということで、受けてみよっかなーと軽い気持ちで面談しました。 ちなみに、それまで大手のSIerの採用面談を受けて最終面談で落とされていました。その時、私を落とした面接官の人は、先にホロラボに転職していて、プロダクトマネジャーをやっています。w
ーー自分を落とした面接官が、自分の転職先に先に転職してるってすごい縁ですねw ホロラボに決めた理由はなんですか?
ホロラボはベンチャーやスタートアップじゃなかった。それまで受託ビジネスをやってきていたし、いわゆる中小企業です。だから、ある程度長く生きていけますよね。 それに、xRしかやっていない。「xRも」やっている企業だと、いざ転職しても、「xRをやってもらうとは言ったけど、まずはここで」とか言われて配属先が違ったり、希望の部署に配属されても部署異動になってしまうこともある。xRが専業の会社ってほとんどないんですよ。
ーー白木さんのxRに対する熱量を感じますね~。 アラフォーでの転職は怖くなかったですか?
そりゃあ、転職は怖いですよ。「転職は35才まで」なんていう話もあるし、当時38才だった。でも、今の仕事を定年までやるのか?とは思いました。 あと、人生には10年に1度ぐらい大きなチャンスはあって、それに乗るか乗るないかは逃さないようにしてましたね。
ーーなるほど。やりたいことや大きなチャンスに思い切って飛び込んでみたんですね。
はい。あと、前職での楽しくない、つまらない仕事は意外に役に立つんですよ。w つまらないというのは自分の場合は、電子カルテで、それがxRに換わればいいんです。 基本的には、PMとしての仕事は同じなので。
ーーそれは転職のハードルを下げてくれそうですね。 ホロラボではどんな仕事をしてきましたか?
前職が大手SIerだったので、大手のお客さんが相性が良いだろうということで、JR東日本さんや電気会社さんの案件などを担当しました。(※ページ最後に、案件例のリンクを貼っています。) 実際に相性はよかったです。相手の論理が分かるので。 例えば、向こうの社内の論理も分かる。予算感が大前提にあるとか、決済額がどれぐらいとか。 あとは、システム系子会社にいたし、実際に案件の窓口になるお客さんは同じような立場なので、そういうところで話が合いましたね。
ーーそういったところも前職の経験が役に立つんですね。 逆に、前職とホロラボで、仕事でどのような点が違いますか?
前の会社は大規模システムなので、ウォーターフォールでやっていたんです。ホロラボの案件はどっちかっていうと、機能を作ってみて体験して、そのフィードバックを元に改善していっている。 だから、アジャイル、リーンスタートアップという考え方が強くなりますね。
この業界は作るものがあってないようなもの。現状はPoC案件が多いので、お客さんも明確にイメージを持っているわけではないんです。だから、このデバイスだったら、ここまでこんな風にできますよっていうのを提案します。まずは、例えば絵コンテやモックアップを作って、簡単にイメージしてもらうことが多いですね。
あと、お客さんの頭の中は、映画、ドラマ、マンガとかがベースになっているので、我々とはノウハウの差が大きいんです。機械の制約もある上で、空想をどこまで現実に落とし込んでいくか、今ないものをどう考えて行くということが大事ですね。だから、イメージを共有するために現実に近いものを手早く作るようにしています。
(写真3:最新のxRデバイス Varjo XR-3をかぶる様子。実は接続していないので何も見えていませんw)
ーーお客様に具体的にイメージを湧かせる、スピード感あるやり取りが大切になりそうですね。 さて、話は変わりますが、ホロラボの良いところってどんなところですか?
割とみんな肯定的。ののしり合わないですよね。w それに、年齢の上下という関係がないです。技術は強い人が強い。プロマネでもある程度の納得はさせなきゃいけないし、腕のある人をある程度納得させなきゃいけないですよね。
ーー確かに「つよつよ」というイメージはありますね。
あと、フルリモートはすごいですよね。家の中で妻と話せる時間も増えました。前職の時にこういう環境だったら、子どもを持つことも考えたかもしれないです。 子育てにも優しいですね。男性でも産休・育休で休んでます。
ーーはい。現時点(2021年6月時点)で、男性育児休業取得率は100%ですね。 他に、おすすめポイントなんかはありますか?
インターネットの黎明期は、HTMLを書けただけで仕事が来ました。自分は次の波がAR、VR、MRだと思っています。その波に乗っておくのは「おいしい」はずです。 それに初期から関わっていると、その分野のコアが身につくし、ずっと蓄積ができるから強いですよね。
ーー最後に記事をここまで読んでいただいた方に一言お願いします。
まあ、やってみたらどうにかなるよね、っていう…。w やらなければ始まらないですよね。 意外に今までのことは無駄にならないです。あとは楽しく生きるためにはどうしたいいかを考えてもらったらいいんじゃないかなと思います。
ーーまさにその言葉の通り、白木さんは行動してきていますよね。 今日はありがとうございました!
ありがとうございました。
(了)
]]>
HoloLens発売から5年。コンシューマーの事例がVRやメタバース方面で盛り上がりを見せる中、BtoB方面ではMixed Realityの技術検証フェーズから実用フェーズに向けた取り組みが着実に進んでいます。一方で、こうしたBtoB方面の取り組みにフォーカスを当てた発表の場が少なく、先行して取り組みをされている企業様同士の交流や、これから取り組みを始める企業様の情報取集の場の必要性を感じていました。
そこで、ホロラボが各社様と取り組みを進めてきた実用に向けた取り組みや、今後メタバースの基盤技術となっていくBIM/CADやCGといった空間情報技術活用に向けた取り組みの事例共有の場として、「HoloLab Conference 2022 #HoloConf22」を開催します。
オンライン一般参加をご希望される方は、下記ページよりお申込みください。 https://hololab.connpass.com/event/241174
オンライン一般参加では、zoomでのリアルタイムセッション視聴/質疑応答、ホロラボDiscordサーバーでのオンライン参加者同士のリアルタイムチャットコミュニケーション(任意)が可能です。
※当日のセッション視聴方法やホロラボDiscordサーバーについてはお申し込みいただいた方に別途ご案内させていただきます。
実用に向けた取り組みをされている各社様とホロラボ合同の事例セッションと、基盤技術や技術調査などについての技術セッションの2種類のセッションを実施します。セッションは2タイムテーブルの進行で合計で最大15セッション程度を予定しています。
また、後日セッションはアーカイブとして公開する予定ですが、映像や音声の編集や一部セッションが非公開になる場合があります。ぜひリアルタイムでご参加ください。
ご登壇予定企業様(敬省略) ※3/17時点での情報になり、10社様程度を予定しています。
ホロラボセッション情報 ※3/17時点での情報になります。
会場施設と連携し各種ガイドラインを遵守とした感染対策の実施を予定しています。 感染症流行状況に応じて、オフライン会場の無観客開催もしくは、会場を利用しない完全オンライン開催への切り替えを予定しています。
(2022/4/26追記)
・東京都様式「イベント開催時のチェックリスト」の公表
記入済み_東京都様式イベント開催時のチェックリスト.pdf - Google ドライブ
株式会社ホロラボ イベント窓口:event@hololab.co.jp
※本記事に記載されている会社名および製品・サービス名は、各社の登録商標または商標です。
]]>実家のリフォームをきっかけに建築に興味を持ち、建築学科に入学。研究室では閉校した学校のリノベーション活用や、空き家の民泊活用などを研究していました。
内装を変えるだけで人がまた集う空間になるということに興味を持ち、内装業界を目指しました。
大学から建築を勉強されていたのですね。
はい、就職活動ではリノベーションや内装といったところを軸に応募し、中でもカルチャーを大事にしながらも新しいことに挑戦し続けている商業施設の会社に惹かれ、そこの内装設計部門に就職。5年間テナント設計を行っていました。そんな中で「BIM(Building Information Modeling)」という技術に出会い、3Dで空間のデータを構築していくことの面白さやAR/VR/MR技術を使ったデータの活用に感銘を受け、建築情報学分野に興味を持ちました。ホロラボでは2021年4月~業務委託契約、10月から正社員として働いています。
去年からだったんですね!今ではなくてはならない存在のように思えます。
ホロラボとの出会いはどこだったんですか?
前職でBIM推進のお仕事をしていたのですが、その情報収集をするのにTwitterを活用していました。そこでmixpaceのアカウントや建築情報学会メンバー、フォトグラメトリの龍さん、BIM講師のタケルさんをフォローしていました。どうやらみなさん繋がりがあって、ホロラボという会社がこの中心にいるな?と気付いた頃に、ちょうどBIMが扱える人の求人のツイートがホロラボから上がったんです。気になる!と引用RTしてみたら武仙さんからその日のうちにDMが飛んできたのがきっかけです(笑)
Twitterから!ホロラボでは結構多いですよね(笑)
Twitterから、多いですよね! お話をしてみたら非常に皆さん気さくで、かつBIMやMRへの希望や熱意にとても共感出来て、最初にDMをいただいてから2週間くらいで転職を決めちゃいました。入ってみたらホロラボ社内にTwitterでフォローしていた人が溢れていて驚きました(笑)
フォロワーが同僚になっちゃうのすごいですよね、入社してからも結構Twitterでやりとりしちゃいます。
みんなツイッタラーですよね(笑)
主にmixpaceをご利用されるお客様のサポートをしています。 mixpaceをご利用されたいお客様のデータが問題なくご利用いただけるか、事前にデータをお預かりして実際にiPad / HoloLens 2で表示が出来るかを確認します。ご利用中のお客様からのお問合せにも対応しており、データをお預かりして不具合状況を調べ、最適にご活用いただけるように手順をお伝えします。
不具合状況を調べるのは、建築の知識があって出来ることですね。
最近はそういったサポートで得た知見をmixpaceサポートデスクに残す仕事も増えてきて、文章を書く仕事が多くなってきた印象が強いです。データ検証と文章を書く仕事で右脳と左脳を駆使しています。
mixpaceサポートデスクではいつもお世話になっていますが、改めて何をされているのか聞くと面白いです。
元々Revitを扱っていたので建設業のお客様からのお問い合わせには対応しやすいのですが、建設業に限らず様々な業種のお客様も増えてきており、その分ソフトウェアやデータの種類の幅も増え、難しいサポート対応が増えてきました。ただ、mixpaceにお申込みいただくお客様の多くは社内でDX推進を行っている方や新しい技術を活用して業務を改革しようという熱意のある方ばかりなんですよね。なので、様々な業種の最先端を拝見できる感じがします。このデータは何に使われるのだろうとか、こういう表示の仕方があるのかとお客様から学ぶことも多く、非常に面白いです。
ホロラボに入る前は新卒で入った商業施設の会社で5年間内装設計の仕事をしていたのですが、仕事が忙しくなかなか資格の勉強が出来なかったんです。
仕事をしながらは本当に難しいですよね。
そんな中、ホロラボへの入社を決めて、とても前向きな決断だった反面、建設業を離れることに少し後ろめたさがありました。大学も建築学科を卒業したのに結局資格も取らないまま業界を離れたらもったいないなと思いまして。そこで、せめて証明できる物をと思い、二級建築士の勉強を始めました。
仕事の証明は確かに難しいので、資格を取っておけば一つの強みになります。
ホロラボで働きながらの勉強方法をお聞きしたいです!
資格学校へ週一回通うために9月の二次試験終了までは業務委託という形で働いていました。業務時間を9時-17時として、だいたい8時から1時間は構造の計算問題。これがかなり頭が冴えて良かったです。17時に終業した後は20時くらいまで集中して勉強時間を確保していました。
ホロラボは完全リモートなので通勤時間がないこともメリットですね 。
そうなんです。終業時間の1分後には勉強にシフトチェンジできるのがリモートの良いところで、はじめは勉強で机に向かうことなんて本当に久しぶりでかなり辛かったのですが、仕事の集中力のまま向かうことが出来たので上手く継続でしました。おかげさまでリフレッシュの時間も他の受験生に比べたらかなり取っていた方だと思います(笑)
小池さんはどんなワークスタイルなの?
ホロラボはフルリモートで通信環境とパソコンとiPad / HoLolens 2があればどこでも仕事出来る環境なので、入社をきっかけに実家へ帰ってきました。初めのころは学生時代に使っていた勉強机で仕事していたのですが腰を痛めてしまったのでデスクとチェアを一新しました。デスクは昇降式の物を購入し、立ったり座ったり同じ姿勢で長時間過ごさないように工夫しています。チェアは背もたれのないバランスチェアを購入しました。基本的には仕事中は立って、勉強中は座るという姿勢でやっていました。
立ちながらなんて健康にも良さそうです…。
二次試験の設計製図になってからは座って作図をするのが難しく、ずっと立って行っていたので椅子の出番はあまりなかったですが、昇降式デスクは今年買って良かったものNo.1です!試験が終わった今も仕事中は基本立ち姿勢で行っています
どうしても家だと色んな誘惑があってだらけてしまうので、慣れるまではかなり集中力を持続するのが難しかったです。起床してから必ずストレッチをして体を温め、朝食後はほぼ座らないようにしています。立った状態でデスクに向かうと、もう仕事するしかないので集中力が保てます。
確かにそうかもしれないですね…仕事するしかない環境作りが大事かもしれません。
あとはチームの文化として、9時の朝会後も基本的には音声通信をつなぎっぱなしにしているので、孤独感もなく私もやらなきゃ!となります。顔の見えない状態でのリモートのお仕事はコミュニケーションがとても重要だと感じていて、チャットツールで細かいことでもすぐ書き込んでみたり、チームでも雑談の時間を多く取るように心掛けたりしています。週一回チーム内でネガティブとポジティブを共有しあうレトロスペクティブの時間は非常に有意義な時間だなと感じています。
雑談時間、今年はもっと増やしたいですね!時間とりましょう(笑)
今年の5月にホロラボ内で保護猫の募集があり、2匹わが家へお迎えしました。先住猫もいたので今は3匹一緒に暮らしています。仕事中もデスクのすぐそばで寝ていたり、かなり癒されています。
会議中のネコチャンの声にこちらも癒されています。
また、平日はフルリモートでほとんど家にいるので、休日はなるべく外出するようにしていました。建築やアートが好きなので、街に出て散歩したり美術館へ行ったり。最近はコロナ禍も落ち着いてイベントも沢山開催されるようになってきたので、先日2年ぶりにコンサートへも行きました!世の中が落ち着いてきたらフルリモートの利点を活かしてワーケーション等もできたらいいなと思っています。
自分の軸があり、指示されなくても自分から課題を見つけ、解決できる人だと思います。良くも悪くもホロラボ内には役職や上下関係がありません。ましてやフルリモートでさらに住んでいる場所もバラバラ。そのため、かなり個人の意思に委ねられた職場環境だと思います。さらに、日々変化する最先端の技術を取り扱っているため、正直誰かからの指示を待っていたら何もできないと思います。
確かに、仕事がSlackでいきなり飛んでくることも多いですし、スケジュール管理も大事ですね。自分がやります!という気持ちが大事なですね。
建設業界の発展に携わりたいという思いでホロラボに入ったのですが、最近は建設業に留まらず様々なお客様との接点が増えてきたので、ものづくりをしているすべての人へAR/VR/MR技術で発展していってほしいなと思うようになりました。そのためにも、mixpaceを沢山の方にご利用いただきたいし、サポートを通じて色んな知見を深めていきたいと思っています。またせっかく資格を取ったので、それがお客様の信頼に繋がったら嬉しいなと思っています。アプリのサポートに限らず、受託案件などより現場に近い立場でお客様と一緒に課題解決をしていけたらいいなと考えています。
大学で建築を学び、内装設計のお仕事からBIMに出会い、ホロラボにjoinした小池さん!仕事をしながら二級建築士を取得したバイタリティに加え、しっかりした発言力と業務遂行力からチームにかかせない存在です。
ホロラボでは各々社員が工夫してフルリモート、スーパーフレックスの中でも仕事とプライベートにメリハリをつけて生活しています。 今度また色々な社員のインタビューを載せていく予定です。
小池さん、第1回目のインタビューありがとうございました!
]]>2020年のふりかえりはこちら
会社設立からなんと5年が経ちました。
2021年は3月のMicrosoft Mesh、10月のFacebookからMetaへの社名変更、11月のMicrosfot Ignite でのメタバースの話が大きな話題でしょうか。。
Microsfot MeshやMicrosoftのメタバースについては下記に記録が残っていますので、ぜひご覧ください。
アウトプットは会社視点、業界視点が多いのですが、手を動かすことも多く、客先に行って現場調整やデモからの3DスキャンからのVPSデモはよくやりました。
会社のほうにも書きましたが、この半年は個人的に手ごたえがあり、向こう半年、1年でそれを実証できればと思います。
2022年はどこまでいけるか楽しみでもあるので、来年のふりかえりで良い成果をかけるようにできればと思います。
]]>会社設立からなんと5年が経ちました。
今年も無事に終えることができました。お客さん、社員のみなさん、関わってくれた皆さんに感謝です。
PR的な内容はこちらから。
スライドはこちら
2020年、2019年のふりかえりはこちら
2021年もコロナ禍のため、なかなか現場へ行くことができないながらも、昨年と比べても数多くのアウトプットが出せました。
会社外も含めた大きな流れとしては、3月のMicrosoft Meshや10月のFacebookからMetaへの社名変更、11月のMicrosfot Ignite でのメタバースの話でしょうか。
Microsfot MeshやMicrosoftのメタバースについては下記に記録が残っていますので、ぜひご覧ください。
業務面では、この半年で自分の中での手ごたえが出てきており、向こう半年、一年で成果として出していければと思います。とはいえ、会社運営上の売上、利益についてはまだまだ課題もあり、この改善をしつつ攻勢で進めていければと考えています。
メンバーもいままでで一番多くの方に入社いただき、フルリモートの体制に移行したこともあり全国各地にメンバーがいます。
4月の「April Dream 4月1日は、夢の日。」に参加し、「遊びにも、仕事にも、勉強にも…あなたの日常にMixed Realityが溶け込んでいる。そんな世界を創る、自由でつよつよな会社です。」という夢を出しています。夢ではありますが、実現可能な世界だと感じていて、時間はまだかかると思いますが徐々にこの世界に近づけていけるように取り組みを進めていきます。
業務としては、株式会社大林組、株式会社ドコモ・森ビル株式会社との取り組みの影響が大きく、エンタープライズ向け、コンシューマー向けともに実運用に向けて進めています。
自社サービスのmixpaceではAutodesk BIM 360およびAzure Remote Renderingの連携を実装し、BIMを使用したワークフローの中にmixpaceが入る、そこで利用される大容量ファイルのHoloLens活用ができるようになりました。
また、toMap連携では、現場でのARデバイスのとは別に、俯瞰した環境での3Dデータ活用を進めています。
2021年は広域AR、大容量データ連携、現場と俯瞰の連携など、パーツがそろってきた印象です。
利用シナリオについてもいくつか有効なケースが見えてきたので、2022年はそれを検証すべく取り組みを進めていきます。
]]>ホロのPさん(Yusuke Saito Ph.D)です。 今年も一年、徐々にアウトプットを出せているような気がしています。良いこと。 自分の時間も作れています。良いこと。 ダイエットは諦めています。悪いことw
というわけで、もう少し具体的に振り返ろうかなと思います。
今年はエンジニアとして、またR&Dでリサーチャとして、兼任で動きました。
エンジニアとして一番大きかったのは、とあるプロジェクトの見直し(設計、開発、自動テストの記述)を行い、 また関連アプリケーション(PC)を追加でリリースしたことです。特に設計面、Model層をちゃんと切り分けて共通化・モジュール化して使いまわせるような形で作り、HoloLensアプリでも、PCアプリでもほぼ同じコードで動くようにできたのはよかったかな、と感じています。
ただ反省面もあって、引継プロジェクトの負債部分を甘く見ていて、結果的に作業量の見積もり精度が低かったのは反省点ですね。
一年を通して、主に空間位置合わせの研究をして、たまに機械学習の記事を書いて、といったような形でしょうか。
空間位置合わせの研究として、アウトプットを出せたのはよかったかなと思います。 ただ、欲を言えば、現場で使えるレベルまで昇華させていきたい、というのが本音であり、今後の目標でもあります。 blog.hololab.co.jp
また、上記内容をVirtual学会で発表できたことも良かったこととして挙げられます。 sites.google.com Virtual空間上で学会を行う、というとても興味深い試みをされており、またそこで発表できたのはとても貴重な経験になりました。今後も学術面でのアウトプットも出していきたいなと考えています。
一年を通して、徐々にではありますが、アウトプットを出せているのは良いことだと思います。来年は、さらにアウトプットに質と量を上げていく、ただあせらずに、というスタンスでやっていこうかなと考えています。 駄文ではありますが、ここまで読んでいただきありがとうございました。 来年もよろしくお願いします。
]]>同件は2021年3月にNTTドコモさま、森ビルさまにて、お台場ヴィーナスフォートの一部を舞台とした広域ARクラウドコンテンツの実証実験が実施され、ホロラボも開発協力との位置づけで参加させて頂いていたものの続編です。
3月時点でいくつもの技術的だったり企画面だったりのチャレンジがあったのですが実証実験自体は成功裏に実現。 約3,100平米(ホロラボ調べ)の広いエリアを使ったfree roam型ARクラウドコンテンツが実現しました。 ※歩きスマホはダメです!
関係者限定での実証実験だった関係で、当時から「体験したい!」と言った声を多数頂いていたのですが、今回この7月にようやくお披露目が出来ることとなりました! ぜひお時間の都合をつけてお台場ヴィーナスフォートでご体験を頂けると嬉しいです!
今回の実証実験についてはすでにNTTドコモさま、森ビルさまからそれぞれでプレスリリースをご発行頂いてますので、内容詳細についてはそちらをご参照ください。 色々とパワーアップしてます!
https://www.nttdocomo.co.jp/binary/pdf/info/news_release/topics_210706_00.pdf
3月と今回7月、二つの実証実験を通して、実にたくさんの人がホロラボメンバーとして開発や制作に参加してくれました。 以下がホロラボメンバーのスタッフクレジットです。
General Direction : Yu Hata - HoloLab Inc. / TheDesignium Inc. Inc. https://twitter.com/yhworld
Assistant/Legal : Takesen - HoloLab Inc. https://twitter.com/takesenit
General Contents Produce : Tomoyo Hirayama - HoloLab Inc. https://twitter.com/Riserva79
Tecnnical Direction / Contents Authoring : Keizo Nagamine - HoloLab Inc. https://twitter.com/KzoNag
Technical Direction : Tomoki Hayashi - HoloLab Inc. https://twitter.com/keshin_sky
Technical Direction : Hinoboru (Nisho Matsushita) - HoloLab Inc. https://twitter.com/liketableteninu
Authoring Tool : Tomonori Mizutani - TheDesignium Inc. https://twitter.com/mizutanikirin
Authoring Tool : Gerald Gmainer - TheDesignium Inc.
Authoring Tool : Yusuke Sakuma - TheDesignium Inc.
CMS/RT Server : Tatsuhiko Hayashi - TheDesignium Inc.
Client Viewer / IoT Server communication : Tomoki Hayashi - HoloLab Inc. https://twitter.com/keshin_sky
Client Viewer : Hinoboru (Nisho Matsushita) - HoloLab Inc. https://twitter.com/liketableteninu
Client Viewer / IoT Visualize : Fumo Yoshida - HoloLab Inc. https://twitter.com/fumobox
Client Viewer : Keizo Nagamine - HoloLab Inc. https://twitter.com/KzoNag
Planning : Tomoyo Hirayama - HoloLab Inc. https://twitter.com/Riserva79
Produce & Creative Direction : Tomoyo Hirayama - HoloLab Inc. https://twitter.com/Riserva79
Programming : Mitsuki Bando - Mark-On https://twitter.com/_udonba
Voice Actoress : Koromo Aida - freelance
Voice Actor : Tomisaburou Horikoshi - freelance
UI design : Tomoyo Hirayama - HoloLab Inc. https://twitter.com/Riserva79
Special Effects : Mao Wu - TheDesignium Inc.
CG Advisory :Yoshitomo Iwamoto - HoloLab Inc. https://twitter.com/yoshipon13
VR world CG Post Production : Ryo Fujiwara - HoloLab Inc. https://twitter.com/lileaLab
CGProducer&Art Director : Ken Yoshida - PICONA ,Inc. https://picona.jp
3D Director : Makoto Sato - PICONA ,Inc.
Character Design : Sayaka Shimada - (RED HOUSE Co., Ltd.)
- 3D Modeling
Modeling supervisor : Sachiko Daigoho - (Misatori Inc.)
3D Lead Modeler : Daigo Taketomi - PICONA ,Inc.
3D Modeler : Ki Chin - PICONA ,Inc.
- 3D Animation
3D Lead Animator : Daigo Taketomi - PICONA ,Inc.
3D Animator : Keita Suzuki - PICONA ,Inc.
3D Animator : Deepak Adhav - PICONA ,Inc.
- Assistant
Production assistant : Mayumi Enomoto - PICONA ,Inc.
3D Modeling Project Manager / Director : Toshio Yasuhara - MELPOT Inc. https://www.melpot.co.jp/
3D Modeling Art Director : Teppei Mizumoto - MELPOT Inc.
3D Artisrt Momo Igarashi - MELPOT Inc.
3D Artisrt Shinnosuke Kotani - MELPOT Inc.
3D Modeling Technical Adviser : Ryosuke Nakai - MELPOT Inc.
Video Editing : Naoyuki Hirasawa - TheDesignium Inc. https://twitter.com/eatora22
App Developing : Matt Hudson - TheDesignium Inc. https://twitter.com/mechpil0t
ーーー
今回の実証実験で、たくさんの方にご体験を頂いてフィードバックを活かしたいと思います。 皆さんのご来場をお待ちしています!
日程 2021 年 7 月 10 日(土)~7 月 11 日(日)、7 月 17 日(土)~7 月 18 日(日)
各日 午前 11 時 ~ 午後 5 時
※感染症状況等を踏まえ、一般体験を中止とさせていただく場合がございます。
実施場所 東京・お台場 ヴィーナスフォート 2F フロア(Venus GRAND)内 噴水広場 ~ 教会広場
参加方法 ヴィーナスフォート 2F 噴水広場付近に設置した受付にて、開催日当日先着にて参加受付
参加費用 無料
使用するデバイス 受付にてタブレット端末をお貸し出し
※Magic Leap 1 の体験はできません。ご了承ください。
リリースノートはこちら
変更点は下記です。
Azure Remote Rendering (ARR) でのモデル表示 と ローカルファイルピッカー(HoloLensのローカルディスクからのアップロード)が可能になりました。
これらは設定の「Experimental Features」から有効にできます。
ARRはContentメニューの左側タブから、ローカルファイルは右下から選択可能です。
ARR、ローカルファイルともにスペースでモデルおよび操作が共有されます。
ARRはモデル、操作の共有が可能。 pic.twitter.com/uF20Rdq3hJ
— 中村 薫 (@kaorun55) 2021年6月7日
ローカルファイルについて、今回の更新か、リリースノートを見ると4月の更新かで、画像ファイルへの対応が行われています(今まではGLB形式のの3Dモデルのみ)
画像ファイルは JPG,PNG,TIFF,GIF に対応しています(GIFは静止画として表示されます)
Meshアプリ内でのARRは、Meshがプレビュー期間中は無料のようです(個別にARRを利用する場合は有料)。
ARRを有効にするか、デフォルトのエンジンを表示するかのタイミングで OneDrriveの MyContent フォルダ ( OneDrive\アプリ\Microsoft Mesh App (Preview) 以下) に remote_models.json というファイルが生成されます。ここにARRで使用するモデルの名前とモデルファイル(arrAssetのSAS)を設定します
arrAssetのSASは変換済みARRアセットのBlobストレージの該当ファイルを選択し作成します。
作成したSAS URLをjsonのsasUriに設定します。
設定後にMeshアプリを起動すると、ARRタブに設定したモデルが表示、選択されます。
ARR用モデルの作成は「Azure Remote Rendering Asset Tool(ARRT)」を使用すると便利です。
]]>HoloLens 2の最新OSバージョンのWindows Holographic version 20H2がリリースされました。
バージョン番号は OSバージョン 21H1 ( ビルド 20346.1002 ) になっています。
Windows Updateにより更新可能です。
リリースノートはこちら。
英語
日本語
以前の更新はこちら
HoloLens 2の最新OSバージョンのWindows Holographic version 20H2がリリースされました - ブログ@HoloLabInc
HoloLens 2の最新OSバージョンのWindows Holographic version 2004がリリースされました - ブログ@HoloLabInc
更新された機能は下記になります(ドキュメントの日本語訳を調整したもの)
機能名 | 簡単な説明 | 対象読者 |
---|---|---|
新しいMicrosoft Edge | Chromium ベースの新しいMicrosoft Edge。 | エンド ユーザー |
WebXR および 360 ビューアー | イマーシブ Web エクスペリエンスと 360 ビデオ再生をお試しください。 | エンド ユーザー |
新しい設定アプリ | レガシ設定アプリは、新しい機能と設定で更新されたバージョンに置き換え中です。 | エンド ユーザー |
色の調整を表示する | 表示する別の色プロファイルを選択します。 | エンド ユーザー |
既定のアプリ ピッカー | ファイルまたはリンクの種類ごとに起動するアプリを選択します。 | エンド ユーザー |
アプリごとのボリュームコントロール | システム ボリュームとは独立してアプリ レベルのボリュームを制御します。 | エンド ユーザー |
Web アプリをインストールする | Microsoft Office Web AppsのようなWebアプリをインストールできます。 | エンド ユーザー |
スワイプして入力する | ホログラフィック キーボードで指のヒントを使用して単語を "スワイプ" します。 | エンド ユーザー |
[スタート] の [電源] メニュー | [スタート] メニューで、HoloLens デバイスの再起動やシャットダウンをができます。 | エンド ユーザー |
[サインイン] 画面に表示される複数のユーザー | [サインイン] 画面に複数のユーザー アカウントを表示します。 | エンド ユーザー |
USB-C 外部マイクのサポート | アプリやリモートアシスタンスで USB C マイクを使用します。 | エンド ユーザー |
キオスクのビジター自動ログオン | ビジターアカウントの自動ログオンをキオスクモードで使用できるようにします。 | IT 管理者 |
キオスクモードでの新しいアプリの新しい AUMIDs | AUMIDs は、新しい設定とエッジアプリを対象としています。 | IT 管理者 |
キオスクモードのエラー処理の改善 | キオスクモードでは、空のスタートメニューの前に、グローバルに割り当てられたアクセスを検索します。 | IT 管理者 |
新しい Settingは、ページ設定の可視性を示します | 新しい SettingPageVisibilityList は、Settings/ポリシーを対象としています。 | IT 管理者 |
フォールバック診断の構成 | 設定アプリでフォールバック診断動作を設定しています。 | IT 管理者 |
近くのデバイスとの共有 | HoloLens から PC にファイルまたは URL を共有します。 | すべて |
新しい OS 診断トレース | OS の更新の設定の新しいトラブルシューティング。 | IT 管理者 |
配信の最適化のプレビュー | 複数の HoloLens デバイスからのダウンロードの帯域幅の消費を削減します。 | IT 管理者 |
いくつかピックアップして紹介します
Chromium ベースの新しいMicrosoft Edgeに変わり、WebRTCやWebXRなどがサポートされました。
設定アプリが更新され、デスクトップのWindows 10のような細かい設定ができるようになりました。
システム → 調整 に色の調整が追加されました。
HoloLens 2の色味調整が可能になります。
スタートメニューから再起動やシャットダウンが可能になりました(今までは音声コマンドやデバイスポータルからのみ)
外部マイクをサポートします(今までは外部マイクは未サポート)。
システム → サウンド より、利用するマイクとスピーカーの設定が可能です。
]]>
中村です。
2021年5月26日から始まったMicrosoft Build 2021。
このKeynoteでのMixed Reality事例が印象的でした。
Keynoteは下記より、登録するとオンデマンドでそのまま見られます。
MR関連は14分あたりからです。
Keynoteで「メタバース」の単語が出たことが意外でしたが、いままで点であったデータが線、面と広がっていくと想像できます。
日本時間 5/27(木) 2:30 AM - 3:00 AM
日本時間 5/27(木) 6:00 AM - 6:30 AM 、 10:00 PM - 10:30 PM
日本時間 5/27(木) 7:00 AM - 8:15 AM
]]>第1回: 「LiDARスキャナ」について調べてみた (1)
第2回: 「LiDARスキャナ」について調べてみた (2)
そして、もとの記事AppleがII-VI(ツーシック)へ440億円を拠出した話題だったんですがw、だいぶ明後日の方向に記事が伸びてしまってますw
さて、前回まででLiDARスキャナの構造が、発光と受光と信号処理になってて、発光素子としてVCSELがビカッって見えないけれど光って、それをDOEがバラっと拡散するところまで書きました。
そうした光が、、、
VCSELアレイが発したレーザー光がDOEで拡散されて、近赤外線で明るくなった各ドットのイメージを、今度はソニー製SPAD(Single Photon Avalanche Diode)の受光素子が捉えて、ToF (Time of Flight):光の到達時間から距離を計算します。
SPAD(Single Photon Avalanche Diode: 単一光子アバランシェダイオード)技術についてはこちらのEETIMESの記事が日本語で読みやすい。https://t.co/INN8ydMLaX
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
そして、この記事もそうですがVCSELのサプライヤーは4億ドルAwardのII-VI IncではなくてLumentumという別な会社の名前になってるんです。 pic.twitter.com/0BsPFDh8zY
このSPAD自体は最後のDがDiodeなだけあって、そのもの自体は受光素子です。ただ、EETimesの記事によるとSPADはアレイ状に配置されていて、かつこのSPADアレイの下にToF計算用のロジック回路を配置して直接配線されている「ロジック統合型CMOSイメージセンサー」とのことでレポートしています。
「旧型の10ミクロンピクセルiToF設計に似ているように見えたが、史上初のインピクセル接続コンシューマーCMOSイメージセンサーであることが判明した。これは、単一光子アバランシェダイオード(SPAD:Single Photon avalanche diode)アレイだ」
また、ToF方式には光の到達時間そのものを「直接」測定するdToF(direct)と、時間ではなく位相の差から「間接的に」距離を計測するiToF(indirect)があります。一般的にはiToFがモバイル機器に使われていましたが、AppleのLiDARは屋外に強く長距離性能に長けたdToFを採用したとのことです。
ということで、冒頭に紹介した記事で「AppleがLiDARサプライヤのII‐VI社へ440億円提供」という文脈から行くと、残念ながらこの分解レポートにおいては下記構成で、II-VI社は含まれていない模様です。
もう一度ニュース原文を読み直して見ると下記の表現でした。
II-VI manufactures vertical-cavity surface-emitting lasers (VCSELs) that help power Face ID, Memoji, Animoji, and Portrait mode selfies. Apple also works with II-VI to manufacture lasers used in the LiDAR Scanner
直訳すると、「II-VIはFace ID、Memoji、Animoji、ポートレートモードの自撮りを実現するVCSELを製造します。また、LiDARスキャナーに利用されるレーザーの生産についてもAppleはII-VIと活動します。
どちらも英語的には現在進行形や現在完了形ではなく、現在系。特にLiDARスキャナーについては、生産についてワークする、だからまだ作ってないのかもしれないw 集めた情報から想定すると、「II-VIはLiDARスキャナの中の重要部品であるVCSELアレイのサプライヤになるかもしれない」という表現が適切なように感じました。
The expansion of the company’s long-standing relationship with II-VI will create additional capacity and accelerate delivery of future components for iPhone, with 700 jobs in Sherman, Texas; Warren, New Jersey; Easton, Pennsylvania; and Champaign, Illinois.
この枠組みで、700名の新規雇用が、テキサス、ニュージャージー、ペンシルバニア、イリノイの各州の工場で産まれるとのこと。
そして、この記事で本当に伝えたかったのはLiDARスキャナの中身だったり技術についてではなくて、米中摩擦や新型コロナにより分断されていく世界で、国際企業たるAppleとしては将来性あるテクノロジーに関連した雇用やSDGsに対応したGreenなサプライチェインを国内に積極投資していく、とのPRが主目的なように読めました。
今回のAppleによる4億ドルAwardも、電子部品、半導体不足だったり米中貿易摩擦みたいなところで、VCSELのような特徴ある技術を使ったキーパーツを自国で生産出来るようにしたり、工場を立てて雇用創出したりの国策に近い動きにも見えますね。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
ってことで、超絶長くなりましたがw、LiDARについて調べてたら日が暮れそうな勢いでしたw
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
「LiDARセンサーの供給元」のLiDARを広義の「Light Detection and Ranging」と考えるとiPhone一台に何系統も搭載されてる。
Rearの狭義LiDAR、FrontのTrueDepthに2~3系統。
しかも、それぞれの部品をマルチソースにしてる可能性も高そう。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
今回の4億円という投資も、今後の戦略技術や部品の生産キャパをAppleが自社用に囲い込みつつ向上させて、更に大量に使ってく方向性と考えると、、、やっぱりおれたちの大好きなLiDARの時代がやってきたって感じですねw
心臓部であるAシリーズなどもQualcomm製を使うのではなくARMコアを独自実装出来るライセンスを持ち、ユーザー体験を作るための根っこからデザインしてきたApple。コアのCPU自体はまだ台湾TSMCが長期パートナーシップの元で製造していますが、M1もMacだけでなくiPadに搭載を始めたことなどからも最新プロセスの生産キャパ問題がレポートされています。
情勢不安や米国が受けた新型コロナの打撃から国内産業の復興を政府が狙いたいのは明確。IntelがAppleシリコンの製造をしたいとのコメントを出していたり。
CPUについてはまだ具体的な動きは見えていない状況ではあります。ただ、モバイルデバイスが日々の生活に溶け込んでどんどん便利になるにつれて、その体験を支えるコア部品の継続安定供給性が極めて重要になってます。
全体的にサプライチェインを自社のコントロール可能な自国内に戻そう、というような動きが加速しそうです。 そして、日本人として気になるのは、ソニーのSPAD CMOSイメージセンサはどうなるのかなってところですねw AppleがII-IV同様にAwardしてソニーセミコンがUS工場に投資してUS現地雇用を産む、みたいな話になるのかな?
さて、ここまでが元々のAppleのAwardに関するニュース記事についての調査と、最後は重要なパーツをいかに安定供給するかが、この情勢不安な状況で国内主義的な方向で重要になって来てるんじゃないかとの仮説についてあれこれと書いてみたブログ記事でした。
そして、ここから先は調査の過程でさらに脱線しまくった部分w 散文的な感じなので流し読みして頂ければッて言う感じです。
あれこれと調べていたら本筋から逸れた方向でも興味深い話があったので、蛇足としてまとめてみますw
現在のLiDARスキャナでVCSELアレイを供給してるとレポートされたLumentum社について調べてみたら、光部品メーカーが食いつ食われつの買収合戦を繰り広げていたのが分かり、これまた興味深かったです。
LumentumもII-VI Incと同様にUSの会社で、通信用や産業用などのレーザー技術の会社。https://t.co/VIo10UNFlH
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
今年2021年の頭から、このLumentumとII-VIの2社にもう1社を含んだ合計3社で、Coherentという同じレーザー技術の企業買収を巡って泥沼の戦いをやってた模様。https://t.co/fmNnxB5AZn
II-VI Incは2018年にはFinisarという通信用レーザー技術の会社を買収してる。https://t.co/eDioZeYygH
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
何となく、2000年前後に光通信用にプレイヤーが増えたのがいったんサチって買収合戦になって、今度はLiDARによる3Dセンシング用で市場が盛り上がって来てる感がある。
2018年のII-VIとFinisarの買収劇をまとめたブログに掲載されていたチャートが、ビジュアルからしてすでに激しい。ディープパープルのメンバーチェンジ遍歴みたいw
FinisarにしてもCoherentにしても、ここで名前が出てくる会社の多くが産業用や通信用レーザーを作っていた企業。武仙も以前SFPの光モジュールとか扱ってたときにFinisarとかは競合他社で名前を聞いた記憶があります。
これは完全に想像ですが、2000年以降ネットワークにおける光通信バブルが起きて、メトロ側からOC-192とか光インターコネクトとかでニーズが出て、FTTHとかが流行って、、、っていうタイミングで多くのメーカーが通信用光部品に投資を実施。あるタイミングで光化がひと段落して横ばいになった市場に対してプレイヤーが多かったので統合が進んだのか、それから更に高付加価値化が求められて企業体力のあるところに集約が行われたのか、など色々となぜこんなに買収が頻繁に行われたのか考えてしまいます。
iPhone搭載DepthセンサーとしてはLiDARよりも歴史の長いFaceIDに使われる「TrueDepth」にも同様にVCSELアレイが使われて、サプライヤーとしてII-VI IncとLumentumの名前も出てくる。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
Lumentumは台湾の化合物半導体ファンドリーWin Semiconductorsに生産委託してるとのこと。https://t.co/Sbkp4gMi9A
ちょっと前2018年の機種、iPhone Xの記事なので最新ではないかもですが、TrueDepth用含めたフロント光学系のTierdownが、ややこしいwhttps://t.co/8K9rjATK0o
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
Depth自体はオーストリアams社Dot投光器とSTMicroのSPADモジュールらしい。(Light Coding方式) pic.twitter.com/8sPVWPcllU
紛らわしいのがFlood illuminatorとProximity SensorがSTMicro製で、これがTime of Flightを名乗るときがあるw
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
そしてこのFlood illuminatorもVCSELを使うし、別なams製のALS(Ambient Light Sensor)もVCSELだったりする模様。
このTrueDepthを調べてる過程で「すごいことに気づいた!」って思ったんですが、、、すぐに間違えてることをあるしおうねさんにご指摘頂きましたww
なんか、すごい細かい事に気づいたかも。。。フロントカメラもDepthをちゃんと2種類使ってる模様。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
1) TrueDepth ~ 顔認識用、Emojiなど
2) FaceID ~ TrueDepthを使わずにFlood illuminatorのToFだけで「顔認証」してる
今色々と実験してみて気づいた。。。勘違いしてた。
1) 細かな3Dの顔認識をする際にだけDot Projectorがオンになる。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
3Dスキャン用アプリだったり、SMSで顔認識を使ったミー文字を使う際。
呼び方もTrueDepthじゃなくって、、、なんて呼んだらいいんだろう。。。もう、初代KinectとかPrimeSenseって呼んでいいですか?whttps://t.co/ywuLz9t1GQ pic.twitter.com/52fWruXDAL
2) FaceID用にFlood illuminatorを使って顔認識をしてる様子。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
二つ光源があって、スタンバイから電源を押してロック状態で明滅する方が恐らくFlood illuminatorで、この反射を見て3D顔認証してるっぽい。
もう一つは認証後のロック画面でも、ロック解除後通常動作時にもずっと点滅してる。 pic.twitter.com/azz8x7cqyj
自分の認識だと、必要な場合にFloodとドットパターン照射を両方組み合わせてますね。Floodで「画像としての顔」の認証を行った後、それが「顔の形をしているか」をドットパターンを照射して3次元計測して判別していると思っています。これが写真印刷した紙では突破できない理由なのだなと https://t.co/74NcZYU9dL
— あるしおうね (@AmadeusSVX) 2021年5月8日
まだちゃんと実験してないんですが、原理的にFaceID認証の一瞬だけドットパターン側も照射されているはず。
2) のFaceID時のFlood illuminatorじゃない方はProximity Sensorと書いてるのでこれもIRを使って反射を見てるセンサーっぽいですね。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
FaceID時には照明替わりにずっと点灯してて、顔認証後は点滅動作になって低消費にしてるけれど、画面の前に顔(らしきもの)があるのかどうかを見てるのかも。
ということで、AppleのiPhone/iPadに搭載されてる光学センサー関係を調べてみたら超大作ブログが出来上がっちゃったというお話でしたw 目に見えない赤外線を操って、めちゃめちゃ限りあるバッテリー容量を有効に活用しながらも色々なUXをさりげなく、かつ結構野心的に実装してあるのが垣間見られました。
赤外線と同じく目に見えないとの観点では非接触充電用だったりU1チップによる超音波広帯域通信だったりと、これまた光学センサーと組み合わせたら面白そうな技術がすでに搭載されていて、、、センサー好きテクノロジー好きとしては引き続きAppleのモノヅクリやUXデザインに目が離せない状況が続きそうです!
ホロラボではLiDARスキャナを使ったiOSアプリも開発しています。
開発のお問い合わせはこちら。
https://hololab.co.jp/#contact
また、ARKitやLiDARを使ったiOSアプリ開発者も激しく募集しています! hololab.co.jp
面白そうだなと思って頂けたら、ぜひお気軽にお問い合わせください!
]]>登録が必要ですが、リプレイセッションがありますので、ぜひご覧ください。
自社事例含めて20分で6件入れてます。概要ながらもポイントを説明しています。
mixpace Remote Renderingについては日本マイクロソフト社のセミナーで紹介しておりますので、ぜひご覧ください。
]]>さて、もとの記事AppleがII-VI(ツーシック)へ440億円を拠出した話題に戻って考えると、
「LiDARのサプライヤー」って言った場合に、このLiDARの構成部品のうちのどのサプライヤーなのかが気になった、ということでしたw 細かくてすみませんw 一応、ホロラボを作る前に半導体商社で光半導体なども扱っていたりで、この辺も関心の深いところでしてw
2021/5の現段階において、Apple製品でLiDARが搭載されてるのが下記の大きく2製品3タイプ。
iPadって、ディスプレイのインチ数が異なると世代が違うので第〇世代ってシンプルに言えない状態なんですねw
まだiPhoneや最新M1 iPad Proの中身に関する情報は多くないので基本は2020年版iPad Pro搭載のLiDARについてですが、こんな資料があったので引用します。
Apple、iPad/iPhoneの裏面に搭載されてる「LiDAR」の中身で今まで詳しいチラシが。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
dToF方式のLiDARモジュールの中身は下記の構成とサプライヤ名。
VCSEL(発光素子) - Lumentumhttps://t.co/QI3Fbh5YSj
SPAD (受光素子) - Sony
DOE (光学素子) - Himax
Source: https://t.co/wTrLp02iou
System Plus社のTierdownレポートのブローシャ: https://www.systemplus.fr/wp-content/uploads/2020/06/SP20557-Apple-iPad-pro-Lidar-Module_flyer.pdf
こちらのレポート(のカタログ)によれば、主要部品は下記とのこと。
このVCSEL、SPAD、DOEのそれぞれがどんなものなのかについてや、AppleのLiDARスキャナで初めてこのサイズで実装されたdToF方式(direct Time of Flight)については、日系XTECHの記事がかなり詳しくまとまってます。関心のある人はぜひご参照ください。(要サブスク登録)
Appleの「LiDAR」の仕組み、dToF(direct Time of Flight)について日経XTECHの記事が詳しい。(登録者向)
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
このVCSEL、SPAD、DOEというOptoelectronics技術の組み合わせであの変態な性能の3Dスキャナがスマホの物理/電気フットプリントに載ることになったのが良く分かります。https://t.co/ruvLvsIxdf
今回このブログでまず注目したいのがVCSEL、ヒカリモノの方です。たしか940nmぐらいのNIRなので肉眼では見えないけれどw
このVCSEL(ビクセル)は光デバイス、半導体レーザーの一種ですが、良い感じの特徴があるので武仙もなぜか前職から気になって覚えてました。
VCSELはVertical Cavity Surface Emitting Laserのアクロニム、頭文字語で、日本語だと「垂直共振器型面発光レーザ」と訳されます。
VCSEL-Vertical Cavity Surface Emitting Laserは垂直共振器型面発光レーザと訳されます。ここでのCavityは英語だと「穴」っていう意味合いもありますが、光を閉じ込めて何度も往復させて増幅する「光共振器」っていう意味合いらしい。共振器が垂直に配置されてるってこと。https://t.co/jHmgiVM9cK pic.twitter.com/6ciFbrLTwr
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
こちらのTweetでの「Cavity」の意味合いに関してSATOMIさんからコメントを頂いてまして、半導体レーザーでは共振(resonance)しつつ発振させるので「共・発振器」の意味合いがあるとのこと。めっちゃ勉強になる。Twitter最高。そして「穴」って覚えててすみませんw
昔々、電通大のレーザー研に居たのですが、普通のレーザーのCavityは発振器と訳していて、半導体レーザーでは、Cavity長をレーザーの波長の整数倍に設計して共振(resonance)も利用して発振効率を上げるので、共・発信器が近いがいねんかも知れません。
— Mitsunori SATOMI (@gravitino) 2021年5月8日
このビビビビクセル、VCSELがどういう特徴を持ってるか分かりやすい図を探したのがこちら。同じヒカリモノデバイスのLEDと、あとはいわゆる普通のレーザーとの構造的な比較。
参照元: The FOA Reference For Fiber Optics - Fiber Optic Transmitter Sources-Lasers and LEDs
この図がめっちゃ分かりやすくて好きです。それぞれ、発光面、共・発振器の配置について書いてみる。(ここでのLASERは気体レーザーなどではなく半導体レーザー、Laser Diodeについて書いてます。)
ここはちょっと自信のない部分で武仙の理解を書きます。間違ってたらツッコミお願いしますw
LASERとVCSELはいずれも共振構造を持っていて、エネルギーを共振させて位相の単一な(Coherent: コヒーレントというらしい)「レーザー光」を生成できます。このレーザー光は波長が急峻で高い直進性が特徴。
LEDはそもそもこの共振構造を持たずに、pn接合のバンドギャップから生まれる光エネルギーをボヤっと大き目の開口から出すw
底面は鏡面構造になってたりと発生した光をなるべく表面から出すようなデザインになってるんですが、位相がバラバラなので減衰しやすい。
波長がLASERから比べれば幅広いし、開口が広く拡散するからボヤっと光る。
それでもってVCSELは、ちょうどLASERとLEDの良いところ取りを狙ったデバイス構造。もともと先にLASERが産まれて、その後に半導体加工技術が向上した結果、共振部を垂直配置して、LED的な低電力でもレーザー光が得られるように出来たもの、、、って理解しています。
ってことで、VCSELも面発光な点はLEDと一緒ですが、Cavityで増幅された光が狭い開口から射出されるため指向性が高く遠くまで光が届く。それでいて端面発光なレーザーより圧倒的に低消費電力化が可能。
なんとこのVCSELは、日本の人が発明。知らなかった。 https://jstage.jst.go.jp/article/lsj/37/9/37_649/_pdf
1977年に伊賀健一博士(現東京工業大学長)により発案
なんだか、ちょっとうれしいw
ただこのVCSELの出す光もレーザーと同じく開口径も狭くて直進性が高いので、LiDARとして使ったとしても遠くまで届きますがそのままでは2D/3Dに距離計測が出来ません。
そのため、Appleが採用しているLiDARではいくつか指向角を広くしたり3Dにするための手法が採用されている模様です。第一回で書いた「Solid Stateで3Dにする方法」で言うと、 1) レーザーを複数にしてラインスキャン状態にする、と3) 光学的に3D LiDARにする、が採られています。
端面を切断してそこから光を取り出すLASERと異なり、VCSELはLEDと同様に、一つの半導体ウェハ上にアレイ配置が可能です。
VCSELが(端面発光)レーザーと比較してもう一つ大きな特徴が、アレイ化が容易な点。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
日経XTECH記事によるとiPad Pro(2020)搭載LiDARモジュールのVCSELも4x16、計64個のアレイ形状。
> VCSELの光源の4つがひとかたまりになって電極につながり、それが16列並んでいた。つまり、合計64点あった pic.twitter.com/cpSHpBhahQ
日経XTECH記事によると、AppleのiPad Pro(2020)搭載LiDARスキャナモジュールにおいてもVCSEL素子は4x16、計64個のアレイ形状と判明しています。
VCSELの光源の4つがひとかたまりになって電極につながり、それが16列並んでいた。つまり、合計64点あった
今度は「Solid Stateで3Dにする方法」における、3) 光学的に3D LiDARにする、手法で更に広い範囲にレーザー光をバラ撒いてます。
iPad Pro(2020)搭載LiDARスキャナでは、この64個のVCSELアレイの光源を回折光学素子(DOE: Diffractive Optical Element)で、9つに分散させてバラまいてる様子が日経XTECH記事で説明されてます。(ぜひ本文を契約して読んでねw
DOEは光波が持つ回折(かいせつ)効果と、その効果を持つ格子状の構造体からなる光学部品。波状の光をスリットを通して回り込ませつつ波頭の集まる場所を集約することで任意の形に光の方向をコントロール出来ます。
LiDARスキャナの中ではDOEを使って、レーザーアレイの直進光を9つに分岐させています。レーザーの指向性の関係で照射範囲が点だったものを、VCSELをアレイ化して2D面にして、更に光学素子で拡散していると考えられます。
iPad Pro(2020)搭載LiDARモジュールでは、更にこの64個のVCSELアレイの光源を回折光学素子(DOE: Diffractive Optical Element)で9つに分散させてバラまいてる様子が日経XTECH記事で説明されてます。(ぜひ本文読んでねw
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
レーザーの指向性の関係で照射範囲が狭いのを光学素子で補ってる感じか。 pic.twitter.com/Ae65YMgSvg
この拡散によって比較的広い範囲にLiDARスキャナの光源を照射出来てるのが分かりますね。
VCSELとDOEによってばら撒かれたレーザー光はLiDARモジュールから放射状に広がっていきます。距離が延びればそれだけ照射範囲も広くなりますが、今度はVCSELの光が減衰するので、おおよそ信頼のおける測距結果が得られるのが5メートル程度。それぐらいの距離をこのドットパターンで覆うと、ちょうど人間の視野をカバーするぐらいになりそう。
手に持つにしても、メガネのように着用するにしても、AR利用を考えた設計になってる気がしますね。
さて、連載はまだ続きます。(次回リンク)
ホロラボではLiDARスキャナを使ったiOSアプリも開発しています。
開発のお問い合わせはこちら。
https://hololab.co.jp/#contact
また、ARKitやLiDARを使ったiOSアプリ開発者も激しく募集しています! hololab.co.jp
面白そうだなと思って頂けたら、ぜひお気軽にお問い合わせください!
]]>主に人、組織、技術の実装あたりです。
最近はHoloLensの土台としてのDXの必要性を感じているのですが、DXは実際には組織論だと考えていて、自分の組織含めて組織の考え方について触れるようにしています。
元々本を読むのは得意ではなかったのですが、Kindleで流し読みを覚えたので、それなりに読めるようになりました。
先日、社内でも自分の考え方として紹介したので、オープンな場でも残しておこうと思います。
いままさにHoloLensで未来を実装している最中なので。
電気の社会実装がおもしろかった。
インパクト、アウトカムの考え方について学ぶ。
「未来を実装する」と一緒に言及されるみたいなので購入。
CX(コーポレート・トランスフォーメーション)、IX(インダストリアル・トランスフォーメーション)あたりに共感。
ここから「両利きの経営」、「(Netflixの)NO RULES」が言及されている。
『DXの思考法』と『未来を実装する』を並べて言及されることが今日2回もあって、なるほどなぁと思いました。https://t.co/xdiJV1qjhy
— Taka Umada 🐴 馬田隆明 (@tumada) 2021年5月14日
DXのこの絵のあたりを読みたかったんだけど、ついおもしろくて一通り読んでしまった。
組織作り、ソフトウェアエンジニアのキャリアパスについて参考になった。
自分が考えていることと近いので、参考にしつつ、会社に適用する。
管理ゼロで成果はあがる~「見直す・なくす・やめる」で組織を変えよう
管理したくないので。
あと、自分の組織の考え方は、勝手に倉貫さんに影響を受けてる。
読んでなかったので。
そういえば、Mixed Reality は AI、量子コンピューターと並んでMicrosoftの次の投資分野だった。
かわぐちさんに教えてもらって。
常に成長できる意識をもってもらいたい。
ユニコーン企業のひみつ ―Spotifyで学んだソフトウェアづくりと働き方
アジャイルサムライのJonathanさんの本。角谷さんの訳。
組織の在り方、文化の醸成など。
ここから「米海軍で屈指の潜水艦艦長による「最強組織」の作り方」と「モチベーション3.0」が言及されている。
「命じる」から「委ねる」へ。
リーダシップのモデルは確実に変わっていて、それは海軍でも同じ。
モチベーション3.0 持続する「やる気!」をいかに引き出すか (講談社+α文庫)
「仕事」を「遊び」に変える
モチベーション3.0の要素 = 自律性 + 熟達 + 目的
会社としては内発的動機付け(「永久内燃機関」と呼んでる)で技術に取り組むことをよしとしている。
ティール組織 ― マネジメントの常識を覆す次世代型組織の出現
会社をヒエラルキーにするつもりはないので、近いのはティール組織だよねってことで。
自分の仕事の考え方、組織の考え方はScrumから来てる。
RSGT 2021の動画などを見てて野中先生の本をいろいろ読んでみた。
ちょうど「ワイズカンパニー」を読み終えたあとだったので、わかりやすかった。
野中先生の最近の本。
SECIモデルは社内やお客さんへの説明でも活用。暗黙知と形式知の話はシナリオによっては顧客課題の本質。
「コネクティング・ドッツ」はこれでその言葉を知った。
アメリカのDXって話で「デザイン思考入門」は馴染みがなかったので。
お客さんとやりたい。
自分が「あれもこれも」な性格で、それを「二項動態」という言葉で定義してるので、それでもいい裏付けとして。
ホロラボの強みは、この知的機動力が高い(新しい技術をすぐに取り込む)こと。
OODAループは海軍の個人判断の考え方、SECIモデルは組織の知的創造プロセス。
バイブル的な。
この知識と(少しの)実体験で、だいぶ考え方が変わった。
どこかで見つけた。
ホロラボの仕事はお客さんの希望を実装することなので、お客さん(ユーザー)に寄り添う組織、意識になることが大切だと考えている(もちろん、社内で関わる人も大切というのは前提)
NO RULES(ノー・ルールズ) 世界一「自由」な会社、NETFLIX (日本経済新聞出版)
これから読む。
自社に対する考え方はNetflixが近いかも。
なんで買ったかは忘れたけど、積んである。
「学習する組織」入門 ― 自分・チーム・会社が変わる 持続的成長の技術と実践
社内でオススメされた(それで「学習する組織」を買ってたことを思い出した)
LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する impress top gearシリーズ
読まないとと思いつつ、読んでない。
]]>ホロラボが出来る前はTMCNという3Dセンサーのコミュニティーで活動していたりもあったので、3Dセンサーのことはすごく今でも気になります。 そんな中で、こんなニュースが出ました。
このニュースが気になってLiDARについて調べ始めたら週末の時間の相当を消費。 Twitterでも反応をたくさんいただいて関心のある人が多そうだったので、こちらのブログにも加筆しつつまとめて書いておきます。 ※そして、書き始めたら分量がとんでもないことになってきたので、たぶん3部作ぐらいになりますw
4億ドルがAppleからUS企業II-VI(ツーシックス)へ提供(Award)されて、LiDAR用コアパーツの生産安定を狙うとの、LiDARファンとしては気になる嬉しい記事。https://t.co/jGPPRwt0Ni
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
そして「LiDARセンサーの供給元」には色々と意味がありそう。調べ始めたら沼だったw
#iPhoneという名のLiDAR https://t.co/NqPnYtPGkn
ニュース記事自体はAppleがLiDARスキャナ用部品のサプライヤーなUS企業II-VI Inc.(ツーシックス)に、4億ドル(約440億円)をAward(支給?)したとの報道。 ただ、それまでいろいろと知ってた話と総合すると「注目のLiDARのサプライヤー」って言い切ると語弊がありそうだなと思って調べ始めたのがきっかけでした。
そもそもLiDARって何よ?って話から始めなければなりませぬ。
なんか、LiDARの略語が何度調べても覚えられないと思っていたら、「Light Detection and Ranging」と、「Laser Imaging Detection and Ranging」のふたつの説?があるんですね。https://t.co/mJ61YTH6iF
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2020年1月15日
こちら、AppleがiPad ProへLiDARを搭載する前の2020年1月につぶやいてます。時代の先を行ってるぜアピール。 何で当時これを言ってたかと言うと、Livoxという車載用ながら当時にしては超ローコストなLiDARが発売されたから。
ホロラボの事業パートナーであるSB C&S社にてDJI社のLiDAR「Livox」のお取り扱いが始まりました。
— ホロラボ (@HoloLabInc) 2020年1月15日
ホロラボでもセンサー事業の一環として取り組んでいきます。 https://t.co/TYKnuI1S9e
LiDAR(ライダー)はいわゆるアクロニム(acronym)=頭文字語で、全体を記載すると下記2つのバリエーションがあるようです。
2文字目の「i」を大文字で書いたり小文字で書いたり、あとWikiによると軍事関係では「LADAR」と記載したりもあるようで表記ゆれが気になるところですが、光の跳ね返りを見て距離を測る技術って、ざっくり覚えてますw
代表的なLiDARの方法で有名なToF方式(Time of Flight)を例にしてみます。ToF方式LiDARの構成は発光部と受光部、その計測回路からなります。光源が発行した際の時間と、受光部がその光を受けた時間の差がTime of Flight、光の飛行時間?ということで、この時間差から計算することで対照物までの距離が割り出せる、という原理です。
あとこれもWikiを読んでなるほどなって思いましたが、いわゆる「レーダー:RADAR」も「Radio Detection and Ranging」のアクロニム。Radio=無線も、Light/Laser=光線もどちらも突き詰めれば「波」って観点では一緒。そう考えると、基本は「LiDAR」が表記的に正統派なのかもとかw
Appleが一番最初にLiDAR搭載を発表したのがA12 Bionicを搭載したiPad Pro2機種で、2020/3/18のことでした。世界的に、この日がLiDAR記念日ですね。(謎 www.apple.com
そしてApple製品においては必ず「LiDAR」と2文字目のiは小文字表記されているので、この場合にはLight Detection and Rangingの略である可能性が高そうです。 そしてLiDARセンサーと言わず、「LiDARスキャナ」なのですよね。
ちょっと話題がそれますが、↑の浜松ホトニクスさんのLiDAR原理をそのまま製品にした感じなのがこの辺のゴルフとかで使う測距計です。写真はニコンのページのものを参照。
測距テクノロジー | テクノロジー | COOLSHOT スペシャルコンテンツ | ニコンイメージング
ただ、これは直進するレーザーの当たった1点のみしか測れないので、「スキャナ」とは言えない感じ。
それで登場するのがこういうもの。
Scanse sweep #LiDAR moves!! It took one year to deliver since the finding, but the sensor and software seems good. pic.twitter.com/wtXsUHlVls
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2017年5月6日
レーザーと受光素子は1つなので、それをモーターで回転させてLiDARデバイスから水平方向360度の距離データを測定します。
これはKickstarterに出てた激安2D LiDAR。動画を見て頂くと、右上のテーブルの上の黒い円筒形のブツがグルグルと120rpmぐらいで回ってるのがLiDARデバイス。左のPCモニタで可視化してるんですが、さすが激安だけあって荒かったりであんまりよく分からないですねw
一般的なLiDARはこのタイプのイメージ。
この方式だと、北陽電機LiDARはインタラクティブコンテンツの制作で使ったりなイメージで有名ですね。
これでもまだLiDARデバイスを中心にした2D平面しか取れないので、これを3Dにしたい各位がいらっしゃいます。
一軸LidarがKeiganモーターで2軸になって
— 光輝@見える補聴器(仮) (@koukiwf) 2018年10月17日
unityで点群可視化!!https://t.co/ccmelz3wF7 pic.twitter.com/WtK33nOvhR
センサー仲間な光輝さんは、2D LiDARの回転平面をもう一つのモーター(Keiganモーター)で物理的に回転させて3Dにしてたり。
他によく見るのが、2D LiDARを2台直交配置して3Dにしてるケースとか。
これはポータブルな産業用スキャナNavVisの着用する3Dスキャナ。THETAで有名な「おっさんが映り込む致命的なバグ」を構造的に取り除きつつ、奥行きの点群もカラーも絶対逃さないぞっていう力強いデザインが魅力的ですw
メカ的に回転させるのはコストが高い、耐久性が下がる、物理フットプリントがデカイ、などの様々な課題があるので、最近はグルグルと回さないで3D LiDARを実現しようとしてる動きが多くみられます。詳しくはそれ系の記事があるのでご参照いただければですが、大きく下記のアプローチとその組み合わせっぽいです。
もともと回転系LiDARを使った自動運転で著名なVelodyneのLiDARは、内部にレーザーを複数チャンネル搭載したものを回すことで限定的ながら3D LiDARを実現する特許を取得していたようで、それで有名なんですね。上記1のアプローチ。
このページが経緯については詳しいです。
IntelもRealSenseシリーズでMEMSを使ったSolid State LiDARをリリースしています。3D LiDAR実現に関しては2のアプローチ。
戦争の火種を内包した危険なTweet。。。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2020年6月18日
そして、肝心なAppleのLiDARスキャナでは、アプローチとしては1の「複数光源」と3つめの「光学的に3D LiDARにする」っていうアプローチを組み合わせたもの、っていう風に武仙は理解をしています。
それを実現してるのが発光素子の「VCSEL: Vertical Cavity Surface Emitting Laser」と、光学素子の「DOE: Diffractive Optical Element」。
Apple、iPad/iPhoneの裏面に搭載されてる「LiDAR」の中身で今まで詳しいチラシが。
— Takesen - 武仙@一緒にMixed Realityやろうぜ!(採用拡大中) (@takesenit) 2021年5月8日
dToF方式のLiDARモジュールの中身は下記の構成とサプライヤ名。
VCSEL(発光素子) - Lumentumhttps://t.co/QI3Fbh5YSj
SPAD (受光素子) - Sony
DOE (光学素子) - Himax
Source: https://t.co/wTrLp02iou
次回投稿ではその辺を詳しく見て行きたいと思います。(次回リンク)
ホロラボではLiDARスキャナを使ったiOSアプリも開発しています。
開発のお問い合わせはこちら。
https://hololab.co.jp/#contact
また、ARKitやLiDARを使ったiOSアプリ開発者も激しく募集しています! hololab.co.jp
面白そうだなと思って頂けたら、ぜひお気軽にお問い合わせください!
]]>2日前にMicrosoft Designのブログから発表された「Touching Holograms」について。
1 Header Sequence_Oscar_Medium.mp4 from Microsoft Design on Vimeo.
↑の動画を見て頂くと、3DCGの豆腐に手で触れて、突っついて、掴んで、、、っていうインタラクションがとても自然に見えると思います。これだけですごく楽しい動画で、SNSのリアクションを見ると「スゲー」「自然だ!」みたいな感じで受け取られていました。
ただブログ本文を読んでみたら、出来上がった成果のビデオも面白いけれど、どちらかというとそこに至る考え方と試行錯誤のプロセスが楽しかったので、自分のメモのためも含めて書き残しておきます。 ぜひ気になった方は原文をそのままだったり日本語に機械翻訳してチェック頂くことをお勧めします。
本文: medium.com
ブログポストのタイトルが和訳すると「ホログラムに触れる」。
普段この「ホログラム」って言葉を使うのにすごく気を遣っているんですがw、ここは敢えて原文そのままにホログラムを使いたいと思います。いわゆる制作方法としての虹色の「ホログラム」を超えた使い方をMicrosoftは敢えてこのブログではやってるように感じてます。HoloLens 2着用者の目の前に、3Dのボリュームを持って提示されるものは「ホログラム」。
以下、メモ的に書いてます。全文訳するのもちょっと違うなと思いつつ、意訳+感想みたいな感じ。
HoloLens 2のデモを初めて装着する人に体験してもらう楽しさについて書いてありますw
ホロレンジャーな皆さんもよく、デモ体験を提供するときに、初めて体験する装着者に何が起こるか詳しいことを告げずに「掴んで持ち上げて」「そっちに置いて」など、Realなものを扱うのと同じような指示をすることがあると思います。
「おぉっ!」っと、ホログラムのRealな動きに全身で驚くデモ初心者の方のリアクションを見て、ニヤニヤした経験がある人はきっと多いはずw
このブログでは、「HoloLens 2におけるハンドトラッキングと視線、視野角の増加によって、インタラクションデザイナーと一般ユーザーの距離が狭まった」と表現されています。「普通の人でも、Realの動作と同じように使える」体験が作れるようになったわけですね。
最新技術は時として専門家にしか使われ得ない複雑さを伴います。しかしながらMixed Realityにおいては今回のHoloLens 2の登場によって、一般人でも特別な操作方法を学ぶことなく、普段の行動の延長として使える最新技術となってきた点がすごくステキですね。
ブログではこの、一般の人でも初見で使えるための考え方や取り組み、より魅力的にするための手法について紹介されてます。
どのようにしてより自然なインタラクションを実現するか。 握る、押す、投げるなどの動作は下記の物理法則の組み合わせで出来上がってます。
これらの物理法則を実現するためにリアルタイム物理エンジンがキーとなります。ゲームなどでは、ユーザーのボタン操作などがバーチャルな物理となって、バーチャルなオブジェクト間でインタラクションを実現します。同様にMixed Realityにおいては物理的なユーザーの動きを(HoloLens 2のジェスチャーなどを介して)バーチャルなオブジェクトとインタラクションさせることで実現します。
2 Physics Intro_Oscar_Medium.mp4 from Microsoft Design on Vimeo.
このビデオで、ハンドジェスチャーで検知されたデジタルツインな手の各ポジションに球形のホログラムが表示されていますが、動きが早くなった際やホログラムのキューブとの接触により該当する箇所の球体が物理エンジンによる勢い、衝突、摩擦、重力が計算されて光っているのが分かると思います。
ただここで問題が発生します。ニュートンの運動の第三法則「作用反作用」。 現実の世界のようにインタラクションを作りたくても、ホログラムでは触覚が提示出来ないのです。
どれだけホログラムの見た目をRealっぽく作ったとしても、現実では感じるはずの触覚がないことからユーザーはその感じることが出来ず、触っている間「ゴースト」のように感じられてしまいます。
Microsoft Designerはこの課題をデザインするため、HoloLens 2で提示可能な「vision:視覚」と「sound:聴覚」の2つの感覚に対してover-communicate: 過剰に感覚提示することで解決を試みています。
触ったり放したりの動作の時に、音を鳴らし、ホログラムは光り、ユーザーにそのホログラムの動作を強く提示します。また、作用反作用はもともと双方向なので、物理での反作用提示が出来ないホログラムは、代わりに光でその関係を演出提示します。
3 Lit Hand_Oscar_Medium.mp4 from Microsoft Design on Vimeo.
手に明るいホログラムを持った手は明るく照らされます。このちょっとしたエフェクト一つでインタラクションに奥行、近接度合い、方向などの情報を付加して、リアルさが格段に上がります。赤く光るホログラムを手に持ったユーザーは「暖かく感じた」と答えたこともあるそうです。
このチャプターがMixed Realityのすごく面白いところw 物理的なリアルさを追い求めた結果、面倒臭かったり不可能だったりで、求めてないバーチャルなものへのインタラクションが発生しちゃいました。
「床に落ちたオブジェクトをしゃがんで拾う」 「はるか遠くに吹っ飛んだオブジェクトを取りに行く」
せっかくバーチャルなのでこういうリアルならではの不便を「法則を曲げる」ことで解決しちゃいます。
4 Surface Gravity_Oscar_Medium.mp4 from Microsoft Design on Vimeo.
落下する対象が近くにある場合には重力が働きますが、無い場合には宇宙ステーションのように宙を漂う、重力の法則を曲げたインタラクション。
重ねたキューブの倒れた先にテーブルがない場合には落ち切らずに倒れ掛かった状態でふわふわ宙に浮かんでる様子とか面白いですw
surface gravityを適用したオブジェクトを高く、手の届かない距離まで放り投げたユーザーがいて、そのオブジェクトを不安定なストールに乗って物理的なリスクをユーザーが冒して回収するケースがあったようです。
それをバカバカしいと感じて、次のインタラクションが産まれました。
5 Telekinesis_Oscar_Medium from Microsoft Design on Vimeo.
このtehekinesisはアイトラッキングとジェスチャーの組み合わせで、見つめてるバーチャルオブジェクトに対して掴んだり引っ張ったりなジェスチャーを実施するとフワっと手元に飛んできたり、動かしたりが出来ます。勢い、衝突、摩擦、重力などの物理法則を複合的に曲げて実現するインタラクション。
リアルな世界にはこの物理法則はありませんが、みんなスターウォーズのフォースなどで慣れ親しんだインタラクションなので、恐らく少し練習したらすぐに慣れて使えるようになりそうです。
ふたつのインタラクションによって実現したビデオのようなリアリスティックな体験はあくまでtangible Mixed Reality interactionの1例で、物理法則を注意深くシミュレートしたデジタル体験においてもっと多様な可能性がある、とのことで、このブログは結ばれます。
いくつか例示されてるなかで、音源のオーナーシップについて「インタラクション表現が変わることによってそのオーナーシップ(所有しているという)感覚にどのような影響を与えるか」っていうケースがすごく興味深い。
How could the feeling of ownership change if you could hold a music album in your hands, put it on your shelf, throw it to your speaker to play, or burn a mixtape and hand it to a friend?
今のデジタル音源の購入はスマホのアプリで決済ボタンを押すだけだし、味気ないプレイリストDBに1行データが増えるだけに感じられます。
これが、街中で掛かってる音源を気に入ったらtelekinesisでドーナッツ盤?を手繰り寄せて、サンプルプレイを楽しんで決済。自分のバーチャルな鞄にドーナッツ盤が挟まって、、、気に入ったらハイファイカセットにお気に入りの他の曲と一緒に吹き込んで友達に投げつけて、、、。
バーチャルで便利になるのはもちろんですが、デジタル体験一つ一つに物理法則を注意深く観察して、Mixed Realityで出来ることや出来ない事を踏まえた新しいインタラクションを考えて、作ってみてっていう試行錯誤をたくさん実施することが重要、なんですね。
ブログの冒頭も、こうやって書いてありました。
The honest answer was, “I don’t know, but try it.”
ホロラボは、XRの可能性や魅力に憑りつかれたたくさんのホロレンジャーが日々Tryしてたくさん失敗?しているエキサイティングな職場ですw
各職種で積極採用をしていますので、こういう新しい体験をたくさんの実験から生み出すことに関心のある方はぜひお気軽にご応募ください。
https://hololab.co.jp/recruit/
また、もっとくわしくホロラボのことが知りたい方は6/4に開催される「xR合同転職相談会」を視聴してみて下さい。他のXR系の会社さんも出るので色々と聞けて面白そうです!
https://www.youtube.com/watch?v=bwO4TCHY8O0
ということで、Mixed RealityでたくさんTry!して、新しい体験を作っていきましょ~!
]]>今週はメンバー間の技術共有、4月になって受託開発案件が落ち着いたこと、連休前の気分転換などから「スキルアップ週間」と称して「モブワーク」のイベントをやってみました。
目的は基本スキル向上と共有(実践練習の場)とし、お題に対する感性を目的としない、さまざまな技術やツール、日ごろ勉強している内容の実践の場と定義しました。完成を目的としないことで、実験のしやすさや、注力するポイントを変えるなど、チームの興味に柔軟に対応できるようにしています。このあたりは Coderetreat の思想を取り入れています。
参加メンバーには1日~3日の時間をとってもらい、チーム編成、アプリ開発(2時間 x 3スプリント)を行いました。毎日作るものは同じでゼロから作るようにしています。これはアプリを作るうえでよくある「作り直したい」を仕組みとしていれているのと、同じことを繰り返すことで内部の洗練を目的にしています。また、毎日最初から始めることで、1日だけの参加者にも入りやすいようにしています。
「毎日ゼロから作る」、「チームを毎日変える」、「全チーム、全日同じテーマで作る」あたりは変数なので、いろいろ変えてみてもおもしろそうです。
初日は作ることにフォーカスをするチームが多く「まずはやってみる」から始まり、2日目は設計・テストへの興味、3日はUI/UXへの取り組みと、同じことを繰り返すためより全体を見通して考えられるようになったように感じました。
ホロラボも30人を超えてきて、フルリモートワークということでメンバー間同士のつながりも意識的にしないといけないということでの今回の取り組み、参加メンバーからは「普段は話さない人と話せた」、「知識の共有ができた」、「個々人で考えてること、意識の疎通は難しい」などのコメントがもらえたので、今後も継続してやってみようと思います。
(オンラインだと、わいわいやってる様子の写真が取れないので、楽しさを伝えきれないのが悩ましいですw)
]]>4/27に日本マイクロソフト主催の「『Azure Remote Renderingを活用して超重量級CAD/BIMを扱う「mixpace Remote Rendering」のご紹介』」に登壇しました。
1時間ほどで内容は下記になっており、HoloLensの概要からAzure Remote Renderingの概要、活用事例まで広く情報を得ることができます。
アーカイブの公開もありますので是非ご覧ください。
サイト
アーカイブ配信はこちら(要申し込み)
スライドはこちら
mixpace Remote Renderingについて
mixpace Remote Renderingは国土交通省 関東地方整備局さまでも活用いただいており、その概要をPTC社のセミナーでも紹介しております。
こちらも要登録ではありますが、ぜひご覧ください。
]]>2021年4月23日に開催された「Kobe HoloLens Meetup! vol.4 - Ignite 座談会」に登壇しました。
内容としてはMicrosoft Meshの全体観、Azure Remote Rendering、 Azure Object Anchorsについてです。
LTでMicrosoft Regional Directorの 室長さんが登壇されたこともあり、後半の座談会はビジネス寄りになりました。こっちよりでの座談会は珍しい気がしますので、ぜひご覧ください。
動画はこちら
スライドは「Microsoft Ignite Recap Community Day」と同じなので下記を参照ください。
]]>ホロラボ 斎藤です。今回、R&Dチームの取り組みの一つとして、BCPDを用いた空間位置合わせに関する調査を行ってみました。
AR/MRにおいて、コンテンツを含む仮想空間と現実空間を合わせることはとても重要です。 それぞれの空間の位置、回転、およびスケールを合わせることによって、ユーザーに違和感なく現実への情報の重ね合わせを行うことができます。
そこで、今回はBCPD(Bayesian Coherent Point Drift)という点群位置合わせの手法の一つを用いて、HoloLens 2で空間位置合わせを行ってみました。
まずはデモ動画をご覧になってください。
特にHoloLens2では、仮想空間の座標系の原点位置および回転は、アプリ起動時の端末位置および回転となります。 しかし、このままだと現実との空間座標系が合っていないため、仮想空間を現実に重畳できません。 したがって、何らかの方法で仮想空間と現実空間の位置合わせを行う必要があります。
今回のデモでいうと、仮想的な家具を示すオブジェクト(水色がベッド、ピンク色がたんす)を、空間位置合わせを使って、 現実の家具の位置へ重畳することにあたります。仮想的な家具を示すオブジェクトの初期配置は起動位置によって違うため、 起動後に仮想空間と現実空間の位置回転の差分を計算し、仮想空間の補正をしていきます。
仮想空間と現実空間の位置合わせのために、よく使われる手法としては、画像マーカーを用いる方法が挙げられます。 また既存サービスとしては、Microsoft社のAzure Spatial Anchors *1 や、Azure Object Anchors *2、およびPTC社のVuforia *3 などが挙げられます。 現状 HoloLens 2 以外では、Immersal \ *4 も注目されています。 ホロラボにおいても、位置合わせに関する研究開発を行っています。
点群位置合わせ手法の一つで、点と点の対応関係を効率よく導くことができる手法です。基本的には非剛体の点群位置合わせ手法ではありますが、パラメータを調整して剛体位置合わせに用いることもできます。 github.com
今回は、BCPDを剛体位置合わせ用のパラメータを指定することで、あらかじめ取得した部屋の点群と、位置合わせしたいタイミングでの部屋の点群の間のRST行列を得ます。 ここでのRST行列とは、回転(Rotate)・拡大縮小(Scale)・平行移動(Translate)を含む4行4列の行列を指します。 下記図は、あらかじめ取得した部屋の点群(青色)と、位置合わせしたいタイミングでの部屋の点群(緑色)、変換した結果の点群(水色)の関係を示しています。
システム概要図を以下に示します。
まず、今回あらかじめ部屋の点群(ターゲット点群)を取得しておきます。
①まず、位置合わせしたいタイミングでの部屋の点群データ(インプット点群)を取得します。 取得にはMRTKのサービスロケータから取得できるSpatial Mapを使用しています。 (Spatial Understandingも使えると思います。)
②次に取得した部屋の点群データ(インプット点群)をローカルネットワークを介してPCへ送信します。 今回BCPDの計算自体は計算用のPCを用意して、ローカルネットワークを介してやり取りをしています。 ただ、手法としてはHoloLens 2上で計算することもできるはずです。
③インプット点群と、あらかじめ取得しておいたターゲット点群を使ってBCPDの計算を行い、二つの点群の間のRST行列を取得します。
④取得した二つの点群の間のRST行列をHoloLens2端末へ送信します。
⑤二つの点群の間のRST行列を用いて、空間をの位置合わせを行います。
今回はHoloLens 2における、BCPD(Bayesian Coherent Point Drift)という点群位置合わせの手法の一つを用いた空間位置合わせシステムを開発しました。 現在、2章で紹介した他の手法と比較して、精度、計算の速さ、利用点群の組み合わせ(例えば、全部屋をターゲットとして、インプットを一部屋にした場合はどうなるか?)についても調査を進めています。 また、点群取得デバイスが違う場合(例えば、iPadのLidarで取得した点群をターゲットにした場合)ではどうすればよいか?などについても研究を進めていきたいと考えています。
*1 Azure Spatial Anchors :
https://azure.microsoft.com/ja-jp/services/spatial-anchors/
*2 Azure Object Anchors :
https://azure.microsoft.com/ja-jp/services/object-anchors/
*3 Vuforia :
https://developer.vuforia.com/
*4 Immersal : https://immersal.com/
]]>2020年4月から、毎日(最低)25分、業務とはあまり関係ないプログラミングをして、GitHubにプッシュするという個人的なチャレンジをしていました。ちょうど1年たって穴をあけることなく目標達成したのでメモとして残しておきます。
なお、ほとんどが private リポジトリで写経などを行った物を上げているだけのものだったりという感じでとくに公開しているものではないです(今後は公開できる何かに注力するのも良いかもしれないとは考えています)。
ちなみに、なぜ 25 分かというと、以前読んだポモドーロテクニック入門という本にかかれていた25分という時間が元になっており、25 分であれば無理なく集中できるという個人的な感触によるものです。PDCAを回して改善とかそういった大層なことはしていません。
あとは、大体の時系列のメモです。
C#プログラミングのイディオム/定石&パターン
Unityだけでなくピュアな C# をもうちょっとしっかり基礎を固めておこうと思ってはじめたものです。内容としてタイトルの通りイディオムやパターンととして使えそうなコードサンプルが豊富にありとても良い本でした。
Unity2017最適化ガイド
普段からUnityを利用するのであれば読んでおいて間違いのない本です。
作れる!学べる!Unreal Engine 4 ゲーム開発入門 第2版
エンジンのバージョンも割と新しく、入門として良い本だと思います。
C++でつくるUNREAL ENGINEアプリ開発
UE C++ について書かれた本は数少ないので貴重な一冊です。
C#によるWindowsシステムプログラミング
読んだのは第一版ですが、他の本ではあまり書かれていないようなマネージドとアンマネージドの章があり参考になりました。並列処理についても詳しく書かれています。GUIについてはWindows Forms で書かれているので少し古いかなという気はします。
UnrealEngine4アクションゲーム ブループリント入門
すべて実装してみましたが、やりたいことを目次から探して逆引きリファレンス本として活用すると良さそうな本です。
GitHub Actions 実践入門
GitHub Actions はまだあまり使いこなせていませんが、動かしてみてどのようなものかを理解だけしました。
Unity ゲームエフェクトマスターガイド
Unity におけるエフェクト解説本も数が限られていると思うので、興味がある方にとっては参考になる本だと思います。パラメータのどのあたりを触ればいいのかといった勘所がなんとなく身についたような気はします。
OpenCV4 基本プログラミング
いつか手を出してみようと思ったままずっとスタックされたままの OpenCV に手を出してみました。この本はC++で説明されていますが、Pythonの本などもあるので興味に合わせて選択するのが良いと思います。画像処理や動画処理は純粋にやってて楽しいです。
WEB+DB PRESS vol.117 Typescript
このころになぜか急に Typescript に興味が沸いたため買ってみたものです。1冊の厚い本と違ってコンパクトにエッセンスが把握できてよかったです。
JavaScript徹底攻略 非同期処理
この著者の方の JavaScript の本は良かったのですべて買いました。代表的なものとしてこの2冊だけ載せておきます。JavaScript の前提知識がない場合は Typescript を始めるならまず初めにこちらを呼んでおくのが良いと思います。
Node.js デザインパターン
JavaScript, TypeScript に興味を持ち始めたのでその勢いのまま Node.js にも手を出してみました。知識がまだ十分に追いついておらずもう一度読み直そうと思っていますが、これも買ってよかったと思える1冊です。
JavaScript グラフィックスプログラミング入門
丁寧にかかれているので JavaScript の勉強としても良い本だと思います。Typescript に書き換えながら実装していました(たまにany使ったりしながら...)。
いまどきのJSプログラマーのための Node.jsとReactアプリケーション開発テクニック
少し古めの本なので、積極的にお勧めはしずらいですが、そのあたりをカバーできる程度の基礎知識が身についているのであれば、参考になる内容も多いと思います。
りあクトⅠ.React言語・環境編
りあクトⅡ.React基礎編
りあクトⅢ.React応用編
りあクト TypeScriptで極める現場のReact開発
React に関してはこれらの本が個人的には一番お勧めです。
オンラインゲームの仕組み
説明するまでもないほど定番かもしれませんがお勧めです。
UniRx/UniTask完全理解
こちらも 最近ではよく使われるライブラリだと思うので、末永く Unity と向き合っていく場合は読んでおくべき本だと思います。
Head Firstデザインパターン
GoF本も有名ですが、デザインパターンについて学びたい場合はこちらも内容としてはわかりやすくお勧めの本です
Rustプログラミング入門
最近Rustの人気が高まり始めたように感じるのでとりあえず手を出してみたという感じです(が、個人的には積極的に手を出す理由も今のところないので Rust はもうちょっと様子見しようかなと思っています)。
実践Vim
プラグインの使い方とかではなく、純粋にVim力を上げるためのガチの本です。
Create game with Unreal C++
これも Unreal C++ について書かれた貴重な本です。順番に進めることで、C++で簡単なシューティングゲームのようなものが作れるようになります。
Azure Functions入門
サーバレスの技術は使いこなせたら便利だろうと思ったので、手を出してみました。Azure Functionsに関する本としてここまでのボリュームでまとめられた情報は他にないと思います。進化の早い領域なので情報が陳腐化していないかは気になるところだと思いますが、今年に入ってから読み始めましたが、特に情報が古くて使えないといったことはありませんでした。
React Native
M1 Mac で React Native をやってみたかったので買ってみたものです。環境構築の基本的な流れは本の通りだと思いますが、M1 Mac が出てから日も浅かったこともあり環境構築も一苦労で、Hello World ができたあたりで力尽きました。またそのうち触りたいと思っています。
ゼロから作るDeep Learning 3
全60ステップあり、1日1ステップぐらいな感じで進めました。だいたい1ステップごとにアウトプットが確認できるような作りになっているので、楽しみながら取り組めます。また Python の使い方(__call__など特別なメソッドの説明やnumpyに関する補足、テスト、モジュール化の方法など)についても適宜説明があるので、Pythonの知識も身に付き一石二鳥です。
あとは目を通しただけの本などをメモとして、、、
レガシーコード改善ガイド
HoudiniとUnreal Engine 4で学ぶリアルタイムVFX
Power Apps ローコードで作成するビジネスアプリ入門
Effective C#6.0/7.0
More Effective C#6.0/7.0
InDesign クリエイター養成講座
プログラミングTypescript
オブジェクト指向UIデザイン
ドメイン駆動設計入門
React.js & NEXT.js 超入門
Clean Architecture
SwiftUI徹底入門
OneNote全事典
Visual Studio Code 実践ガイド
Blazor入門
エッセンシャルWPF
昨年7月にHoloLensMeetupで発表した手の動作認識では、機械学習のライブラリとしてOpenCVForUnityを用いていました。 画像処理の機能が使える反面、OpenCVForuUnityを使用する場合だとライセンス料がかかってしまう、という欠点があります。
そこで、HoloLens2でWindows.AI.MachineLearningを使って手の動作認識をしてみました。 UWP標準の機能を用いることで、特別にライセンス料などのコストをかけることがなく機械学習を用いることができます。
コードはGithubに上げてあります。 ポイントをいくつか挙げて解説していきます。
https://docs.microsoft.com/ja-jp/windows/ai/
Microsoft公式のWindowsアプリに機械学習を実装を行うことができます。UWPアプリにも対応しています。
モデルファイルは下記を参考にしてください stopengin0012.hatenablog.com
アップしたコード上では、HoloLens実機のピクチャフォルダ以下を参照するようにしています。
private string dirName = "HandGestureModel"; private string fileName = "handgesture_v001.onnx"; private async Task LoadModelAsync() { #if WINDOWS_UWP var dir = await KnownFolders.PicturesLibrary.GetFolderAsync(dirName); var file = await dir.GetFileAsync(fileName); // モデルのロード handGestureModelGen = await HandGestureModel.CreateFromStreamAsync(file as IRandomAccessStreamReference); if (handGestureModelGen == null) { Debug.LogError("モデルデータの読み込みに失敗しました. "); } #endif }
したがって、下記図に示すように、ビルド時にCapabilityを設定してあげる必要があります。
また、(結構忘れそうな事項として)onnx拡張子のファイルへの参照を有効にします。 下記の図のように、サポートされるファイルの種類に「.onnx」を指定してください。
基本的には、先日の記事で実行確認した時と同じです。 入力を合わせることに注意してください。
... (using参照) #if WINDOWS_UWP using Windows.AI.MachineLearning; using Windows.Storage; using Windows.Storage.Streams; #endif ... private async Task<string> RecognizeGesture() { #if WINDOWS_UWP ... float[] data = ReadToFloatArray(handJointController.handGestureData); handGestureInput.Input120 = TensorFloat.CreateFromArray(new long[] { 1, columns * frameCount }, data); //Evaluate the model var handGestureOutput = await handGestureModelGen.EvaluateAsync(handGestureInput); IList<string> stringList = handGestureOutput.label.GetAsVectorView().ToList(); //Debug.Log($"判定された動作ラベル:{stringList[0]}"); //IL2CPP 確認用 var label = stringList[0]; return label; #endif }
HoloLens2でWindows.AI.MachineLearningを使って手の動作認識を実装しました。 その上で気をつけるポイントをいくつかまとめました。
昨年7月のスライドです
www.slideshare.net]]>
sklearnで作成したRansomForestモデルをONNXファイルに変換し、Windows Machine Learningで利用する際に気を付けることを書いていきます。
サンプルに、HoloLens2取得したHandGestureを分類するコードをGithubに挙げました。 github.com
Windows Machine LearningのUWPアプリでONNXモデルを利用する際、どうやらモデルに型不明な経路(?)があると、ロードに失敗します。
これを防ぐために、convert_sklearn関数でinitial_typesやfinal_typesを指定します。 ここでfinal_types指定の際、zipmap出力の型(map(string,tensor(float))の指定方法がわからず、方法を模索していたところ、zipmap変換をしない方法にたどり着きました。
options = {id(pipeline): {'zipmap': False}}
上記のoptionsをconvert_sklearnの引数に指定します。
from skl2onnx import convert_sklearn from winmltools.convert.common.data_types import FloatTensorType, StringTensorType, Int64TensorType options = {id(pipeline): {'zipmap': False}} rf_onnx = convert_sklearn(pipeline, target_opset=7, options=options, name = 'RandomForestClassifier', initial_types=[('input', FloatTensorType([1, 120]))], )
出力されたONNXモデルは以下のようになります。
ONNXのバージョンに気をつける必要はありますが、とりあえずwinmltoolsのコンバータを使用せず、最新のskl2onnxを使うことができました。
from skl2onnx import convert_sklearn
当然といえば当然ですが、入力・出力の型を合わせる必要があります。skleanrからのコンバート時にinitial_typesを指定するなども、その一環として行っています。
... # データ入力時 handGestureInput input = new handGestureInput(); input.Input120 = TensorFloat.CreateFromArray(new long[] { 1 , 120 }, feature); ... public sealed class handGestureInput { public TensorFloat Input120; }
TensorString型の取り出しには、一癖あるなぁと感じます。 取り出し方としては、TensorString.GetAsVectorView().ToList()で、string型のListに変換し、その要素を取り出します。
//Evaluate the model var handGestureOutput = await handGestureModelGen.EvaluateAsync(input); IList<string> stringList = handGestureOutput.label.GetAsVectorView().ToList(); Debug.WriteLine($"判定された動作ラベル:{stringList[0]}");
sklearnで作成したRansomForestモデルをONNXファイルに変換し、Windows Machine Learningで利用する際に気を付けることを書きました。 (HoloLens2上で実行できたらいいな....)
]]>会社のふりかえりはこちら。
今年は肩書がふえました。「XR コンソーシアム理事」と「Microsoft Reginal Director」の2つです。
自分のできること、得意なことを考えると、こういう活動ができるのがいいのかなと思っています。
会社としてもMixed Reality Partner ProgramでGoldの認定をいただけたので、業界的にそういう立ち位置で見られるんだということで、それに見合った動き方ができるようには心がけています。
執筆としては「HoloLens 2入門」を出版しました。
開発ではなく利用に向けた本で、いまの状況から見ても本はこちら側でよかったと思っています。開発については変化が早いこと、公式ドキュメントが充実していることからなかなか悩ましいところです。継続的なアップロードができる環境であれば。という感じでしょうか。
登壇はHoloLens以外のところを意識的に増やしました。
HoloLensに関しては立場的なところで出ることが多くなりました。それ以外のところは必要な時だけ出るようにしています。
開発プロセスとしてRSGT2020から始まり、Agile Fest Osaka、Agile Tech EXPOと年間通して関わることができました。この一年でやっと自分の中で腹落ちしてきた感があります。
ほかにPower Platformに注力しています。ここで作ったベースは引き続き取り組んでおり、一部はテストながらもお客さん環境でも稼働するようになりました。
この辺りはXR Kaigiの講演動画を見てもらえるといいのかなと思います。
だいぶ総力戦感が出てきて、まぁ大変って感じはありますが、それはそれで楽しいのでまぁいいかなという感じです。
コロナ禍で会社をフルリモートにしたので開発時間が増えたのがうれしいところです。
動画は以下でアーカイブが公開されています。
2020 Epic MegaJam Kickoff | Inside Unreal
内容としては以下の5つあります(括弧内は開始時間)。
製品紹介の動画が流されていました。興味のある方はすでに見たことがあるかもしれませんが、こちらは動画を見ていただくのが一番分かりやすいと思います。
以下のような内容について説明されていました。
プロジェクトの初期設定から始まり、UX Tools のインポート方法やキューブをハンド操作できるものをストリーミングで行うところまで説明されています。
この内容とほぼ同様のことができる状態のものをテンプレートとして用意しているので、興味があればお試しください。
またこちらの動画でもほぼ同じ内容を「日本語で」説明しています。
MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTER
UX Tools を利用してハンドメニューを実装する方法が1から説明されておりとても参考になります。 また実機へのデプロイ方法も最後に説明されています。
パフォーマンスを考慮して以下の内容が説明されています。 とても参考になる内容のため、別途ブログにでも書きたいと思います。
以上、現時点において UX Tools の使い方やパフォーマンスに関する内容はとても貴重なものであると思いますので興味のある方はご覧になられると良いと思います。
]]>
まず最初に、テンプレートにするためのプロジェクトを作成します。
プロジェクト名については、すでに TP_HoloLensBP というテンプレートが存在していたので、自分が作成した物であることが分かる名称にするのが良いと思いますが、ここでは TP_HoloLens という名称にしたものとします。
具体的なプロジェクトの内容として以下の設定を行っておくのが良いと思います。
これらの具体的な設定方法については以下をご参照ください。
MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTER
C:\Program Files\Epic Games\UE_[Version]\Templates 配下に先ほど作成したプロジェクトを格納します
以下のフォルダは削除します
Templates\TP_HoloLens\Config\DefaultGame.ini を開き ProjectName 変数を追加します
[/Script/EngineSettings.GeneralProjectSettings] ProjectID=4D0B0F6940B43F7E0260AE87738672FB ProjectName=HoloLens Template
Templates\TP_FirstPerson\Config\TemplateDefs.ini を Templates\TP_HoloLens\Config\TemplateDefs.ini. にコピーします
Templates\TP_HoloLens\Config\TemplateDefs.ini を開き、LocalizedDisplayNames 変数と LocalizedDescriptions 変数を更新します
LocalizedDisplayNames=(Language="en",Text="HoloLens") LocalizedDescriptions=(Language="en",Text="HoloLens template") LocalizedDisplayNames=(Language="ko",Text="HoloLens") LocalizedDescriptions=(Language="ko",Text="HoloLens Template") LocalizedDisplayNames=(Language="ja",Text="HoloLens") LocalizedDescriptions=(Language="ja",Text="HoloLens用のテンプレートです") LocalizedDisplayNames=(Language="zh-Hans",Text="HoloLens") LocalizedDescriptions=(Language="zh-Hans",Text="HoloLens Template")
ClassTypes, AssetTypes の行はテンプレートの説明に表示するためだけのものであり、プロジェクトの作成には影響しないため削除します
また以下の行を削除します
SharedContentPacks=(MountName="FirstPerson",DetailLevels=("Standard")) SharedContentPacks=(MountName="Geometry",DetailLevels=("Standard","High"))
Templates\TP_HoloLens\Media に以下ファイルを格納するとサムネイルとして表示されます
以上でプロジェクト作成時にテンプレートとして表示されます。
プロジェクト作成後からすぐに UX Tools のコンポーネントも利用可能な状態になっています。
テンプレートは以下で公開しています。 1drv.ms
こういった便利なテンプレートはおそらくそのうち公式から公開されるとは思いますが、それまでのつなぎとして利用されると良いと思います。
本日のアンリアルフェスのNON-GAME講演は株式会社ホロラボ(@HoloLabInc)の加藤さま(@hi_rom_)による
— アンリアルエンジン (@UnrealEngineJP) 2020年11月18日
「MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発」です
こちらもライブによる質疑応答ありです!https://t.co/NthGBxxlOk #ue4 #ue4fest #HoloLens #MRTK pic.twitter.com/RKv9x9n2Sh
動画は以下で公開されています。
MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTER
UE4 を利用した HoloLens 2 アプリ開発に興味がある方は是非ご参照ください。
]]>
CameraOffsetTest
CameraOffsetInputSimulationProfile を試すシーンのようです。
説明がないので詳しいことはわかりませんが Oculus Quest 2 など別のデバイスで必要となるカメラオフセット調整用でしょうか。
ColorPickerExample
実行時にさまざまなマテリアルのカラー値を変更するカラーピッカーと対話するためのいくつかの異なる方法を示したサンプル。
DialogExample
ダイアログコントロールの使用法を示したサンプル。
DockExample
ドックのサンプル。このコントロールを使用すると、オブジェクトを所定の位置に出し入れして、パレット、シェルフ、およびナビゲーションバーを作成できる。
DwellExample
Dwell のサンプル。項目に視線を合わせ、見つめ続けることでトリガーするコントロール。
ElasticSystemExamples
弾性システムのサンプル。MRTK 内で動的、応答性、および手続き型のフィードバックとアニメーションを可能にする。
MRTKExamplesHub
MRTKExamplesHubMainMenu の親シーン。
MRTKExamplesHubMainMenu
MRTK の様々なサンプルを確認することができるシーン。
複数のシーンを切り替えるための Scene System の参考にもなる。 詳細については MRTK Examples Hub (日本語)参照。
HandCoachExample
体験で使用できるさまざまなハンドコーチの例を示したサンプル。
HandMenuLayoutExamples
ハンドメニューレイアウトの例をいくつか示したサンプル。
JoystickExample
ジョイスティックのサンプル。
ジョイスティックを使用して大きなオブジェクトを移動、拡大縮小、回転する方法を示している。また、ジョイスティックの動作を微調整するスライダーが下にある。
MixedRealityKeyboardExample
OS標準のキーボードを表示するサンプル。
Unity エディター上ではキーボードは表示されないが、物理キーボードで入力は可能。
NonNativeKeyboardExample
OS標準ではない独自のキーボードを表示するサンプル。
Unity エディター上でも表示される。
PulseShaderExamples
ハンドメッシュと空間メッシュの視覚化にパルスシェーダーを使用する方法を示したサンプル。
RiggedHandVisualizer
SkinnedMeshを制御して手を視覚化するサンプル。(詳細)
DirectionalIndicatorExample
方向インジケーターの使用法を示したサンプル。
FollowSolverExample
Follow ソルバー(追跡対象のターゲットの前に要素を配置するソルバー)のサンプル。
MRTK v2.5.0 の更新内容については、リリースノート をご参照ください。
MRTK v2.5.0 では UPM(Unity Package Manager) を利用した場合 Examples を個別にインストールする必要があります。
UPM によるインストールについては、以下を参照ください。
Mixed Reality Toolkit and Unity Package Manager
以降、各シーンの概要です。
AudioLoFiEffectExamples
ローファイオーディオのサンプル。球をタップすることで3種類の効果を確認できる。
AudioOcclusionExamples
音の遮蔽を確認することができるサンプル。壁の前と後ろで音の聞こえ方が変わる。
BoundaryVisualizationExample
境界を視覚化するサンプル(VR向け機能)。
DiagnosticsDemo
診断システムを使用して実行時のアプリケーションパフォーマンスを確認するサンプル。
EyeTrackingDemo-00-RootScene
アイトラッキングの他のサンプル(02~05)の親シーン。
EyeTrackingDemo-01-BasicSetup
アイトラッキングを行うための最小設定のシーン。
EyeTrackingDemo-02-TargetSelection
アイゲイズと選択(エアタップまたは音声コマンド)で宝石を破壊するサンプル。
EyeTrackingDemo-03-Navigation
アイゲイズとスクロール、パン、ズームイン/アウトのサンプル。
EyeTrackingDemo-04-TargetPositioning
目とハンドまたはボイスによるオブジェクトの選択、移動を行うサンプル。
EyeTrackingDemo-05-Visualizer
アイトラッキングデータをビジュアライズするサンプル。
Glb-Loading-Demo
ネット経由で Glb ファイルを読み込むサンプル。
Gltf-Loading-Demo
StreamingAssets にある Gltf ファイルを読み込むサンプル。
予め StreamingAssets 配下に gltfファイルを準備しておくか、または以下の [Copy models to StreamingAssets] ボタンを押してモデルを取得しておく必要がある。
HandInteractionExamples
プレス、タッチ、グラブ、スクロール、移動、回転、スケールなど、さまざまなタイプのハンドトラッキングインタラクションを示したサンプル。
HandInteractionGestureEventsExample
IMixedRealityGestureHandler を使用したさまざまなタイプのジェスチャーイベント(Select, Hold, Manipulation, Navigation)を示したサンプル。
HandInteractionRecordArticulatedHandPose
手のポーズ(位置・回転)を記録するサンプル。Record Right Hand、もしくは Record Left Hand のボイスコマンドで記録を開始し、Stop ボイスコマンドで記録を停止する。Console に記録内容が json で表示される。
HandInteractionTouchablesExample
さまざまなタッチ可能なコンポーネントと、それらがさまざまなコライダーとどのようにインタラクションするかを示したサンプル。
HandMenuExamples
ハンドメニューを表示するサンプル(追跡されたオブジェクトを手で拘束されたコンテンツの安全な領域に拘束するソルバーである HandConstraint の使用方法を示している)。ハンドメニューを表示するには、手を上げて手のひらを見る必要がある。
LeapMotionHandTrackingExample
Leap Motion によるハンドトラッキングのサンプル。本サンプルを試すには、Leap Motion Controller が必要。
NearMenuExamples
様々なメニューのサンプル。ピン止めしたり、掴んで移動したりできる。
DictationExample
音声を録音し、音声のテキスト化を行うことができるサンプル。日本語を表示する場合は日本語のフォントを入れる必要がある。
DisablePointersExample
PointerUtils の利用方法を示したサンプル。
コードから Hand Ray、Gaze、Grab、Poke などのポインターをオンオフすることができ、 HoloLens 1 と 2 などのスタイルのインタラクションを切り替えることができる。
InputActionsExample
異なるソースからの入力をユーザー定義の入力アクションにマッピングし、単一のリスナーを介してそれを処理する方法を示したサンプル。
回転可能なオブジェクトにフォーカスを当てた状態で、以下のアクションのいずれかを行うと Cube が回転する。
InputDataExample
手、頭、目、モーションコントローラーの位置・ポジションなどの入力データにアクセスする方法を示したサンプル。
PointerResultExample
ポインタのヒット位置を利用して、ポインタクリック時にオブジェクトを生成する方法を示したサンプル。
PrimaryPointerExample
プライマリポインタ変更イベントを使用してプライマリポインタを追跡する方法を示したサンプル。
感覚を掴むために、異なるコントローラを使用してチーズを選択して操作したり、コントローラを切断したり、トラッキングロスを強制したりして遊ぶと良いらしい。
SpeechInputExamples
音声コマンドの構成および使用する方法を示したサンプル。
Open, Close, Change Color, (Select) の音声コマンドが登録されており、音声コマンド発声時にフォーカスが必要な Local Speech Handler と フォーカスの必要がない Global Speech Handler の例が示されている。
ScrollingObjectCollection
ScrolingObjectCollection コンポーネントを使用したさまざまなタイプのスクロールインタラクションを示したサンプル。
SolverExamples
ソルバーのサンプル。
ソルバーは、あらかじめ定義されたアルゴリズムに従ってオブジェクトの位置と向きを計算する手段を容易にするコンポーネント。
SurfaceMagnetismSpatialAwarenessExample
Spatial Awarenessを使ってSurface Magnetism Solver の使用を示したサンプル。
現実空間の壁の表面にオブジェクトがスナップして、ポインタに追従する。
TapToPlaceExample
タップしてオブジェクトを配置するサンプル。
タップして配置すると、オブジェクトがサーフェスに配置される。 サーフェスが検出されない場合、オブジェクトは、ソルバーハンドラーにあるTrackedTargetType(ヘッド、コントローラーレイ、ハンドジョイント)を基準にしたデフォルトの距離に配置される。
SpatialAwarenessMeshDemo
空間認識のサンプル。現実環境をワイヤーフレームメッシュで表示する。
球のクリックで環境認識のオブザーバーの動作を停止・再開できる。
ClippingExamples
Mixed Reality Toolkit/Standard シェーダをクリッピングプリミティブ(ClippingPlane、ClippingSphere、およびClippingBox)と組み合わせて使用して、メッシュ上のピクセルを動的にクリップする方法を示したサンプル。
HoverLightExamples
Mixed Reality Toolkit/Standard シェーダと HoverLights を組み合わせて使用し、メッシュをダイナミックにライトする方法を示したサンプル。
MaterialGallery
Mixed Reality Toolkit/Standard シェーダで可能なマテリアルとシェーディング手法の例を示したサンプル。
OutlineExamples
Mixed Reality Toolkit/Standard シェーダを MeshOutline、MeshOutlineHierarchy、および MeshSmoother コンポーネントと組み合わせて、さまざまな手法を使用してメッシュレンダラーの輪郭を描く方法を示したサンプル。
StandardMaterialComparison
Unity/Standard シェーダと Mixed Reality Toolkit/Standard シェーダを比較したサンプル。
StandardMaterials
Mixed Reality Toolkit によって提供される標準的なマテリアルを示したサンプル。
MixedRealityCapabilityDemo
プラットフォームとデータプロバイダーによってサポートされる Capability の状況を表示するサンプル。
BoundingBox
BoundingBoxExamples
様々なタイプのバウンディングボックスのサンプル。
BoundingBox コンポーネントは deprecated となっているので注意。今後は BoundsControl を利用する。
BoundingBoxRuntimeExample
実行時にバウンディングボックスを作成し、さまざまなバウンディングボックスのプロパティを変更する方法を示したサンプル。
BoundingBox コンポーネントは deprecated となっているので注意。今後は BoundsControl を利用する。
BoundsControl
BoundsControlExamples
様々なタイプのバウンディングボックスのサンプル。
BoundsControlRuntimeExample
実行時にバウンディングボックスを作成し、さまざまなバウンディングボックスのプロパティを変更する方法を示したサンプル。
Collections
ObjectCollectionExamples
オブジェクトコレクションのサンプル。
オブジェクトコレクションは、あらかじめ定義された3次元形状のオブジェクトの配列をレイアウトするのに役立つレイアウトコントロール。
Interactables
InteractablesExamples
Interactable コンポーネントのサンプル。
Interactableは、ボタンやUIコントロールなどのインタラクティブなコンテンツを構築するための基本コンポーネントであり、インタラクティブな状態に基づいてフィードバックを提供する。
Lines
LineExamples
ライン描画のサンプル。ラインは Data Provider と Renderer の2つのコンポーネントから成る。
ManipulationHandler
ManipulationHandlerExample
ManipulationHandler のサンプル。 ManipulationHandler コンポーネントは deprecated となっているので注意。今後は ObjectManipulator を利用する。
球が操作でき、 壁にぶつかると、インタラクションが停止する。
ObjectManipulator
ObjectManipulatorExample
ObjectManipulator のサンプル。
球が操作でき、 壁にぶつかると、インタラクションが停止する。
ObjectManipulatorExamplePhysics
ObjectManipulator の物理機能をテストするためのサンプル。
PressableButton
PressableButtonExample
PressableButton のさまざまなカスタマイズ例を示したサンプル。
ProgressIndicator
ProgressIndicatorExamples
進行状況インジケーターのサンプル。
Slate
SlateExample
Slate プレハブでの HandInteractionPanZoom スクリプトの使用を示したサンプル。
Slider
SliderExample
ピンチスライダーコントロールの使用方法を示したサンプル。
Text
TextPrefabExamples
テキストプレハブのサンプル。
適切なスケーリング値と Text3DShader によるオクルージョンサポートにより、品質が最適化されている。
Tooltips
TooltipExamples
ツールチップのサンプル。
簡単にいうと、HoloLens2に内蔵されているセンサー類のストリームデータを可視化・保存できるモードのことです。 もちろん、研究用途のためなので、動作保証とかないです。(なので、お仕事で使う場合は気をつけてください) また、Preview版なので、変更される可能性が高いです。 詳しくは、下記ドキュメントをご覧になってください。 docs.microsoft.com
ドキュメント通りやれば大丈夫なはず。 OSのversionが19041.1356 以降となってれば使えるはずです。 また、デバイスポータルでReserchmodeを有効にすることを忘れずに。
公式にサンプルコードが公開されています. https://github.com/microsoft/HoloLens2ForCV
本記事では、Samples/StreamRecorder以下を参照します。 ここには、記録するためのプロジェクト(C++)と、保存したデータをロードするコード類(Python)が入っています - StreamRecorderApp : 記録するためのプロジェクト(C++) - StreamRecorderConverter : 保存したデータをロードするコード類(Python)
まず、ソリューションファイルStreamRecorderApp/StreamRecorder.sln を開きます。
(20200912時点)現在のコードだと、RGBカメラの情報やEyeTrackingの情報を記録するモードになっていません。 これを有効にするために、以下の手順を踏んでください。
AppMain.cppファイルのコードを少し変えます。 //Set streams to capture となっている部分に以下を追記(20200912時点)してください。
std::vector<ResearchModeSensorType> AppMain::kEnabledRMStreamTypes = { ResearchModeSensorType::DEPTH_LONG_THROW }; std::vector<StreamTypes> AppMain::kEnabledStreamTypes = { StreamTypes::PV , StreamTypes::EYE };
Debugビルド、ARM64で実行すると、Start・Stopボタンが表示されます。 Start押し、適当な時間の後Stopを押して記録が完了するのを待ちます。 記録が完了すると、以下の図ようにHandの位置などが可視化された状態になります。
仮想環境を作成し、python3, numpy, opencv-python. open3dをインストールしてください。 この辺は省略します。
python StreamRecorderConverter/recorder_console.py --workspace_path <output_folder> --dev_portal_username <user> --dev_portal_password <password>
すると、下記のようなコンソール画面になります。download_allを入力してEnterを押すと、実機からダウンロードされます。
データには、HandやGazeのデータがCSV形式になっていたり、またCameraパラメータなどもあるようです。
下記コマンドで、ダウンロードしたデータを、いくつかのスクリプトで読み込める形にできます。 - <path_to_capture_folder> : 実機からダウンロードしたフォルダのパスを指定してください("2020-09-11-175712"のように日付の形式になっているフォルダです)
python process_all.py --recording_path <path_to_capture_folder>
python convert_images.py --recording_path <path_to_capture_folder>
python project_hand_eye_to_pv.py --recording_path <path_to_capture_folder>
青がGaze, 緑がHandかな??
python tsdf-integration.py --pinhole_path <path_to_pinhole_projected_camera>
tsdf-mesh.plyが作成されます.
]]>
確認した MRTK のバージョンは v2.4.0 です。なお、今のタイミングでこのような調べ物をしているのは MRTK がかなり安定してきており v.2.5.0 だろうが v.2.6.0 だろうが大きく変わることはないと考えているためです(HoloToolKit → MRTK になったような破壊的変更が無い限りは問題ないはず)。
さっそく継承関係から見ていきます。
以下のインタフェース、クラスについては、こちら で確認済みのものになります。
登録済みデータプロバイダーが現在のプラットフォームで要求された機能をサポートしているかどうかを確認するためのインタフェース。
public interface IMixedRealityCapabilityCheck { // 1つ以上の登録済みデータプロバイダーが現在のプラットフォームで要求された機能をサポートしているかどうかを確認する bool CheckCapability(MixedRealityCapability capability); }
引数の MixedRealityCapability は以下のような enum です。
public enum MixedRealityCapability { ArticulatedHand = 0, GGVHand, MotionController, EyeTracking, VoiceCommand, VoiceDictation, SpatialAwarenessMesh, SpatialAwarenessPlane, SpatialAwarenessPoint }
Mixed Reality Toolkitの入力システムのマネージャーインターフェイス。入力システム機能を提供するためのすべての代替システムは、このインターフェースから派生する必要がある。
かなりの要素を持ったインタフェースですが、大半がイベントを発生させるメソッドで、例えば Visual Studio で #region Input Events
でアウトラインの折り畳みを行うとそれなりにすっきりします。また、残りのメソッドは主に入力に関する情報をスタックに出し入れするものであることが分かります。
public interface IMixedRealityInputSystem : IMixedRealityEventSystem { // 入力が有効なときに発生するイベント event Action InputEnabled; // 入力が無効なときに発生するイベント event Action InputDisabled; // 手やモーションコントローラーなどの入力マネージャーによって検出されたインタラクション入力ソースのリスト HashSet<IMixedRealityInputSource> DetectedInputSources { get; } // 入力マネージャーによって現在検出されているIMixedRealityControllerのリスト // これは、リスト内のIMixedRealityInputSourcesのサブセットであるため、このプロパティはDetectedInputSourceに似ている HashSet<IMixedRealityController> DetectedControllers { get; } // ConfigurationProfileプロパティの型付き表現 MixedRealityInputSystemProfile InputSystemProfile { get; } // この入力システムによって実装されている現在のフォーカスプロバイダー IMixedRealityFocusProvider FocusProvider { get; } // この入力システムによって実装されている現在のレイキャストプロバイダー IMixedRealityRaycastProvider RaycastProvider { get; } // この入力システムによって実装されている現在の Gazeプロバイダー IMixedRealityGazeProvider GazeProvider { get; } // この入力システムによって実装されている現在の EyeGazeプロバイダー IMixedRealityEyeGazeProvider EyeGazeProvider { get; } // 入力が現在有効かどうかを示す bool IsInputEnabled { get; } // 無効な入力状態を入力システムにプッシュする // 入力が無効になっている間、イベントは送信されず、カーソルは待機中のアニメーションを表示する void PushInputDisable(); // 無効な入力状態を入力システムからポップする // 最後の無効状態が解除されると、スタック入力が再度有効になる void PopInputDisable(); // 入力をすぐに再度有効にする入力無効スタックをクリアする void ClearInputDisableStack(); // ゲームオブジェクトをモーダル入力スタックにプッシュする // ゲームオブジェクトの入力ハンドラは、フォーカスされたオブジェクトの前に入力イベントを優先する void PushModalInputHandler(GameObject inputHandler); // モーダル入力スタックから最後のゲームオブジェクトを削除する void PopModalInputHandler(); // スタックからすべてのモーダル入力ハンドラーをクリアする void ClearModalInputStack(); // ゲームオブジェクトをフォールバック入力スタックにプッシュする // モーダルオブジェクトまたはフォーカスオブジェクトがイベントを消費しない場合、ゲームオブジェクトの入力ハンドラーに入力イベントが与えられる void PushFallbackInputHandler(GameObject inputHandler); // フォールバック入力スタックから最後のゲームオブジェクトを削除する void PopFallbackInputHandler(); // スタックからすべてのフォールバック入力ハンドラーをクリアする void ClearFallbackInputStack(); #region Input Events ★★★ ここから下は(上の2個を除いて)イベントを発生させるメソッド ★★★ #region Input Source Events // 新しい一意の入力ソースIDを生成する // すべての入力ソースは、コンストラクターまたは初期化でこのメソッドを呼び出す必要がある uint GenerateNewSourceId(); // 新しい入力ソースをリクエストする IMixedRealityInputSource RequestNewGenericInputSource(string name, IMixedRealityPointer[] pointers = null, InputSourceType sourceType = InputSourceType.Other); // 入力ソースが検出されたというイベントを発生させる void RaiseSourceDetected(IMixedRealityInputSource source, IMixedRealityController controller = null); // 入力ソースが失われたというイベントを発生させる void RaiseSourceLost(IMixedRealityInputSource source, IMixedRealityController controller = null); // 入力ソースの追跡状態が変更されたというイベントを発生させる void RaiseSourceTrackingStateChanged(IMixedRealityInputSource source, IMixedRealityController controller, TrackingState state); // 入力ソースの位置が変更されたというイベントを発生させる void RaiseSourcePositionChanged(IMixedRealityInputSource source, IMixedRealityController controller, Vector2 position); // 入力ソースの位置が変更されたというイベントを発生させる void RaiseSourcePositionChanged(IMixedRealityInputSource source, IMixedRealityController controller, Vector3 position); // 入力ソースの回転が変更されたというイベントを発生させる void RaiseSourceRotationChanged(IMixedRealityInputSource source, IMixedRealityController controller, Quaternion rotation); // 入力ソースのポーズ(位置・回転)が変更されたというイベントを発生させる void RaiseSourcePoseChanged(IMixedRealityInputSource source, IMixedRealityController controller, MixedRealityPose position); #endregion Input Source Events #region Focus Events // フォーカスが変更された事前イベントを発生させる // このイベントは、フォーカス変更イベントの前にロジックを実行するのに役立つ void RaisePreFocusChanged(IMixedRealityPointer pointer, GameObject oldFocusedObject, GameObject newFocusedObject); // フォーカス変更イベントを発生させる void RaiseFocusChanged(IMixedRealityPointer pointer, GameObject oldFocusedObject, GameObject newFocusedObject); // フォーカス開始イベントを発生させる void RaiseFocusEnter(IMixedRealityPointer pointer, GameObject focusedObject); // フォーカス終了イベントを発生させる void RaiseFocusExit(IMixedRealityPointer pointer, GameObject unfocusedObject); #endregion Focus Events #region Pointers #region Pointer Down // ポインタダウンイベントを発生させる void RaisePointerDown(IMixedRealityPointer pointer, MixedRealityInputAction inputAction, Handedness handedness = Handedness.None, IMixedRealityInputSource inputSource = null); #endregion Pointer Down #region Pointer Dragged // ポインタのドラッグイベントを発生させる void RaisePointerDragged(IMixedRealityPointer pointer, MixedRealityInputAction inputAction, Handedness handedness = Handedness.None, IMixedRealityInputSource inputSource = null); #endregion Pointer Dragged #region Pointer Click // ポインタクリックイベントを発生させる void RaisePointerClicked(IMixedRealityPointer pointer, MixedRealityInputAction inputAction, int count, Handedness handedness = Handedness.None, IMixedRealityInputSource inputSource = null); #endregion Pointer Click #region Pointer Up // ポインタアップイベントを発生させる void RaisePointerUp(IMixedRealityPointer pointer, MixedRealityInputAction inputAction, Handedness handedness = Handedness.None, IMixedRealityInputSource inputSource = null); #endregion Pointer Up #endregion Pointers #region Generic Input Events #region Input Down // 入力ダウンイベントを発生させる void RaiseOnInputDown(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction); #endregion Input Down #region Input Up // 入力アップイベントを発生させる void RaiseOnInputUp(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction); #endregion Input Up #region Float Input Changed // フロート入力の変更を発生させる void RaiseFloatInputChanged(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction, float inputValue); #endregion Float Input Changed #region Input Position Changed // 2自由度の入力イベントを発生させる void RaisePositionInputChanged(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction, Vector2 position); // 3自由度の入力イベントを発生させる void RaisePositionInputChanged(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction, Vector3 position); #endregion Input Position Changed #region Input Rotation Changed // 3自由度の入力イベントを発生させる void RaiseRotationInputChanged(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction, Quaternion rotation); #endregion Input Rotation Changed #region Input Pose Changed // 6自由度の入力イベントを発生させる void RaisePoseInputChanged(IMixedRealityInputSource source, Handedness handedness, MixedRealityInputAction inputAction, MixedRealityPose inputData); #endregion Input Pose Changed #endregion Generic Input Events #region Generic Gesture Events // ジェスチャー開始イベントを発生させる void RaiseGestureStarted(IMixedRealityController controller, MixedRealityInputAction action); // ジェスチャー更新イベントを発生させる void RaiseGestureUpdated(IMixedRealityController controller, MixedRealityInputAction action); // ジェスチャー更新イベントを発生させる void RaiseGestureUpdated(IMixedRealityController controller, MixedRealityInputAction action, Vector2 inputData); // ジェスチャー更新イベントを発生させる void RaiseGestureUpdated(IMixedRealityController controller, MixedRealityInputAction action, Vector3 inputData); // ジェスチャー更新イベントを発生させる void RaiseGestureUpdated(IMixedRealityController controller, MixedRealityInputAction action, Quaternion inputData); // ジェスチャー更新イベントを発生させる void RaiseGestureUpdated(IMixedRealityController controller, MixedRealityInputAction action, MixedRealityPose inputData); // ジェスチャー完了イベントを発生させる void RaiseGestureCompleted(IMixedRealityController controller, MixedRealityInputAction action); // ジェスチャー完了イベントを発生させる void RaiseGestureCompleted(IMixedRealityController controller, MixedRealityInputAction action, Vector2 inputData); // ジェスチャー完了イベントを発生させる void RaiseGestureCompleted(IMixedRealityController controller, MixedRealityInputAction action, Vector3 inputData); // ジェスチャー完了イベントを発生させる void RaiseGestureCompleted(IMixedRealityController controller, MixedRealityInputAction action, Quaternion inputData); // ジェスチャー完了イベントを発生させる void RaiseGestureCompleted(IMixedRealityController controller, MixedRealityInputAction action, MixedRealityPose inputData); // ジェスチャー完了イベントを発生させる void RaiseGestureCanceled(IMixedRealityController controller, MixedRealityInputAction action); #endregion #region Speech Keyword Events // 音声コマンドの認識イベントを発生させる void RaiseSpeechCommandRecognized(IMixedRealityInputSource source, RecognitionConfidenceLevel confidence, TimeSpan phraseDuration, DateTime phraseStartTime, SpeechCommands command); #endregion Speech Keyword Events #region Dictation Events // ディクテーション仮説イベントを発生させる void RaiseDictationHypothesis(IMixedRealityInputSource source, string dictationHypothesis, AudioClip dictationAudioClip = null); // ディクテーション結果イベントを発生させる void RaiseDictationResult(IMixedRealityInputSource source, string dictationResult, AudioClip dictationAudioClip = null); // ディクテーション完了イベントを発生させる void RaiseDictationComplete(IMixedRealityInputSource source, string dictationResult, AudioClip dictationAudioClip); // ディクテーションエラーイベントを発生させる void RaiseDictationError(IMixedRealityInputSource source, string dictationResult, AudioClip dictationAudioClip = null); #endregion Dictation Events #region Hand Events // articulated hand の関節情報が更新されたことをシステムに通知する void RaiseHandJointsUpdated(IMixedRealityInputSource source, Handedness handedness, IDictionary<TrackedHandJoint, MixedRealityPose> jointPoses); // articulated hand のメッシュが更新されたことをシステムに通知する void RaiseHandMeshUpdated(IMixedRealityInputSource source, Handedness handedness, HandMeshInfo handMeshInfo); // タッチ開始イベントを発生させる void RaiseOnTouchStarted(IMixedRealityInputSource source, IMixedRealityController controller, Handedness handedness, Vector3 touchPoint); // タッチ更新イベントを発生させる void RaiseOnTouchUpdated(IMixedRealityInputSource source, IMixedRealityController controller, Handedness handedness, Vector3 touchPoint); // タッチ完了イベントを発生させる void RaiseOnTouchCompleted(IMixedRealityInputSource source, IMixedRealityController controller, Handedness handedness, Vector3 touchPoint); #endregion Hand Events #endregion Input Events }
データプロバイダーを取得するためのインタフェース。
// システムが管理されたデータプロバイダーへのアクセスを提供できるようにする public interface IMixedRealityDataProviderAccess { // 登録されたデータプロバイダーのコレクションを取得する IReadOnlyList<IMixedRealityDataProvider> GetDataProviders(); // 指定されたタイプの登録されたデータプロバイダーのコレクションを取得する IReadOnlyList<T> GetDataProviders<T>() where T : IMixedRealityDataProvider; // 指定した名前で登録されているデータプロバイダーを取得する // 指定された名前で複数のデータプロバイダーが登録されている場合、最初のプロバイダーが返される IMixedRealityDataProvider GetDataProvider(string name); // 指定された名前(オプション)で登録され、指定されたタイプに一致するデータプロバイダーを取得する // 指定された名前で複数のデータプロバイダーが登録されている場合、最初のプロバイダーが返される T GetDataProvider<T>(string name = null) where T : IMixedRealityDataProvider; }
ここで出てくる IMixedRealityDataProvider の中身は以下の通り空です。
すべてのデータプロバイダーが IMixedRealityDataProvider を継承(というか中身がないけど実装)しなければいけない決め事と考えればよいでしょう。
// すべての Mixed Reality データプロバイダーに必要なインターフェイス // データプロバイダーは、必要な情報(例:入力コントローラーの状態)を備えたサービスを提供するコンポーネント public interface IMixedRealityDataProvider : IMixedRealityService { // Reserved for future use. }
IMixedRealityDataProvider の管理とアクセスのために定義された機能を持つ MRTK システムのコアとなる抽象クラス。
public abstract class BaseDataProviderAccessCoreSystem : BaseCoreSystem, IMixedRealityDataProviderAccess { // データプロバイダーのリスト private readonly List<IMixedRealityDataProvider> dataProviders = new List<IMixedRealityDataProvider>(); // 親のResetを呼んだあとに、具体的処理は各データプロバイダーに委譲 public override void Reset() { base.Reset(); foreach(var provider in dataProviders) { provider.Reset(); } } // 以下も上に同じ public override void Enable() { } public override void Update() { } public override void LateUpdate() { } // コンストラクタ protected BaseDataProviderAccessCoreSystem(BaseMixedRealityProfile profile = null) : base(profile) { } // dataProviders リストからのデータプロバイダーを取得する #region IMixedRealityDataProviderAccess Implementation public virtual IReadOnlyList<IMixedRealityDataProvider> GetDataProviders() { } public virtual IReadOnlyList<T> GetDataProviders<T>() where T : IMixedRealityDataProvider { } public virtual IMixedRealityDataProvider GetDataProvider(string name) { } public virtual T GetDataProvider<T>(string name = null) where T : IMixedRealityDataProvider { } #endregion IMixedRealityDataProviderAccess Implementation // 指定されたタイプのデータプロバイダーを登録する protected bool RegisterDataProvider<T>( Type concreteType, SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1), params object[] args) where T : IMixedRealityDataProvider { return RegisterDataProviderInternal<T>( true, // Retry with an added IMixedRealityService parameter concreteType, supportedPlatforms, args); } // 指定された具象型のインスタンスを作成し、プロバイダーを登録する内部メソッド private bool RegisterDataProviderInternal<T>( bool retryWithRegistrar, Type concreteType, SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1), params object[] args) where T : IMixedRealityDataProvider { // 略... T dataProviderInstance; try { // ★データプロバイダーインスタンスの生成 dataProviderInstance = (T)Activator.CreateInstance(concreteType, args); } // 略... return RegisterDataProvider(dataProviderInstance); } // 指定されたタイプのサービスを登録する protected bool RegisterDataProvider<T>(T dataProviderInstance) where T : IMixedRealityDataProvider { // 略... dataProviders.Add(dataProviderInstance); dataProviderInstance.Initialize(); return true; } // 指定したタイプのデータプロバイダーの登録を解除する // name 引数が指定されていない場合、最初のインスタンスが登録解除される protected bool UnregisterDataProvider<T>(string name = null) where T : IMixedRealityDataProvider { T dataProviderInstance = GetDataProvider<T>(name); // 略... return UnregisterDataProvider(dataProviderInstance); } /// データプロバイダーの登録を解除する protected bool UnregisterDataProvider<T>(T dataProviderInstance) where T : IMixedRealityDataProvider { // 略... if (dataProviders.Contains(dataProviderInstance)) { dataProviders.Remove(dataProviderInstance); dataProviderInstance.Disable(); dataProviderInstance.Destroy(); return true; } return false; } }
簡単にまとめると内容としては、
クラスになっています。
ボリュームも多いのでポイントを絞って見ていきます。
まず、Proiory が 1 であり、他のすべてのマネージャーの前に処理されるためこの入力システムが重要なものであることがわかります。
public override uint Priority => 1;
次に初期化処理です。細かい部分を省くと以下の通りです。
// 初期化処理 public override void Initialize() { // プロファイルの取得 MixedRealityInputSystemProfile profile = ConfigurationProfile as MixedRealityInputSystemProfile; // インプットモジュールのチェック BaseInputModule[] inputModules = UnityEngine.Object.FindObjectsOfType<BaseInputModule>(); // InputSystemProfileのチェック // InputActionRulesProfileのチェック // PointerProfileのチェック // イベントデータのインスタンス生成 sourceStateEventData = new SourceStateEventData(EventSystem.current); ... // データプロバイダの生成 CreateDataProviders(); }
データプロバイダの生成(CreateDataProviders)では、
しています。
次にポイントとなるのは、イベントハンドリングを行う Handle〇〇メソッドの部分になると思います。以下4つあります。
Handle〇〇メソッドが主に行っているのはイベントのディスパッチ処理で、イベントディスパッチメソッドは以下3つあります。
グローバルリスナーとはオブジェクトにフォーカスしていない状態でイベントを実行するためのものになります。(例えば、何もフォーカスしていない状態でもエアタップしたらCubeを表示したい、といった場合などに利用する)
Handle〇〇メソッドは(大量にある)Raise△△メソッドから呼ばれています。
イベント処理に関しては、すべて見ても重複する内容が多いので、例として ポインターをクリックした際に呼ばれる RaisePointerClicked メソッドについて確認をしてみます。
この RaisePointerClicked 自体は、ソリューションを検索をするとわかりますが何かしらのポインターから呼ばれるもので、 必要な情報が引数で渡ってきます。
// まず public メソッドになっているここが外部から呼ばれる public void RaisePointerClicked(IMixedRealityPointer pointer, MixedRealityInputAction inputAction, int count, Handedness handedness = Handedness.None, IMixedRealityInputSource inputSource = null) { // インプットイベントデータを生成する pointerEventData.Initialize(pointer, inputAction, handedness, inputSource, count); HandleClick(); } private void HandleClick() { // HandlePointerEventにイベントデータとハンドラーを渡す HandlePointerEvent(pointerEventData, OnInputClickedEventHandler); } // HandlePointerEvent の引数にある OnInputClickedEventHandler は以下のように定義された delegate private static readonly ExecuteEvents.EventFunction<IMixedRealityPointerHandler> OnInputClickedEventHandler = delegate (IMixedRealityPointerHandler handler, BaseEventData eventData) { // OnInputClickedEventHandler が呼ばれたら以下が実行される var casted = ExecuteEvents.ValidateEventData<MixedRealityPointerEventData>(eventData); handler.OnPointerClicked(casted); // ←★イベントが発生すると最終的にこれが呼ばれる }; // ポインタイベントの処理 private void HandlePointerEvent<T>(BaseEventData eventData, ExecuteEvents.EventFunction<T> eventHandler) where T : IMixedRealityPointerHandler { var baseInputEventData = ExecuteEvents.ValidateEventData<BaseInputEventData>(eventData); // グローバルリスナーにイベントをディスパッチする DispatchEventToGlobalListeners(baseInputEventData, eventHandler); if (baseInputEventData.used) { // 使用済みとマークされている場合、イベントがそれ以上進行しないようにする return; } // ポインターにフォーカスされたオブジェクトにイベントをディスパッチする DispatchEventToObjectFocusedByPointer(pointerEventData.Pointer, baseInputEventData, false, eventHandler); if (!baseInputEventData.used) { // フォールバック処理を行う DispatchEventToFallbackHandlers(baseInputEventData, eventHandler); } }
流れを追うと
という形になります。
上の流れの中から、最終的には OnInputClickedEventHandler の中の
handler.OnPointerClicked(casted);
という部分が呼ばれることになりますが、これにより開発者が独自に定義した部分が呼ばれ、またその際にイベントデータがパラメータとして渡ってきます。
イベントデータに関しては以下のような継承関係になっています。
詳細の説明については省略しますが、ポインターのクリックに関するイベントは以下で定義されているものになります。
private MixedRealityPointerEventData pointerEventData;
この pointerEventData は RaisePointerClicked メソッドが呼ばれたときに以下の部分で生成されています。
// インプットイベントデータを生成する
pointerEventData.Initialize(pointer, inputAction, handedness, inputSource, count);
このデータがパラメータとして渡って来るので必要があれば利用することができます。 どのようなデータが渡ってきているのかは以下のように実際に見てみるのが早いでしょう。
これらのイベント処理の確認として簡単なサンプルを以下に示します。
例えば以下のようなクラスを実装して Hierarchy の GameObject にアタッチすると、オブジェクトにフォーカスした状態でクリックすると OnPointerClicked メソッド内の処理が実行されます。
public class PointerSample : MonoBehaviour, IMixedRealityPointerHandler { public void OnPointerClicked(MixedRealityPointerEventData eventData) { // ★クリックしたときに呼ばれる処理 } public void OnPointerDown(MixedRealityPointerEventData eventData) { // 何かしらの実装 } public void OnPointerDragged(MixedRealityPointerEventData eventData) { // 何かしらの実装 } public void OnPointerUp(MixedRealityPointerEventData eventData) { // 何かしらの実装 } }
グローバルリスナーを利用する場合(オブジェクトにフォーカスしていなくてもクリック時に何かしらの処理を行いたい場合)には以下のような実装になります。
public class PointerSample : MonoBehaviour, IMixedRealityPointerHandler { private void OnEnable() { // グローバルリスナーに登録 CoreServices.InputSystem?.RegisterHandler<IMixedRealityPointerHandler>(this); } private void OnDisable() { // グローバルリスナーの登録を解除 CoreServices.InputSystem?.UnregisterHandler<IMixedRealityPointerHandler>(this); } public void OnPointerClicked(MixedRealityPointerEventData eventData) { // ★クリックしたときに呼ばれる処理(オブジェクトにフォーカスしていなくても実行される) } ... }
以上を簡単にまとめると 「クリックした、オブジェクトにフォーカスした、ジェスチャーを開始した」などのイベントがますどこかで発生し、MixedRealityInputSystem の対応する Raise△△メソッドが呼ばれ、最終的に開発者が実装した処理が実行される という流れになります。
その他の部分についてはモーダル処理を行う部分があります。 これについては、一般的なGUIのアプリケーションでもあるようにダイアログ表示中などに他のボタンを押したり操作できないようにするもので、同様の物と考えれば良いと思います。
ということで、MixedRealityInputSystem の実装について確認してみました。
ざっくりとまとめると MixedRealityInputSystem とは
ものであると言えるかと思います(入力を取り扱う門番的なイメージ)。
Inputに関しては、 プロファイルが階層構造になっており、さらにいくつかのプロファイルがあったり、データプロバイダーもいくつかの種類があるので今後そのあたりについても見ていきたいと思います。
]]>HoloLensで取得した温度情報をAzure IoT Hubに入れて、Stream Analytics経由でPower BIに出力できた。
— 中村 薫 (@kaorun55) 2020年8月9日
↓これをなぞってみた。https://t.co/nMLapJfauC pic.twitter.com/LVzFJE1ELC
温度センサーはOmron 2JCIE-BU01。このデータをアドバタイズパケットでHoloLens 2で取得、HoloLens 2からAzure IoT Hubにデータを送信しています。Azure IoT HubからはStream Analytics経由でPower BIに入れています。
元のドキュメントはこちら。
ここではHoloLens 2にUSBで接続していますが、アドバタイズパケットで取得しているためセンサーの電源取得のみです。またアドバタイズパケットのため接続不要でデータを取り込んでいます。
]]>
確認したのは Unity 2018.4.23 ~ Unity 2020.1.0のリリースノートです。
HoloLensのキーワードが入っていなくても影響する改善はあるかもしれないのであくまで参考までに。
XR: Editor crash when using holographic emulator with hololens (1141385, 1163557)
XR: Fix issue with Depth Based LSR on HoloLens V2 that caused significant jitter. (1169760, 1169761)
Universal Windows Platform: Fixed TouchScreenKeyboard's SHIFT key duplicating last typed character on HoloLens. (1184623, 1191743)
XR: Added HoloLens 2 as a device name when running on HoloLens 2 devices. (1161756, 1188262)
XR: Fix hololens remoting connect failure once connect has failed at least 1 time. (1204419)
This has been backported and will not be mentioned in final notes.
XR: Fixed disconnecting after exiting play mode while remoting to Hololens. (1137090)
This has been backported and will not be mentioned in final notes.
XR: Add more details to error message when Hololens remoting fails to load the dll. (1161718)
XR: Fixed assert due to invalid camera pose on first frame of Hololens remoting connect. (1243433)
XR: Fixed Holographic Emulation Window remoting bug that caused Unity to remote to Hololens 1 devices when Hololens 2 was selected.
XR: Fixed Hololens 2 camera snapshots not containing Unity app content.
XR: Prevent Hololens app pause when switching focus to a 2D view within a running application.
なお、以下は調べようと思ったきっかけです。
]]>InputField は特に設定の必要なしに配置したものを押すだけでキーボード出てくるはずだよなーと思ったけど、出てこなくて結構時間がかかってしまった。結果としては、Unity 2018.4.23f1 だと出てこなくて Unity 2019.4.5f1 だと出てきた。対応するようになったのどのverからだろう? #HoloLens2
— 広務(Hiromu) (@hi_rom_) 2020年8月3日
[Tokyo HoloLens ミートアップ vol.21] ホロラボでのアプリ開発技術
Unity で HoloLens (UWP) アプリを作る際のパッケージ名をプロダクト名に変更するスクリプト - たるこすの日記
https://mplus-fonts.osdn.jp/about.html
https://github.com/webrtc-uwp/webrtc-uwp-sdk
https://github.com/microsoft/MixedReality-WebRTC
https://github.com/microsoft/MixedReality-WebRTC/releases/tag/v1.0.3
https://github.com/microsoft/MixedReality-WebRTC/releases
世界一わかりやすいClean Architecture - nuits.jp blog
Unity ライブラリを Git submodule で管理する - たるこすの日記
https://github.com/tarukosu/go-unity-cli
HoloLens 向け 2D ブラウザアプリ、HoloBrowser を公開しました - ブログ@HoloLabInc
https://github.com/HoloLabInc/XRLineRenderer/tree/hololab/for-hololens
https://github.com/HoloLabInc/XRLineRenderer/releases/tag/hololab-v1.0.0
https://github.com/microsoft/WindowsDevicePortalWrapper
https://github.com/HoloLabInc/HoloLensAppManager
Common Data Service とは何か? - Power Apps | Microsoft Docs
https://github.com/StefH/NETStandard.HttpListener
先日、Unity のビジュアルスクリプティングアセットである Bolt の無料化の発表がありました。Bolt を触るのは初めてですが、HoloLens 開発において使えるかどうか試してみました。
まず先に結論としては、簡単な動作確認程度ではありますが問題なく使えることが分かりました。
Bolt をインポートします。
Bolt をインポートすると、Unityのメニューに Tools -> Install Bolt という項目が追加されるので選択します。
以下の画面が出たので Api Compatibility Level を .NET Standard 2.0 にしたら動かないかもしれません(未確認)。ここでは素直に .NET 4.x で進めることにします。
Setup Wizard が表示されますがすべてデフォルト(およびお好みの設定)で進めます。
Assembly Options の項目については、MRTK の機能を Bolt で使う場合には必要になるものだと思いますが、こちらも後から設定ができるので変更なしで進めます。
キューブを Bolt により回転させるサンプルを作ります。
まずは Cube を配置します。
Cube に Flow Machine コンポーネントを追加します。
Flow Machine の New ボタンを押します。
エラーが表示されますが無視して続けます。
Flow Machine の Edit Graph ボタンを押します。
以下のような画面が表示されます。
右クリックをして Rotate で検索をして、Rotate(xAngle, yAngle, zAngle, relativeTo) を選択します。
Update と Rotate をマウスドラッグでつなぎます。また yAngle に 1 を設定します。
以上で Play ボタンを押すとキューブが回転していることが確認できます。
UnityEditor で動作することが確認できるので、実機にデプロイしてみます。
動きません。。
以下は、PC で実行したものですが以下のようなエラーが出ました。
調べたところ、AOT Pre-Build というものが必要なようです。メニューにあるので実行します。
再度ビルドしなおして、デプロイしてみます。
動きました!
— 広務(Hiromu) (@hi_rom_) 2020年7月24日
Bolt を利用して HoloLens アプリを開発できることがわかりました。
まだあまり詳しく触ってはいませんが、MRTK の機能を Bolt から使うには Setup Wizard で表示された Assembly Options での設定が必要になると思います。MRTK は dll が機能ごとに分割されているのですべて登録するのは大変かもしれませんが、今後そのあたりも見てみたいと思います。
Unity で長期的なプロジェクトやライブラリを作成する際、 ソースコードが公開されている Unity ライブラリや社内ライブラリを使う場合に、 Git submodule でコードを取り入れるようにしています。
自分の Git リポジトリにライブラリのコードを入れることに比べて、以下のようなメリットがあります。
この記事では、自分がどのように Git submodule を使ってプロジェクトを構成しているかを紹介します。
リポジトリのルートフォルダの中の _external
フォルダにライブラリのコードが入ります。
このままでは自分の Unity プロジェクトから使えないため、
Assets
フォルダ内に必要なライブラリのフォルダへのシンボリックリンクを作成します。
シンボリックリンクをはるためのバッチファイルやツールをルートフォルダの中の _tools
フォルダに格納します。
シンボリックリンクは go-symlink-creator
という自作のツールを使って作成しています。
このツールを使えば、どこからどこにリンクをはるのかという定義を yaml ファイルで行えます。
プロジェクトをセットアップする際の手順を紹介します。
まずは、リポジトリのルートフォルダに _external
, _tools
フォルダを作成します。
_external
フォルダへライブラリを追加_external
フォルダには、Git submodule でライブラリをクローンします。
> git submodule add <repository>
利用するブランチやタグを変更する場合は、クローンしたフォルダ内で変更します。
_tools
フォルダへシンボリックリンク作成ツールを追加Releases · HoloLabInc/go-symlink-creator · GitHub
上記ページから go-symlink-creator.exe
をダウンロードし、_tools
フォルダに保存します。
また、以下のような SymlinkSettings.yaml
ファイルを作成し、_tools
フォルダに保存します。
src はリンク先のファイル・フォルダの親フォルダ、dest はリンクを作成するフォルダ、target はリンクを作成するファイル・フォルダです。
symlinks: - src: \path\to\source\folder dest: \path\to\destination\folder target: - FolderA - FolderB include-meta-file: true # meta ファイルのリンクも作成する
最後に、クリックだけで実行できるようにバッチファイル (createSymlink.bat
) を作成します。
@echo off cd /d %~dp0 call go-symlink-creator SymlinkSettings.yaml pause
このバッチファイルを実行することで、シンボリックが作成されます。
シンボリックリンクのファイルは Git の管理対象から外します。
.gitignore ファイルを作成し、シンボリックリンクのファイルを指定してください。
以上でプロジェクトのセットアップは完了です。
上記のセットアップを行ったプロジェクトをクローンする場合は、 リポジトリをクローンした後にサブモジュールのクローンを実行します。
> git clone <repository> > cd <repository> > git submodule init > git submodule update
その後、シンボリックリンクを作成するバッチファイルを実行します
> _tools\createSymlink.bat
HoloLens アプリ開発で利用される MRTK を、Git submodule で利用する手順を紹介します。
上記で紹介した手順の具体例となります。
まずは、リポジトリのルートフォルダに _external
, _tools
フォルダを作成します。
_external
フォルダへ MRTK を追加_external
フォルダで以下を実行します。
> git submodule add git@github.com:microsoft/MixedRealityToolkit-Unity.git
利用するバージョンを指定します。
例えば、MRTK v2.4.0 を使う場合は以下のようにします。
> cd MixedRealityToolkit-Unity > git checkout v2.4.0
_tools
フォルダへシンボリックリンク作成ツールを追加go-symlink-creator.exe
と createSymlink.bat
については同じ内容のため省略します。
SymlinkSettings.yaml
は以下のようになります。
symlinks: - create-dest-folder: true # dest フォルダ (Assets\MRTK) が存在しなければ作成する include-meta-file: true src: ..\_external\MixedRealityToolkit-Unity\Assets\MRTK dest: ..\Assets\MRTK target: - Core - Providers - SDK - Services - Tools - Extensions # Examples を利用しない場合は削除する - Examples
Assets フォルダに .gitignore
ファイルを作成し、以下の内容を記入します。
/MRTK /MRTK.meta
以上、自分が普段行っている Unity ライブラリを Git submodule で管理する手順の紹介でした。
]]>以前の記事でポインターが FocusProvider と関係していることが分かったので、今回は FocusProvider について見ていくことにしました(確認したバージョンはMRTK v2.4.0)。
かなり長くなってしまったので最初に FocusProvider とはどのようなものかを簡単にまとめると
入力ソースを検出したときにソースに紐づいたポインターを FocusProvider 内に登録する
各ポインターがフォーカスしている(レイがヒットしている)オブジェクトの詳細を取得する
フォーカスしているオブジェクトに対して必要に応じてイベントを発生させる(OnFocusEnter / OnFocusExit など)
というものです。
詳細について特に興味がなければここまでで大丈夫だと思います。
以降はほとんど調べたことのメモという感じなので興味のある方だけご覧ください。
では、まず継承関係を見てみます。
入り組んだ印象がありますが、順を追って見ていきます。
リソースを解放するためのインタフェース。Dispoaseメソッドを持つのみ。
すべての Mixed Reality Services の汎用インターフェース。
以下は、コードからコメントを削除したもの。割とシンプルです。が、内容としてはオブジェクトのライフサイクルにおける処理を担っているので重要なものと言えます。Monobehaviour を継承せずにライフサイクルを管理するためのインタフェースと考えれば分かりやすいと思います。
public interface IMixedRealityService : IDisposable { string Name { get; } uint Priority { get; } BaseMixedRealityProfile ConfigurationProfile { get; } void Initialize(); void Reset(); void Enable(); void Update(); void LateUpdate(); void Disable(); void Destroy(); }
Mixed Reality Toolkit と互換性のあるイベントシステムを実装するために使用されるインターフェイス。
Obsolete な物を除いたコードは以下。3つのメソッドを持つのみですが、ちょっと分かりにくいと感じるかもしれません。ただ具体的な処理はこのインタフェースを実装したクラス次第なので、こういったメソッドがあるんだなとだけ理解しておけば良いと思います。
public interface IMixedRealityEventSystem : IMixedRealityService { // すべてのイベントを処理して目的の受信者に転送するための主な機能 void HandleEvent<T>(BaseEventData eventData, ExecuteEvents.EventFunction<T> eventHandler) where T : IEventSystemHandler; // 引数に渡されたハンドラを、T インターフェースを介して処理されるすべてのイベントのグローバルリスナーとして登録する void RegisterHandler<T>(IEventSystemHandler handler) where T : IEventSystemHandler; // 登録されたハンドラーを解除する void UnregisterHandler<T>(IEventSystemHandler handler) where T : IEventSystemHandler; }
なお、3つのメソッドすべてにおいて、型パラメータの T として IEventSystemHandler(もしくはその派生型)であることが指定されています。そのためこれを理解するには IEventSystemHandler については理解しておく必要があります。
IMixedRealityService を実装し、すべてのサービスのデフォルトプロパティを提供する。
抽象クラスであまり中身はありません。気になるところは以下ぐらいです。
このクラスを継承することで、他のシステムの機能にイベント機能を持たせることができる基本イベントシステム。
継承元にある IMixedRealityService の実装は Destroy メソッド以外は含まれていないので、主な内容としては IMixedRealityEventSystem のデフォルト実装をしたものであるということでしょうか。 IMixedRealityEventSystem で Obsolete とされている EventListeners / Register メソッド / Unregister メソッドに関連する部分については省略しつつ、実装を見てみます。
// (このイベントシステムに)登録された型によってグループ化されたすべてのイベントハンドラーのディクショナリ public Dictionary<Type, List<EventHandlerEntry>> EventHandlersByType // RegisterHandler API を介して登録されたすべてのハンドラーにイベントを送信する public virtual void HandleEvent<T>(BaseEventData eventData, ExecuteEvents.EventFunction<T> eventHandler) where T : IEventSystemHandler { (略...) List<EventHandlerEntry> handlers; if (EventHandlersByType.TryGetValue(typeof(T), out handlers)) { for (int i = handlers.Count - 1; i >= 0; i--) { var handlerEntry = handlers[i]; (略...) // ★このメソッド内で一番重要な部分 // EventHandlersByTypeから一致する型のインタフェースのハンドラーを取り出しイベントを実行する // つまり、 // T 型のインタフェースを継承した handler インスタンスの eventHandler メソッドに // eventData パラメータを渡して実行する eventHandler.Invoke((T)handlerEntry.handler, eventData); } } (略...) }
今の段階では、具体的にどのようなデータやハンドラーが渡ってくるのかは分かりませんが、何かしらのインタフェース(T)を実装したインスタンスのメソッドを実行する部分になります。 (なお、呼び出し元は MixedRealityInputSystem クラスの DispatchEventToGlobalListeners メソッドです)
このイベントのディスパッチ中に EventHandlersByType ディクショナリへの追加・削除を行うことは安全ではないため、eventExecutionDepth という変数と postponedActions というリストを用いて制御するような処理も入っています。
// 引数に渡されたハンドラー(IEventSystemHandlerを継承したインスタンス)を、T インターフェースを介して処理されるすべてのイベントのグローバルリスナーとして登録する public virtual void RegisterHandler<T>(IEventSystemHandler handler) where T : IEventSystemHandler { (略...) // IEventSystemHandler を除いた handler の親インターフェースも登録する TraverseEventSystemHandlerHierarchy<T>(handler, RegisterHandler); } // 登録されたハンドラーを解除する public virtual void UnregisterHandler<T>(IEventSystemHandler handler) where T : IEventSystemHandler { (略...) // IEventSystemHandler を除いた handler の親インターフェースも登録を解除する TraverseEventSystemHandlerHierarchy<T>(handler, UnregisterHandler); }
EventHandlersByType ディクショナリおよびその内部のリストに型とハンドラーを登録・解除しています。 グローバルリスナー(オブジェクトにフォーカスが当たっていなくても入力を受け付けるもの)として登録・解除するところがポイントかと思います。
上記以外の部分については private メソッドなので、上記処理を行うための内部処理になります。
コンストラクタで プロファイルの設定と Priorityを 5 に設定している(コアシステムのデフォルトの優先度は他のサービスよりも高い)だけで、他はObsolete。
Unity で準備されたインタフェース、中身は空。
すべての入力ハンドラーの基本インターフェース。
これにより、ExecuteEvents.ExecuteHierarchy<IIMixedRealityBaseInputHandler> を使用して、すべての入力ハンドリングインターフェイスにイベントを送信できる。
コードは以下の通りで中身は空。
public interface IMixedRealityBaseInputHandler : IEventSystemHandler {}
音声認識に反応するために実装するインターフェース。
メソッドを 1 つだけ持つ。
public interface IMixedRealitySpeechHandler : IMixedRealityBaseInputHandler { void OnSpeechKeywordRecognized(SpeechEventData eventData); }
入力ソースが検出または失われたときなど、ソースの状態変化に対応するために実装するインターフェイス。
メソッドは以下の 2 つを持つ。
public interface IMixedRealitySourceStateHandler : IEventSystemHandler { // ソースが検出されると発生する void OnSourceDetected(SourceStateEventData eventData); // ソースが失われたときに発生する void OnSourceLost(SourceStateEventData eventData); }
ポインターのフォーカスを処理するフォーカスプロバイダーを実装するためのインタフェース。
以下は、日本語コメントを付けたもの。どのようなものがあるかだけ目を通しておき、あとは、継承先の FocusProvider を見ていくのが良いと思います。
public interface IMixedRealityFocusProvider : IMixedRealityService, IMixedRealitySourceStateHandler, IMixedRealitySpeechHandler { // オーバーライド範囲がない限り、すべてのポインターがGameObjectと衝突できる最大距離 float GlobalPointingExtent { get; } // レイキャストの対象となるフォーカスポインターのレイヤーマスク LayerMask[] FocusLayerMasks { get; } // EventSystem がレイキャストに使用するカメラ Camera UIRaycastCamera { get; } // 現在のプライマリポインタ。 使用中のプライマリポインターセレクターによって決定される(MixedRealityPointerProfile.PrimaryPointerSelectorを参照) IMixedRealityPointer PrimaryPointer { get; } // ポインティングソースの現在フォーカスされているオブジェクトを取得する // ポインティングソースが登録されていない場合、GazeのFocused GameObjectが返される GameObject GetFocusedObject(IMixedRealityPointer pointingSource); // ポインティングソースの現在フォーカスされているオブジェクトの詳細情報を取得する bool TryGetFocusDetails(IMixedRealityPointer pointer, out FocusDetails focusDetails); // 指定されたポインターのFocusDetailsを設定し、現在設定されているフォーカスポイントをオーバーライドする // これは、フォーカスがロックされている場合でも、特定のポインターのFocusDetailsを変更するために使用できる bool TryOverrideFocusDetails(IMixedRealityPointer pointer, FocusDetails focusDetails); // 新しい一意のポインターIDを生成する uint GenerateNewPointerId(); // ポインタがフォーカスプロバイダーに登録されているかどうかを確認する bool IsPointerRegistered(IMixedRealityPointer pointer); // ポインタをフォーカスプロバイダーに登録する bool RegisterPointer(IMixedRealityPointer pointer); // フォーカスプロバイダーに登録されているポインタの登録を解除する bool UnregisterPointer(IMixedRealityPointer pointer); // 指定されたタイプのすべての登録済みポインターへのアクセスを提供する IEnumerable<T> GetPointers<T>() where T : class, IMixedRealityPointer; // プライマリポインターの変更をサブスクライブする void SubscribeToPrimaryPointerChanged(PrimaryPointerChangedHandler handler, bool invokeHandlerWithCurrentPointer); // プライマリポインタの変更のサブスクライブを解除する void UnsubscribeFromPrimaryPointerChanged(PrimaryPointerChangedHandler handler); }
入力システムのポインターの動作や、その他の設定を取得・設定するためのインターフェースを提供する。
動作は、ポインターごとではなく、ポインタータイプと入力タイプに基づいて記述される。
これは、表示される新しいポインターが一貫した動作を維持するようにするため。
public interface IPointerPreferences { // 指定されたポインタの PointerBehavior を取得する PointerBehavior GetPointerBehavior(IMixedRealityPointer pointer); // 指定されたポインタータイプ、利き手、および入力タイプの PointerBehavior を取得する PointerBehavior GetPointerBehavior<T>( Handedness handedness, InputSourceType sourceType) where T : class, IMixedRealityPointer; // 指定されたポインタータイプ、利き手、および入力タイプの PointerBehavior を設定する void SetPointerBehavior<T>(Handedness handedness, InputSourceType inputType, PointerBehavior pointerBehavior) where T : class, IMixedRealityPointer; // 視線ポインターのポインター動作 // 内部クラスであるため、内部視線ポインターは実際にはここから参照できないため、視線ポインターを一意にする PointerBehavior GazePointerBehavior { get; set; } }
なお、PointerBehavior とは以下のようなポインターの動作を示す enum です。
public enum PointerBehavior { // ポインターのアクティブ状態はMRTK入力システムによって管理される // ニアポインター(グラブ、ポーク)の場合、常に有効になる // ニアポインターでない場合、同じ手のニアポインターがアクティブな場合は無効になる // これは、手がグラブ可能なものの近くにあるときにレイをオフにすることを可能にするもの Default = 0, // 他のどのポインターがアクティブであるかに関係なく、ポインターは常にオン AlwaysOn, // 他のどのポインターがアクティブであるかに関係なく、ポインターは常にオフ AlwaysOff };
フォーカスプロバイダーは、入力ソースごとにフォーカスされたオブジェクトを処理する。
さてついに本題の FocusProvider です。
言うまでもなく、上で書いてきたすべてのインタフェースの実装をしたもので、確認のために継承関係の図を再掲します。
また、FocusProvider は内部に PointerHitResult / PointerData / PointerPreferences クラスを持っています。PointerData クラスについては継承元があるので、継承関係を掲載します。
中間ヒット結果を格納するためのヘルパークラス。ポインターの可能なすべてのヒットが処理されたら、PointerDataに適用する必要がある。
インスタンスの等価性を判断するためのインタフェース。
ポインタの結果を定義するインターフェイス。
public interface IPointerResult { // ポインターレイステップの開始点。 Vector3 StartPoint { get; } // 現在フォーカスされているゲームオブジェクトの詳細。 FocusDetails Details { get; } // 現在のポインターのターゲットGameObject GameObject CurrentPointerTarget { get; } // 前のポインターターゲット。 GameObject PreviousPointerTarget { get; } // 最後のレイキャストヒットを生成したステップのインデックス。レイキャストヒットがない場合は0。 int RayStepIndex { get; } }
ポインターに関する情報を持つ。
コンストラクタでポインターを渡され生成される。
ヒットしているオブジェクトの詳細情報などのポインターに関連した付随情報を持つ。
ポインターの動作を取得・設定するためのクラス(入力ソースのタイプ、ポインターのタイプ、手に応じたポインタービヘイビアーを持つ)
以降は、FocusProvider の実装にコメントを日本語で付けたものです。重要そうなメソッドなどは中身を簡略化しつつコメントを入れました。
/// フォーカスプロバイダーは、入力ソースごとにフォーカスされたオブジェクトを処理します。 /// 必要に応じてGaze Pointerのみを取得するための便利なプロパティがあります。 public class FocusProvider : BaseCoreSystem, IMixedRealityFocusProvider, IPointerPreferences { // コンストラクタ public FocusProvider(MixedRealityInputSystemProfile profile) : base(profile) { ...} // このディクショナリにポインター情報を格納する private readonly Dictionary<uint, PointerData> pointers = new Dictionary<uint, PointerData>(); private readonly HashSet<GameObject> pendingOverallFocusEnterSet = new HashSet<GameObject>(); private readonly Dictionary<GameObject, int> pendingOverallFocusExitSet = new Dictionary<GameObject, int>(); private readonly List<PointerData> pendingPointerSpecificFocusChange = new List<PointerData>(); private readonly Dictionary<uint, IMixedRealityPointerMediator> pointerMediators = new Dictionary<uint, IMixedRealityPointerMediator>(); private readonly PointerHitResult hitResult3d = new PointerHitResult(); private readonly PointerHitResult hitResultUi = new PointerHitResult(); // シーンクエリタイプが SphereOverlap の場合に対象とするコライダーの最大数 private readonly int maxQuerySceneResults = 128; // 複合コライダーの場合、個々のコライダーはフォーカスを受け取るかどうか private bool focusIndividualCompoundCollider = false; public IReadOnlyDictionary<uint, IMixedRealityPointerMediator> PointerMediators => pointerMediators; // アクティブな IMixedRealityNearPointers の数 public int NumNearPointersActive { get; private set; } // ゲイズカーソルを除く、アクティブなファーインタラクション(モーションコントローラーレイ、ハンドレイなど)をサポートするポインターの数 public int NumFarPointersActive { get; private set; } // プライマリーポインターを取得・設定する(変更時は変更イベント発火) public IMixedRealityPointer PrimaryPointer { ... } private IMixedRealityPointer primaryPointer; #region IMixedRealityService Properties // 名前 public override string Name { get; protected set; } = "Focus Provider"; // プライオリティー(Default値 10, コアシステム 5 なので重要であることがわかる) public override uint Priority => 2; // ポインターの届く距離(プロファイルに設定されている値を取得する、デフォルト値は10) float IMixedRealityFocusProvider.GlobalPointingExtent { ... } // フォーカスするレイヤーマスク(PointerProfileから取得する) private LayerMask[] focusLayerMasks = null; public LayerMask[] FocusLayerMasks { ... } // uiRaycastCamera用のレンダリングテクスチャ(デバイスディスプレイの解像度に関係なくドラッグの閾値が同じように扱われるようするために利用) private RenderTexture uiRaycastCameraTargetTexture = null; // UIコンポーネントへのヒット判定するためのUIレイキャストカメラ private Camera uiRaycastCamera = null; public Camera UIRaycastCamera => uiRaycastCamera; #endregion IMixedRealityService Properties // このサービスを開始するために MixedRealityToolkit が正しくセットアップされているかどうかを確認する private bool IsSetupValid { ... } // GazeProvider は特殊なため、登録されたポインタでなくても追跡するようにする // StabilizationPlaneModifier およびユーザーがどこを見ているかを気にする可能性のある他のコンポーネントのために、 // フォーカスにゲイズが使用されていない場合でも、ゲイズのレイキャストを行う必要がある private PointerData gazeProviderPointingData; private PointerHitResult gazeHitResult; // 新しいレイキャスト位置のキャッシュ(UIレイキャスト結果の更新にのみ使用される) private Vector3 newUiRaycastPosition = Vector3.zero; // 中間ヒット結果を格納するためのヘルパークラス // ポインターの可能なすべてのヒットが処理されたら、PointerDataに適用する必要がある private class PointerHitResult { public MixedRealityRaycastHit raycastHit; public RaycastResult graphicsRaycastResult; public GameObject hitObject; public Vector3 hitPointOnObject = Vector3.zero; public Vector3 hitNormalOnObject = Vector3.zero; public RayStep ray; public int rayStepIndex = -1; public float rayDistance; // 略... } // ポインターに関する情報を持つクラス [Serializable] private class PointerData : IPointerResult, IEquatable<PointerData> { // ポインター(コンストラクタで設定される) public readonly IMixedRealityPointer Pointer; // フォーカスしているオブジェクトの詳細情報 public FocusDetails Details { ... } private FocusDetails focusDetails = new FocusDetails(); // 略... // ポインターのヒット情報を更新する // FocusProvider の Update > UpdatePointers > UpdatePointer メソッドから呼ばれる public void UpdateHit(PointerHitResult hitResult) { // hitResult をもとに focusDetails を更新する } // フォーカスがロックされているときにフォーカス情報を更新する // (ロックされている場合は、UpdateHitではなくこっちが呼ばれる) // オブジェクトが動いている場合、ヒットポイントが新しいワールドトランスフォームに更新されます。 public void UpdateFocusLockedHit() { // } // 略... } // ゲイズポインターの有効・無効を切り替えるステートマシン(手が表示されたらゲイズカーソルを非表示にしたりなど) private readonly GazePointerVisibilityStateMachine gazePointerStateMachine = new GazePointerVisibilityStateMachine(); // プライマリポインターを選択するために使用されるインターフェイス private IMixedRealityPrimaryPointerSelector primaryPointerSelector; // プライマリポインターの変更時に発生するイベント private event PrimaryPointerChangedHandler PrimaryPointerChanged; #region IMixedRealityService Implementation // FocusProvider の初期化処理 public override void Initialize() { ... } // FocusProvider の終了処理 public override void Destroy() { ... } // 毎フレーム行う処理 public override void Update() { if (!IsSetupValid) { return; } UpdatePointers(); // ポインターの更新 UpdateGazeProvider(); // ゲイズは特別扱い UpdateFocusedObjects();// フォーカスオブジェクトの更新 PrimaryPointer = primaryPointerSelector?.Update(); } // ゲイズがフォーカスに使用されていないシナリオでも、ゲイズレイキャストプロバイダーを更新する private void UpdateGazeProvider() { ... } #endregion IMixedRealityService Implementation #region Focus Details by IMixedRealityPointer // ポインターがフォーカスしているオブジェクトを取得する public GameObject GetFocusedObject(IMixedRealityPointer pointingSource) { ... } // ポインターがフォーカスしているオブジェクトの詳細を取得する public bool TryGetFocusDetails(IMixedRealityPointer pointer, out FocusDetails focusDetails) { ... } // フォーカス情報を上書きする public bool TryOverrideFocusDetails(IMixedRealityPointer pointer, FocusDetails focusDetails) { ... } #endregion Focus Details by IMixedRealityPointer #region Utilities // 新しいポインターIDを生成する public uint GenerateNewPointerId() { ... } // UIRaycastCamera を作成するためのユーティリティ private void FindOrCreateUiRaycastCamera() { ... } // UIRaycastCamera を廃棄する private void CleanUpUiRaycastCamera() { ... } // ポインターが pointers ディクショナリに登録されているかどうかを返す public bool IsPointerRegistered(IMixedRealityPointer pointer) { ... } // pointers ディクショナリにポインターを登録する public bool RegisterPointer(IMixedRealityPointer pointer) { ... } // すべてのポインターをメディエイター・ pointers ディクショナリに登録する // 初期化時および入力ソースが検出されたときに呼ばれる private void RegisterPointers(IMixedRealityInputSource inputSource) { ... } // ポインターの登録を解除する public bool UnregisterPointer(IMixedRealityPointer pointer) { ... } // T型のポインターのコレクションを取得する public IEnumerable<T> GetPointers<T>() where T : class, IMixedRealityPointer { ... } // プライマリーポインターが変更したときに通知をするようサブスクライブする public void SubscribeToPrimaryPointerChanged(PrimaryPointerChangedHandler handler, bool invokeHandlerWithCurrentPointer) { ... } // プライマリーポインター変更通知のサブスクライブを解除する public void UnsubscribeFromPrimaryPointerChanged(PrimaryPointerChangedHandler handler) { ... } // 指定されたポインティング入力ソースの登録済み PointerData を返す private bool TryGetPointerData(IMixedRealityPointer pointer, out PointerData data) { ... } // すべてのポインターを更新する private void UpdatePointers() { ... } // ポインターを更新する private void UpdatePointer(PointerData pointerData) { // ポインターのOnPreSceneQuery関数を呼び出す。これにより、レイキャストの準備をする機会が与えられる pointerData.Pointer.OnPreSceneQuery(); // 略... // ポインターがロックされている場合は、フォーカスされているオブジェクトをそのままにする // これにより、ポインターがオブジェクトを指していない場合でも、これらのオブジェクトでイベントを確実に実行できる if (pointerData.Pointer.IsFocusLocked && pointerData.Pointer.IsTargetPositionLockedOnFocusLock) { pointerData.UpdateFocusLockedHit(); // 略... } else { // 略... // フォーカスされているオブジェクトを特定する QueryScene(pointerData.Pointer, raycastProvider, prioritizedLayerMasks, hitResult3d, maxQuerySceneResults, focusIndividualCompoundCollider); // 略... // ここでのみヒット結果を適用して、現在のターゲットの変更がフレームごとに1回だけ検出されるようにする pointerData.UpdateHit(hit); // 略... } // 略... // ポインターのOnPostSceneQuery関数を呼び出す。これにより、レイキャストの結果に応答する機会が与えられる pointerData.Pointer.OnPostSceneQuery(); } // terminus をオブジェクトがヒットした位置に書き換えてRayStepを更新している // (名称からも長く伸びているレイをオブジェクトとヒットした位置まで切り詰めるというイメージだと思う) private void TruncatePointerRayToHit(IMixedRealityPointer pointer, PointerHitResult hit) { ... } // 優先度の高いヒット結果を取得する private PointerHitResult GetPrioritizedHitResult(PointerHitResult hit1, PointerHitResult hit2, LayerMask[] prioritizedLayerMasks) { ... } // アクティブなポインターを整頓するために非アクティブなポインターを無効にする private void ReconcilePointers() { // 略... // ゲイズポインターのステートマシンを更新する(ゲイズポインターを有効にするか無効にするかを設定する) gazePointerStateMachine.UpdateState() { ... } // 略... } #region Physics Raycasting // 球のオーバーラップ結果を保存するために使用されるコライダー private static Collider[] colliders = null; // シーンクエリを実行して、コライダーを備えたどのシーンオブジェクトが現在注視されているかを特定する private static void QueryScene(IMixedRealityPointer pointer, IMixedRealityRaycastProvider raycastProvider, LayerMask[] prioritizedLayerMasks, PointerHitResult hit, int maxQuerySceneResults, bool focusIndividualCompoundCollider) { // ポインターがヒットしているオブジェクトを見つける(フォーカスしているオブジェクトを特定する)処理 } #endregion Physics Raycasting #region uGUI Graphics Raycasting // Unity グラフィックレイキャストを実行して、現在どの uGUI 要素がポイントされているかを特定する private void RaycastGraphics(IMixedRealityPointer pointer, PointerEventData graphicEventData, LayerMask[] prioritizedLayerMasks, PointerHitResult hit) { // ポインターがヒットしているuGUI要素を見つける(フォーカスしているUIオブジェクトを特定する)処理 } // 単一のグラフィック RayStep をレイキャストする private bool RaycastGraphicsStep(PointerEventData graphicEventData, RayStep step, LayerMask[] prioritizedLayerMasks, out RaycastResult uiRaycastResult) { ... } #endregion uGUI Graphics Raycasting // 必要に応じて、フォーカスイベントを入力マネージャーに発生させる private void UpdateFocusedObjects() { // MixedRealityInputSystem の RaiseFocusEnter や RaiseFocusExit メソッド等が呼ばれ、 // そして ExecuteEvents.ExecuteHierarchy(eventTarget, focusEventData, eventHandler) がよればイベントを実行 // 最終的にターゲットオブジェクト(フォーカスしているオブジェクト)の OnFocusEnter / OnFocusExit メソッド等が呼ばれる // ★つまりフォーカスイベントの発生源がここ★ } #endregion Utilities #region ISourceState Implementation // ソースが検出されたときにポインターを登録する public void OnSourceDetected(SourceStateEventData eventData) { ... } // ソースの検出が失われたときにポインターの登録を解除する public void OnSourceLost(SourceStateEventData eventData) { ... } #endregion ISourceState Implementation #region IMixedRealitySpeechHandler Implementation // 「select」の音声が認識されると、目または頭に基づくゲイズカーソルを再アクティブ化するフラグを立てる public void OnSpeechKeywordRecognized(SpeechEventData eventData) { ... } #endregion #region IPointerPreferences Implementation private List<PointerPreferences> customPointerBehaviors = new List<PointerPreferences>(); // ポインターの動作(ビヘイビアー)を取得する public PointerBehavior GetPointerBehavior(IMixedRealityPointer pointer) { ... } // 指定されたポインタ型の動作(ビヘイビアー)を取得する public PointerBehavior GetPointerBehavior<T>(Handedness handedness, InputSourceType sourceType) where T : class, IMixedRealityPointer { ... } private PointerBehavior GetPointerBehavior(Type type, Handedness handedness, InputSourceType sourceType) { ... } // ポインターの動作(ビヘイビアー)のプロパティ public PointerBehavior GazePointerBehavior { get; set; } = PointerBehavior.Default; // ポインターの動作(ビヘイビアー)を設定する(PointerUtils から呼ばれる) // PointerUtilsから呼ばれてポインターの有効・無効の切り替えを行っている public void SetPointerBehavior<T>(Handedness handedness, InputSourceType inputType, PointerBehavior pointerBehavior) where T : class, IMixedRealityPointer { ... } // ポインター設定クラス(ソースのタイプ、ポインターのタイプ、手に応じたポインタービヘイビアーを持つ) private class PointerPreferences { ... } #endregion }
フォーカスがロックされている状態とは?
もう少し詳しく書くと
RaisePointerUp で IsFocusLocked = false に設定される
GGVPointer は OnInputDown 時にオブジェクトにフォーカスが当たっていれば IsFocusLocked = true そうでなければ false に設定される
ロックされている間は、ポインターがオブジェクトを指していない場合でもフォーカスされているものとして扱うためのもので、ポインターが当たっていないオブジェクトでもフォーカスイベントを確実に実行するための仕組み。
プライマリーポインターとは?
RayStep とは?
CurvePointerを生成するときに以下のように生成されています。
protected int LineCastResolution = 10;
Rays = new RayStep[LineCastResolution];
CurvePointer 以外の LinePointer や PokePointer や SpherePointer では 要素は1つしか持っていません。
Rays = new RayStep[1];
GenericPointer も以下の通り要素は1つです。
public RayStep[] Rays { get; protected set; } = { new RayStep(Vector3.zero, Vector3.forward) };
つまり「レイを何分割するか」というもので、カーブを描いていなければ基本的に1直線なので1つのレイと考えればよさそうです。
TruncatePointerRayToHit メソッドは何をしているか?
一番優先度が高いレイヤーのオブジェクトとヒットしている場合は(それ以上先にレイが伸びている必要がないので)レイの終点をこのヒット位置まで切り詰める(ということだと思う)。
MixedRealityInputSystemProfile で Focus Provider Type として FocusProvider が設定されている
GazeProviderは特殊扱いする(登録されたポインタでなくても追跡する)
FocusProvider の実装について確認しました。
概要については冒頭に書いた通りです。
今後も入力周りを中心に、(自分のメモとして)徐々に内部の実装について確認していきたいと思います。
なお、FocusProvider は以下の通り MRTK の中ではライン数がベスト 10 に入るヘビー級のクラスです。
]]>MRTKのライン数の多いファイルベスト10 pic.twitter.com/tpiMVdvFyp
— 広務(Hiromu) (@hi_rom_) 2020年6月12日
The August 2020 update (10.0.19041.1113) で解決されたようです。 https://holodevelopers.slack.com/archives/C1CQKRQM6/p1597188506274500?thread_ts=1593035544.420800&cid=C1CQKRQM6
HoloLens 2 を PC に USB 接続してデプロイするとタイムアウトすることが良くあります。 これについては既知の問題のようで、中の人も認識しているようです。
developercommunity.visualstudio.com
そして、 問題の原因を特定し、将来のOSアップデートで対応されるとのコメントもあります。
Good news! We've identified the cause of the problem and have identified the fix. We're working to include it in a future OS update for your HoloLens device.
現状としては、アップデートを待つしかありませんが、いくつかの回避策が提示されているため以下に記載しておきます。
USBケーブルを取り外して再接続し、再試行すること(数回ためすとうまくいくことがある)
appxパッケージを作成しDevice Portalを介してサイドロードする
Wi-Fiを使用する
USBを使用する場合は、以下の手順で接続する
IPv4アドレスをコピーする
Visual Studioで、WiFiの場合と同様に「リモートマシン」を使用するようにデバッグを構成するが、手順5でコピーしたIPアドレスを入力する
42万円のハードで遊ぶパズルゲーム楽しい! #HoloLens2 pic.twitter.com/YZNMxrIKMd
— 広務(Hiromu) (@hi_rom_) 2020年7月9日
これは、Unreal Engine で作られた Microsoft からリリースされた初の HoloLens 2 向けアプリとのことです。
We have launched our first @HoloLens 2 application built with @UnrealEngine to the @Microsoft Store! Check out HoloPipes, the classic pipe puzzle game played in 3D with direct object interaction.https://t.co/gF5i1xHH8X
— Mixed Reality DevRel Team (@MxdRealityDev) 2020年7月8日
このアプリについて、HoloDevelopers という世界中の HoloLens 開発者の集まる slack において、アプリ開発者の方が以下のようなコメントをしていました。
内容としては「アイトラッキングのパーミッション確認がでるけど、どこで利用しているの?」という質問に対する回答で
Eye tracking is used a couple ways:
To determine "attention" on things like the hand menu (i.e. don't pop up the hand menu if you're looking somewhere else)
To disambiguate between actionable holograms when there are multiple holograms close to the hand
とのことです。
訳すと
アイトラッキングはいくつかの方法で使用されます。
ハンドメニューなどの "注意"を判断する(つまり、他の場所を探している場合は、ハンドメニューをポップアップしないようにする)
手の近くに複数のホログラムがある場合に、実行可能なホログラムを明確にする
また、他にも
「ハンドトラッキングだけで直感的に選択できるようにするために、多くのヒューリスティックを試みましたが、ハンドの位置のみから意図を判断することは困難です。 アイトラッキングを追加することで、選択ロジックを単純化し、より直感的に感じることができました。」といったコメントもありました。
ユーザーはその機能に気づくことはないかもしれませんが、それがポイントのようでもあります。とても有用な内容だと思ったのでご紹介しました。
ちなみに、以下はユーザーにまるわかりなアイトラッキングの例です。
アイトラッキングをアイトラッキングするの作った(赤い部分が見ているところ)#HoloLens2 #xeyes pic.twitter.com/A21vT7fzFI
— 広務(Hiromu) (@hi_rom_) 2020年3月29日
アイトラッキングの実装方法については、以下もご参照ください。
]]>これをこのまま使っていると複数のアプリケーションでパッケージ名が被ってしまい、 アプリケーションが上書きされて消えてしまう、インストールできない、といった問題が発生します。
手動での変更方法は以下のブログで紹介されています。
ここでは、この値を自動で変更するスクリプトを紹介します。
ホロラボでは、以下のスクリプトを HoloLabToolkit という社内向けのアプリ開発ライブラリに入れています。
(namespace などは一部変更しています)
このスクリプトは Unity Editor の起動時やビルドターゲット変更時に実行され、 Company Name やパッケージ名がデフォルトのままであるときに以下のように変更を行います。
Company Name : スクリプトで設定した値
パッケージ名: プロダクト名(Unity プロジェクトを新規作成するときのプロジェクト名)
社内ツールや個人の開発ツールに入れてご活用ください。
]]>具体的な実装の確認に入る前に、ポインターについて理解するには MRTK の入力システム(Input System)について理解する必要があります。入力システムは MRTK のアーキテクチャ全体の中の以下赤枠の部分になります。
入力システムに関するドキュメントは以下。
ドキュメントにある以下の図が入力システムについて分かりやすくまとまっています。
図を見ると入力システムは、以下のもので構成されていることがわかります。
Device Manager(Data Provider)
Controller
Pointer
Focus
Cursor
Interactable
GameObject with PointerHandler
以上のような階層で構成されているものの一つにポインターがあることが分かったので、ポインターについて詳しく見ていきます。
ポインターに関しては、以下2つのドキュメントに目を通すと良いと思います。
Architecture / Input System / Controllers, pointers, and focus
Feature Overviews / Input System / Pointers
Teleport pointers (VR向け機能)
Pointer event interfaces
以下のインターフェイスを 1 つ以上実装し、コライダーを持つ GameObject に割り当てられた MonoBehaviour は、関連するインターフェイスで定義された Pointer インタラクションイベントを受信する
イベント | 説明 | ハンドラー |
---|---|---|
Before Focus Changed / Focus Changed | ポインターがフォーカスを変更するたびに、フォーカスを失ったゲームオブジェクトと、フォーカスを獲得したゲームオブジェクトの両方に発生する | IMixedRealityFocusChangedHandler |
Focus Enter / Exit | 最初のポインタが入ったときにフォーカスを得るゲームオブジェクトと、最後のポインタが離れるときにフォーカスを失うゲームオブジェクトの上に発生する | IMixedRealityFocusHandler |
Pointer Down / Dragged / Up / Clicked | ポインターの押下、ドラッグ、リリースを報告するために発生する | IMixedRealityPointerHandler |
Touch Started / Updated / Completed | PokePointerなどのタッチ対応ポインターによって発生し、タッチアクティビティを報告する | IMixedRealityTouchHandler |
ポインタ入力イベント
すべての有効なポインタを調べる方法
var pointers = new HashSet<IMixedRealityPointer> foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources) { foreach (var pointer in inputSource.Pointers) { if (pointer.IsInteractionEnabled && !pointers.Contains(pointer)) { pointers.Add(pointer); } } }
Primary pointer
Pointer result
Disable pointers
UnityEditor を介したポインターインタラクション
ポインターの長さ
ほとんどドキュメントを翻訳しただけのような内容になりましたが、入力システムとポインターについて確認しました。
簡単にまとめるとポインターとは、
という感じでしょうか。 その点を踏まえつつ、HoloLens 2 におけるハンド操作部分だけを抜き出した絵にしてみました。
次回(?)は GazePointer によって生成される InternalGazePointer について確認していこうと思います。
]]>
デフォルトでは表示になっていますが、常に表示されるとちょっと邪魔だったりします。
なので、必要なければプロファイラの設定でオフにしておくと良いと思います。
もしくは、ToggleFeaturesPanel プレハブを置いておくと動的に表示・非表示を切り替えられるので便利です(必要なくなったらプレハブを削除すればよい)。
または、音声コマンドで非表示にすることもできます(発音がよければ)。
写真にあるような、Development Console が片目にだけ表示される場合がありますが、文字が小さくてほとんど読めません。 これはMaster ビルドだと表示されませんが、 Debugビルド、およびRelease ビルドでは表示されます(なぜかReleaseビルドでも表示される)。
スクリプトから
Debug.developerConsoleVisible = false;
として消すこともできます。
以下のissueにある通り TouchScreenKeyboard.visible が正しい値を返さないため、キーボードの表示・非表示の正しい状態を取得するのは MixedRealityKeyboard.cs を参考にするのが良いです。
ドキュメント
以前認識したQRコードがキャッシュに残り、アプリ起動時に検出していないはずのQRコードを検出することがあります。これは「特定のタイムスタンプよりも古い QR コードを無視するようにアプリを構成する」ことで対応できます。
ドキュメントのQRコードの管理にも以下のように書かれています。
特定のタイムスタンプよりも古い QR コードを無視するようにアプリを構成することをお勧めします。 現時点では、API は QR コード履歴のクリアをサポートしていません。
QRコードトラッキングのサンプルコードは以下。
]]>Microsoft MVPを再受賞しました。
今年はもう一つ増えて、 Microsoft Regional Director(RD) を拝命しました。
MVPが技術的なアウトプットやフィードバックに対して、RDはビジネス的なアプトプットやフィードバックを求められる位置になります。 RDもMVP同様に個人につくのですが、ビジネス的なので個人では無理で会社ありきと思ってます。
会社で認定されているMRPP(Mixed Reality Partner Program)と合わせて、個人と会社での、技術とビジネスのアウトプットについて、評価と期待をされていると認識してます。
まぁ肩書が増えてもやることは変わらないので、粛々とHoloLens 2の実運用に向けて進んでいきます。
]]>まず、MRTKをインポートし、メニューの [Mixed Reality Toolkit] > [Add to Scene and Configure...]を選択します。 この時点ですでに最低限動作をする状態となっているため、Hierarchy を確認します。
この中で、MixedRealityToolkit の子にある複数の GameObject は UnityEditor 上でアクティブなサービスを可視化するために表示しているだけのもの(*1)なので、無視すると具体的に見る必要があるコンポーネントは以下の4つになります。
MixedRealityToolkit オブジェクト
Main Camera オブジェクト
この4つのスクリプトを元にして MRTK は動作していることになります。 この中で、EventSystem は Unity の機能であり MRTK の実装ではありません。
また、MixedRealityInputModule は StandaloneInputModule を継承したもので EventSystem と一緒に用いて動作するものになるため uGUI を利用する際に必要なものとなります。
確認として MixedRealityInputModule コンポーネントを削除して PressableButtonHoloLens2 プレハブのボタンを配置してみても問題なく操作できます。(なお EventSystem は削除するとエラーがでます)
従って、uGUI はひとまず利用しない前提で考えると、MRTK の中身を把握していくためには、以下2つのコンポーネントを掘り下げていけば良いことになります。(たったの2つ!)
次に、MonoBehaviour を継承したものなので イベント関数の実行順序 の順に追っていきます(終了関連の処理は省略)
Awake()
OnEnable()
Start() なし
Update() / LateUpdate()
MixedRealityInputSystem 初期化の段階で、GazePointar へのアクセスがあるので、OnEnableよりも前に InitializeGazePointer メソッドが呼ばれ、ポインターの生成・初期化を行っている。またカーソルも生成される(InitializeGazePointerの中にブレークポイントを張って実行すると確認できる)。
Awake() なし
OnEnable()
Start()
Update()
LateUpdate()
次にシーンを実行してみたときの Hierarchy です。
以下のゲームオブジェクトが追加されています。
これらの GameObject は MixedRealityToolkit または GazeProvider (またはその中で新たに生成されたオブジェクトの中)で生成されていると言えます(*2)。
MixedRealityToolkit コンポーネントがサービス全体のとりまとめをおこなっていることがわかりました。プロファイルで利用したいサービスの具象クラスを設定するようになっているので、さらに詳細を把握したい場合は、その具象クラスを追っていけば良いことがわかります。
(*1) プロファイルの Editor > Use Service Inspectors のコメントを見るとそう書かれており、チェックを外すと Hierarchy から GameObject も削除されます
(*2) 実際に生成されている場所は以下
DefaultCursor(Clone) :
None_GGVPointer :
UIRaycastCamera :
6/18発売です。
書籍の内容については会社ブログのほうにまとめたので、こちらは個人的なことを。
前提としては下記になります。
読者の対象は企業のユーザーさんを想定しているため、HoloLens 2の概要、事例、セットアップ、運用、アプリの使い方が中心です。アプリ開発に関する要素はありません。
2017年に日本でHoloLens 1がリリースされました。この時はなんとなく会社を作ったほうがいい雰囲気から会社を作って、どうなるかもよくわからない状況でした。2017年、2018年と徐々に方向性が見えてきたところでの2019年のHoloLens 1ディスコン。HoloLens 2が2019年の後半にでることだけが見えている状況で、HoloLens 1がうまく適用できるところからHoloLens 2への準備を着々としていました。
2019年の後半にHoloLens 2の販売が開始され、ユーザーが手に取る機会が増えました。HoloLens 2から始めて触れるユーザーも多くいて、それが今後も増えていくということから、書籍はユーザー向けとしました。本の賞味期限としても、HoloLens 2リリース後すぐであれば、仮にHoloLens 3がでるとしても数年は使うことができます。それまでにHoloLens 2のユーザーをできるかぎり増やすことが自分の仕事と考えています。
開発向けに関しては、書籍の初版が2000-3000部とすると、それだけのHoloLensアプリ開発者がいるかというとNoでしょうし、ユーザーが増えて様々使ってもらうことによって、ユーザーのやりたいことが増え、結果的に開発者が必要になってくる状況になるといいなと思っています。
また、開発者向けの場合、日ごと変わっていくUnityやMRTKに対して、どのような内容がいいのかというのが正直見えていません。昨今のように日々変わっていく状況では、物理的な書籍よりもWebや動画のほうがいいのかなとも思います。とはいえ、書籍のほうが広がり、認知度などの面でよいこともわかっているので、うまい方法があればやってみたいです。
今回は社内や宮浦さん、森さんにだいぶ叩いてもらいましたので、だいぶ読みやすいと思います。内容、構成などもだいぶ手入れをしてもらってるのですが、書いてるのは自分なのでそのあたりはご了承ください。
HoloLensが広まるにつれ、HoloLens外での要素が増えてきます。セットアップや運用、さまざまな用途など。薄く紹介のプロビジョニングパッケージ、MDM(Intune)。アプリからのDynamics 365、言葉だけの紹介になっていますがPower Platform。範囲がいつのまにか大きく広がっていて、それぞれを適切に使い分けながら、ユーザーに合わせた環境を作ることが大切になってきます。
いろいろと書き足りなかったところ、新しい情報などは会社のブログに追記していきます。前書きからリンク集にはアクセスできるようになっているので、そこをポータルにしようと思います。
]]>前の記事はこちら www.hiromukato.com
「物を掴んだりボタンを押したりできる最低限の機能をHoloLens 2 および UnityEditorで確認できる」ための実装を確認する場合どのあたりを見ればよいのかについてあたりをつけました。
そこからもう少し踏み込んで、MRTK v2.4.0(Foundation)をインポートし、必要のないものをできる限り削除するプロジェクトを準備ところまで落とし込みました。 以下のReleaseページにunitypackageとして準備しています。Unity 2019.3.15f1で動作確認済みです。
以下はGitHubのコミットログですが行った作業です。 見ての通りですがほとんどがデータ提供元(Provider) と特定の機能を提供する Services 配下のものなので、基本的にその機能を利用としない限りは動作に影響はないと思います(ただし動作を保証するものではありませんのでご注意ください)。
音声認識や空間認識機能も思い切って削除していますが、ベースとなる部分を把握できれば後は必要な時に差分としてみていけばいいのではないかと思います。 なお、Gltf関連やInputAnimationアセンブリあたりも消せるかと思いましたが、エラーが出たので消すのは止めておきました。
MRTKで何かを作るのではなく、最低限の動作を把握しようとした場合に利用できるのではないかと思ったので公開してみました。
]]>まずは以下に示す通り .cs ファイルの一覧を作りました。
(csv化したスクリプトはこちら)
https://1drv.ms/x/s!AurL06W3WNM4pOtAuohrR4zuJtPNDQ?e=LMiM0t
1215行目にありますが、すべてのソースで 181,840行もあります。 1日1,000行見たとしても180日かかりますね。。
ということで、効率的に見ていかないと時間ばかりかかってしまうなと思ったので、Unityから出力されるアセンブリごとに概要をまとめてみました。
https://1drv.ms/x/s!AurL06W3WNM4pOs-axSQ1o7SAeENdA?e=CUL69f
こちらは、スクショも張っておきます。
合計で55のアセンブリ(プロジェクト)があります。 Visual Studioで開いたときにいきなりこれだけのプロジェクトがあるだけでも圧倒されてしまいますが、この中で最低限HoloLens実機・およびUnityEditorで動作させるために見ればいい部分はどこかという点で重要な部分に色を付けました。これで7個まで絞り込めました。この7個の詳細についてはおいおい見ていこうと思います。
とっかかりとして、まずはここまで。
]]>以降で、順を追って確認していきます。
Unityのプロジェクトを新規作成し、MRTK(v2.4.0)をインポートする
メニューの [Mixed Reality Toolkit] > [Add to Scene and Configure...] を選択する
Canvas を配置する
Canvas の位置・サイズを任意の値に調整する(以下は例)
Canvas のインスペクターにある「Convert to MRTK Canvas」ボタンを押す
以下のようにRender Mode が World Space になり、Canvas Utility コンポーネントが追加されている。また、Add NearInteractionTouchableUnityUI ボタンがあるので押す
すると、Near Interaction Touchable Unity UI コンポーネントが追加される
NearInteractionTouchableUnityUI の Events To Receive を Pointer に変更する
Canvas に Scroll View を配置する
Scroll View > Viewport > Content に Text を配置する(Textにはスクロールが確認できるように任意の文字列をいれる)
Text の Rect Transform のAnchor Presets は、stretch/stretch を選択する(Shift + Alt を押すと表示される中の一番右下の項目)
ここで MRTK で推奨されている XR Settings の Depth Format を 16-bit depth でビルドをする
UnityEditor上では問題なく見えていたが、実機では以下のようにMaskが正しく機能していない(16-bit depthの場合ステンシルバッファーが作成されないことが原因)
Depth Format を 24-bit depth に変更することで正しく表示される
Depth Format を 16-bit depth のままとする場合には、Mask の代わりに RectMask2D を使うことで同様の結果を得ることができる
Unity UI でニアインタラクションをおこなうための設定(特にUnity UIの部分)
マスク機能を使う場合の注意点
]]>上記の変更箇所以外は、以下の通りとなります。
v2.3.0までの設定方法 www.hiromukato.com
]]>設定だけであればスクショを見るだけで完了すると思います。
キャリブレーションされていない場合、アイトラッキングシステムは入力を返さない 以下のどちらかでキャリブレーションを行う
'Simulate Eye Position' にチェックを入れる
default head gaze cursor を無効にすることが推奨されている
// Show the object at the hit position of the user's eye gaze ray with the target. gameObject.transform.position = CoreServices.InputSystem.EyeGazeProvider.HitPosition; // If no target is hit, show the object at a default distance along the gaze ray. gameObject.transform.position = CoreServices.InputSystem.EyeGazeProvider.GazeOrigin + CoreServices.InputSystem.EyeGazeProvider.GazeDirection.normalized * defaultDistanceInMeters;
// Turn off all hand rays PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff); // Restore default behavior for rays (on if not near something grabbable) PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default); // Turn off hand rays for the right hand only PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right); // Turn off the gaze pointer PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);
上の記事はハンズオンを中心とした内容でしたが、今回は概要やコンセプトに関するドキュメントの内容をサマリ(というより自分が気になった部分を抜き出したもの)としてまとめました。
Unityでホログラフィックリモート処理とリモートレンダリングを使用する
※価格に関しての注意点:クライアントのアプリとクラウド上のVMが接続されていなくても、VMが起動している時間で課金されます。一定時間経過すると自動的にVMが停止するようになっていますが、必要ない場合は明示的にセッションを停止するようにしておくと良いと思います。停止方法については以下の「セッションの停止方法」参照
Azureのリソース設定(これをしないことには始まりません、サンプルの確認もできない)
Azure Remote Rendering アカウントの作成
サンプルを動かす
オリジナルのモデルを確認する
スクラッチでUnityの実装をする
Azure ポータルから(これが一番簡単かつ確実だと思います)
Quickstarts アプリの場合
Auto-Stop Session にチェックを入れると Play 終了後セッションを停止する
arr-showcase-app アプリの場合
インスペクタにセッション操作ボタンがある
チュートリアルのアプリの場合
Connect-AzAccount -Subscription <subscriptionID>
.\RenderingSession.ps1 -GetSessions
.\RenderingSession.ps1 -StopSession -Id <sessionID>
arr-showcase-app アプリにおいて Azure のアカウント情報は RemoteRenderingService オブジェクトのインスペクタで設定するようになっていますが、以下のような arr.account.xml をStreamingAssetsに格納するか、もしくは、arr.overrides.xml を Application.persistentDataPath に格納することでもアカウント情報を設定することができます。(arr.account.xml についてはドキュメントで触れられているもののどのような内容を記載すればいいのかが書かれていなかったのでソースを確認しました)
<?xml version="1.0" encoding="utf-8"?> <Configuration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Account> <AccountDomains> <AccountDomain>eastus.mixedreality.azure.com</AccountDomain> <AccountDomain>westeurope.mixedreality.azure.com</AccountDomain> <AccountDomain>westus2.mixedreality.azure.com</AccountDomain> <AccountDomain>southeastasia.mixedreality.azure.com</AccountDomain> </AccountDomains> <AccountId>★アカウント情報</AccountId> <AccountKey>★アカウントキー</AccountKey> </Account> <Storage> <StorageAccountName>★ストレージ名</StorageAccountName> <StorageAccountKey>★ストレージのアカウントキー</StorageAccountKey> <StorageModelContainer>★モデルを格納したコンテナ</StorageModelContainer> </Storage> <Session> <MaxLeaseTime>300</MaxLeaseTime> <AutoRenewLease>true</AutoRenewLease> <AutoReconnect>true</AutoReconnect> <AutoReconnectRate>15.0</AutoReconnectRate> </Session> </Configuration>
概要
ドキュメント
GitHub
価格
利用可能なリージョン
制限
ネットワーク要件
C# API
上記サイトを参考に HoloLens 2 で QR コードをトラッキングするサンプルを試したのでメモ
GitHub の以下サンプルをダウンロードする
必要な物がすべてこの中に含まれているので参考サイトに書かれているNuGet パッケージのダウンロードなどは必要ない
Unity で SampleQRCodes を開く
QRCodesSample シーンを開く
Universal Windows Platform に Switch Platform
Depth Buffer Sharing has 24-bit depth format selected. Consider using 16-bit for performance. の警告がでるので対応
Audio Spatializer Plugin not currently set to MS HRTF Spatializer. Switch to MS HRTF Spatializer under Project Settings > Audio > Spatializer Plugin の警告が出るので対応
キャプチャでは見えませんが、起動後 HoloLens 上ではエラーが表示されています。またそれが原因か起動した場所に座標軸が残ったままになっていますが、QRコードの認識は問題なくできました。
環境認識カメラで QR コードを認識しているためこのように動画のキャプチャが可能です。
QR コードの検出には webcam 機能が必要ですが、検出はデバイスの追跡カメラを使用して行われます。 これにより、デバイスの写真/ビデオ (PV) カメラとの検出と比較して、より広範な検出とバッテリ寿命が提供されます。
QR コードを正しく読み取るには、コードのすべての辺の周りに余白が必要です。
Windows Mixed Reality デバイスは、それぞれ 5 cm 未満の QR コードでは機能しません。5から 10 cm の長さの辺までの QR コードの場合、コードを検出するには非常に近い必要があります。 また、このサイズでコードを検出するのにも時間がかかります。
コードを正確に検出するための正確な時間は、QR コードのサイズだけでなく、コードから離れた場所までの距離に依存します。
バージョン1の QR コードが 10 ~ 25 cm 幅を超える場合、最小検出距離は0.15 メートルから0.5 メートルの範囲内です。
特定のタイムスタンプよりも古い QR コードを無視するようにアプリを構成することをお勧めします。
会社のふりかえりはこちら blog.hololab.co.jp
大体の発表が会社に紐づいているのでこちらに残すことが少ないのですが、 2019年は Microsoft de:code, Unite 2019, XR Kaigi, Microsoft Ignite Tour Tokyoといった大きなイベントで登壇することができました。
まぁ引き続きHoloLensなんですが、Azure Kinet が3月に日本でも発売開始になるので、こちらをぼちぼちまとめていこうかと思います。
HoloLens 2については、HoloLensというよりはMRTKで差分くらいなのでちょっとどうなんだろう(HoloLens 2用にまとめなおすのはアリかもしれないけど)
会社の方はだいぶお任せできるようになってきたので、2020年は開発の時間を増やしたいところです。結果的に2018年のふりかえりに書いてたオフロードはおおよそできている状態になったかなと。
2020年の目標としては、手を動かす時間を増やすことになります。また新しいものがたくさん出てくるので、それにちゃんとついていかないと。
イベントページはこちら
当日のまとめはこちら
ホロラボで5台調達できて色々触っていたのですが、Twitter見てると見てみたい、触ってみたい方が多かったので急遽開催してみました。
デザイニウムでも3台調達できたでので、7人の開発は1人1台+見学用に1台という、この時期で豪華な買いになりました。スタッフ含めてご協力いただいた方に感謝します。
Kinect v2までのゲームコントローラーからブランディングを変えたことで、いままでHoloLensを扱っていたお客さんも興味を持ってくれるようになりました。Kinect v2も最後のほうは産業用途が増えていたので、HoloLens 2と同様にいい場所に配置されたのではないかと思っています。
]]>
このエントリでは外部同期の手順について解説します。
ドキュメントはこちら
外部同期は複数台のAzure Kinect DKをオーディオケーブルで接続し、Depthのシャッターを同時に切ることができます。これによって複数台のAzure Kinect DKで同一タイムスタンプのDepth、IRのデータが生成されるので、同じタイミングでの空間スキャンができます。また、タイムスタンプが同一なので、それぞれのデータをクラウドにアップして後処理するなどの利用が考えられます。
ポイントは下記になります
なお、オーディオケーブルを接続する場所は付属のドライバでネジを外し、ケースを外すと出てきます(めんどくさい)。
Azure Kinect Viewerを使用しても外部同期を行うことができます。
デバイスを開き、ケーブルの状態を確認します。
Azure Kinect Viewerでの表示
起動してしばらくするとDepthのタイムスタンプが同じ値になります。
4台までの接続は確認しています。
スプリッタは2分岐でも5分岐でも動作しました。
ケーブル(5m/10m)
サンワサプライ オーディオケーブル 5.0m ブラック KM-A2-50K2
分岐
3.5mmオーディオ分配ケーブル 音声出力分岐コード イヤホンマイク機能搭載 ステレオミニY分岐ジャックコネクタケーブル 4極メス x 2-4極オス x 1 延長コード 多用型
Amazonベーシック 5ウェイ マルチヘッドホンオーディオスプリッター コネクター レッド
外部同期することでセンサーデータの同期の保証や後処理が可能になります。
ケーブルの取り回しが大変ですが、複数台のAzure Kinect DKを使う場合には導入を検討してみてください。
]]>Azure Kinect SDKをインストールすることで、開発に必要なファイルやビューアーツール、Azure Kinect DKデータのレコーダー、ファームウェアアップデートツールなどが利用可能になります。
公式のドキュメントはこちら
Azure Kinect のSensor SDKはこちらからダウンロードして、インストールします。
BodyTracking SDKはこちらから
Azure Kinect DKのプログラムを開発環境以外で動作させるときはSDKのインストールは不要で、実行ファイル(exe)と関連DLL(k4a.dll, depthengine_1_0.dll, k4arecord.dll)のみで動作します。
Azure Kinect DKはUVC(USB Video Class)という標準ドライバで動作し間に入るサービスもないため、センサーをUSB接続し、アプリ一式のみで実行可能となります。
デフォルトのビューアーです。最初の動作確認に使用します。
スタートメニューから「Azure Kinect Viewer」を検索するか、インストールフォルダ(通常は C:\Program Files\Azure Kinect SDK vX.Y.Z)のtools以下にある「k4aviewer.exe」を起動します。
通常は「Open Device」から該当のシリアル番号(複数接続されているときのAzure Kinect DKの識別子)を開きます。1つのAzure Kinect Viewerアプリでは1台のAzure Kinect DKのみ扱えるので、複数台のAzure Kinect DKを操作する場合には複数のAzure Kinect Viewerアプリを起動しOpenするAzure Kinect DKを変更します。
記録データの再生を行う場合には「Open Recording」に録画ファイル(拡張子 mkv)のパスを入力(ダイアログはないのでパスをコピペしますw)してmkvファイルを選択します。
Azure Kinect DKの動作を開始する前にデバイスの設定を行います。
基本的な設定としては、Depthのモード、カラーのフォーマットと解像度、フレームレートになります。
Depthのモードとモードによる見え方の違いは下記になります。
カラーのフォーマットと解像度は下記になります。 BGRAについてはMJPEGをSDKでデコードして作成しているようです。
フレームレートはDepthとカラーの最大値の小さい方に引きずられます。
「Color Control」を開くとカラーカメラの各種設定を変更できます。
外部同期の設定を行います(詳しくは後述)。同期ケーブルの接続はハード的に検出しておりSDKで取得ができます。
Azure Kinect DKの動作を開始すると、2Dでの画面が表示されます。IR、Depth、カラー、IMUとセンサー温度、マイクが取得できます。
3D表示に切り替えると点群で表示されます。
再生モードの場合は、自動で再生が開始され録画データのフォーマットが表示されます。
録画ツールです。コマンドラインアプリのため、コンソール画面やbatファイルで起動します。
ドキュメントはこちら
パラメーターは下記の通りです。
よく使うのはカラーモードの「-c」やDepthモードの「-d」あたりでしょうか。
例えば1080pのNFOV、Binnedは下記のようになります。
k4arecorder.exe -c 1080p -d NFOV_2X2BINNED -r 30 nfov_bined_1.mkv
1080pのWFOV、Unbinnedは下記のようになります。
k4arecorder.exe -c 1080p -d WFOV_UNBINNED -r 15 wfov_unbined_1.mkv
録画されたmkvはAzure Kinect Viewerで再生できます。
BodyTracking用のサンプルアプリです。BodyTracking SDKをインストールすると「C:\Program Files\Azure Kinect Body Tracking SDK\tools」にインストールされます。
k4abt_simple_3d_viewerはONNXを使用しているため、関連するCUDAのインストールが必要です。
インストールに関するドキュメントはこちらです。
CUDAは10.0固定となっており、インストールしてPCを再起動することで利用可能となります。CUDAをインストールする際に、GeForceのドライバのバージョンが下がる場合があるので、最新のドライバをインストールしなおします。
cuDNN はZIPでダウンロードするので、展開して「cudnn64_7.dll」にパスを通すかexeと同じ場所に置きます。
最後にVisual Studio 2015のRuntimeをインストールします(すでにインストール済みと出る場合にはそのまますすみます)。
この状態で実行すると動作し、下記のキーボード操作が可能になります。
下記の動画は「body visualization mode」と「3d window layout」を有効にした状態です。
うごいたーwwww pic.twitter.com/0GU3C1lKYU
— 中村 薫(Kaoru Nakamura) (@kaorun55) July 25, 2019
下記のようなエラーでしばらく動かなかったのですが、GeForceのドライバがエラーになっていたのでドライババージョンの問題だった可能性が高いです(今回はPCをリセットしてインストール手順を順に行いました)。
SDKをインストールすることでAzure Kinect DKの動作確認とデータの録画ができます。
録画することで、アプリ開発の際に再現性のある状態にできるので、現場データの録画は開発の最初に行うと良いかと思います。
]]>米国と中国のみ。日本へは一度現地の住所に送って転送。電波は出してないので技適は対象外。
URLは「en-us」にすること。「ja-jp」はNotFoundになる。
SDKはオープンに開発されています。
動きがないので微妙だけどないよりはマシ
こちらご覧ください
Depth性能が素晴らしく良い。
とりあえず、動作確認 pic.twitter.com/OjQxXin0FL
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年7月8日
複数台のAzure Kinect DKのシャッタータイミングをハード的に同期させる機構。Azure Kinect DKは複数台運用も含めて設計されていることがわかる。
1 PCで4 KinectをExternal Syncで動かせたw pic.twitter.com/FhumU0EfQP
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年7月10日
OpenCV + PCL(Point Cloud Library) + 1 Kinect pic.twitter.com/Y0wMyRih2i
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年7月8日
外部同期はいったん置いておいてC#のプロジェクトを動かしてみた #AzureKinect pic.twitter.com/gqwkpxHI8U
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年7月8日
]]>C#でできればUnityに行ける pic.twitter.com/0c09eiSpnu
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年7月8日
呼んでいただいたみなさん、ありがとうございました。
今年はHoloLens 2とAzure Kinect DKが発売されるので、また楽しい一年になりそうです。ぜひ色々なところに広げていきたいので、ご連絡いただければと思います!
いまの受賞分野はWindows Developmentですが、昔はKinect for Windowsだった時期もありました。
おすすめのデフォルトプロファイル追加
HTK から MRTK v2 へのポーティング改善(HTK と MRTKv2 で GUID が重複していたため新しい GUID を振りなおした)
ポーティング改善はこれっぽいですねhttps://t.co/bdEdOIYs4M
— たるこす (@tarukosu) June 13, 2019
ハンドアタッチメニュー(Experimental)
参考: #4532
MRTK Standard Shader と Lightweight Render Pipeline との連携
MixedRealityServiceRegistryの追加
MixedRealityPlayspace プロパティの追加
IMixedRealityDataProviderAccessインターフェイスの追加
いくつかのAPIを変更
MixedRealityToolkit
MixedRealityPlayspace プロパティの削除
IMixedRealityBoundarySystem
BoundaryVisualizationProfile プロパティの追加
IMixedRealityDiagnosticsSystem
DiagnosticsSystemProfile プロパティの追加
IMixedRealityInputSystem
InputSystemProfile プロパティの追加
IMixedRealitySpatialAwarenessSystem
SpatialAwarenessProfile プロパティの追加
GetObserver と GetObservers メソッドをobsolete に変更
MixedRealityInputSystem
IMixedRealityDataProviderAccess を実装
MixedRealitySpatialAwarenessSystem
IMixedRealityDataProviderAccess を実装
その他不具合修正
Unity 2018.4 LTS 対応
Unity 2019.1 対応
一応会社ブログにはリンクだけまとめたんですが、個人的な思いというか考えてることは切り離した方がいいかなと思い、こちらにもまとめます。
第一回で「実際の導入を見据えた案件も少しずつ出始めています」としていますが、これはホロラボでの開発期間、契約期間からも実感しています。
2018年は長くても半年くらいのプロジェクトがいくつかでしたが、2019年は1年分の予算を確保していただき開発や調査にそれだけのコスト(時間、費用)をかける企業が増えてきました。プロジェクトはEnvisioning(導入) → PoC(概念実証) → Pilot(部分導入) →Deploy(実導入)と進んでいき、Pilot以降を見据えた取り組みが増えてきています。
去年あたりから、プロジェクト数の数字などを出すようにしています。これは外からあまり見えない実態みたいなものを出していきたいという気持ちがあります。HoloLensはいろいろなところで使われ始めています。とはいってもどのくらいの会社が使ってるの? どのくらいのプロジェクトが回ってるの?という数字が見えたほうがイメージしやすいのではと思っています。
例えば2018年の数字的なところはこちらです。2019年上半期もまとめてもらったので、どこかで出せるといいとは思ってるのですが、なかなか機会がなく。単純な数字でいうと、2019年半分で2018年一年分くらいにはなってます(プロジェクト数、売り上げなど)。
HoloLensの導入は手段であって目的ではありません。目的は業務の効率化であり、業務の効率化は線であって点ではありません。第二回で「自社の業務について「めちゃめちゃ考える」こと」と入れていますが、お客さん自身が自分たちの業務を考えること自体に意味があると感じています。実際にボトルネックはどこなのか?それはHoloLensでなければ解決できないのか?
MRPPのトレーニングで最初に言われたことは「Why? HoloLens?」でした。これは「なぜHoloLensでなければならないのか?」、「HoloLens以外の方法が最適ではないのか?」という問いに答えられるようにしなさいということです。これをお客さんとの会話の中で見つけ出さないといけません。なので、お客さんとの会話は大切で、もしHoloLens以外が最適であれば、HoloLens以外を選択するという提案をすることもあります。あくまでもぼくらの仕事はお客さんの業務の課題の解決なので。
業務課題の解決という意味では、点で見るとHoloLensが最適でも線で見るとHoloLens以外が最適なケースも往々にしてあります。ある業務ではHoloLensを使って改善ができるとしても、よくよくワークフローで話を聞くと、その前工程が実はボトルネックで、そこにはHoloLens以外の解決手段が適している場合があります。
なので仕様含めて丸投げされる場合は非常に厳しいですし効果も出にくいと考えています(これはHoloLensに限らないですが)。ぼくらは技術の提供はできますが、業務プロセスに関しては素人なので、そこはお客さん側でやってもらうこと。それをベースに技術的に解決することが自分たちの仕事と思っています。
とはいえ、多くのお客さんと話していると、課題は似ていたり、やりたいことが似ていることは多く、そういう共通項を見つけやすいことがお客さんと接している時間が長いことのメリットかなと思っています。
最近ちょっと考えてるのが、デジタルトランスフォーメーションだったり出社だったりというのは、技術ではなく文化(気持ち)の面が大きく作用するのかなと思っています。
たとえばデジタルトランスフォーメーションで紙をなくすといった場合に、いままで紙でやり取りしていたものが一切なくなるとして、それで業務が回るのか?という心配が変化を阻害するのではないかと思っています。
人間は変化を恐れるものなので、先に不安があると変化しない方を選択します。であれば、技術的な解決と並行して、心理的な不安を取り除くというなことも必要なんだろうなとぼんやり考えています。それをしないと表面上の導入に過ぎず、時間が経つともとに戻ってしまい、本当の意味での変革にはならないと思っています。
第三回にもありますが、個人的には今ビジネス向けVRをやりたいと思っています(諸々のリソースの関係でなかなか難しいのですが)。自分の中では昨今のスタンドアロンVRをVRとして見ていない節があり、HoloLensと同列に考えています。HoloLens、Mirage Solo、Oculus Go、Oculus Quest、それぞれ、性能、値段、機能によってメリット、デメリットがあり、それぞれ排他ではなく選択肢として考えると自分の中ではすっと入ってきたりします。HoloLens 2になり性能も似たようになったので性能的なひっかかりは少なくなると考えています。そういう意味ではWindows MR Immersiveのスタンドアロンが出てくれることを期待していたりします。
HoloLensは光学シースルーデバイスとして高性能ではありますが値段が高いことがとにかくネックになる。それに対してOculus Go、Oculus Questは10分の1程度に収まる。HoloLensでやっていることが必ずしもHoloLensでなくても良くてOculus Go、Oculus Questでも問題ない場合、単純にデバイス量で10倍は見込めます(ソフトウェアの費用は入れていませんが、そこは全体で調整すればいいのかなと思っています)。
第一回にある「米ウォルマートが従業員向けのVRトレーニングでOculus Goを17,000台購入」というのがありますが、ここまではいかなくてもまとまった台数の導入というのは非現実的なものではないかなと思っています。
]]>Unityアプリのソース管理ってどうしてますか?
— 中村 薫 (@kaorun55) 2019年1月30日
サブモジュール的な共通機能をどうやって管理してるのかわからん。
Unity プロジェクトを Git で管理している場合には、利用するモジュールは Git submodule を使って管理するというのが自然です。
しかし、Git submodule で利用したいリポジトリが通常の Unity プロジェクトの場合、 プロジェクトのルート直下は Assets, Packages, ProjectSettings などのフォルダになっているため、自分のプロジェクトの Assets 以下にそのまま入れられません。
例えば、MixedRealityToolkit-Unity だと以下のようなリポジトリ構成になっています。
自分の Unity プロジェクトの Assets フォルダに入れたいのは、MixedRealityToolkit-Unity の Assets 以下のフォルダです。
Git submodule で別のフォルダにクローンし、Assets 内にシンボリックリンクをはるという方法を使っています。
シンボリックリンク自体は Git の管理下に入れず、バッチファイルで作成しています。
はじめはシンボリックリンク自体も Git で管理しようとしたのですが、Git for Windows だとデフォルトではシンボリックリンクが有効にならないようなので、諦めました。
上記プロジェクトでは、Git Submodule で External フォルダに MixedRealityToolkit-Unity を入れています。
クローンした後、以下のバッチファイルを実行し、External 内のフォルダからプロジェクトの Assets フォルダ内へのシンボリックリンクをはります。
@echo off setlocal ENABLEDELAYEDEXPANSION cd /d %~dp0 set FOLDER_1=MixedRealityToolkit set FOLDER_2=MixedRealityToolkit.SDK set FOLDER_3=MixedRealityToolkit.Services set FOLDER_4=MixedRealityToolkit.Providers set FOLDER_5=MixedRealityToolkit.Examples set FOLDER_6=MixedRealityToolkit.Extensions set FOLDER_7=MixedRealityToolkit.Tools set i=1 :BEGIN call set f=%%FOLDER_!i!%% if defined f ( rem echo Create symbolic link !f! mklink /D ..\Assets\!f! ..\External\MixedRealityToolkit-Unity\Assets\!f! mklink ..\Assets\!f!.meta ..\External\MixedRealityToolkit-Unity\Assets\!f!.meta set /A i+=1 goto :BEGIN ) pause
また、.gitignore にシンボリックリンクのファイルを追記しておきます。
/Assets/MixedRealityToolkit /Assets/MixedRealityToolkit.meta /Assets/MixedRealityToolkit.Generated /Assets/MixedRealityToolkit.Generated.meta /Assets/MixedRealityToolkit.Examples /Assets/MixedRealityToolkit.Examples.meta /Assets/MixedRealityToolkit.Extensions /Assets/MixedRealityToolkit.Extensions.meta /Assets/MixedRealityToolkit.Providers /Assets/MixedRealityToolkit.Providers.meta /Assets/MixedRealityToolkit.SDK /Assets/MixedRealityToolkit.SDK.meta /Assets/MixedRealityToolkit.Services /Assets/MixedRealityToolkit.Services.meta /Assets/MixedRealityToolkit.Tools /Assets/MixedRealityToolkit.Tools.meta
バッチファイルをリポジトリに入れているので、クローン時の操作は以下のような手順になります。
> git clone git@github.com:HoloLabInc/LeapMotionInputForMRTK.git --recursive > LeapMotionInputForMRTK\External\createSymlink.bat
前本さんのブログでは、指定したフォルダだけをクローンするように Git submodule の設定をするという方法が紹介されています。
こちらも参考にしてみてください。
こんにちは、たるこすです。
LeapMotionInputForMRTK という、HoloLens(第一世代)と Leap Motion を使って HoloLens 2 のハンドインプットのシミュレーションができるものを作りました。
これにより、HoloLens 2 が無くても、HoloLens 2 のハンドトラッキングを利用したアプリの動作確認をすることができます。
コード、そして Leap Motion を HoloLens に取り付けるマウンタの3Dモデルは GitHub で公開しています。
2019年4月に MixedRealityToolkit-Unity (以下、MRTK) v2 RC1 が公開されました。
MRTK v2 は HoloLens 2 を含む、いくつかのデバイスをサポートしています。
MRTK v1 は HoloLens(第一世代)用のツールキットで、Head Gaze (頭の向き)がカーソルとなる入力方式でした。 MRTK v2 は、HoloLens 2 のハンド入力をサポートしているので、指先でボタンを押したり、手でものをつかんだりする UI が用意されています。
MRTK v2 の勉強を始めようと思ったのですが、2019年6月時点ではまだ HoloLens 2 を手に入れることができません。
HoloLens 2 がないと、ハンド入力の挙動確認がかなり難しいです。
(Unity Editor でマウスやキー入力でシミュレートすることは一応可能です)
そこで、HoloLens + Leap Motion でハンド入力の挙動確認をするために作りました。
アプリケーションは Unity Editor 上で実行し、Holographic Remoting を使って HoloLens で表示しています。
MRTK v2 の概要については、@Ash_Yin の資料が詳しいです。
この資料の P.37 で説明されている、MRTK.Providers 部分を拡張し、Leap Motion 用のスクリプトを追加しました。
詳しくは、コードを読んでいただくのがいいと思います。 github.com
自分は HoloLens で利用することしか考えていなかったのですが、de:code 2019 の Unity Technologies さんのブースで、 WinMR Immersive Headset + Leap Motion で LeapMotionInputForMRTK を使うデモが展示されていました!
twitter.comEXPOのUnityさんブースで@tarukosu さんのハンドジェスチャー体験しました。良かったです(*´ω`*) pic.twitter.com/NJA7KzNfWF
— だん (@arcsin16) 2019年5月29日
体験したところ、視野角が広く映像がキレイで、現実は見えないですが表示する映像としては HoloLens 2 により近い見た目でした。
HoloLens + Leap Motion の場合は、Holographic Remoting を使うためにどうしても見た目の質が下がってしまいます。
HoloLens 2 が待ちきれない! という方はぜひお試しください
]]>2019年4月24日に、Intel RealSense Japan Meetup が開催されました!
私は20分間の発表時間をいただいて、「現実世界コンピューティング RealSenseとロボットとHoloLens」というタイトルで話をしました。
簡単に言うと、Roomba や WHILL に RealSense T265 と D435i をくっつけて、自律移動できるようにしたという内容です。
さらに、移動の目標地点を HoloLens で設定することができます。
会場に WHILL を持ち込み、実機デモも行いました。無事動いてよかったです。
たるこす( @tarukosu )さんによる、現実世界コンピューティング。 realsense x ホロレンズ x #WHIILL 。なにこの未来。 #RealSense #TMCN #パーソルPT pic.twitter.com/XsRE6TusDn
— Seiya Shimizu (@Seiya_S) April 24, 2019
スライド中にもリンクを載せているデモ動画です。
RealSense T265 は2つの魚眼カメラとIMUで自己位置を認識できるデバイスなのですが、非常に使いやすかったです。
今回は、ロボットの位置を T265 でとれる値をそのまま信じて使いました。
ロボット自体のホイールオドメトリも利用していません。
より正確に自己位置を認識したい場合は、T265 の位置データと、別の Lidar などのセンサデータを使って SLAM するのが良い気がします。
第二回 Intel RealSense Japan Meetup も予定されているので、興味があるかたは是非ご参加ください!
]]>5/2, 3にマイクロソフトにより開催されたMixed Reality Dev Daysに参加してきました。
世界中から約400人が参加したそうです。
We’re excited to celebrate the announcement of the HoloLens 2 Developer Edition with almost 400 of our closest developer friends here on campus for #MRDevDays!https://t.co/Q7VK8y4i6q pic.twitter.com/bsr6Sc1qkC
— Mixed Reality DevRel Team (@MxdRealityDev) May 2, 2019
アジェンダは以下画像の通りで、同時間帯に複数のテクニカルセッションおよび、ハンズオンが行われました。
セッション情報については(全てではないかもしれませんが)後ほど公開されるとの話を聞いたため、5/2 A.M.の共通のセッション以外はすべてハンズオンに参加しました。
ハンズオンの内容は準備されたマニュアル通りにアプリを実装したりビルド・デプロイするものではなく、各机にHoloLens 2 が4台置いてありシェアしながら自由に使えるようになっていました。
なお、MRTKを利用したチュートリアルについては以下に公開されています。
チュートリアル
あくまで開発段階のものであるため画面のキャプチャを公開することは禁止されていました。 従い以降は、実機を使っておこなったことや感じたことのまとめになります。
主に行ったこととしては
全てのMRTKのサンプルを実機動作確認したかったのですが、時間とHoloLens 2 実機の台数が限られていたため、HoloLens 2 の大きな特徴であるHandTracking/EyeTrackingに絞って動作確認を行いました。 他にどのようなサンプルがあるのかについては以下にまとめています。
ハンズオンは以下環境で動作確認を行った。
現地で新しいMRTKが出ていることに気づいたので、パフォーマンスチェックのみ以下を利用した。
using System.Collections.Generic; using UnityEngine; using Microsoft.MixedReality.Toolkit.Input; using Microsoft.MixedReality.Toolkit.Utilities; public class PalmSample : MonoBehaviour, IMixedRealityHandJointHandler { /// <summary> /// 生成するオブジェクトのプレハブ /// </summary> [SerializeField] private GameObject pref; /// <summary> /// 掌の位置 /// </summary> private Vector3 palmPos; void Start() { palmPos = Vector3.zero; } public void ShowObject() { var camera = CameraCache.Main.transform; var ray = new Ray(camera.position, camera.rotation * Vector3.forward); var obj = Instantiate(pref); obj.transform.position = palmPos; obj.transform.LookAt(camera); obj.transform.Rotate(new Vector3(0, 180, 0)); Destroy(obj, 2); } public void OnHandJointsUpdated(InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData) { MixedRealityPose pose; eventData.InputData.TryGetValue(TrackedHandJoint.Palm, out pose); if (pose != null) { palmPos = new Vector3(pose.Position.x, pose.Position.y, pose.Position.z); } } }
FPS | HoloLens 1 | HoloLens 2 |
---|---|---|
60 | 6 | 15 |
50 | 20 | |
45 | 10 | |
40 | 30 | |
35 | 40 | |
30 | 60 | |
28 | 20 | |
20 | 100 | |
19 | 30 | |
15 | 40 | |
13 | 200 | |
10 | 60 | |
08 | 300 | |
06 | 100 | 400 |
05 | 130 | 500 |
03 | 200 | |
02 | 300 | |
01 | 400 | |
01 | 500 |
※HoloLens 2 では数値が安定しなかったのでおおよその目安、またHoloLens 2 の状態や製品版ではパフォーマンスが変わる可能性があるのであくまで参考情報です
ちょうど公開されたようです。
良くも悪くも今まで通り。Intel RealSense D435に近い印象。 現状ではCのSDKしかないので差別要因も不明。C#のSDKが出たらCognitiveとの連携などは簡単にできるようになるはず(ただ、それはRealSenseでもできるので、決定的な差別化要因にはならないと思う)。
単体であればIntel RealSense D435、複数台であれば日立LGのToFセンサーとの比較が必要になると思う。
セットされていた環境はUSB-C to Aのデータケーブルと、USBの電源ケーブルでした。USB-Cでバスパワーできないものどうなんだろう?と思ったので、HoloLens 2のUSB-Cケーブルを拝借してKinectに接続してみたところ、USB-Cケーブル1本のみで接続できました。
Azure Kinect DKの全体観についてはこちらでまとめていますので合わせてどうぞ。
]]>
今回、MRCなど画面の投稿は禁止されているので、見た目については想像にて補完ください。
確かにかぶりやすい。 フリップアップもじゃまにならず、そのままコードを書いているとつけてることを忘れるほど。ただ、前に出っ張るので、壁とかにあてそう。動く機構がついたので、全体的にはHoloLens 1よりも扱いに気を付けないといけない気がします。
ここから
この #HoloLens 2 ハンズオンをやる前の「準備編」はこちらです。
— Madoka 🇺🇸4/27-5/8(水)米国なう (@chomado) 2019年4月29日
ー
Install the toolshttps://t.co/rImJFhjQuP
ー
とくに MRTK のバージョンや Unity のバージョン、また「Windows 10 SDK 10.0.18362.0 or later」ってのが重要
ついに! #HoloLens 2 の公式ハンズオン資料が公開されました!
— Madoka 🇺🇸4/27-5/8(水)米国なう (@chomado) 2019年4月29日
実機が無くてもエミュレータで開発ができます。
第1話:HoloLens 2 ハローワールドhttps://t.co/lNZ8NjG1rD
第2話:UI, ハンドトラッキング, 新しいMRTK構成https://t.co/jdRvijRC2p
第3話以降も(PC閲覧時)左のメニューから辿れます
開発環境はこちらを参照してください。 前提として、CPUが変わったのでアプリはARMまたはARM64でビルドしないと動作しません。エミュレーターはx86で動作環境がことなるのでネイティブプラグインなどは注意してください。
Getting your app ready for HoloLens 2 - Mixed Reality | Microsoft Docs
Unityは2018.3および2019.1がサポートされています。 Unity 2019.1を使用した場合の違いはARMおよびARM64でのビルドが可能(2018ではARMのみ可能)、LI2CPPビルドのみ可能(.NETビルドは不可)
項目 | Unity 2018 | Unity 2019 |
---|---|---|
プラットフォーム | ARM | ARM, ARM64 |
対応ビルド | .NET, IL2CPP | LI2CPP |
Visual Studioは2017が推奨されていますが、Visual Studio 2019でもビルド可能です。ARM64ビルドはVisual Studio 2019でのみ可能となります。
既存のHoloLens 1アプリをHoloLens 2に移植する。 最初はかなり多いシナリオかと思います。今回はホロラボで開発したものを中心に4つほどHoloLens 2化しました。
Lenovo C630のようなPCのWindows 10 on ARM環境では、x86(Win32)でビルドした実行ファイルがそのまま動作します。 これはWindows 10 on ARM環境でx86のエミューレーションを行っており、本来はCPUアーキテクチャが異なるため実行できないx86の実行ファイルをARM環境で動作させることができます。なお、x86エミュレーションは32bitアプリのみでx64のような64bitアプリのエミュレーションはできません。
この機能はHoloLens 2にはないようで、x86でビルドしたアプリの配置や、パッケージのインストールはエラートなります。 そのため、既存のHoloLens 1アプリをHoloLens 2で実行させる場合は、ARMでビルドをし直す必要があります。
おおよそ2倍ほど性能あがってる可能性があります。
ARM(32bit)、ARM64(64bit)にかかわらず、アプリから使用できるメモリ量は2GBのようです。
開発機なので今後の改善に期待という前提で微妙な点
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
・SLAMのトラッキング精度
・色ムラ
・表示密度
・ハンドトラッキング
このくらい
少し広めに認識してました。
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
正面見た状態でキーボードのあたりの手は認識してます。という位置関係は追えるみたいです。 https://t.co/GylOVHSkQw
このあたりが限界? pic.twitter.com/jd8IzVgqDw
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
思った以上に自然にできた
そういう意味では視線に合わせてスクロールします(顔は動かさずに)。
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
MRCの投稿が禁止されてるので正確にお伝え出来ないのがツライのですが、このサンプルで地図の端をみると地図がするクロースする動作をしました。https://t.co/vu4pH8iSx5
Unity 2019 + MRTK v2 + ARM64でのビルドは一応実機動作まではOK
Unity 2019 + MRTK v2 + ARM64で動作確認できた#MRDevDays https://t.co/5Rx5EpuNFj
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
リサーチモードのみ
Depthへのアクセスはv1同様にリサーチモードからのみとのことです。 https://t.co/dMv5rBeiXf
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
持っているらしいけど、ドライバのインストールができないので、その制約がクリアできれば使えそう
ホストは持ってるそうです。ドライバがなんとかなればという感じみたいです。 https://t.co/UzxXErnnSR
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
現状、Hololens 2側のアプリがないためできない
[1]について、現状ではHoloLens側のRemotingアプリがないので動かせかったです。 https://t.co/S2aRtPz5Zu
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
HoloLens 1と同様に可能
]]>[2]について。
— 中村 薫(Kaoru Nakamura) (@kaorun55) 2019年5月3日
・MRCはv1同様にありました(Device Portalがv1とほぼ同じ)
・Miracastの安定性と速度がv1と比べてかなり上がってるようです(PCの接続アプリで確認)#MRDevDays https://t.co/S2aRtPz5Zu
今回は x64 Windows マシンの VisualStudio 2019 で UWP アプリを ARM64 向けにビルドし、 それを ARM64 マシンで実行してリモートデバッグする方法を紹介します。
「設定」アプリの「更新とセキュリティ > 開発者向け」ページで「開発者モード」を選択します。
さらに、同じページの「デバイスの検出 > デバイスがUSB接続とローカルネットワークに表示されるようにします」を ON にします。
「Remote Tools for Visual Studio 2019」は Visual Studio がインストールされていない環境でリモートデバッグを実行するためのツールです。
以下のページからインストーラをダウンロードできます。
ARM64 を選択し、ダウンロードボタンを押します。
インストールすると、 Remote Debugger というアプリがインストールされます。 これを起動しておくと、別マシンからリモートデバッグできる状態となります。
Visual Studio 2019 で UWP アプリケーションプロジェクトを作成します。
上部のメニューのソリューションプラットフォームで ARM64 を選択します。
次に、プロジェクトのプロパティページを表示します。
表示方法は、メニューの「デバッグ > (プロジェクト名) のプロパティ」をクリックするか、ソリューションエクスプローラーでプロジェクトを右クリックして「プロパティ」をクリックするかです。
「デバッグ」のページでターゲットデバイスを「リモートコンピューター」に設定し、リモートコンピューターの IP アドレスを入力します。 また、認証モードを「ユニバーサル(暗号化されていないプロトコル)」に設定します。
デバッグ実行を開始すると、初回のみ PIN 番号が求められます。
リモートデバッグマシンで 「設定」アプリの「更新とセキュリティ > 開発者向け」ページで「デバイスの検出 > ペアリング」ボタンを押すと、PIN番号が表示されます。
これをビルドマシンに入力するとペアリングが行われ、リモートデバッグが可能になります。
デバッグ実行すると、アプリケーションがリモートコンピューターで起動します。
ローカルで実行するときと同様に、コードにブレイクポイントをはってデバッグできます。
Unity で作る UWP アプリケーションを ARM64 対応する方法については、アキヒロさんがブログを書かれているのでそちらをご覧ください。
]]>beta2で確認したデモシーンは以下。 www.hiromukato.com
EyeTracking
mrtk_eyes_00_RootScene
アイトラッキングの他のサンプル(02~05)の親シーン
mrtk_eyes_01_BasicSetup
アイトラッキングを行うための最小設定のシーン
mrtk_eyes_02_TargetSelection
アイゲイズと選択(エアタップまたは音声コマンド)で宝石を破壊するサンプル
mrtk_eyes_03_Navigation
アイゲイズとスクロール、パン、ズームイン/アウトのサンプル
mrtk_eyes_04_TargetPositioning
目とハンドまたはボイスによるオブジェクトの選択、移動を行うサンプル
mrtk_eyes_05_Visualizer
アイトラッキングデータをビジュアライズするサンプル
Gltf
Glb-Loading-Demo
Glbの読み込みサンプル(エラーが出たためMain CameraのStandaloneImputModuleコンポーネントを削除してMixedRealityInputModuleコンポーネントを追加)
Gltf-Loading-Demo
Gltfの読み込みサンプル(エラーが出たためMain CameraのStandaloneImputModuleコンポーネントを削除してMixedRealityInputModuleコンポーネントを追加)
HandTracking
HandInteractionExamples
ハンドトラッキングと様々なインタラクションタイプのサンプル
HandInteractionGestureEventsExample
ハンド操作によるホールド、マニピュレーション、ナビゲーションのサンプル
HandInteractionPanZoomExample
ハンド操作によるパン、ズームのサンプル
HandInteractionUnityUIExample
ハンド操作によるUnity UIのインタラクションサンプル
まずは、公式のサンプルプロジェクトを動かすところから試してみました。
公式ドキュメントはこちらです。
まず、GitHub の gRPC リポジトリをクローンします。
$ git clone -b v1.19.0 https://github.com/grpc/grpc
クローンした grpc フォルダの中にある examples\csharp\Helloworld\Greeter.sln
を Visual Studio で開きます。
Greeter, GreeterClient, GreeterServer という3つのプロジェクトが含まれていました。
GreeterClient と GreeterServer をそれぞれ実行します。
ただし、自分の環境ではそれぞれのプロジェクトにある Program.cs で指定されているポート番号を変更する必要がありました。
詳しいことは良くわからないのですが、デフォルトで指定されている 50051 ポートは Windows では何かの用途で確保されていて使えないようです。
参考: https://support.microsoft.com/en-us/help/4093046/ports-blocked-after-you-install-monthly-rollup-package-kb4074588
今回はポート番号を10051に変更して動作させました。
GreeterServer
GreeterClient
以下はサンプルコードから抜粋したコードです。
サーバ側のコード
クライアント側のコード
クライアント側では Name に "you" を代入した HelloRequest メッセージを作成し、SayHello メソッドを呼んでいます。
サーバ側では、Message に "Hello " + request.Name (ここでは "Hello you")を代入した HelloReply メッセージを返します。
クライアント側で HelloReply の Message を表示すると、"Hello you" が表示されます。
.proto ファイルは Protocol Buffers(プロトコルバッファ)のメッセージ構造を記述するものです。
gRPC は Protocl Buffers を使っていて、.proto ファイルでRPCのメソッドやメッセージ型を定義します。
サンプルプログラムでは、以下のような定義になっています。
記法を知らなくても、なんとなく以下のような定義が読み取れます。
この proto ファイルによる定義から、各言語(今回はC#)用のスクリプトが自動生成されます。
今回は gRPC の C# サンプルプログラムを動かしてみました。
次回は、空の UWP プロジェクトから gRPC クライアントを作成し、このサンプルプログラムと通信できるようにしようと思います。
We often get asked the same old beginner questions... Does Unity support dogs? How do I make a dog? etc. If people would just read the documentation once in a while you'd know we have built-in support since 2015, right there in the menu. Read the docs here https://t.co/GGk3Xk5tyz pic.twitter.com/ojSH7MEZO3
— UnityDocs (@UnityDocs) April 1, 2019
なぜ猫ではなく犬なのか。
勢いだけで作りました。後悔はしていません。
犬しかないのは許せないのでねこちゃん版もつくりました pic.twitter.com/OgWy76qFak
— ヒロム(Hiromu) (@hi_rom_) April 2, 2019
作成方法は、
犬のメッシュをFBXでエクスポート
Mayaで犬から猫に手作業で修正
objでエクスポートしたものをいい感じに編集してCSに張り付け
MRTK V2が正式リリースされるとまたやり方が変わると思いますが、MRTKに対応したHoloLensWithOpenCVForUnityExampleのunitypackageを入れるぐらいではないかと予想しています。
ロードマップによるとMRTK V2は2019年7月にリリース予定です。
Unityのプロジェクトを作成し、HoloToolkit-Unity-2017.4.3.0をインポートする
github.com
メニューの Mixed Reality Toolkit -> Configure -> Apply Mixed Reality Project Settings を選択し Apply する
メニューの Mixed Reality Toolkit -> Configure -> Apply Mixed Reality Scene Settings を選択し Apply する
メニューの Mixed Reality Toolkit -> Configure -> Apply UWP Capability Settings を選択し Webcamにチェックをいれて(他は必要に応じてチェックをいれ) Apply する
メニューの Build Settings... を選択し、Player Settings を選択する
Other Settings の Scripting Backend を IL2CPPにし、Api Compatibility Levelを .NET Standard 2.0にする(.NET 4.xでも動作すると思います)
OpenCV for Unityをインポートする
assetstore.unity.com
メニューの Tools -> OpenCV for Unity -> Set Plugin Import Settings を選択する(処理が終わるとConsoleにSetPluginImportSettings Success ...というメッセージが表示されます)
OpenCVForUnity配下のStreamingAssetsフォルダをAssets直下に移動する
HoloLensCameraStream v0.3.0-betaをインポートする
github.com
API Update Required ダイアログが表示された場合は I Made a Backup, Go Ahead! を選択する
Assets/CamStream/Plugins/WSA/HoloLensCameraStream を選択し、Inspector の Platform settings -> ScriptingBackend を Il2Cpp に変更し Apply ボタンを押す
HoloLensWithOpenCVForUnityExample_v1.0.2 をインポートする
github.com
メニューの Build Settings... を選択し、Scenes In Build に 以下のシーンを追加する
以上でプロジェクト設定は終了です。 (Build Settings の Build ボタンを押したところ、ビルドが終了するのに20分以上はかかりました)
HoloLensにデプロイすることで動作確認することができます。
HoloLensPhotoCaptureExample
HoloLensComicFilterExample
]]>シーンを実行すると以下のような表示になります。fpsと使用メモリ、ピークメモリ、最大メモリが表示されています。
シーン起動時のHierarchyは以下のようになっています。
SceneDescriptionPanel 配下はただの説明パネル用のオブジェクトなので、実質 SceneContent 一つだけががメインのオブジェクトになります。
SceneContentのInspectorを見ると
の2つのコンポーネントが付いています。
以下それぞれの詳細を見ていきます。
ソースはシンプルな内容となっており、 Diagnostics/Profilerの表示・非表示をトグルで切り替えるためのメソッドがあるだけです。
音声コマンドで先ほどの2つのトグル動作を実現しています。
ここで 「Toggle Profile」、「Toggle Diagnostics」の2つの音声コマンドがKeywordとし登録されていますが、シーン内にはこれらのワードは登録されていません。どこで登録されているのかを探したところ、DefaultMixedRealitySpeechCommandsProfile に登録されていました。
Profileは継承関係を辿るとScriptableObjectから派生したものであることが分かるので、一度作成してしまえば使いまわしができて便利そうです。
<継承関係>
Diagnostics Systemはコアシステムとして実装されているので、プロファイラを有効にすることでいつでも表示できるようになります。 アプリケーションのfps、メモリ使用量が特別な実装を必要とせずに確認できるのでお手軽にパフォーマンスチェックができて便利だと思います。 HoloToolkitではFPSDisplayというPrefabを利用して実行時にFPSを確認することが多かったと思いますが、MRTKv2ではDiagnostics Systemを利用することになりそうです。
MRTKに組み込まれている診断システムは VisualProfiler-Unity を組み込んだもののようです。
]]>Photoshopまでやって満足していましたが、最近Houdiniを触り始めたのでとりあえずやっておきました。
Houdiniの使い方がだんだん分かり始めてきました。 #Houdini pic.twitter.com/zJhdvt0F0o
— ヒロム(Hiromu) (@hi_rom_) 2019年3月26日
UIの作り方については以下を参照しました。 qiita.com
簡単に手順をまとめておくと、
Python Panelを選択
New Interfaceを選択
Name, Labelを任意の内容に変更し、SAMPLE CODEと書かれている部分以降にPythonの実装をする
Tabbarに表示したい場合は、Toolbar Menuタブで右側に移動する
Pane Tabに表示したい場合は、Toolbar Menuタブで右側に移動する
スクリプトは以下に公開しています。
]]>こんにちは、たるこすです。
2018年10月に開催された Hacktoberfest というイベントに参加し、T シャツを貰いました。
Hacktoberfest は Hack, October, Festival を組み合わせた言葉で、OSS のお祭りです。
本家のイベントは DigitalOcean 社によって開催されているもので、10月中に GitHub で公開されている OSS に PR(Pull Request) を5つ送るとTシャツがもらえるというものです。 hacktoberfest.digitalocean.com
今回私が参加したのは Microsoft が開催した Hacktoberfest イベントで、10月中に Microsoft が公開している OSS に PR を1件送ればTシャツがもらえるというものでした。 cloudblogs.microsoft.com
HoloLens 用のライブラリである、MixedRealityToolkit-Unity に Pull Request を送りました。
HoloLens がオブジェクトに近づいたときに Stabilization Plane がカメラの近くにきてしまい描画が不安定になる問題があったので、Stabilization Plane の最小距離をカメラの NearClip の距離にするという内容です。
「コメントが来たらちゃんと答えられるかな...」とドキドキしていたのですが、特に何のコメントもなくマージされました。
2019/1/4 に Tシャツが届きました!
GitHub の vscode のリポジトリのページがイラストとして描かれています。
今年も Hacktoberfest が開催されるようであれば、是非参加したいと思います!
]]>
実演中、手順の中で「なぜここはこうしているの?」「私だったらこうするんだけどな」というような質問や意見が飛び交い、 活発に議論をしていました。(研究室のゼミのような雰囲気でしたw)
スライドにあること以外でも、例えば、以下のようなことについて議論しました。
本来、マーカーに用いる画像の選定などはVuforia公式のガイドラインに沿うのが良いと思います。
ただ、QRコードをしばしば用いたりする理由としては、
といった理由が挙げられました。もちろん、ロゴなどの画像を用いる場合、よりコンテンツとして現実を意識したものになるため、QRコードが必ずしもコンテンツにとって最適解というわけではありません。
作業を進めるなか、マーカーを大きめにして印刷した場合どうなるか?といった検証を行いたいことがあるようです(Unity内)。 この場合、inspectorにて、ImageTargetのScaleやImageTarget BehaviorのAdvancedオプションの値を変更すればよい。ただ、これはあくまでサッと検証したい場合での応急措置であり、製作する場合はきちんとマーカーの設定からやり直したほうがよいという結論に至りました。
使いたいマーカーの画像サイズは、縦横比が1:1になっていない場合があります。この場合、VuforiaサイトのTargetManagerにて画像サイズを登録する場合、widthには何の値を入力すれば良いか、ということが議論になりました。
回答としては、縦長であろうと横長であろうと、登録する画像の横幅を入力すれば良い。。。のですが、 ARコンテンツを作成する際の手順を踏まえながら考えるのがより良いと考えます。
というのは、コンテンツを作成する際、ユーザーはどこから入ってきて、どのようにマーカーを見て、どのようにオブジェクトやエフェクトを表示するか、という演出を事前に考えるはずです。そして、「登録する画像の横幅」というのは、ユーザーがマーカーを見るときの向きを考慮したうえで、画像をを作成・登録し、その画像を印刷した時の横幅を入力するのが良いのではないかと考えます。
VuforiaをUnityで使用する際、いくつかの手順を踏んでコンテンツを作ることになります。今回、社内での知見共有会にて議論した結果、新たに気をつけなくてはいけないポイントや、人によって手順や考えが異なる点(小さい違いではあるものの)などがあることが分かりました。そういった点を社内で共有することで、同じ技術を同じ期待値で製作することができるのではないか、とも考えられます。今後も、Vuforiaだけでなく、他の技術についても共有していきたいです。
]]>登壇含めて会社ブログの方には書いてたんですが、個人の活動は個人のブログの方に書いた方がいいかなぁと思ったりしました。
まぁ、会社運営も含めてやりながらいい方法を探していくしかないんですが。
ドメインも含めて変えようかな。
一年通しで無事終わりました。まぁ昨年も登記が1/18なのでほぼ1年ではあるんですが、11月決算なので年度としても丸一年ということで。
www.slideshare.net
今年どういう視点で仕事をしていたかというのは上記スライドを見てもらえればと思います。ホロラボはスタートアップではなくスモールビジネスなので、売り上げはきちんと立ってますがもうひと頑張りというところですね。そこには来年に向けての仕込みも入っているので、それがきちんと芽が出るかというのはドキドキではあります。
今年は人が増えて色々と規模も大きくなってきたのでだいぶバタバタしています。お金の規模、人の人数、仕事の規模とそれぞれステップが変わった感じがするので、それぞれをバランスするために考えることが多くてなかなか大変です。がそれも楽しかったりします(お金大事、人大事、仕事大事)。安直な言葉でいうと学びが多かったんですが、考えて実践してふりかえってをひたすら繰り返していました。伊藤さん含めてたくさんの人に助けてもらって、お客さん含めてたくさん迷惑をかけつつ、なんとか乗り切った感じです。まぁ実際にはこんなとことに書けることは上っ面でしかないのですがw
スライドにない部分で去年との変化としては、製造業系が増えた、いわゆる日本の大手メーカーが動いている、東京以外のお客さんが増えた。というところがあります。内容も検証段階とは言え1件1件がとても重い(ヘビーなほう)ので、実務メンバーには結構な負担になってる反面、それをこなす強力なメンバーに恵まれたという実感があります。こういうのはWebにあまり出ない部分なので、露出されるころにはだいぶ世界は変わった後なのかなと。そういう意味でTwitterやWebで見えてるHoloLens界隈の視界と、社内(というか自分かな)から見えるHoloLens界隈の視界はだいぶ違うんじゃないかなと思っています。
とりあえず2年間走ってふりかえって見ると、会社としての価値というものが意外といろいろなところに出始めてるとは感じています。といういう価値の部分をお金に換えて社員のみんなに還元できるとようにするのが今の自分の仕事なんだろうなとは思います。あとは立ち位置、期待値など面白い位置にいるのですが、そのぶん成果を出し続けないといけないので、それ自体も良くも悪くもなんでしょうね(当初のゆるふわな部分もあれば、そうでない部分もある)。
自分の仕事といえば、最近は雑談するのが仕事になってる面もあって、社員と雑談、お客さんと雑談などなど。どんなに技術が進歩しても対面での会話には勝てないと思うのは、そういうのがあったりします。0か1ではなく程度の問題なので、目的、用途、制約など、さまざまな条件には当然よるのですが。
まぁどうなるか分からないので変わらず走りながら考えるしかないですね。仕込みはいろいろしてますが、どれが当たるかわからないので弾は多く作っておくくらいしかないですね。とはいえ、発散しつつも収束するようになってくるとは思うので、変わらず面白い立ち位置には居られるんじゃないかなと思ってます。
自分の仕事的にはオフロードを心がけてみます。もうちょっと手を動かせる時間を作りたいなと。定期的に社内で議題に出しつつ答えが出てないのですが、いまやってることは営業も、マネジメントも、もちろん開発も手を動かして技術を理解してないと難しいんじゃないかと思っています(自分がそうだからってことで解はないのですが)。とにかく知識と技術は更新しておかないと。
平日が忙しすぎてCoder Dojoにすっかり行けなくなってしまいました。会社が落ち着くまではしょうがないかなぁと思ってます。。。
出張や打ち合わせが多くてあまり家にいられないのもちょっとなぁとは思いますが、これも会社が落ち着くまではしょうがないかぁと思ってます。。。
健康診断の結果もアレだったのですが、これも会社が落ち着くまではしょうがないかぁと思ってます(とりあえず平日の夜家にいるときのお酒はやめましたw)。。。
まぁ、しばらくは時間の大半は会社に振り分けですね。
]]>
akihiroさん(@akihiro01051)のHololens上でのwindowsML画像認識デモを
RS5で動かす時のメモです。
akihiro-document.azurewebsites.net
RS5への変更に伴い、windows MLの名前空間は以下のようにPreviewが除かれました。
Windows.AI.MachineLearning.Preview → Windows.AI.MachineLearning
そして、コード面でもいくつか変更点があったようです。
- Windows 10 Insider Preview 17763.1
- Windows 10 SDK Insider Preview 17763
- Visual Studio 2017
- Unity 2017.4.12f1
- Hololens RS5 preview 17720
まず、以下のリンクのリポジトリからWindows-Machine-LearningのサンプルをCloneします。
https://github.com/Microsoft/Windows-Machine-Learning
また、Windows-Machine-Learning\Samples\SqueezeNetObjectDetection\UWP\cs\Assets 以下にある
- model.onnx
- Labels.json
の二つのファイルを確保しておいてください。
次に、本記事冒頭で述べたakihiroさんのプロジェクトをCloneします。
GitHub - akihiro0105/WindowsMLDemo_HoloLens_Unity: This Repository is WindowsML demo(ObjectDetection) with Unity in HoloLens
その後、確保しておいた二つのファイルを、Assets\StreamingAssets 以下に置いてください。
(Labels.jsonは上書きで構いません。また、元のSqueezeNet.onnxは削除して大丈夫です。)
そして、Unityからプロジェクトをビルドし、生成されたvisual studioプロジェクトの
WindowsML_Demo.csを変更していきます
・ 10行目 using参照を変更します。
//using Windows.AI.MachineLearning.Preview; //削除 //追加 using Windows.AI.MachineLearning;
・ 28行目ファイル名を変更します。
SqueezeNet.onnx → model.onnx
・67行目 Previewを外します。
//private LearningModelPreview _model = null; //削除 //追加 private LearningModel _model = null;
・68, 69行目 この辺がsessionに統一され、使いやすくなった感じはあります。
//private ImageVariableDescriptorPreview _inputImageDescription; //削除 //private TensorVariableDescriptorPreview _outputTensorDescription; //削除 //追加 private LearningModelSession _session = null;
・97行目 SqueezeNet.onnx → model.onnx
・98行目Previewを外します。
//_model = await LearningModelPreview.LoadModelFromStorageFileAsync(modelFile); //削除 //追加 _model = await LearningModel.LoadFromStorageFileAsync(modelFile);
・100~103行目 sessionに統一され、コードもすっきり書くことができます。
//削除 //List<ILearningModelVariableDescriptorPreview> inputFeatures = _model.Description.InputFeatures.ToList(); //List<ILearningModelVariableDescriptorPreview> outputFeatures = _model.Description.OutputFeatures.ToList(); //_inputImageDescription = inputFeatures.FirstOrDefault(feature => feature.ModelFeatureKind == LearningModelFeatureKindPreview.Image) as ImageVariableDescriptorPreview; //_outputTensorDescription = outputFeatures.FirstOrDefault(feature => feature.ModelFeatureKind == LearningModelFeatureKindPreview.Tensor) as TensorVariableDescriptorPreview; //追加 _session = new LearningModelSession(_model, new LearningModelDevice(LearningModelDeviceKind.Default));
・146~148行目
// WindowsMLに入力,出力形式を設定する //削除 //LearningModelBindingPreview binding = new LearningModelBindingPreview(_model as LearningModelPreview); //binding.Bind(_inputImageDescription.Name, inputFrame); //binding.Bind(_outputTensorDescription.Name, _outputVariableList); //追加 LearningModelBinding binding = new LearningModelBinding(_session); ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputFrame); binding.Bind("data_0", imageTensor);
・151~152行目
// Process the frame with the model //削除 //LearningModelEvaluationResultPreview results = await _model.EvaluateAsync(binding, "test"); //List<float> resultProbabilities = results.Outputs[_outputTensorDescription.Name] as List<float>; //追加 var results = await _session.EvaluateAsync(binding, ""); var resultTensor = results.Outputs["softmaxout_1"] as TensorFloat; var resultVector = resultTensor.GetAsVectorView();
・157, 164行目 resultProbabilities → resultVector
結果としては以下のような動画になります。
画面に近づいた時には猫が、 ノートPCを写している時はノートPCとして認識されているのがわかるかと思います。
最後にブルームしたときのUIは、RS5ならではのUIです。
youtu.be
また、猫の画像はこちらを使用させていただきました。
・Hololens RS5でakihiroさん(@akihiro01051)のwindowsML画像認識デモを動かした
・その際の変更点などを示した
2018/09/29 にびっくりするアナウンスがありました!
Microsoft が Robot Operating System [ROS1] for Windows の試験的リリースを発表したのです!
ROS を知らない方向けに簡単に説明すると、ROS はロボット用のフレームワークで、主に研究用として世界中で幅広く使われています。
早速インストールしてみます。
以下のページに書かれている手順でバイナリインストールを実行します。
https://github.com/ms-iot/ROSOnWindows/blob/master/GettingStarted/Setup.md
まだ試験的なリリースのため、インストールの方法もまた変わってしまうと思うので、ここでは実行結果だけご紹介します。
コマンドプロンプトを開き、以下のように PATH の設定と setup.bat を実行します。
> set PATH=C:\opt\rosdeps\x64\bin;%PATH% > C:\opt\ros\melodic\x64\setup.bat
毎回実行するのは面倒なので、以下のようなバッチファイルを作って実行するといいと思います。
set PATH=C:\opt\rosdeps\x64\bin;%PATH% call C:\opt\ros\melodic\x64\setup.bat
roscore と rospy_tutorials の talker, listener を実行してみました。
talker が値を Publish し、listener が Subscribe して表示します。
ROS 版 Hello World と言える、talker, listener が無事動きました。
2018/9/30 時点では、ROS のすべてが Windows で動くわけではありません。 対応状況は以下のページに書かれています。
個人的には、ROS# に期待しています。
UWP や WPF などの Windows アプリで ROS が使えたり、Unity での 2D/3D アプリや VR アプリで ROS が使えたりすると、かなり出来ることが増えるので楽しみです。
こんにちは、たるこすです。
みなさん、交通費申請していますか?
私が所属している株式会社ホロラボでは、毎月 Google スプレッドシートに1か月分の交通経路と交通費を記入して申請することになっています。
ですが、毎日オフィスに行くわけではないので定期券を持っておらず、オフィスに行った場合も含めて交通費を記入しないといけないため、
毎月結構な量になってしまいます。
この作業が面倒だったので、Suica などの交通系 IC カードの履歴を読み取り、自動的に Google スプレッドシートに記入するシステム「にゃーん」を開発しました。
Suica の履歴を読み取って、自動的に Google スプレッドシートに交通費を書き込むシステム「にゃーん」が完成しました!
— たるこす (@tarukosu) 2018年7月19日
ソースコードはそのうち公開します🐱 pic.twitter.com/ROuEmKSuFT
「にゃーん」の仕組みですが、は大きく分けると以下の2つからなっています。
Suica の履歴を読み取る部分はえむにわさんのコードを利用させていただきました。
履歴として読み取れるのは直近20件の利用データです。
このデータに含まれているのは利用金額ではなくその地点での残高のため、前後2件のデータから利用金額を求めています。
また、読み取れる履歴には電車やバスなどの交通費だけでなくチャージやコンビニ等の支払い履歴も含まれていますが、
交通費だけのデータだけをスプレッドシートに書き込むようにしています。
交通費を書きこむスプレッドシートは、テンプレートとなるシートを用意しておいてそれを人ごと月ごとにコピーするようにしています。
スプレッドシートに重複してデータを書き込んでしまってはいけないので、
履歴データに含まれる ID(履歴ごとに1ずつ増えていく番号)を使ってまだ書き込まれていないデータのみを書き込むようにしています。
どの ID までを書き込んだかという情報は、交通費のシートとは別のスプレッドシートに書き込んでいます。
スプレッドシートへのデータの書き込みは、Google Spread Sheet API を使って行っています。 また、フォルダの作成や交通費申請シートのテンプレートのコピーは Google Drive API を使っています。
ソースコードは Github で公開しています。 github.com
セットアップ方法も Github のページに記載しています。
いくつか機材が必要にはなりますが、是非試してみてください。
セットアップに関する不明点は、Github の方に issue としてあげていただければと思います。
私は以下の機材を利用しました。
Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Clear)-Physical Computing Lab
ソニー SONY 非接触ICカードリーダー/ライター PaSoRi RC-S380
iBUFFALO PC用スピーカー USB電源 ブラック BSSP29UBK
みなさんからの「作ってみたよ」という報告をお待ちしています!
]]>OpenCVforUnityのサンプルを利用します。
(ライセンス関係に抵触する可能性があるため、ソースコードを用いた説明は省きます。)
(また、ある程度OpenCVを知っていることを前提とします。Mat形式とか。)
具体的には、Hololensのカメラ画像をOpenCVforUnityで加工して透過表示するサンプルとして、
OpenCVforUnityのHoloLensComicFilterExample.csを編集していきます。
まずは、以下の動画をご覧ください。
Comic Filter Sample of OpenCVforUnity with HoloLens
少しわかりづらいかもしれませんが、
視線のある一定範囲に漫画の線が重なるような表示が透過されているのが確認できます。
このように、Hololensのカメラ映像をOpenCVforUnityで加工して、透過表示することができます。
次に、HoloLensComicFilterExample.csを編集し、
カメラ画像の特徴量を表示するように変更します。以下の動画をご覧ください。
ORB Feature Visualization Test of OpenCVforUnity with HoloLens
コミックフィルターをかける代わりに、
ORB特徴量として複数の小さい円が表示されているのが確認できます。
(右の画像は、静止画でORB特徴を算出した例です。)
これは、HoloLensComicFilterExample.csのOnFrameMatAcquired関数を変更しています。
流れを説明する前に、ちょっとポイントがあります。 これらのサンプルでは、実際のカメラの範囲より少し狭めになるよう、表示する画像を変換しています。 (変換部分をわかりやすくするため、処理を軽くするため等が考えられます。)
そのとき、カメラのサイズそのままの画像加工用のdstMat、
少し狭めの表示領域となるdstMatClippingROIがあります。
確認が取れていないので、推測になりますが....
dstMatClippingROIは、その表示領域部分のみdstMatのメモリを参照しています。(のはず)
つまり、dstMatClippingROIのみ加工し、dstMatごと、テクスチャに貼るMatへコピーするという流れになります。
(ちょっと自信ない)
そして、以下がOnFrameMatAcquired関数での流れとなります。
① Hololensカメラ画像 → 変数bgraMat (BGRA32形式のMatデータ)として受け取る
② 変数bgraMatを表示サイズへ変換
(Mat bgraMatClipROI = new Mat(bgraMat, processingAreaRect);)
③ bgraMatClipROI → dstMatClippingROI (この時にしたい処理をする。今回は特徴量表示。)
④ dstMat → bgraMatへコピー
私のリポジトリは現在メンテナンスしていません。
ROS# を UWP で使いたい場合は、公式の README にも記載されている以下のリポジトリを使ってみてください。
こんにちは、たるこすです。
シーメンスが公開している ROS# という OSS を UWP 対応させました。
オリジナルのリポジトリはこちら github.com
UWP 対応させたものはこちらです。 github.com
ROS# は Unity アプリから ROS のトピックをやりとりするためのライブラリです。
URDF のロボットモデルから Unity の GameObject を作成するツールも入っています。
ROS のトピックをやりとりする仕組みですが、Unity 上で ROS が 動くというわけではなく、rosbridge を利用しています。
rosbridge というのは、ROS を利用できない環境 (Webページ, Windows など)から ROS を使えるようにするため、JSON 形式で データを中継してくれる仕組みです。通信方式は Websocket, TCP, UDP がサポートされていて、ROS# では Websocket を使っています。
UWP とは Universal Windows Platform の略称で、Windows 10 で動作するアプリ形式です。通常の PC であれば従来の .exe のアプリケーションも動作しますが、HoloLens では UWP アプリしか動作しません。そのため、HoloLens で ROS# を動かすには UWP で動作するよう修正する必要がありました。
Unity Editor 上や .exe 形式にビルドして実行した場合と UWP でビルドして実行した場合では実行環境が違い、一部 API が UWP で使えません。また、プラグイン(DLL) も UnityEditor 用と UWP 用にそれぞれビルドしたものを使う必要があります。
Editor 用プラグインは Assets > RosSharp > Plugins に、UWP 用プラグインは Assets > RosSharp > Plugins > WSA に配置しています。
https://github.com/siemens/ros-sharp/tree/master/Unity3D/Assets/RosSharp/Plugins
ROS# では、以下の DLL が Unity のプロジェクトに入っていました。
これらの UWP 用のものを用意する必要がありましたが、UrdfImporter.dll については一旦あきらめました。 UrdfImporter は URDF 形式のロボットのモデルファイルを読んで Unity のオブジェクトとしてインポートする機能ですが、動的な読み込みを諦めれば Unity Editor 上でのみ動作すれば事足りるためです。さらに、MathNet.Numerics.dll とSystem.Threading.dll は UrdfImporter.dll で利用しているものだったため、これらも必要なくなりました。
Newtonsoft.Json.dll については、UWP で動作する dll も配布されているので、そちらをインポートしました。
websocket-sharp.dll は UWP 版が無いのですが、UWP の MessageWebSocket を使って websocket-sharp とインタフェースを合わせたクラスのコードが公開されており、そちらを利用しました。 github.com
さて、残るは RosBridgeClient.dll です。
RosBridgeClient.dll を作成するプロジェクトは ROS# のリポジトリに入っています。このプロジェクトをもとに、以下の前本さんのブログを参考にして UnityEditor 用の DLL を作るプロジェクトと UWP 用の DLL を作るプロジェクトを作成しました。 satoshi-maemoto.hatenablog.com
ソースコード: https://github.com/tarukosu/ros-sharp/tree/master/RosBridgeClient
ソースコードは共有にしていて、UnityEditor 用と UWP 用でコードを書き分けたい場合は以下のようにしています。
#if NETXF_CORE // UWP 用コード #else // Unity Editor 用コード #endif
RosBridgeClient では、URDF を読むところで Thread を使っていて UWP ではコンパイルできないため、以下のようにして UWP ではコードを無効にしています。
Task を使えば同等のことは実現できるのですが、未実装です。
private void receiveRobotDescription(ServiceReceiver serviceReciever, object serviceResponse) { #if NETFX_CORE //TODO imprementation #else string robotDescription = formatTextFileContents(((ParamValueString)serviceResponse).value); Thread importResourceFilesThread = new Thread(() => importResourceFiles(robotDescription)); importResourceFilesThread.Start(); Thread writeTextFileThread = new Thread(() => writeTextFile((string)serviceReciever.HandlerParameter, robotDescription)); writeTextFileThread.Start(); Status["robotDescriptionReceived"].Set(); #endif }
Unity の C# スクリプトでも同様に、UWP で利用できない API を使っている部分を UWP でも動作するように修正しました。
ClockTimePublisher というスクリプトで Thread を使っていたので、以下のように UWP では Task を使うように書き換えています。
public class ClockTimePublisher : Publisher { ... #if NETFX_CORE private Task task; private CancellationTokenSource tokenSource; #else private Thread clockTimeIterate; #endif protected override void Start() { base.Start(); #if NETFX_CORE tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; task = new Task(async () => { while (true) { if (token.IsCancellationRequested) { break; } StartPublication(EventArgs.Empty); await Task.Delay(timestep); } }, token); task.Start(); #else clockTimeIterate = new Thread(ClockTimeIterate); clockTimeIterate.Start(); #endif } ...
以上の変更を行うことで、ROS# を UWP でビルドできるようになりました。
次のブログ記事では、この ROS# を使って HoloLens アプリを作成した話を書く予定です。
マイクロソフト MVP アワード プログラムとは - マイクロソフト MVP
自身の活動について少し振り返ると、本格的にブログを書き始めたのは 2016 年の 11 月からになります。その数ヵ月後に HoloLens と出会ってその面白さに取りつかれ、その後は主に HoloLens 関連の技術ブログを書いてきました。
この一年の活動としては、ブログ・Twitter での情報発信の他に、コミュニティイベントでの スタッフ・LT・展示も行っていました。
blog.d-yama7.com tarukosu.hatenablog.com
今後も引き続き HoloLens コミュニティを盛り上げて行きたいと思います!
]]>こんにちは、たるこすです。
みなさん、バイナリデータ読んでいますか?
今回は、バイナリデータを読むのに便利な Visual Studio Code(VSCode) の拡張機能「hexdump for VSCode」を紹介します。
以前まではバイナリデータを読むときには vim のバイナリモードを使っていたのですが、 この拡張機能があることを知り、使ってみたところとても便利でした。
VS Code の拡張の 「hexdump for VSCode」がめっちゃ便利だった。
— たるこす (@tarukosu) 2018年6月20日
マウスカーソルを合わせるとそこから先の数バイトを Int とか Float とかとして読んだ場合の値を表示してくれる pic.twitter.com/vSF5vC8GTw
twitter で軽くツイートしてみたら、800 件以上のリツイートと 1600 件以上のいいねがついたのでかなり驚きました。
これは興味がある方が多そうだということで、ブログ記事を書くことにしました。
VSCode をインストールしていない場合は、以下のサイトからインストールしてください。
VSCode を起動したら、左側のメニューの四角いアイコンが拡張機能のマークです。クリックし、検索欄に hexdump と入力します。 hexdump for VSCode が表示されたら、「インストール」ボタンをクリックします。
「再読み込み」ボタンをクリックすると、機能が有効になります。
hexdump for VSCode のインストールができていれば、ファイルを右クリックすると「Show Hexdump」というメニューが出てきます。
「Show Hexdump」をクリックすると、以下のようにバイナリデータが表示されます。
2桁の16進数ごとにスペースを空けて表示されています。この2桁の値が 1Byte です。また、右側の緑色で表示されているものは ascii コードで解釈したときの文字です。
スクリーンショットだとマウスカーソルが消えてしまっていますが、カーソルをデータに合わせるとそこから先の数倍とを Int8, Float32, Float64 などとして読んだときの値が表示されます。デフォルトでは Little Endian で値を解釈します。右クリックし、Toggle Between Little and Big Endian をクリックすると、Little Endian と Big Endian を切り替えられます。
バイナリデータはただのバイト列なので、値を読み取るにはファイルフォーマットに沿って解釈していく必要があります。
今回は、3D モデルデータのフォーマットである STL ファイルを読んでみます。フォーマットについては、以下のページを参考にさせていただきました。モデルデータについても以下のページで配布されていた cube-binary.stl を使っています。
最初の 80 バイトは文字列が入っているということで、右側の緑色の文字を読むと cube-binary というモデル名が入っていることがわかります。また、そのあとはスペースで埋められていますが、53バイト以降はよくわからない値が入っていました。
81バイト目から4バイトが三角形の枚数です。00000050:
の右の 0C にカーソルを合わせると、以下のようになります。Uint 32:
の欄を見ると 12 となっているので、三角形は 12 枚ということがわかります。
次からは 4 バイトの float が連続します。
00 00 00 00 00 00 00 80 00 00 80 3F
カーソルを合わせて Float32:
の欄を読み取ると 0, 0, 1 と読み取ることができます。
ここから先も同様に float のデータを読んでいけば値を読み取っていけます。
バイナリデータを読む機会があれば、「hexdump for VSCode」をぜひ使ってみてください。
]]>こんにちは、たるこすです。
2018/6/23 に開催された HoloLens Meetup で HoloLens, ロボットアーム(uArm Swift Pro), RealSense D415 を使ったデモを展示しました。
もともとは HoloLens でトランプをタップすると、その位置にアームが動いてトランプを吸い上げ、箱の中に入れるというデモをしようと思っていました。
しかし、プログラム自体は動作したのですが、ロボットアームの調子が悪くアームを持ち上げるときに関節の角度が指令値とずれるという現象が発生してしまいました。
そのため仕方なく、ロボットアームを手で動かすと HoloLens 上で表示しているロボットも現実のアームと同期して動作するというデモに切り替えました。
また、このデモでは RealSense で取得した点群データを表示するという機能もあります。
点群データをそのまま送ると転送データ量が多くなる上 HoloLens 側での描画がつらいめ、ダウンサンプリングしたデータを HoloLens に送って表示しています。
ちょっとわかりづらいですが、中央の綾鷹のペットボトルに点群が重畳表示されているのがお分かりいただけると思います。
仕組みについて、ものすごく簡易的に説明します。
ロボットアーム、RealSense は PC (Ubuntu) に接続されており、この PC がロボットアームの間接角や RealSense のセンサーデータを取得します。 PC から HoloLens へは WebSocket を使ってデータを送っています。
HoloLens アプリ内は取得した間接角を元にロボットアームのモデルを変形させて描画しています。
詳しい話は別途ブログ記事を書きたいと思います。
アプリを体験していただいた方からコメントをいただきました!
宮浦さん
「RealSense はデバッグがしやすくなって便利そう。なにが見えている見えていないというのがわかってよい。
ロボットアームの仕組みは操作手順の説明、危険予測、作業支援などに活用できそう。」
井出さん
「ロボット、ROS、HoloLens は熱い! 早くロボットを HoloLens で動かしたい!」
匿名
「ロボティクスxHoloLensは面白い!」
ごんちゃん
「工場の生産ラインとかでHololensが活用できる日も近い!(かも!)」
シンさん
「センサーとMRすごい未来感あって楽しみ!」
PE 江畑さん
「SF感あって半端ないって!」
サミィさん
「なんかスゴイのはちょっと被っただけでわかりました。
センサーと合体すごい!」
woops39 さん
「これが初HoloLensでした笑
未来感ですね!!」
るこてこさん
「ロボットとしっかり動きがリンクされてて感動しました!
現実のロボットがよりかっこよく見えるようになったらいいですね!」
pown さん
「危険作業の確認とかに使えそうと思いました。」
mitsuru さん
「IoTとMRはすごく親和性が高いと思っていて、真骨頂をみた感じがしました。」
Jack さん
「点群のデータがすごい!IoT最高!!!」
YusukeSaito さん
「デバッグ用にモーターの状態などの数値情報が可視化できると最強だと思います。」
デモを体験していただいた皆さん、コメントをいただいた皆さん、本当にありがとうございました!
]]>先日、HoloTheremin(ホロテルミン) という HoloLens アプリをストア公開しました。ストア公開した HoloLens アプリはこれで2つになりました。
指を上げると音が出て、指の位置によって音が変化するという楽器アプリです。詳しくは以下の動画を見てみてください。
このアプリを作ったきっかけはごんびぃーくんのツイートでした。
— ごんびぃーさん (@GONBEEE_project) 2017年12月18日
これをみて、まず初めに作ったのが以下の動画です。
ごんびーくんアイデアの Holoテルミン 作ってみた(イメージと違うかもしれないけど)
— たるこす (@tarukosu) 2017年12月21日
鏡に向かって撮影してます#HoloLens #HoloLensJP #Holoテルミン pic.twitter.com/ii2XhzvIDF
この時は、指の位置に合わせて Sin 波で音を生成したんですが、なんというか味気ない音になってしまったので、その後しばらくの間放置プロジェクトになっていました。
ストア公開したバージョンでは、スクリプトで音を生成することをあきらめ、楽器音の再生速度を変えることで音の高低を変えるようにしています。
]]>UWPには、アプリをBackgroundで実行するためのバックグラウンドタスクが用意されています。 まずは、以下の動画をご覧ください。BackgroundでMusicを再生しながら、Reseach Modeを呼んでいる様子です。 (ソースコードはMicrosoftのWindows-universal-samplesを利用しています。 https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BackgroundMediaPlayback)
(また、ResearchModeのアプリは@akihiroさんのブログ(http://akihiro-document.azurewebsites.net/post/hololens_researchmode2/)の UWP(C#)版を利用しています。)
さて、ここでバックグラウンドタスクにおける二種類のプロセスがあるそうです。 この二つのプロセスについて、まとめてみました。 (参考 : バックグラウンド タスクのガイドライン - UWP app developer | Microsoft Docs )
A. インプロセス
アプリとそのバックグラウンド プロセスが同じプロセスで実行されるプロセス。
今回のBackgroundMediaPlayer Sampleはこちらのプロセスを利用しています。
[利点]
インプロセス バックグラウンド タスクでは、プロセス間通信が不要のため、記述内容は複雑になりません。
[欠点]
インプロセス バックグラウンド タスクでは、DeviceUseTrigger、DeviceServicingTrigger、IoTStartupTask の各トリガーがサポートされていません。
(→センサ系のトリガーが使えない)
また、アプリケーション内での VoIP バックグラウンド タスクのアクティブ化がサポートされていません。(→VoIPはアウトプロセス)
[特徴]
Application オブジェクトから EnteredBackground と LeavingBackground という 2 つの新しいイベントを使用できます。
EnteredBackground イベントは、アプリがバックグラウンドで実行されている間に処理されるコードを実行します。また、LeavingBackground イベントは、アプリがフォアグラウンドに移動したことを知るために処理します。
(シンプルに実装できる。)
B. アウトプロセス
[利点]
アウトプロセスタスクでのコードがクラッシュしても、フォアグラウンドでのコードはクラッシュしません。また、 DeviceUseTrigger、DeviceServicingTrigger、IoTStartupTask の各トリガーを使用できます。
[欠点]
プロセス間通信を利用するため、記述内容が複雑になりがちです
[特徴(というより、書くべき処理)]
- IBackgroundTask インターフェイスを実装するクラスを作ると、コードをバックグラウンドで実行できます。 このコードは、SystemTrigger や MaintenanceTrigger などを使って特定のイベントをトリガーすると実行されます。
- 実行するバックグラウンド タスクを登録します
- イベント ハンドラーでバックグラウンド タスクの完了を処理します
- アプリがバックグラウンド タスクを使うことをアプリ マニフェストで宣言します
(工程が多く複雑(?)。)
- カメラセンサ情報 + Networkをbackgroundで実行、サーバー側にセンサ情報を投げ続ける。 この場合、アウトプロセスを利用する必要があると考えます。
アプリをBackgroundで実行する様子と、そのために用意されたバックグラウンドタスクにおける二つのプロセスについてまとめました。 今回は公式ドキュメントの中で用意された二つのプロセスについて着目しましたが、実装面には触れていません。 Backgroundで何を処理させたいかで、どちらのプロセスを選択すべきかが変わる、といったところでしょうか。 今後は、Hololensのカメラセンサ等をBackgroundで処理していこうと思います。
]]>点群処理といえばコレ、といったくらいメジャーなPoint CLoud Library(http://pointclouds.org/)をwidows + visual studio 2017でプログラミングできるようにしていきます。
...とはいっても、先行的に@UnaNancyOwenさんなどがall-in-one packageを作成しており、導入を楽にしていただいています。とても助かっていますw
まずはじめに、パッケージをインストールしましょう。
http://unanancyowen.com/pcl181/
にアクセスします。次に、以下の図1の中の自分の環境に合わせたものをダウンロードします。 (私の場合、PCL 1.8.1 All-in-One Installer MSVC2017 x64です。)
ダウンロードしたら、exeファイルを起動してインストールしていきます。
今回、PATHは自動で追加しないようにします。
(最近のブログを見ると、追加しても大丈夫になってるっぽい。)
他は、defaultのままで大丈夫です。
次に、環境変数を設定していきます。
大雑把に説明すると、「PCLの実行ファイルはここにあるよ!」ということをPCに教えてあげます。
「winsowsキー(窓が書いてあるキー)+R」で「sysdm.cpl」をファイル名を指定して実行し、システムのプロパティを呼びます。
そして、詳細設定タブ->環境変数をクリックすると、図2のような画面が現れるはずです。
システム環境変数において、「PCL_ROOT」「OPENNI2_REDIST64」があることを確認してください。
(なければ、図2と同様に上記二つの変数と値を入力してください。)
次に、pathを設定します。pathの列をクリックし、編集ボタンをクリックすると、図3のような画面が現れます。 図3の下部5行を追加してください。(3rdPartyの部分は要らないかもですが、念のため)
PCLはCmake(https://cmake.org/)でのプロジェクト生成を推奨されています。そこで、CMakeをインストールします。 公式ページのdownloadから環境に合わせたwindowsインストーラーパッケージをダウンロードし、インストールします。 この際、PATHを自動登録し、デスクトップアイコンにチェックを入れましょう(この辺は好みでw)
インストールしたら、「winsowsキー+R」で「cmd」を実行、コマンドプロンプト上で「cmake -version」と打ち、以下の図4にようになればOKです。 ここで、一度PCを再起動させてください。(環境変数の変更を適用するため)
Point Cloud Library 1.8.1 has been releasedhttp://unanancyowen.com/pcl181/に、「Basic CMakeLists for PCL」の項があります。 Basic CMakeLists.txt for PCL(https://gist.github.com/UnaNancyOwen/f4dcd74ab870a0fc9e7a)の右上にDownload ZIPをクリックし、解凍し、フォルダ名を分かりやすいように変更しましょう。今回は、図5のように、フォルダ名を「sampleProject」に変更しています。
次に、CMakeを起動し、上部二つのダイアログボックスに先ほどのsampleProjectのパスを指定します。 configureをクリックし、お使いの環境のvisual studio(今回ならvisual studio 15 2017 WINI64)、use default native compliersを選択、Finishボタンをクリック。 そのまま「Generate」をクリック、Generate doneというログが出たら、「Open Project」でプロジェクトを開きましょう。
以下の図6のようなプロジェクトが開かれていると思います。この状態で、「Ctrl + F5キー」を押すと、main.cppが実行されます。
main.cppの実行を確認したあとは、PCLのサンプルを実行してみましょう。
project->Source Files->main.cpp をダブルクリックして開き、以下のコードに置き換えて「Ctrl + F5キー」で実行してみてください。
(source codeはこちらのものを変更しています:http://www.pointcloud.jp/blog_n14/)
#include <pcl/visualization/cloud_viewer.h> #include <iostream> #include <pcl/io/io.h> #include <pcl/io/pcd_io.h> int user_data; void viewerOneOff(pcl::visualization::PCLVisualizer& viewer) { viewer.setBackgroundColor(1.0, 0.5, 1.0); pcl::PointXYZ o; o.x = 1.0; o.y = 0; o.z = 0; viewer.addSphere(o, 0.25, "sphere", 0); std::cout << "i only run once" << std::endl; } void viewerPsycho(pcl::visualization::PCLVisualizer& viewer) { static unsigned count = 0; std::stringstream ss; ss << "Once per viewer loop: " << count++; viewer.removeShape("text", 0); viewer.addText(ss.str(), 200, 300, "text", 0); user_data++; } int main() { pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGBA>); pcl::visualization::CloudViewer viewer("Cloud Viewer"); viewer.showCloud(cloud); //This will only get called once viewer.runOnVisualizationThreadOnce(viewerOneOff); //This will get called once per visualization iteration viewer.runOnVisualizationThread(viewerPsycho); while (!viewer.wasStopped()) { user_data++; } return 0; }
マウスのホイールを引き、左クリックを押したまま移動で、原点を中心に回転できたりします。 すると、以下の図7のような画面が出てくると思います。これが出てきたら、PCLのセッティングは一旦完了となります。
windows10 + visual sturido 2017の環境にて、PCLのセットアップを行いました。 今後は、さまざまな点群処理の実装を行っていこうかと思います。
]]>RGBカメラセンサといえば視野の範囲内の映像を平面上に表示するのが一般的でした。 しかし近年AR(Augumented Reality)やVR(Virtual Reality)技術の発展により、 平面ではなく立体的に展開された映像を体験することが容易となっています。
そして立体的に展開された映像を撮影するために、様々なデバイスが提案されています。 その中でも、今回はRICHO THETA VとMirage Cameraについて着目します。
RICHO THETA V は上下左右360度全ての方向を撮影することができるカメラです。
4K画質(3840 x 1920、56Mbps)、30fpsの動画を撮影することができます。
Mirage Camera は VRヘッドセットであるMirage soloと同時に発表されたデバイスです。
全面に1300万画素のカラーカメラが二つ付いており、こちらは前方を基準に上下左右180度の映像を撮影できます。
また、仕様を見るとこちらもRICHO THETA Vと同様に4K画質、30fpsの動画を撮影することができます。
図1にカメラ性能などの比較した図を載せます。また、これらは各公式サイトから引用しています。 RICHO THETA V も Mirage Cameraも、どちらも4K画質で動画を取得することができます。 しかしながら、前者は360°、後者は180°の映像出力に最適化されているため、当然見え方が変わってくるはずです。
次に同じ4K画質で動画を撮影できるため、Mirage Cameraの方が狭い視野の反面、綺麗な見た目で撮影できると予想しています。
その際、どの程度綺麗にとれるのか?ということに興味が湧いています。
さらに、この解像度次第では高度な画像処理にも耐えうるかもしれません。
....と、妄想が膨らむところで、今後実際の使用感について書いていこうと考えています。
]]>Unity Editor および HoloLens で SignalR が使えたので、その方法を紹介します。
かずき (@okazuki) さんがブログで SignalR を Windows Mixed Reality で使う方法を紹介されていたのですが、UWP でしか動かないと Unity Editor でデバッグできなくて面倒なので、Unity Editor でも使えるかどうか試してみました。
先ほどのかずきさんのブログを参考にして ASP.NET MVC で実装しました。
ブログの通りに実装して実行したところ、"ファイルまたはアセンブリ 'Microsoft.Owin'、またはその依存関係の 1 つが読み込めませんでした。見つかったアセンブリのマニフェスト定義はアセンブリ参照に一致しません。" というエラーが発生しました。
インストールされていた Owin のバージョンが古かったことが原因で、4.0.0 に更新すると動きました。
はじめに、以下のページから NuGet のコマンドラインツールをダウンロードします。
ダウンロードした nuget.exe にパスを通すか、コマンドプロンプトで nuget.exe があるディレクトリに移動した後で、以下のコマンドを実行します。
> nuget install Microsoft.AspNet.SignalR.Client -OutputDirectory signalr
すると、signalr ディレクトリに SignalR.Client とその依存パッケージ(Newtonsoft.Json) がダウンロードされます。
Microsoft.AspNet.SignalR.Client.2.2.3 ディレクトリには lib フォルダがあり、その中にプラットフォーム別の DLL が入っています。
Unity 2017 ではデフォルトの .NET のバージョンが .NET 3.5 なのですが、SignalR.Client は .NET 3.5 で使えるものがなかったので、Unity の .NET のバージョンを上げる必要があります。
Player Settings の Other Settings 欄の Scripting Runtime Version を Experimental (.NET 4.6 Equivalent) に変更することで、.NET 4.6 までの DLL が使えるようになります。
次に、Assets 内に Plugins フォルダを作成し、その中に WSA フォルダを作成します。Plugins フォルダは Assets 直下じゃなくても大丈夫です。
Plugins フォルダ内に、Microsoft.AspNet.SignalR.Client.2.2.3\lib\net45\Microsoft.AspNet.SignalR.Client.dll
と Newtonsoft.Json.6.0.4\lib\net35\Newtonsoft.Json.dll
をインポートします。また、両方とも Inspector で Any Platform のチェックを外し、Include Platforms の WSAPlayer のチェックを外します。これで、この DLL は Unity Editor 上では使われますが、UWP では使われなくなります。
次は、UWP 用の DLL をインポートします。
WSA フォルダに
Microsoft.AspNet.SignalR.Client.2.2.\lib\netcore50\Microsoft.AspNet.SignalR.Client.dll
と
Newtonsoft.Json.6.0.4\lib\netcore45\Newtonsoft.Json.dll
をインポートします。
こちらの DLL には、WSAPPlayer のみチェックが入るようにします。
かずきさんのブログの SignalRManager.cs を作成し、適当な GameObject にアタッチします。ただし、スクリプト内の
#if UNITY_UWP
#endif
は削除します。
これで、Unity Editor 上でも、UWP (HoloLens) でも SignalR が使えるようになりました。
]]>SignalR を使ってオブジェクト生成 pic.twitter.com/kP7KUWum1s
— たるこす (@tarukosu) 2018年4月27日
半面、CoderDojoは当日参加以外のところまで手が回らなかったのが申し訳ないところです。
個人的には今年は会社と仕事を回すことが精いっぱいでアウトプットが少なかったです。とはいえ、ホロラボのメンバー含めて自分よりも細かくアウトプットを出す方が増えたので、やり方含めて考えないといけない時期なのかもです。
会社的には今年は助走のつもりで動いていました。おかげさまで2018年は年明け早々フルスロットルな感じです。強力なメンバーも順次増えていく予定で、会社としてもアウトプットも順次出していけると思います。
強力なメンバーに集まってもらうことができたので、来年は個人→グループ→チームにしていくことが自分の仕事になると思っています。向こう数年はまたプログラマーというロールから一旦はずれる時期になりそうです。
ということで、来年もよろしくお願いします。
1位がRealSenseなのと、9位にRedmineのBacklog Pluginの記事が入ってた(6年前)。
順位 | ページ | PV |
---|---|---|
1 | Intel RealSense まとめ | 8204 |
2 | HoloLensまとめ | 7278 |
3 | Kinect for Windows SDK v2.0 でDepth(距離)データを取得する | 6268 |
4 | Kinect for Windows SDK v2.0 でBody(関節など)を取得する | 5920 |
5 | Intel RealSenseをMax OSやLinuxでも使える librealsense を使ってみた | 4950 |
6 | HoloLensアプリの開発を始めるまでの資料を作りました | 4824 |
7 | HoloLensの環境マッピング(Spatial Mapping)の使い方 | 4409 |
8 | これから Kinect for Windows SDK を始めたい人へ | 4336 |
9 | RedmineのBacklogsプラグインを使ってみた | 4334 |
10 | Microsoft Kinect v2まとめ | 3518 |
こんにちは、たるこすです。
今回の記事は Oculus Rift Advent Calendar 2017 の19日目の記事です。
HoloLens と Tango を連携させ、Tango を HoloLens 用ガンコントローラとして使ってみました。
まずはデモ動画をご覧ください。
Tango とは Google が開発した AR フレームワークで、対応端末は 2機種(Zenfone AR, Phab 2 Pro) 発売されています。
外部センサなしで高精度の SLAM を行うことができ非常に優秀なのですが、残念なことに Tango ブランドは終了することが発表されています。さらに、12/15 には、Tangoのサポートは 2018年3月1日 に終了するということが発表されました。 jp.techcrunch.com
ガンコントローラのトリガーは Tango アプリで取得し、HoloLens に送信しています。 また、Tango の位置を HoloLens に送ることで、HoloLens でガンコントローラの位置を取得できます。
しかし、Tango アプリと HoloLens アプリでは座標系が異なってしまうので、Tango から受け取った値そのままでは HoloLens 上では正しい位置になりません。
そこで、Tango アプリの画面にマーカー画像を表示し、それを HoloLens で認識した際に HoloLens 座標系での Tango の原点を計算します。 Tango アプリから受け取った座標は Tango 原点から見た座標なので、それを先ほど計算した Tango の原点を使って HoloLens 座標系に変換します。
こうすることで、HoloLens アプリで Tango の位置を使って操作ができるようになります。
カワダから発売されている、AR マジックガンというおもちゃのコントローラを使いました。
本来の使い方は、ガンに普通のスマートフォンを取り付け、壁に貼ったポスターをマーカーとしてスマホの画面で AR ゲームをするというものです。公式のスマホアプリを入れるとガンコントローラと Bluetooth 接続し、トリガーのボタンを取得できます。
今回は自作のアプリでガンコントローラと接続して値を読み取りたかったのですが、調べても情報が見つからなかったため方法がわかりませんでした。そこで、ガンコントローラを分解し、中のスイッチにジャンパーワイヤーをはんだ付けして外に取り出し、Teensy というマイコンで ON/OFF を読み取りました。Teensy は Zenfone AR に USB で接続し、Zenfone AR からはキーボードとして認識させています。
このあたりの話は、また別記事に詳しくまとめようと思います。
作成した Tango アプリの機能は以下の2つです。
実装内容については、大きく分けて以下の3つになりました。
Tango SDK に含まれている、Tango Manager と Tango Camera のプレハブをシーンに配置しました。
これで、Tango 端末の位置に合わせて Main Camera が移動するようになります。
以下のような画面を作成しました。
シーンには以下のように、Canvas に RawImage, InputField, Button を配置しています。
RawImage は HoloLens で認識するためのマーカー画像を表示する用です。
InputField と Button は、HoloLens と通信する際に必要となる HoloLens の IP アドレスを入力するために使います。 アドレスを入力してボタンをタップすると、IP アドレスが設定され、入力欄は非表示にしています。
Tango アプリから HoloLens へのデータの送信には、UNET の LLAPI (Low-Level API) を利用しました。
以前利用した際もブログに書いていたので、こちらも併せてご覧ください。
データ送受信のマネージャとして、以下のスクリプトを作成します。このスクリプトは、受信側の HoloLens アプリでも使用します。
これを空のゲームオブジェクトにアタッチし、以下のように設定します。
Tango の位置やコントローラ入力は、以下のスクリプトで送信します。
これを、空のゲームオブジェクトにアタッチし、NetworkManger として先ほど作成したオブジェクトを設定します。
これで、Tango アプリは完成です。
プロジェクトに HoloToolkit-Unity をインポートします。
シーンに、HoloLensCamera, Directional Light, SpatialMapping を配置します。Directional Light は 1つだと風船が暗く見えてしまったので、2つ設置しました。
また、はまりやすいのが Capability の設定です。今回のアプリでは以下の設定が必要なので、気を付けてください。
UNET でデータを受信するため、先ほど Tango アプリでも利用した LLAPINetworkManager.cs を使います。
LLAPINetworkManager.cs を空のオブジェクトにアタッチし、以下のように設定します。
HoloLens アプリの LLAPINetworkManager で設定する Local Port の番号と、Tango アプリで設定する Server Port を一致させるようにしてください。
さらに、受信したデータを処理するスクリプトとして、以下の UnetTangoController.cs を作成します。 ボタンの値を受信した場合は SelectButton の値が変更され、位置を受信した場合は UnetTangoController.cs がアタッチされたオブジェクトの位置が変更されます。
ITangoController.cs は以下のようなスクリプトです。
初めは、通信に Photon を使っていたので、切り替えを簡単にできるようにインタフェースを作りました。
光線銃オブジェクトは、ヒエラルキーでは以下のような構成となっています。
TangoOrigin が Tango 座標系の原点、Gun が Tango(ガンコントローラ)の位置、Muzzle が銃口、Aim が照準となっています。
Gun オブジェクトにアタッチする GunScript.cs では、先ほどの UnetTangoController.cs で取得した値を使って光線銃の処理を行います。GunScript.cs から関係する部分だけを抜き出すと以下のようになります。
このスクリプトでは、Gun オブジェクトの Position, Rotation を Tango から受け取った値に更新しています。正確に言うと、Tango から値を受け取るフレームレートが低くそのままだとカクカクして見えてしまうため、滑らかに見えるように前の値と補間して設定しています。
マーカー画像の認識には Vuforia を使っています。
シーンに ARCamera と ImageTarget のプレハブを配置し、認識のための設定を行います。
詳しくは以下のブログをご覧ください。 tarukosu.hatenablog.com
さらに、ImageTarget に以下の CustomTrackingHandler.cs をアタッチします。
これは、Vuforia のトラッキング状態を Action で通知するためのスクリプトです。
次に、GunScript.cs で Tango の原点の計算を行います。先ほどは一部を省略した状態でしたが、以下が GunScript.cs の全体です。
重要なのは、OnTracking 内で Tango 原点を求めている部分です。originToMarker が HoloLens 原点からマーカーへの変換行列、tangoOriginToMarker が Tango 原点からマーカーへの変換行列、originToTangoOrigin が HoloLens 原点から Tango 原点への変換行列となっています。
Inspector では以下のように設定します。
これによって、TangoOrigin の位置が Tango アプリでの原点の位置に移動され、Gun の位置が Tango の位置と一致するようになります。
アプリの実装内容をすべて書くのは大変だったので、以下の部分は省略しました。ごめんなさい。
Set ボタンが押されたら、Input Field に入力された IP を LLAPINetworkManager.cs の Server Address に設定するようにしました。
Muzzle から Ray を飛ばし、ぶつかったところに黄色いオブジェクトを表示させて照準としています。
Volumetric Lines というアセットを使って光線を作成しました。
風船は MRDesingLabs_Unity の DesignLabs_Unity_Examples
に入っているモデルを使いました。
光線と風船の衝突を判定し、風船が割れる処理を行っています。
風船が割れたときに出る紙吹雪は、以下のブログを参考にして作成しました。
出来上がったデモは出現する風船を撃つというだけのものですが、しばらくやっていたくなるような楽しいデモになりました。制限時間や得点などを入れてゲーム性を上げるともっと楽しくなりそうです。
また、今後の発展としては、複数人で対戦したり、現実のものとのインタラクションを入れたりしたいと思っています。
@OculusTan さんによる「VRすきまアワード作品紹介?」です。お楽しみに!
]]>こんにちは、たるこすです。
2016/11/27 から1年間継続を目標として毎週ブログ投稿を始めました。前回の投稿(2017/11/19)で52週連続、そして今回の投稿で53週連続の投稿となります。
1年は52週と1日なので、今回の投稿をもって「1年間毎週ブログ投稿達成!」となりました。
ここから先は、1年間の投稿の振り返りや良かったことを書いていきますが、最初に伝えたいことを2点あげておきます。
1年間で投稿した記事の内訳は以下の通りです。
カテゴリー | 投稿件数 |
---|---|
イベント参加報告 | 5件 |
Unity, HoloLens | 30件 |
おうちハック, ガジェット | 7件 |
Windows関連 | 7件 |
Android | 2件 |
その他 | 1件 |
Unity, HoloLens 関連が 30 件とダントツで多く、イベント参加報告も 5件中4件 が 「HoloLens Meetup」 というイベントについてなのでほとんどが HoloLens 関連の記事ですね。
作ったデモ動画をいくつかはっておくので良ければ見てみてください。
また、「ブログの目次」ページに各ブログ記事へのリンクをまとめています。 tarukosu.hatenablog.com
毎週ブログ投稿を始めたのは、発信力をつけたいと思ったからでした。
1年前のことなので正確には覚えていないのですが、「発信力をつけたい」と思った理由として以下のことがありました。
1年前までのブログ投稿は10件くらいだったので、毎週ブログ投稿をよく決意したなぁと思います。1年前の自分に感謝です。
ブログ投稿を始める前は某イカのゲームだけで土日が終わっていたこともありました。ブログ投稿を始めてからは毎週ブログ記事を書かなければいけないので、実装・技術調査・イベント参加など、何かしらの活動を行ってそれをブログ記事にまとめるという活動を行うようになりました。
土日の時間の使い方がかなり変わったと思います。
始めは恥ずかしくてあまりやっていなかったのですが、ブログを投稿したらそれをツイートするようにしていました。リツイートやいいねがもらえると嬉しいですし、リツイートが多いとブログへのアクセス数も多くなりました。
GOROman さんや凹みさんから記事に対してコメントがもらえたこともあり、非常にモチベーションがあがりました。
これいいなあ
— GOROman (@GOROman) 2017年1月16日
[おうちハック]Raspberry Pi 3 と USBカメラで赤ちゃんモニタリングページを作る - たるこすの日記 https://t.co/1r1dd3lpmt
これはかなり面白くて次やりたいと思ってるんですが、家電やガジェットの位置が空間のどこにあるかが(予め登録しておけば)認識できるので、向くだけで音声認識開始するっていうのは誤認識問題に対する1つの解だと思いますhttps://t.co/patqmkk8to#HoloLensJP
— 凹 (@hecomi) 2017年3月25日
これまでで一番リツイートが多かったのが以下のツイートでした。(ブログ投稿についてのツイートではないですが)
ついに"チカラ"を手に入れてしまった... #HoloLens pic.twitter.com/xuFwmY6gW6
— たるこす (@tarukosu) 2017年2月18日
この件は MoguraVR さんにも記事として取り上げていただきました。
前に試した技術をもう一度使いたくなることが時々あります。以前使ったときにメモを書いて残してあればよいのですが、ブログを書く前はなかなか面倒でメモを書くことはほとんどありませんでした。
ブログ投稿を始めてからは、実装中にメモを書くことが増え、ブログ記事を書く段階で誰でもわかりやすいようにさらにメモを整理するようになりました。
検索してヒットする、というのも嬉しいポイントでした。ローカルに残したメモだと、どこに保存してあるのか分からなくてメモを探すのに時間がかかることもありますが、ブログだとググれば出てきます。さらに、仕事中に必要になっても、会社の PC でググれば記事が出てくるので非常に便利でした。
HoloLens 関連の開発が多かったので特に言えることなのですが、ブログ投稿を続けることでデモアプリやデモ動画がだんだんと増えてきました。そうすると、イベントで会った人にデモ動画を見せたり HoloLens を使ってデモができるようになりました。5分間 LT(ライトニングトーク)での発表も何度か行いました。
また、これは仕事関連でブログを始めたことと直接は関係ないのですが、Unite 2017 Tokyo という Unity のイベントで講演することができました。社外で発表する機会が増えた1年になりました。
この一年間で知り合いがかなり増えました。技術系イベント(主に HoloLens Meetup)に参加したことが主な要因ですが、ただ参加するだけではなくプレゼン発表したりやデモを見せたりできたことが良かったと思います。
また、イベントで会った方に「ブログ読んでいます」と言っていただけることもあり、とても嬉しかったです。
自分は飽きっぽい性格で、これまでは何かを決意してもすぐに飽きてやめてしまうことが多かったのですが、ブログ投稿を続けるにあたっては以下の2点を意識しました。
何があっても毎週投稿するというのが大事だったと思います。極端なことをいうと、「あ」とだけ書いて投稿することもできるわけですが、それでも投稿をやめてしまうよりは全然いいと思います。(多分ものすごく恥ずかしいので、来週からは頑張ろうと思うはず)
もし、「今週は忙しかった」などの何かしらの理由をつけて投稿しないという例外を作ってしまうと、投稿しないことへのハードルがかなり下がってしまいます。そうすると、その後も事あるごとに投稿しない週を作ってしまい、そのうちやめてしまうのではないかと思います。
皆さんがそうなるとは限らないですが、自分は絶対にそうなってしまうと思ったので必ず毎週投稿するというのを強く意識していました。
ブログ投稿を続けるために大変だったのが、何についてブログを書くか、というブログのネタを考えることでした。 毎週、平日の間になんとなくネタを考えて、土日で実装とブログ投稿を行うことが多かったです。
実装とブログ投稿にかけられる時間がたっぷりあるわけではないので、実装時間が短くてもブログ投稿できそうなネタを選んで実装を進めるようにしました。また、1週間で終わりそうにない少し大きめのネタであれば、ブログ投稿も数回に分けて行うようにしました。
実装が終わっていても、ブログ記事を書く段階でスラスラ書けるときとそうでないときがありました。 どういったときに書きづらいのかは自分でも良くわからないのですが、ひとつ思い当たるのは知識が少ない分野のブログは書きづらかったです。他の人に読まれるため間違ったことを書きたくないと思い、文章を書くのが慎重になったり書いた文章が正しいかどうか調べたりして、時間がかかりました。
目標としていた1年間を達成したので、一旦毎週投稿は終わりにします。ただ、今後もブログ投稿は続けていきたいと思っているのでよろしくお願いします。
]]>今回は Unity 2017 の新機能である Timeline の勉強がてら、HoloLens でふわっとメニューウィンドウを表示させたいと思います。
ホーム画面で Bloom したときに出てくるメニュー画面のような感じで、アプリ内のメニュー画面を出すというイメージです。
この動きを Unity で Timeline 使って作ってる pic.twitter.com/q4Mayg1i40
— たるこす (@tarukosu) 2017年11月18日
ただし、アプリ内で Bloom を使うとアプリが終了してしまうため、アプリ内のメニュー画面には Bloom は使えません。そのため、ダブルタップ(Air-Tap を二連続で行うジェスチャ)を行うと、メニューを出すようにしてみます。
新規プロジェクトを作成し、HoloToolkit をインポートします。細かいところは省略しますが、HoloToolkit を使って HoloLens 用の設定を行います。
シーンに以下のプレハブを配置します。
メニューウィンドウは MRDesignLabs のボタンを使って作るのが良いかと思いますが、今回は一旦キューブの組み合わせで作ってみました。以下のような構成で、MenuWindow と MenuPanel は空のオブジェクト、Background と Button はキューブのサイズを調整して作成しました。
また、視線の向きにウィンドウが追従するよう、MenuWindow には Tagalong と Billboard を付けました。きれいに追従するように、BoxCollider のサイズと Tagalong の Minimum Horizontal/Vertical Overlap の値を少し変更しています。
メニューができたところで、Timeline を使ってアニメーションを付けていきます。Timeline という機能の詳細について説明はしない(説明できるほど理解できていない)ので、知らない方は以下のサイトやスライドを見てみてください。
www.slideshare.net
Hierarchy で MenuPanel を選択した状態で、Window > Timeline Editor を開き、Create ボタンを押します。
Playable オブジェクトの保存ウィンドウが出るので、名前を入力します。これで、Timeline が作成され、必要なコンポーネントがオブジェクトにアタッチされます。
Timeline が自動再生されないよう、 Play On Awake のチェックは外しておきます。
はじめは、Timeline の AnimationTrack(新しく Timeline を作成するとデフォルトで表示されている)を使って位置や回転のアニメーションを作ろうとしました。しかし、キーフレーム(ひし形マークが表示されているところ)を登録するところまではいいのですが、キーフレームの時刻を調整しアニメーション速度を変更する方法がわかりませんでした。
そこで AnimationTrack は一旦あきらめ、 PlayableTrack という Timeline からスクリプトを実行させる仕組みを使いました。PlayableTrack を使うには、PlayableBehaviour と PlayableAsset を継承したクラスをそれぞれ作成します。今回は、Position, Rotation, Scale, マテリアルのアルファ値 を変更するスクリプトをそれぞれ作成しました。
PositionPlayableBehaviour.cs の ProcessFrame が Timeline で実行されたときに毎フレーム呼ばれるメソッドです。
こちらを参考に 3次関数で開始と終了のアニメーション速度をゆっくりにしています。 appleorbit.hatenablog.com
Rotation, Scale, マテリアルのアルファ値 を変更するスクリプトもほぼ同じです。すべて表示すると長くなってしまうので、リンクをはっておきます。
次は作成したスクリプトを Timeline に追加していきます。PlayableAsset を Timeline にドラッグ&ドロップすると、Track が作成され PlayableAsset が追加された状態になります。Timeline 上で PlayableAsset を選択するとインスペクタに詳細が表示されます。GameObject にアタッチする通常のスクリプトと同じように、ここで GameObject を指定したりパラメータの調整を行います。
また、音声データを Timeline にドラッグ&ドロップすれば、Audio Track が作成されます。Audio Track ではどの Audio Source から音を再生するかを指定する必要があるので、MenuPanel に Audio Source をアタッチしそれを指定しています。
作成したタイムラインは以下のようなものです。
また、それぞれの Asset のパラメータは以下のように設定しました。
次は、作成ウィンドウを開く Timeline を複製し、閉じるアニメーションの Timeline を作成しました。編集したい Timeline は Inspector で Playable Director の Playable で設定していないと Timeline のプレビューができないのでご注意ください。
閉じるアニメーションは開くアニメーションよりは短い時間で動作するようにしています。
設定したパラメータは以下の通りです。
作成した開くアニメーションの Timeline と閉じるアニメーションの Timeline を切り替えて実行するために、以下のスクリプトを MenuPanel に設定します。
また、以下のスクリプトを MenuWindows に設定し、Toggle メソッドを呼ぶとウィンドウが開いたり閉じたりするようにします。
冒頭でも書きましたがアプリ内では Bloom を使えないため、メニューの表示にはそれ以外のアクションを使う必要があります。いろいろな方法がありますが、ダブルタップを使うのが便利です。
ダブルタップは以下のようなスクリプトで認識することができます。
空のオブジェクト(MenuWindowManager) を作成し、上記スクリプトをアタッチします。また、インスペクターで MenuWindows を割り当てます。
これで、ダブルタップでメニューの表示・非表示ができるようになりました。
以下のように、ダブルタップでふわっとメニューウィンドウが表示できるようになりました。メニューのデザインや音はイケてないですが、今回はアニメーションさせることが目的だったのでそこは許してください。
Timeline を使ってメニューウィンドウをアニメーション表示させてみた pic.twitter.com/qrqjgCoZ65
— たるこす (@tarukosu) 2017年11月19日
Timeline は初めてつかってみたのですが、動きや音などを組み合わせて一連のアニメーションを簡単に作ることができました。今後も活用しようと思います。
]]>Windows 10 の「フォト」アプリの新機能 Story Remix (ストーリーリミックス)をご存知でしょうか?
画像や動画からムービーを作ることができる機能で、以下のようなムービーが簡単に作成できます。
Story Remix で作成したムービー pic.twitter.com/1jHWHxa7YI
— たるこす (@tarukosu) 2017年11月12日
かなりすごい機能なのにまったく話題になっていなくて寂しいので、使い方を簡単に紹介したいと思います。
まずは、ムービーの素材となる画像や動画が必要です。普段は息子の写真や動画を使っていますが、今回はデモ用に猫の映像を使います。以下のサイトから、動画と画像をそれぞれダウンロードしました。
フォトアプリを立ち上げ、左上の「コレクション」を選択すると画像や動画の一覧が表示されます。
ここに表示される画像は、「フォルダー」メニューで設定したフォルダに含まれているものになります。表示するフォルダを追加するには「検索する場所を選択する」をクリックして設定してください。
素材として使う画像や動画は「フォルダー」メニューで設定されているフォルダに移動するか、画像や動画があるフォルダを追加するかして、「コレクション」での一覧に表示されるようにしてください。
左上のメニューで「コレクション」または「作品」を選択すると、右側に「作成」というメニューが表示されます。「作成」をクリックし、さらに「ビデオのリミックス」をクリックします。もし、これらのメニューが表示されない場合は「フォト」アプリのアップデートを試してみてください。
まず、リミックスに使う素材の選択です。使いたい画像や動画にチェックを入れ、「追加」ボタンを押します。
なんと、これだけで自動的にムービーが作成されてしまいます。映像の切り替えはちゃんと曲のタイミングに合わせてくれます。
自動リミックスで作られたムービー(音が出ます) pic.twitter.com/z7SeBUdCNq
— たるこす (@tarukosu) 2017年11月12日
気に入らない場合は「自動リミックス」ボタンを押すと、別のアレンジでムービー作成をやり直してくれます。
自動で作成されたムービーをベースに、手動で修正を加えることもできます。「ビデオの編集」ボタンを押すと、編集画面が表示されます。
編集画面では以下のことが行えます。
「3D 効果」というのが Story Remix 最大の特徴だと思うので、詳しい使い方を紹介します。それ以外の機能はそれほど複雑ではないので、試してみれば使い方はわかると思います。
「3D 効果」は動画素材のみに使える機能で、動画に 3D のエフェクトを付け加えることができます。エフェクトを付けたい動画を選択し、「3D 効果」をクリックすると編集画面が表示されます。
2017/11/12 時点では、55 種類のエフェクトが用意されていました。エフェクトには、画面全体に表示されるものと、画面の好きな箇所に表示できるものがあります。(今のところ、どちらのパターンなのかは試してみるまで分かりません)
ここでは、「風船」というエフェクトを使ってみます。右側のエフェクト一覧から「風船」をビデオ内にドラッグ&ドロップすると、エフェクトが追加されます。
この状態で下の再生ボタンを押すと、以下のようになります。風船は画面内の決まった位置に表示されているというのがわかると思います。
3D効果のテスト
— たるこす (@tarukosu) 2017年11月12日
ポイントへのアタッチなし pic.twitter.com/iwKbNScZsO
ここで、右側の欄の風船のエフェクトで「ポイントへのアタッチ」をオンにし、いかりマークを猫の頭の位置に置きます。
こうすると、以下のようになります。
3D効果のテスト
— たるこす (@tarukosu) 2017年11月12日
ポイントへのアタッチあり pic.twitter.com/PPpn7mUsJv
これ、すごいですよね!
猫が動くのに合わせて風船の表示される場所が移動しているのがわかると思います。
ポイントへのアタッチを使うと、いかりのマークを付けた所のものや場所をトラッキングして、その位置との相対位置を保つようにエフェクトが表示されます。動きが早すぎたり特徴が少なすぎたりするとうまくいかないこともありますが、基本的には何に対してもアタッチさせられます。
先ほどの 3D 効果に加え、動画のトリミング位置や文字の表示などを変更することで、冒頭で紹介したムービーが完成しました。
Story Remix で作成したムービー pic.twitter.com/1jHWHxa7YI
— たるこす (@tarukosu) 2017年11月12日
今回紹介した Story Remix が発表されたのは Build 2017 というマイクロソフトのイベントだったのですが、そこで紹介されていたデモでは「Remix 3D」で公開されている 3D モデルを利用できていました。2017/11/12 時点ではその機能はまだ利用できませんでしたが、そのうちアップデートされて利用できるようになるでしょう!
今後のアップデートにも期待したいと思います。
]]>こんにちは、たるこすです。
ついに、Wii リモコンを HoloLens のコントローラとして使えるようになりました。
この記事では、デモ動画と実装の仕組みを紹介します。
まずはデモ動画をご覧ください。
Wii リモコンを向けた方向にカーソルが移動し、Wii リモコンの B ボタン(背面のトリガー)を押すことでオブジェクトを選択できるようになりました。
以下のサイトの Prerequisites 欄に書かれていますが、2011年11月以降に製造された Wii リモコン は Microsoft 標準の Bluetooth ドライバでは接続できません。
手元にあった Wii リモコンは Wii U を買ったときについてきた新しいものなので、HoloLens と直接接続することはできませんでした。古い Wii リモコンであればもしかしたら接続できるかもしれないので、もし持っている方は試してみてください。
今回は、Wii リモコンは PC と接続し、PC 側で値を読み取って HoloLens に送ることにしました。
以下の記事にもまとめましたが、Wii リモコンはセンサーバー(実際にはセンサーではなく両端に赤外線 LED がついているもの)と組み合わせることで、Wii リモコンを向けている位置を取得することができます。
今回は、Wii リモコンのポインタ位置と A,B ボタンの入力を PC で受け取って HoloLens に送っています。
PC と Wii リモコンを接続し、値を読み取るところまでは以下の記事にまとめています。
上記記事で利用している Unity-Wiimote のサンプルシーンをベースにして、変更を加えていきます。
HoloLens へのデータの送信は、HoloToolkit の Sharing を使っています。HoloToolkit に Prefab として入っている Sharing をシーンに配置します。
Wii リモコンの値の上記記事で利用している Unity-Wiimote のサンプルシーンに Wii リモコンの値を読み取るコードが入っているので、そちらを参考に以下のスクリプトを作成しました。
また、値の送信用に WiimoteMessages.cs を作成しました。こちらは HoloToolkit に含まれる CustomMessages.cs をベースに変更を加えたものです。
これら2つのコードを空の GameObject にアタッチします。
プロジェクトを作成し、MixedRealityToolkit-Unity(HoloToolkit-Unity) と MRDesignLabs_Unity をインポートします。
まずは、 HoloLens, Sharing プレハブを配置します。
Wii リモコンから得られるポインタ位置は、センサーバーをモニターの下に置いた際のモニター上の 2D の位置になります。これを HoloLens で使うためには、HoloLens の座標系での位置に変換する必要があります。そこで、モニターに 2D のマーカー画像を表示し、Vuforia をつかってマーカー位置を認識することでモニターの位置を認識させます。
HoloLens で Vuforia を使う方法については、以下の記事にまとめています。
ImageTarget の子要素として、操作対象とするオブジェクトとスクリーン位置を表す Quad オブジェクトを配置しています。モニターに映ったマーカー画像を認識すると、ImageTarget の座標がマーカーの位置に移動し、子要素もそれに合わせて移動します。
空の GameObject を作成し(名前は WiiMote)ReceiveWiimote.cs と WiimoteMessages.cs をアタッチします。
WiimoteMessages.cs は PC 側アプリで使ったものと同じです。
ReceiveWiimote.cs は以下のようなスクリプトで、PC から送られてきた 2D のポインタ位置から、Wii リモコンの位置姿勢を推定し WiiMote オブジェクトの位置姿勢を変更しています。
まず、2D のポインタ位置と 3D のモニターの位置姿勢(Vuforia を使って設定した Quad オブジェクトの位置姿勢)を使って 3D のポインタ位置を計算します。そして、WiiMote オブジェクトの位置は HoloLens の現在位置の 40cm 下に(かなり適当な値ですが)、姿勢は transform.LookAt
を使って 3D のポインタ位置を向くようにしています。
最後に、先ほど作成した WiiMote オブジェクトの位置姿勢を使ってカーソルを移動させるようにします。WiiMote オブジェクトの子要素として、WiiMoteInput オブジェクト(空の GameObject) を作成し、以下のスクリプトをアタッチします。
作成した WiiMoteInput をカーソルに利用するようにします。
HoloLens > FocusManager > HoloLens Focuser を Inspector で表示し、Input Source に WiiMoteInput を設定します。
次に、MRDesignLabs に含まれる InputSources.cs を編集し、以下のフィールドを付け加えます。
public InputSourceWiiMote wiiMote;
これにより、HoloLens > InputMapping を Inspector で表示したときに、InputShellMap の Input Sources 欄に Input Source Wii Mote が表示されるようになります。
以上で HoloLens 側のアプリは完成です。
アプリの実行は以下のような手順で行います。
再度デモの映像を貼っておきます。
Wii リモコンを使った操作は HoloLens 標準の操作方法 (Gaze, Air-Tap) に比べて直感的で使いやすいと感じました。センサーバーの配置や PC 側の準備が必要だったり、センサーバーがある方向にしか使えないという問題はありますが、展示コンテンツでは十分活用できそうです。
センサーバーの LED の間隔を広くして遠めに配置すれば Wii リモコンを動かして認識される範囲が広くなるはずなので、是非試してみたいと思っています。
]]>こんにちは、たるこすです。
ここのところ、Wii リモコンを HoloLens のコントローラとして使おうとしています。
前回はセンサーバーの自作方法について紹介しました。
今回は Unity で Wii リモコンの入力を受け取る方法についてです。
Wii リモコンは Wii U を買ったときについてきた Wii モーションプラスコントローラを使っています。
以下のサイトの Prerequisites 欄に書かれていますが、2011年11月より前に製造された Wii リモコン は Microsoft 標準の Bluetooth ドライバで接続できるそうです。ですが、それ以降の Wii リモコンはMayflash Wireless Sensor のようなものを使うか、東芝の Bluetooth ドライバを使う必要があるようです。
今回は、東芝の Bluetooth ドライバを使うことにしました。そのために、東芝の Bluetooth ドライバを採用している Planex の BT-MicroEDR2X を購入しました。 付属の CD にドライバが入っています。
インストールを行い、Bluetooth 設定を開くと、以下のようなウィンドウが表示されます。
Wii リモコンの 1 ボタンと 2 ボタンを同時押しし、ペアリング待ち状態にしたうえで、左下の新しい接続をクリックします。
接続設定はカスタムモードを選択します。
以下のように Bluetooth 機器として見つかったら、それを選択して「次へ」を押します。
あとは「次へ」や「OK」を押していけば接続が完了します。
うまく接続されれば、以下のように緑と黄色の線がつながったようなアイコンが表示されます。
以下のサイトから、Touchmote をダウンロードします。
私は 64bit 用のインストーラをダウンロードしました。exe を実行するとインストールされます。
PC と Wii リモコンが Bluetooth 接続された状態で TOUCHMOTE を起動すると、以下のようなウィンドウが表示され Wii リモコンが接続されていることがわかります。
この状態で、センサーバーに向かって Wii リモコンを動かすと丸いカーソルが表示され、A ボタンを押すとスクロール B ボタンを押すとクリックができます。
Wii リモコンの入力を PC への入力に対してどのように割り当てるかは、コンフィグで設定することができます。Settings を開き、「CONTROLLER CONFIG」をクリックすると設定画面が表示されます。
デフォルトでは Default, Mouse pointer, Steering Wheel の 3 つのレイアウトが定義されていますが、既存のレイアウトの設定変更や新しいレイアウトの追加も行えます。
HoloLens 用の入力に使う場合には、Touchmote ではなにも操作してほしくないため、何もしないためのレイアウトを作成します。
以下のようにすべての入力を Disable に紐づけています。また、"Available in Layout Chooser" にチェックを入れておきます。こうすることで、Wii リモコンの HOME ボタンを 3 秒間長押しした際に出てくるレイアウト選択メニューで、作成したレイアウトを選択できるようになります。
Unity-Wiimote という Unity で Wii リモコンの入力を受け取れるプロジェクトが公開されています。
release ページに zip がありますが、ここに含まれている unitypackage はサンプルシーンが入っていないので、リポジトリをクローンして使ってみます。
クローンしたら Unity で開きます。Unity のバージョンは 2017.1.2f1 を利用しました。
Scene という名前のサンプルシーンを開くと、以下のように Wii リモコンと黒い板が表示されました。
実行し、"Find Wiimote" ボタンを押すと Wii リモコンの入力(押されているボタンとポインタ位置)が表示されます。
ただし、Unity Editor で実行する際は、起動する順序にコツがいりました。Touchmote は一旦終了させ、先に Unity を実行して "Find Wiimote" を押します。そのあと Touchmote を起動します。この順序で起動させないと、Wii リモコンのポインタ位置が Unity 側でうまく取得できませんでした。
アプリをビルドして実行した際はこの問題は起きず、Touchmote は起動させたままで大丈夫でした。
実行時は以下のような感じです。緑色の点がポインタの位置、白い2つの点が Wii リモコンから見えているセンサーバーの LED の位置です。
次は、当初の目標通り Wii リモコンを HoloLens のコントローラとして使いたいと思います。
]]>こんにちは、たるこすです。
今回は Visual Studio Code で Emacs キーバインドを使う方法についてです。
以前、以下の記事で「Emacs Keymap」をインストールすれば良いと書いたのですが、久しぶりに調べてみると状況が変わっていたので改めて記事を書きたいと思います。
「Emacs Keymap」は hiro-sun という方が作成された拡張機能ですが、リポジトリを見てみると 2016/11/10 で開発が止まっています。
そこで、「Emacs Keymap」をフォークしているリポジトリの更新状況を見てみます。 github.com
そうすると、こちらのリポジトリが活発に更新されているようです。 github.com
VSCode の拡張機能でも「Emacs Friendly Keymap」という名前で提供されています。
「Emacs Friendly Keymap」をインストールしたら、「Emacs Keymap」は無効化もしくはアンインストールしてしまいます。
「Emacs Friendly Keymap」の説明を見ると、オリジナル (hiro-sun さんの Emacs Keymap) と比べて以下の変更があると書かれていました。
そのほかにもいくつかのキーバインドが追加されているようです。
「Emacs Friendly Keymap」で設定されていないキーバインドがある場合、リポジトリに Pull Request を送るのが正攻法ですが少しハードルが高いです。そこで、キーボードショートカットの設定でキーバインドを追加してみます。
ファイル > 基本設定 > キーボードショートカット と選択することでキーボードショートカットのタブを開きます。
タブが開いたら keybindings.json のリンクをクリックします。
今回は、以下のように編集し、キーバインドを設定しました。
「Emacs Friendly Keymap」は基本的な Emacs キーバインドはほとんど使えるようになっています。是非使ってみてください。
]]>こんにちは、たるこすです。
少し前に久しぶりに Wii U で遊んだのですが、その時に Wii リモコンを HoloLens のコントローラとして使えると面白いなぁと思ったので挑戦してみようと思います。
まずは下準備として、 Wii が無くてもセンサーバーを使えるようにするため、センサーバーを自作してみました。
センサーバーとは、Wii リモコンを向けた場所を認識するためのもので、モニターの上や下に設置して使います。
"センサー"と名前についてはいますが実際にはセンサーバーからは赤外線がでているだけで、受光部はリモコン側についています。純正のセンサーバーには左右それぞれ 5 つずつ LED がついていますが、自作する場合には左右に少なくとも 1 つずつの LED を設置すればセンサーバーとして機能するようです。
以下のものを用意しました。(といっても全部家にあったので新しく買う必要はありませんでした。)
なんでも OK
配線用にこんな感じのものを利用
サンハヤト ジャンプワイヤキット SKS-140 単線タイプのワイヤのセット品
電源モジュールへの電源供給用
スマホを充電用でよく使われる、USB が刺さる AC アダプタ
akizukidenshi.comhttp://akizukidenshi.com/catalog/g/gI-04311/
部品を準備してしまえば、あとは簡単です。ブレッドボードに部品をさしていきます。
まずは電源モジュールをブレッドボードに刺し、5V → 赤外線 LED → 75Ω抵抗 → GND と配線します。LED には向きがあるので注意してください。また、違う部品を使う場合には、LED への電流量を考えて適切な抵抗を計算して使用してください。
もう片方の LED も同様に配線します。
これで完成です。電源をつなぎ、電源モジュールのスイッチを押して電源モジュールの LED が点灯すれば OK です。 赤外線は肉眼では見えないので、赤外線 LED から光がでているかどうかはカメラで確認するのが便利です。
ただし、今回はじめて知ったのですが、スマホの外側カメラには赤外線をカットするフィルターが入っているようで、内側カメラと外側カメラで見た際に見え方に違いがあります。
Nexus 5 では外側カメラだと光が弱く、内側カメラだと明るく光って見えました。
iPhone 5S では外側カメラだと光っていないように見え、内側カメラだと光って見えました。
はじめはこのことを知らなかったので、外側カメラで見て光っていないと思いしばらく悩みました。
Wii を起動 (Wii U の場合は Wii モードを起動)し、リモコンを自作センサーバーに向けて動かしてみます。画面のポインタが動けば OK です。
まずはお試しで作ったので赤外線 LED 2つの幅が狭く Wii リモコンを動かせる幅が狭かったのですが、LED を離して設置すればリモコンを大きく動かしても認識できそうです。
]]>こんにちは、たるこすです。
ついに HoloLens とルンバ(Roomba)を組み合わせた HoloRoomba が動くようになりました! くまちゃんを乗せることにより見た目もかわいくなっています。
まずは動画をご覧ください。
Roomba(とラズベリーパイ)だけでも移動はできますが、部屋の中のある場所に自動で移動するというのは難しいです。そこで、HoloLens を使います。HoloLens は空間の 3D マップを作成しその中で自分がどこにいるのかというのを把握できるため、現在地と目的地の差分から移動方向を決めてルンバに指令を送り、目的地に移動することができます。というわけで、約 40 万円で自律移動ロボットを作ることができます。
また、HoloLens の映像を見ながら人が操縦できるようにすれば、遠隔地から操縦して部屋の中を動き回ったり AR 戦車ゲームのようなこともできそうです!
ルンバは通常の掃除用のものを使っています(ルンバ 622)。カバーを外し、ジャンパワイヤと USB シリアル変換アダプター を使って Raspberry Pi に接続することで、コマンドを送って動作させられるようになります。
詳しくは以下のブログ記事に書いています。 tarukosu.hatenablog.com
次に、Raspberry Pi 上に Web サーバを立て、WebSocket を使って移動の指示を受け取れるようにします。
詳しくは以下のブログ記事に書いています。 tarukosu.hatenablog.com
Unity で HoloLens アプリを作成しました。
以下の動画のように、空間をタップすることで目的地を設置します。
アプリ内のメニューで "Start" ボタンをタップすると移動が開始されるので、素早く HoloLens をルンバの上に置きます。
ルンバの移動方向は、HoloLens の現在位置と目的地の差分から決定します。HoloLens の前方向と、現在位置から目的地への方向の間の角度を算出し、角度が大きければ目的地が正面を向くように回転させます。角度が小さくなれば、前方への移動と回転を同時に指令します。スクリプトでは以下のようになっています。
上のスクリプトに出てくる RoombaWebSocketController
は WebSocket を使って Raspberry Pi に指示を送るためのクラスです。HoloLens で WebSocket を使う方法は以下の記事に書いているので、気になる方はご覧ください。
「ヒミツのくまちゃん」というぬいぐるみのようなおもちゃが売られています。イヤフォンジャックから音を流すことで、くまちゃんが体と口を動かしながら音を出してくれます。
こどもクラブ ヒミツのくまちゃん シャーベットピンク 2930012 85827
流す音声は Raspberry Pi で Open JTalk を動かして音声合成しました。
次は、Microsoft の Immersive Device (VR ヘッドセット) を使って、遠隔地から HoloRoomba を操縦できるようにしたいと思っています。
]]>こんにちは、たるこすです。
最近 HoloLens を使って Roomba を操縦しようとしているのですが、その際に HoloLens で WebSocket を使えるようにしたので、その方法についてまとめようと思います。
Unity Editor で実行する場合と HoloLens 上 (UWP) で実行する場合で実行環境が違っており、通信周りの API が違うため同一のコードは動きません。そこで、それぞれの環境に向けて、WebSocket 用ライブラリを作成します。
以下のブログを参考にさせていただきました。
以下の記事のとおり、websocket-sharp をビルドします。 qiita.com
作成した websocket-sharp.dll を Unity に読み込み、以下のように Inspector で Editor でのみ利用するように設定します。
始めは冒頭で紹介したブログで紹介されている以下のリンク先のコードを使ってみたのですが、私の環境だとなぜか WebSocket の接続がすぐに切れてしまいました。 github.com
別のコードを探したところ、以下のリポジトリが見つかりました。
リポジトリに含まれている UwpWebsocket.cs を Unity にインポートするだけで利用できます。
UwpWebsocket.cs が websocket-sharp のメソッド名にあわせてくれているため、利用する側はコードを共通化することができます。
かなり省略していますが、以下のようなコードで WebSocket を使うことができました。
using WebSocketSharp; ... class RoombaWebSocketController : MonoBehavior { ... WebSocket websocket; ... public void Connect(){ websocket = new WebSocket(uri); websocket.ConnectAsync(); } public void Disconnect() { websocket.Close(); } public void SendCommand(string msg) { if(websocket != null && websocket.IsAlive) { websocket.Send(msg); } } ... }
@dy_karous さんから以下の情報をいただきました。ありがとうございます!
]]>UWPでWebsocketを使うならば、MS純正のMessageWebSocketかWebSocket4Netなんかもおすすめです。https://t.co/a9AEYZPYdu https://t.co/wLFS7CBZJS
— d_yama (@dy_karous) 2017年10月1日
今回は Raspberry Pi にルンバ操縦用のサービスを立て、PC やスマホから操作する方法について紹介します。
ブラウザからコントロールできるようになった! pic.twitter.com/wIK613ofsl
— たるこす (@tarukosu) 2017年9月10日
今回紹介するコードは、以下のリポジトリで公開しています。
使うためには、Raspberry Pi で以下のコマンドを実行してください。
リポジトリのクローン
$ git clone https://github.com/tarukosu/RoombaRPC.git
サブモジュール(ルンバコントロール用ライブラリ)のセットアップ
$ git submodule init $ git submodule update $ touch roomba/__init__.py
依存パッケージのインストール
$ apt install python-dev $ pip install pyserial $ pip install zerorpc
RPC サーバの起動
$ python server.py
操作用 Web サービスのセットアップ
(RPC サーバとは別のコンソールを開いて) $ cd server $ sudo apt install libzmq-dev $ npm install $ npm -g install bower $ bower install virtualjoystick.js
app.js, index.html 内のIPアドレスをRaspberry Pi の IPアドレスに書き換え
Web サーバの起動
$ node app.js
npm install
の際に zmq のインストールに失敗する場合は、以下のページが参考になるかもしれません。
zerorpc という ZeroMQ と MessagePack を使った RPC ライブラリを利用しました。
Raspberry Pi で動作するサーバのコードは以下のようになります。
RoombaRPC クラスで定義したメソッドが、zerorpc を使ってマシン内の別サービスや別のマシンから呼び出せるようになります。
virtualjoystick.js というライブラリを使い、ブラウザ上でジョイスティックのような操作ができるようにしました。操作された際の値は websocket を使ってサーバ側に送信されます。サーバ側では受け取った値を引数とし、zerorpc を使って RPC サーバにコマンドを送ります。
次回は HoloLens を使って Roomba を自律移動させるというホロルンバを紹介します。
]]>youtube で動画が公開されているので、ぜひご覧ください。 www.youtube.com
前半のセッションについて、簡単に振り返ってみます。
例のハッカソンで作られた Artgram という HoloLens アプリの機能として、音声認識による画像検索を作られた話です。
HoloLens の標準音声入力は英語のみなので、日本語の認識ができません。そこで、クラウド音声認識サービスを利用したとのことです。
主な音声認識サービスとして Google のものと Microsoft のものがあったが、UWP(HoloLens) からストリーミング音声認識サービスを使うなら、実装の都合上 Bing Speech API のほうが楽だとのことです。
ハッカソンでは実装しなかったが、WebRTC を使って API に常時接続すれば、リアルタイム音声認識もできるようになるはずとのことです。
短期間の実装のため、音声認識に合わせて Microsoft Bing Image Search を利用。
Unity と Microsoft API の連携であれば、実装例があるはず…
ただし、HoloLens 上で動かすには Castle Windsor というライブラリに依存しているところを削除する必要がある。
ライブデモで、「とある魔術の禁書目録」という言葉を認識し、検索した画像の表示が行えていました。
これからの UI として音声入力は非常に重要になって来そうなので、自分でも音声認識を試してみたいと思います。
ちびっこにかっこよく見られたい! ということで、指パッチンエアタップの講習がありました。
HoloLens を初めて試す人にエアタップを教えるときは「親指と人さし指をくっつけて離す」というのがわかりやすいとのこと。それを進化させ、中指で音を鳴らしつつエアタップするのが指パッチンエアタップです。
また、以前澤さんもおっしゃっていましたが、ゲイズ(視線カーソル)を合わせてから腕を上げてタップするのがかっこいいとのことです。
PCを背負って WinMR を装着し、Insta 360 one(全天球カメラ)を自撮り棒にとりつけて自身を撮影します。Insta 360 one の映像と WinMR の映像を組み合わせると一人でデモ動画を撮影できます。
GoPro などでも自撮りはできますが、Insta 360 one を使うと撮影時に画角やフレーミングを気にしなくてよく、後から編集できるので楽だそうです。
下記の2つのアセットが DLL を使っており、 UWP に対応していない
残念ながらスタッフの作業で講演を聞くことができませんでした。後で動画で見ようと思います。
後半の LT のコーナーで、Meetup vol.2 以来となる LT 発表をしました。時間の都合上、ほとんどデモ動画を見せるだけになってしまったのですが、実装の詳細は過去のブログ記事に書いているので良ければご覧ください。
HoloLens Meetup 初参加という方も多く、公演の合間の休憩時間の HoloLens デモは非常に盛り上がっていました。今後は Immersive Device から Windows Mixed Reality を始めるという方が増えてくると思うので、そういった方を巻き込んでコミュニティがどんどん盛り上がってくると嬉しいです。
]]>ブラウザからコントロールできるようになった! pic.twitter.com/wIK613ofsl
— たるこす (@tarukosu) 2017年9月10日
ルンバと Raspberry Pi の接続については、こちらの記事を参考にさせていただきました。
また、上記記事でも書かれている通り場合によってはルンバを壊してしまう可能性があるため、試される方は自己責任でお願いします。
Amazon で調べて安そうなものを購入しました。900番台のルンバは有線での通信ができないそうなのでご注意ください。
【国内正規品】 iRobot ロボット掃除機 ルンバ 622 ホワイト
棚の中で眠っていた Raspberry Pi 3 を使いました。
Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Element14版, Clear)-Physical Computing Lab
Raspberry Pi 3 用です。
この変換アダプターを使うことで、Raspberry Pi 側は USB で接続することができます。
USB シリアル変換アダプターと Raspberry Pi との接続に1本、Raspberry Pi への給電に1本必要です。
ルンバと変換アダプターとの接続にオス-オスの普通のジャンパワイヤを3本使います。
Raspberry Pi への給電用として使います。
Anker PowerCore 10000 (10000mAh 最小最軽量 大容量 モバイルバッテリー) iPhone&Android対応 *2017年9月時点
詳細は省略しますが、新しく Raspberry Pi を購入した場合は OS のインストールが必要です。今回は、以前インストールしていた Raspbian という標準の OS を利用しています。
まず、ルンバ上面のカバーを取り外します。ダストボックスを取り外し、取り外したあたりからカバーを上に持ち上げたらガコッと外れました。
まず、USB シリアル変換アダプターが 5V の設定になっていることを確認してください。
USB シリアル変換アダプターの RX, TX, GND にそれぞれジャンパワイヤをさします。
ルンバ側は、中段左に変換アダプターの TX からのワイヤ、中段右に RX からのワイヤ、下段中央に GND からのワイヤをさします。
最後に、USB シリアル変換アダプターと Raspberry Pi を USB ケーブルで接続します。
Raspberry Pi で以下のコマンドを実行し、デバイス名を確認します。 私の場合は /dev/ttyUSB0 で認識されていました。
$ ls /dev/tty*
しかし、以下のように権限を確認すると、一般ユーザに Read Write 権限がありません。
$ ls -l /dev/ttyUSB0 crw-rw---- 1 root dialout 188, 0 9月 9 20:54 /dev/ttyUSB0
そこで、 /etc/udev/rules.d/50-udev-default.rules
を作成(すでにある場合は編集)し、以下の行を記入します。
KERNEL=="ttyUSB[0-9]*", GROUP="dialout", MODE="0666"
USBケーブルを抜き差しすると、以下のように権限が変更されました。
$ ls -l /dev/ttyUSB0 crw-rw-rw- 1 root dialout 188, 0 9月 9 21:05 /dev/ttyUSB0
この部分は、以下のページを参考にしました。
上記PDFの仕様を読んでコマンドを送信することも可能ですが、以下のライブラリでコマンドをラップしてくれているのでこれを使います。
リポジトリのクローンと pyserial のインストールを行います。
$ git clone https://github.com/martinschaef/roomba.git $ pip install pyserial
roomba フォルダ内で以下のスクリプトを作成し、実行します。
うまくいけば、センサの値が表示されルンバが少し回転します。
また、roomba に含まれる starwars.py を実行すると、ダースベイダーのテーマが演奏されます。
このライブラリに入ってたサンプルプログラム(音楽の演奏)を動かしてみたhttps://t.co/j6rkcmiTH8 pic.twitter.com/EKMWasv3mi
— たるこす (@tarukosu) 2017年9月9日
今回のブログは一旦ここまでとして、次回はこのライブラリを使って遠隔から操縦できるようにしていきます。
]]>HoloTooliitのバージョンやUNET対応などでパッケージが分かれているようです(UNET対応版の1.5.7.2は未検証です)。
1.5.7.0でCalibrationアプリでカメラ画像が出ないことがあります。
解決方法を教えてもらったので記録しておきます。
DeckLingManager.cppの72行目あたり
videoDisplayMode = bmdModeHD1080p5994
これを
videoDisplayMode = bmdModeHD1080i5994
にすると動作します。または「1080p」などに該当する部分を環境に合わせて変更します。
SpectatorViewの環境を作るときはGoPro HERO 5とBlackmagic Intensity Shuttle USB 3.0を使うことが多いのですが、Blackmagic Intensity Shuttle USB 3.0が1080pに対応しておらず1080iのみでしか出力できないためと思われます。リファレンスのIntensity Pro 4K Captureは1080pに対応しています。
【国内正規品】 GoPro ウェアラブルカメラ HERO5 Black CHDHX-501-JP
Blackmagic Design キャプチャーカード Intensity Shuttle for USB 3.0 000856
スライドはこちら。
Xtion2やOpenNI2、NiTE2の概要と、KinectやRealSenseでの事例です。内容的には数年前のおさらいです。
2013年にPrimeSenseがAppleに買収されたことで、XtionやOpenNIがクローズされました。その時期からASUSとしてはXtion2のセンサーを探していたそうで、やっと今年製品としてリリースすることができたそうです。
センシング形式はToF、チップはTIを使っています。
流通はは来週あたりから開始されるとのこと。
Kinect v2やRealSenseとの仕様上の性能比較は下記の通りです。
センサー性能的にはKinect v2、サイズ的にはRealSenseに近くなっています。
特長を下記に列挙します。
購入にあたっての注意事項も列挙します
点群精度についてはかなり微妙な感じがします。。。
発表会でASUSの製品担当の方もいたのでフィードバックしました。せっかくOpenNIを使える環境が復活したので、今後の改善に期待したいです。
Depth画像は、かなりきれいに取れています。
点群については、状況確認中です。
PLYで落としてみた。
— 中村 薫 (@kaorun55) 2017年4月27日
正面から見ると良さそうなんだけど、横からみると波うってる気がする。 pic.twitter.com/KcHmNRvm8L
天井と壁もとってみたけど、やっぱりもう一声欲しいところ。 pic.twitter.com/VvYZNVnWxd
— 中村 薫 (@kaorun55) 2017年4月27日
]]>PCLのビューアーで出してみた(左側はカーテンです) pic.twitter.com/9spYjmbWM2
— 中村 薫 (@kaorun55) 2017年4月27日
Windows Mixed Realityヘッドセットについて「HoloLens互換」や「廉価版HoloLens」という言い方をされることがありますが、基本的には別物と考えた方が良いです。
互換があるとすれば「HoloLensと同じ排他の3DアプリがUWPで動作する」くらいです。ソフトウェア開発では近いところにいますが、ハードウェアや体験については別々にと思った方が間違いありません。
製品としては「Mixed Realityヘッドセット」ですが、ドキュメントでは「Immersive(イマーシブ:没入)ヘッドセット」と記載されており、Oculus RiftやHTC ViveなどVRヘッドセットに近いです。 ドキュメントにある機能的な違いを下記表にしました。
HoloLens同様Unityでの開発が中心となります。
開発環境はこちらのfor immersive headsetsを参照。
概要としては下記です
AcademyはMRヘッドセット対応しており、Mixed Reality 250が追加され、HoloLensとMRヘッドセット用アプリのSharingを学べます。
HoloLensのARだけでなくMRヘッドセットでVR環境もできるようになりました。 MRヘッドセットはシースルーやジェスチャーがないなどHoloLensと体験の違いはありますが、PC接続のためHoloLensよりも高負荷をかけられることがメリットになります。
年末にリリースが予定されているモーションコントローラーが出てからが本番ですね。
]]>順番は話の流れ。
HoloLensを買えば実現できる基本的な事例ですが、いままでだと研究対象にもなっていた事例です。
HoloLensを装着した人とPCの人ととのSkypeで、HoloLens装着者の視界が見えるので遠隔でサポートできます。ここでは簡単なSkype単体を使った電気工事の事例ですが、あとで紹介するthyssenkruppのエレベーターのようにアプリに組み込んで(おそらく独自に実装して)業務のサポートツールとして使うこともできます。
表示するモデルの大きさに対する流れの作り方、センサーデータのシミュレーションの話をするときに使っています。
動画ではわかりづらい重要な要素がいくつかあります。
IoTやDeep Learning/Machine Learning、スマートグラスと話をつなげるときに使っています。
いくつかの要素の複合体です。
HoloLensを使った計測事例です。計測や精度の話をするときに使っています。
キッチンのリフォームシミュレーションです。実際に店舗でも使われているようです。
店舗訪問前、店舗見学中、店舗側の情報解析の3つに分かれており、ビジネス的な要素がかなり強いです。
今現在引き合いの多い建築向け動画です。
BIMや3D CADで設計した建築データを、建築中の場所に重畳させる、配管を通してメンテナンスに活用するといった、3D CADデータをより長期的に活用する方法について示されています。
こちらも建設向け動画です。
建設対象のモデル、工程、記録などがすべてHoloLens内に入っています。
橋のスケーリングを変更できるので、設計データと実際の建設物との大きさのイメージがリンクされるので教育目的への活用も期待できます。
さまざまな要素により現在の実現は難しいですが、よく話にでます。
リルタイムで3Dデータを再構築し、遠隔コミュニケーションに使用します。
より現実的なところで3D動画です。
HologramsのバレリーナやBuild 2017でのシルクドソレイユのパフォーマンスなどに使われています。
後処理型ですが、各フレームごとにメッシュ情報とテクスチャを持っており、3Dの動画といえる状態になっています。
おおよそ上記の動画で説明しています。
分野もさまざま用途のさまざまですが、分野にとらわれず要素を分解して組み立てると多くの方面に使えると思っています。
]]>7/15(土)に「Tokyo HoloLens ミートアップ vol.4」を開催しました。 hololens.connpass.com
今回はスタッフ含めて146人の参加となり、前回よりも多くの方にお越しいただけた印象です。 また試験的に司会など担当をいままでと変えてみました(直前にいろいろありましたが、元々そういう話をしてました)。
スタッフとして参加してくれた方も20人ほどとなり、ミートアップ以外にできることも模索していこうと思います。
同日、となりのセミナールームBにて「第1回 IPABセミナー Mixed Realityとその産業応用」も開催されており、ぼくはそちらにてHoloLensの概要のお話をしていました。
第1回 IPABセミナー Mixed Realityとその産業応用 — IPAB
こちらは参加者が大学の先生などアカデミックな方だったので、ミートアップとはまた違った話ができました。 途中でセミナー参加者の方にもミートアップを覗いてもらい雰囲気を体感してもらいました。
とはいえ、Device PortalのFile Explorerからアクセスできる方が何かと便利なので、必然的に「カメラロール」、「ドキュメント」、「アプリのローカルフォルダ」の3種類になると思います。
それぞれの特長をまとめます。これらを踏まえて決めればよいかと思います。
こちらのリポジトリに置いています。
カメラロールへのファイル書き込みサンプルです。
// カメラロール // ピクチャライブラリの権限が必要 // フォルダは作れない { var file = await KnownFolders.CameraRoll.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting); using (var stream = await file.OpenStreamForWriteAsync()) { var bytes = System.Text.Encoding.UTF8.GetBytes(@"テストてすとtest"); await stream.WriteAsync(bytes, 0, bytes.Length); } }
権限はUnityエディター上で「PuctureLibrary」をチェックします。
UWPプロジェクトの上書きなどで権限がうまく入らない場合には「Package.appxmanifest」の「ピクチャライブラリ」を直接チェックしてください。
ドキュメントへのファイル書き込みサンプルです。
// ドキュメントフォルダ // 1. Package.appxmanifestを開き // 「宣言」から「ファイルの種類の関連付け」を行い、書き込むファイルの拡張を追加する // 2. Package.appxmanifestを「コードを表示」で開き下記を追加する // <uap:Capability Name="documentsLibrary" /> { var folder = await KnownFolders.DocumentsLibrary.CreateFolderAsync("DocumentLibraryTest", CreationCollisionOption.OpenIfExists); var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting); using (var stream = await file.OpenStreamForWriteAsync()) { var bytes = System.Text.Encoding.UTF8.GetBytes(@"テストてすとtest"); await stream.WriteAsync(bytes, 0, bytes.Length); } }
ドキュメントフォルダへのアクセス権限は「Package.appxmanifest」への設定と、ファイル関連付けの2つを行います。
Package.appxmanifestを「コードを表示」で開き下記を追加します。
<uap:Capability Name="documentsLibrary" />
Package.appxmanifestを開き「宣言」から「ファイルの種類の関連付け」を行い、書き込むファイルの拡張を追加します。
特に権限の必要もなく書き込めます。ただし、デプロイごとにファイルが初期化されます。 ファイルは「User Files\LocalAppData\<アプリ名>\LocalState」 以下に作成されます。
// ローカルフォルダー // 「User Files\LocalAppData\<アプリ名>\LocalState」 以下にできる { var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync( "DocumentLibraryTest", CreationCollisionOption.OpenIfExists); var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting); using (var stream = await file.OpenStreamForWriteAsync()) { var bytes = System.Text.Encoding.UTF8.GetBytes(@"テストてすとtest"); await stream.WriteAsync(bytes, 0, bytes.Length); } }]]>
このため、Unityの.NET 3.5とUWPのコードが共存することになります。特に問題になるのが、UWPではasync/awaitを多用しますが、Unityの環境ではC#のバージョン的にそもそもasync/awaitが使えないため、コードの多くがこれを想定していません。
ここではUnityのアプリでasync/awaitを使う方法について紹介します。またasync/awaitでマルチスレッドになるので、同期の方法についても合わせて紹介します。おかしなところがあったら教えてください。
UWPではないUnityでのasync/awaitはこちらが詳しいです。
UWPにビルドしたコード上でasync/awaitを使う方法を2つ紹介します。
リポジトリはこちら
ちなみにUWP内のみコードを有効にするには #if UNITY_UWP をつけます。他にもいくつか定義がありますが、UWPビルドのどこかたタイミングで有効になるので、ビルドエラーになる場合もあります(細かくは調べていません)。
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; #if UNITY_UWP using System.Threading.Tasks; #endif public class AsycnAwaitTest : MonoBehaviour { public TextMesh textMeshAynsc; public TextMesh textMeshCoroutine; // Use this for initialization void Start() { #if UNITY_UWP // Task.Runでasyncする Task.Run(async () => { UnityEngine.WSA.Application.InvokeOnAppThread(()=>{ textMeshAynsc.text = "Task.Run before : " + Time.time; }, true); await Task.Delay(5000); UnityEngine.WSA.Application.InvokeOnAppThread(() => { textMeshAynsc.text = "Task.Run after : " + Time.time; }, true); }); StartCoroutine(HeavyTask()); #endif } private IEnumerator HeavyTask() { #if UNITY_UWP // WaitWhileでまつ textMeshCoroutine.text = "Task.Run before : " + Time.time; var task = Task.Delay(5000); yield return new WaitWhile( () => !task.IsCompleted); textMeshCoroutine.text = "Task.Run after : " + Time.time; #else yield return null; #endif } }
Task.Run()で非同期タスクを起こし、この中のメソッドをasyncで定義すればその中ではawaitが使えます。これがシンプルだと思います。
StartCoroutine()で非同期処理を開始します。 コルーチンはasyncにできずawaitが使えないので、非同期メソッドのTaskを受け取りyield return new WaitWhile()で待ちます。従来のコードとの整合をとりつつ非同期メソッドを使う感じでしょうか。
上記2つの最大の違いはTask.Run()の場合はマルチスレッド、StartCoroutine()の場合はシングルスレッドになります(スレッドを生成せずメインスレッドを分割する)。
これによって何が変わるかというとTask.Run()内ではGameObjectへのアクセスができなくなります。WPFなどと同様にUIのオブジェクトはメインスレッドのみアクセスが可能です。そのため、ここで使っている3D TextのTextMeshをTask.Run()内で直接触ると例外が発生します。通常はSynchronizationContextで制御しますが、Unityにはこの仕組みがありません。
ではどうするかというと、UnityEngine.WSA.Application.InvokeOnAppThread()を使います。これによってアプリスレッド(Unityのメインスレッド)で処理されます。
もう一つ、UnityEngine.WSA.Application.InvokeOnUIThread()というのもありますが、こちらはXAMLのメインスレッドのようです。
ドキュメントはこちら docs.unity3d.com
]]>「Windows Holographic」は「Windows Mixed Reality」に名前が変わったようです。
Windows Mixed Realityは$299~という価格でHoloLensの$3,000とはだいぶ違うのですが、値段相応に環境もかなり違います。ということで相違点をまとめてみます Windows Mixed RealityのHMDは想像の範囲でもあるので随時更新します。
HoloLens | Windows Mixed Reality HMD | |
---|---|---|
価格 | $3,000/$5,000(PC不要) | $299~(別途PCが必要) |
動作形態 | スタンドアロン | PC接続 |
ケーブル | なし | あり |
現実の見え方 | シースルー | 外界の映像は見えない |
パフォーマンス | 固定(CPUはAtom) | PCに依存 |
アプリ実行環境 | UWP | UWP |
環境センシング | Inside-Out | Inside-Out |
それらを解決する一つの方法として、Spectator Viewというものがリリースされました。
試してみて動くところまではできました。右側のカラー映像が結果です。
なんとなく動いた pic.twitter.com/MVE4Gtj7ps
— 中村 薫 (@kaorun55) 2017年2月14日
間違っているところなどあればフィードバックいただけると助かります。
Spectator ViewはHoloLensアプリに第三者視点を提供します。いままでもMixed Reality Captureでできましたが、よりきれいな映像にすることができます。
Spectator Viewの特長をまとめるとこのようになります。
制約としては下記が考えられます。
このことから、開発したアプリを公の場で発表する、プロモーションビデオの撮影という用途になると思います。
Microsoft HoloLens: Uses for Spectator View
必要なソフトウェアやリグのための3Dモデルはこちらにあります。cloneするかHoloLensCompanionKit全体をダウンロードしてください。
Spectator Viewには写真の機材が必要です。
「3D Printed Adapter」および「Aluminum HoloLens Bracket」は自分で作る必要があります。
このほかに下記機材が必要です
カメラとレンズは下記を推奨のようです。合わせて約50万円です。
Canon デジタル一眼レフカメラ EOS 5D Mark III ボディ EOS5DMK3
Canon 単焦点広角レンズ EF14mm F2.8 L II USM フルサイズ対応
Hotshoeはちょっと値段が高い(元のAmazon.comが$6(600円)くらい、Amazon.co.jpが6000円くらい)ので別で買った方がよさそうです。。。
HDMIキャプチャボードは下記のようです(PCIe接続)。約24,000円です。
Blackmagic Design intensity pro 4k ビデオキャプチャボード
カメラについてはHDMI出力できれば良さそう。キャプチャーボードは最初の写真を見る限りUSB接続でも良さそうということで、下記2つを購入して試しました。両方で約8万円です。
Blackmagic Design キャプチャーカード Intensity Shuttle for USB 3.0 000856
手順はこちらに詳しく書いてあります。
必要なソフトウェア
Desktop Video SDKが見つけづらかったので注意してください。下記画像の「Desktop Video 10.8.3 SDK」です。
それぞれインストールを行います。OpenCVは展開してCドライブ直下においてください(「C:\opencv」となるように)。
カメラとHoloLensのRGBカメラの位置を合わせるためにキャリブレーションを行います。
「HoloLensCompanionKit\HoloLensCompanionKit-master\SpectatorView\Calibration」にある「Calibration.sln」を開きます。
「dependencies.props」というファイルがあるので、下記2つのパスが通っていることを確認してください。
実行するとカメラの映像が表示されます。
つぎにHoloLensとカメラを配置します。今回はリグがないので、HoloLensの上にGoProをおいているだけです。
HoloLensとPCはUSBケーブルで接続します。
Calibrationプロジェクトの「stdafx.h」を開き、デバイスポータルのユーザー名とパスワードを設定します。事前にHoloLensのデバイスポータルをONにして、ユーザー名とパスワードを設定してください。
次に キャリブレーションを行います。GitHubにあるキャリブレーションパターンを印刷します。固めのボードに張るとよいと思います。
Caribrationアプリを起動し、キャリブレーションボードを動かします。途中Mixed Reality Captureが起動するので、HoloLensのカメラ撮影時のLEDが点滅します。
「C:\Users\<ユーザー名>\Documents\CalibrationFiles」にカメラ画像とHoloLensの画像および「CalibrationData.txt」が生成されます。
必要かどうかわかりませんが「HoloLensCompanionKit\SpectatorView\Compositor」をビルドします。HoloLensの実機情報をやりとりする部分です。PC側のCompositorはx64、HoloLensに組み込む側はx86ですので両方のビルドを行い「CopyDLL.cmd」を実行します。
「HoloLensCompanionKit-master\SpectatorView\Samples\SharedHolograms」をUnityで起動します。Holograms-240をベースにSpectator Viewのアドインが入っています。
先ほどの「CalibrationData.txt」をProjectビューに追加します。
メニューに「Spectator View」が追加されます。「Compositor」を開くと新しいウィンドウが表示されます。これがSpectator Viewの画面になります。
「Spectator View」のアドインは「AddIns\HolographicCameraRig」になるようです。
ビルド設定から「Run In Backgorund」にチェックします。これで(Unityエディター側の動作だと思いますが)ウィンドウがバックグラウンド状態でも実行されます。
Sharingサービスを実行します。
ここで表示されるサーバーのIPアドレスを後で使用します。
場合によってはSchemaバージョンエラーが出る場合があります。その場合はオリジナルのHolograms-240やHoloToolkit-UnityにあるSharingServerを使用してください。
Spectator View(HoloLens)とSharingサーバーのIPアドレスを設定します。
まずはエディター上で実行してSharingサーバーに接続できることを確認します。
続いてUWPを行い、HoloLensにデプロイします。
HoloLens上でこのアプリを実行し(デバイスポータルから起動すると楽です)、Sharingサーバーに接続されていることを確認します。次にUnityエディター上で実行し、サーバーおよびHoloLensに接続できると、PC上のカメラ位置がHoloLensに同期するようになります。
なんとなく動いた pic.twitter.com/MVE4Gtj7ps
— 中村 薫 (@kaorun55) 2017年2月14日
機材が複雑かつ3Dプリントで作成する必要がある、環境構築が煩雑、HoloLensが2台以上必要であることから、なかなか試しづらいですがアプリデモでは必要になってくるかと思います。
自分も3台のHoloLensでMixed Reality Captureを使った第三者視点はやったので。
]]>
TMCNベースでPETS、ホロラボ、ショッカソン、HoloEyes 連合で展示をしていました。
HoloLensが目を引くので、休憩時間中は人もたえず、3,4台体制だったので、今回も結構な人数に体験してもらうことができたと思います。
17:25分からの枠でした。
200-300人くらいでしょうか。おかげさまで満席でした。
最初に聞いてみたところ、HoloLens持ってる人は数人、興味あるけど買ってない人が9割くらい、まだかぶったことがないひとが6割くらいのようです。
Togetterのまとめと当日の資料はこちらです。
]]>
参加してくれた方々、協力してくれた各地のスタッフの方々、会場提供などご協力いただいた方々ありがとうございます。
各地それぞれ楽しく会を開催できました。
2016/12/2の日本での予約開始時にリリースが2017/1/18に決まったことを受けてTMCNや各地のxMCNメンバーの方に持ちかけたところ、みなさん乗ってくれました。
1/18に株式会社ホロラボの登記をしたこともあり、会社紹介もかねて回ることができて良かったです。
HoloLens所持者を対象としたハンズオンと、興味あるからすべてを対象としたミートアップの2部構成で、ハンズオンは92人、ミートアップは237人の方にご参加いただきました(スタッフ除く)。
ハンズオンでは、1台のHoloLensを使ったアプリ開発の初歩から複数台のHoloLensの空間を強調させるSharing体験までを行いました。Sharingは複数台のHoloLensが必要ですが、HoloLensの真価を発揮するための重要な特徴であることから、せっかく集まるこの機会に体験してもらおうと考えました。
今回ぼくが使った資料はこちらにまとめています。ハンズオン、ミートアップで使用した資料をまとめています。HoloLensの概要から開発体験までできました。実施したうえでの改定事項も対応していきます。
最初のイベントは福岡で17人の方にご参加いただき開催しました。
日本マイクロソフトの高橋忍さんにもご参加いただき、HoloLensを含めたマイクロソフト全体の話や、ハンズオンのフィードバックをいただくことができました。
平日の日中、HoloLens所持者対象にもかかわらず60人以上の方がハンズオンに参加してくれました。スタッフと合わせると80台を超えたHoloLensが集結しました。
Photo by 集合写真家Masahiro Takechi
この写真がHoloLensの生みの親であるAlex Kipmanまで届いたこと。
<3 <3 <3 https://t.co/H1usmRuJGS
— Alex Kipman (@akipman) 2017年2月2日
HoloLens公式アカウントからリプライをもらったことが、個人的に非常にうれしかったです。
@kaorun55 what a great looking group!
— Microsoft HoloLens (@HoloLens) 2017年2月2日
ミートアップも申し込みで約200人、スタッフも合わせて実際に参加された人数が約180人、HoloLensの台数は数えきれないほどになりました。
日本マイクロソフトのWindows本部長である三上さんからも開会のあいさつをいただきました。
ここで発表していただいた坪倉さんのスライドがとても分かりやすいので、特に広告などコンシューマー向けにHoloLensの利用を検討している方は一度見ておくべし。と思います。
取材記事もでています。
PANORA VR » HoloLensはおもちゃではない——クリエイターが語る「仕事でMR」の魅力とは?
ハンズオン、ミートアップの様子は動画でも公開しています。
大阪は34人の方に参加していただきました。
日本マイクロソフトの西脇さんとちょまどさんにもご参加いただき、日本のコミュニティでは初の公開となるSruface Studioのデモが行われました。Surface Studio、DialとHoloLensの連携も今後楽しみですね。
大阪開催の後、参加者の @sumihiro さんが、iPhone用のHoloLensキーボードを作ってくれました。HoloLensは日本語入力が難しいのですが、このアプリでだいぶ改善されました。
HoloLensにiPhoneから文字入力ができるHoloKeyboardをAppStoreで配信開始しました!https://t.co/czMdoSTo4e
— ヤバいスミヒロ (@sumihiro) 2017年2月9日
オープンソース版も並行して公開していますので、どうぞご利用ください。#HoloLens #HoloLensJP
最後の東北では15人の方にご参加いただきました。
日本マイクロソフトの金尾さんから、マイクロソフト全体の中でのHoloLensの位置づけについてお話いただきました。
HoloLensを購入して、コミュニティに参加する人が100人近くもいることが今回一番の驚きです。日本の購入数の初動が「欧州6か国合計」の3倍と言われるなど、たくさんのHoloLensが日本に来ています。
今回のミートアップで各地でHoloLensを活用しようとしている方たちとたくさん出会えたので、これからも継続して進めていこうと思います。
]]>
慣れるとスキャンからリグ入れまでで30-60分でしょうか。
詳しい人からすると目新しいものではないかもしれませんが、手軽にここまでできるようになったというのは進歩なんだろう思います。
フリー素材です。常識の範囲内でご使用ください。
https://www.dropbox.com/sh/kxtcgvzbgxo4bzv/AAAS1TkKjCWPe826qYXQkhr_a?dl=0
1. iPadにStructure Sensorを接続し、itSeez3Dで3Dスキャンします。このとき、Tポーズでとることで、リグを入れて好きなようにできます。ただし、Tポーズの3Dスキャンが難しいのでAポーズでリグを入れてモデルを調整するやり方でもいいかもしれません。
2. スキャンデータはクラウドに上げて処理されます。しばらくすると、iPadでプレビューできます。itSeez3Dアプリでここまでの手順は無料です。
3. 3Dデータに問題なければダウンロードします。ここで課金が発生します。
4. 3Dモデルの形式はOBJなので、MeshLabなどで見られます。
5.このモデルをMayaに入れ、モデルを調整(スケールの関係でX,Y,Zの大きさをそれぞれ100倍、正面を向くように回転)し、自動リグ処理をします。
このファイルをFBXで出力すれば、Unity上で扱えるようになります。
6.モーションデータを作成します。UnityはBVHファイルが使えないので、Motion Builderでモデルデータに埋め込むか、BlenderでBVHをFBXに変換します。
7.3DモデルとモーションデータをUnityに入れ、アプリを作成します。
そのままだとHoloLensで表示するには重いのでメッシュの数を減らしたり、ボーンも調整してあげると、きれいに表示できるようになります。
ちなみに、モーションデータはPerfume official global websiteのものを使用しています。
3Dスキャン、リグ入れは場所、機動性とトレードオフで改善可能なので、それも進めようと思います。
]]>・学校が推奨しているOSがwindows
ですので、windows上で仮想OSとか使わずに機械学習のライブラリが使えるような
環境構築をしていきたいと思います。
確認済み環境:Windows 8.1 Pro, 64bit
参考:基本的にはこの二つを参考にしています。
参考1 : やってみよう分析!第8章:PythonとEclipse(PyDev)で作る分析環境 for Windows - Qiita
参考2 :
PythonでNumpyとMatplotlibを利用する(Windows) - Gobble up pudding
ここからpython2.7の最新版をダウンロードしてください。
ページ下部の、windows x86-64 MSI installerを選択してください。
インストーラを起動した後は、主にインストーラに従う形でOKです。
環境変数のPathに、
C:¥Python27;
を追加してください
(ここら辺は他にも解説しているサイトがありますので、割愛します)
[確認]
コマンドプロンプトで
python
と打ち、以下の画面になればOKです。
参考1とここから少しづつ変わっていきます。
具体的には、.whlファイルのインストール方法と、msiインストーラを使わないことが
記事と違うところです。
http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy
から、適切なバージョンのものを選んでダウンロードしてください。
(今回の場合, 64bit でpython 2.7なので、
numpy‑1.9.2+mkl‑cp27‑none‑win amd64.whl
を選びます。)
ダウンロードが完了したら、C:¥Python27¥Scripts
のフォルダに入れて下さい。
これから、whlファイルをインストールします。
具体的には、pipというパッケージ管理ツールを利用します。
まず、コマンドプロンプト上で、C:¥Python27¥Scriptsへ移動します。
次に、
pip install (インストールしたいwhlファイル(!!ファイル名は変えてはダメ!!))
と打ち、以下のようなコンソールが出て来ればnumpyのインストールが完了します。
[確認]
コマンドプロンプト上で
python
と打ったあと、
import numpy
と打ち、Errorが出てなければ大丈夫です。
次に、numpyと同様にして、以下の二つのライブラリを導入してください。
scipy
http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy
pandas
http://www.lfd.uci.edu/~gohlke/pythonlibs/#pandas
[確認]
numpyの時と同様、確認してください。
参考1で言われている通り、matplotlibは楽です。
コマンドプロンプト上で、C:¥Python27¥Scriptsへ移動します。
そして、以下のコマンドを打つだけですw
pip install matplotlib
機械学習ライブラリである、scikit-learnをインストールします。
(念のため、このライブラリを最後にしています。)
numpyの時と同様にして、インストールをしてください。
http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikit-learn
参考1の通りです。
Eclipseをインストールし、pyDevをインストールしてください。
Eclipseを再起動したのち、「File -> New -> Other..」を選択
PyDev Project を選択
青いリンクのような場所をクリックし、Pythonの情報をEclipse側に設定します.
(自動設定のような項が真ん中のボタンに出るので、その真ん中のボタンを押してください(画像なし))
そして、Finishを押します。
出現したプロジェクトフォルダのところで右クリック→ PyDev Module
を選択します。
このような形でパッケージ名とmodule名を命名したください。
適当な場所から、サンプルを拾ってきて、実行(上部の再生ボタン)を押し、
Python Run を選択して実行し、できればOK!
サンプル:
http://scikit-learn.org/stable/auto_examples/plot_cv_predict.html#example-plot-cv-predict-py
以下のページを参考にしてください。
]]>