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