細かい使い方、作り方はともかく、Xcodeに取り込んで使う旨で引っかかった点、気づいた点を書く。
2019年11月29日金曜日
Blenderで3Dモデルを作ってXcodeで使う
無料だけど高機能な3DアプリのBlender。ARなんかで表示させるモデルを作りたくて勉強してる。
細かい使い方、作り方はともかく、Xcodeに取り込んで使う旨で引っかかった点、気づいた点を書く。
細かい使い方、作り方はともかく、Xcodeに取り込んで使う旨で引っかかった点、気づいた点を書く。
2019年10月2日水曜日
ARAnchorの追加と削除
以下はARKit3とSpriteNodeで作る、XcodeのARのテンプレート(AR空間にインベーダー👾の絵文字スプライトを表示させるやつ)を基に直したもの。
ARAnchorの追加
Scene.swiftの方でARAnchorの位置を決めて
sceneView.session.add(anchor: )
すると、ViewControllerのARSKViewDelegateメソッド
view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode?
が呼ばれるので、そこで貼りたいSpriteNodeをreturnしてやると、それがAnchorに貼られるという変則的なやり方になっている。
実際にどうやってanchorにspriteを貼ってるのかは知らない。
貼る時も削除する時も、sceneView.sessionに対してのメソッドを使ってるわけだ。
Scene.swift
//カメラ前方の位置にSpriteを表示するためのanchorを貼る
func addAlienAnchor(sceneView: ARSKView) -> Void {
if let currentFrame = sceneView.session.currentFrame {
var translation = matrix_identity_float4x4 //世界座標と向きを表す4*4の行列
//前方の多少ランダムな位置を決定
//行列の3列目のz値に-0.4なら前方0.4m
let x:Float = 0
let y:Float = 0
let z:Float = -4
translation.columns.3.x = x
translation.columns.3.y = y
translation.columns.3.z = z
//カメラの向いてる方向に対しての表示位置を計算
let transform = simd_mul(currentFrame.camera.transform, translation)
//セッションに新しいARアンカーを追加
let anchor = ARAnchor(transform: transform)
sceneView.session.add(anchor: anchor) //sceneViewのsessionにアンカー追加
//アンカー追加によってViewControllerのdelegateが呼ばれる
}
}
ViewController.swift
引数anchorがこれからspriteを貼るanchor。
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
//省略するが、ここにAnchorに貼りたいSpriteNodeを作り、returnで返す
return spriteNode
}
ARAnchorの削除
新たなARAnchorを貼るとき、または貼るSpriteNodeを作った時、anchorを管理用の変数に入れておき、削除が必要になったらそれを削除すると、それに貼り付いているSpriteNodeもろとも削除される。
sceneView.session.remove(anchor: anchor)
ARKitのカメラの露出を変えたい(今は無理っぽい)
以下は最新のiOS13、ARKit3でのお話。今後のことは知らん。
たとえば晴れた昼間カーテンをした部屋の中だと1/60や1/90、青空だと1/4484、太陽に向けると1/10000。暗い押入れに向けた場合1/60だった。
やりたいこと
夜の外とか暗いところでARKitで撮影すると、普通のカメラ撮影に比べてやたら暗いので、露出がコードから変えられないものか。
調べる
最初に、今のところ調べた結果ではカメラの撮影設定(オートフォーカスとかも)をいじれるAPIは公開されていないようだ。
明るい所ではシャッター速度を変えて露出を調節しているようだが(絞りまで変えているかは知らない)、暗い所ではスローシャッターの限界が1/60秒みたい。
ちなみにARカメラのシャッター速度は以下のコードでわかる。
if let currentFrame = sceneView.session.currentFrame {
let 露光時間 = 1 / currentFrame.camera.exposureDuration
print("露光時間 1/\(露光時間)")
}
あんまりスローシャッターにすると手ぶれで物体の検出に影響するから制限してるっぽい? ISO感度も変更しない?
結論
今は無理っぽい。
あんまり暗い場所での使用は推奨されないんだろうな。ARanchorにSprite貼って表示させても、距離感が狂うせいか勝手に大きさが変わったり、消えちゃうことも。
暗闇に浮かぶ宇宙人や幽霊を表現したいんだが、別のやり方考えなきゃダメか?
2019年3月30日土曜日
MMDの3DキャラをSceneKitに表示させたい
WindowsにMikuMikuDance(MMD)ってアプリがあって、3Dキャラをアニメーションで踊らせたりできるわけだが、そのキャラをiOSのSceneKitに表示してみたいと考えた。
特にARKitを使ってけものフレンズのサーバルちゃんとかを室内に表示させたり。
調べてわかったのが以下のやり方。
Blenderとadd-onがダウンロードできるアドレスは自分で調べてください。
特にARKitを使ってけものフレンズのサーバルちゃんとかを室内に表示させたり。
調べてわかったのが以下のやり方。
Blenderとadd-onがダウンロードできるアドレスは自分で調べてください。
- 3DソフトBlenderとadd-on機能を使って、MMDの.mmxファイルをiOSで扱える.daeフォーマットに変換。
- Xcodeプロダクトに変換したdaeファイルをAdd。
- ARKitのサンプルコードを使って表示。
1:.pmxファイルを.daeファイルに変換
Blenderとadd-onのプラグインをダウンロードし、以下のBlenderの設定フォルダにプラグインを入れる。
Macintosh HD/ユーザ/(ユーザ名)/ライブラリ/Application Support/Blender/(アプリのバージョン。たとえば2.79)/scripts/addons
しかし、アプリ起動しただけじゃ設定フォルダが作られないらしい。File / UserPreferences... でウィンドウを開き、Save User Settingsを押すとできるようだ。それでもプラグインをしまうscriptsフォルダ以下ができないみたいなので、自作することになった。scripts、addonsと複数形なので間違えないように。
またそのフォルダに入れるのはblender_mmd_tools-masterフォルダ内のmmd_toolsフォルダ以下だけ。
BlenderのUser Preferencesウィンドウを開いてAdd-onsのObject:mmd-toolsにチェックを入れると、.mmxファイルのインポートができるようになる。
.daeにエクスポート
拡張子.daeは正式にはCOLLADAっていうんだね。
エクスポート時は対象となるオブジェクトを選択し、以上のようにいくつかボタンをチェックし(チェックを外すのも)、コンボボックスからレンダーを選んでから行う。
2:プロダクトに.daeファイルをAdd
.pmxファイルをインポートし.daeファイルにエクスポートしたら、それをXcodeのart.scnassetsフォルダにaddする。
.daeファイルだけでやっている人がいたのだが、それだけだと当然テクスチャーが表示されない。しょうがないのでテクスチャーその他を含んだフォルダごとaddした。
その状態でその.daeファイルを選択すると、ちょっと時間がかかるがXcode上に3Dキャラが表示される。
もしその中にrigidbodiesというカテゴリができていたら、いらないらしいので削除しちゃっていい。
表示はすごく拡大されて歪んでるので、scaleなどを調整してやらないといけない。
保存できない問題が
.scnファイルをいじった後、RunやSaveしようとすると
The document “serval.dae” could not be autosaved. Your changes will not be saved until the problem is resolved.
などと出てなぜか保存できないことがあった。
どうやらHomeフォルダ以下のPermissionがおかしくなってたらしく、以下の2つのサイトを参考にPermissionの修復をしたところ、無事に保存できるようになった。
Homeフォルダ以下全てのファイルを修復するようなので、結構時間はかかる。
https://forums.developer.apple.com/thread/109669#335313
https://support.apple.com/en-us/HT203538
うちの環境だけの問題かもしれない。
The document “serval.dae” could not be autosaved. Your changes will not be saved until the problem is resolved.
などと出てなぜか保存できないことがあった。
どうやらHomeフォルダ以下のPermissionがおかしくなってたらしく、以下の2つのサイトを参考にPermissionの修復をしたところ、無事に保存できるようになった。
Homeフォルダ以下全てのファイルを修復するようなので、結構時間はかかる。
https://forums.developer.apple.com/thread/109669#335313
https://support.apple.com/en-us/HT203538
うちの環境だけの問題かもしれない。
EditorメニューのConvert to SceneKit scene file format (.sce) を選んで.scnファイルに変換する。
2018年9月13日木曜日
ARのお勉強/Sprite版
ARSessionの開始手順
AR空間に表示するSpriteや3Dオブジェクトは別として、とりあえずARSessionだけ開始する方法
SKSceneを読み込み、SKSceneViewのsceneとして表示
@IBOutlet var sceneView: ARSKView! //StoryboardのSceneViewと接続されてる
if let scene = SKScene(fileNamed: "Scene") {
sceneView.presentScene(scene)
}
Scene.swiftへのアクセスは以下のようにすればできる。
let s = sceneView.scene as! Scene
AR空間を認識させる
バックカメラを使い、デバイスの位置、向き、AR空間の認識などを行う。開始時に行われ、数秒間待たされる。
let configuration = ARWorldTrackingConfiguration()
let configuration = ARWorldTrackingConfiguration()
ARSession開始
ARWorldTrackingConfigurationで認識したAR設定に基づいてARSessionを開始する。
sceneView.session.run(configuration)
AR空間にオブジェクトを表示させる
ARAnchor
ARのオブジェクトを表示する位置を指定するのがARAnchor。ARAnchorをAR空間に貼り付けた後、動かせるのか、動かせないのかはまだ不明。
行列でできている
ARAnchorの値は4*4の行列(matrix_identity_float4x4)で示される。例)以下は変数に作られたばかりの行列の値
simd_float4x4([[1.0, 0.0, 0.0, 0.0)], [0.0, 1.0, 0.0, 0.0)], [0.0, 0.0, 1.0, 0.0)], [0.0, 0.0, 0.0, 1.0)]])
その行列の4個目(0オリジンなのでindexなら3)の要素のうちx, y, zがそれぞれAR空間の軸に対応しており、デバイスを中心にしたARAnchorの位置を1m = 1.0としてFloatで指定する。
- xは0がデバイス位置、プラスが下↓、マイナスが上↑
- yは0がデバイス位置、プラスが右方向→、マイナスが左方向←
- zは0がデバイス位置、プラスが後方(液晶モニタ側)、マイナスが前方(カメラの先)
指定方法
//世界座標と向きを表す4*4の行列
var transform = matrix_identity_float4x4
//行列の3列目のz値に-0.2で前方0.2mを指定
transform.columns.3.x = 0
transform.columns.3.y = 0
transform.columns.3.z = -0.2
ARSKViewDelegate
AR空間に表示するものには、2DのSpriteと3Dのオブジェクトの2つあるが、今回は2DのSprite。ARAnchorに実際にSpriteを貼るには以下のDelegateメソッドを利用する。
新規ARAnchor追加で呼ばれる
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? { }新しいARAnchorが追加されると呼ばれ、そこに貼りたいSpriteをreturnしてやればいい。
ARAnchorにSKNodeが貼られると呼ばれる
func view(_ view: ARSKView, didAdd node: SKNode, for anchor: ARAnchor) { }
SpriteのActionを使う
view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? で返すSpriteNodeにActionを設定してやればいいのだが、直接そのSpriteNodeを返してもARAnchorに固定されているため、思ったような動きをしてくれない。
そこで空のSKNodeを作り(仮にreturnNodeとする)、それにaddChildeした上で、そのreturnNodeを返してやればいい。
そこで空のSKNodeを作り(仮にreturnNodeとする)、それにaddChildeした上で、そのreturnNodeを返してやればいい。
let returnNode = SKNode()
中略
returnNode.addChild(spriteNode)
return returnNode
Spriteを消す時には、このダミーの親ノードも消さないとゴミが残っちゃうぞ。
Spriteを消す時には、このダミーの親ノードも消さないとゴミが残っちゃうぞ。
2018年6月15日金曜日
AR画面にSpriteを表示したい
Xcode9のARのテンプレートに用意されてるが、それを学習する。
ARもSpriteもよくわかってないので、時々トンチンカンかもしれませんよ。
ARSKViewにdelegateが設定されており、SceneがtouchされてScene.swiftで新しいanchorが追加されると、ViewControllerに書かれた以下のdelegateメソッドが呼ばれ、anchor位置に👾のSpriteを表示する。
以下のARSKViewのdelegateメソッドが新しいanchorが追加されたら呼ばれるもの
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? { }
ARAnchorは4*4の行列で表されており、カメラを向けた位置の値(currentFrame.camera.transform)を別に用意した行列の変数(translation)と計算して変更している。
translationは行列の3列目のzの値に-0.2を設定し、カメラ位置の情報と演算することで前方0.2mのAnchor位置を設定している。
同じく以下のようにx,yの値を変更すれば、3次元空間上のAnchor位置を変更できる。なぜか横軸がy、縦軸がxっぽいのが納得いかないが。
AR開始時のカメラ(デバイス)の向きを基準に、以下のような意味になるようだ。
以下のように3列目のx,y,zを変更すれば、ある程度自由な位置に表示できる。
ARもSpriteもよくわかってないので、時々トンチンカンかもしれませんよ。
使用ファイル
- Scene.sks
- Spriteを表示するための場所。Viewみたいなものだろ。場所として持ってるだけで、InterfaceBuilder的には何も設定されてないっぽい。
- Scene.swift
- Scene.sksに結びついてるクラス
- 表示されたSceneがtouchされたらどうのこうの…という処理をしてるようだ
- ViewController.swift
- Scene.sksをロードして表示する
- AR画面にSpriteを表示するためのARSKViewのdelegateメソッドで実際にSprite(ここではLabelNodeで👾)を表示してる
Scene.swift
touchしたらカメラの向いた方向の、カメラ位置の20cm先にARAnchorを追加する。
ARAnchorとは
ARシーンにオブジェクトを配置するために使用する、実世界の位置と方向の情報。ARAnchorを追加すれば、カメラの向きを変えたり、近づいたり離れたりしても、その空間上の位置を覚えててくれるわけですな。それによってそこに配置したSpriteに近づいたり離れたりできるわけだ。
カメラに対する実オブジェクトまたは仮想オブジェクトの位置と向きを追跡するには、アンカーオブジェクトを作成し、add(anchor :)メソッドを使用してそれらをARセッションに追加する。
ARKitは、ワールドトラッキングセッションでplaneDetection(平面探索)オプションを有効にすると、アンカーも自動的に追加される。
ViewController
Scene.sksをロードし、ARSKViewに表示。ARSKViewにdelegateが設定されており、SceneがtouchされてScene.swiftで新しいanchorが追加されると、ViewControllerに書かれた以下のdelegateメソッドが呼ばれ、anchor位置に👾のSpriteを表示する。
以下のARSKViewのdelegateメソッドが新しいanchorが追加されたら呼ばれるもの
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? { }
デリゲートに、新たに追加されたアンカーに対応するSpriteKitノードを提供するように要求します。LabelNodeを作り、それをreturnしてるので、追加されたanchorの位置に表示している
任意の位置に表示させたい
Scene.swiftのtouchBegan()ではカメラを向けた方角の前方(設定では0.2m)に👾を表示させるべくARAnchorを追加している。ARAnchorは4*4の行列で表されており、カメラを向けた位置の値(currentFrame.camera.transform)を別に用意した行列の変数(translation)と計算して変更している。
translationは行列の3列目のzの値に-0.2を設定し、カメラ位置の情報と演算することで前方0.2mのAnchor位置を設定している。
同じく以下のようにx,yの値を変更すれば、3次元空間上のAnchor位置を変更できる。なぜか横軸がy、縦軸がxっぽいのが納得いかないが。
AR開始時のカメラ(デバイス)の向きを基準に、以下のような意味になるようだ。
- zは+が背後、-が前方
- xは+が下、-が上方向
- yは+が右手、-が左手
以下のように3列目のx,y,zを変更すれば、ある程度自由な位置に表示できる。
if let currentFrame = sceneView.session.currentFrame {
var translation = matrix_identity_float4x4 //世界座標と向きを表す4*4の行列
//zが奥行きの軸はいいとして、xが横軸、yが縦軸と思いきや、xが縦、yが横みたい?
translation.columns.3.z = -0.2 //奥行き(前方0.2m)
translation.columns.3.x = -1.0 //縦軸(上方1.0m)
translation.columns.3.y = 0.5 //横軸(右手0.5m)
//これは南を向いてデバイスを水平に構えた時の行列の値
var transform = matrix_float4x4([0.0237875, -0.9977, 0.0634782, 0.0], [0.999125, 0.02154, -0.035859, 0.0], [0.0344092, 0.0642756, 0.997339, 0.0], [-0.000370748, -0.114079, -0.340914, 1.0])
//南向き水平の値に対し、x,y,zの値を演算して変更している
transform = simd_mul(transform, translation)
//セッションに新しいARアンカーを追加
let anchor = ARAnchor(transform: transform) //アンカーを作成
sceneView.session.add(anchor: anchor) //sceneViewのsessionにアンカー追加
//これによってViewControllerのdelegateが呼ばれる
}
2018年6月5日火曜日
WWDC2018
ゆんべ美國でおこなわれたWWDCの開発関係の自分用まとめ。
- iOS 12発表
- リリースは秋
- インストール対象はiOS11が動くデバイス
- パフォーマンスが向上
- Pixarと共同でAR関係の新ファイルフォーマット USDZ(ユーエスディーズィー) を開発
- Apple純正AR物差しアプリ 「Measure」発表
- ARKit 2発表
- 顔認識やレンダリングその他を改良、最大4人のマルチユーザをサポート
- その他もろもろ
- macOS Mojave(モハーベ)発表
- リリースは秋
- iOSのUIKitをmacOSに導入
- Appleからニュース、株式、音声メモ、ホームの各iOSアプリをMac用にリリース
- 2019年にデベロッパにも提供され、iOSアプリをmacOSに移植可能に
- iOSとmacOSの統合は否定
OSの改良でパフォーマンス向上してくれるのは歓迎。
でもまたいろいろいじらなきゃいけない点が出てくるだろーなー。仮により簡単に作れるようになったとしても、概念や扱い方が大きく違ったりすると直すのがめんどい。こちとら新しいアプリ作りたいんじゃ。過去のアプリのサポートばっかりやってられるかい!
ARKit1もまだよく使ってない。こないだiPhone買ったばかりだし。
Measureって、日本のAppStoreに同名のアプリ(個人開発)があるんだけど、いいのか? まさかそのアプリを買収するわけじゃないよね?
UIKitがMacでも使えるようになるのはいいね。扱いが統一されるとやりやすい。移植可能になるというより、移植が楽になるってこっちゃな。今までのmacOSのUIを司ってたAPIを置き換えちゃうわけじゃないんでしょ?
iOSはUIKitだけにあらずなので、そのほかのAPIというかFrameworkの互換性ってのはどんなもんなのかね?
ラベル:
Apple Developer,
AR,
iOS,
MacOS,
UI部品
2017年9月3日日曜日
ARとモーションセンサー覚書
勉強中のARプログラミングと、CMMotionManager( )を使ったモーションセンサー等についてメモっとく。
ジンバルロック
詳しくはググってほしいけど、3軸の姿勢センサーの2軸の動きが重なってしまい、姿勢が正しく計測できなくなること。
姿勢センサーを使ったアプリで、時々「∞の字に動かしてください」とか出るのはこれをリセットするためか?
Pitch, Roll, Yaw値の範囲
CMMotionManager( )のAttitudeとして得られるそれぞれの値の範囲(度数法の角度で)
- Pitch
- -90 〜 0 〜 90
- デバイスを机に画面を上で寝かせた状態が0
- 垂直に起こした状態が90
- デバイス上部を垂直に下にした状態が-90
- Roll
- -180 〜 0 〜 180
- デバイスを机に画面を上で寝かせた状態が0
- 左に傾けて起こしていくとマイナスになって、完全にひっくり返すと-180
- 右に傾けて起こしていくとプラスになって、完全にひっくり返すと180
- Yaw
- -180 〜 0 〜 180
- デバイスを机に画面を上で寝かせて西を向けた状態が0
- 反時計回りでプラスになって、東で180
- 時計回りでマイナスになって、東で-180
2017年8月2日水曜日
ARkitのクラス
iOS11から搭載されるARkitのクラスの情報の概要。
まあよくわからんのだけれども…。
拡張現実感(Augmented reality:AR)は、デバイスのカメラからのライブビューに2Dまたは3D要素を追加して、それらの要素を現実の世界に生息するように見せるユーザーエクスペリエンスを記述します。
ARKitは、デバイスのモーショントラッキング、カメラシーンキャプチャ、高度なシーン処理、および便利さの表示を組み合わせて、ARエクスペリエンスを構築する作業を簡素化します。
あなたのアプリをARKitをサポートするデバイスでのみ利用できるようにするには、アプリのInfo.plistのUIRequiredDeviceCapabilitiesセクションにあるarkitキーを使用します。
拡張現実感がアプリの副機能である場合は、isSupported プロパティを使い、現在のデバイスが使用するセッション構成をサポートしているかどうかを判断します。
まあよくわからんのだけれども…。
拡張現実感(Augmented reality:AR)は、デバイスのカメラからのライブビューに2Dまたは3D要素を追加して、それらの要素を現実の世界に生息するように見せるユーザーエクスペリエンスを記述します。
ARKitは、デバイスのモーショントラッキング、カメラシーンキャプチャ、高度なシーン処理、および便利さの表示を組み合わせて、ARエクスペリエンスを構築する作業を簡素化します。
重要
ARKitには、A9以降のプロセッサを搭載したiOSデバイスが必要です。あなたのアプリをARKitをサポートするデバイスでのみ利用できるようにするには、アプリのInfo.plistのUIRequiredDeviceCapabilitiesセクションにあるarkitキーを使用します。
拡張現実感がアプリの副機能である場合は、isSupported プロパティを使い、現在のデバイスが使用するセッション構成をサポートしているかどうかを判断します。
最初のステップ
ARSession class
拡張現実体験に必要なデバイスカメラとモーション処理を管理する共有オブジェクト。
構成(Configurations)
class ARSessionConfiguration
デバイスの向きのみを追跡する基本構成。
——デバイスの傾き(回転)に関してのみで、位置に関しての情報(デバイスを左に動かしたとかそういうこと)は扱わない。
class ARWorldTrackingSessionConfiguration
デバイスの向きと位置を追跡し、デバイスカメラが認識する実際の表面を検出する構成。
——デバイスの傾き(回転)と位置に関しての情報(デバイスを左に動かしたとかそういうこと)の双方を扱う。
標準ビュー(Standard Views)
Building a Basic AR Experience
ARセッションを設定し、SceneKitまたはSpriteKitを使用してARコンテンツを表示します。
class ARSCNView
3D SceneKitコンテンツを使用して、カメラビューを拡大するARエクスペリエンスを表示するためのビュー。
class ARSKView
2D SpriteKitコンテンツを使用して、カメラビューを拡大するARエクスペリエンスを表示するビュー。
カスタムビュー(Custom View)
Displaying an AR Experience with Metal
カメラ画像のレンダリングと位置追跡情報を使用して、オーバーレイコンテンツを表示することにより、カスタムARビューを構築します。
実世界の物体と位置(Real-World Objects and Positions)
class ARAnchor
ARシーンにオブジェクトを配置するために使用できる、実際の位置と方向。
class ARPlaneAnchor
ARセッションで検出された、実際の平面の位置と向きに関する情報。
class ARHitTestResult
ARセッションのデバイスカメラビュー内のポイントを調べることで見つかった、実際のサーフェスに関する情報。
カメラとシーンの詳細(Camera and Scene Details)
class ARFrame
ARセッションの一部としてキャプチャされた、ビデオ画像および位置追跡情報。
class ARCamera
ARセッションにおけるキャプチャされた、ビデオフレームのカメラ位置および撮像特性に関する情報。
class ARLightEstimate
ARセッション内のキャプチャされた、ビデオフレームに関連する推定シーン照明情報。
2017年3月9日木曜日
モーションセンサー、うまくいくようないかないような
モーションセンサーには以下のようなものがある。
値の範囲は決まっているはずだが、センサーの精度の問題なのか、範囲の上限/下限値にならないことも多く、上限/下限値をまたいだ処理をさせると値が飛んでしまうこともあり困る。
プロはどうやってスムーズな処理をしてるんだろう? 誰かおせーて!!
- 加速度センサー(Accelerometer)
- X軸、Y軸、Z軸方向に動かした場合、どちらの方向にどれだけ加速度がかかったか
- ジャイロセンサー(Gyro)
- X軸、Y軸、Z軸を軸として傾けた場合の、1秒あたりに傾いたラジアン角を得られる(角速度)
- 磁気センサー(Magnetometer)
- X軸、Y軸、Z軸の磁力センサーの値
- デバイスモーション(DeviceMotion)
- 加速度、ジャイロ、磁気の3センサーを統合して加工。ということはこれだけ使えばいい?
- 公式には「装置の姿勢、回転速度、および加速度のカプセル化された測定値」とある。
- 加速度計は、重力加速度とユーザー加速度の2つの加速度ベクトルの合計を測定します。 ユーザー加速度は、ユーザーがデバイスに与える加速度です。 Core Motionは、ジャイロスコープと加速度計の両方を使用してデバイスの姿勢を追跡することができるため、重力とユーザーの加速度を区別できます。 CMDeviceMotionオブジェクトは、重力加速度およびユーザー加速度プロパティの両方の測定値を提供します。
- 姿勢センサー(Attitude)
- X軸、Y軸、Z軸を軸として傾けた場合の角度(Pitch、Roll、Yawのオイラー角)、行列(マトリックス)、クォータニオン(よくわからんが)を得られる。
- X軸中心の前後の傾きがpitch
- 画面上で寝かせて0度。起こしていくと増えていき、垂直で90度。さらに画面下向きに寝かせていくと減っていき0度に。
- 増えていった値が90度を境に減るはずだが、時には87度前後で減り出したり、よくわからない。
- Y軸中心の左右の回転がroll
- pitchが90度を超えると急に-150度とかになったり、わからない
- Z軸中心の左右の傾きがyaw
- これがわずかに傾いてるだけでもpitchの値が90までいかないうちに減り出すことがあるようだ。
- 重力加速度(Gravity)
- 地球の重力に対しての向き
- X軸はLandscapeでホームボタンが右なら-1.0、左なら1.0、Portrateなら0
- Y軸はPortrateでホームボタンが下なら-1.0、上なら1.0、Landscapeなら0
- Z軸は画面が真上なら-1.0、垂直に立てると0、画面が真下なら1.0
ライブラリはあらかじめCoreMotionをimportしとく。
import CoreMotion //モーションセンサー
var motionMgr:CMMotionManager?
センサーの設定とスタートまで
//モーションマネージャーは各種センサー共通
motionMgr = CMMotionManager()
//更新頻度(秒)
motionMgr?.deviceMotionUpdateInterval = 0.1 //姿勢センサー
//姿勢センサースタート(クロージャでセンサーが更新された時の処理を書く)
motionMgr?.startDeviceMotionUpdates(to: OperationQueue.current!, withHandler: { (data, error) in
let pitchDeg = round(180 * data!.attitude.pitch / M_PI)
let rollDeg = round(180 * data!.attitude.roll / M_PI)
let yawDeg = round(180 * data!.attitude.yaw / M_PI)
})
//姿勢センサーの停止
motionMgr?.stopDeviceMotionUpdates()
ローパスフィルター
センサーの値がノイズによってばらけることが多いらしく、前回検出した値との加算平均を取る処理(これをローパスフィルターとかハイパスフィルターとか言うらしい)をした方がいいそうである。
最新の値の90%と、前回の値の10%を足すわけですな。
//ローパスフィルター処理(ここでは0.9がレート)
var outputValue:Double
if (self.prevAngle != nil) {
outputValue = (pitchDeg * 0.9) + (self.prevAngle! * (1.0 - 0.9))
} else {
outputValue = pitchDeg
}
self.prevAngle = outputValue
他のセンサー使用時
センサーの値を取り出す各種プロパティは省略。
//各センサーの更新頻度(秒)設定
motionMgr?.accelerometerUpdateInterval = 0.1 //加速度センサー
motionMgr?.gyroUpdateInterval = 0.1 //ジャイロセンサー
//各センサーのスタート(引数は省略したが姿勢センサーと同様に)
motionMgr?.startAccelerometerUpdates() //加速度センサー
motionMgr?.startGyroUpdates() //ジャイロセンサー
//各センサー停止
motionMgr?.stopAccelerometerUpdates() //加速度センサー
登録:
投稿 (Atom)

