
This directory contains an extension for the motor module.  To use this
extension call (require-extra "extended-motor-actions"), and placing that
call into any model which needs this extension will ensure it gets 
loaded.  Alternatively one can load the motor-extension.lisp file after 
loading the main ACT-R load file, or place that file into the modules 
directory of the actr7 hierarchy so that it gets compiled and loaded 
automatically.

This extension combines a few extensions which have been written for the
motor module together in one file.  It replaces the default motor module
with an updated version which has more capabilities, but the default 
operation of the extended module should not change how existing models
work.  However, there will be some differences in the trace output with 
how the manual request trace events are displayed and the addition of a
new release-key event following every output-key.

Here are the changes introduced with the extensions:

- The model now generates actions for both pressing and releasing keys which 
can be detected by the modeler.  The actions from the existing module 
(punch, peck, peck-recall, and press-key) all now result in both a press 
and release of the key/button.   This extension updates the default
virtual keyboard and mouse devices to now also generate signals for
the release actions.  The keyboard generates a release-key signal with the
same parameters as output-key: model and key, and the mouse generates a
release-mouse signal with the same parameters as click-mouse: model, mouse
position, and finger. Those new signals are only generated for model actions
because the visible virtual window extension for human interaction has
not been updated to provide them.


- The model is now able to hold keys down and new requests related to holding 
and releasing keys are described below.  If the model requests an action
which uses a finger which is currently being held down then there's an extra 
burst-time cost to execute the release of that key before performing the
requested action. 


- The motor module now has the option of using separate execution and/or 
processor stages for the two hands which allows motor actions on different 
hands to potentially operate in parallel.  There is still only one preparation
stage however.  The default operation of the new module is for one execution
stage and one processor stage (like the default motor module), but that can 
be changed with parameters as described below.


- The trace of the motor actions for preparing, initiating, and finishing an
action now indicate which action and hand it corresponds to since there may
be parallel actions ongoing. 


- There are more high-level actions like press-key which perform operations
given a key.  Details on the new actions are found below.


- There is a new module created, named motor-extension, which adds two new
buffers, manual-left and manual-right.  These can be used for tracking the 
operation of the model's hands separately and also allows for querying 
whether individual fingers are currently busy i.e. holding down a key.
These can be used to track separate hand activity for BOLD activation
traces, but when doing so two processor and two execution stages will 
need to be enabled to avoid seeing preparation shared between them (since
preparation engages the processor stage).

- Cursor 'drag' actions (those made while holding down a finger on the
  same hand) can be slowed down relative to non-drag actions.

Here are more details on the new parameters, buffers, signals, and requests.
 

release-key (model key)

This signal will be generated by the updated keyboard when a key which was
pressed is released.  All release-key signals will be preceded by a call to
output-key for that key.  However there may not always be a call to release-
key for every output-key because the model may be reset or otherwise stopped
or cleared before the release action occurs.

release-mouse (model position finger)

This signal will be generated by the updated mouse cursor when a button
on the mouse is released.  Like the release-key signal for the keyboard,
there will always be a preceding click-mouse call, but every click-mouse
may not have a corresponding release-mouse.


New model parameters available:

:key-release-time (default value .04)

The time in seconds between when the action which is releasing a key is started
and when that key actually registers as being released.  Used in the timing of
all the actions which include a releasing of a key.  The assumption is that there
is some distance over which the finger must be moved before the key stops being
pressed.  All of the release actions are based on a burst-time cost, thus this
parameter should be set to a value no greater than the value of the :motor-burst-time
parameter.  

NOTE: This parameter and the existing :key-closure-time parameter should really 
be modeled as a distance instead of a time cost, but since the motor movement 
isn't modeled at that level (fingers are only positioned on a plane not in 
actual 3-space) a simple cost assumption is used.

:dual-processor-stages (default value nil)

A boolean indicating whether the motor module should use separate processor
stages for each hand.

:dual-execution-stages (default value nil)

A boolean indicating whether the motor module should use separate execution
stages for each hand.

:peck-strike-distance (default 0.0)

The distance from the center of a key at which a peck action is considered
to make contact with the key and start depressing it.  The value can be
from 0 to .5 (the width of a key is 1.0 and movement is computed from 
center of key to center of key thus the finger movement crosses a distance of
about half of the target key when striking it depending upon the angle).  This
affects when the output-key action occurs.  

The default motor module assumes that peck sytle actions occur after the entire 
movement completes and ignore the key closure time parameter for peck actions.

If this parameter is set to nil then that default behavior will occur.

If it is set to a non-nil value then the peck and peck-recoil actions
will generate the output-key action at the time: ct + t(d - psd) where
ct is the key-closure-time, t(x) is the time along a minimum jerk velocity
profile for the whole movement at which the distance is x, d is the
length of the whole movement and psd is the value of :peck-strike-distance.

Thus, with the default value of 0 the output-key action will be key-closure-time
later than it would be with the default motor module timing, and values
larger than 0 will decrease that time.


:default-punch-delay (.075s default)

This is the delay time for a delayed-punch action when the model doesn't 
specify a delay.

:fast-punch-delay (.05s default)

This is the delay time for a delayed-punch action when the model specifies
a delay of fast.

:slow-punch-delay (.1s default)

This is the delay time for a delayed-punch action when the model specifies
a delay of slow.

:cursor-drag-delay (nil default)

Indicates whether to slow down cursor drag actions, and if so by how much.
If set to t or a number then that number is added to the control order
value of the cursor before calculating the time with Fitts' Law.  A value
of t sets it to .8 which provides a reasonable match to data from this paper:

I. Scott MacKenzie, Abigail Sellen, and William A. S. Buxton. 1991. 
A comparison of input devices in element pointing and dragging tasks.
In Proceedings of the SIGCHI Conference on Human Factors in 
Computing Systems (CHI '91), Scott P. Robertson, Gary M. Olson,
and Judith S. Olson (Eds.). ACM, New York, NY, USA, 161-166. 
DOI: http://dx.doi.org/10.1145/108844.108868 




New Buffers for tracking hands: 

manual-left and manual-right

These buffers allow for the same queries as the manual buffer except for
the preparation query which they do not provide.  The processor and execution
queries of these buffers are busy if that stage of the specified hand is busy
(or if either hand is when there aren't separate stages).  The state is busy
if either the processor or execution stage is busy.

Each also adds additional queries for the fingers on that hand.  A finger
query is busy if the finger is holding a key or mouse button down or 
performing an action which affects the state of a key or mouse button being 
held down, and free otherwise.  Note however, that because it is possible
for actions to be queued for exeution, just because a finger reports as
down does not mean that it will still be down at the time an action requested
to occur actually executes i.e. the finger could be being held down, but 
there could already be an action queued that will release it before a new
request will be executed.

Here is the output of the buffer-status call for the manual-left buffer for
reference:

MANUAL-LEFT:
  buffer empty          : T
  buffer full           : NIL
  buffer failure        : NIL
  buffer requested      : NIL
  buffer unrequested    : NIL
  state free            : T
  state busy            : NIL
  state error           : NIL
  processor free        : T
  processor busy        : NIL
  execution free        : T
  execution busy        : NIL
  last-command          : NONE
  index  free           : T
  index  down           : NIL
  middle free           : T
  middle down           : NIL
  ring   free           : T
  ring   down           : NIL
  pinkie free           : T
  pinkie down           : NIL
  thumb  free           : T
  thumb  down           : NIL

Neither buffer does anything with requests which it receives nor are there any 
chunks placed into either one.



New request actions for the manual buffer.

Here are low-level actions for directly manipulating the fingers:

cmd hold-punch
 hand [left | right]
 finger [index | middle | ring | pinkie | thumb]

Press and hold down the indicated finger.  If the finger
is already being held down then first release it and press
it again.


cmd hold-peck
 hand [left | right]
 finger [index | middle | ring | pinkie | thumb]
 r distance
 theta direction

Move the finger based on the distance and direction and hold it 
down at that location.  If the finger is currently being held 
down then first release it and then perform this movement.


cmd release
 hand [left | right]
 finger [index | middle | ring | pinkie | thumb]

Release the indicated finger from being held down leaving that finger
at the same location.  If the finger is not being held down do nothing and
output a warning.


cmd release-recoil
 hand [left | right]
 finger [index | middle | ring | pinkie | thumb]
 r distance
 theta direction

Release the indicated finger from being held down and then move
it the indicated distance and direction without pressing down at
that location.  If the finger is not being held down do nothing and
output a warning.

cmd release-all-fingers

Release all fingers which are currently being held down.  The execution
cost of the action is two burst-times (default of 50ms) with the release
happening during the first burst-time (assuming the key release time is
less than burst-time).  Will delay if preparation is not free until 
preparation is free (should guarantee that it's alway the next action),
but not recommended to rely upon that.  Will check if any fingers are 
down and only executes if there is, and only requires execution of a
hand if it has fingers down.

cmd point-finger
 hand [left | right]
 finger [index | middle | ring | pinkie | thumb]
 r distance
 theta direction

Move the finger based on the distance and direction without pressing
down at the target location.  If the finger is currently being held 
down the release it before performing this movement.


cmd delayed-punch
 hand [ left | right ]
 finger [ index | middle | ring | pinkie | thumb ]
 {delay [ fast | slow | # ] }

Press down and then release the indicated finger in its current
location.  The release will occur delay seconds after the press
if delay is provided as a number.  If delay is not provided then 
the default delay time is used.  If delay is either fast or slow, 
then the value is taken from the corresponding parameter.  If
:randomize-time is enabled then the delay will be randomized.
If the finger is currently being held down it is released before
performing this action.  This does not depend on the key-release-time
and assumes that is already accounted for in the delay given.



Here are new high-level actions that will generate the corresponding 
low-level movement necessary.


cmd type-key
 key key

Move the appropriate finger to the indicated key, press and release it.  The
finger is moved from where it currently is (unlike press-key which assumes
it's on the home position) and returns to where it was after striking the key
(which may not be the home row position).
If the finger is currently being held down it is released before
performing this action.


cmd hit-key
 key key

Move the appropriate finger to the key and press and release it.  The
finger is moved from where it currently is and stays over the key which is hit.
If the finger is currently being held down it is released before
performing this action.


cmd hold-key
 key key

Move the appropriate finger to the key and press it keeping it held down.  The
finger is moved from where it currently is.
If the finger is currently being held down it is released before
performing this action.


cmd release-key
 key key

If the appropriate finger for that key is currently holding it down release it
and leave the finger at that position.  If the finger is not holding down that
key print a warning and do nothing.


cmd release-key-to-home
 key key

If the appropriate finger for that key is currently holding it down release it
and move the finger back to its home position without striking the corresponding
home key.  If the finger is not holding down that key print a warning and do nothing.


cmd move-to-key
 key key

Move the appropriate finger to that key without pressing it.  The finger is moved
from where it currently is.
If the finger is currently being held down it is released before
performing this action.


cmd move-finger-to-home
 hand [left | right]
 finger [index | middle | ring | pinkie | thumb]

Move the specified finger to its home position without pressing it.  If the finger
is currently holding a key down release it before moving.  If the finger is already
at the home position do nothing and print a warning.


cmd all-fingers-to-home
 {hand [left | right]}

Move all fingers on the specified hand, or both hands if no hand specified,
to their home positions.  Like move-finger-to-home any finger which is holding
a key will be released first.  If all the fingers are on the home positions
do nothing and print a warning.  This action has a cost of the max of 200ms 
and the time for each of the involved hands to do the necessary hand-ply
(plus the initilization cost and a burst cost to finish).


cmd hold-mouse

Execute a hold-punch with the right index finger to depress the mouse button.
If the hand is not located on the mouse print a warning and do nothing.


cmd release-mouse

Release the right index finger to release the mouse button.  If the 
finger is not holding the button down or the hand is not located on the
mouse do nothing and print a warning.
