1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "data_fetcher_shared_memory.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
13 const double kMeanGravity
= 9.80665;
15 void FetchMotion(SuddenMotionSensor
* sensor
,
16 content::DeviceMotionHardwareBuffer
* buffer
) {
20 if (!sensor
->ReadSensorValues(axis_value
))
23 buffer
->seqlock
.WriteBegin();
24 buffer
->data
.accelerationIncludingGravityX
= axis_value
[0] * kMeanGravity
;
25 buffer
->data
.hasAccelerationIncludingGravityX
= true;
26 buffer
->data
.accelerationIncludingGravityY
= axis_value
[1] * kMeanGravity
;
27 buffer
->data
.hasAccelerationIncludingGravityY
= true;
28 buffer
->data
.accelerationIncludingGravityZ
= axis_value
[2] * kMeanGravity
;
29 buffer
->data
.hasAccelerationIncludingGravityZ
= true;
30 buffer
->data
.allAvailableSensorsAreActive
= true;
31 buffer
->seqlock
.WriteEnd();
34 void FetchOrientation(SuddenMotionSensor
* sensor
,
35 content::DeviceOrientationHardwareBuffer
* buffer
) {
38 // Retrieve per-axis calibrated values.
40 if (!sensor
->ReadSensorValues(axis_value
))
43 // Transform the accelerometer values to W3C draft angles.
45 // Accelerometer values are just dot products of the sensor axes
46 // by the gravity vector 'g' with the result for the z axis inverted.
48 // To understand this transformation calculate the 3rd row of the z-x-y
49 // Euler angles rotation matrix (because of the 'g' vector, only 3rd row
50 // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz.
51 // Then, assume alpha = 0 and you get this:
54 // y_acc = - cos(gamma) * sin(beta)
55 // z_acc = cos(beta) * cos(gamma)
57 // After that the rest is just a bit of trigonometry.
59 // Also note that alpha can't be provided but it's assumed to be always zero.
60 // This is necessary in order to provide enough information to solve
63 const double kRad2deg
= 180.0 / M_PI
;
64 double beta
= kRad2deg
* atan2(-axis_value
[1], axis_value
[2]);
65 double gamma
= kRad2deg
* asin(axis_value
[0]);
67 // TODO(aousterh): should absolute_ be set to false here?
68 // See crbug.com/136010.
70 // Make sure that the interval boundaries comply with the specification. At
71 // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has
72 // the upper bound open on both.
74 beta
= -180; // -180 == 180 (upside-down)
76 gamma
= nextafter(90, 0);
78 // At this point, DCHECKing is paranoia. Never hurts.
79 DCHECK_GE(beta
, -180.0);
80 DCHECK_LT(beta
, 180.0);
81 DCHECK_GE(gamma
, -90.0);
82 DCHECK_LT(gamma
, 90.0);
84 buffer
->seqlock
.WriteBegin();
85 buffer
->data
.beta
= beta
;
86 buffer
->data
.hasBeta
= true;
87 buffer
->data
.gamma
= gamma
;
88 buffer
->data
.hasGamma
= true;
89 buffer
->data
.allAvailableSensorsAreActive
= true;
90 buffer
->seqlock
.WriteEnd();
97 DataFetcherSharedMemory::DataFetcherSharedMemory() {
100 DataFetcherSharedMemory::~DataFetcherSharedMemory() {
103 void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask
) {
104 DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
105 DCHECK(sudden_motion_sensor_
);
106 DCHECK(consumer_bitmask
& CONSUMER_TYPE_ORIENTATION
||
107 consumer_bitmask
& CONSUMER_TYPE_MOTION
);
109 if (consumer_bitmask
& CONSUMER_TYPE_ORIENTATION
)
110 FetchOrientation(sudden_motion_sensor_
.get(), orientation_buffer_
);
111 if (consumer_bitmask
& CONSUMER_TYPE_MOTION
)
112 FetchMotion(sudden_motion_sensor_
.get(), motion_buffer_
);
115 DataFetcherSharedMemory::FetcherType
DataFetcherSharedMemory::GetType() const {
116 return FETCHER_TYPE_POLLING_CALLBACK
;
119 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type
, void* buffer
) {
120 DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
123 switch (consumer_type
) {
124 case CONSUMER_TYPE_MOTION
:
125 motion_buffer_
= static_cast<DeviceMotionHardwareBuffer
*>(buffer
);
126 if (!sudden_motion_sensor_
)
127 sudden_motion_sensor_
.reset(SuddenMotionSensor::Create());
128 UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable",
129 sudden_motion_sensor_
.get() != NULL
);
130 return sudden_motion_sensor_
.get() != NULL
;
131 case CONSUMER_TYPE_ORIENTATION
:
132 orientation_buffer_
=
133 static_cast<DeviceOrientationHardwareBuffer
*>(buffer
);
134 if (!sudden_motion_sensor_
)
135 sudden_motion_sensor_
.reset(SuddenMotionSensor::Create());
136 UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable",
137 sudden_motion_sensor_
.get() != NULL
);
138 return sudden_motion_sensor_
.get() != NULL
;
145 bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type
) {
146 DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
148 switch (consumer_type
) {
149 case CONSUMER_TYPE_MOTION
:
150 if (motion_buffer_
) {
151 motion_buffer_
->seqlock
.WriteBegin();
152 motion_buffer_
->data
.allAvailableSensorsAreActive
= false;
153 motion_buffer_
->seqlock
.WriteEnd();
154 motion_buffer_
= NULL
;
157 case CONSUMER_TYPE_ORIENTATION
:
158 if (orientation_buffer_
) {
159 orientation_buffer_
->seqlock
.WriteBegin();
160 orientation_buffer_
->data
.allAvailableSensorsAreActive
= false;
161 orientation_buffer_
->seqlock
.WriteEnd();
162 orientation_buffer_
= NULL
;
171 } // namespace content