diff options
Diffstat (limited to 'chromium/content/browser/device_orientation/accelerometer_mac.cc')
-rw-r--r-- | chromium/content/browser/device_orientation/accelerometer_mac.cc | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/chromium/content/browser/device_orientation/accelerometer_mac.cc b/chromium/content/browser/device_orientation/accelerometer_mac.cc new file mode 100644 index 00000000000..04c5d71b65c --- /dev/null +++ b/chromium/content/browser/device_orientation/accelerometer_mac.cc @@ -0,0 +1,105 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/device_orientation/accelerometer_mac.h" + +#include <math.h> + +#include "base/logging.h" +#include "content/browser/device_orientation/orientation.h" +#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" + +namespace content { + +// Create a AccelerometerMac object and return NULL if no valid sensor found. +DataFetcher* AccelerometerMac::Create() { + scoped_ptr<AccelerometerMac> accelerometer(new AccelerometerMac); + return accelerometer->Init() ? accelerometer.release() : NULL; +} + +AccelerometerMac::~AccelerometerMac() { +} + +AccelerometerMac::AccelerometerMac() { +} + +const DeviceData* AccelerometerMac::GetDeviceData(DeviceData::Type type) { + if (type != DeviceData::kTypeOrientation) + return NULL; + return GetOrientation(); +} + +// Retrieve per-axis orientation values. +// +// Axes and angles are defined according to the W3C DeviceOrientation Draft. +// See here: http://dev.w3.org/geo/api/spec-source-orientation.html +// +// Note: only beta and gamma angles are provided. Alpha is set to zero. +// +// Returns false in case of error. +// +const Orientation* AccelerometerMac::GetOrientation() { + DCHECK(sudden_motion_sensor_.get()); + + // Retrieve per-axis calibrated values. + float axis_value[3]; + if (!sudden_motion_sensor_->ReadSensorValues(axis_value)) + return NULL; + + // Transform the accelerometer values to W3C draft angles. + // + // Accelerometer values are just dot products of the sensor axes + // by the gravity vector 'g' with the result for the z axis inverted. + // + // To understand this transformation calculate the 3rd row of the z-x-y + // Euler angles rotation matrix (because of the 'g' vector, only 3rd row + // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz. + // Then, assume alpha = 0 and you get this: + // + // x_acc = sin(gamma) + // y_acc = - cos(gamma) * sin(beta) + // z_acc = cos(beta) * cos(gamma) + // + // After that the rest is just a bit of trigonometry. + // + // Also note that alpha can't be provided but it's assumed to be always zero. + // This is necessary in order to provide enough information to solve + // the equations. + // + const double kRad2deg = 180.0 / M_PI; + + scoped_refptr<Orientation> orientation(new Orientation()); + + orientation->set_beta(kRad2deg * atan2(-axis_value[1], axis_value[2])); + orientation->set_gamma(kRad2deg * asin(axis_value[0])); + // TODO(aousterh): should absolute_ be set to false here? + // See crbug.com/136010. + + // Make sure that the interval boundaries comply with the specification. At + // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has + // the upper bound open on both. + if (orientation->beta() == 180.0) { + orientation->set_beta(-180.0); // -180 == 180 (upside-down) + } + if (orientation->gamma() == 90.0) { + static double just_less_than_90 = nextafter(90, 0); + orientation->set_gamma(just_less_than_90); + } + + // At this point, DCHECKing is paranoia. Never hurts. + DCHECK_GE(orientation->beta(), -180.0); + DCHECK_LT(orientation->beta(), 180.0); + DCHECK_GE(orientation->gamma(), -90.0); + DCHECK_LT(orientation->gamma(), 90.0); + + orientation->AddRef(); + return orientation.get(); +} + +bool AccelerometerMac::Init() { + sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); + return sudden_motion_sensor_.get() != NULL; +} + +} // namespace content |