iOS 5でcmdevicemotionでデバイスの見出しを取得するにはどうすればよいですか
-
27-10-2019 - |
質問
ジャイロを使用してARアプリを開発しています。 Apple Code Example Parkを使用しています。回転行列を使用して座標の位置を計算し、非常にうまく機能しますが、今では「レーダー」を実装しようとしているので、デバイスの見出しの関数でこれを回転させる必要があります。 CllocationManagerの見出しを使用していますが、それは正しくありません。
問題は、画面で取得したものを正確に反映するためにcmattitudeを使用してデバイスの見出しを取得するにはどうすればよいですか?
私はローテーションマトリックスとそのようなことで新しいです。
これは、AR座標の計算に使用されるコードの一部です。態度でcameratransformを更新します:
CMDeviceMotion *d = motionManager.deviceMotion;
if (d != nil) {
CMRotationMatrix r = d.attitude.rotationMatrix;
transformFromCMRotationMatrix(cameraTransform, &r);
[self setNeedsDisplay];
}
そして、DrawRectコードで:
mat4f_t projectionCameraTransform;
multiplyMatrixAndMatrix(projectionCameraTransform, projectionTransform, cameraTransform);
int i = 0;
for (PlaceOfInterest *poi in [placesOfInterest objectEnumerator]) {
vec4f_t v;
multiplyMatrixAndVector(v, projectionCameraTransform, placesOfInterestCoordinates[i]);
float x = (v[0] / v[3] + 1.0f) * 0.5f;
float y = (v[1] / v[3] + 1.0f) * 0.5f;
また、ピッチ角でビューを回転させます。モーションの更新は、北を使用して開始されます。
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical];
ですから、デバイスの「ロール」/見出しを任意の位置(任意のピッチとヨーを使用して)に入手するには可能だと思いますが、方法はわかりません。
解決
cmdevicemotionによって返される回転行列から見出しを計算する方法はいくつかあります。これは、Appleのコンパスの同じ定義を使用することを想定しています。ここで、Northが指す +Y方向(iPhoneの上部)が0の見出しを返し、iPhoneを右に回転させると見出しが増加します。 、など。
まず、更新を開始したら、必ず見出しが利用可能であることを確認してください。
if (([CMMotionManager availableAttitudeReferenceFrames] & CMAttitudeReferenceFrameXTrueNorthZVertical) != 0) {
...
}
次に、モーションマネージャーを開始するときは、Xからの態度をXから尋ねます。
[motionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXTrueNorthZVertical
toQueue: self.motionQueue
withHandler: dmHandler];
モーションマネージャーがモーションアップデートを報告したら、XYプレーンでデバイスがどれだけ回転したかを知りたいと思う。 iPhoneの上部に興味があるので、その方向のポイントを選択し、回転した回転マトリックスを使用して回転して回転後にポイントを取得します。
[m11 m12 m13] [0] [m12]
[m21 m22 m23] [1] = [m22]
[m31 m32 m33] [0] [m32]
ファンキーなブラケットはマトリックスです。 ASCIIを使用してできる最高のものです。 :)
見出しは、回転点と真の北の間の角度です。回転点のxおよびy座標を使用して、アークタンジェントを抽出することができます。これにより、ポイントとx軸の間に角度が得られます。これは実際には私たちが望むものから180度離れているので、それに応じて調整する必要があります。結果のコードは次のようになります:
CMDeviceMotionHandler dmHandler = ^(CMDeviceMotion *aMotion, NSError *error) {
// Check for an error.
if (error) {
// Add error handling here.
} else {
// Get the rotation matrix.
CMAttitude *attitude = self.motionManager.deviceMotion.attitude;
CMRotationMatrix rm = attitude.rotationMatrix;
// Get the heading.
double heading = PI + atan2(rm.m22, rm.m12);
heading = heading*180/PI;
printf("Heading: %5.0f\n", heading);
}
};
1つのゴッチャがあります。iPhoneの上部がまっすぐ上下またはまっすぐ下に向けられている場合、方向は未定義です。その結果、M21とM22はゼロ、または非常に近いことになります。これがアプリにとって何を意味するかを決定し、それに応じて条件を処理する必要があります。たとえば、M12*M12 + M22*M22がゼロに近い場合、-Z軸(iPhoneの後ろ)に基づいて見出しに切り替えることができます。
これはすべて、Appleが通常コンパスのために行っているように、XY平面を回転させたいと思っています。モーションマネージャーによって返された回転マトリックスを使用して、Y軸に沿って尖ったベクトルを回転させるために機能します。これは、このマトリックスです。
[0]
[1]
[0]
別のベクトルを回転させるために - say、1つはnに沿って尖っています-z-は別のマトリックスを使用します。
[0]
[0]
[-1]
もちろん、あなたはまた、別の平面でアークの接線を取る必要があるので、
double heading = PI + atan2(rm.m22, rm.m12);
使用します
double heading = PI + atan2(-rm.m33, -rm.m13);
XZ平面で回転を取得します。