Home | History | Annotate | Download | only in firmware_TouchMTB
      1 # -*- coding: utf-8 -*-
      2 #
      3 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 """This configuration file defines the gestures to perform."""
      8 
      9 from collections import defaultdict
     10 from firmware_constants import DEV, GV, VAL
     11 from validators import (CountPacketsValidator,
     12                         CountTrackingIDNormalFingerValidator,
     13                         CountTrackingIDFatFingerValidator,
     14                         DragLatencyValidator,
     15                         DiscardInitialSecondsValidator,
     16                         DrumrollValidator,
     17                         HysteresisValidator,
     18                         LinearityFatFingerValidator,
     19                         LinearityNormalFingerValidator,
     20                         MtbSanityValidator,
     21                         NoGapValidator,
     22                         NoReversedMotionValidator,
     23                         PhysicalClickValidator,
     24                         PinchValidator,
     25                         RangeValidator,
     26                         ReportRateValidator,
     27                         StationaryValidator,
     28                         StationaryFingerValidator,
     29                         StationaryTapValidator,
     30 )
     31 
     32 
     33 # Define which score aggregator is to be used. A score aggregator collects
     34 # the scores from every tests and calculates the final score for the touch
     35 # firmware test suite.
     36 score_aggregator = 'fuzzy.average'
     37 
     38 
     39 # Define some common criteria
     40 count_packets_criteria = '>= 3, ~ -3'
     41 drumroll_criteria = '<= 2.0'
     42 # linearity_criteria is used for strictly straight line drawn with a ruler.
     43 linearity_criteria = '<= 0.8, ~ +2.4'
     44 # relaxed_linearity_criteria is used for lines drawn with thumb edge or
     45 # fat fingers which are allowed to be curvy to some extent.
     46 relaxed_linearity_criteria = '<= 1.5, ~ +3.0'
     47 no_gap_criteria = '<= 1.8, ~ +1.0'
     48 no_level_jump_criteria = '<= 10, ~ +30'
     49 no_reversed_motion_criteria = '<= 5, ~ +30'
     50 pinch_criteria = '>= 200, ~ -100'
     51 range_criteria = '<= 0.01, ~ +0.07'
     52 min_report_rate = 60
     53 max_report_interval = 1.0 / min_report_rate * 1000
     54 report_rate_criteria = '>= %d' % min_report_rate
     55 stationary_finger_criteria = '<= 1.0'
     56 stationary_tap_criteria = '<= 1.0'
     57 hysteresis_criteria = '<= 2.0'
     58 drag_latency_criteria = '<= 28.0'
     59 
     60 MIN_MOVING_DISTANCE = 20
     61 
     62 
     63 # Define filenames and paths
     64 docroot = '/tmp'
     65 report_basename = 'touch_firmware_report'
     66 html_ext = '.html'
     67 ENVIRONMENT_REPORT_HTML_NAME = 'REPORT_HTML_NAME'
     68 log_root_dir = '/var/tmp/touch_firmware_test'
     69 fw_prefix = 'fw_'
     70 device_description_dir = 'tests/device'
     71 version_filename = '.version'
     72 
     73 
     74 # Define parameters for GUI
     75 score_colors = ((0.9, 'blue'), (0.8, 'orange'), (0.0, 'red'))
     76 num_chars_per_row = 28
     77 
     78 
     79 # Define the validators that are shown only when there are failures.
     80 validators_hidden_when_no_failures = ['PinchValidator',
     81                                       'CountTrackingIDNormalFingerValidator',
     82                                       'CountTrackingIDFatFingerValidator',
     83                                       'CountPacketsValidator']
     84 
     85 
     86 # Define the parent validators from which the derived validators should be
     87 # merged in the top-level summary table.
     88 merged_validators = [StationaryValidator,]
     89 
     90 
     91 # Define the path to find the robot gestures library path
     92 robot_lib_path_local = '/usr/local/lib*'
     93 robot_lib_path = '/usr/lib*'
     94 python_package = 'python*\.*'
     95 gestures_sub_path = 'site-packages/touchbotII'
     96 
     97 
     98 # Define the gesture names
     99 NOISE_LINE = 'noise_line'
    100 NOISE_STATIONARY = 'noise_stationary'
    101 NOISE_STATIONARY_EXTENDED = 'noise_stationary_extended'
    102 ONE_FINGER_TRACKING = 'one_finger_tracking'
    103 ONE_FINGER_TO_EDGE = 'one_finger_to_edge'
    104 TWO_FINGER_TRACKING = 'two_finger_tracking'
    105 FINGER_CROSSING = 'finger_crossing'
    106 ONE_FINGER_SWIPE = 'one_finger_swipe'
    107 TWO_FINGER_SWIPE = 'two_finger_swipe'
    108 PINCH_TO_ZOOM = 'pinch_to_zoom'
    109 ONE_FINGER_TAP = 'one_finger_tap'
    110 TWO_FINGER_TAP = 'two_finger_tap'
    111 ONE_FINGER_PHYSICAL_CLICK = 'one_finger_physical_click'
    112 TWO_FINGER_PHYSICAL_CLICK = 'two_fingers_physical_click'
    113 THREE_FINGER_PHYSICAL_CLICK = 'three_fingers_physical_click'
    114 FOUR_FINGER_PHYSICAL_CLICK = 'four_fingers_physical_click'
    115 FIVE_FINGER_PHYSICAL_CLICK = 'five_fingers_physical_click'
    116 STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS = \
    117         'stationary_finger_not_affected_by_2nd_finger_taps'
    118 FAT_FINGER_MOVE_WITH_RESTING_FINGER = 'fat_finger_move_with_resting_finger'
    119 DRAG_EDGE_THUMB = 'drag_edge_thumb'
    120 TWO_CLOSE_FINGERS_TRACKING = 'two_close_fingers_tracking'
    121 RESTING_FINGER_PLUS_2ND_FINGER_MOVE = 'resting_finger_plus_2nd_finger_move'
    122 TWO_FAT_FINGERS_TRACKING = 'two_fat_fingers_tracking'
    123 FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS = \
    124         'first_finger_tracking_and_second_finger_taps'
    125 DRUMROLL = 'drumroll'
    126 RAPID_TAPS = 'rapid_taps_20'
    127 ONE_FINGER_TRACKING_FROM_CENTER = 'one_finger_tracking_from_center'
    128 DRAG_LATENCY = 'drag_latency'
    129 # This following gesture is for pressure calibration.
    130 PRESSURE_CALIBRATION = 'pressure_calibration'
    131 
    132 # The gaps in MM required between fingertips for these tests
    133 FINGER_CROSSING_GAP_MM = 1
    134 FAT_FINGER_AND_STATIONARY_FINGER_GAP_MM = 1
    135 
    136 # This denotes the list of the numbers of fingers for physical click tests.
    137 # It corresponds to ONE/TWO/THREE/FOUR/FIVE_FINGER_PHYSICAL_CLICK defined above.
    138 fingers_physical_click = [1, 2, 3, 4, 5]
    139 
    140 
    141 # Define the complete list
    142 gesture_names_complete = {
    143     DEV.TOUCHPAD: [
    144         NOISE_LINE,
    145         NOISE_STATIONARY,
    146         ONE_FINGER_TRACKING,
    147         ONE_FINGER_TO_EDGE,
    148         TWO_FINGER_TRACKING,
    149         FINGER_CROSSING,
    150         ONE_FINGER_SWIPE,
    151         ONE_FINGER_TRACKING_FROM_CENTER,
    152         TWO_FINGER_SWIPE,
    153         PINCH_TO_ZOOM,
    154         ONE_FINGER_TAP,
    155         TWO_FINGER_TAP,
    156         ONE_FINGER_PHYSICAL_CLICK,
    157         TWO_FINGER_PHYSICAL_CLICK,
    158         THREE_FINGER_PHYSICAL_CLICK,
    159         FOUR_FINGER_PHYSICAL_CLICK,
    160         FIVE_FINGER_PHYSICAL_CLICK,
    161         STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
    162         FAT_FINGER_MOVE_WITH_RESTING_FINGER,
    163         DRAG_EDGE_THUMB,
    164         TWO_CLOSE_FINGERS_TRACKING,
    165         RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
    166         TWO_FAT_FINGERS_TRACKING,
    167         FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
    168         DRUMROLL,
    169         RAPID_TAPS,
    170         DRAG_LATENCY,
    171     ],
    172     DEV.TOUCHSCREEN: [
    173         NOISE_LINE,
    174         NOISE_STATIONARY,
    175         ONE_FINGER_TRACKING,
    176         ONE_FINGER_TO_EDGE,
    177         TWO_FINGER_TRACKING,
    178         FINGER_CROSSING,
    179         ONE_FINGER_SWIPE,
    180         ONE_FINGER_TRACKING_FROM_CENTER,
    181         TWO_FINGER_SWIPE,
    182         PINCH_TO_ZOOM,
    183         ONE_FINGER_TAP,
    184         TWO_FINGER_TAP,
    185         STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
    186         FAT_FINGER_MOVE_WITH_RESTING_FINGER,
    187         DRAG_EDGE_THUMB,
    188         TWO_CLOSE_FINGERS_TRACKING,
    189         RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
    190         TWO_FAT_FINGERS_TRACKING,
    191         FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
    192         DRUMROLL,
    193         RAPID_TAPS,
    194         DRAG_LATENCY,
    195     ],
    196 }
    197 
    198 
    199 # Define what gestures the robot can perform.
    200 # This also defines the order for the robot to perform the gestures.
    201 # Basically, two-fingers gestures follow one-finger gestures.
    202 robot_capability_list = [
    203     NOISE_LINE,
    204     NOISE_STATIONARY,
    205     ONE_FINGER_TRACKING,
    206     ONE_FINGER_TO_EDGE,
    207     ONE_FINGER_SWIPE,
    208     ONE_FINGER_TRACKING_FROM_CENTER,
    209     ONE_FINGER_TAP,
    210     RAPID_TAPS,
    211     TWO_FINGER_TRACKING,
    212     TWO_CLOSE_FINGERS_TRACKING,
    213     TWO_FINGER_SWIPE,
    214     TWO_FINGER_TAP,
    215     STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
    216     FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
    217     RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
    218     FINGER_CROSSING,
    219     PINCH_TO_ZOOM,
    220     DRUMROLL,
    221     TWO_FAT_FINGERS_TRACKING,
    222     FAT_FINGER_MOVE_WITH_RESTING_FINGER,
    223     ONE_FINGER_PHYSICAL_CLICK,
    224     TWO_FINGER_PHYSICAL_CLICK,
    225     THREE_FINGER_PHYSICAL_CLICK,
    226     FOUR_FINGER_PHYSICAL_CLICK,
    227 ]
    228 
    229 NO_FINGER = None
    230 TINY_FINGER = 0
    231 NORMAL_FINGER = 1
    232 LARGE_FINGER = 2
    233 FAT_FINGER = 3
    234 ALL_FINGERTIP_SIZES = [TINY_FINGER, NORMAL_FINGER, LARGE_FINGER, FAT_FINGER]
    235 FINGERTIP_DIAMETER_MM = {TINY_FINGER: 8, NORMAL_FINGER: 10,
    236                          LARGE_FINGER: 12, FAT_FINGER: 14}
    237 
    238 custom_tips_required = {
    239     DRAG_LATENCY: [NO_FINGER, NO_FINGER, FAT_FINGER, NO_FINGER],
    240     ONE_FINGER_PHYSICAL_CLICK: [NORMAL_FINGER, NO_FINGER, NO_FINGER, NO_FINGER],
    241     TWO_FINGER_PHYSICAL_CLICK: [NO_FINGER, NORMAL_FINGER, NO_FINGER,
    242                                 NORMAL_FINGER],
    243     THREE_FINGER_PHYSICAL_CLICK: [NO_FINGER, NORMAL_FINGER, NORMAL_FINGER,
    244                                   NORMAL_FINGER],
    245     TWO_FAT_FINGERS_TRACKING: [FAT_FINGER, FAT_FINGER, FAT_FINGER, FAT_FINGER],
    246     FAT_FINGER_MOVE_WITH_RESTING_FINGER: [NORMAL_FINGER, NO_FINGER,
    247                                           FAT_FINGER, NO_FINGER],
    248     FINGER_CROSSING: [NORMAL_FINGER, NO_FINGER, NORMAL_FINGER, NO_FINGER],
    249     NOISE_LINE: [NO_FINGER, NORMAL_FINGER, NO_FINGER, NO_FINGER],
    250     NOISE_STATIONARY: [NORMAL_FINGER, NO_FINGER, NO_FINGER, NO_FINGER],
    251     NOISE_STATIONARY_EXTENDED: [NORMAL_FINGER, NO_FINGER, NO_FINGER, NO_FINGER],
    252 }
    253 default_tips_required = [NORMAL_FINGER, NORMAL_FINGER,
    254                          NORMAL_FINGER, NORMAL_FINGER]
    255 finger_tips_required = defaultdict(lambda:default_tips_required,
    256                                    custom_tips_required)
    257 
    258 def get_gesture_names_for_robot(device):
    259     """Get the gesture names that a robot can do for a specified device."""
    260     return [gesture for gesture in robot_capability_list
    261                     if gesture in gesture_names_complete[device]]
    262 
    263 
    264 # Define the list of one-finger and two-finger gestures to test using the robot.
    265 gesture_names_robot = {
    266     DEV.TOUCHPAD: get_gesture_names_for_robot(DEV.TOUCHPAD),
    267     DEV.TOUCHSCREEN: get_gesture_names_for_robot(DEV.TOUCHSCREEN),
    268 }
    269 
    270 gesture_names_quickstep = [DRAG_LATENCY]
    271 
    272 # Define the list of gestures that require a function generator to run
    273 gesture_names_fngenerator_required = [NOISE_LINE, NOISE_STATIONARY,
    274                                       NOISE_STATIONARY_EXTENDED]
    275 
    276 # Define the list of gestures to test in NOISE mode.
    277 gesture_names_noise_extended = [NOISE_STATIONARY_EXTENDED]
    278 
    279 
    280 # Define the gesture for pressure calibration
    281 gesture_names_calibration = [PRESSURE_CALIBRATION,]
    282 
    283 # Define the relative segment weights of a validator.
    284 # For example, LinearityMiddleValidator : LinearityBothEndsValidator = 7 : 3
    285 segment_weights = {VAL.BEGIN: 0.15,
    286                    VAL.MIDDLE: 0.7,
    287                    VAL.END: 0.15,
    288                    VAL.BOTH_ENDS: 0.15 + 0.15,
    289                    VAL.WHOLE: 0.15 + 0.7 + 0.15,
    290 }
    291 
    292 
    293 # Define the validator score weights
    294 weight_rare = 1
    295 weight_common = 2
    296 weight_critical = 3
    297 validator_weights = {'CountPacketsValidator': weight_common,
    298                      'CountTrackingIDNormalFingerValidator': weight_critical,
    299                      'CountTrackingIDFatFingerValidator': weight_rare,
    300                      'DragLatencyValidator': weight_critical,
    301                      'DrumrollValidator': weight_rare,
    302                      'LinearityNormalFingerValidator': weight_common,
    303                      'LinearityFatFingerValidator': weight_rare,
    304                      'MtbSanityValidator': weight_critical,
    305                      'NoGapValidator': weight_common,
    306                      'NoReversedMotionValidator': weight_common,
    307                      'PhysicalClickValidator': weight_critical,
    308                      'PinchValidator': weight_common,
    309                      'RangeValidator': weight_common,
    310                      'ReportRateValidator': weight_common,
    311                      'HysteresisValidator': weight_common,
    312                      'StationaryFingerValidator': weight_common,
    313                      'StationaryTapValidator': weight_common,
    314 }
    315 
    316 
    317 # Define the gesture list that the user needs to perform in the test suite.
    318 def get_gesture_dict():
    319     """Define the dictionary for all gestures."""
    320     gesture_dict = {
    321         NOISE_STATIONARY:
    322         Gesture(
    323             name=NOISE_STATIONARY,
    324             variations=((GV.LOW_FREQUENCY, GV.MED_FREQUENCY, GV.HIGH_FREQUENCY),
    325                         (GV.HALF_AMPLITUDE, GV.MAX_AMPLITUDE),
    326                         (GV.SQUARE_WAVE,),
    327                         (GV.TL, GV.TR, GV.BL, GV.BR, GV.TS, GV.BS, GV.LS, GV.RS,
    328                          GV.CENTER),
    329             ),
    330             prompt='Hold one finger on the {3} of the touch surface with a '
    331                    '{0} {1} {2} in noise.',
    332             subprompt={
    333                 GV.TL: ('top left corner',),
    334                 GV.TR: ('top right corner',),
    335                 GV.BL: ('bottom left corner',),
    336                 GV.BR: ('bottom right corner',),
    337                 GV.TS: ('top edge',),
    338                 GV.BS: ('bottom side',),
    339                 GV.LS: ('left hand side',),
    340                 GV.RS: ('right hand side',),
    341                 GV.CENTER: ('center',),
    342                 GV.LOW_FREQUENCY: ('5kHz',),
    343                 GV.MED_FREQUENCY: ('500kHz',),
    344                 GV.HIGH_FREQUENCY: ('1MHz',),
    345                 GV.HALF_AMPLITUDE: ('10Vpp',),
    346                 GV.MAX_AMPLITUDE: ('20Vpp',),
    347                 GV.SQUARE_WAVE: ('square wave',),
    348             },
    349             validators=(
    350                 DiscardInitialSecondsValidator(
    351                     CountTrackingIDNormalFingerValidator('== 1')),
    352                 DiscardInitialSecondsValidator(
    353                     StationaryTapValidator(stationary_tap_criteria, slot=0)),
    354             ),
    355         ),
    356         NOISE_LINE:
    357         Gesture(
    358             name=NOISE_LINE,
    359             variations=((GV.LOW_FREQUENCY, GV.MED_FREQUENCY, GV.HIGH_FREQUENCY),
    360                         (GV.HALF_AMPLITUDE, GV.MAX_AMPLITUDE),
    361                         (GV.SQUARE_WAVE,),
    362                         (GV.BLTR,),
    363                         (GV.NORMAL,),
    364             ),
    365             prompt='Draw a straight line from {3} with a {0} {1} {2} in noise.',
    366             subprompt={
    367                 GV.LOW_FREQUENCY: ('5kHz',),
    368                 GV.MED_FREQUENCY: ('500kHz',),
    369                 GV.HIGH_FREQUENCY: ('1MHz',),
    370                 GV.HALF_AMPLITUDE: ('10Vpp',),
    371                 GV.MAX_AMPLITUDE: ('20Vpp',),
    372                 GV.SQUARE_WAVE: ('square wave',),
    373                 GV.NORMAL: ('',),
    374                 GV.BLTR: ('bottom left to top right',),
    375             },
    376             validators=(
    377                 DiscardInitialSecondsValidator(
    378                     CountTrackingIDNormalFingerValidator('== 1')),
    379                 DiscardInitialSecondsValidator(
    380                     LinearityNormalFingerValidator(linearity_criteria, finger=0,
    381                                                    segments=VAL.MIDDLE)),
    382                 DiscardInitialSecondsValidator(
    383                     NoGapValidator(no_gap_criteria, slot=0)),
    384                 DiscardInitialSecondsValidator(
    385                     NoReversedMotionValidator(no_reversed_motion_criteria,
    386                                               slots=0, segments=VAL.MIDDLE)),
    387                 DiscardInitialSecondsValidator(
    388                     NoReversedMotionValidator(no_reversed_motion_criteria,
    389                                               slots=0, segments=VAL.BOTH_ENDS)),
    390                 DiscardInitialSecondsValidator(
    391                     ReportRateValidator(report_rate_criteria)),
    392             ),
    393         ),
    394         NOISE_STATIONARY_EXTENDED:
    395         Gesture(
    396             name=NOISE_STATIONARY_EXTENDED,
    397             variations=(tuple(GV.EXTENDED_FREQUENCIES),
    398                         (GV.MAX_AMPLITUDE,),
    399                         (GV.SQUARE_WAVE,),
    400                         (GV.CENTER,),
    401             ),
    402             prompt='Hold one finger on the {3} of the touch surface with a '
    403                    '{0} {1} {2} in noise.',
    404             subprompt=dict({
    405                 GV.CENTER: ('center',),
    406                 GV.MAX_AMPLITUDE: ('20Vpp',),
    407                 GV.SQUARE_WAVE: ('square wave',),
    408             }.items() +
    409                 {freq: (freq,) for freq in GV.EXTENDED_FREQUENCIES}.items()),
    410             validators=(
    411                 DiscardInitialSecondsValidator(
    412                     CountTrackingIDNormalFingerValidator('== 1')),
    413                 DiscardInitialSecondsValidator(
    414                     StationaryTapValidator(stationary_tap_criteria, slot=0)),
    415             ),
    416         ),
    417         ONE_FINGER_TRACKING:
    418         Gesture(
    419             name=ONE_FINGER_TRACKING,
    420             variations=((GV.LR, GV.RL, GV.TB, GV.BT, GV.BLTR, GV.TRBL),
    421                         (GV.SLOW, GV.NORMAL),
    422             ),
    423             prompt='Take {2} to draw a straight, {0} line {1} using a ruler.',
    424             subprompt={
    425                 GV.LR: ('horizontal', 'from left to right',),
    426                 GV.RL: ('horizontal', 'from right to left',),
    427                 GV.TB: ('vertical', 'from top to bottom',),
    428                 GV.BT: ('vertical', 'from bottom to top',),
    429                 GV.BLTR: ('diagonal', 'from bottom left to top right',),
    430                 GV.TRBL: ('diagonal', 'from top right to bottom left',),
    431                 GV.SLOW: ('3 seconds',),
    432                 GV.NORMAL: ('1 second',),
    433             },
    434             validators=(
    435                 CountTrackingIDNormalFingerValidator('== 1'),
    436                 LinearityNormalFingerValidator(linearity_criteria, finger=0,
    437                                                segments=VAL.MIDDLE),
    438                 NoGapValidator(no_gap_criteria, slot=0),
    439                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0,
    440                                           segments=VAL.MIDDLE),
    441                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0,
    442                                           segments=VAL.BOTH_ENDS),
    443                 ReportRateValidator(report_rate_criteria),
    444             ),
    445         ),
    446 
    447         ONE_FINGER_TO_EDGE:
    448         Gesture(
    449             name=ONE_FINGER_TO_EDGE,
    450             variations=((GV.CL, GV.CR, GV.CT, GV.CB),
    451                         (GV.SLOW,),
    452             ),
    453             prompt='Take {2} to draw a striaght {0} line {1}.',
    454             subprompt={
    455                 GV.CL: ('horizontal', 'from the center off left edge',),
    456                 GV.CR: ('horizontal', 'from the center off right edge',),
    457                 GV.CT: ('vertical', 'from the center  off top edge',),
    458                 GV.CB: ('vertical', 'from the center off bottom edge',),
    459                 GV.SLOW: ('2 seconds',),
    460             },
    461             validators=(
    462                 CountTrackingIDNormalFingerValidator('== 1'),
    463                 LinearityNormalFingerValidator(linearity_criteria, finger=0,
    464                                                segments=VAL.MIDDLE),
    465                 NoGapValidator(no_gap_criteria, slot=0),
    466                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    467                 RangeValidator(range_criteria),
    468                 ReportRateValidator(report_rate_criteria),
    469             ),
    470         ),
    471 
    472         TWO_FINGER_TRACKING:
    473         Gesture(
    474             name=TWO_FINGER_TRACKING,
    475             variations=((GV.LR, GV.RL, GV.TB, GV.BT, GV.BLTR, GV.TRBL),
    476                         (GV.SLOW, GV.NORMAL),
    477             ),
    478             prompt='Take {2} to draw a {0} line {1} using a ruler '
    479                    'with TWO fingers at the same time.',
    480             subprompt={
    481                 GV.LR: ('horizontal', 'from left to right',),
    482                 GV.RL: ('horizontal', 'from right to left',),
    483                 GV.TB: ('vertical', 'from top to bottom',),
    484                 GV.BT: ('vertical', 'from bottom to top',),
    485                 GV.BLTR: ('diagonal', 'from bottom left to top right',),
    486                 GV.TRBL: ('diagonal', 'from top right to bottom left',),
    487                 GV.SLOW: ('3 seconds',),
    488                 GV.NORMAL: ('1 second',),
    489             },
    490             validators=(
    491                 CountTrackingIDNormalFingerValidator('== 2'),
    492                 LinearityNormalFingerValidator(linearity_criteria, finger=0,
    493                                                segments=VAL.MIDDLE),
    494                 LinearityNormalFingerValidator(linearity_criteria, finger=1,
    495                                                segments=VAL.MIDDLE),
    496                 NoGapValidator(no_gap_criteria, slot=0),
    497                 NoGapValidator(no_gap_criteria, slot=1),
    498                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    499                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
    500                 ReportRateValidator(report_rate_criteria),
    501             ),
    502         ),
    503 
    504         FINGER_CROSSING:
    505         Gesture(
    506             # also covers stationary_finger_not_affected_by_2nd_moving_finger
    507             name=FINGER_CROSSING,
    508             variations=((GV.LR, GV.RL, GV.TB, GV.BT, GV.BLTR, GV.TRBL),
    509                         (GV.SLOW, GV.NORMAL),
    510             ),
    511             prompt='Place one stationary finger near the center of the '
    512                    'touch surface, then take {2} to draw a straight line '
    513                    '{0} {1} with a second finger',
    514             subprompt={
    515                 GV.LR: ('from left to right', 'above the stationary finger'),
    516                 GV.RL: ('from right to left', 'below the stationary finger'),
    517                 GV.TB: ('from top to bottom',
    518                         'on the right to the stationary finger'),
    519                 GV.BT: ('from bottom to top',
    520                         'on the left to the stationary finger'),
    521                 GV.BLTR: ('from the bottom left to the top right',
    522                           'above the stationary finger',),
    523                 GV.TRBL: ('from the top right to the bottom left',
    524                           'below the stationary finger'),
    525                 GV.SLOW: ('3 seconds',),
    526                 GV.NORMAL: ('1 second',),
    527             },
    528             validators=(
    529                 CountTrackingIDNormalFingerValidator('== 2'),
    530                 NoGapValidator(no_gap_criteria, slot=1),
    531                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
    532                 ReportRateValidator(report_rate_criteria, finger=1),
    533                 StationaryFingerValidator(stationary_finger_criteria, slot=0),
    534             ),
    535         ),
    536 
    537         ONE_FINGER_SWIPE:
    538         Gesture(
    539             name=ONE_FINGER_SWIPE,
    540             variations=(GV.BLTR, GV.TRBL),
    541             prompt='Use ONE finger to quickly swipe {0}.',
    542             subprompt={
    543                 GV.BLTR: ('from the bottom left to the top right',),
    544                 GV.TRBL: ('from the top right to the bottom left',),
    545             },
    546             validators=(
    547                 CountPacketsValidator(count_packets_criteria, slot=0),
    548                 CountTrackingIDNormalFingerValidator('== 1'),
    549                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    550                 ReportRateValidator(report_rate_criteria),
    551             ),
    552         ),
    553 
    554         TWO_FINGER_SWIPE:
    555         Gesture(
    556             name=TWO_FINGER_SWIPE,
    557             variations=(GV.TB, GV.BT),
    558             prompt='Use TWO fingers to quickly swipe {0}.',
    559             subprompt={
    560                 GV.TB: ('from top to bottom',),
    561                 GV.BT: ('from bottom to top',),
    562             },
    563             validators=(
    564                 CountPacketsValidator(count_packets_criteria, slot=0),
    565                 CountPacketsValidator(count_packets_criteria, slot=1),
    566                 CountTrackingIDNormalFingerValidator('== 2'),
    567                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    568                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
    569                 ReportRateValidator(report_rate_criteria),
    570             ),
    571         ),
    572 
    573         PINCH_TO_ZOOM:
    574         Gesture(
    575             name=PINCH_TO_ZOOM,
    576             variations=(GV.ZOOM_IN, GV.ZOOM_OUT),
    577             prompt='Using two fingers, preform a "{0}" pinch by bringing'
    578                    'your fingers {1}.',
    579             subprompt={
    580                 GV.ZOOM_IN: ('zoom in', 'farther apart'),
    581                 GV.ZOOM_OUT: ('zoom out', 'closer together'),
    582             },
    583             validators=(
    584                 CountTrackingIDNormalFingerValidator('== 2'),
    585                 PinchValidator(pinch_criteria),
    586                 ReportRateValidator(report_rate_criteria),
    587             ),
    588         ),
    589 
    590         ONE_FINGER_TAP:
    591         Gesture(
    592             name=ONE_FINGER_TAP,
    593             variations=(GV.TL, GV.TR, GV.BL, GV.BR, GV.TS, GV.BS, GV.LS, GV.RS,
    594                         GV.CENTER),
    595             prompt='Use one finger to tap on the {0} of the touch surface.',
    596             subprompt={
    597                 GV.TL: ('top left corner',),
    598                 GV.TR: ('top right corner',),
    599                 GV.BL: ('bottom left corner',),
    600                 GV.BR: ('bottom right corner',),
    601                 GV.TS: ('top edge',),
    602                 GV.BS: ('bottom side',),
    603                 GV.LS: ('left hand side',),
    604                 GV.RS: ('right hand side',),
    605                 GV.CENTER: ('center',),
    606             },
    607             validators=(
    608                 CountTrackingIDNormalFingerValidator('== 1'),
    609                 StationaryTapValidator(stationary_tap_criteria, slot=0),
    610             ),
    611         ),
    612 
    613         TWO_FINGER_TAP:
    614         Gesture(
    615             name=TWO_FINGER_TAP,
    616             variations=(GV.HORIZONTAL, GV.VERTICAL, GV.DIAGONAL),
    617             prompt='Use two fingers aligned {0} to tap the center of the '
    618                    'touch surface.',
    619             subprompt={
    620                 GV.HORIZONTAL: ('horizontally',),
    621                 GV.VERTICAL: ('vertically',),
    622                 GV.DIAGONAL: ('diagonally',),
    623             },
    624             validators=(
    625                 CountTrackingIDNormalFingerValidator('== 2'),
    626                 StationaryTapValidator(stationary_tap_criteria, slot=0),
    627                 StationaryTapValidator(stationary_tap_criteria, slot=1),
    628             ),
    629         ),
    630 
    631         ONE_FINGER_PHYSICAL_CLICK:
    632         Gesture(
    633             name=ONE_FINGER_PHYSICAL_CLICK,
    634             variations=(GV.CENTER, GV.BL, GV.BS, GV.BR),
    635             prompt='Use one finger to physically click the {0} of the '
    636                    'touch surface.',
    637             subprompt={
    638                 GV.CENTER: ('center',),
    639                 GV.BL: ('bottom left corner',),
    640                 GV.BS: ('bottom side',),
    641                 GV.BR: ('bottom right corner',),
    642             },
    643             validators=(
    644                 CountTrackingIDNormalFingerValidator('== 1'),
    645                 PhysicalClickValidator('== 1', fingers=1),
    646                 StationaryTapValidator(stationary_tap_criteria, slot=0),
    647             ),
    648         ),
    649 
    650         TWO_FINGER_PHYSICAL_CLICK:
    651         Gesture(
    652             name=TWO_FINGER_PHYSICAL_CLICK,
    653             variations=None,
    654             prompt='Use two fingers physically click the center of the '
    655                    'touch surface.',
    656             subprompt=None,
    657             validators=(
    658                 CountTrackingIDNormalFingerValidator('== 2'),
    659                 PhysicalClickValidator('== 1', fingers=2),
    660                 StationaryTapValidator(stationary_tap_criteria, slot=0),
    661                 StationaryTapValidator(stationary_tap_criteria, slot=1),
    662             ),
    663         ),
    664 
    665         THREE_FINGER_PHYSICAL_CLICK:
    666         Gesture(
    667             name=THREE_FINGER_PHYSICAL_CLICK,
    668             variations=None,
    669             prompt='Use three fingers to physically click '
    670                    'the center of the touch surface.',
    671             subprompt=None,
    672             validators=(
    673                 CountTrackingIDNormalFingerValidator('== 3'),
    674                 PhysicalClickValidator('== 1', fingers=3),
    675             ),
    676         ),
    677 
    678         FOUR_FINGER_PHYSICAL_CLICK:
    679         Gesture(
    680             name=FOUR_FINGER_PHYSICAL_CLICK,
    681             variations=None,
    682             prompt='Use four fingers to physically click '
    683                    'the center of the touch surface.',
    684             subprompt=None,
    685             validators=(
    686                 CountTrackingIDNormalFingerValidator('== 4'),
    687                 PhysicalClickValidator('== 1', fingers=4),
    688             ),
    689         ),
    690 
    691         FIVE_FINGER_PHYSICAL_CLICK:
    692         Gesture(
    693             name=FIVE_FINGER_PHYSICAL_CLICK,
    694             variations=None,
    695             prompt='Use five fingers to physically click '
    696                    'the center of the touch surface.',
    697             subprompt=None,
    698             validators=(
    699                 CountTrackingIDNormalFingerValidator('== 5'),
    700                 PhysicalClickValidator('== 1', fingers=5),
    701             ),
    702         ),
    703 
    704         STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS:
    705         Gesture(
    706             name=STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
    707             variations=(GV.AROUND,),
    708             prompt='Place your one stationary finger in the middle of the '
    709                    'touch surface, and use a second finger to tap '
    710                    'all around it many times (50)',
    711             subprompt=None,
    712             validators=(
    713                 CountTrackingIDNormalFingerValidator('>= 25'),
    714                 StationaryFingerValidator(stationary_finger_criteria, slot=0),
    715             ),
    716         ),
    717 
    718         FAT_FINGER_MOVE_WITH_RESTING_FINGER:
    719         Gesture(
    720             name=FAT_FINGER_MOVE_WITH_RESTING_FINGER,
    721             variations=(GV.LR, GV.RL, GV.TB, GV.BT),
    722             prompt='With a stationary finger on the {0} of the touch surface, '
    723                    'draw a straight line with a FAT finger {1} {2} it.',
    724             subprompt={
    725                 GV.LR: ('center', 'from left to right', 'below'),
    726                 GV.RL: ('bottom edge', 'from right to left', 'above'),
    727                 GV.TB: ('center', 'from top to bottom', 'on the right to'),
    728                 GV.BT: ('center', 'from bottom to top', 'on the left to'),
    729             },
    730             validators=(
    731                 CountTrackingIDFatFingerValidator('== 2'),
    732                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    733                                             finger=1, segments=VAL.MIDDLE),
    734                 NoGapValidator(no_gap_criteria, slot=1),
    735                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
    736                 ReportRateValidator(report_rate_criteria, finger=1),
    737                 StationaryFingerValidator(stationary_finger_criteria, slot=0),
    738             ),
    739         ),
    740 
    741         DRAG_EDGE_THUMB:
    742         Gesture(
    743             name=DRAG_EDGE_THUMB,
    744             variations=(GV.LR, GV.RL, GV.TB, GV.BT),
    745             prompt='Drag the edge of your thumb {0} in a straight line '
    746                    'across the touch surface',
    747             subprompt={
    748                 GV.LR: ('horizontally from left to right',),
    749                 GV.RL: ('horizontally from right to left',),
    750                 GV.TB: ('vertically from top to bottom',),
    751                 GV.BT: ('vertically from bottom to top',),
    752             },
    753             validators=(
    754                 CountTrackingIDFatFingerValidator('== 1'),
    755                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    756                                             finger=0, segments=VAL.MIDDLE),
    757                 NoGapValidator(no_gap_criteria, slot=0),
    758                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    759                 ReportRateValidator(report_rate_criteria),
    760             ),
    761         ),
    762 
    763         TWO_CLOSE_FINGERS_TRACKING:
    764         Gesture(
    765             name=TWO_CLOSE_FINGERS_TRACKING,
    766             variations=(GV.LR, GV.TB, GV.TLBR),
    767             prompt='With two fingers close together (lightly touching each '
    768                    'other) in a two finger scrolling gesture, draw a {0} '
    769                    'line {1}.',
    770             subprompt={
    771                 GV.LR: ('horizontal', 'from left to right',),
    772                 GV.TB: ('vertical', 'from top to bottom',),
    773                 GV.TLBR: ('diagonal', 'from the top left to the bottom right',),
    774             },
    775             validators=(
    776                 CountTrackingIDFatFingerValidator('== 2'),
    777                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    778                                             finger=0, segments=VAL.MIDDLE),
    779                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    780                                             finger=1, segments=VAL.MIDDLE),
    781                 NoGapValidator(no_gap_criteria, slot=0),
    782                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    783                 ReportRateValidator(report_rate_criteria),
    784             ),
    785         ),
    786 
    787         RESTING_FINGER_PLUS_2ND_FINGER_MOVE:
    788         Gesture(
    789             name=RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
    790             variations=((GV.TLBR, GV.BRTL),
    791                         (GV.SLOW,),
    792             ),
    793             prompt='With a stationary finger in the bottom left corner, take '
    794                    '{1} to draw a straight line {0} with a second finger.',
    795             subprompt={
    796                 GV.TLBR: ('from the top left to the bottom right',),
    797                 GV.BRTL: ('from the bottom right to the top left',),
    798                 GV.SLOW: ('3 seconds',),
    799             },
    800             validators=(
    801                 CountTrackingIDNormalFingerValidator('== 2'),
    802                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    803                                             finger=1, segments=VAL.MIDDLE),
    804                 NoGapValidator(no_gap_criteria, slot=1),
    805                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
    806                 ReportRateValidator(report_rate_criteria, finger=1),
    807                 StationaryFingerValidator(stationary_finger_criteria, slot=0),
    808             ),
    809         ),
    810 
    811         TWO_FAT_FINGERS_TRACKING:
    812         Gesture(
    813             name=TWO_FAT_FINGERS_TRACKING,
    814             variations=(GV.LR, GV.RL),
    815             prompt='Use two FAT fingers separated by about 1cm to draw '
    816                    'a straight line {0}.',
    817             subprompt={
    818                 GV.LR: ('from left to right',),
    819                 GV.RL: ('from right to left',),
    820             },
    821             validators=(
    822                 CountTrackingIDFatFingerValidator('== 2'),
    823                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    824                                             finger=0, segments=VAL.MIDDLE),
    825                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    826                                             finger=1, segments=VAL.MIDDLE),
    827                 NoGapValidator(no_gap_criteria, slot=0),
    828                 NoGapValidator(no_gap_criteria, slot=1),
    829                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    830                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
    831                 ReportRateValidator(report_rate_criteria),
    832             ),
    833         ),
    834 
    835         FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS:
    836         Gesture(
    837             name=FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
    838             variations=(GV.TLBR, GV.BRTL),
    839             prompt='While drawing a straight line {0} slowly (~3 seconds), '
    840                    'tap the bottom left corner with a second finger '
    841                    'gently 3 times.',
    842             subprompt={
    843                 GV.TLBR: ('from top left to bottom right',),
    844                 GV.BRTL: ('from bottom right to top left',),
    845             },
    846             validators=(
    847                 CountTrackingIDNormalFingerValidator('== 4'),
    848                 LinearityFatFingerValidator(relaxed_linearity_criteria,
    849                                             finger=0, segments=VAL.MIDDLE),
    850                 NoGapValidator(no_gap_criteria, slot=0),
    851                 NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
    852                 ReportRateValidator(report_rate_criteria),
    853             ),
    854         ),
    855 
    856         DRUMROLL:
    857         Gesture(
    858             name=DRUMROLL,
    859             variations=(GV.FAST, ),
    860             prompt='Use the index and middle finger of one hand to make a '
    861                    '"drum roll" {0} by alternately tapping each finger '
    862                    'for 5 seconds.',
    863             subprompt={
    864                 GV.FAST: ('as fast as possible',),
    865             },
    866             validators=(
    867                 CountTrackingIDNormalFingerValidator('>= 5'),
    868                 DrumrollValidator(drumroll_criteria),
    869             ),
    870             timeout = 2000,
    871         ),
    872 
    873         RAPID_TAPS:
    874         Gesture(
    875             name=RAPID_TAPS,
    876             variations=(GV.TL, GV.BR, GV.CENTER),
    877             prompt='Tap the {0} of the touch surface 20 times quickly',
    878             subprompt={
    879                 GV.TL: ('top left corner',),
    880                 GV.TS: ('top edge',),
    881                 GV.TR: ('top right corner',),
    882                 GV.LS: ('left edge',),
    883                 GV.CENTER: ('center',),
    884                 GV.RS: ('right edge',),
    885                 GV.BL: ('bottom left corner',),
    886                 GV.BS: ('bottom edge',),
    887                 GV.BR: ('bottom right corner',),
    888             },
    889             validators=(
    890                 CountTrackingIDNormalFingerValidator('== 20'),
    891             ),
    892             timeout = 2000,
    893         ),
    894 
    895         ONE_FINGER_TRACKING_FROM_CENTER:
    896         Gesture(
    897             name=ONE_FINGER_TRACKING_FROM_CENTER,
    898             variations=((GV.CR, GV.CT, GV.CUL, GV.CLL),
    899                         (GV.SLOW, GV.NORMAL),
    900             ),
    901             prompt='Place a stationary finger on the center of the touch '
    902                    'surface for about 1 second, and then take {2} to draw a '
    903                    '{0} line {1}.',
    904             subprompt={
    905                 GV.CR: ('horizontal', 'to the right',),
    906                 GV.CT: ('vertical', 'to the top',),
    907                 GV.CUL: ('diagonal', 'to the upper left',),
    908                 GV.CLL: ('diagonal', 'to the lower left',),
    909                 GV.SLOW: ('2 seconds',),
    910                 GV.NORMAL: ('1 second',),
    911             },
    912             validators=(
    913                 HysteresisValidator(hysteresis_criteria, finger=0),
    914             ),
    915         ),
    916 
    917         DRAG_LATENCY:
    918         Gesture(
    919             name=DRAG_LATENCY,
    920             variations=None,
    921             prompt='Run one finger back and forth across the pad making sure '
    922                    'to break the laser completely on each pass.  Make at least '
    923                    'twenty passes.',
    924             subprompt=None,
    925             validators=(
    926                 CountTrackingIDNormalFingerValidator('== 1'),
    927                 DragLatencyValidator(drag_latency_criteria),
    928             ),
    929         ),
    930 
    931         PRESSURE_CALIBRATION:
    932         Gesture(
    933             name=PRESSURE_CALIBRATION,
    934             variations=(GV.SIZE0, GV.SIZE1, GV.SIZE2, GV.SIZE3, GV.SIZE4,
    935                         GV.SIZE5, GV.SIZE6, ),
    936             prompt='Draw circles continuously for 5 seconds '
    937                    'using the metal finger of size {0}.',
    938             subprompt={
    939                 GV.SIZE0: ('0 (the smallest size)',),
    940                 GV.SIZE1: ('1',),
    941                 GV.SIZE2: ('2',),
    942                 GV.SIZE3: ('3',),
    943                 GV.SIZE4: ('4',),
    944                 GV.SIZE5: ('5',),
    945                 GV.SIZE6: ('6 (the largest size)',),
    946             },
    947             validators=(
    948                 CountTrackingIDNormalFingerValidator('== 1'),
    949             ),
    950         ),
    951     }
    952     return gesture_dict
    953 
    954 
    955 class FileName:
    956     """A dummy class to hold the attributes in a test file name."""
    957     pass
    958 filename = FileName()
    959 filename.sep = '-'
    960 filename.ext = 'dat'
    961 
    962 
    963 class Gesture:
    964     """A class defines the structure of Gesture."""
    965     # define the default timeout (in milli-seconds) when performing a gesture.
    966     # A gesture is considered done when finger is lifted for this time interval.
    967     TIMEOUT = int(1000/80*10)
    968 
    969     def __init__(self, name=None, variations=None, prompt=None, subprompt=None,
    970                  validators=None, timeout=TIMEOUT):
    971         self.name = name
    972         self.variations = variations
    973         self.prompt = prompt
    974         self.subprompt = subprompt
    975         self.validators = validators
    976         self.timeout = timeout
    977