OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "data_fetcher_shared_memory.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/metrics/histogram.h" | |
9 #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" | |
10 | |
11 namespace { | |
12 | |
13 const double kMeanGravity = 9.80665; | |
14 | |
15 void FetchMotion(SuddenMotionSensor* sensor, | |
16 content::DeviceMotionHardwareBuffer* buffer) { | |
17 DCHECK(buffer); | |
18 | |
19 float axis_value[3]; | |
20 if (!sensor->ReadSensorValues(axis_value)) | |
21 return; | |
22 | |
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(); | |
32 } | |
33 | |
34 void FetchOrientation(SuddenMotionSensor* sensor, | |
35 content::DeviceOrientationHardwareBuffer* buffer) { | |
36 DCHECK(buffer); | |
37 | |
38 // Retrieve per-axis calibrated values. | |
39 float axis_value[3]; | |
40 if (!sensor->ReadSensorValues(axis_value)) | |
41 return; | |
42 | |
43 // Transform the accelerometer values to W3C draft angles. | |
44 // | |
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. | |
47 // | |
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: | |
52 // | |
53 // x_acc = sin(gamma) | |
54 // y_acc = - cos(gamma) * sin(beta) | |
55 // z_acc = cos(beta) * cos(gamma) | |
56 // | |
57 // After that the rest is just a bit of trigonometry. | |
58 // | |
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 | |
61 // the equations. | |
62 // | |
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]); | |
66 | |
67 // Make sure that the interval boundaries comply with the specification. At | |
68 // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has | |
69 // the upper bound open on both. | |
70 if (beta == 180.0) | |
71 beta = -180; // -180 == 180 (upside-down) | |
72 if (gamma == 90.0) | |
73 gamma = nextafter(90, 0); | |
74 | |
75 // At this point, DCHECKing is paranoia. Never hurts. | |
76 DCHECK_GE(beta, -180.0); | |
77 DCHECK_LT(beta, 180.0); | |
78 DCHECK_GE(gamma, -90.0); | |
79 DCHECK_LT(gamma, 90.0); | |
80 | |
81 buffer->seqlock.WriteBegin(); | |
82 buffer->data.beta = beta; | |
83 buffer->data.hasBeta = true; | |
84 buffer->data.gamma = gamma; | |
85 buffer->data.hasGamma = true; | |
86 buffer->data.allAvailableSensorsAreActive = true; | |
87 buffer->seqlock.WriteEnd(); | |
88 } | |
89 | |
90 } // namespace | |
91 | |
92 namespace content { | |
93 | |
94 DataFetcherSharedMemory::DataFetcherSharedMemory() { | |
95 } | |
96 | |
97 DataFetcherSharedMemory::~DataFetcherSharedMemory() { | |
98 } | |
99 | |
100 void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) { | |
101 DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); | |
102 DCHECK(sudden_motion_sensor_); | |
103 DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || | |
104 consumer_bitmask & CONSUMER_TYPE_MOTION); | |
105 | |
106 if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION) | |
107 FetchOrientation(sudden_motion_sensor_.get(), orientation_buffer_); | |
108 if (consumer_bitmask & CONSUMER_TYPE_MOTION) | |
109 FetchMotion(sudden_motion_sensor_.get(), motion_buffer_); | |
110 } | |
111 | |
112 DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const { | |
113 return FETCHER_TYPE_POLLING_CALLBACK; | |
114 } | |
115 | |
116 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { | |
117 DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); | |
118 DCHECK(buffer); | |
119 | |
120 if (!sudden_motion_sensor_) | |
121 sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); | |
122 bool sudden_motion_sensor_available = sudden_motion_sensor_.get() != NULL; | |
123 | |
124 switch (consumer_type) { | |
125 case CONSUMER_TYPE_MOTION: | |
126 motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer); | |
127 UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable", | |
128 sudden_motion_sensor_available); | |
129 if (!sudden_motion_sensor_available) { | |
130 // No motion sensor available, fire an all-null event. | |
131 motion_buffer_->seqlock.WriteBegin(); | |
132 motion_buffer_->data.allAvailableSensorsAreActive = true; | |
133 motion_buffer_->seqlock.WriteEnd(); | |
134 } | |
135 return sudden_motion_sensor_available; | |
136 case CONSUMER_TYPE_ORIENTATION: | |
137 orientation_buffer_ = | |
138 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
139 UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable", | |
140 sudden_motion_sensor_available); | |
141 if (sudden_motion_sensor_available) { | |
142 // On Mac we cannot provide absolute orientation. | |
143 orientation_buffer_->seqlock.WriteBegin(); | |
144 orientation_buffer_->data.absolute = false; | |
145 orientation_buffer_->data.hasAbsolute = true; | |
146 orientation_buffer_->seqlock.WriteEnd(); | |
147 } else { | |
148 // No motion sensor available, fire an all-null event. | |
149 orientation_buffer_->seqlock.WriteBegin(); | |
150 orientation_buffer_->data.allAvailableSensorsAreActive = true; | |
151 orientation_buffer_->seqlock.WriteEnd(); | |
152 } | |
153 return sudden_motion_sensor_available; | |
154 default: | |
155 NOTREACHED(); | |
156 } | |
157 return false; | |
158 } | |
159 | |
160 bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { | |
161 DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); | |
162 | |
163 switch (consumer_type) { | |
164 case CONSUMER_TYPE_MOTION: | |
165 if (motion_buffer_) { | |
166 motion_buffer_->seqlock.WriteBegin(); | |
167 motion_buffer_->data.allAvailableSensorsAreActive = false; | |
168 motion_buffer_->seqlock.WriteEnd(); | |
169 motion_buffer_ = NULL; | |
170 } | |
171 return true; | |
172 case CONSUMER_TYPE_ORIENTATION: | |
173 if (orientation_buffer_) { | |
174 orientation_buffer_->seqlock.WriteBegin(); | |
175 orientation_buffer_->data.allAvailableSensorsAreActive = false; | |
176 orientation_buffer_->seqlock.WriteEnd(); | |
177 orientation_buffer_ = NULL; | |
178 } | |
179 return true; | |
180 default: | |
181 NOTREACHED(); | |
182 } | |
183 return false; | |
184 } | |
185 | |
186 } // namespace content | |
OLD | NEW |