クワマイでもできる

クワマイでもわかる

ZED miniでAR動画を撮影する

f:id:kuwamai:20190307144753p:plain

ステレオカメラのZED miniを使ってAR動画を撮影する手順をメモ。バーチャルな映像とリアルの映像を混ぜつつリアルの寝室にボールをぶちまける映像が撮れた。

ZED miniについて

Stereolabsが販売しているステレオカメラ。HMDに取り付ければStereo pass-through機能で現実世界が立体視できる。
他にも現実世界を3DスキャンするSpatial mapping機能や、映像からカメラ位置姿勢を推定するInside-out tracking機能、深度推定によるOcclusion機能とか色々ある。とりあえず公式動画。

VR機器2台も用いて卓球とはなんとも贅沢である。

できた映像

こんな感じ。

動作環境

  • Windows 10
  • Unity 2017.3.1f
  • ZED SDK 2.5
  • ZEDUnityPlugin v2.5
  • HTC VIVE

追記(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/PrefabsZED_Rig_StereoZED_Rig_Monoがある。HMDによる立体視(Stereo pass-through)をする際はStereoの方を、そうでない場合はMonoをHierarchieに追加する。
今回はZED_Rig_Stereoを追加した。もうこれだけで実行するとカメラが起動してカメラ映像が見れるし、Occlusionもされる。親切。

f:id:kuwamai:20190228191408p:plain

  • 公式ドキュメント

カメラ設定

ZED_Rig_StereoZED Managerがアタッチされており、カメラ映像に関する設定がいろいろできる。

f:id:kuwamai:20190228220456p:plain

さらに下にあるOpen Camera Controlをクリックするとウィンドウが開き、ホワイトバランスや彩度等が設定できる。

カメラ位置の設定

ZED miniは単体でもPosition trackingができるけど、OculusやVIVEデバイスとの位置関係は分かっていない。例えばTrackerの位置に3Dオブジェクトを表示させても、ZED miniの映像と3Dオブジェクトの位置がずれてしまう。 そのためControllerやTrackerにZED miniを固定し、どのデバイスに固定したのか設定する必要がある。今回はHMDに取り付ける設定をする。

ZED_Rig_StereoZED Controller Trackerをアタッチし、Device To Trackの項目にHMDを設定する。 また、Latency Compensationによって、映像とデバイス位置の遅延を調整することができる。

f:id:kuwamai:20190228221507p:plain

ZED_Rig_Stereoの子オブジェクトであるCamera_eyesZED Offset Controllerをアタッチする。これでZED miniのPosition trackingとHMDのPosition trackingが一致するようになる。

f:id:kuwamai:20190228222627p:plain

  • 公式ドキュメント

  • 追記(2020/5/10)
    厳密にどのバージョン以降か確認できてませんが、ZED Plugin v3.1.0ではこの方法が使えなかったので上記のドキュメントを見てください。

Controller, Trackerの設定

ControllerやTrackerの位置に合わせたオブジェクトを表示したい場合はカメラと同様、オブジェクトにZED Controller Trackerをアタッチする。

f:id:kuwamai:20190228233551p:plain

  • 公式ドキュメント

Spatial mapping

Spatial mapping機能を用いて現実の床や壁、家具などのオブジェクトとバーチャルなオブジェクトの衝突判定を行うことができる。ZED_Rig_Stereoの子オブジェクトにAssets/ZED/Examples/SpatialMapping/PrefabsZED_Spatial_Mappingを追加する。

f:id:kuwamai:20190228233931p:plain

実行時にZED Spatial Mapping ManagerStart Spatial Mappingボタンを押すことでSpatial mappingが始まり、Stop Spatial Mappingを押してSpatial mappingを終了することができる。

f:id:kuwamai:20190228234350p:plain

  • 公式ドキュメント

ROS#:カメラ映像をSubscribe

UnityとROSを通信させるのに便利なROS#(ros sharp)には、ROSでPublishしたカメラ映像をUnityでSubscribeするスクリプトが用意されている。ROS#v1.2c以前とv1.3ではちょっと使い方が違うのでメモ。

動作環境

  • Unity動作用PC
  • ROS動作用PC
    • Ubuntu16.04
    • ROS Kinetic Kame

ROS#のセットアップ

セットアップ方法は以前書いた。今回はセットアップ済みの状態から始める。

kuwamai.hatenablog.com

カメラ映像のSubscribe

Planeの配置

Hierarchie windowを右クリックして3D Object/Pleneを選択。
このObjectにカメラ映像が表示されるので、お好みのObjectで。

f:id:kuwamai:20181212005224p:plain

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

f:id:kuwamai:20181212005743p:plain

カメラ映像のPublishは以前作成したシミュレーター上のカメラ映像を使ってみる。リンク先のREADMEの通りにコマンドを実行していけば、上記スクショと同じTopic名の映像がPublishされる。
これは例なので、自分で作ったロボットがあれば適宜Topic名を合わせてください。

カメラ映像の確認

UnityとROSの接続はセットアップ編を参照。

kuwamai.hatenablog.com

無事に接続したら、Planeにカメラ映像が表示される。

f:id:kuwamai:20181212012711p:plain

ちなみにシミュレーターの外観はこんな感じ。明るいグレーがシミュレーター上の空、暗いグレーが地面、白いのがロボット本体。

f:id:kuwamai:20180711172137p:plain

参考

ROSのセットアップはこちら。

ROS#:Objectの位置姿勢をPublish

UnityとROSを通信させるのに便利なROS#(ros sharp)には、Unity上のGameObjectの位置姿勢を配信(Publish)するスクリプトが用意されている。ROS#v1.2c以前とv1.3ではちょっと使い方が違うのでメモ。

動作環境

  • Unity動作用PC
  • ROS動作用PC
    • Ubuntu16.04
    • ROS Kinetic Kame

ROS#のセットアップ

セットアップ方法は以前書いた。今回はセットアップ済みの状態から始める。

kuwamai.hatenablog.com

配信の手順

Pose Stamped Publisher

RosConnectorがアタッチされているオブジェクトにAssets/RosSharp/Scripts/RosBridgeClient/RosCommuncation/PoseStampedPublisher.csをアタッチする。

位置姿勢を配信させたいGameObjectをPublished Transformにドラッグ&ドロップする。 Topic、Frame Idは好きな名前を入れる。

f:id:kuwamai:20181211235251p:plain

ちなみにTopicはデータの名前、Frame Idは座標系の名前のようなもの。なので複数GameObjectの位置姿勢を配信する際はFrame Idを統一しておくと良い。

データの確認

UnityとROSの接続はセットアップ編を参照。

kuwamai.hatenablog.com

無事に接続したら、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
  • 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.slnVisual Studioで開く。

ビルド設定

ビルドタブから構成マネージャーを選択。

f:id:kuwamai:20181125135332p:plain

アクティブソリューション構成をRelease、アクティブソリューションプラットフォームをAny CPUに設定して閉じる。

f:id:kuwamai:20181125160829p:plain

スクリプトの追加

ソリューションエクスプローラーから先ほど作成したスクリプト(今回はFloat32.cs)を追加する。

f:id:kuwamai:20181125155716p:plain

ビルド

ビルドタブからソリューションのビルドを実行。 f:id:kuwamai:20181128185619p:plain

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名や数値を入れてみる。

f:id:kuwamai:20181129200252p:plain

動作確認

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] - WindowsUbuntu

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にある。

f:id:kuwamai:20181128171925p:plain

Inspector windowに表示されるOther Settings/Configuration/Scripting Runtime Versionを.Net 4.x Equivalentに設定。

f:id:kuwamai:20181128171141p:plain

Import

公式リポジトリかAsset storeからimportできる。

RosConnectorの設定

Assets/RosSharp/Scripts/RosCommunication/RosConnectorをGameObjectにアタッチ(下画像ではRosConnectorという名前のObject)。Ros Bridge Server UrlにROSを起動しているPCのipアドレスを入力する。 ポート番号はデフォルトが9090なので:以降は通常気にしなくて良い。

f:id:kuwamai:20181125211312p:plain

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する際はこちら。
ロボットに搭載されたカメラ映像を見る際にオススメ。

参考

更新

2019年06月11日

v1.4も同様の手順で動作したので動作環境に追記した。

RViz:"No transform from [link_name] to [map]"

f:id:kuwamai:20181031194937p:plain 作成したURDFモデルをRVizで表示する際、上のスクショのようにエラーが出る。

RobotModelStatus Errorが生じており、各linkにはNo transform from [link_name] to [map]と表示されている。

今回はcamera_linkからmapへの座標変換ができていないみたい。 基準となるフレームが無いので、camera_linkの位置姿勢が計算できなくなっている状態。

解決方法

f:id:kuwamai:20181031195001j:plain Fixed Frameから基準にしたいフレームを選択する。

VRChatに銀河を作る[1]

f:id:kuwamai:20180912190228p:plain VRChatで星を立体的に見れたら楽しそうだと思った。最終的に星の位置情報に合わせてパーティクルが光るワールドを作ってみた。色々初めてのことが多かったので、メモ。Unity初心者が見よう見まねでやった記録なので、多分もっと良い方法があります。

できたもの

こんな感じで立体的に星がパーティクルとして表示される。

つづき

この記事を書いた後にあれこれ大幅にアップデートした。その話はこっちに書いた。

ネタを考える過程

なぜ星を表示しようとしたのですか?と聞かれまくるので書いておく。

僕にとって今回が初めてのワールド製作で、VRChatのSDKに関して知識が一切ない。せっかく作るなら面白いワールドにしたかったので、簡単かつ面白そうなテーマを考えていた。

モデリングもできないので、教育機関向けに公開されてるデータを持ってきて置くだけならできそう。多分星の位置情報とかありそう。「星 位置 データ」でGoogle検索したらヒッパルコス星表が出てきました。要するに何ら脈絡はない。さらにいうと僕自身天文に関する知識はオリオン座が見つけられる程度。光ってる星の名前がわかんなくても星は綺麗だよね。

制作の記録

星の位置データを入手

星の位置はヒッパルコス星表というものが有名らしい。
以下の記事が参考になりました。

参考サイトにある通り、下記サイトからヒッパルコス星表がダウンロードできる。

HEASARC Browse: Search of STAR CATALOG Catalog(s)

必要な項目にチェックを入れる。今回はname, parallax(距離), vmag(明るさ), ra_deg(赤経), dec_deg(赤緯)を選択。 通常天文では角度を時, 分, 秒で表現されたものを使うらしいけど、普通に度の表記も選択できた。ありがたい。

f:id:kuwamai:20180914202102p:plain

チェックしたらLimit Results ToをNo Limitにする。そしてStart Search。これで該当する星が全部出てくる。今気づいたけどOutput Formatの項目でもう少し読み込みやすい選択肢があったかも。今度機会があったら見てみる。

f:id:kuwamai:20180914202434p:plain

データの前処理

ダウンロードするとこんな感じでずらっとデータが書いてある。

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モデルを作ることにした。BlenderPythonで動かすことができる。今回みたいにたくさんのデータに従った3Dモデルを作るときは便利そう。BlenderPythonを動かす方法は下記のサイトが参考になりました。

追記(2020/10/01): ↑の記事がリンク切れだったので↓の記事を参考にしました

で、僕が書いてみたスクリプトはこんな感じ。

できた3Dモデルがこちらになります。ウニみたい。fbxでエクスポートしました。

f:id:kuwamai:20180917161653p:plain

スクリプトにエラーがあるとコンソール画面に出るらしいんだけど、macだと後からコンソールがひらけない。ターミナルから起動する必要があるらしい。

ターミナルからBlenderを起動

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はできたけど、星が多すぎて宇宙ヤバイ。絞り込み検索すれば良いわけだけど、銀河からいい感じに星を絞り込む知識皆無。いつか再挑戦したい。

http://astro1.sc.niigata-u.ac.jp/~nishi/Gaia/HTUJ.html