Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec0c3289 authored by Robert Dalton's avatar Robert Dalton
Browse files

Tune stillness detector for more responsive headtracking

Bug: 243821894
Test: manual - validated through listening tests

Change-Id: I2b07ac16e790d03b05f2ba0912d92901598d2bd5
parent e0d43b42
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -88,10 +88,12 @@ class HeadTrackingProcessorImpl : public HeadTrackingProcessor {
    }

    void calculate(int64_t timestamp) override {
        // Handle the screen first, since it might trigger a recentering of the head.
        bool screenStable = true;

        // Handle the screen first, since it might: trigger a recentering of the head.
        if (mWorldToScreenTimestamp.has_value()) {
            const Pose3f worldToLogicalScreen = mScreenPoseBias.getOutput();
            bool screenStable = mScreenStillnessDetector.calculate(timestamp);
            screenStable = mScreenStillnessDetector.calculate(timestamp);
            mModeSelector.setScreenStable(mWorldToScreenTimestamp.value(), screenStable);
            // Whenever the screen is unstable, recenter the head pose.
            if (!screenStable) {
@@ -105,7 +107,8 @@ class HeadTrackingProcessorImpl : public HeadTrackingProcessor {
        if (mWorldToHeadTimestamp.has_value()) {
            Pose3f worldToHead = mHeadPoseBias.getOutput();
            // Auto-recenter.
            if (mHeadStillnessDetector.calculate(timestamp)) {
            bool headStable = mHeadStillnessDetector.calculate(timestamp);
            if (headStable || !screenStable) {
                recenter(true, false);
                worldToHead = mHeadPoseBias.getOutput();
            }
+18 −5
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@ void StillnessDetector::reset() {
    mFifo.clear();
    mWindowFull = false;
    mSuppressionDeadline.reset();
    // A "true" state indicates stillness is detected (default = true)
    mCurrentState = true;
    mPreviousState = true;
}

void StillnessDetector::setInput(int64_t timestamp, const Pose3f& input) {
@@ -33,7 +36,15 @@ void StillnessDetector::setInput(int64_t timestamp, const Pose3f& input) {
    discardOld(timestamp);
}

bool StillnessDetector::getPreviousState() const {
    return mPreviousState;
}

bool StillnessDetector::calculate(int64_t timestamp) {
    // Move the current stillness state to the previous state.
    // This allows us to detect transitions into and out of stillness.
    mPreviousState = mCurrentState;

    discardOld(timestamp);

    // Check whether all the poses in the queue are in the proximity of the new one. We want to do
@@ -60,15 +71,17 @@ bool StillnessDetector::calculate(int64_t timestamp) {

    // If the window has not been full, return the default value.
    if (!mWindowFull) {
        return mOptions.defaultValue;
        mCurrentState = mOptions.defaultValue;
    }

    // Force "in motion" while the suppression deadline is active.
    if (mSuppressionDeadline.has_value()) {
        return false;
    else if (mSuppressionDeadline.has_value()) {
        mCurrentState = false;
    }
    else {
        mCurrentState = !moved;
    }

    return !moved;
    return mCurrentState;
}

void StillnessDetector::discardOld(int64_t timestamp) {
+4 −1
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ class StillnessDetector {
    void setInput(int64_t timestamp, const Pose3f& input);
    /** Calculate whether the stream is still at the given timestamp. */
    bool calculate(int64_t timestamp);

    /** Return the stillness state from the previous call to calculate() */
    bool getPreviousState() const;
  private:
    struct TimestampedPose {
        int64_t timestamp;
@@ -92,6 +93,8 @@ class StillnessDetector {
    const float mCosHalfRotationalThreshold;
    std::deque<TimestampedPose> mFifo;
    bool mWindowFull = false;
    bool mCurrentState = true;
    bool mPreviousState = true;
    // As soon as motion is detected, this will be set for the time of detection + window duration,
    // and during this time we will always consider outselves in motion without checking. This is
    // used for hyteresis purposes, since because of the approximate method we use for determining
+2 −2
Original line number Diff line number Diff line
@@ -65,13 +65,13 @@ constexpr float kAutoRecenterRotationThreshold = 10.5f / 180 * M_PI;

// Screen is considered to be unstable (not still) if it has moved significantly within the last
// time window of this duration.
constexpr auto kScreenStillnessWindowDuration = 3s;
constexpr auto kScreenStillnessWindowDuration = 750ms;

// Screen is considered to have moved significantly if translated by this much (in meter, approx).
constexpr float kScreenStillnessTranslationThreshold = 0.1f;

// Screen is considered to have moved significantly if rotated by this much (in radians, approx).
constexpr float kScreenStillnessRotationThreshold = 7.0f / 180 * M_PI;
constexpr float kScreenStillnessRotationThreshold = 15.0f / 180 * M_PI;

// Time units for system clock ticks. This is what the Sensor Framework timestamps represent and
// what we use for pose filtering.