APIデモ->グラフィックス-> コンパス
デバイスの自然な向きを変更しない限り、正しく機能します。ほとんどの携帯電話では縦向きで、ほとんどの10インチタブレットは横向きです。変更する場合は、これを90度回転させる必要があります。そのシステムの3D修正を見たいのですが。
100%確実に使用する必要があります remapCoordinateSystem() メソッド。
それらの軸マッピング(理論数学)がどのように計算されるかについての説明を見ることができれば、どのように(コード)それが素晴らしいかを見たいと思います。
私は理解しようとしましたが、すべての線形代数を忘れました。
ここ なぜ使用しなければならないのかはわかりますが、方法はわかりません。
float R[] = new float[9];
// X (product of Y and Z) and roughly points East
// Y: points to Magnetic NORTH and tangential to ground
// Z: points to SKY and perpendicular to ground
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
これらの座標はこの位置にあるようです:-デバイスはテーブルで言います(x軸とy軸はテーブル上にあります)
のみ
getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_0
問題は、このコードをどのように完成させるかです:-それらのケースブランチ
switch (mScreenRotation) {
case Surface.ROTATION_0:
Log.v("SurfaceRemap", "0 degree");
axisX = SensorManager.AXIS_X;// is this valid?
axisY = SensorManager.AXIS_Y;// is this valid?
break;
case Surface.ROTATION_90:
Log.v("SurfaceRemap", "90 degree");
// examples says remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);
axisX = SensorManager.AXIS_Y;
axisY = SensorManager.AXIS_MINUS_X;
break;
case Surface.ROTATION_180:
Log.v("SurfaceRemap", "180 degree");
break;
case Surface.ROTATION_270:
Log.v("SurfaceRemap", "270 degree");
break;
default:
Log.v("SurfaceRemap", "don't know the mScreenRotation value: "+mScreenRotation+" you should never seen this message!");
break;
}
boolean remapped = SensorManager.remapCoordinateSystem(R, axisX, axisY, R);
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);// All three angles above are in radians and positive in the counter-clockwise direction.
inclination = SensorManager.getInclination(I);
編集:私は小さなテストアプリケーションを作成しました。画面上に画面の回転が表示されます:0、90、270度(現在180度にすることはできません)
回転0が変更されていない場合(axisX = SensorManager.AXIS_X;axisY = SensorManager.AXIS_Y;
)90度よりも次のようになります。
axisX = SensorManager.AXIS_MINUS_Y;
axisY = SensorManager.AXIS_X;
グーグルのドキュメントがどこか間違った値を言っているよりも!質問はどこですか?
getRotationMatrix これを返します:
Xは、ベクトル積Y.Zとして定義されます(デバイスの現在の位置で地面に接し、おおよそ東を指します)。
Yは、デバイスの現在の位置で地面に接しており、磁北極を指しています。
Zは空を指し、地面に垂直です。
上記の電話を参照してください!バックカメラを地面に向けて、左から右に行きたいです。
getOrientation これを返します:
Xは、ベクトル積Y.Zとして定義されます(デバイスの現在の位置で地面に接し、おおよそ西を指します)。
Yは、デバイスの現在の位置で地面に接しており、磁北極を指しています。
Zは地球の中心を指し、地面に垂直です。
values[0]
:方位角、Z軸を中心とした回転。
values[1]
:ピッチ、X軸を中心とした回転。
values[2]
:ロール、Y軸を中心とした回転。
電話はどうあるべきですか?
最後に、航空機のような角度の値が欲しいです。北に向かっている私の電話(私):(ヨーは方位角です)
if ScreenRotation = 0 degree
Pitch axis = -orientationAxisX = rotationAxisX
Roll axis = orientationAxisY = rotationAxisY
Yaw axis = orientationAxisZ = -rotationAxisZ
スイッチブランチを完了するには、remapCoordinateSystemメソッドjavadocに従って考えてみます。
[〜#〜] x [〜#〜]デバイスのX軸がマップされるワールド軸と方向を定義します。
[〜#〜] y [〜#〜]デバイスのY軸がマップされるワールド軸と方向を定義します。
したがって、デバイスを自然な方向(90、180、または270度)から回転させて、次のことを自問してください。元のデバイス方向のX正軸は、現在のデバイス方向でどの軸に対応しますか。そして、Y軸についても同じです。
したがって、デバイスを90度回転させると、元のXの正の軸が現在の正のY軸に対応し、元の正のY軸が現在の方向の負のX軸に対応することがわかります。
したがって、次のようになります。
switch (mScreenRotation) {
case Surface.ROTATION_0:
axisX = SensorManager.AXIS_X;
axisY = SensorManager.AXIS_Y;
break;
case Surface.ROTATION_90:
axisX = SensorManager.AXIS_Y;
axisY = SensorManager.AXIS_MINUS_X;
break;
case Surface.ROTATION_180:
axisX = SensorManager.AXIS_MINUS_X;
axisY = SensorManager.AXIS_MINUS_Y;
break;
case Surface.ROTATION_270:
axisX = SensorManager.AXIS_MINUS_Y;
axisY = SensorManager.AXIS_X;
break;
default:
break;
}
それは私のために働いた、それが役立つことを願っています。
Keianhzoに感謝します、あなたの答えは地面に平らな電話でうまくいきます。ディスプレイを「透視」するARアプリケーションの場合、これが機能することがわかりました。適切な軸を使用してください。
int screenRotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
//use the correct axis
int axisX = SensorManager.AXIS_X;
int axisY = SensorManager.AXIS_Y;
switch (mMode) {
case LOOK_THROUGH: {
// look through always uses x and z
axisX = SensorManager.AXIS_X;
axisY = SensorManager.AXIS_Z;
break;
}
case FLAT: {
// flat changes the x axis depending on rotation state
switch (screenRotation) {
case Surface.ROTATION_0:
axisX = SensorManager.AXIS_X;
axisY = SensorManager.AXIS_Y;
break;
case Surface.ROTATION_90:
axisX = SensorManager.AXIS_Y;
axisY = SensorManager.AXIS_MINUS_X;
break;
case Surface.ROTATION_180:
axisX = SensorManager.AXIS_MINUS_X;
axisY = SensorManager.AXIS_MINUS_Y;
break;
case Surface.ROTATION_270:
axisX = SensorManager.AXIS_MINUS_Y;
axisY = SensorManager.AXIS_X;
break;
default:
break;
}
break;
}
default:
break;
}
方向度を取得します。
boolean success = SensorManager.remapCoordinateSystem(getQuaternion().getMatrix4x4().getMatrix(), axisX, axisY, mRotationMatrixTransformed);
if (success) {
SensorManager.getOrientation(mRotationMatrixTransformed, mOrientationValues);
for (int i = 0; i < 3; i++) {
mOrientationDegrees[i] = (float) Math.toDegrees(mOrientationValues[i]);
}
//And for look through, add the rotation state
if (mMode == MODE.LOOK_THROUGH) {
// look through has different angles depending on rotation state
switch (screenRotation) {
case Surface.ROTATION_90: {
mOrientationDegrees[2] += 90;
break;
}
case Surface.ROTATION_180: {
mOrientationDegrees[2] += 180;
break;
}
case Surface.ROTATION_270: {
mOrientationDegrees[2] += 270;
break;
}
}
}
これが私のアプリケーションで魔法を使う方法です:
float[] rotationMatrixOrig = new float[9];
SensorManager.getRotationMatrix(rotationMatrixOrig, null, lastAccelerometerValue, lastMagnetometerValue);
int screenRotation = app.getCurrentActivity().getWindowManager().getDefaultDisplay().getRotation();
int axisX, axisY;
boolean isUpSideDown = lastAccelerometerValue[2] < 0;
switch (screenRotation) {
case Surface.ROTATION_0:
axisX = (isUpSideDown ? SensorManager.AXIS_MINUS_X : SensorManager.AXIS_X);
axisY = (Math.abs(lastAccelerometerValue[1]) > 6.0f ?
(isUpSideDown ? SensorManager.AXIS_MINUS_Z : SensorManager.AXIS_Z) :
(isUpSideDown ? SensorManager.AXIS_MINUS_Y : SensorManager.AXIS_Y));
break;
case Surface.ROTATION_90:
axisX = (isUpSideDown ? SensorManager.AXIS_MINUS_Y : SensorManager.AXIS_Y);
axisY = (Math.abs(lastAccelerometerValue[0]) > 6.0f ?
(isUpSideDown ? SensorManager.AXIS_Z : SensorManager.AXIS_MINUS_Z) :
(isUpSideDown ? SensorManager.AXIS_X : SensorManager.AXIS_MINUS_X));
break;
case Surface.ROTATION_180:
axisX = (isUpSideDown ? SensorManager.AXIS_X : SensorManager.AXIS_MINUS_X);
axisY = (Math.abs(lastAccelerometerValue[1]) > 6.0f ?
(isUpSideDown ? SensorManager.AXIS_Z : SensorManager.AXIS_MINUS_Z) :
(isUpSideDown ? SensorManager.AXIS_Y : SensorManager.AXIS_MINUS_Y));
break;
case Surface.ROTATION_270:
axisX = (isUpSideDown ? SensorManager.AXIS_Y : SensorManager.AXIS_MINUS_Y);
axisY = (Math.abs(lastAccelerometerValue[0]) > 6.0f ?
(isUpSideDown ? SensorManager.AXIS_MINUS_Z : SensorManager.AXIS_Z) :
(isUpSideDown ? SensorManager.AXIS_MINUS_X : SensorManager.AXIS_X));
break;
default:
axisX = (isUpSideDown ? SensorManager.AXIS_MINUS_X : SensorManager.AXIS_X);
axisY = (isUpSideDown ? SensorManager.AXIS_MINUS_Y : SensorManager.AXIS_Y);
}
float[] rotationMatrix = new float[9];
SensorManager.remapCoordinateSystem(rotationMatrixOrig, axisX, axisY, rotationMatrix);
電話UIが回転0にロックされている場合、次の値をなしで取得していますremapCoordinateSystem()
Pitch (phone) = -Pitch (API)
Roll (phone) = Roll (API)
Yaw (phone) = Azimuth (API)
電話UIが強制的に回転90された場合:
ヨー値は古い方向で-90度(-PI/2)です!!! =>私は実際には北ではなく東に行きます。
電話を0,0,0の位置に持っていくと:
Pitch (phone) = -Roll (API)
Roll (phone) = -Pitch (API)
Yaw (phone) = Azimuth (API)
電話UIが180回転を強制された場合:
ヨー値は古い方向で+/- 180度(+/- PI)です!!! =>私は実際には北ではなく南に行きます。
電話を0,0,0の位置に持っていくと:
Pitch (phone) = Pitch (API)
Roll (phone) = -Roll (API)
Yaw (phone) = Azimuth (API)
電話UIが強制的に回転270の場合:
ヨー値は古い方向で+90度(+ PI/2)です!!! =>私は実際には北ではなく西に行きます。
電話を0,0,0の位置に持っていくと:
Pitch (phone) = Roll (API)
Roll (phone) = Pitch (API)
Yaw (phone) = Azimuth (API)
私は少し修正を書き、次のようにテストしました:Android:screenOrientation="fullSensor"
public static final void fixRotation0(float[] orientation) { //azimuth, pitch, roll
orientation[1] = -orientation[1]; // pitch = -pitch
}
public static final void fixRotation90(float[] orientation) { //azimuth, pitch, roll
orientation[0] += Math.PI / 2f; // offset
float tmpOldPitch = orientation[1];
orientation[1] = -orientation[2]; //pitch = -roll
orientation[2] = -tmpOldPitch; // roll = -pitch
}
public static final void fixRotation180(float[] orientation) { //azimuth, pitch, roll
orientation[0] = (float)(orientation[0] > 0f ? (orientation[0] - Math.PI) : (orientation[0] + Math.PI)); // offset
orientation[2] = -orientation[2]; // roll = -roll
}
public static final void fixRotation270(float[] orientation) { //azimuth, pitch, roll
orientation[0] -= Math.PI / 2; // offset
float tmpOldPitch = orientation[1];
orientation[1] = orientation[2]; //pitch = roll
orientation[2] = tmpOldPitch; // roll = pitch
}
ほとんどの場合、機能しています。 1軸を中心に180度すばやく回転すると、システムがねじ込まれます。
利用可能な完全なコード Githubで