xref: /aosp_15_r20/external/libchrome-gestures/include/palm_classifying_filter_interpreter.h (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <map>
6 #include <set>
7 
8 #include <gtest/gtest.h>  // for FRIEND_TEST
9 
10 #include "include/filter_interpreter.h"
11 #include "include/finger_metrics.h"
12 #include "include/gestures.h"
13 #include "include/macros.h"
14 #include "include/tracer.h"
15 
16 #ifndef GESTURES_PALM_CLASSIFYING_FILTER_INTERPRETER_H_
17 #define GESTURES_PALM_CLASSIFYING_FILTER_INTERPRETER_H_
18 
19 namespace gestures {
20 
21 // This interpreter looks at the location and pressure of contacts and may
22 // optionally classify each as a palm. Sometimes a contact is classified as
23 // a palm in some frames, and then in subsequent frames it is not.
24 // This interpreter is also used to suppress motion from thumbs in the
25 // bottom area of the pad.
26 
27 class PalmClassifyingFilterInterpreter : public FilterInterpreter {
28   FRIEND_TEST(PalmClassifyingFilterInterpreterTest, ExternallyMarkedPalmTest);
29   FRIEND_TEST(PalmClassifyingFilterInterpreterTest, PalmAtEdgeTest);
30   FRIEND_TEST(PalmClassifyingFilterInterpreterTest, PalmReevaluateTest);
31   FRIEND_TEST(PalmClassifyingFilterInterpreterTest, PalmTest);
32   FRIEND_TEST(PalmClassifyingFilterInterpreterTest, StationaryPalmTest);
33  public:
34   // Takes ownership of |next|:
35   PalmClassifyingFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
36                                    Tracer* tracer);
~PalmClassifyingFilterInterpreter()37   virtual ~PalmClassifyingFilterInterpreter() {}
38 
39  protected:
40   virtual void SyncInterpretImpl(HardwareState& hwstate, stime_t* timeout);
41 
42  private:
43   void FillOriginInfo(const HardwareState& hwstate);
44   void FillPrevInfo(const HardwareState& hwstate);
45   void FillMaxPressureWidthInfo(const HardwareState& hwstate);
46 
47   // Part of palm detection. Returns true if the finger indicated by
48   // |finger_idx| is near another finger, which must not be a palm, in the
49   // hwstate.
50   bool FingerNearOtherFinger(const HardwareState& hwstate,
51                              size_t finger_idx);
52 
53   // Returns true iff fs represents a contact that may be a palm. It's a palm
54   // if it's in the side edge (or top edge if filter_top_edge_ is set) with
55   // sufficiently large pressure. The pressure required depends on exactly how
56   // close to the edge the contact is.
57   bool FingerInPalmEnvelope(const FingerState& fs);
58 
59   // Returns true iff fs represents a contact that is in the bottom area.
60   bool FingerInBottomArea(const FingerState& fs);
61 
62   // Updates *palm_, pointing_ below.
63   void UpdatePalmState(const HardwareState& hwstate);
64 
65   // Updates the hwstate based on the local state.
66   void UpdatePalmFlags(HardwareState& hwstate);
67 
68   // Updates the distance travelled for each finger along +- x/y direction.
69   void UpdateDistanceInfo(const HardwareState& hwstate);
70 
71   // Returns the length of time the contact has been on the pad. Returns -1
72   // on error.
73   stime_t FingerAge(short finger_id, stime_t now) const;
74 
75   // Time when a contact arrived. Persists even when fingers change.
76   std::map<short, stime_t> origin_timestamps_;
77   // FingerStates from when a contact first arrived. Persists even when fingers
78   // change.
79   std::map<short, FingerState> origin_fingerstates_;
80 
81   // FingerStates from the previous HardwareState.
82   std::map<short, FingerState> prev_fingerstates_;
83 
84   // Max reported pressure for present fingers.
85   std::map<short, float> max_pressure_;
86 
87   // Max reported width for present fingers.
88   std::map<short, float> max_width_;
89 
90   // Accumulated distance travelled by each finger.
91   // _positive[0]  -->  positive direction along x axis
92   // _positive[1]  -->  positive direction along y axis
93   // _negative[0]  -->  negative direction along x axis
94   // _negative[1]  -->  negative direction along y axis
95   std::map<short, float> distance_positive_[2];
96   std::map<short, float> distance_negative_[2];
97 
98   // Same fingers state. This state is accumulated as fingers remain the same
99   // and it's reset when fingers change.
100   std::set<short> palm_;  // tracking ids of known palms
101   // These contacts are a subset of palms_ which are marked as palms because
102   // they have a large contact size.
103   std::set<short> large_palm_;
104   // These contacts have moved significantly and shouldn't be considered
105   // stationary palms:
106   std::set<short> non_stationary_palm_;
107 
108   static const unsigned kPointCloseToFinger = 1;
109   static const unsigned kPointNotInEdge = 2;
110   static const unsigned kPointMoving = 4;
111   // tracking ids of known fingers that are not palms, along with the reason(s)
112   std::map<short, unsigned> pointing_;
113 
114 
115   // tracking ids that were ever close to other fingers.
116   std::set<short> was_near_other_fingers_;
117 
118   // tracking ids that have ever travelled out of the palm envelope or bottom
119   // area.
120   std::set<short> fingers_not_in_edge_;
121 
122   // Previously input timestamp
123   stime_t prev_time_;
124 
125   // Maximum pressure above which a finger is considered a palm
126   DoubleProperty palm_pressure_;
127   // Maximum width_major above which a finger is considered a palm
128   DoubleProperty palm_width_;
129   // Maximum width_major above which a finger is considered a palm if there are
130   // other contacts
131   DoubleProperty multi_palm_width_;
132   // If a finger was previously classified as palm, but its lifetime max
133   // pressure is less than palm_pressure_ * fat_finger_pressure_ratio_,
134   // lifetime max width is less than palm_width_ * fat_finger_width_ratio_,
135   // and has moved more than fat_finger_min_dist_, we consider it as a fat
136   // finger.
137   DoubleProperty fat_finger_pressure_ratio_;
138   DoubleProperty fat_finger_width_ratio_;
139   DoubleProperty fat_finger_min_dist_;
140   // The smaller of two widths around the edge for palm detection. Any contact
141   // in this edge zone may be a palm, regardless of pressure
142   DoubleProperty palm_edge_min_width_;
143   // The larger of the two widths. Palms between this and the previous are
144   // expected to have pressure linearly increase from 0 to palm_pressure_
145   // as they approach this border.
146   DoubleProperty palm_edge_width_;
147   // If filter_top_edge_ is set, any contact this close to the top edge may be
148   // a palm.
149   DoubleProperty palm_top_edge_min_width_;
150   // Palms in edge are allowed to point if they move fast enough
151   DoubleProperty palm_edge_point_speed_;
152   // A finger can be added to the palm envelope (and thus not point) after
153   // it touches down and until palm_eval_timeout_ [s] time.
154   DoubleProperty palm_eval_timeout_;
155   // A potential palm (ambiguous contact in the edge of the pad) will be marked
156   // a palm if it travels less than palm_stationary_distance_ mm after it's
157   // been on the pad for palm_stationary_time_ seconds.
158   DoubleProperty palm_stationary_time_;
159   DoubleProperty palm_stationary_distance_;
160   // For a finger in the palm envelope to be qualified as pointing, it has to
161   // move in one direction at least palm_pointing_min_dist_ and no more
162   // than palm_pointing_max_reverse_dist_ in the opposite direction.
163   DoubleProperty palm_pointing_min_dist_;
164   DoubleProperty palm_pointing_max_reverse_dist_;
165   // If a palm splits right on the edge, sometimes the pressure readings aren't
166   // high enough to identify the palm.  If two fingers on the edge of the pad
167   // are closer together than this value, then they are likely a split palm.
168   DoubleProperty palm_split_max_distance_;
169   // Determines whether we look for palms at the top edge of the touchpad.
170   BoolProperty filter_top_edge_;
171 
172   DISALLOW_COPY_AND_ASSIGN(PalmClassifyingFilterInterpreter);
173 };
174 
175 }  // namespace gestures
176 
177 #endif  // GESTURES_PALM_CLASSIFYING_FILTER_INTERPRETER_H_
178