summaryrefslogtreecommitdiff
path: root/chromium/content/browser/device_orientation/accelerometer_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/device_orientation/accelerometer_mac.cc')
-rw-r--r--chromium/content/browser/device_orientation/accelerometer_mac.cc105
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