Unityで3D空間をコントローラーで移動させて、障害物に衝突したらちゃんと止まるようにする
コントローラーを使ってキャラクターを移動させて、障害物にぶつかったら止まるという基本の動作をUnityで実装する方法
つかったもの
Unity version
- unity 5.6.4f1
ユニティちゃん
- なんでもいいんだけど、以前から使ってみたかったユニティちゃんを利用
- ダウンロード - UNITY-CHAN!
Oculus Utilities
- versionは1.20.0(2017/11/09 release)
- https://developer.oculus.com/downloads/package/oculus-utilities-for-unity-5/
コントローラー
- みんな大好き箱〇コントローラー(PC用)
準備
床と障害物となる柱を設置
- 床は3D object > Terrain
- 柱は3D object > Cylinder
その前にユニティちゃんを配置
- import package > custom packageでダウンロードしてきたユニティちゃんパッケージをimport
- unitychan prefabsをHierarchyにD&Dして配置、位置調整
スクリプト(今回はunityWalking.cs)を作成してunitychanにセット
- create > C# script
Oculus Utilityのimport
- import package > custom packageでダウンロードしてきたOculus Utilityパッケージをimport
(コントローラーの十字キーの設定)
開発
以下のサイト様がとてもわかりやすかったので、上から試していってみた
tama-lab.net
1. transform.position
- 座標を直接書き換えることで移動する
- 移動というより瞬間移動的なもの
- 上記の理由より衝突判定を抜けてしまうことが多い
using System.Collections; using System.Collections.Generic; using UnityEngine; public class unityWalking : MonoBehaviour { public float speed = 3f; void Update () { if (Input.GetAxis("Vertical") > 0){ transform.position += transform.forward * speed * Time.deltaTime; } if (Input.GetAxis("Vertical") < 0){ transform.position -= transform.forward * speed * Time.deltaTime; } if (Input.GetAxis("Horizontal") > 0){ transform.position += transform.right * speed * Time.deltaTime; } if (Input.GetAxis("Horizontal") < 0){ transform.position -= transform.right * speed * Time.deltaTime; } } }
これで移動はできるようになったがcylinderを突き抜けていってしまうので衝突判定の設定をする
cylinderにはデフォルトでCapsule colliderがセットされているので、unitychanの方にcolliderとrigitbodyを設定する
- rigidbody
- use Gravity:オフ
- Is Kinematic:オフ
- capsule collider
- height: 2
- Center: 0, 1, 0
これで衝突判定されるようになったが、柱にぶつかった時の挙動がちょっと微妙。
調べればよい解決法があるのかもしれないがとりあえず次の方法を試してみる
2. RigidBody
Rigidbody.AddForce
- rigidbody
- use Gravity:オフ
- Is Kinematic:オフ
- capsule collider
- height: 2
- Center: 0, 1, 0
using System.Collections; using System.Collections.Generic; using UnityEngine; public class unityWalking : MonoBehaviour { public float speed = 10f; public Rigidbody rb; void Start(){ rb = GetComponent<Rigidbody> (); } void FixedUpdate () { float x = Input.GetAxis ("Horizontal") * speed; float z = Input.GetAxis ("Vertical") * speed; rb.AddForce (x, 0, z); } }
rigidbodyに力を加えて押す感じ?慣性で動き続けてしまうので微妙
Rigidbody.Velocity
using System.Collections; using System.Collections.Generic; using UnityEngine; public class unityWalking : MonoBehaviour { public float speed = 3f; float moveX = 0f; float moveZ = 0f; Rigidbody rb; void Start(){ rb = GetComponent<Rigidbody> (); } void Update () { moveX = Input.GetAxis ("Horizontal") * speed; moveZ = Input.GetAxis ("Vertical") * speed; Vector3 direction = new Vector3 (moveX, 0, moveZ); } void FixedUpdate(){ rb.velocity = new Vector3 (moveX, 0, moveZ); } }
- 慣性はなくなった
- ただ衝突判定時に回転してしまう
これもちゃんと調べればきちんと動く方法があるかもしれないのだが、とりあえず次を試してみる
3. CharacterController
CharacterController.SimpleMove
結論から言うとこのCharacter Controllerを使うと自分の意図してた動きを実現することができた
このCharacter Controllerとはカプセルcolliderと移動機能をセットにしたものでrigidbodyもセットしても反映されないらしいので、上の方法でセットしていたcolliderとrigidbodyは今回はセットしない
その代わりにCharacter Controllerをセットする
- Character Controller
- Center : 0, 1, 0
- Height : 2
using System.Collections; using System.Collections.Generic; using UnityEngine; public class unityWalking : MonoBehaviour { public float speed = 3f; float moveX = 0f; float moveZ = 0f; CharacterController controller; void Start(){ controller = GetComponent<CharacterController> (); } void Update () { moveX = Input.GetAxis ("Horizontal") * speed; moveZ = Input.GetAxis ("Vertical") * speed; Vector3 direction = new Vector3 (moveX, 0, moveZ); controller.SimpleMove (direction); } }
Unityでシーン遷移するとライトが暗くなる問題
UnityでSceneManager.LoadScene ("scene名")でシーンを移動すると、移動先のシーンのライトが暗くなる問題が発生した。
問題のシーンを遷移せずに初期画面として実行すると正常にライトが表示されるにも関わらず、他のシーンから移動すると暗くなってしまう。
調べてみると何時の頃からかライト情報の取り扱いが変更になったらしい
解決法
- 問題のシーンを開く
- Window > Lighting > Settingsでライトの設定を開く
- 一番下に表示されるAuto Generateのチェックを外し、その隣のGenerate Lightingをクリックする
以上でシーン遷移後もライトが暗くなる問題は解決できた
raspberryPi3にinfluxdb v1.3をインストールする
以前ラズベリーパイにv1.2のinfluxdbをインストールしましたが、今回はv1.3です
portaltan.hatenablog.com
Install InfluxDB
# ライブラリ設定 $ curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add - OK $ source /etc/os-release $ test $VERSION_ID = "7" && echo "deb https://repos.influxdata.com/debian wheezy stable" | sudo tee /etc/apt/sources.list.d/influxdb.list $ test $VERSION_ID = "8" && echo "deb https://repos.influxdata.com/debian jessie stable" | sudo tee /etc/apt/sources.list.d/influxdb.list deb https://repos.influxdata.com/debian jessie stable $ sudo apt-get update # インストール $ sudo apt-get install influxdb $ sudo service influxdb start # 確認 $ ps aux | grep influx nouziru 8210 0.0 0.2 4276 2012 pts/1 S+ 12:59 0:00 grep influx influxdb 29797 13.1 4.3 800484 38508 ? Ssl 11:15 13:40 /usr/bin/influxd -config /etc/influxdb/influxdb.conf $ ss -lntp | grep 808 LISTEN 0 128 127.0.0.1:8088 *:* LISTEN 0 128 :::8086 :::* $ influxd config ### 各種項目が表示される
influxコマンド確認
$ influx Connected to http://localhost:8086 version 1.3.7 InfluxDB shell version: 1.3.7 > show databases name: databases name ---- _internal > create database debug > show databases name: databases name ---- _internal debug > use debug Using database debug > show measurements
ちなみにssl化しているときやport番号を変更しているときはssl, unsafeSsl, portオプションが必要
> influx -ssl -unsafeSsl -port 10443
API確認
# pingチェック $ curl -sl -I http://localhost:8086/ping HTTP/1.1 204 No Content Content-Type: application/json Request-Id: 0c85b3cf-d3f2-11e7-8003-000000000000 X-Influxdb-Version: 1.3.7 Date: Tue, 28 Nov 2017 04:10:20 GMT # database確認 $ curl http://localhost:8086/query --data-urlencode "q=SHOW DATABASES" {"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"],["debug"]]}]}]} # テストデータ投入(measurement: test_measurement / field: record1, 2) $ curl -i -XPOST "http://localhost:8086/write?db=debug" --data-binary 'test_measurement record1=100' $ curl -i -XPOST "http://localhost:8086/write?db=debug" --data-binary 'test_measurement record2=200' $ curl -i -XPOST "http://localhost:8086/write?db=debug" --data-binary 'test_measurement record1=300,record2=400' # テストデータ確認 $ curl -G 'http://localhost:8086/query?db=debug' --data-urlencode 'q=SELECT * FROM test_measurement' {"results":[{"statement_id":0,"series":[{"name":"test_measurement","columns":["time","record1","record2"],"values":[["2017-11-28T04:16:19.266486831Z",100,null],["2017-11-28T04:16:28.640633831Z",null,200],["2017-11-28T04:16:44.255827602Z",300,400]]}]}]} # テストデータ確認(pretty=trueをつけると改行されて表示される) $ curl -G 'http://localhost:8086/query?db=debug&pretty=true' --data-urlencode 'q=SELECT * FROM test_measurement' { "results": [ { "statement_id": 0, "series": [ { "name": "test_measurement", "columns": [ "time", "record1", "record2" ], "values": [ [ "2017-11-28T04:16:19.266486831Z", 100, null ], [ "2017-11-28T04:16:28.640633831Z", null, 200 ], [ "2017-11-28T04:16:44.255827602Z", 300, 400 ] ] } ] } ] } # influxコマンドで確認すると $ influx Connected to http://localhost:8086 version 1.3.7 InfluxDB shell version: 1.3.7 > use debug Using database debug > select * from test_measurement name: test_measurement time record1 record2 ---- ------- ------- 1511842579266486831 100 1511842588640633831 200 1511842604255827602 300 400
tips
status確認スクリプト
#!/bin/sh HOST="https://localhost" PORT=443 echo "**********************************************************************************************************************" echo "[ping]" ping=`curl -ksI ${HOST}:${PORT}/ping` echo "$ping" echo "************************************************************************************************************************" echo "[db]" db=`curl -sk ${HOST}:${PORT}/query --data-urlencode "q=SHOW DATABASES"` echo "$db" echo "************************************************************************************************************************" echo "[latest records]" desc=`curl -skG "${HOST}:${PORT}/query?db=DEBUG&pretty=true" --data-urlencode "q=SELECT * FROM test_measurement ORDER BY time DESC LIMIT 1"` echo "$desc"
追記
csvでデータをexportする方法
$ curl -H "Accept: application/csv" -skG "${HOST}:${PORT}/query?db=${DB_NAME}" --data-urlencode "q=SELECT * FROM ${measurement_name}" > test.csv
Reference
ラズベリーパイの音声をDAC(pcm5102a)でI2S出力する
普段音声出力はRaspberryPi3のオーディオジャック(アナログ出力)から行っていますが、DACを介すことでI2S出力(デジタル出力)に変更する方法です
I2S
I2Cじゃありません. Inter IC SoundでI2Sです
4本(または3本)の信号線でステレオ音声をシリアル伝送する規格
名前 | rasPiのpin No. | 説明 |
BCK(BCLK) | 12 | ・bit clock ・serial clock(SCLK)とも呼ばれる |
LRCK(LRCLK) | 35 | ・Left Right Clock ・ステレオにおいて、LチャネルとRチャネルを区別するための信号 |
DATA | 40 | ・PCM Data ・serial data ・デジタル化された音声データのビット列 |
MCK | - | ・Master Clock ・ラズパイのGPIOからは出力されていない ・ICによっては上記3信号と同期するように自動で調整してくれるものもあり、その場合は不要 (今回使うPCM5102AもBCKから生成してくれるので不要) ・System Clock(SYSCLK)とも呼ばれる |
DAC
Degital Analog Converter
ラズパイからI2Sで出力したデジタル信号をスピーカーやヘッドフォンで使えるアナログ信号に変換するもの
今回はPCM5102AというDACチップを利用します
デジタル-アナログ変換回路 - Wikipedia
使ったもの
世の中には既に全て実装済みのDACボードがありますが、今回はチップを買って全てブレッドボード上に1から組み上げます
item | 買ったところ | 個数 |
IC&変換基板 | http://akizukidenshi.com/catalog/g/gK-11836/ | 1 |
ブレッドボード | http://akizukidenshi.com/catalog/g/gP-00315/ | 1 |
ブレッドボード用電源モジュール | https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4RAW | 1 |
抵抗(47Ω) | http://akizukidenshi.com/catalog/g/gR-25470/ | 3 |
抵抗(470Ω) | http://akizukidenshi.com/catalog/g/gR-25471/ | 2 |
コンデンサ(2.2nF) | http://akizukidenshi.com/catalog/g/gP-07686/ | 2 |
コンデンサ(0.1μF) | http://akizukidenshi.com/catalog/g/gP-10147/ | 4 |
コンデンサ(2.2μF) | http://akizukidenshi.com/catalog/g/gP-08152/ | 2 |
コンデンサ(10μF) | http://akizukidenshi.com/catalog/g/gP-04621/ | 4 |
回路図
公式ページのデータシートに回路図例があるので、その通りに組み込みます
http://www.tij.co.jp/jp/lit/ds/symlink/pcm5102a.pdf
注意する点としては
- GNDに落とすところはグランドバウンス対策で47Ω抵抗をはさんでいる
- SCK(MCK)は今回ラズパイからとれないので、GNDに落とすことでpcm5102AがBCKから生成してくれる
- ブレッドボード電源モジュールは3.3Vで使用
- 上記のデータシートの回路図はなぜかICチップ逆になっているので注意
ケーブル接続
次にラズパイと上記のDACセットを接続する
I2Sは普通に調べても表記されていないことが多く、以下のサイトがわかりやすいです
https://bluefish.orz.hm/sdoc/raspi_i2sout.html
ソフトウェア側設定
ハードのほうの組み込みが完了したら、次はラズベリーパイ側の設定を行っていきます
pcm5102Aのドライバはデフォルトでラズベリーパイにインストールされている(/boot/overlays/以下で確認できるか)ので、利用するための記述のみ行います
ドライバのマッピング
sudo vi /boot/config ### 以下の1行を末尾に追加 dtoverlay=hifiberry-dac
ドライバのロード
起動時にドライバをロードするように設定する
sudo vi /etc/modules ### 以下の1行を末尾に追加 snd_soc_hifiberry_dac
上記の設定が済んだら一度再起動する
確認
以下のようにドライバ変更が反映されていたらOK
$ lsmod | grep dac snd_soc_hifiberry_dac 2511 0 snd_soc_core 125885 3 snd_soc_bcm2835_i2s,snd_soc_hifiberry_dac,snd_soc_pcm5102a snd_pcm 75698 4 snd_bcm2835,snd_soc_core,snd_soc_hifiberry_dac,snd_pcm_dmaengine $ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA] . . card 1: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI] . .
DACがcard0のdevice0に割り当てられていることが確認できる
音声出力確認
wavファイルで確認
注意点として、この構成ではモノラルの音源は再生できず、再生しようとすると以下のようなエラーになってしまう
$ aplay -D hw:0,0 /usr/share/sounds/alsa/Noise.wav Playing WAVE '/usr/share/sounds/alsa/Noise.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono aplay: set_params:1239: Channels count non available
なので適当にフリーの音源サイトからwavファイルをダウンロードしてきてそれを再生する
- 今回は以下のフリーサイトからダウンロード
- http://www.ne.jp/asahi/music/myuu/wave/wave.htm
$ aplay -D hw:0,0 /home/pi/fanfare.wav Playing WAVE '/home/pi/fanfare.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
mp3で確認
mp3で確認する場合はmpg321等を利用する
$ mpg321 #{mp3file}
環境によってはエラーが出るが、sudoで実行するとうまくいくことがある
以上で完了。想像以上にてこずった。
ケーブルを整理してラズパイから給電に変更したもの
openssl.cnfは編集せずにオレオレ証明書をSAN対応させてchrome58へinstallする
前回自己証明書の作成方法を書いたんですが、IEとかはその証明書を使えば警告なしでアクセスできるようになるんですがChromeの場合は以下のような警告が出てしまいます
これはChromeが今年の春らへんにリリースしたv58から証明書の中の項目のCN(Common Name)の利用を非推奨化し、SAN(Subject Alternative Name)の方を利用しなさいという仕様になったためです
手順の途中でFQDNを入力するところがあったと思いますが、通常ではここで入力した値はCNという項目の値になります
しかしChromeではCNではなくSANの方へ入力したいので少し追加で操作が必要です
調べているとopenssl.cnfを編集する方法がよく出てきますが、サイトによって編集箇所や記述も違い、かつ編集量も多いので、色々調べていった結果以下のようにSANの情報だけ別ファイルにエクステンションとして切り出し、そのファイルをオプションで読み込ませてやることでopenssl.cnfは編集せずSAN対応版の証明書を作成することができました
# 秘密鍵とCSRは普通に作成(以前作成したものでよい) ## extension fileの作成 $ echo subjectAltName=DNS:${FQDN} > san.ext # 自己証明書の作成 $ openssl x509 -days 3650 -req -signkey ${name}.key < ${name}.csr > ${name}.crt -extfile san.ext
本当にSAN情報が付加されているかは以下のコマンドで確認できます
$ openssl x509 -text -noout -in ${name}.crt Certificate: . . Signature Algorithm: sha256WithRSAEncryption . . X509v3 extensions: X509v3 Subject Alternative Name: DNS:fizzbaz.foobar.com . .
自己証明書の作成方法
自己証明書(オレオレ証明書)の作成方法
基本的には
1. 秘密鍵の作成
2. 秘密鍵を使って証明書署名要求の作成
3. 秘密鍵と証明書署名要求を使って証明書の作成
という流れになる
1. 秘密鍵の作成
$ openssl genrsa -aes128 2048 > test.key
2. 証明書署名要求(CSR: Certificate Signing Request)の作成
$ openssl req -new -key test.key -out test.csr Enter pass phrase for test.pem: # 秘密鍵作成時に入力したパスワード入力 . . . ----- Country Name (2 letter code) [AU]:JP # 国名 State or Province Name (full name) [Some-State]:Tokyo #都道府県名 Locality Name (eg, city) []:Setagaya # 市区町村名 Organization Name (eg, company) [Internet Widgits Pty Ltd]:HogeHoge, Inc. # 会社・団体名 Organizational Unit Name (eg, section) []:Development Section1 # 部署名 Common Name (e.g. server FQDN or YOUR name) []:foobar.nouziru.com # FQDN Email Address []: nouziru@mail.com # メールアドレス Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: # 入力不要 An optional company name []: # 入力不要
確認
$ openssl req -text -noout -in test.csr Certificate Request: Data: Version: 0 (0x0) Subject: C=JP, ST=Tokyo, L=Setagaya, O=HogeHoge, Inc., OU=Development Section1, CN=foobar.nouziru.com/emailAddress=nouziru@mail.com Subject Public Key Info: . . .
3. 自己証明書(CRT)の作成
$ openssl x509 -days 3650 -req -signkey test.key < test.csr > test.crt Signature ok subject=/C=JP/ST=Tokyo/L=Setagaya/O=HogeHoge, Inc./OU=Development Section1/CN=foobar.nouziru.ddns.net/emailAddress=nouziru@mail.com Getting Private key
確認
$ openssl x509 -text -noout -in test.crt
以上で自己証明書の作成は完了
$ ls -l total 44 -rw-r--r-- 1 nouziru nouziru 1359 Oct 12 13:11 test.crt -rw-r--r-- 1 nouziru nouziru 1082 Oct 12 12:58 test.csr -rw-r--r-- 1 nouziru nouziru 1766 Oct 12 12:56 test.key
csrファイルは特に必要ないので削除してもかまわない
その他
derファイルへの変換
$ openssl x509 -in test.crt -outform DER -out test.der
SAN情報を付加する場合(Chrome58対策)
crtを作るときに以下のようにextファイルを作成してdomain情報をのせる
## create extension file $ echo subjectAltName=DNS:${YOUR DOMAIN} > v3.ext # generate crt $ openssl x509 -days 3650 -req -signkey ${name}.key < ${name}.csr > ${name}.crt -extfile v3.ext
ThetaS vs. Gear360(2017)
スペック比較
ThetaS | Gear360 | |
---|---|---|
静止画解像度(最大) | 5376×2688 | 5472 x 2736 |
静止画撮影モード |
|
|
オート撮影補助機能 |
|
特になし |
ISO感度 | ISO100~1600
|
ISO400~1600(?)
|
シャッタースピード | 1/6400~60秒 | 設定不可 |
F値(絞り) | F2.0(固定) | F2.2(固定) |
露出補正 | -2.0~+2.0EV (1/3EVステップ) | -3.0~+3.0EV (1/10EVステップ) |
ホワイトバランス |
|
|
マルチブラケット |
|
なし |
セルフタイマー | 2秒, 5秒, 10秒 | 2秒, 5秒, 10秒 |
インターバル撮影 | 8秒~60分内で指定可能 | なし |
HDR合成 | 4枚で合成 |
|
静止画出力形式 | equirectangular | dual-fisheye |
動画解像度(最大) | 1920×1080 | 4096×2048 |
動画フレームレート | 30fps | 24fps |
動画記録時間(最大) | 25分 | 130分 |
メモリー | 8GB(内蔵) | 256GB(別売りmicroSD) |
ペアリング可能端末 | ||
動画出力形式 | dual-fisheye | dual-fisheye |
静止画・動画編集アプリ
ThetaS
Gear360
Galaxy Gear 360 | Galaxy Mobile Japan 公式サイト
- アプリの項目を見ても説明書に載ってるURLにアクセスしてもサイト内検索しても見つからなくて、探すのにかなり手こずった・・・
比較してみた
- スティッチ精度
- 両方スティッチの精度は高い
- ただしGear360の場合はレンズの境目が少しぼやける
- また、Gear360では二つのレンズ間で色味が異なる
- HDR機能
- ThetaSの方が優秀だった(室内撮影)
- Gear360は風景HDRと指定があるので、外でとるとまた違う結果になるかもしれない
- 撮影
- 設定項目などでThetaSの圧勝
- スマホアプリ
- Gear360はGalaxy端末からじゃないとフルに機能を使えないのが辛い
- 画質
- Gear360は若干画像にノイズがのる
- 動画
- Gear360は動画の途中でレンズの境目に被写体(動体検知している?)が入ると、その被写体を優先的に貼りあわせようとするので他がゆがむ
- これは好みだが無くてもいい気がする
- ThetaSはスティッチ範囲は固定のよう
- 動画はやはり2k(ThetaS)と4k(Gear360)では比べ物にならないほど差が出る
- 2kはブラウザベースでも結構厳しい
- Gear360は動画の途中でレンズの境目に被写体(動体検知している?)が入ると、その被写体を優先的に貼りあわせようとするので他がゆがむ
- VR
- Gear360はGalaxy端末を利用した場合はすぐにGearVRから確認できるので楽
まとめ
- 静止画をとるならThetaS
- 動画をとるならGear360
とはいえGear360(2017)は出たばっかりで、ThetaSは発売してから結構時間がたって色々FBももらって洗練されていっているのは当然なので、今後のFW updateに期待したい