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

Commit 7901bddf authored by Ytai Ben-Tsvi's avatar Ytai Ben-Tsvi
Browse files

Fix display orientation handling

- Apply the orientation compensator before the filter. Otherwise, we
  won't tend to identity, but rather to a rotated frame, which is
  incorrect.
- Enable rate limiting when orientation changes, but only when a new
  world-to-screen pose arrives. This makes sure that rate limiting is
  applied at the point of discontinuity regardless of the order of
  operations.

Test: atest --host libheadtracking-test
Bug: 188502620
Change-Id: I58e1c3807f875ae2735e65122a3ffb8483bde2a3
parent 9bae7429
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -53,10 +53,10 @@ TEST(HeadTrackingProcessor, BasicComposition) {
    processor->setWorldToHeadPose(0, Pose3f(), Twist3f());
    processor->setWorldToScreenPose(0, Pose3f());

    processor->setDisplayOrientation(physicalToLogical);
    processor->setWorldToHeadPose(0, worldToHead, Twist3f());
    processor->setWorldToScreenPose(0, worldToScreen);
    processor->setScreenToStagePose(screenToStage);
    processor->setDisplayOrientation(physicalToLogical);
    processor->calculate(0);
    ASSERT_EQ(processor->getActualMode(), HeadTrackingMode::SCREEN_RELATIVE);
    EXPECT_EQ(processor->getHeadToStagePose(), worldToHead.inverse() * worldToScreen *
+13 −7
Original line number Diff line number Diff line
@@ -57,7 +57,14 @@ class HeadTrackingProcessorImpl : public HeadTrackingProcessor {
    }

    void setWorldToScreenPose(int64_t timestamp, const Pose3f& worldToScreen) override {
        mScreenPoseDriftCompensator.setInput(timestamp, worldToScreen);
        if (mPhysicalToLogicalAngle != mPendingPhysicalToLogicalAngle) {
            // We're introducing an artificial discontinuity. Enable the rate limiter.
            mRateLimiter.enable();
            mPhysicalToLogicalAngle = mPendingPhysicalToLogicalAngle;
        }

        mScreenPoseDriftCompensator.setInput(
                timestamp, worldToScreen * Pose3f(rotateY(-mPhysicalToLogicalAngle)));
        mWorldToScreenTimestamp = timestamp;
    }

@@ -66,10 +73,7 @@ class HeadTrackingProcessorImpl : public HeadTrackingProcessor {
    }

    void setDisplayOrientation(float physicalToLogicalAngle) override {
        if (mPhysicalToLogicalAngle != physicalToLogicalAngle) {
            mRateLimiter.enable();
        }
        mPhysicalToLogicalAngle = physicalToLogicalAngle;
        mPendingPhysicalToLogicalAngle = physicalToLogicalAngle;
    }

    void calculate(int64_t timestamp) override {
@@ -80,8 +84,7 @@ class HeadTrackingProcessorImpl : public HeadTrackingProcessor {
        }

        if (mWorldToScreenTimestamp.has_value()) {
            const Pose3f worldToLogicalScreen = mScreenPoseDriftCompensator.getOutput() *
                                                Pose3f(rotateY(-mPhysicalToLogicalAngle));
            const Pose3f worldToLogicalScreen = mScreenPoseDriftCompensator.getOutput();
            mScreenHeadFusion.setWorldToScreenPose(mWorldToScreenTimestamp.value(),
                                                   worldToLogicalScreen);
        }
@@ -129,6 +132,9 @@ class HeadTrackingProcessorImpl : public HeadTrackingProcessor {
  private:
    const Options mOptions;
    float mPhysicalToLogicalAngle = 0;
    // We store the physical to logical angle as "pending" until the next world-to-screen sample it
    // applies to arrives.
    float mPendingPhysicalToLogicalAngle = 0;
    std::optional<int64_t> mWorldToHeadTimestamp;
    std::optional<int64_t> mWorldToScreenTimestamp;
    Pose3f mHeadToStagePose;
−122 B (38.9 KiB)
Loading image diff...