ZED miniでAR動画を撮影する
ステレオカメラのZED miniを使ってAR動画を撮影する手順をメモ。バーチャルな映像とリアルの映像を混ぜつつリアルの寝室にボールをぶちまける映像が撮れた。
ZED miniについて
Stereolabsが販売しているステレオカメラ。HMDに取り付ければStereo pass-through機能で現実世界が立体視できる。
他にも現実世界を3DスキャンするSpatial mapping機能や、映像からカメラ位置姿勢を推定するInside-out tracking機能、深度推定によるOcclusion機能とか色々ある。とりあえず公式動画。
VR機器2台も用いて卓球とはなんとも贅沢である。
できた映像
こんな感じ。
動作環境
追記(2020/5/10)
下記環境でも同様の設定で動きました。微妙にパラメータの名称が記事中のスクショと異なりますが見ればすぐわかる程度の違いでほぼ変わりないです。
- Unity 2018.4.20f1
- ZED SDK v3.1.2
- ZED Plugin v3.1.0
ZED miniの3Dモデル
今回の記事では使わなくてもいいけど、ZED miniを何かしらに取り付けたいときはここに公開されてる3Dモデルが役に立つ。例えばトラッカーやコントローラに固定するマウンタを作ってみたり、ロボットに載せてみたり。なぜかQ&Aコーナーにしか載ってないので少し不便。
作成手順
セットアップ
下記のサイトからZED SDKをインストールする。
Unity向けのPluginは下記のサイトに公開されているのでパッケージをインポート。
HMDを使う際はOculus Rift CV1とHTC VIVEに対応しているのでそれぞれのPluginをAsset storeからインポートしておく。
HMDへのZED miniの取り付け方は下記のサイトで説明されている。付属のガイドに合わせてカメラホルダーを粘着テープで貼り付ける方式。
テープが強力でHMDとカメラホルダーの付け外しがしんどいので、僕は貼り付け前に頑張って剥がして違うテープにした。ZED miniを使わないときもカメラホルダーが邪魔に感じない人は付属のテープで問題ないと思う。
Camera prefabの追加
Asset/ZED/Prefabs
にZED_Rig_Stereo
とZED_Rig_Mono
がある。HMDによる立体視(Stereo pass-through)をする際はStereoの方を、そうでない場合はMonoをHierarchieに追加する。
今回はZED_Rig_Stereo
を追加した。もうこれだけで実行するとカメラが起動してカメラ映像が見れるし、Occlusionもされる。親切。
- 公式ドキュメント
カメラ設定
ZED_Rig_Stereo
にZED Manager
がアタッチされており、カメラ映像に関する設定がいろいろできる。
さらに下にあるOpen Camera Control
をクリックするとウィンドウが開き、ホワイトバランスや彩度等が設定できる。
カメラ位置の設定
ZED miniは単体でもPosition trackingができるけど、OculusやVIVEデバイスとの位置関係は分かっていない。例えばTrackerの位置に3Dオブジェクトを表示させても、ZED miniの映像と3Dオブジェクトの位置がずれてしまう。 そのためControllerやTrackerにZED miniを固定し、どのデバイスに固定したのか設定する必要がある。今回はHMDに取り付ける設定をする。
ZED_Rig_Stereo
にZED Controller Tracker
をアタッチし、Device To Track
の項目にHMD
を設定する。
また、Latency Compensation
によって、映像とデバイス位置の遅延を調整することができる。
ZED_Rig_Stereo
の子オブジェクトであるCamera_eyes
にZED Offset Controller
をアタッチする。これでZED miniのPosition trackingとHMDのPosition trackingが一致するようになる。
公式ドキュメント
追記(2020/5/10)
厳密にどのバージョン以降か確認できてませんが、ZED Plugin v3.1.0ではこの方法が使えなかったので上記のドキュメントを見てください。
Controller, Trackerの設定
ControllerやTrackerの位置に合わせたオブジェクトを表示したい場合はカメラと同様、オブジェクトにZED Controller Tracker
をアタッチする。
- 公式ドキュメント
Spatial mapping
Spatial mapping機能を用いて現実の床や壁、家具などのオブジェクトとバーチャルなオブジェクトの衝突判定を行うことができる。ZED_Rig_Stereo
の子オブジェクトにAssets/ZED/Examples/SpatialMapping/Prefabs
のZED_Spatial_Mapping
を追加する。
実行時にZED Spatial Mapping Manager
のStart Spatial Mapping
ボタンを押すことでSpatial mappingが始まり、Stop Spatial Mapping
を押してSpatial mappingを終了することができる。
- 公式ドキュメント
ROS#:カメラ映像をSubscribe
UnityとROSを通信させるのに便利なROS#(ros sharp)には、ROSでPublishしたカメラ映像をUnityでSubscribeするスクリプトが用意されている。ROS#v1.2c以前とv1.3ではちょっと使い方が違うのでメモ。
動作環境
- Unity動作用PC
- Windows 10
- ROS# v1.3
- Unity 2018.2.17f1
- Visual studio 2017
- ROS動作用PC
- Ubuntu16.04
- ROS Kinetic Kame
ROS#のセットアップ
セットアップ方法は以前書いた。今回はセットアップ済みの状態から始める。
カメラ映像のSubscribe
Planeの配置
Hierarchie windowを右クリックして3D Object/Plene
を選択。
このObjectにカメラ映像が表示されるので、お好みのObjectで。
Image Subscriber
RosConnectorがアタッチされたGameObjectにAssets/RosSharp/Scripts/RosBridgeClient/RosCommuncation/ImageSubscriber.cs
をアタッチする。
TopicにSubscribeしたいカメラ映像のTopic名を書いて、Mesh Rendererに先ほど作成したPlaneをドラッグ&ドロップ。Time Stepは…よくわかんないけどTopicが来てから何ms更新しない的なやつかな。
大きいほど映像の更新がゆっくりになります。
↓なんかコメントが書いてある。
the rate(in ms in between messages) at which to throttle the topics
カメラ映像のPublishは以前作成したシミュレーター上のカメラ映像を使ってみる。リンク先のREADMEの通りにコマンドを実行していけば、上記スクショと同じTopic名の映像がPublishされる。
これは例なので、自分で作ったロボットがあれば適宜Topic名を合わせてください。
カメラ映像の確認
UnityとROSの接続はセットアップ編を参照。
無事に接続したら、Planeにカメラ映像が表示される。
ちなみにシミュレーターの外観はこんな感じ。明るいグレーがシミュレーター上の空、暗いグレーが地面、白いのがロボット本体。
参考
- ROS# v1.2c以前の手順
ROSのセットアップはこちら。
ROS#:Objectの位置姿勢をPublish
UnityとROSを通信させるのに便利なROS#(ros sharp)には、Unity上のGameObjectの位置姿勢を配信(Publish)するスクリプトが用意されている。ROS#v1.2c以前とv1.3ではちょっと使い方が違うのでメモ。
動作環境
- Unity動作用PC
- Windows 10
- ROS# v1.3
- Unity 2018.2.17f1
- Visual studio 2017
- ROS動作用PC
- Ubuntu16.04
- ROS Kinetic Kame
ROS#のセットアップ
セットアップ方法は以前書いた。今回はセットアップ済みの状態から始める。
配信の手順
Pose Stamped Publisher
RosConnectorがアタッチされているオブジェクトにAssets/RosSharp/Scripts/RosBridgeClient/RosCommuncation/PoseStampedPublisher.cs
をアタッチする。
位置姿勢を配信させたいGameObjectをPublished Transformにドラッグ&ドロップする。 Topic、Frame Idは好きな名前を入れる。
ちなみにTopicはデータの名前、Frame Idは座標系の名前のようなもの。なので複数GameObjectの位置姿勢を配信する際はFrame Idを統一しておくと良い。
データの確認
UnityとROSの接続はセットアップ編を参照。
無事に接続したら、ROSを動作させているPC側のターミナルから下記コマンドを入力すると、Topicが配信されていることがわかる。
$ rostopic list /pose_test
Topicのデータが見たい場合は下記のコマンドを入力。poseとorientationに位置姿勢が表示されていることがわかる。
$ rostopic echo /pose_test header: seq: 11806 stamp: secs: 251 nsecs: 204 frame_id: "Unity" pose: position: x: 0.125135 y: 0.9609885 z: 1.93874049 orientation: x: 0.39447543 y: -0.253540576 z: 0.820601046 w: 0.3266807
参考
ROSのセットアップはこちら。
ROS#:Message typeの追加
UnityとROSを通信させるのにROS#(ros sharp)を使った。Message typeを追加する方法が公式Wikiにあったので、忘れないようにメモ。
動作環境
- Unity動作用PC
- Windows 10
- ROS# v1.3
- Unity 2018.2.17f1
- Visual studio 2017
- ROS動作用PC
- Ubuntu16.04
- ROS Kinetic Kame
ソースコードのDL
ROS#のリリースページからソースコードをダウンロードする。
Message typeの作成
ros-sharp/Libraries/RosBridgeClient/Messages
にMessage typeが定義されている。今回は公式wikiと同様に/Standard
にFloat32.csを作成してみる。
using Newtonsoft.Json; namespace RosSharp.RosBridgeClient.Messages.Standard { public class Float32 : Message { [JsonIgnore] public const string RosMessageName = "std_msgs/Float32"; public float data; public Float32() { data = 0; } } }
ソリューションのビルド
ros-sharp\Libraries\RosSharp.sln
をVisual Studioで開く。
ビルド設定
ビルドタブから構成マネージャーを選択。
アクティブソリューション構成をRelease、アクティブソリューションプラットフォームをAny CPUに設定して閉じる。
スクリプトの追加
ソリューションエクスプローラーから先ほど作成したスクリプト(今回はFloat32.cs)を追加する。
ビルド
ビルドタブからソリューションのビルドを実行。
RosBridgeClient.dllの置き換え
ros-sharp\Libraries\RosBridgeClient\bin\Release\RosBridgeClient.dll
をUnityプロジェクト内のAssets\RosSharp\Plugins
にコピペする。
Publisherの作成
FloatPublisher.csを作成。公式wikiのサンプルはこんな感じ。
namespace RosSharp.RosBridgeClient { public class FloatPublisher : Publisher<Messages.Standard.Float32> { public float messageData; private Messages.Standard.Float32 message; protected override void Start() { base.Start(); InitializeMessage(); } private void InitializeMessage() { message = new Messages.Standard.Float32 { data = messageData }; } private void Update() { message.data = messageData; Publish(message); } } }
このスクリプトをRosConnectorと同じGameObjectにアタッチして、好きなtopic名や数値を入れてみる。
動作確認
ROSを起動するPC側のターミナルで下記コマンドを実行し、Rosbridge serverを起動する。
$ roslaunch rosbridge_server rosbridge_websocket.launch
Unityを実行すると、Messageがpublishされる。ターミナルに下記コマンドを入力することでtopicを確認できる。
$ rostopic list /float_test
Messageの内容を出力する際は下記のコマンド。
$ rostopic echo /float_test data: 3.0
参考
ROS#のセットアップはこちら。
ROSのセットアップはこちら。
ROS#:UnityとROSの接続
UnityでARやVRのインターフェースを作って、ROSで動作するロボットと通信したかった。今回はROS#(ros sharp)を使ってみる。
動作環境[1] - WindowsとUbuntu
Unity動作用にWindows PC、ROS動作用にUbuntu PCを用いました。
- Unity動作用PC
- Windows 10
- ROS# v1.3
- Unity 2018.2.17f1
- ROS動作用PC
- Ubuntu16.04
- ROS Kinetic Kame
動作環境[2] - Ubuntu
Ubuntu PCにUnityを入れても同様の手順で動作しました。
GAZEBO等のシミュレータと連携させる際にオススメです。
- Ubuntu16.04
- ROS Kinetic Kame
- ROS# v1.4
- Unity 2018.4.0f1
ROS# v1.3, v1.4はUnity2018.2.6以降に対応している。
それ以前のUnityを使う際はROS# v1.2cが使える。
ROS#のセットアップ
Scripting Runtime Versionの設定
この手順はROS# v1.3以降から必要になった。設定項目はEdit/Project Settings/Player
にある。
Inspector windowに表示されるOther Settings/Configuration/Scripting Runtime Version
を.Net 4.x Equivalentに設定。
Import
公式リポジトリかAsset storeからimportできる。
RosConnectorの設定
Assets/RosSharp/Scripts/RosCommunication/RosConnector
をGameObjectにアタッチ(下画像ではRosConnectorという名前のObject)。Ros Bridge Server UrlにROSを起動しているPCのipアドレスを入力する。
ポート番号はデフォルトが9090なので:
以降は通常気にしなくて良い。
Rosbridge serverのインストール
ROSを起動するPCのターミナルに下記コマンドを入力。
$ sudo apt-get install ros-kinetic-rosbridge-server
接続の確認
下記コマンドでRosbridge serverを起動。
$ roslaunch rosbridge_server rosbridge_websocket.launch
正常に起動すると最後に以下の出力が表示される。ポートが9090になっていることがわかる。
[INFO] [1543148743.067570]: Rosbridge WebSocket server started on port 9090
Unityを実行すると、Rosbridge server側に接続が通知される。切断も同様。
[INFO] [1543148773.264767]: Client connected. 1 clients total. [INFO] [1543148776.534702]: Client disconnected. 0 clients total.
ROS#関連記事
ROSのセットアップはこちら。
ROS#のMessage type追加方法はこちら。
ROS#でObjectの位置姿勢をPublishする際はこちら。
AR, VRにオススメ。
ROS#でカメラ映像をSubscribeする際はこちら。
ロボットに搭載されたカメラ映像を見る際にオススメ。
参考
ROS#公式wiki
ROS# v1.2c以前の手順
更新
2019年06月11日
v1.4も同様の手順で動作したので動作環境に追記した。
RViz:"No transform from [link_name] to [map]"
作成したURDFモデルをRVizで表示する際、上のスクショのようにエラーが出る。
RobotModel
にStatus Error
が生じており、各linkにはNo transform from [link_name] to [map]
と表示されている。
今回はcamera_linkからmapへの座標変換ができていないみたい。 基準となるフレームが無いので、camera_linkの位置姿勢が計算できなくなっている状態。
解決方法
Fixed Frameから基準にしたいフレームを選択する。
VRChatに銀河を作る[1]
VRChatで星を立体的に見れたら楽しそうだと思った。最終的に星の位置情報に合わせてパーティクルが光るワールドを作ってみた。色々初めてのことが多かったので、メモ。Unity初心者が見よう見まねでやった記録なので、多分もっと良い方法があります。
できたもの
こんな感じで立体的に星がパーティクルとして表示される。
つづき
この記事を書いた後にあれこれ大幅にアップデートした。その話はこっちに書いた。
ネタを考える過程
なぜ星を表示しようとしたのですか?と聞かれまくるので書いておく。
僕にとって今回が初めてのワールド製作で、VRChatのSDKに関して知識が一切ない。せっかく作るなら面白いワールドにしたかったので、簡単かつ面白そうなテーマを考えていた。
モデリングもできないので、教育機関向けに公開されてるデータを持ってきて置くだけならできそう。多分星の位置情報とかありそう。「星 位置 データ」でGoogle検索したらヒッパルコス星表が出てきました。要するに何ら脈絡はない。さらにいうと僕自身天文に関する知識はオリオン座が見つけられる程度。光ってる星の名前がわかんなくても星は綺麗だよね。
制作の記録
星の位置データを入手
星の位置はヒッパルコス星表というものが有名らしい。
以下の記事が参考になりました。
参考サイトにある通り、下記サイトからヒッパルコス星表がダウンロードできる。
HEASARC Browse: Search of STAR CATALOG Catalog(s)
必要な項目にチェックを入れる。今回はname, parallax(距離), vmag(明るさ), ra_deg(赤経), dec_deg(赤緯)を選択。 通常天文では角度を時, 分, 秒で表現されたものを使うらしいけど、普通に度の表記も選択できた。ありがたい。
チェックしたらLimit Results ToをNo Limitにする。そしてStart Search。これで該当する星が全部出てくる。今気づいたけどOutput Formatの項目でもう少し読み込みやすい選択肢があったかも。今度機会があったら見てみる。
データの前処理
ダウンロードするとこんな感じでずらっとデータが書いてある。
Results from heasarc_hipparcos: Hipparcos Main Catalog Coordinate system: Equatorial |name |parallax|vmag |ra_deg |dec_deg | |HIP 48752 | 4.17| 7.84|149.16726051|-89.78245385| |HIP 71348 | 2.08| 6.82|218.87831588|-89.77169600| |HIP 42708 | 2.39| 7.20|130.51854607|-89.46050180|
よく見るといろいろ項目が空白になっているものもある。
|HIP 62662 | 8.73| 9.23|192.59313824|-88.12099013| |HIP 57037 | |10.84| | | |HIP 32914 | |11.43| | | |HIP 46043 | 2.62| 9.68|140.84701457|-87.97397795|
プログラムで対処するのが面倒なので、事前にコマンドで取り除いた。随分乱暴だけど、とりあえず以下のコマンドで空白がある行を除去できる。
BrowseTargets.1213.1536347830
とは僕がダウンロードしたヒッパルコス星表のファイル名のこと。これでhippa.txtに空白のないデータが保存された。
$ grep -v " " BrowseTargets.1213.1536347830 > hippa.txt
座標系の変換
星の位置は角度と距離で表現された球座標系。BlenderやUnityは直交座標系なので変換する必要がある。変換するスクリプトをPythonで書いてみた。
で、ひたすらxyzが並んだデータができた。
https://raw.githubusercontent.com/Kuwamai/3d_HIP_mesh/master/hippa_pos.txt
モデリング
この方法が一番いいのかわからないけど、星の位置を頂点とする3Dモデルを作ることにした。BlenderはPythonで動かすことができる。今回みたいにたくさんのデータに従った3Dモデルを作るときは便利そう。BlenderでPythonを動かす方法は下記のサイトが参考になりました。
追記(2020/10/01): ↑の記事がリンク切れだったので↓の記事を参考にしました
で、僕が書いてみたスクリプトはこんな感じ。
できた3Dモデルがこちらになります。ウニみたい。fbxでエクスポートしました。
スクリプトにエラーがあるとコンソール画面に出るらしいんだけど、macだと後からコンソールがひらけない。ターミナルから起動する必要があるらしい。
Unityの作業
Mesh Particle Emitter
できた銀河のモデルをUnityに置いて、Mesh Particle Emitterを適用すると、モデルの各頂点からパーティクルが出てくる。公式のマニュアル通りにやったらできた。
https://docs.unity3d.com/ja/current/Manual/HOWTO-MeshParticleEmitter.html
VRC SDK
なんと、ワールドにするにはVRCWorldというPrefabを一個置くだけで良いらしい。こちらの記事が参考になりました。
デフォルトでジャンプができないらしく、PlayerModsを適用させるらしい。こちらの記事が参考になりました。
つまづいたところ
Blenderでモデリングする際、頂点データさえあればMesh Particle Emitterが適用できるかと思ったけど、パーティクルが出てこなかった。なのでBlenderのスクリプトは頂点を設定した後に面を張っている。
今後の展望
もっと作り込めば普通に楽しめるコンテンツになりそう。とはいえ続ける時間も気力もないので、星が好きなVRChatユーザーの方がいらっしゃれば続きをやっていただきたいです。。。
星座の表示
正直どの星が何なのかさっぱりなので、有名な星座を構成する星は色を変えるとかした方が分かり易そう。オリオン座を横から見てみたい。
銀河の回転
よくプラネタリウムは何時何分の空ですとかやってるから、この銀河のオブジェクトを回転させる仕組みができたら実現できそう。シェーダーで頑張れば時間も出せるはず。知らんけど。
軽量化
VRChatでパーティクルを数十万も出すもんじゃない気がする。ただ点が出てれば良いだけなので、何かもっと軽量な方法を知りたい。点群情報をテクスチャに埋め込んで、シェーダーで表示する方法とかあるらしい。
この記事が参考になるらしいんだけど。。。来世読む。
星の増量
今回はヒッパルコス星表を試したけど、もっと星の多いGaia星表というものがある。使えそうなデータだけで10億。
こちらの記事を参考にDLはできたけど、星が多すぎて宇宙ヤバイ。絞り込み検索すれば良いわけだけど、銀河からいい感じに星を絞り込む知識皆無。いつか再挑戦したい。