blob: eb23298349ae85b96b58a6db0fe50ff0e2029926 [file] [log] [blame]
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -07001/*
2 * Copyright 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "SpatializerPoseController.h"
17
Ytai Ben-Tsvie9b34952021-09-10 12:48:27 -070018#define LOG_TAG "SpatializerPoseController"
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070019//#define LOG_NDEBUG 0
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070020#include <sensor/Sensor.h>
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070021#include <utils/Log.h>
22#include <utils/SystemClock.h>
23
24namespace android {
25
26using media::createHeadTrackingProcessor;
27using media::HeadTrackingMode;
28using media::HeadTrackingProcessor;
29using media::Pose3f;
30using media::SensorPoseProvider;
31using media::Twist3f;
32
33using namespace std::chrono_literals;
34
35namespace {
36
37// This is how fast, in m/s, we allow position to shift during rate-limiting.
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -070038constexpr auto kMaxTranslationalVelocity = 2;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070039
40// This is how fast, in rad/s, we allow rotation angle to shift during rate-limiting.
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -070041constexpr auto kMaxRotationalVelocity = 4 * M_PI;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070042
43// This should be set to the typical time scale that the translation sensors used drift in. This
44// means, loosely, for how long we can trust the reading to be "accurate enough". This would
45// determine the time constants used for high-pass filtering those readings. If the value is set
46// too high, we may experience drift. If it is set too low, we may experience poses tending toward
47// identity too fast.
48constexpr auto kTranslationalDriftTimeConstant = 20s;
49
50// This should be set to the typical time scale that the rotation sensors used drift in. This
51// means, loosely, for how long we can trust the reading to be "accurate enough". This would
52// determine the time constants used for high-pass filtering those readings. If the value is set
53// too high, we may experience drift. If it is set too low, we may experience poses tending toward
54// identity too fast.
55constexpr auto kRotationalDriftTimeConstant = 20s;
56
57// This is how far into the future we predict the head pose, using linear extrapolation based on
58// twist (velocity). It should be set to a value that matches the characteristic durations of moving
59// one's head. The higher we set this, the more latency we are able to reduce, but setting this too
60// high will result in high prediction errors whenever the head accelerates (changes velocity).
61constexpr auto kPredictionDuration = 10ms;
62
63// After losing this many consecutive samples from either sensor, we would treat the measurement as
64// stale;
65constexpr auto kMaxLostSamples = 4;
66
67// Time units for system clock ticks. This is what the Sensor Framework timestamps represent and
68// what we use for pose filtering.
69using Ticks = std::chrono::nanoseconds;
70
71// How many ticks in a second.
72constexpr auto kTicksPerSecond = Ticks::period::den;
73
74} // namespace
75
76SpatializerPoseController::SpatializerPoseController(Listener* listener,
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -070077 std::chrono::microseconds sensorPeriod,
78 std::chrono::microseconds maxUpdatePeriod)
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070079 : mListener(listener),
80 mSensorPeriod(sensorPeriod),
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070081 mProcessor(createHeadTrackingProcessor(HeadTrackingProcessor::Options{
82 .maxTranslationalVelocity = kMaxTranslationalVelocity / kTicksPerSecond,
83 .maxRotationalVelocity = kMaxRotationalVelocity / kTicksPerSecond,
84 .translationalDriftTimeConstant = Ticks(kTranslationalDriftTimeConstant).count(),
85 .rotationalDriftTimeConstant = Ticks(kRotationalDriftTimeConstant).count(),
86 .freshnessTimeout = Ticks(sensorPeriod * kMaxLostSamples).count(),
87 .predictionDuration = Ticks(kPredictionDuration).count(),
88 })),
Ytai Ben-Tsvi8b6fe3a2021-09-13 15:55:44 -070089 mPoseProvider(SensorPoseProvider::create("headtracker", this)),
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070090 mThread([this, maxUpdatePeriod] {
91 while (true) {
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -070092 Pose3f headToStage;
93 std::optional<HeadTrackingMode> modeIfChanged;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070094 {
95 std::unique_lock lock(mMutex);
96 mCondVar.wait_for(lock, maxUpdatePeriod,
97 [this] { return mShouldExit || mShouldCalculate; });
98 if (mShouldExit) {
99 ALOGV("Exiting thread");
100 return;
101 }
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700102
103 // Calculate.
104 std::tie(headToStage, modeIfChanged) = calculate_l();
105 }
106
107 // Invoke the callbacks outside the lock.
108 mListener->onHeadToStagePose(headToStage);
109 if (modeIfChanged) {
110 mListener->onActualModeChange(modeIfChanged.value());
111 }
112
113 {
114 std::lock_guard lock(mMutex);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700115 if (!mCalculated) {
116 mCalculated = true;
117 mCondVar.notify_all();
118 }
119 mShouldCalculate = false;
120 }
121 }
122 }) {}
123
124SpatializerPoseController::~SpatializerPoseController() {
125 {
126 std::unique_lock lock(mMutex);
127 mShouldExit = true;
128 mCondVar.notify_all();
129 }
130 mThread.join();
131}
132
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700133void SpatializerPoseController::setHeadSensor(int32_t sensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700134 std::lock_guard lock(mMutex);
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700135 // Stop current sensor, if valid and different from the other sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700136 if (mHeadSensor != INVALID_SENSOR && mHeadSensor != mScreenSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700137 mPoseProvider->stopSensor(mHeadSensor);
138 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700139
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700140 if (sensor != INVALID_SENSOR) {
141 if (sensor != mScreenSensor) {
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700142 // Start new sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700143 mHeadSensor =
144 mPoseProvider->startSensor(sensor, mSensorPeriod) ? sensor : INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700145 } else {
146 // Sensor is already enabled.
147 mHeadSensor = mScreenSensor;
148 }
149 } else {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700150 mHeadSensor = INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700151 }
152
Ytai Ben-Tsvi95b00c82021-08-27 15:27:08 -0700153 mProcessor->recenter(true, false);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700154}
155
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700156void SpatializerPoseController::setScreenSensor(int32_t sensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700157 std::lock_guard lock(mMutex);
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700158 // Stop current sensor, if valid and different from the other sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700159 if (mScreenSensor != INVALID_SENSOR && mScreenSensor != mHeadSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700160 mPoseProvider->stopSensor(mScreenSensor);
161 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700162
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700163 if (sensor != INVALID_SENSOR) {
164 if (sensor != mHeadSensor) {
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700165 // Start new sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700166 mScreenSensor =
167 mPoseProvider->startSensor(sensor, mSensorPeriod) ? sensor : INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700168 } else {
169 // Sensor is already enabled.
170 mScreenSensor = mHeadSensor;
171 }
172 } else {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700173 mScreenSensor = INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700174 }
175
Ytai Ben-Tsvi95b00c82021-08-27 15:27:08 -0700176 mProcessor->recenter(false, true);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700177}
178
179void SpatializerPoseController::setDesiredMode(HeadTrackingMode mode) {
180 std::lock_guard lock(mMutex);
181 mProcessor->setDesiredMode(mode);
182}
183
184void SpatializerPoseController::setScreenToStagePose(const Pose3f& screenToStage) {
185 std::lock_guard lock(mMutex);
186 mProcessor->setScreenToStagePose(screenToStage);
187}
188
189void SpatializerPoseController::setDisplayOrientation(float physicalToLogicalAngle) {
190 std::lock_guard lock(mMutex);
191 mProcessor->setDisplayOrientation(physicalToLogicalAngle);
192}
193
194void SpatializerPoseController::calculateAsync() {
195 std::lock_guard lock(mMutex);
196 mShouldCalculate = true;
197 mCondVar.notify_all();
198}
199
200void SpatializerPoseController::waitUntilCalculated() {
201 std::unique_lock lock(mMutex);
202 mCondVar.wait(lock, [this] { return mCalculated; });
203}
204
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700205std::tuple<media::Pose3f, std::optional<media::HeadTrackingMode>>
206SpatializerPoseController::calculate_l() {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700207 Pose3f headToStage;
208 HeadTrackingMode mode;
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700209 std::optional<media::HeadTrackingMode> modeIfChanged;
210
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700211 mProcessor->calculate(elapsedRealtimeNano());
212 headToStage = mProcessor->getHeadToStagePose();
213 mode = mProcessor->getActualMode();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700214 if (!mActualMode.has_value() || mActualMode.value() != mode) {
215 mActualMode = mode;
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700216 modeIfChanged = mode;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700217 }
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700218 return std::make_tuple(headToStage, modeIfChanged);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700219}
220
221void SpatializerPoseController::recenter() {
222 std::lock_guard lock(mMutex);
223 mProcessor->recenter();
224}
225
226void SpatializerPoseController::onPose(int64_t timestamp, int32_t sensor, const Pose3f& pose,
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700227 const std::optional<Twist3f>& twist) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700228 std::lock_guard lock(mMutex);
229 if (sensor == mHeadSensor) {
230 mProcessor->setWorldToHeadPose(timestamp, pose, twist.value_or(Twist3f()));
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700231 }
232 if (sensor == mScreenSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700233 mProcessor->setWorldToScreenPose(timestamp, pose);
234 }
235}
236
237} // namespace android