Improve suppression behavior after reset
Previously, if we had an outlier pose in the buffer right after a
reset, we would consider the state to be "in motion" for the following
window-duration and then on top of that at a window-duration of
suppression. This causes the effective window duration to be twice
the desired one.
With this change, we consider the suppression period to start from the
time of the last outlier pose rather than the time when motion was
last detected.
Test: atest --host libheadtracking-test
Test: Manual verification of head-tracking behavior.
Change-Id: I6b74cc6e7870aa43ca5d79db241b85e0c0217938
diff --git a/media/libheadtracking/StillnessDetector-test.cpp b/media/libheadtracking/StillnessDetector-test.cpp
index 02f9d8a..b6cd479 100644
--- a/media/libheadtracking/StillnessDetector-test.cpp
+++ b/media/libheadtracking/StillnessDetector-test.cpp
@@ -83,13 +83,10 @@
EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
EXPECT_EQ(mDefaultValue, detector.calculate(600));
- detector.setInput(900, withinThreshold);
- EXPECT_EQ(mDefaultValue, detector.calculate(900));
+ detector.setInput(1299, withinThreshold);
+ EXPECT_FALSE(detector.calculate(1299));
detector.setInput(1300, baseline);
- EXPECT_FALSE(detector.calculate(1300));
- detector.setInput(1500, baseline);
- EXPECT_FALSE(detector.calculate(1899));
- EXPECT_TRUE(detector.calculate(1900));
+ EXPECT_TRUE(detector.calculate(1300));
}
TEST_P(StillnessDetectorTest, NotStillRotation) {
@@ -110,13 +107,10 @@
EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
EXPECT_EQ(mDefaultValue, detector.calculate(600));
- detector.setInput(900, withinThreshold);
- EXPECT_EQ(mDefaultValue, detector.calculate(900));
+ detector.setInput(1299, withinThreshold);
+ EXPECT_FALSE(detector.calculate(1299));
detector.setInput(1300, baseline);
- EXPECT_FALSE(detector.calculate(1300));
- detector.setInput(1500, baseline);
- EXPECT_FALSE(detector.calculate(1899));
- EXPECT_TRUE(detector.calculate(1900));
+ EXPECT_TRUE(detector.calculate(1300));
}
TEST_P(StillnessDetectorTest, Suppression) {
@@ -134,10 +128,10 @@
EXPECT_TRUE(detector.calculate(1000));
detector.setInput(1100, outsideThreshold);
EXPECT_FALSE(detector.calculate(1100));
- detector.setInput(2000, middlePoint);
- EXPECT_FALSE(detector.calculate(2000));
- EXPECT_FALSE(detector.calculate(2099));
- EXPECT_TRUE(detector.calculate(2100));
+ detector.setInput(1500, middlePoint);
+ EXPECT_FALSE(detector.calculate(1500));
+ EXPECT_FALSE(detector.calculate(1999));
+ EXPECT_TRUE(detector.calculate(2000));
}
TEST_P(StillnessDetectorTest, Reset) {
@@ -150,8 +144,8 @@
const Pose3f withinThreshold =
baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
EXPECT_EQ(mDefaultValue, detector.calculate(0));
- detector.setInput(0, baseline);
- EXPECT_EQ(mDefaultValue, detector.calculate(0));
+ detector.setInput(300, baseline);
+ EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.reset();
detector.setInput(600, baseline);
EXPECT_EQ(mDefaultValue, detector.calculate(600));
diff --git a/media/libheadtracking/StillnessDetector.cpp b/media/libheadtracking/StillnessDetector.cpp
index 9806352..be7c893 100644
--- a/media/libheadtracking/StillnessDetector.cpp
+++ b/media/libheadtracking/StillnessDetector.cpp
@@ -36,17 +36,22 @@
bool StillnessDetector::calculate(int64_t timestamp) {
discardOld(timestamp);
- // Check whether all the poses in the queue are in the proximity of the new
- // one. We want to do this before checking the overriding conditions below, in order to update
- // the suppression deadline correctly.
+ // Check whether all the poses in the queue are in the proximity of the new one. We want to do
+ // this before checking the overriding conditions below, in order to update the suppression
+ // deadline correctly. We always go from end to start, to find the most recent pose that
+ // violated stillness and update the suppression deadline if it has not been set or if the new
+ // one ends after the current one.
bool moved = false;
if (!mFifo.empty()) {
- for (auto iter = mFifo.begin(); iter != mFifo.end() - 1; ++iter) {
+ for (auto iter = mFifo.rbegin() + 1; iter != mFifo.rend(); ++iter) {
const auto& event = *iter;
if (!areNear(event.pose, mFifo.back().pose)) {
// Enable suppression for the duration of the window.
- mSuppressionDeadline = timestamp + mOptions.windowDuration;
+ int64_t deadline = event.timestamp + mOptions.windowDuration;
+ if (!mSuppressionDeadline.has_value() || mSuppressionDeadline.value() < deadline) {
+ mSuppressionDeadline = deadline;
+ }
moved = true;
break;
}