2012-04-17 6 views
2

iPhone上で拡張現実感ビューを作成したいと思います。出発点として、私はAppleのpARkデモプロジェクトを見てきました。ただし、deviceMotionプロパティは、カメラ変換を行うための回転行列を取得するために使用されます。しかし、deviceMotionはジャイロスコープ(iPhone 4以降で利用可能)を使用しており、3GSもサポートしたいので(3GSは私の唯一の開発デバイスです)、私はこのアプローチを使用できません。そこで、加速度計とコンパスから入手できるデータを使用して、自分自身で回転行列を作成したいと考えています。ジャイロスコープを持たないデバイスでCMRotationMatrixを作成する方法

残念ながら、私は自分自身で行う数学スキルが不足しています。私の問題の最も適切なハンズオンガイドはthisだと私には思われましたが、実装に続いて私の問題に適応していないように見えました(POIビューは一時的にしか見えず、私のonDisplayLinkメソッド(大きな変更を加えた唯一のメソッド)を投稿しました)。私は関連する数学を読み上げようとしましたが、この時点では、自分自身でアプローチを見つけたり、自分のコードでエラーを見つけたりするには、それについて十分に知りません。助けてください。

編集:センサーデータがintよりも倍精度で格納され、スムージングが少し追加されていることがわかりました。ここでは、デバイスの回転時に側面から表示されるPOIが、上から降りてくるのをより明確に見ることができます。おそらく、何が間違っているのかを指すのに役立ちます。北を指し

装置がテーブル上に置かれ
CMAccelerometerData* orientation = motionManager.accelerometerData; 
CMAcceleration acceleration = orientation.acceleration; 

vec4f_t normalizedAccelerometer; 
vec4f_t normalizedMagnetometer; 

xG = (acceleration.x * kFilteringFactor) + (xG * (1.0 - kFilteringFactor)); 
yG = (acceleration.y * kFilteringFactor) + (yG * (1.0 - kFilteringFactor)); 
zG = (acceleration.z * kFilteringFactor) + (zG * (1.0 - kFilteringFactor)); 

xB = (heading.x * kFilteringFactor) + (xB * (1.0 - kFilteringFactor)); 
yB = (heading.y * kFilteringFactor) + (yB * (1.0 - kFilteringFactor)); 
zB = (heading.z * kFilteringFactor) + (zB * (1.0 - kFilteringFactor)); 

double accelerometerMagnitude = sqrt(pow(xG, 2) + pow(yG, 2) + pow(zG, 2)); 
double magnetometerMagnitude = sqrt(pow(xB, 2) + pow(yB, 2) + pow(zB, 2)); 

normalizedAccelerometer[0] = xG/accelerometerMagnitude; 
normalizedAccelerometer[1] = yG/accelerometerMagnitude; 
normalizedAccelerometer[2] = zG/accelerometerMagnitude; 
normalizedAccelerometer[3] = 1.0f; 

normalizedMagnetometer[0] = xB/magnetometerMagnitude; 
normalizedMagnetometer[1] = yB/magnetometerMagnitude; 
normalizedMagnetometer[2] = zB/magnetometerMagnitude; 
normalizedMagnetometer[3] = 1.0f; 

vec4f_t eastDirection; 

eastDirection[0] = normalizedAccelerometer[1] * normalizedMagnetometer[2] - normalizedAccelerometer[2] * normalizedMagnetometer[1]; 
eastDirection[1] = normalizedAccelerometer[0] * normalizedMagnetometer[2] - normalizedAccelerometer[2] * normalizedMagnetometer[0]; 
eastDirection[2] = normalizedAccelerometer[0] * normalizedMagnetometer[1] - normalizedAccelerometer[1] * normalizedMagnetometer[0]; 
eastDirection[3] = 1.0f; 

double eastDirectionMagnitude = sqrt(pow(eastDirection[0], 2) + pow(eastDirection[1], 2) + pow(eastDirection[2], 2)); 

vec4f_t normalizedEastDirection; 

normalizedEastDirection[0] = eastDirection[0]/eastDirectionMagnitude; 
normalizedEastDirection[1] = eastDirection[1]/eastDirectionMagnitude; 
normalizedEastDirection[2] = eastDirection[2]/eastDirectionMagnitude; 
normalizedEastDirection[3] = 1.0f; 

vec4f_t northDirection; 

northDirection[0] = (pow(normalizedAccelerometer[0], 2) + pow(normalizedAccelerometer[1],2) + pow(normalizedAccelerometer[2],2)) * xB - (normalizedAccelerometer[0] * xB + normalizedAccelerometer[1] * yB + normalizedAccelerometer[2] * zB)*normalizedAccelerometer[0]; 
northDirection[1] = (pow(normalizedAccelerometer[0], 2) + pow(normalizedAccelerometer[1],2) + pow(normalizedAccelerometer[2],2)) * yB - (normalizedAccelerometer[0] * xB + normalizedAccelerometer[1] * yB + normalizedAccelerometer[2] * zB)*normalizedAccelerometer[1]; 
northDirection[2] = (pow(normalizedAccelerometer[0], 2) + pow(normalizedAccelerometer[1],2) + pow(normalizedAccelerometer[2],2)) * zB - (normalizedAccelerometer[0] * xB + normalizedAccelerometer[1] * yB + normalizedAccelerometer[2] * zB)*normalizedAccelerometer[2]; 
northDirection[3] = 1.0f; 

double northDirectionMagnitude; 

northDirectionMagnitude = sqrt(pow(northDirection[0], 2) + pow(northDirection[1], 2) + pow(northDirection[2], 2)); 

vec4f_t normalizedNorthDirection; 

normalizedNorthDirection[0] = northDirection[0]/northDirectionMagnitude; 
normalizedNorthDirection[1] = northDirection[1]/northDirectionMagnitude; 
normalizedNorthDirection[2] = northDirection[2]/northDirectionMagnitude; 
normalizedNorthDirection[3] = 1.0f; 

CMRotationMatrix r; 
r.m11 = normalizedEastDirection[0]; 
r.m21 = normalizedEastDirection[1]; 
r.m31 = normalizedEastDirection[2]; 
r.m12 = normalizedNorthDirection[0]; 
r.m22 = normalizedNorthDirection[1]; 
r.m32 = normalizedNorthDirection[2]; 
r.m13 = normalizedAccelerometer[0]; 
r.m23 = normalizedAccelerometer[1]; 
r.m33 = normalizedAccelerometer[2]; 

transformFromCMRotationMatrix(cameraTransform, &r); 

[self setNeedsDisplay]; 

と略(Compass.appを使用して)、私は、このデータをログ:

Accelerometer: x: -0.016692, y: 0.060852, z: -0.998007 
Magnetometer: x: -0.016099, y: 0.256711, z: -0.966354 
North Direction x: 0.011472, y: 8.561041, z:0.521807 
Normalized North Direction x: 0.001338, y: 0.998147, z:0.060838 
East Direction x: 0.197395, y: 0.000063, z:-0.003305 
Normalized East Direction x: 0.999860, y: 0.000319, z:-0.016742 

ない正気見えますか?

編集2:私は、明らかに私の目標の半分に私を導く1にrの割り当てを更新しました:デバイスが直立しているとき、私は今水平面の近くにランドマークを見ます。しかし、彼らは彼らの予想される場所から約90度のクロックワードです。また、ベータ版が提案し、移動後の出力:iPhone 4のホールドを取得した後

Accelerometer: x: 0.074289, y: -0.997192, z: -0.009475 
Magnetometer: x: 0.031341, y: -0.986382, z: -0.161458 
North Direction x: -1.428996, y: -0.057306, z:-5.172881 
Normalized North Direction x: -0.266259, y: -0.010678, z:-0.963842 
East Direction x: 0.151658, y: -0.011698, z:-0.042025 
Normalized East Direction x: 0.961034, y: -0.074126, z:-0.266305 
+0

私はコードをテストする手段がありませんが、いくつかの機会があります。 'eastDirection'と' northDirection'が意図どおりに動作することを確認できますか? – Beta

+0

私は確信していませんので、上記の編集と一緒にいくつかのログデータを追加しました。それは役に立ちますか? – mss

+0

よく見えます。北は+ Y、東は+ Xです。南端を90度回転して北端を上げると、東はまだ+ X、北は-Zであることを確認する必要があります。今、ローテーションマトリックスで何をしたいのですか?それがいつ働いているかをどのように知っていますか? – Beta

答えて

2

は、私がCoreMotion姿勢データの出力と上記のコードによって生成されたデータを比較することができました。これで、私は次のように私の回転行列に値を割り当てる必要があることが分かった:

CMRotationMatrix r; 
r.m11 = normalizedNorthDirection[0]; 
r.m21 = normalizedNorthDirection[1]; 
r.m31 = normalizedNorthDirection[2]; 
r.m12 = 0 - normalizedEastDirection[0]; 
r.m22 = normalizedEastDirection[1]; 
r.m32 = 0 - normalizedEastDirection[2]; 
r.m13 = 0 - normalizedAccelerometer[0]; 
r.m23 = 0 - normalizedAccelerometer[1]; 
r.m33 = 0 - normalizedAccelerometer[2]; 

これは、ほぼ同じ値を示しますが、もちろん、ジャイロを使っCoreMotionによって生成されたデータは、はるかに優れています。とにかく、3GSを合理的にサポートするための出発点です。たぶん何らかのフィルタリングによって得られる追加の品質があるかもしれませんが、努力する価値があるかどうかはまだ決めていません。

関連する問題