OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "device/sensors/data_fetcher_shared_memory.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/metrics/histogram_macros.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" | |
13 | |
14 namespace device { | |
15 | |
16 const double kMeanGravity = 9.80665; | |
17 | |
18 void FetchMotion(SuddenMotionSensor* sensor, | |
19 DeviceMotionHardwareBuffer* buffer) { | |
20 DCHECK(sensor); | |
21 DCHECK(buffer); | |
22 | |
23 float axis_value[3]; | |
24 if (!sensor->ReadSensorValues(axis_value)) | |
25 return; | |
26 | |
27 buffer->seqlock.WriteBegin(); | |
28 buffer->data.acceleration_including_gravity_x = axis_value[0] * kMeanGravity; | |
29 buffer->data.has_acceleration_including_gravity_x = true; | |
30 buffer->data.acceleration_including_gravity_y = axis_value[1] * kMeanGravity; | |
31 buffer->data.has_acceleration_including_gravity_y = true; | |
32 buffer->data.acceleration_including_gravity_z = axis_value[2] * kMeanGravity; | |
33 buffer->data.has_acceleration_including_gravity_z = true; | |
34 buffer->data.all_available_sensors_are_active = true; | |
35 buffer->seqlock.WriteEnd(); | |
36 } | |
37 | |
38 void FetchOrientation(SuddenMotionSensor* sensor, | |
39 DeviceOrientationHardwareBuffer* buffer) { | |
40 DCHECK(sensor); | |
41 DCHECK(buffer); | |
42 | |
43 // Retrieve per-axis calibrated values. | |
44 float axis_value[3]; | |
45 if (!sensor->ReadSensorValues(axis_value)) | |
46 return; | |
47 | |
48 // Transform the accelerometer values to W3C draft angles. | |
49 // | |
50 // Accelerometer values are just dot products of the sensor axes | |
51 // by the gravity vector 'g' with the result for the z axis inverted. | |
52 // | |
53 // To understand this transformation calculate the 3rd row of the z-x-y | |
54 // Euler angles rotation matrix (because of the 'g' vector, only 3rd row | |
55 // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz. | |
56 // Then, assume alpha = 0 and you get this: | |
57 // | |
58 // x_acc = sin(gamma) | |
59 // y_acc = - cos(gamma) * sin(beta) | |
60 // z_acc = cos(beta) * cos(gamma) | |
61 // | |
62 // After that the rest is just a bit of trigonometry. | |
63 // | |
64 // Also note that alpha can't be provided but it's assumed to be always zero. | |
65 // This is necessary in order to provide enough information to solve | |
66 // the equations. | |
67 // | |
68 const double kRad2deg = 180.0 / M_PI; | |
69 double beta = kRad2deg * atan2(-axis_value[1], axis_value[2]); | |
70 double gamma = kRad2deg * asin(axis_value[0]); | |
71 | |
72 // Make sure that the interval boundaries comply with the specification. At | |
73 // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has | |
74 // the upper bound open on both. | |
75 if (beta == 180.0) | |
76 beta = -180; // -180 == 180 (upside-down) | |
77 if (gamma == 90.0) | |
78 gamma = nextafter(90, 0); | |
79 | |
80 // At this point, DCHECKing is paranoia. Never hurts. | |
81 DCHECK_GE(beta, -180.0); | |
82 DCHECK_LT(beta, 180.0); | |
83 DCHECK_GE(gamma, -90.0); | |
84 DCHECK_LT(gamma, 90.0); | |
85 | |
86 buffer->seqlock.WriteBegin(); | |
87 buffer->data.beta = beta; | |
88 buffer->data.has_beta = true; | |
89 buffer->data.gamma = gamma; | |
90 buffer->data.has_gamma = true; | |
91 buffer->data.all_available_sensors_are_active = true; | |
92 buffer->seqlock.WriteEnd(); | |
93 } | |
94 | |
95 DataFetcherSharedMemory::DataFetcherSharedMemory() {} | |
96 | |
97 DataFetcherSharedMemory::~DataFetcherSharedMemory() {} | |
98 | |
99 void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) { | |
100 DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); | |
101 DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || | |
102 consumer_bitmask & CONSUMER_TYPE_MOTION); | |
103 | |
104 if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION) | |
105 FetchOrientation(sudden_motion_sensor_.get(), orientation_buffer_); | |
106 if (consumer_bitmask & CONSUMER_TYPE_MOTION) | |
107 FetchMotion(sudden_motion_sensor_.get(), motion_buffer_); | |
108 } | |
109 | |
110 DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const { | |
111 return FETCHER_TYPE_POLLING_CALLBACK; | |
112 } | |
113 | |
114 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { | |
115 DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); | |
116 DCHECK(buffer); | |
117 | |
118 switch (consumer_type) { | |
119 case CONSUMER_TYPE_MOTION: { | |
120 if (!sudden_motion_sensor_) | |
121 sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); | |
122 bool sudden_motion_sensor_available = | |
123 sudden_motion_sensor_.get() != nullptr; | |
124 | |
125 motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer); | |
126 UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable", | |
127 sudden_motion_sensor_available); | |
128 if (!sudden_motion_sensor_available) { | |
129 // No motion sensor available, fire an all-null event. | |
130 motion_buffer_->seqlock.WriteBegin(); | |
131 motion_buffer_->data.all_available_sensors_are_active = true; | |
132 motion_buffer_->seqlock.WriteEnd(); | |
133 } | |
134 return sudden_motion_sensor_available; | |
135 } | |
136 case CONSUMER_TYPE_ORIENTATION: { | |
137 if (!sudden_motion_sensor_) | |
138 sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); | |
139 bool sudden_motion_sensor_available = | |
140 sudden_motion_sensor_.get() != nullptr; | |
141 | |
142 orientation_buffer_ = | |
143 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
144 UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable", | |
145 sudden_motion_sensor_available); | |
146 if (sudden_motion_sensor_available) { | |
147 // On Mac we cannot provide absolute orientation. | |
148 orientation_buffer_->seqlock.WriteBegin(); | |
149 orientation_buffer_->data.absolute = false; | |
150 orientation_buffer_->seqlock.WriteEnd(); | |
151 } else { | |
152 // No motion sensor available, fire an all-null event. | |
153 orientation_buffer_->seqlock.WriteBegin(); | |
154 orientation_buffer_->data.all_available_sensors_are_active = true; | |
155 orientation_buffer_->seqlock.WriteEnd(); | |
156 } | |
157 return sudden_motion_sensor_available; | |
158 } | |
159 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: { | |
160 orientation_absolute_buffer_ = | |
161 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
162 // Absolute device orientation not available on Mac, let the | |
163 // implementation fire an all-null event to signal this to blink. | |
164 orientation_absolute_buffer_->seqlock.WriteBegin(); | |
165 orientation_absolute_buffer_->data.absolute = true; | |
166 orientation_absolute_buffer_->data.all_available_sensors_are_active = | |
167 true; | |
168 orientation_absolute_buffer_->seqlock.WriteEnd(); | |
169 return false; | |
170 } | |
171 default: | |
172 NOTREACHED(); | |
173 } | |
174 return false; | |
175 } | |
176 | |
177 bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { | |
178 DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); | |
179 | |
180 switch (consumer_type) { | |
181 case CONSUMER_TYPE_MOTION: | |
182 if (motion_buffer_) { | |
183 motion_buffer_->seqlock.WriteBegin(); | |
184 motion_buffer_->data.all_available_sensors_are_active = false; | |
185 motion_buffer_->seqlock.WriteEnd(); | |
186 motion_buffer_ = nullptr; | |
187 } | |
188 return true; | |
189 case CONSUMER_TYPE_ORIENTATION: | |
190 if (orientation_buffer_) { | |
191 orientation_buffer_->seqlock.WriteBegin(); | |
192 orientation_buffer_->data.all_available_sensors_are_active = false; | |
193 orientation_buffer_->seqlock.WriteEnd(); | |
194 orientation_buffer_ = nullptr; | |
195 } | |
196 return true; | |
197 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: | |
198 if (orientation_absolute_buffer_) { | |
199 orientation_absolute_buffer_->seqlock.WriteBegin(); | |
200 orientation_absolute_buffer_->data.all_available_sensors_are_active = | |
201 false; | |
202 orientation_absolute_buffer_->seqlock.WriteEnd(); | |
203 orientation_absolute_buffer_ = nullptr; | |
204 } | |
205 return true; | |
206 default: | |
207 NOTREACHED(); | |
208 } | |
209 return false; | |
210 } | |
211 | |
212 } // namespace device | |
OLD | NEW |