sensors.dart 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import 'dart:math';
  2. const int AXIS_X = 1;
  3. const int AXIS_Y = 2;
  4. const int AXIS_Z = 3;
  5. const int AXIS_MINUS_X = AXIS_X | 0x80;
  6. const int AXIS_MINUS_Y = AXIS_Y | 0x80;
  7. const int AXIS_MINUS_Z = AXIS_Z | 0x80;
  8. List<double> getOrientation(List<double> R) {
  9. List<double> values = List.filled(3, 0);
  10. if (R.length == 9) {
  11. values[0] = atan2(R[1], R[4]);
  12. values[1] = asin(-R[7]);
  13. values[2] = atan2(-R[6], R[8]);
  14. } else {
  15. values[0] = atan2(R[1], R[5]);
  16. values[1] = asin(-R[9]);
  17. values[2] = atan2(-R[8], R[10]);
  18. }
  19. return values;
  20. }
  21. bool getRotationMatrix(List<double> R, List<double> I, List<double> gravity, List<double> geomagnetic) {
  22. double Ax = gravity[0];
  23. double Ay = gravity[1];
  24. double Az = gravity[2];
  25. final double normsqA = (Ax * Ax + Ay * Ay + Az * Az);
  26. final double g = 9.81;
  27. final double freeFallGravitySquared = 0.01 * g * g;
  28. if (normsqA < freeFallGravitySquared) {
  29. // gravity less than 10% of normal value
  30. return false;
  31. }
  32. final double Ex = geomagnetic[0];
  33. final double Ey = geomagnetic[1];
  34. final double Ez = geomagnetic[2];
  35. double Hx = Ey * Az - Ez * Ay;
  36. double Hy = Ez * Ax - Ex * Az;
  37. double Hz = Ex * Ay - Ey * Ax;
  38. final double normH = sqrt(Hx * Hx + Hy * Hy + Hz * Hz);
  39. if (normH < 0.1) {
  40. // device is close to free fall (or in space?), or close to
  41. // magnetic north pole. Typical values are > 100.
  42. return false;
  43. }
  44. final double invH = 1.0 / normH;
  45. Hx *= invH;
  46. Hy *= invH;
  47. Hz *= invH;
  48. final double invA = 1.0 / sqrt(Ax * Ax + Ay * Ay + Az * Az);
  49. Ax *= invA;
  50. Ay *= invA;
  51. Az *= invA;
  52. final double Mx = Ay * Hz - Az * Hy;
  53. final double My = Az * Hx - Ax * Hz;
  54. final double Mz = Ax * Hy - Ay * Hx;
  55. if (R != null) {
  56. if (R.length == 9) {
  57. R[0] = Hx;
  58. R[1] = Hy;
  59. R[2] = Hz;
  60. R[3] = Mx;
  61. R[4] = My;
  62. R[5] = Mz;
  63. R[6] = Ax;
  64. R[7] = Ay;
  65. R[8] = Az;
  66. } else if (R.length == 16) {
  67. R[0] = Hx;
  68. R[1] = Hy;
  69. R[2] = Hz;
  70. R[3] = 0;
  71. R[4] = Mx;
  72. R[5] = My;
  73. R[6] = Mz;
  74. R[7] = 0;
  75. R[8] = Ax;
  76. R[9] = Ay;
  77. R[10] = Az;
  78. R[11] = 0;
  79. R[12] = 0;
  80. R[13] = 0;
  81. R[14] = 0;
  82. R[15] = 1;
  83. }
  84. }
  85. if (I != null) {
  86. // compute the inclination matrix by projecting the geomagnetic
  87. // vector onto the Z (gravity) and X (horizontal component
  88. // of geomagnetic vector) axes.
  89. final double invE = 1.0 / sqrt(Ex * Ex + Ey * Ey + Ez * Ez);
  90. final double c = (Ex * Mx + Ey * My + Ez * Mz) * invE;
  91. final double s = (Ex * Ax + Ey * Ay + Ez * Az) * invE;
  92. if (I.length == 9) {
  93. I[0] = 1;
  94. I[1] = 0;
  95. I[2] = 0;
  96. I[3] = 0;
  97. I[4] = c;
  98. I[5] = s;
  99. I[6] = 0;
  100. I[7] = -s;
  101. I[8] = c;
  102. } else if (I.length == 16) {
  103. I[0] = 1;
  104. I[1] = 0;
  105. I[2] = 0;
  106. I[4] = 0;
  107. I[5] = c;
  108. I[6] = s;
  109. I[8] = 0;
  110. I[9] = -s;
  111. I[10] = c;
  112. I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
  113. I[15] = 1;
  114. }
  115. }
  116. return true;
  117. }
  118. bool remapCoordinateSystem(List<double> inR, int X, int Y, List<double> outR) {
  119. if (inR == outR) {
  120. final List<double> temp = List.filled(16, 0.0);
  121. // we don't expect to have a lot of contention
  122. if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
  123. final int size = outR.length;
  124. for (int i = 0; i < size; i++) {
  125. outR[i] = temp[i];
  126. }
  127. return true;
  128. }
  129. }
  130. return remapCoordinateSystemImpl(inR, X, Y, outR);
  131. }
  132. bool remapCoordinateSystemImpl(List<double> inR, int X, int Y, List<double> outR) {
  133. /*
  134. * X and Y define a rotation matrix 'r':
  135. *
  136. * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0
  137. * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0
  138. * r[0] ^ r[1]
  139. *
  140. * where the 3rd line is the vector product of the first 2 lines
  141. *
  142. */
  143. final int length = outR.length;
  144. if (inR.length != length) {
  145. return false; // invalid parameter
  146. }
  147. if ((X & 0x7C) != 0 || (Y & 0x7C) != 0) {
  148. return false; // invalid parameter
  149. }
  150. if (((X & 0x3) == 0) || ((Y & 0x3) == 0)) {
  151. return false; // no axis specified
  152. }
  153. if ((X & 0x3) == (Y & 0x3)) {
  154. return false; // same axis specified
  155. }
  156. // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
  157. // this can be calculated by exclusive-or'ing X and Y; except for
  158. // the sign inversion (+/-) which is calculated below.
  159. int Z = X ^ Y;
  160. // extract the axis (remove the sign), offset in the range 0 to 2.
  161. final int x = (X & 0x3) - 1;
  162. final int y = (Y & 0x3) - 1;
  163. final int z = (Z & 0x3) - 1;
  164. // compute the sign of Z (whether it needs to be inverted)
  165. final int axis_y = (z + 1) % 3;
  166. final int axis_z = (z + 2) % 3;
  167. if (((x ^ axis_y) | (y ^ axis_z)) != 0) {
  168. Z ^= 0x80;
  169. }
  170. final bool sx = (X >= 0x80);
  171. final bool sy = (Y >= 0x80);
  172. final bool sz = (Z >= 0x80);
  173. // Perform R * r, in avoiding actual muls and adds.
  174. final int rowLength = ((length == 16) ? 4 : 3);
  175. for (int j = 0; j < 3; j++) {
  176. final int offset = j * rowLength;
  177. for (int i = 0; i < 3; i++) {
  178. if (x == i) outR[offset + i] = sx ? -inR[offset + 0] : inR[offset + 0];
  179. if (y == i) outR[offset + i] = sy ? -inR[offset + 1] : inR[offset + 1];
  180. if (z == i) outR[offset + i] = sz ? -inR[offset + 2] : inR[offset + 2];
  181. }
  182. }
  183. if (length == 16) {
  184. outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
  185. outR[15] = 1;
  186. }
  187. return true;
  188. }