123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- /*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "SensorDevice.h"
- #include "SensorFusion.h"
- #include "SensorService.h"
- namespace android {
- // ---------------------------------------------------------------------------
- ANDROID_SINGLETON_STATIC_INSTANCE(SensorFusion)
- SensorFusion::SensorFusion()
- : mSensorDevice(SensorDevice::getInstance()),
- mEnabled(false), mGyroTime(0)
- {
- sensor_t const* list;
- Sensor uncalibratedGyro;
- ssize_t count = mSensorDevice.getSensorList(&list);
- if (count > 0) {
- for (size_t i=0 ; i<size_t(count) ; i++) {
- if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
- mAcc = Sensor(list + i);
- }
- if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
- mMag = Sensor(list + i);
- }
- if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
- mGyro = Sensor(list + i);
- }
- if (list[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
- uncalibratedGyro = Sensor(list + i);
- }
- }
- // Use the uncalibrated gyroscope for sensor fusion when available
- if (uncalibratedGyro.getType() == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
- mGyro = uncalibratedGyro;
- }
- // 200 Hz for gyro events is a good compromise between precision
- // and power/cpu usage.
- mEstimatedGyroRate = 200;
- mTargetDelayNs = 1000000000LL/mEstimatedGyroRate;
- mFusion.init();
- }
- }
- void SensorFusion::process(const sensors_event_t& event) {
- if (event.type == mGyro.getType()) {
- if (mGyroTime != 0) {
- const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
- mFusion.handleGyro(vec3_t(event.data), dT);
- // here we estimate the gyro rate (useful for debugging)
- const float freq = 1 / dT;
- if (freq >= 100 && freq<1000) { // filter values obviously wrong
- const float alpha = 1 / (1 + dT); // 1s time-constant
- mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha;
- }
- }
- mGyroTime = event.timestamp;
- } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
- const vec3_t mag(event.data);
- mFusion.handleMag(mag);
- } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
- const vec3_t acc(event.data);
- mFusion.handleAcc(acc);
- mAttitude = mFusion.getAttitude();
- }
- }
- template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
- template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
- status_t SensorFusion::activate(void* ident, bool enabled) {
- ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorFusion::activate(ident=%p, enabled=%d)",
- ident, enabled);
- const ssize_t idx = mClients.indexOf(ident);
- if (enabled) {
- if (idx < 0) {
- mClients.add(ident);
- }
- } else {
- if (idx >= 0) {
- mClients.removeItemsAt(idx);
- }
- }
- mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
- mSensorDevice.activate(ident, mMag.getHandle(), enabled);
- mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
- const bool newState = mClients.size() != 0;
- if (newState != mEnabled) {
- mEnabled = newState;
- if (newState) {
- mFusion.init();
- mGyroTime = 0;
- }
- }
- return NO_ERROR;
- }
- status_t SensorFusion::setDelay(void* ident, int64_t ns) {
- // Call batch with timeout zero instead of setDelay().
- mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
- mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
- mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
- return NO_ERROR;
- }
- float SensorFusion::getPowerUsage() const {
- float power = mAcc.getPowerUsage() +
- mMag.getPowerUsage() +
- mGyro.getPowerUsage();
- return power;
- }
- int32_t SensorFusion::getMinDelay() const {
- return mAcc.getMinDelay();
- }
- void SensorFusion::dump(String8& result) {
- const Fusion& fusion(mFusion);
- result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "
- "q=< %g, %g, %g, %g > (%g), "
- "b=< %g, %g, %g >\n",
- mEnabled ? "enabled" : "disabled",
- mClients.size(),
- mEstimatedGyroRate,
- fusion.getAttitude().x,
- fusion.getAttitude().y,
- fusion.getAttitude().z,
- fusion.getAttitude().w,
- length(fusion.getAttitude()),
- fusion.getBias().x,
- fusion.getBias().y,
- fusion.getBias().z);
- }
- // ---------------------------------------------------------------------------
- }; // namespace android
|