1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project 3*ec779b8eSAndroid Build Coastguard Worker * 4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*ec779b8eSAndroid Build Coastguard Worker * 8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*ec779b8eSAndroid Build Coastguard Worker * 10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License. 15*ec779b8eSAndroid Build Coastguard Worker */ 16*ec779b8eSAndroid Build Coastguard Worker 17*ec779b8eSAndroid Build Coastguard Worker #pragma once 18*ec779b8eSAndroid Build Coastguard Worker 19*ec779b8eSAndroid Build Coastguard Worker #include <string> 20*ec779b8eSAndroid Build Coastguard Worker 21*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/Statistics.h> 22*ec779b8eSAndroid Build Coastguard Worker #include <media/Pose.h> 23*ec779b8eSAndroid Build Coastguard Worker 24*ec779b8eSAndroid Build Coastguard Worker namespace android::media { 25*ec779b8eSAndroid Build Coastguard Worker 26*ec779b8eSAndroid Build Coastguard Worker /** 27*ec779b8eSAndroid Build Coastguard Worker * PosePredictorVerifier is used to validate predictions 28*ec779b8eSAndroid Build Coastguard Worker * 29*ec779b8eSAndroid Build Coastguard Worker * This class is not thread-safe 30*ec779b8eSAndroid Build Coastguard Worker */ 31*ec779b8eSAndroid Build Coastguard Worker class PosePredictorVerifier { 32*ec779b8eSAndroid Build Coastguard Worker public: toString()33*ec779b8eSAndroid Build Coastguard Worker std::string toString() const { 34*ec779b8eSAndroid Build Coastguard Worker return mErrorStats.toString(); 35*ec779b8eSAndroid Build Coastguard Worker } 36*ec779b8eSAndroid Build Coastguard Worker 37*ec779b8eSAndroid Build Coastguard Worker static constexpr int64_t kMillisToNanos = 1000000; 38*ec779b8eSAndroid Build Coastguard Worker verifyActualPose(int64_t timestampNs,const Pose3f & pose)39*ec779b8eSAndroid Build Coastguard Worker void verifyActualPose(int64_t timestampNs, const Pose3f& pose) { 40*ec779b8eSAndroid Build Coastguard Worker for (auto it = mPredictions.begin(); it != mPredictions.end();) { 41*ec779b8eSAndroid Build Coastguard Worker if (it->first < timestampNs) { 42*ec779b8eSAndroid Build Coastguard Worker it = mPredictions.erase(it); 43*ec779b8eSAndroid Build Coastguard Worker } else { 44*ec779b8eSAndroid Build Coastguard Worker int64_t dt = it->first - timestampNs; 45*ec779b8eSAndroid Build Coastguard Worker if (std::abs(dt) < 10 * kMillisToNanos) { 46*ec779b8eSAndroid Build Coastguard Worker const float angle = pose.rotation().angularDistance(it->second.rotation()); 47*ec779b8eSAndroid Build Coastguard Worker const float error = std::abs(angle); // L1 (absolute difference) here. 48*ec779b8eSAndroid Build Coastguard Worker mLastError = error; 49*ec779b8eSAndroid Build Coastguard Worker mErrorStats.add(error); 50*ec779b8eSAndroid Build Coastguard Worker } 51*ec779b8eSAndroid Build Coastguard Worker break; 52*ec779b8eSAndroid Build Coastguard Worker } 53*ec779b8eSAndroid Build Coastguard Worker } 54*ec779b8eSAndroid Build Coastguard Worker } 55*ec779b8eSAndroid Build Coastguard Worker addPredictedPose(int64_t atNs,const Pose3f & pose)56*ec779b8eSAndroid Build Coastguard Worker void addPredictedPose(int64_t atNs, const Pose3f& pose) { 57*ec779b8eSAndroid Build Coastguard Worker mPredictions.emplace_back(atNs, pose); 58*ec779b8eSAndroid Build Coastguard Worker } 59*ec779b8eSAndroid Build Coastguard Worker lastError()60*ec779b8eSAndroid Build Coastguard Worker float lastError() const { 61*ec779b8eSAndroid Build Coastguard Worker return mLastError; 62*ec779b8eSAndroid Build Coastguard Worker } 63*ec779b8eSAndroid Build Coastguard Worker cumulativeAverageError()64*ec779b8eSAndroid Build Coastguard Worker float cumulativeAverageError() const { 65*ec779b8eSAndroid Build Coastguard Worker return mErrorStats.getMean(); 66*ec779b8eSAndroid Build Coastguard Worker } 67*ec779b8eSAndroid Build Coastguard Worker 68*ec779b8eSAndroid Build Coastguard Worker private: 69*ec779b8eSAndroid Build Coastguard Worker static constexpr double kCumulativeErrorAlpha = 0.999; 70*ec779b8eSAndroid Build Coastguard Worker std::deque<std::pair<int64_t, Pose3f>> mPredictions; 71*ec779b8eSAndroid Build Coastguard Worker float mLastError{}; 72*ec779b8eSAndroid Build Coastguard Worker android::audio_utils::Statistics<double> mErrorStats{kCumulativeErrorAlpha}; 73*ec779b8eSAndroid Build Coastguard Worker }; 74*ec779b8eSAndroid Build Coastguard Worker 75*ec779b8eSAndroid Build Coastguard Worker } // namespace androd::media 76