xref: /aosp_15_r20/frameworks/native/include/input/OneEuroFilter.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /**
2  * Copyright 2024 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 
17 #pragma once
18 
19 #include <chrono>
20 #include <optional>
21 
22 #include <input/Input.h>
23 
24 namespace android {
25 
26 /**
27  * Low pass filter with adaptive low pass frequency based on the signal's speed. The signal's cutoff
28  * frequency is determined by f_c = f_c_min + β|̇x_filtered|. Refer to
29  * https://dl.acm.org/doi/10.1145/2207676.2208639 for details on how the filter works and how to
30  * tune it.
31  */
32 class OneEuroFilter {
33 public:
34     /**
35      * Default cutoff frequency of the filtered signal's speed. 1.0 Hz is the value in the filter's
36      * paper.
37      */
38     static constexpr float kDefaultSpeedCutoffFreq = 1.0;
39 
40     OneEuroFilter() = delete;
41 
42     explicit OneEuroFilter(float minCutoffFreq, float beta,
43                            float speedCutoffFreq = kDefaultSpeedCutoffFreq);
44 
45     OneEuroFilter(const OneEuroFilter&) = delete;
46     OneEuroFilter& operator=(const OneEuroFilter&) = delete;
47     OneEuroFilter(OneEuroFilter&&) = delete;
48     OneEuroFilter& operator=(OneEuroFilter&&) = delete;
49 
50     /**
51      * Returns the filtered value of rawPosition. Each call to filter must provide a timestamp
52      * strictly greater than the timestamp of the previous call. The first time the method is
53      * called, it returns the value of rawPosition. Any subsequent calls provide a filtered value.
54      *
55      * @param timestamp The timestamp at which to filter. It must be strictly greater than the one
56      * provided in the previous call.
57      * @param rawPosition Position to be filtered.
58      */
59     float filter(std::chrono::nanoseconds timestamp, float rawPosition);
60 
61 private:
62     /**
63      * Minimum cutoff frequency. This is the constant term in the adaptive cutoff frequency
64      * criterion. Units are Hertz.
65      */
66     const float mMinCutoffFreq;
67 
68     /**
69      * Slope of the cutoff frequency criterion. This is the term scaling the absolute value of the
70      * filtered signal's speed. Units are 1 / position.
71      */
72     const float mBeta;
73 
74     /**
75      * Cutoff frequency of the signal's speed. This is the cutoff frequency applied to the filtering
76      * of the signal's speed. Units are Hertz.
77      */
78     const float mSpeedCutoffFreq;
79 
80     /**
81      * The timestamp from the previous call.
82      */
83     std::optional<std::chrono::nanoseconds> mPrevTimestamp;
84 
85     /**
86      * The raw position from the previous call.
87      */
88     std::optional<float> mPrevRawPosition;
89 
90     /**
91      * The filtered velocity from the previous call. Units are position per nanosecond.
92      */
93     std::optional<float> mPrevFilteredVelocity;
94 
95     /**
96      * The filtered position from the previous call.
97      */
98     std::optional<float> mPrevFilteredPosition;
99 };
100 
101 } // namespace android
102