2

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

残念ながら、私には自分でそれを行うための数学のスキルがありません。調べてみると、これが私の問題に最も関連するハンズオン ガイドであると思われました、実装後、私の問題に適応していないようです (POI ビューはデバイスの動きのために一瞬しか表示されず、一見より多くのように見えます)。その見出しよりも; onDisplayLink メソッド (大きな変更がある唯一のメソッド) を以下に投稿しました)。関連する数学を調べてみましたが、この時点では、自分でアプローチを見つけたり、コード内のエラーを見つけたりするのに十分な知識がありません。何か助けてください。

編集:以来、センサー データは int よりも double で保存する方がよいことを認識し、少しスムージングを追加しました。これで、デバイスの回転時に横から表示されるはずの 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: r の割り当てを、目標の途中にあるように見えるものに更新しました。デバイスが直立している場合、水平面近くにランドマークが表示されるようになりました。ただし、予想される位置から時計回りに約 90 度ずれています。また、ベータによって提案された移動後の出力:

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
4

1 に答える 1

2

iPhone 4 を入手した後、上記のコードによって生成されたデータを 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 を適切にサポートするための出発点です。ある種のフィルタリングによって追加の品質が得られる可能性がありますが、それが努力する価値があるかどうかはまだ判断していません.

于 2012-04-25T09:12:37.143 に答える