Android 的 SensorManager.getRotation 是如何工作的(即数学)?
How does Android's SensorManager.getRotation work (i.e. the math)?
我大致了解它的用途 ("Computes the inclination matrix I as well as the rotation matrix R transforming a vector from the device coordinate system to the world's coordinate system"),但我不明白 它是如何工作的。
javadoc is well written and the source is available here但我不懂数学(例如,mathematica/physical是什么意思的值Hx,Hy和Hz ? 例如:Hx = Ey*Az - Ez*Ay
)。此外,该方法后面会发生什么。
我已经粘贴了上面 GrepCode link 中的代码,留下了源代码行号以便于参考。谢谢。
971 public static boolean More ...getRotationMatrix(float[] R, float[] I,
972 float[] gravity, float[] geomagnetic) {
973 // TODO: move this to native code for efficiency
974 float Ax = gravity[0];
975 float Ay = gravity[1];
976 float Az = gravity[2];
977 final float Ex = geomagnetic[0];
978 final float Ey = geomagnetic[1];
979 final float Ez = geomagnetic[2];
980 float Hx = Ey*Az - Ez*Ay;
981 float Hy = Ez*Ax - Ex*Az;
982 float Hz = Ex*Ay - Ey*Ax;
983 final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
984 if (normH < 0.1f) {
985 // device is close to free fall (or in space?), or close to
986 // magnetic north pole. Typical values are > 100.
987 return false;
988 }
989 final float invH = 1.0f / normH;
990 Hx *= invH;
991 Hy *= invH;
992 Hz *= invH;
993 final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
994 Ax *= invA;
995 Ay *= invA;
996 Az *= invA;
997 final float Mx = Ay*Hz - Az*Hy;
998 final float My = Az*Hx - Ax*Hz;
999 final float Mz = Ax*Hy - Ay*Hx;
1000 if (R != null) {
1001 if (R.length == 9) {
1002 R[0] = Hx; R[1] = Hy; R[2] = Hz;
1003 R[3] = Mx; R[4] = My; R[5] = Mz;
1004 R[6] = Ax; R[7] = Ay; R[8] = Az;
1005 } else if (R.length == 16) {
1006 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
1007 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
1008 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
1009 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
1010 }
1011 }
1012 if (I != null) {
1013 // compute the inclination matrix by projecting the geomagnetic
1014 // vector onto the Z (gravity) and X (horizontal component
1015 // of geomagnetic vector) axes.
1016 final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
1017 final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
1018 final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
1019 if (I.length == 9) {
1020 I[0] = 1; I[1] = 0; I[2] = 0;
1021 I[3] = 0; I[4] = c; I[5] = s;
1022 I[6] = 0; I[7] =-s; I[8] = c;
1023 } else if (I.length == 16) {
1024 I[0] = 1; I[1] = 0; I[2] = 0;
1025 I[4] = 0; I[5] = c; I[6] = s;
1026 I[8] = 0; I[9] =-s; I[10]= c;
1027 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
1028 I[15] = 1;
1029 }
1030 }
1031 return true;
1032 }
他们是cross product
。假设方法中传递的参数之一是 gravity
,因此是 Sky axis
。另一个假设是传入的 magnetic
参数位于 North-Sky
平面中。因此,这两个向量的 cross product
是与 North-Sky
平面正交的向量,即 East
。现在 Sky
和 East
的叉积是一个与这两个正交的向量,即 North
。将所有这些归一化将为 World coordinate
.
提供标准正交基础
在上面的计算中,H
是 East
而 M
是 North
.
我大致了解它的用途 ("Computes the inclination matrix I as well as the rotation matrix R transforming a vector from the device coordinate system to the world's coordinate system"),但我不明白 它是如何工作的。
javadoc is well written and the source is available here但我不懂数学(例如,mathematica/physical是什么意思的值Hx,Hy和Hz ? 例如:Hx = Ey*Az - Ez*Ay
)。此外,该方法后面会发生什么。
我已经粘贴了上面 GrepCode link 中的代码,留下了源代码行号以便于参考。谢谢。
971 public static boolean More ...getRotationMatrix(float[] R, float[] I,
972 float[] gravity, float[] geomagnetic) {
973 // TODO: move this to native code for efficiency
974 float Ax = gravity[0];
975 float Ay = gravity[1];
976 float Az = gravity[2];
977 final float Ex = geomagnetic[0];
978 final float Ey = geomagnetic[1];
979 final float Ez = geomagnetic[2];
980 float Hx = Ey*Az - Ez*Ay;
981 float Hy = Ez*Ax - Ex*Az;
982 float Hz = Ex*Ay - Ey*Ax;
983 final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
984 if (normH < 0.1f) {
985 // device is close to free fall (or in space?), or close to
986 // magnetic north pole. Typical values are > 100.
987 return false;
988 }
989 final float invH = 1.0f / normH;
990 Hx *= invH;
991 Hy *= invH;
992 Hz *= invH;
993 final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
994 Ax *= invA;
995 Ay *= invA;
996 Az *= invA;
997 final float Mx = Ay*Hz - Az*Hy;
998 final float My = Az*Hx - Ax*Hz;
999 final float Mz = Ax*Hy - Ay*Hx;
1000 if (R != null) {
1001 if (R.length == 9) {
1002 R[0] = Hx; R[1] = Hy; R[2] = Hz;
1003 R[3] = Mx; R[4] = My; R[5] = Mz;
1004 R[6] = Ax; R[7] = Ay; R[8] = Az;
1005 } else if (R.length == 16) {
1006 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
1007 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
1008 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
1009 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
1010 }
1011 }
1012 if (I != null) {
1013 // compute the inclination matrix by projecting the geomagnetic
1014 // vector onto the Z (gravity) and X (horizontal component
1015 // of geomagnetic vector) axes.
1016 final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
1017 final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
1018 final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
1019 if (I.length == 9) {
1020 I[0] = 1; I[1] = 0; I[2] = 0;
1021 I[3] = 0; I[4] = c; I[5] = s;
1022 I[6] = 0; I[7] =-s; I[8] = c;
1023 } else if (I.length == 16) {
1024 I[0] = 1; I[1] = 0; I[2] = 0;
1025 I[4] = 0; I[5] = c; I[6] = s;
1026 I[8] = 0; I[9] =-s; I[10]= c;
1027 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
1028 I[15] = 1;
1029 }
1030 }
1031 return true;
1032 }
他们是cross product
。假设方法中传递的参数之一是 gravity
,因此是 Sky axis
。另一个假设是传入的 magnetic
参数位于 North-Sky
平面中。因此,这两个向量的 cross product
是与 North-Sky
平面正交的向量,即 East
。现在 Sky
和 East
的叉积是一个与这两个正交的向量,即 North
。将所有这些归一化将为 World coordinate
.
提供标准正交基础
在上面的计算中,H
是 East
而 M
是 North
.