SensorFusion.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "SensorDevice.h"
  17. #include "SensorFusion.h"
  18. #include "SensorService.h"
  19. namespace android {
  20. // ---------------------------------------------------------------------------
  21. ANDROID_SINGLETON_STATIC_INSTANCE(SensorFusion)
  22. SensorFusion::SensorFusion()
  23. : mSensorDevice(SensorDevice::getInstance()),
  24. mEnabled(false), mGyroTime(0)
  25. {
  26. sensor_t const* list;
  27. Sensor uncalibratedGyro;
  28. ssize_t count = mSensorDevice.getSensorList(&list);
  29. if (count > 0) {
  30. for (size_t i=0 ; i<size_t(count) ; i++) {
  31. if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
  32. mAcc = Sensor(list + i);
  33. }
  34. if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
  35. mMag = Sensor(list + i);
  36. }
  37. if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
  38. mGyro = Sensor(list + i);
  39. }
  40. if (list[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
  41. uncalibratedGyro = Sensor(list + i);
  42. }
  43. }
  44. // Use the uncalibrated gyroscope for sensor fusion when available
  45. if (uncalibratedGyro.getType() == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
  46. mGyro = uncalibratedGyro;
  47. }
  48. // 200 Hz for gyro events is a good compromise between precision
  49. // and power/cpu usage.
  50. mEstimatedGyroRate = 200;
  51. mTargetDelayNs = 1000000000LL/mEstimatedGyroRate;
  52. mFusion.init();
  53. }
  54. }
  55. void SensorFusion::process(const sensors_event_t& event) {
  56. if (event.type == mGyro.getType()) {
  57. if (mGyroTime != 0) {
  58. const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
  59. mFusion.handleGyro(vec3_t(event.data), dT);
  60. // here we estimate the gyro rate (useful for debugging)
  61. const float freq = 1 / dT;
  62. if (freq >= 100 && freq<1000) { // filter values obviously wrong
  63. const float alpha = 1 / (1 + dT); // 1s time-constant
  64. mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha;
  65. }
  66. }
  67. mGyroTime = event.timestamp;
  68. } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
  69. const vec3_t mag(event.data);
  70. mFusion.handleMag(mag);
  71. } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
  72. const vec3_t acc(event.data);
  73. mFusion.handleAcc(acc);
  74. mAttitude = mFusion.getAttitude();
  75. }
  76. }
  77. template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
  78. template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
  79. status_t SensorFusion::activate(void* ident, bool enabled) {
  80. ALOGD_IF(DEBUG_CONNECTIONS,
  81. "SensorFusion::activate(ident=%p, enabled=%d)",
  82. ident, enabled);
  83. const ssize_t idx = mClients.indexOf(ident);
  84. if (enabled) {
  85. if (idx < 0) {
  86. mClients.add(ident);
  87. }
  88. } else {
  89. if (idx >= 0) {
  90. mClients.removeItemsAt(idx);
  91. }
  92. }
  93. mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
  94. mSensorDevice.activate(ident, mMag.getHandle(), enabled);
  95. mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
  96. const bool newState = mClients.size() != 0;
  97. if (newState != mEnabled) {
  98. mEnabled = newState;
  99. if (newState) {
  100. mFusion.init();
  101. mGyroTime = 0;
  102. }
  103. }
  104. return NO_ERROR;
  105. }
  106. status_t SensorFusion::setDelay(void* ident, int64_t ns) {
  107. // Call batch with timeout zero instead of setDelay().
  108. mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
  109. mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
  110. mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
  111. return NO_ERROR;
  112. }
  113. float SensorFusion::getPowerUsage() const {
  114. float power = mAcc.getPowerUsage() +
  115. mMag.getPowerUsage() +
  116. mGyro.getPowerUsage();
  117. return power;
  118. }
  119. int32_t SensorFusion::getMinDelay() const {
  120. return mAcc.getMinDelay();
  121. }
  122. void SensorFusion::dump(String8& result) {
  123. const Fusion& fusion(mFusion);
  124. result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "
  125. "q=< %g, %g, %g, %g > (%g), "
  126. "b=< %g, %g, %g >\n",
  127. mEnabled ? "enabled" : "disabled",
  128. mClients.size(),
  129. mEstimatedGyroRate,
  130. fusion.getAttitude().x,
  131. fusion.getAttitude().y,
  132. fusion.getAttitude().z,
  133. fusion.getAttitude().w,
  134. length(fusion.getAttitude()),
  135. fusion.getBias().x,
  136. fusion.getBias().y,
  137. fusion.getBias().z);
  138. }
  139. // ---------------------------------------------------------------------------
  140. }; // namespace android