\documentstyle[12pt,final,twoside,times,sfheads]{rccldoc}
\begin{document}
\tolerance=1000
\pagenumbering{roman}
\title{RCI User's Guide}
\author{John Lloyd}

\date{July 1992}
\maketitle
\parskip = 2ptplus3pt

\begin{abstract}
This document is meant to provide an informal introduction to the RCI
real-time control environment. It is meant to be somewhat tutorial in nature.
Due to time limitations, the treatment of some of the material is briefer than
it should be.

\par\vfill
\copyrightNotice
\end{abstract}
\newpage

\tableofcontents
\newpage
\pagenumbering{arabic}

\chapter{Introduction}

RCI is a package for creating real time control processes 
attached to a parent UNIX process. It includes primitives for
creating the tasks, scheduling them, and communicating with them using
either shared memory or message passing.

The control tasks are created on either an auxiliary CPU that resides on the
same backplane as the UNIX CPU (also known as the {\it arbiter} CPU), 
or, if the necessary support has been configured into the UNIX kernel, on the
UNIX CPU itself. The tasks use the 
same code image as the main UNIX program, which is demand-loaded into the 
various auxiliary CPUs. The effect is that the real-time tasks
appear to execute as high priority ``background'' routines belonging
to the same RCI program.

The control tasks generally do not have access to the usual UNIX system calls
(see section \ref{restrict.sec}).
Communication with the ``outside world'' is accomplished through special RCI
primitives. There are also a few RCI routines for doing things such as
checking bus addresses, printing to the CPU console line, and getting the
system time.

When an RCI task is run on an auxiliary CPU, only those portions
of the image required to support the real time control tasks are loaded 
into the CPU. 
Alternatively, when a task is run on the arbiter CPU, 
then the ``real-time'' part of the image is locked into main memory so that it
will be 
available at task execution time without having to be paged in. This means
that the RCI library has to be able to locate, at run-time, the code and data
segments used by the control tasks. To facilitate this, those parts of a 
user's program that constitute the control task need to be be written as
separate modules which are compiled and loaded so as to appear at known
locations in 
the image. A special front end to the C compiler, known as the
{\tt rcc} command, is provided to allow the user to do this with a minimum of
effort. RCI programs are compiled and loaded with the {\tt rcc} command
analogously to the way non-RCI programs are compiled and loaded with the {\tt
cc} command. 

The set of RCI real-time tasks are referred to in this document as the {\it
control} level, while the main UNIX program which creates and controls them 
is referred to as either the UNIX level, or the {\tt planning} task.
For simplicity, control of the program is centralized in the planning task.
In general, primitives which create or control RCI tasks may only be called 
from the planning level, while primitives which simply obtain information
about tasks may be called from anywhere. When in doubt, the reference manual
should be consulted for the routine in question.

RCI was originally implemented to help provide real-time control
on MicroVAX and Sun4 systems, which have very poor intrinsic facilities
for this. On these systems, RCI operates with the help of
special kernel modifications. Systems on which RCI has since been
implemented, such as SGI IRIX and VxWorks, provide sufficient real-time
support without kernel modification. In these cases, RCI is technically
unnecessary, although it is still useful for code portability.

The only system on which auxiliary CPUs are supported is the
MicroVAX-II. On all other systems, only RCI tasks on the UNIX
CPU are supported. The term ``UNIX'' in this document more
accurately means ``host operating system'' (as in the case 
with VxWorks).

\chapter{Preliminaries}

RCI makes use of a few basic definitions defined in the file 
{\filefont h/cdefs.h}. These definitions include:
\begin{verbatim}
        #define NULL    0
        #define NULLF   (int(*)())0

        #define YES     1
        #define NO      0
        #define UNDEF   -1
\end{verbatim}

{\tt NULL} is a ``generic'' null, and
{\tt NULLF} is a null pointer to a function returning {\tt int}. Three 
logical value states are defined by {\tt YES}, {\tt NO}, and {\tt UNDEF}.

All of the RCI functions, and many of the data structures,
described in this manual are documented in detail in the RCI reference 
manual. The reference manual is on line, and individual entries can be
accessed using the {\tt man} command. For instance, to find specific
information about the {\tt rciCreate()} call, one may do
\begin{verbatim}
        man rciCreate
\end{verbatim}

Access to the RCI manual pages is dependent on the user setting
the environment variable {\tt MANPATH} (see {\tt man man}) 
to include the directory {\filefont \$RCCL/man}.

\chapter{Task Creation}\label{create}

We shall begin right away by presenting a program that creates a control task.
\subsubsection*{File main.c:}
\begin{verbatim}
   #include <rci.h>

   extern sayHello();

   main()
   {
        RCI_DESC *td;

        td = rciCreate ("task1", 0x2);
        rciExecute (td, sayHello, 1234);
        rciClose();
   }
\end{verbatim}

\subsubsection*{File control.c:}
\begin{verbatim}
   #include <rci.h>

   sayHello (td, arg)
   RCI_DESC *td;
   int arg;
   {
        rciPrintf ("Hello world (%d)\n", arg)
   } 
\end{verbatim}

This sample program contains two modules, one for the UNIX level, and
one for the RCI control level. It can be compiled with
the command:
\begin{verbatim}
        rcc main.c CTRL control.c
\end{verbatim}

Modules referenced by the control level must appear to the right of the {\tt
CTRL} keyword, while modules referenced by only the
UNIX level modules may be placed on the left. By default, the {\tt rcc}
command references the appropriate RCI libraries (see {\tt man rcc}), and,
contrary to the {\tt cc} command,
will name the resulting image file after the first module specified
(in this case, {\tt main}).
Apart from these features and a couple of others, {\tt rcc} 
functions identically to the {\tt cc} command. Modules may be compiled
separately, as in the following command sequence:
\begin{verbatim}
        rcc -c main.c
        rcc -c CTRL control.c
        rcc main.o CTRL control.o
\end{verbatim}
Note that {\tt control.c} is placed to the right of the {\tt CTRL} keyword
when it is compiled separately.
Technically speaking, {\tt rcc} is necessary only to load the final image 
and compile the control level components; the UNIX modules ({\tt main.o}
above) can be precompiled with {\tt cc}.

When run, the program creates an RCI task by calling the primitive {\tt
rciCreate()} from the planning level.
The first
argument is the task name, and the second argument is a bitmask
describing the set of candidate CPUs on which the task may be created.
The arbiter CPU is defined to be CPU 0 (corresponding to a mask value of 0x1).
RCI will attempt to assign the task to an auxiliary CPU first, if one
has been selected and is available. Under the
current implementation, an auxiliary CPU may be used by only one
RCI program at a time. 
If it is busy (i.e., already allocated to another RCI program), 
or is otherwise not available, RCI will attempt to create the task on another
CPU specified in the mask. The arbiter CPU, if it contains the required kernel
support to run RCI
tasks, is generally always available, since it may be used
by more than one RCI program. In the sample program, the task is created on
CPU 1.

Once the task is created, {\tt rciCreate()} returns 
a pointer to a task descriptor ({\tt td}), 
which is the handle used to obtain information about the task
and describe it to various controlling primitives.
{\tt rciCreate()} returns {\tt NULL} if it
was unable to create the task.

One particular data structure that may be obtained from the task descriptor
is the task control block (TCB, data type {\tt RCI\_TCB}), 
which may be obtained with the
macro {\tt TASKTCB(td)}. This structure contains information concerning
task scheduling and execution, such as the number of control cycles the
task has executed and the control functions which define the task, as well
as a few data ``registers'' available for application use. Many of the fields
in the task control block are parameters which are set by the task controlling
primitives that will be described later; the TCB can be used to reference 
what these values are.
For a complete descriptor of the fields in the TCB that
are visible to the user, see {\tt man RCI\_TCB}.

After the sample program creates the task, it calls upon the
primitive
{\tt rciExecute()} to execute a function
with a specified argument in the context of that task.
The primitive blocks until the execution of the function is complete.
Within the function itself, the 
routine {\tt rciPrintf()} is used to print a message from the
control level. On Sun4 and MicroVAX systems, this message will
go to the console of whatever CPU is running the task.
While {\tt rciPrintf()} accepts a variable argument
format identical to {\tt printf()}, the present implementation restricts the
total number of characters that may be output 
(1024 at the time of this writing).
In the sample program, the message 
\begin{verbatim}
        Hello world (1234)
\end{verbatim}
should appear.

The last thing the program does is call {\tt rciClose()}, which deletes all
RCI tasks and releases all resources that they use. Technically speaking, this
is not necessary at the end of a program (it will be done automatically when
the devices that RCI references are closed by the program exit), but it is
clean. At the moment, there is no primitive to delete a
particular RCI task. This restriction is simply due to the limited time 
which was available to implement the present version. It is not particularly
troublesome since the functions themselves which are executed by a control
task are dynamically configurable.

Other information which may be obtained from the task descriptor {\tt td}
is the number of the CPU on which the task is running (using the
macro {\tt TASKCPU(td)}), and the corresponding bitmask (using {\tt
TASKCPUMASK(td)}). This information is useful, for instance, in creating two
tasks that run on the same CPU, regardless of where the first task was
created, as demonstrated in the following code fragment:
\begin{verbatim}
        td1 = rciCreate ("task1", 0x6);
        td2 = rciCreate ("task2", TASKCPUMASK(td1));
\end{verbatim}
Task 1 may be created on either CPU 1 or 2, while task 2 must be
created on the same CPU as task 1.
If it is known that an RCI program will be later requiring a certain set of
CPUs for task creation, it may wish to reserve these CPUs ahead of time
so that it knows it has them. This can be done with the call
\begin{verbatim}
        mask = rciAllocCpus(reqmask)
\end{verbatim}
where {\tt reqmask} is a bitmask specifying the CPUs to be reserved. The
routine 
returns a mask of the CPUs that it was actually able to allocate. As
described above, it may not be possible to allocate a CPU because either 
it is not
present in the system, or it has been allocated by another RCI task. Once CPUs
are allocated, either with {\tt rciAllocCpus()} or implicitly through
{\tt rciCreate()}, they remain allocated until the program either exits
or calls {\tt rciClose()}.

\chapter{Task Scheduling}

The example program given above did not actually {\it start} 
the RCI task running
independently. To do this, it is necessary to specify a
set of control functions for the task (a {\it startup}, {\it run}, and 
{\it release} function) as well as a scheduling discipline, and then set the
task running with the {\tt rciStart()} primitive.

A program that does this is given below:

\subsubsection*{File main.c:}
\begin{verbatim}
   #include <rci.h>

   extern startupFxn();
   extern controlFxn();
   extern releaseFxn();

   main()
   {
        RCI_DESC *td;

        td = rciCreate ("task1", 0x2);

        rciControlFxns (td, startupFxn, controlFxn, releaseFxn, 1234);
        rciScheduling (td, ON_CLOCK, 0);
        rciRate (td, 1000, 0);
        rciStart (TASKMASK(td));

        printf ("Hit <CR> to terminate:\n");
        while (getchar() != '\n')
           ;
        rciRelease (~0);
        rciClose();
   }
\end{verbatim}

\subsubsection*{File control.c:}
\begin{verbatim}
   #include <rci.h>

   startupFxn(td, arg)
   RCI_DESC *td;
   int arg;
   { 
        rciPrintf ("starting\n");
   }

   controlFxn(td, arg)
   RCI_DESC *td;
   int arg;
   { 
        rciPrintf ("time = %d\n", rciTime());
   }

   releaseFxn(td, arg, code)
   RCI_DESC *td;
   int arg;
   int code;
   { 
        rciPrintf ("releasing\n");
   }
\end{verbatim}

This program creates a task and uses {\tt rciControlFxns()} to
assign it a {\it startup} function, which is called when the task is
later activated, a {\it control} function, which is called repeatly whenever
the
task is woken up, and a {\it release} function, which
is called when the task is released. Any of the these functions may be omitted
by specifying them as {\tt NULLF}. 
Each function is called by RCI with two arguments:
a pointer to the task descriptor of the task itself, and an integer sized
argument, which is specified by the fifth argument
to {\tt rciControlFxns()}. The release function is called with an additional
argument: A condition code describing the reason for the release (either
a call was made to {\tt rciRelease()}, or some sort of error condition
occurred). The code
associated with a normal release request is {\tt RELEASE\_REQ}. Other codes,
associated with error conditions, are discussed in the section on
error handling and recovery.

When an RCI control function is called, it must
run to completion before any function from any other task is permitted to
be executed. In other words, there is only one execution priority level. This
way of doing things, while certainly not ideal for many applications, is
largely the result a requirement that it be possible to run RCI control
tasks on the UNIX CPU.

{\tt rciScheduling()} is used to specify a scheduling discipline
for the task, which determines what will cause the control function
to be executed.
The discipline given in this example is {\tt ON\_CLOCK}, which means that the
task will be executed periodically at the rate given by {\tt rciRate()}. 

{\tt rciRate()} sets the sample rate associated with a task,
in terms of an {\it interval} (second argument) and an {\it offset}
(third argument), where both quantities are given in milliseconds.
The
interval is the length of time between executions, while the offset is a
phase shift which permits the execution of
different tasks running at the same frequency
to be skewed with respect to each other. The sample rate specification is used
directly to control scheduling with the {\tt ON\_CLOCK} and {\tt ON\_TRIGGER}
disciplines (the latter is discussed in the next section). The {\tt interval}
argument is also used
by the RCI watchdog timer (discussed later) as an indication of a task's
expected execution rate.

The sample program next activates the task by calling {\tt rciStart()}, which
takes as an argument a bitmask specifying the tasks to be started, allowing
different tasks to be started at exactly the same time. The bitmask
for a particular task can be obtained by using the macro
{\tt TASKMASK(td)}. Bit masks corresponding to non-existent tasks, or tasks
already activated, are ignored, so that all tasks can be specified
with the construct {\tt \~{}0}.

After the program receives user confirmation, it releases the task with a call
to {\tt rciRelease()}, which, like {\tt rciStart()}, takes a bitmask as
an argument. The use of {\tt \~{}0} to release all the tasks 
is illustrated in the program.

The function {\tt rciTime()}, called by the main control function, returns the
current system time in milliseconds. The system time is initialized to 0 at the
first call to {\tt rciCreate()}.
Running the program should produce an output like the following:
\begin{verbatim}
        starting
        time is 1000
        time is 2000
        time is 3000
             .
             .
             .
        releasing
\end{verbatim}

\chapter{More Task Scheduling}

This section describes the different RCI scheduling disciplines in detail.

In scheduling a task, we generally want to do one of three things:

\medskip
\begin{list}{}{}
\item[1.] 
Wake the task up at a specified point, or set of points, in time;

\item[2.] 
Wake the task up when we discover a certain condition to be true;

\item[3.]
Wake the task up when a specific event or interrupt signals us.
\end{list}
\medskip

Since at this time our hardware does not permit auxiliary 
processors to receive interrupts from external devices, 
we are concerned mostly with the first two scheduling disciplines.
The exception to this occurs in the case of a control task
running on the arbiter CPU, which
both can and must use interrupts in the process of scheduling tasks since it must
share time with UNIX (more will be said about this later).

It is also useful to consider a combination method of scheduling,
where we first wake up an external
device at some system controlled time rate, and then this device
wakes up the task proper (ala method 2).
This permits overlap between the external device's 
``getting ready''
and the execution of some other control task (or 
the tail end of the control task in question).
Scheduling in this way is known as 
{\it triggering}, and will be discussed later on.

\section{Clock Scheduling}

Running an RCI task at a fixed clock rate was described in the
preceding section. To do this, the program should make the following
calls:
\begin{verbatim}
        rciScheduling (td, ON_CLOCK, 0);
        rciRate (td, interval, offset);
\end{verbatim}
(again, the third argument to {\tt rciScheduling()} will be discussed 
in section \ref{polling}).

Once the task has been started, its control function
will be invoked every time
the following relation is true:
\begin{verbatim}
        ((time - offset) % interval) = 0
\end{verbatim}
where {\tt time} is the elapsed time (in milliseconds)
since the task was started.
The control function does not take an active role in its
scheduling. Information about the rate is available to the control task 
as the {\tt interval} and {\tt offset} fields in the task descriptor.

The scheduling discipline must be set when the task is 
{\it idle}, but the rate may be changed at any time. When the rate
is changed, the variable {\tt newRate} is set in the task
descriptor. The control task may then examine the {\tt interval}
and {\tt offset} fields in the task control block (TCB) to determine what the
new rate is. The variable {\tt newRate} is cleared automatically after
one cycle.

\section{Function Scheduling}

With the other scheduling disciplines, the task takes an active
role in its scheduling behavior.

With function scheduling ({\tt ON\_FUNCTION}), 
the task is responsible for providing a
wakeup function which the monitor will poll with to determine when
to wake the task up. The wakeup function should return 
1 if the task is ready to be run and 0 otherwise.
Setting up this sort of scheduling may look like this:
\begin{verbatim}
        rciScheduling (td, ON_FUNCTION, 0);

        ... and from within the task (presumably the startup function) ...

        startupFxn(td)
        RCI_DESC *td;
        {
           if (td->scheduleDisp == ON_FUNCTION)
            { rciWakeupOn (td, wakeupFxn, arg);
            }
           ...
        }
\end{verbatim}

The control task must cooperate with the planning task in setting up
a wakeup function. It can do this by examining the
{\tt scheduleDisp} field in the task control block. The wakeup function 
and argument is specified by the {\tt rciWakeupOn()} call. Though
in principle this call could be made for the task by the planning
level, we discourage it, mainly because if the argument is a
pointer (which turns out to commonly be the case) there is no
guarantee that the pointer will be valid if the planning task and the control 
task occupy different CPUs.

If a wakeup function is not specified, it will simply never be woken up.
The wakeup functions can be changed in mid-flight. The wakeup function
is cleared when the task is released.

\section{Trigger Scheduling}

A combination of the above two disciplines is obtained with the
{\tt ON\_TRIGGER} discipline, mentioned earlier.
Trigger scheduling implies that a trigger function is called
for the task at a specified sample rate, which wakes up an external
device which in turn wakes up the control task itself later on.

As with {\tt ON\_FUNCTION} scheduling, setting up
trigger scheduling requires the cooperation of the control task.
The planning task executes the following sequence.

\begin{verbatim}
        rciScheduling (td, ON_TRIGGER, 0);
        rciRate (td, interval, offset);
\end{verbatim}

When the control task starts up, it then should execute some code that
looks like the following:
\begin{verbatim}
        startupFxn(td)
        { 
           if (td->scheduleDisp == ON_TRIGGER)
            { rciWakeupOn (td, fxn, arg)
              rciSetTrigger (triggerFxn, arg);
            }
        }
\end{verbatim}

The call to {\tt rciWakeupOn()} simply specifies a function that will be
used to activate the main task. {\tt rciSetTrigger()} is a special
call that instructs the task's monitor to schedule the indicated
trigger function at the next time consistent with the tasks rate
information ({\tt interval} and {\tt offset}). Unlike regular task
control, the trigger function can interrupt control functions
belonging to any task (though it cannot interrupt another trigger function).

The trigger must be reset on every subsequent call to the control
task's main function; the trigger will not be called until this
happens. The reason for having to reset the trigger explicitly
is that the trigger function may share resources with the main control
function (e.g., both may access the same I/O device). Consequently, it is
important that the control task be able to control the point
at which the trigger is enabled (at the very end of the control function,
if necessary). 

If the task takes inappropriately long lengths of time to execute,
it may fall behind it's desired schedule. In this case, when
{\tt rciSetTrigger()} is called, the monitor
will determine that the ``time to the next trigger'' will be 
$\le 0$. It that event, the trigger function is simply called right
away ({\tt rciSetTrigger()} degenerates to a fancy subroutine call).

When the task is released, any pending trigger functions should
be disabled with another call to {\tt rciSetTrigger()} containing
a {\tt NULL} function argument:
\begin{verbatim}
        releaseFxn(td)
        { 
            rciSetTrigger (NULLF, 0);

            ... other things a release function does ...
        }
\end{verbatim}
Failure to do this may result in a trigger function being called
after the release.

\section{Timer ASTs}

A convenient extra that we have introduced is the ability for 
RCI control tasks to invoke timer ASTs\footnote
{The terms AST is borrowed from VMS, where it stands for
{\it asynchronous system trap}, and means, pompousity aside,
a software interrupt.}. A control task can set one up in
the following way:
\begin{verbatim}
        RCI_TIMER_AST (time, function, arg);
\end{verbatim}
This can be done by the control task only, since it involves making
requests to the operating system on the task's CPU (though
a timer AST can be set up via an {\tt rciExecute()} call, which 
permits considerable flexibility).
Only one timer AST is permitted per control task. Using the
{\tt RCI\_TIMER\_AST()} call twice simply invalidates the old 
AST. A pending AST can be canceled by specifying an AST 
with a {\tt NULLF} function pointer.

The timer AST mechanism allows a control task to run a little
``mini task'' in the background, which can do very time critical things.
All pending AST's are canceled when the task is released (i.e., none
will be delivered after the task's {\tt release()} function is entered).

\section{The Polling Interrupt}\label{polling}

For a task running with either the {\tt ON\_FUNCTION} or {\tt ON\_TRIGGER}
scheduling disciplines on the arbiter (UNIX) CPU, it is necessary to 
provide a polling interrupt which will interrupt the normal execution
of UNIX and call the RCI monitor function so that the latter may determine if
the task  
is runnable. The polling interrupt is provided by a UNIX device whose driver
is configured to accept some special I/O controls that support RCI, and
in particular allow the RCI monitor function to be called when the device
receives an interrupt. An RCI program should submit an open file descriptor
for this device as the third argument to the {\tt rciScheduling()} call.

If the task in question is not running on the arbiter, and the scheduling
discipline does not require a polling interrupt, then {\tt rciScheduling()}
ignores its third argument.

The polling interrupt does not have to bear any direct relationship to
when the task actually should be woken up, but it is not a bad idea
to have it do so.
For instance, suppose an RCI task is configured with a
wakeup function that returns true when the external device sets a
bit in a parallel port. If the setting of this bit can also
cause an interrupt to be delivered to the arbiter, then this interrupt should
be used as the polling interrupt. A UNIX device driver should be written for
the port that supports the RCI I/O controls.

It should be emphasized that the only purpose of the polling interrupt
is simply to make sure that RCI gets control of the arbiter CPU at
the right time to run any required RCI tasks. No additional functionality
is implied.
One could use as a polling interrupt an interrupt from a real-time clock
that was delivered once every millisecond; this would be application
independent but would restrict the execution time of all associated arbiter
tasks to a 1 millisecond granularity. It would also put a heavy load on the
UNIX CPU.

\section{Default Wakeup Functions}

RCI provides a couple of special purpose routines that may be specified as
wakeup functions. The first of these is {\tt rciOnInterrupt()}, which should
be specified as follows:
\begin{verbatim}
        rciWakeupOn (td, rciOnInterrupt, (int)td)
\end{verbatim}

This wakeup function causes the specified task to be woken up once and only once for
every {\it polling interrupt} it receives. Needless to say, this function is
only of use for tasks which are associated with polling interrupts (which at the
moment is limited to tasks running on the arbiter). It is also possible
to use this function in association with tasks that are run off of UNIX
signals, a feature that is discussed in a later section on simulation.

The second function is {\tt rciTimeReady()}, which is set up as follows:
\begin{verbatim}
        rciWakeupOn (td, rciTimeReady, (int)td)
\end{verbatim}
This causes the function to behave as though it were scheduled using 
the {\tt ON\_CLOCK} discipline -- the function will return true when the system
time is equal to the task execution time computed using the interval and
offset specified by {\tt rciRate()}.

\section{Specifying Timeout Behavior}\label{timeout}

RCI maintains a timeout mechanism by which tasks are aborted if too much time
elapses before they are woken up or if they fall too far behind schedule. The
timeout behavior of a task can be altered with the {\tt rciTimeout()}
command:
\begin{verbatim}
        rciTimeout (td, blockCnt, lagCnt, lagWindow)
\end{verbatim}

{\tt blockCnt} controls the {\it block timeout} -- the length of
time that a task should 
wait for a wakeup before aborting with a {\tt BLK\_TIMEOUT} condition.
{\tt blockCnt} specifies this time in
units of control cycles, where the nominal length of each control cycle is
taken to be the {\it interval} time set by {\tt rciRate()}. If this interval
has not been defined, or {\tt blockCnt} is given as 0, then
block timeouts are disabled. Specifying a negative {\tt blockCnt} causes the
system to use the default value.

{\tt lagCnt} and {\tt lagWindow} control the task's {\it lag timeout},
which causes a timeout to occur if a task falls too far behind schedule.
The RCI task monitor keeps a decaying average, over a window {\tt lagWindow}
cycles long, of how many control cycles the task has fallen behind schedule.
When this value reaches .63 of {\tt lagCnt}, then the task aborts with
a {\tt LAG\_TIMEOUT} condition.
As with the block timeout feature, the units of {\tt lagCnt} and {\tt
lagWindow} are the nominal cycle times specified by {\tt rciRate()}.
If no interval time has been specified for the task, or  {\tt lagCnt} is given
as 0, then lag timeouts are disabled. Specifying a {\tt lagCnt} of less then 0
or a {\tt lagWindow} less than 1 causes the system to use default values. 

\begin{quote}
{\bf NOTE: Lag timeouts are not implemented in the current
system release.}
\end{quote}

The default timeout settings for a control task are (1) block timeouts
enabled with {\tt blockCnt} equal to 2, and (2) lag timeouts disabled.

\section{Simulation Scheduling}

There is a fourth scheduling discipline available, {\tt ON\_SIGNAL}, which
enables an RCI task to be run off of a UNIX signal instead of some real time
event. A task executed in this way runs in the context of the planning UNIX
process, inside a signal handler, instead of at an elevated priority. 
Tasks
running {\tt ON\_SIGNAL} must be resident on the arbiter CPU.

The main reason for this facility is to  provide a convenient hook by
which control task execution can be simulated, without any of the limitations
normally imposed on the real time tasks: A task run {\tt ON\_SIGNAL} has
access to all the usual UNIX system calls, and can be run under the debugger.

When scheduling a task this way, the third argument to {\tt rciScheduling}
should be the UNIX signal number that will trigger the task. More
exactly, what occurs is that the UNIX signal becomes a polling interrupt, with
it still being necessary for the task to specify an appropriate wakeup
function. If it is simply desired for the task to wake up once and only once
every time the specified signal is delivered, then the wakeup function
{\tt rciOnInterrupt()} can be used. A simple sample program which runs a 
task on signal every 3 seconds using {\tt SIGALRM} is shown below:

\subsubsection*{Planning module:}
\begin{verbatim}
   #include <signal.h>
   
   #include "../h/rci.h"
   
   extern int startupFxn();
   extern int controlFxn();
   
   main()
   {
           RCI_DESC *td;
   
           td = rciCreate ("testtask", 0x1);
           rciScheduling (td, ON_SIGNAL, SIGALRM);
           rciControlFxns (td, startupFxn, controlFxn, NULLF, 0);
   
           rciStart (~0);
           printf ("Hit <CR> to exit:\n");
           while (getchar() != '\n')
              ;
           rciRelease (~0);
   }
\end{verbatim}

\subsubsection*{Control module:}
\begin{verbatim}
   #include "../h/rci.h"
   
   extern int rciOnInterrupt();
   
   startupFxn (td)
   RCI_DESC *td;
   {
           rciWakeupOn (td, rciOnInterrupt, (int)td);
           alarm (3);
   }
   
   controlFxn (td)
   RCI_DESC *td;
   {
           printf ("woke up\n");
           alarm (3);
   }
\end{verbatim}

This program creates the task {\tt testtask} and then sets it up to run
{\tt ON\_SIGNAL} using {\tt SIGALRM}. A call is made to {\tt rciStart()},
whereupon the startup function is called, which instructs the monitor to use 
{\tt rciOnInterrupt()} as a wakeup function and then sets an alarm for three
seconds later. The main control function prints a message and then resets the
alarm. Program execution continues until the user types a newline character.
It should be noted that since both the planning and control levels execute in
the context of a UNIX process, there technically should be no need to compile
the planning and control levels as separate modules. However, because 
the routine {\tt rciControlFxns()} is programmed to return an error if the
functions specified to it are not part of the control segment, we continue to
divide the program into planning and control sections.

Simulation mode is used in conjunction with the RCI robot support to provide 
special simulation tools for robot control tasks; see section \ref{simtools}.

\chapter{Intertask Communication and Memory Allocation}

\section{Locating Task Descriptors}

There are several primitives available for obtaining 
a descriptor for an RCI task
from anywhere within the program. It is necessary
to use these primitives since the descriptor address seen by one part of the
program may not have the same value in another part of the program.

{\tt getRciTask(name)} returns the descriptor for the named task, where
{\tt name} should be same name that was specified in
{\tt rciCreate()}. To obtain a task descriptor using the task number
as a key, {\tt findRciTask(num)} should be used (the task number
is a small integer returned by the macro {\tt TASKNUM(td)}).
The descriptor of the current task can be returned using
{\tt getCurrentTask()}. The name of a task can be obtained from the descriptor
with the routine {\tt rciTaskName(td)}. Finally,
the number of the CPU on which code is executing is contained in the
variable {\tt rciCpu}.

\section{Shared Memory Sections}

The basic RCI inter-task communication paradigm is centered around
shared memory, segments of which can be allocated by the planning task and
then referenced and used by both the planning task and the control tasks.
Support is provided for three different kinds of shared memory segment:

\medskip
\begin{list}{}{}
\item[1.]{\it shared segments.} These are blocks of memory that are shared
among the planning task and one control task.

\item[2.]{\it global segments.} These are blocks of memory that can be shared
between all tasks.

\item[3.]{\it local segments.} These are blocks of memory that are private to
a particular control task. The reason that allocation is the responsibility of
the planning task rather than the control task (using some form of {\tt
malloc()} call) is that the latter is difficult to provide given the requirement
that it be possible to run control tasks on the arbiter CPU.
\end{list}
\medskip

\begin{quote}
\bf NOTE: Programmers should remember that pointer references
are generally not valid across shared memory sections, since the virtual
addresses of sections may be different on different CPUs
\end{quote}

Once a shared memory segment is created by the planning task, it can be
located by a control task using a special {\it get} primitive which uses
the {\it name} of the segment as a key.
Alternatively, a shared memory section can be located
using a {\it find} primitive, which uses the 
address of the section as seen by the planning task as a key. 

The basic usage of the shared memory mechanism is illustrated by a simple
program that reads a string from the terminal, and sends this string to
a task. The first task then passes the string on to a second task, which then
returns it to the planning task. Both tasks also store the string in a 
circular buffer of locally allocated memory. While this example is quite
contrived, and could also be coded very differently, it does illustrate the
usage of most of the shared memory primitives.

\subsubsection*{File shmemDemo.h:}
\begin{verbatim}
   #define BUFSIZE      256

   typedef struct {
          void *lmem;
          int ready;
          char buf[BUFSIZE];
   } SMEM;

   typedef struct {
          int ready;
          char buf[BUFSIZE];
   } GMEM;

   typedef struct {
          char buf[BUFSIZE];
   } LMEM;
\end{verbatim}

\subsubsection*{File shmemDemo.c:}
\begin{verbatim}
   #include "../h/rci.h"
   #include "shmemDemo.h"
   
   extern startupFxn();
   extern controlFxn();
   
   main()
   {
        RCI_DESC *td1, *td2;
        SMEM *smem1, *smem2;
        char ibuf[BUFSIZE];
   
        td1 = rciCreate ("task1", 0x2);
        rciRate (td1, 1000, 500);
        rciScheduling (td1, ON_CLOCK, 0);
        rciControlFxns (td1, startupFxn, controlFxn, NULLF, 0);
        smem1 = (SMEM*)rciSharedMemory ("SMEM", sizeof(SMEM), td1);
        smem1->lmem = rciLocalMemory ("LMEM", sizeof(LMEM), td1);
   
        td2 = rciCreate ("task2", 0x2);
        rciRate (td2, 1000, 0);
        rciScheduling (td2, ON_CLOCK, 0);
        rciControlFxns (td2, startupFxn, controlFxn, NULLF, 0);
        smem2 = (SMEM*)rciSharedMemory ("SMEM", sizeof(SMEM), td2);
        smem2->lmem = rciLocalMemory ("LMEM", sizeof(LMEM), td2);
   
        rciGlobalMemory ("GMEM", sizeof(GMEM), ~0, TASKCPU(td1));
   
        rciStart(~0);
   
        while (1)
         { gets (ibuf);
           strcpy (smem1->buf, ibuf);
           smem1->ready = 1;
           while (!smem2->ready)
              ;
           printf ("%s\n", smem2->buf);
           smem2->ready = 0;
         }
   }
\end{verbatim}

\subsubsection*{File shmemDemoCtrl.c:}
\begin{verbatim}
   #include "../h/rci.h"
   #include "shmemDemo.h"
   
   startupFxn(td)
   RCI_DESC *td;
   {
        td->tcb->sharedMem = getSharedMemory("SMEM");
        td->tcb->globalMem = getGlobalMemory("GMEM");
   }
   
   controlFxn(td)
   RCI_DESC *td;
   {
        SMEM *smem = (SMEM*)td->tcb->sharedMem;
        GMEM *gmem = (GMEM*)td->tcb->globalMem;
        LMEM *lmem = (LMEM*)smem->lmem;
   
        if (strcmp(rciTaskName(td), "task1") == 0)
         { if (smem->ready)
            { strcpy (gmem->buf, smem->buf);
              strcpy (lmem->buf, smem->buf);
              gmem->ready = 1;
              smem->ready = 0;
            }
         }
        else
         { if (gmem->ready)
            { strcpy (smem->buf, gmem->buf);
              strcpy (lmem->buf, gmem->buf);
              smem->ready = 1;
              gmem->ready = 0;
            }
         }
   }
\end{verbatim}

The shared data structures are defined in the file {\tt shmemDemo.h}.
These include type {\tt SMEM}, shared between the planning task and each
control task, the type {\tt GMEM}, accessible to all tasks but here used only
by the two control tasks, and the type {\tt LMEM}, which describes
memory local to each control task.

The main program creates two tasks, sets up each one to run at a
1 second rate (skewed by half a second with respect to each other), 
and then creates a shared section for each one and a global section.

The primitive
{\tt rciSharedMemory()} creates a section shared between a particular
task and the planning level, zeros it, and returns a pointer to it. 
Access to this
section is limited to the planning task and the control task it was created
for.
Its first argument is a string label
identifying the section.
This argument can be declared
{\tt NULL} if other tasks are planning to reference the memory with the
{\it find} primitive {\it
findSharedMemory()} rather than the {\it get} primitive
{\it getSharedMemory()}.
The second argument is the size
of the section in bytes, and the third argument is the task descriptor for the
task with which the section will be shared. The same label name can be re-used
for a shared section assigned to a different task; this was part of the
motivation for differentiating between {\it shared} sections and {\it global
sections}. 

{\tt rciLocalMemory()} is used to set up a section of local memory for each
task. It takes the same arguments as {\tt rciSharedMemory}: a string
label, the section size, and a task descriptor. 
The label can be declared {\tt NULL} if the section is not later
referenced with {\tt getLocalMemory()}.
Note that the memory returned by {\tt rciLocalMemory()} is
{\bf not} automatically zeroed under the present implementation. 
The pointer value returned
by the routine can be used directly by the control task, although the
planning task {\bf does not} have access to this memory. The control task can
hence obtain a pointer to the local section either with a {\it get} primitive,
or by taking the pointer directly from planning level. In the sample program,
the latter is done, with the pointer being passed to the task through the {\tt
SMEM} structure. 

{\tt rciGlobalMemory()} creates a global memory section, which can be
accessed by any task, zeros it, and returns a pointer to it. 
The routine takes four arguments: A string label, the section
size in bytes, an access mask (not currently implemented),
and the pool from which the section should be allocated. 
The label can be declared {\tt NULL} if the section is later referenced
with {\tt findGlobalMemory()} rather than {\tt getGlobalMemory()}.
It is necessary to specify an allocation pool CPU since it is
not clear a priori where the global memory should reside. (For shared
sections, the allocation pool is chosen to be the one that can be accessed
the fastest
by the CPU hosting the target control task). Under the current implementation,
each of the auxiliary CPUs contain their own pools that can be used to provide
system wide shared memory. There are no other types of pools presently 
available. Pool specifications are hence equivalent
to CPU numbers at the moment; allocated memory from a
pool on a CPU will ensure that the section can be rapidly accessed from that
CPU. On the other hand, worrying about what pool to specify
is often more trouble than it is worth. If the
pool argument is 0, then a default pool is used, which (presently) is that
belonging to the arbiter CPU.

Once the program has set up all the shared memory, it starts the two tasks and
the goes into a loop where it reads a string from the terminal, passes it to
task 1, and then waits for task 1 to pass it to task 2 and task 2 to pass it
back to the planning level. The string is then printed out to verify it made the
journey all right.

The control task startup function locates the shared and global sections
using the respective calls 
{\tt getSharedMemory()} and {\tt getGlobalMemory()}.
It then stores the returned pointers into the {\tt sharedMem}
and {\tt globalMem} fields of the task control block, which are provided as a
place to store such pointers so that the control task will not have to keep
re-referencing sections during each control cycle. There is also
a field {\tt localMem} in the TCB, but this program does not use it since
the local memory pointer can be obtained directly from the {\tt SMEM} data.

Inside the main control function, the primitive {\tt rciTaskName()} is used to
find the name of the task from the task descriptor and determine whether this
is task number 1 or task number 2 (there are other ways of doing this,
such as checking a flag in the shared section, or examining the 
task number which can be obtained with the macro {\tt TASKNUM(td)}).
Depending on which task the function finds itself in, it checks the
appropriate receive buffer, and, if it is ready, copies the data into the
appropriate output buffer as well as its local buffer, clears the input ready flag,
and sets the output ready flag for pickup by the next task.

An alternative way of referencing memory sections, not presented in this
example, is possible using the primitives
\begin{verbatim}
        findSharedMemory(keyaddr)
        findGlobalMemory(keyaddr)
\end{verbatim}
which use the section addresses known to the planing task ({\tt keyaddr}) as a
key to locate the section. This address can be passed to the task either
through another structure, or as a routine argument. The planning task address
cannot be used directly since the same section may have different addresses on
different CPUs. There is no primitive {\tt findLocalMemory()}, since in that
case the value received by the planning task {\it is} the value usable by the
control task.

\section{Shared Memory Objects}

A slightly higher level of shared memory is available to RCI programs in
the form of shared {\it memory 
objects}. Shared memory objects differ from shared memory
sections in a few ways: 

\medskip
\begin{list}{}{}
\item {1.} Memory objects can be freed and the space re-used.

\item {2.} There are primitives available for atomically reading and writing a
shared memory object.

\item {3.} They are global in scope and can be accessed by any RCI task.
\end{list}
\medskip

Basically, shared memory 
objects are intended emulate shared variables. The example
in the previous section, when rewritten using shared memory
objects, and omitting
the part where the control tasks copy the string passed to them into 
local memory, looks like this:

\subsubsection*{File memDemo.h:}
\begin{verbatim}
   #define BUFSIZE 256
   
   typedef struct {
           void *bufaddr1;
           void *bufaddr2;
           void *bufaddr3;
           int ready1;
           int ready2;
           int ready3;
   } KEYBUF;
\end{verbatim}

\subsubsection*{File memDemo.c:}
\begin{verbatim}
   #include "../h/rci.h"
   #include "memDemo.h"
   
   extern controlFxn();
   
   main()
   {
           RCI_DESC *td1, *td2;
           KEYBUF *keybuf;
           char ibuf[BUFSIZE];
   
           td1 = rciCreate ("task1", 0x2);
           rciRate (td1, 1000, 500);
           rciScheduling (td1, ON_CLOCK, 0);
           rciControlFxns (td1, NULLF, controlFxn, NULLF, 0);
   
           td2 = rciCreate ("task2", 0x2);
           rciRate (td2, 1000, 0);
           rciScheduling (td2, ON_CLOCK, 0);
           rciControlFxns (td2, NULLF, controlFxn, NULLF, 0);
   
           keybuf = (KEYBUF*)allocMem("KEYBUF", sizeof(KEYBUF), 0);
           keybuf->bufaddr1 = allocMem(NULL, BUFSIZE, TASKCPU(td1));
           keybuf->bufaddr2 = allocMem(NULL, BUFSIZE, TASKCPU(td1));
           keybuf->bufaddr3 = allocMem(NULL, BUFSIZE, TASKCPU(td2));
   
           rciStart(~0);
   
           while (1)
            { gets (ibuf);
              writeMem (keybuf->bufaddr1, ibuf);
              keybuf->ready1 = 1;
              while (!keybuf->ready3)
                 ;
              readMem (keybuf->bufaddr3, ibuf);
              printf ("%s\n", ibuf);
              keybuf->ready3 = 0;
            }
   }
\end{verbatim}

\subsubsection*{File memDemoCtrl.c:}
\begin{verbatim}
   #include "../h/rci.h"
   #include "memDemo.h"
   
   controlFxn(td, arg)
   RCI_DESC *td;
   int arg;
   {
   
           KEYBUF *keybuf;
           char *buf1;
           char *buf2;
           char *buf3;
           char tempbuf[BUFSIZE];
   
           keybuf = (KEYBUF*)getMemByName("KEYBUF");
   
           if (strcmp(rciTaskName(td), "task1") == 0)
            {
              buf1 = (char*)getMemByAddr(keybuf->bufaddr1);
              buf2 = (char*)getMemByAddr(keybuf->bufaddr2);
   
              if (keybuf->ready1)
               { readMem (buf1, tempbuf);
                 writeMem (buf2, tempbuf);
                 keybuf->ready2 = 1;
                 keybuf->ready1 = 0;
               }
            }
           else
            {
              buf2 = (char*)getMemByAddr(keybuf->bufaddr2);
              buf3 = (char*)getMemByAddr(keybuf->bufaddr3);
   
              if (keybuf->ready2)
               { readMem (buf2, tempbuf);
                 writeMem (buf3, tempbuf);
                 keybuf->ready3 = 2;
                 keybuf->ready2 = 0;
               }
            }
   }
\end{verbatim}

The objects are allocated with the primitive {\tt allocMem()}. The first
argument is a (optional) string label,
the second argument is the size of the memory object in bytes, 
and the third argument designates the pool from which it should be
allocated. The pool argument serves the same purpose as the pool
argument in {\tt rciGlobalMemory()}.
With the present implementation, where each
pool is associated with a CPU, this is simply a
CPU number, with CPU 0 being the usual default.

As with shared memory sections, it is also possible to specify a {\tt NULL}
label and instead let the control task find the memory by keying on the
planning level address. In the sample program, the first piece of
memory allocated,
{\tt KEYBUF}, is used to 
store the planning level addresses of the three other memory objects.

Each control task obtains pointers to the memory
objects by first calling
{\tt getMemByName()} to locate {\tt KEYBUF}, and then calling
{\tt getMemByAddr()}. 
to locate the three buffers.

When the tasks pass copies of the string around, they use the primitives
{\tt readMem()} and {\tt writeMem()}. These are used to implement
atomic memory referencing: {\tt writeMem()} takes a memory object
(first argument) and copies into it the contents of a buffer (second
argument), and {\tt readMem()} takes a memory object (first 
argument) and copies
its contents into a buffer (second argument).  The sizes of the read and write
buffers are assumed to be the same sizes as the memory objects. 
Use of these primitives
is atomic, in that no other {\tt readMem()} or {\tt writeMem()}
on the same memory will proceed while
another is in progress.

If an atomic access of a memory
object is not necessary, its address may be
used directly. The read and write primitives were used in the sample program 
for illustrative purposes only; it would been equally possible
to write fragments like
\begin{verbatim}
        strcpy (buf3, buf2);
\end{verbatim}
instead of
\begin{verbatim}
        readMem (buf2, tempbuf);
        writeMem (buf3, tempbuf);
\end{verbatim}

There is also a general purpose copying primitive:
\begin{verbatim}
        accessMem (mem, src, dest, size)
\end{verbatim}
This simply copies {\tt size} bytes from {\tt src} into {\tt dest},
taking care to lock {\tt mem} before doing so. This routine
is mainly useful for copying only portions of a memory object, or for
copying other things that are not contained there at all, but 
for which the memory object provides a reasonable mutual exclusion reference.

This leads us to the general locking primitives,
\begin{verbatim}
        lockMem (mem)
        unlockMem (mem)
\end{verbatim}
which can be used to lock a memory object and then unlock it. While
a memory object is locked, all other references to it through
{\tt readMem()}, {\tt writeMem()}, {\tt accessMem()}, or {\tt lockMem()}
will be blocked. Memory objects can thus be used as general purpose
mutual exclusion flags.

\begin{quote}
\bf NOTE: {\tt lockMem()} and {\tt unlockMem()} cannot
currently be called from the planning task.
\end{quote}

An additional memory object primitive is {\tt getMemName(p)}, which takes a
pointer to piece of memory and returns a pointer to it's name.

\section{Task Local Memory}

Local memory for an RCI task can be allocated by the planning level
with the {\tt rciLocalMem()} primitive described above.
It can also be allocated (and freed) by the control task itself using the
primitives
\begin{verbatim}
      rciMalloc (size)
      rciFree (ptr)
\end{verbatim}
whose use is analogous to {\tt malloc()} and {\tt free()}. 
However, the control task cannot call {\tt malloc()} because
in general it cannot use UNIX system calls (see section
\ref{restrict.sec}).

The memory pool available to {\tt rciMalloc()} is not very large
(as low as 128 Kbytes in some cases). Also, memory should
be freed by the same task which allocated it (see {\tt rciMalloc(3)} for
details). 

\section{Message Passing}

Although shared memory is the basic means of RCI inter-task communication,
message passing primitives have been made available. These include

\medskip
\begin{list}{}{}
\item[1.] A {\it send} primitive by which messages may be sent from one
task to another;

\item[2.] A {\it receive} primitive by which a task may accept messages from a
specified task.
\end{list}
\medskip

The primitives do not block; this was not seen as necessary since message
passing is not used by RCI as a synchronizing or scheduling mechanism.

A simple example which implements the sample program of the previous section
using send and receive primitives is given below:

\subsubsection*{File msgDemo.c:}
\begin{verbatim}
   #include "../h/rci.h"
   
   extern controlFxn();
   
   #define BUFSIZE 256
   
   main()
   {
           RCI_DESC *td1, *td2;
           char ibuf[BUFSIZE];
           int size;
   
           td1 = rciCreate ("task1", 0x2);
           rciRate (td1, 1000, 500);
           rciScheduling (td1, ON_CLOCK, 0);
           rciControlFxns (td1, NULLF, controlFxn, NULLF, 0);
   
           td2 = rciCreate ("task2", 0x2);
           rciRate (td2, 1000, 0);
           rciScheduling (td2, ON_CLOCK, 0);
           rciControlFxns (td2, NULLF, controlFxn, NULLF, 0);
   
           rciStart(~0);
   
           while (1)
            { gets (ibuf);
              rciSend (TASKMASK(td1), ibuf, strlen(ibuf)+1);
              while ((size = rciReceive (TASKMASK(td2), ibuf, 
                                         BUFSIZE, NULL)) == 0)
                 ;
              printf ("%s\n", ibuf);
            }
   }
\end{verbatim}

\subsubsection*{File msgDemo.c:}
\begin{verbatim}
   #include "../h/rci.h"
   
   #define BUFSIZE 256
   
   controlFxn(td, arg)
   RCI_DESC *td;
   int arg;
   {
           char buf[BUFSIZE];
           int size;
           RCI_DESC *td1, *td2;
   
           td1 = rciDescriptor ("task1");
           td2 = rciDescriptor ("task2");
   
           if (getCurrentTask() == td1)
            {
              if (size = rciReceive (0x1, buf, BUFSIZE, NULL))
               { rciSend (TASKMASK(td2), buf, size);
               }
            }
           else
            { 
              if (size = rciReceive (TASKMASK(td1), buf, BUFSIZE, NULL))
               { rciSend (0x1, buf, size);
               }
            }
   }
\end{verbatim}

There is no need to explicitly open a communication channel to pass messages;
there is an implicit channel open between each pair of tasks (this was done
for 
simplicity both at the application and implementation level, but could perhaps
prove to be a nuisance later on).

Sending a message is done by calling {\tt rciSend()}, which takes as its
first argument the bit code of the task to which the message is to be sent
(for which the macro {\tt TASKMASK()} is useful). At present, {\tt rciSend()}
cannot broadcast to multiple tasks; if more than one bit is set in the
destination mask, the message is sent to the task indicated by the lowest bit.
The next two arguments specify the message buffer and its size, in bytes.

The first argument of {\tt rciReceive()}
specifies the tasks from which messages may be received ({\tt \~{}0}
may be used to indicate ``any task''). The next two arguments specify the
address and size of a buffer in which the message is to be placed. 
The last argument to {\tt rciReceive()} is an optional pointer through which
the task descriptor of the sending task may be obtained.

Messages
are received on a first in, first out basis; messages coming from the same
task will be arrive in the same order in which they were sent.
All flushing of message queues must be done by the user; to help do this,
there is
the routine {\tt rciFlush(mask)}, which flushes all incoming messages from the
tasks specified by the bitmask {\tt mask}.

The sample program above makes use of an additional primitive,
{\tt rciDescriptor()}, which takes the name of a task and returns a pointer to
its descriptor.

\section{Signaling the Planning Level}

To provide a means of asynchronously notifying the planning task from the
control level, the routine {\tt rciSignal(signum)} may be used to send the
UNIX signal {\tt signum} to the planning task.

\section{Synchronizing with the Planning Level}

The routine {\tt rciBlock()} provides a convenient way to synchronize 
planning level and control task activity. It usefulness capitalizes on the
fact that the execution of a control task is likely to be a regular, periodic
event. {\tt rciBlock(td)} will wait until the specified control task has
completed one complete cycle from time the routine was called. In
cases where the planning task does something that the control task is
sure to notice on the next cycle, this eliminates the need for the control
task to send an explicit acknowledge of whatever it was that
the planning task did. 

\chapter{Restrictions and Side Effects}\label{restrict.sec}

This section summarizes the restrictions that apply to RCI programs
and control tasks.

\medskip
\begin{list}{}{}
\item[1.]
All modules containing 
code and data referenced at the control level must be compiled 
and loaded with the {\tt rcc} command (as described in section
\ref{create}).

\item[2.]
UNIX system calls may not be available at the control level.
This is {\it strictly} true on MicroVAX and Sun4 systems, where
system calls at the control level will result in a program
crash. Consequences can be even more severe on MicroVAX systems
(see \ref{halt}). On systems where the RCI has been implemented
using real-time features supplied by the host operating
system (such as on SGI systems or VxWorks), then the control level
is in fact just a high-priority process and does have access
to system calls. However, it should be remembered that system
calls can be very time consuming, and offer the potential 
for disturbing the control level timing.
%%%
%%% Printing can be done to the control CPU console line using
%%% {\tt rciPrint()}. 

\item[3.]
Infinite loops are not detected per-se. An infinite loop occurring
at the control level on the arbiter CPU has the unfortunate effect
of hanging the whole system. On MicroVAX and Sun4 systems,
it is possible to recover from this by breaking the system at
the console, entering a bogus program counter value, and resuming. This
will cause an error that will be intercepted by the RCI exception handling
code and result in a normal program crash.

\item[4.]
RCI programs reserve the use of the UNIX signals {\tt SIGHUP} and
{\tt SIXCPU}. {\tt SIGHUP} is used to signal the planning task that
an RCI abort has been issued (by a call to {\tt rciAbort()}).
{\tt SIGXCPU} is used to notify the planning task of a program crash
at the control level (see section \ref{crash}).
\end{list}
\medskip
\section{Preventing reboots on the MicroVAX-II}\label{halt}

A UNIX system call made from the RCI control level on the arbiter
CPU of a MicroVAX-II system may cause the system to reboot automatically.
This is because the MicroVAX appears to interpret system call instructions
in kernel mode as halt instructions, and system call instructions
will be issued if the program invokes a UNIX system call by accident
at the control level (the typical case involves a {\tt write} call
being issued by {\tt printf()}). 

To set the MicroVAX so that
it actually halts in these cases, break into the console monitor
(hit {\tt <brk>}) and enter the following command sequence:
\begin{verbatim}
        >>> d/w/p 200b801c 23   ! set halt enable
        >>> c                   ! continue system operation
\end{verbatim}
If a system call now occurs at the control level, the CPU will simply
halt and enter console mode. One can then recover by forcing an abort:
\begin{verbatim}
        >>> d/l/g pc ffffffff   ! set program counter to -1
        >>> c                   ! continue
\end{verbatim}
This will be caught by the RCI exception handling code and
will result in a normal program crash.

\chapter{Error Handling and Recovery}

\section{The Error Stack}\label{estack}

Most RCI primitives return either {\tt NULL} or -1 in the event of an
error, depending on whether the routine normally returns a pointer
or not. There is also a facility, known as the {\it error stack},
which they may use to return
error codes and messages.

Any routine which encounters an error condition may
place an error code and message on the error stack by calling
the primitive
\begin{verbatim}
        errorMsg (code, fmt, args ...);
\end{verbatim}
The first argument is the error code, while the following arguments
specify the error message using a the usual {\tt printf()} method
of a format string followed by a variable number of value arguments (NOTE:
the total size of a message string is limited; consult the
reference manual). When the error is passed back, the calling routine
may add additional error codes and messages of its own to the stack. Once
a level is reached at which it is desirable to print out the all the
accumulated error
messages (usually the RCI application level), this may be done using the
primitive {\tt printErrors()}, which prints the error messages to
{\tt stdout}. It will probably also be desired to clear the 
error stack at this point, which may be done using {\tt clearErrors()}.

Individual error codes within the stack may be examined using {\tt
getErrorCode(level)}, where {\tt level} is the stack level (0 is the one
most recently added). Individual error messages may be examined with
the primitive {\tt getErrorMsg(level)}. The depth of the error stack at any time
may 
be examined with {\tt numErrors()}. The most recent error code/message
may be popped of the stack with {\tt popError()}, and the error code
associated with any level may be set using {\tt setErrorCode(level, value)}.

The usage of some of these routines is illustrated with a very simple example:

\begin{verbatim}
   #define BENGIN  1
   #define BAD     2
   
   int condition = BAD;
   
   main()
   {
           if (level1() < 0)
            { printErrors();
              clearErrors();
            }
   }
   
   level1()
   {
           if (level2() < 0)
            { if (getErrorCode (0) == BENIGN)
               { clearErrors();
               }
              else
               { errorMsg (0, "error found at level 1\n");
                 return (-1);
               }
            }
   }
   
   level2()
   {
           errorMsg (condition, "error found at level 2\n");
           return (-1);
   }
\end{verbatim}

When this example is run, it will either print out nothing (if
{\tt condition} is set to {\tt BENIGN}), or the following traceback
if {\tt condition} is set to {\tt BAD}:
\begin{verbatim}
        error found at level 1
        error found at level 2
\end{verbatim}

The purpose of the error stack is to make it possible to
provide a comprehensive trace back of errors, particularly
when something goes wrong ``several
levels down''. While the error stack
is mostly used at the moment for RCI/RCCL system diagnostics, other
application software may use the same facility.

In the RCI example programs described above, there has been no attempt
to check whether routines return successfully. This was done to make the
example clear, but, needless to say, is not usually good
practice. 

Not all RCI routines make use of the error stack. 
The reference manual documents which ones do.

Since many RCI primitives use the error stack,
the proper way to code calls to these primitives is to use a paradigm
something like 
\begin{verbatim}
        if ((td = rciCreate ("bar", 0x2)) == NULL)
         { printErrors();
           clearErrors();
         }
\end{verbatim}
Since this can be a bit tedious to code, there is an RCI feature,
{\tt EXIT\_ON\_ERROR}, which when selected
(see section \ref{options}) 
causes routines to automatically dump their error stack and
force a program exit in the event of an error.

\section{The Error Stack for an RCI Task}

An RCI control task has its own error stack that is saved
and restored with the task's context. Calling
{\tt errorMsg()} from within an RCI control task will cause
the specified message to go to a private error stack for
that task.

To access the error stack for an RCI task from {\it outside}
the task's context, one can use the routines described in
{\tt rciErrorMsg(3)}. These perform the same operations as the regular
error stack routines, but they take an extra argument
describing the RCI task whose error stack should be used.

{\tt printErrors()} will fail if called from the control level;
{\tt rciPrintErrors()} should be used instead.

For errors detected at the control level, a common thing
to do is call the routine {\tt rciAbortErrors()}, which calls
{\tt rciAbort()} (see next section)
using the most recent error code and all the
accumulated messages on the error stack. Routines which use
the error stack can thus be called from the
control level in this way:
\begin{verbatim}
        if ((td = ctrlLevelRoutine()) == NULL)
         { rcclAbortErrors();
         }
\end{verbatim}

\section{Bailing Out: rciAbort()}

All RCI control levels can make use of the {\tt rciAbort()}
function, which raises an abort condition and releases all control tasks.
A call to {\tt rciAbort()} contains an error code, followed by a 
{\tt printf()} style message
format string and variable number of value arguments:
\begin{verbatim}
        rciAbort (ETimeout, "task number %d timed out\n", TASKNUM(td));
\end{verbatim}
The total size of the message that may be created by {\tt rciAbort()} is
limited; consult the reference manual.

When an abort condition is raised, the following things occur:

\medskip
\begin{list}{}{}
\item[1.]The signal {\tt SIGHUP} is sent to the planning task, where it
invokes a built-in abort handler.

\item[2.]Each task acknowledges the abort and releases itself
by calling its release function
(if any) with the {\tt EXTERNAL\_ABORT} release code (except for the task
which initiated the abort, where the release function has probably been already
called with a more specific release code). The abort handler waits for all
tasks to acknowledge the abort; if they fail to do so, a fatal error is
generated and the program exits.

\item[3.]
The abort handler then calls the user defined abort routine, if any. If there
is no such routine, then the abort message is simply printed and the program
exits.
\end{list}
\medskip

A user program can set up an abort handler using the routine {\tt
rciAbortHandler()}, which takes as an argument the desired handler function
and returns either the previously specified handler function, if any,
or {\tt NULL}. When the abort handler is called, it is given three arguments:
the {\tt code} passed to {\tt rciAbort()}, the message specified 
by {\tt rciAbort()}, and the task descriptor of the task that issued the 
abort. This information can be used by the handler routine in performing
remedial action or printing diagnostics.
For example, setting up an abort handler that simply performs the default
action of printing diagnostic information and exiting can be done as follows:
\begin{verbatim}
   abortHandler (code, msg, td)
   int code;
   char *msg;
   RCI_DESC *td;
   {
        printf ("\nRCI ABORT: task '%s' on cpu %d\n%s\n", 
                rciTaskName(td), td->cpu, msg);
        exit (-1);
   }

   main()
   {
        rciAbortHandler (abortHandler);

        ... rest of the program ...
   }
\end{verbatim}

Abort handlers may also continue program execution. The easiest way to do this
is to throw out of the abort handler to a predefined catch point, using the
UNIX {\tt setjmp()} and {\tt longjmp()} routines (see {\tt setjmp(3)}). A
simple program that handles velocity and torque limits in this way
is shown below:

\begin{verbatim}
   #include <setjmp.h>

   #include <rci.h>
   #include <errorCodes.h>

   jmp_buf catchFrame;

   abortHandler (code, msg, td)
   int code;
   char *msg;
   RCI_DESC *td;
   {
        if (code == EMaxVel || code == EMaxTor ||
            code == EReqVel || code == EReqTor )
         { longjmp (catchFrame, 1);
         }
        else
         { printf ("\nRCI ABORT: task '%s' on cpu %d\n%s\n", 
                   rciTaskName(td), td->cpu, msg);
           exit (-1);
         }
   }

   main()
   {
        int status;

        rciAbortHandler (abortHandler);

        if ((status = setjmp (catchFrame)) != 0)
         { printf ("velocity or torque limit exceeded; restarting\n");
         }

        ... rest of the program ...
   }
\end{verbatim}

The {\tt code} passed to the abort handler is the same code that was specified
when the task called {\tt rciAbort()}. It is assumed in this example that the
control task, when it detects a velocity or torque limit condition,
calls {\tt rciAbort()} with one of the appropriate codes checked for by the
handler. Normally such checking is done by the robot communication functions
(see section \ref{robotinterface}),
and so the abort is issued from there. 

\section{Status Codes for the Release Function}\label{statuscode}

As was described earlier, a control task's release function is called with a
third argument describing what condition is responsible for the task being
released. These condition codes, defined in {\tt rci.h}, are
\begin{verbatim}
        RELEASE_REQ
        EXTERNAL_ABORT
        BLK_TIMEOUT
        LAG_TIMEOUT
        STARTUP_FXN_ERR
        CONTROL_FXN_ERR
\end{verbatim}

{\tt RELEASE\_REQ} indicates that the task is being released as the normal
result of a planning level call to {\tt rciRelease()}. {\tt EXTERNAL\_ABORT}
is used to indicate that some task other than the current one issued a call to
{\tt rciAbort()}. {\tt BLK\_TIMEOUT} and {\tt LAG\_TIMEOUT} are set if the
task aborted due to either a block or lag timeout condition (see section
(\ref{timeout})). {\tt STARTUP\_FXN\_ERR} and {\tt CONTROL\_FXN\_ERR} 
indicate that either the startup function or the control or execute
functions issued a call to {\tt rciAbort()}.

\section{Program Crashing}\label{crash}

If an RCI program crashes at the planning level, one gets the usual
\begin{verbatim}
        <something bad happened> (core dumped)
\end{verbatim}
If a crash occurs at the control level, then information about the
crash and why it happened is packaged into small message by the RCI
support code and sent to the planning task along with a 
{\tt SIGXCPU} signal. This invokes a handler that prints
a message and forces a program exit. On Sun4 and MicroVAX systems,
a numeric stack trace is printed of the control level at the
point where the error occurred. 
The trace contains,
for each nested routine, the program counter value within the routine and the
arguments with which the routine was called. The most deeply nested routine
is printed first. We do not, at the moment, print a symbolic trace,
so it is necessary to use {\tt adb} to find the routine names which
correspond to the listed program counter values.
On SGI systems, a core file
is generated for the control task and so there is no need for
a stack trace.

\chapter{External I/O: The Easy Way}

So far, this manual has only described ways of communicating between tasks.
For communicating with the outside world, RCI assumes a machine architecture
that supports memory mapped I/O. An application can then talk directly to the
memory map, or can go through a defined I/O routine interface (described in
the next section).

For interacting directly with the memory map, RCI provides two variables:
\begin{verbatim}
        unsigned char *rciIOpage;
        unsigned char *rciBus;
\end{verbatim}

The function of these variables is described here for the
MicroVAX/Q-bus implementation. Consult the
manual page {\tt rciBus(3)} to see what portions of I/O space
they map on other systems.

{\tt rciIOpage} points to the base of a piece of memory that is mapped onto
the Q-bus I/O page (an 8 Kbyte region at the top of the bus address space). 
A device register located there 
can be accessed with a code fragment that looks like:
\begin{verbatim}
        #define ADDR 0177560 /* 16 bit Q-bus address */

        extern unsigned char *rciIOpage;
        unsigned short *reg;

        *reg = (unsigned short *)(rciIOpage + (0x1fff & ADDR));
        *reg |= 1;
\end{verbatim}

This example sets the first bit of a device register located at 
0177560. The pointer to the register is obtained by adding the low order
13 bits of address to the I/O page base (13 bits since the I/O page is 8 Kbytes
long). It should also be noted from the example that the 
Q-bus is word and byte oriented; hence the use of {\tt short} data types.

{\tt rciBus} points to the base of a piece of memory that is mapped onto
the entire Q-bus (a 4 Megabyte region in the case of the Q22-bus)\footnote
{The top 8 K of this space actually overlaps the Q-bus I/O page,
but whether or not I/O space devices can be accessed from {\tt rciBus} depends
on the device itself; accesses from {\tt rciIOpage} go through a different
translation mechanism that also asserts a special line on the bus to designate
I/O page access, which can be used by devices to cut down on decoding.}.
Use of the main Q-bus address space is usually reserved for devices such as
bus adapters or frame/image buffers.

Under the present implementation, {\tt rciIOpage} and {\tt rciBus} are
available from the time the first call is made to {\tt rciCreate()}.
This may become more complicated when RCI is ported to the SUN VME system.
Caution should be used in accessing the address spaces from
the planning level, since if there is no memory present there UNIX will crash with
a machine exception. Accesses from the RCI control level are safe from
such crashes, which will cause a program crash instead.

To determine whether or not memory exists at a particular bus location,
a user can use the function
\begin{verbatim}
        rciBadAddr(address, size)
\end{verbatim}
which behaves identically
to the {\tt badaddr()} routine used by UNIX device drivers, returning 1 if the
memory 
does not exist and 0 if it does. {\tt address} is the location to be tested,
and {\tt size} is the size of the location, in bytes. At the moment, {\tt
size} is restricted to 1, 2, and 4; other values will cause the routine to 
return -1. 

\chapter{External I/O: The Formal Way}\label{formaldev}

\section{RCI I/O Devices}

RCI also provides a defined I/O interface that is geared toward 
doing simple, single channel,
packet oriented communication between an RCI task and an
external process. RCI devices are used by
the robot interface routines to support their communication 
with robot controllers,
and the device model itself has been essentially designed to
meet these needs. The purpose of the RCI device interface is to provide a
device independent I/O package for use by RCI applications.

The driver interface for an RCI device consists of nine functions:

\medskip
\begin{list}{}{}
\item[1.]{\it read} -- read a packet of data from the device, blocking until
the device is ready to send the packet or the call times out.

\item[2.]{\it write} -- write a packet of data to the device, blocking until
the device is ready to receive the packet or the call times out.

\item[3.]{\it testRead} -- see if the device is ready to send a packet (i.e.,
a call to {\it read} will not block).

\item[4.]{\it testWrite} -- see if the device is ready to receive
a packet (i.e., a call to {\it write} will not block).

\item[5.]{\it signal} -- send an unsolicited signal to the device.

\item[6.]{\it probe} -- see if the interface is physically present.

\item[7.]{\it attach} -- establish contact with the device and confirm that it
is ready to do I/O.

\item[8.]{\it detach} -- reset the interface and leave it in a known state.

\item[9.]{\it ioctl} -- control I/O parameters such as timeout and blocking
times.
\end{list}
\medskip

Pointers to these routines, as well as other information specified to the
device,
are contained in an {\tt IO\_DEVICE} structure;
for a complete description of this, see {\tt man 7 IOdevice}. A more complete
description of the I/O routines will be presented later. In the following 
discussion, the variable {\tt dev} will be used to indicate a pointer to
an {\tt IO\_DEVICE} structure.

Each RCI task may attach one I/O device, which is done by specifying the
name of the device and its address to the routine {\tt rciAllocDevice()}:
\begin{verbatim}
        IO_DEVICE *dev;
        struct devAddr devAddr;

        devAddr.name = "pri";
        devAddr.address = 0177700;
 
        rciAllocDevice (td, &devAddr, DEV_ALL);
        dev = TASKDEV(td);
\end{verbatim}
In this example the device has the name {\tt pri}, and it is 
located at the address {\tt 0177700}. The routine 
{\tt rciAllocDevice()} simply initializes the 
{\tt IO\_DEVICE} structure belonging to the task {\tt td} and sets the 
device name and address information as specified. 
The name of the device specifies the set of driver routines with which
the I/O device structure will be instantiated (as described in the
file {\filefont drivers/IODriverTable.c}), 
while the address is an integer that identifies
the specific
location of the device. The third argument describes whether or not
the device may be opened by more than one
RCI task, and should be set to one of the
following four values:
\medskip
\begin{list}{}{}
\item[$\diamondsuit$]{\tt DEV\_NONE} -- device cannot be opened multiple times
from the same RCI program or any other program.
\item[$\diamondsuit$]{\tt DEV\_INTERNAL} -- device can be opened multiple
times from within the same RCI program, but not by different programs;
\item[$\diamondsuit$]{\tt DEV\_EXTERNAL} -- device can be opened multiple
times from different RCI programs, but not within the same program;
\item[$\diamondsuit$]{\tt DEV\_ALL} -- device can be opened multiple times.
If the device cannot be opened according the given  access requirements, the
call will fail by returning -1 and error information will be placed on
the error stack.
\end{list}
\medskip

The device address is stored into the I/O device structure by
{\tt rciAllocDevice()} where it can be
used by the probe routine to locate the program memory location of 
the device registers. This address is normally specified with the
{\tt address} field of the {\tt devAddr} structure.
The {\tt devAddr} structure also contains fields for up to
{\tt MAX\_DEVARGS} optional arguments that are also stored into 
the I/O device structure. These can be used in any way needed by the
driver, including providing additional addressing information. {\tt devAddr}
also contains another field, {\tt addrStr}, which is used specifically
to provide addressing information to the simulator driver {\tt sim}.

Once a device is assigned to a task, a pointer the device structure may be
obtained using the macro {\tt TASKDEV()}. A device may be deallocated using
the primitive {\tt rciDeallocDevice()}.

The device driver routines must be called from within the control routines.
A typical usage of them is illustrated by the following example:
\begin{verbatim}
    startupFxn(td)
    RCI_DESC *td;
    {
        IO_DEVICE *dev = TASKDEV(td);

        if ((*dev->probe)(dev) < 0)
         { rciAbortErrors();
         }
        if ((*dev->attach)(dev) < 0)
         { rciAbortErrors();
         }
        (*dev->ioctl)(dev, IOC_SETBLOCK_TIME, 1000);
    }

   #define MAXDATA      256
   #define RELEASE_SIG  2

   controlFxn(td)
   RCI_DESC *td;
   {
        IO_DEVICE *dev = TASKDEV(td);
        int numbytes;
        char databuf[MAXDATA];

        if ((numbytes = (*dev->read)(dev, databuf, MAXDATA)) < 0)
         { rciAbortErrors();
         }

        ... compute information to send back to device ... 

        if ((*dev->write)(dev, databuf, numbytes) < 0)
         { rciAbortErrors();
         }
   }

   releaseFxn (td)
   RCI_DESC *td;
   {
        (*dev->signal)(dev, RELEASE_SIG);
        (*dev->detach)(dev);
   }
\end{verbatim}

The startup function first calls the probe routine to make sure that the
I/O interface is physically present, and then calls the attach routine to
``make contact'' with whatever device is on the other end of the interface.
If any of the driver functions fail, an appropriate
error code is normally placed
on the error stack \footnote
{Error codes for RCI I/O drivers are defined in the
file {\filefont h/errorCodes.h}.}.
A call to the {\it ioctl} routine sets the allowed blocking time to 1 second,
meaning 
that calls to the {\it read} or {\it write} routine will wait that length of
time for a response from the other 
side before throwing in the towel.

The main control routine simply uses the {\it read} and {\it write}
routines to exchange packets of information with the
external device. This usage is more or less exactly what the robot control
applications do, only the calls to the I/O functions are hidden inside robot
communication functions that do pre-processing on the incoming packets and 
post-processing on the outgoing packets.

In the release function, the {\it signal} routine is used to send a
notification to the external device that a release is being performed and the
control session is now being terminated. In more complex cases, it might be
desirable to follow up the signal by sending and possibly receiving packets
of information with {\tt read} and {\tt write} calls.

\section{Detailed Description of Driver Functions and Variables}

\subsection{probe routine}

The {\tt probe} routine is modeled after the UNIX probe routine. Its purpose
is simply to check to see if the interface hardware is physically there
(although it does not necessarily check to see if there is anything on the
{\it other side} of the device). The probe routine takes one argument,
which is a pointer to the device, and returns the size of the device, in bytes,
if it is physically
present, and -1 if it is not. It should be called before any of the other
routines, since if the interface hardware is not actually present,
a memory violation will result when the device is used. {\tt probe}
is also usually responsible for instantiating the field {\tt location}
within the device; this is used internally by the driver routines
and provides a pointer to the actual program memory location which is mapped
onto the device hardware. It is computed by the probe routine from the data
in the {\tt address} field, and perhaps other information supplied
in the {\tt args} field. The reason for providing the {\tt location}
field is simply speed, so that other routines will not have to recompute
the memory address (this is really important only for routines like
{\tt testRead} or {\tt testWrite}, where very fast execution may be desired).
The probe routine also normally sets the field {\tt dev->size} to the size of
the interface in bytes.

\subsection{attach routine}

The {\tt attach} routine is usually the first routine called when we
initiate a communication session. Its purpose is to establish a connection
between the task and the application at the other end. The attach routine
takes one argument, which is a pointer to the device structure, and returns a
non-negative value if it succeeds and a negative value if it fails.
Typically, the reason for the attach routine failing is that the
device on the other end is not listening.

\subsection{read routine}

The read routine is used to read in a packet of information from the
external process. If no packet is immediately available, {\tt read}
will wait for it for a limited period of time.
The default blocking time is system dependent, but the blocking time
can be set using the {\tt IOC\_SET\_BLOCKTIME} I/O control 
(see \ref{ioctl}).

{\tt read} takes three arguments: a pointer to the device descriptor,
a buffer, and a buffer size, which indicates the maximum number
of bytes that can be received. 
\begin{verbatim}
        (*dev->read)(dev, buffer, size);
\end{verbatim}
The function returns the actual
number of bytes received, and may also set the field 
{\tt byteCount} in {\tt dev} to this number. 
If the incoming packet is larger than the
buffer can accommodate, then the packet is dropped and {\tt read}
returns an error (by returning a negative value). A packet containing
zero bytes is a valid packet. 

\subsection{read test routine}

This routine returns true if there is data immediately available
from the external task; i.e., a call to {\tt read} will not block.
{\tt testRead()} takes one argument, which is a pointer to the device descriptor.

\subsection{write routine}

The write routine is used to send a packet of data to the external
process. If the external process is not able to receive the data yet,
{\tt write} will block for a limited period of time until it is.
The default blocking time is system dependent, but the block time
can be set using the {\tt IOC\_SET\_BLOCKTIME} I/O control (see 
\ref{ioctl}).

{\tt write} takes three arguments: a pointer to the device descriptor,
a buffer, and a buffer size, which indicates the number
of bytes to be sent. 
\begin{verbatim}
        (*dev->write)(dev, buffer, size);
\end{verbatim}
The function returns the actual
number of bytes sent, although this will always be equal to
{\tt size} unless the function fails, in which case a negative number is
returned.

\subsection{write test routine}

This routine returns true if it is possible to write to the external
task immediately; i.e., a call to {\tt write} will not block. 
{\tt testWrite()} takes one argument, which is a pointer to the device
descriptor.

\subsection{signal routine}

The signal routine is used to send signals to the external process.
What the external process does with these signals is up to it, although
the basic idea is that the external process can bind them to software
interrupts. The {\tt signal} routine takes two arguments:
a pointer to the device structure, and a signal number.
\begin{verbatim}
        (*dev->signal)(dev, signum)
\end{verbatim}
The number of signals actually implemented is device-specific;
robot interface applications assume that there are at least two signals, where
signal 1 is used to initiate a control cycle on the robot and signal 2
is used to indicate the termination of a control session.

\subsection{ioctl routine}\label{ioctl}

The {\tt ioctl} routine is modeled after the UNIX {\tt ioctl} routine and
is used to set options and parameters within the device. The routine
takes three arguments: a pointer to the I/O device, an integer
specifying an action to be performed, and a generic pointer to data to be
passed in or out. 
\begin{verbatim}
        (*dev->ioctl)(dev, com, data)
\end{verbatim}

The standard I/O control commands include the following:

\medskip
\begin{list}{}{}
\item[$\diamondsuit$]{\tt IOC\_SET\_BLOCKTIME --}
Specifies, in milliseconds, the length of time a {\tt read}
or {\tt write} can block without timing out. {\tt data} should
be a pointer to an integer.

\item[$\diamondsuit$]{\tt IOC\_GET\_BLOCKTIME --}
Returns the length of time, in milliseconds, that a {\tt read}
or {\tt write} can block without timing out. {\tt data} should
be a pointer to an integer.

\item[$\diamondsuit$]{\tt IOC\_TIMEOUT --}
Used to scale internal timeout parameters. This is used by
maintenance software only. {\tt data} should
be a pointer to an integer.

\item[$\diamondsuit$]{{\tt IOC\_SIGINTER\_ENABLE} --}
Enables interrupts on the device. This is used for instances where the
task is running on the arbiter CPU and the task is connected to a
polling interrupt, although the UNIX driver that supports the polling
interrupt should handle this automatically
and make this call (and the next one) probably obsolete.
{\tt data} is ignored.

\item[$\diamondsuit$]{{\tt IOC\_SIGINTER\_DISABLE} --}
Disables device interrupts, as per the call above.
{\tt data} is ignored.
\end{list}
\medskip

\subsection{detach routine}

This routine simply does a ``reset'' on all the registers associated
with the physical interface device and puts them into a known
state (presumably so that subsequent calls to {\tt attach} have a
chance of succeeding). The routine takes one argument, which is a pointer
to the device structure.

\subsection{device fields}

The fields in the {\tt IO\_DEVICE} structure that are visible to the user are:
\begin{verbatim}
        char *name;
        int unit;
        int address;
        char *addrStr;
        int args[MAX_DEVARGS];
        unsigned char *location;
        int size;
        int timeout;
        int blocktime;
        int byteCount;
\end{verbatim}
{\tt name} is simply a copy of the device driver name as specified in the
attach routine. {\tt unit} is a small integer assigned by the system to each
device when it is opened that
distinguishes devices with the same name at different addresses. It can be
used within the driver as an index into an array of per-device data
structures. {\tt address} is the integer address specified in
the attach routine. {\tt addrStr} is a supplemental address information
string, supplied using a field in {\tt struct devAddr}, that is mainly
used by the simulator driver {\tt sim}.
{\tt args} is a set of (optional) argument values, passed in by the {\tt
rciAllocDevice()} routine, that may be used in any way the driver requires.
{\tt location} is a pointer to the memory area that is
mapped onto the device registers; it is normally computed by the probe routine
from the I/O page map information and the device address.
{\tt size} is the size of the device in bytes, normally set by the probe
routine. {\tt timeout} is a timeout parameter 
describing how long the driver
should wait for what it assumes will be an immediate response from the
interface, while {\tt blocktime} is the length of time that the driver should
wait for the external device to be able to respond to a {\tt read} or {\tt
write} request before timing out; both of these parameters can be set with the
{\tt ioctl()} routine (see above). 
{\tt byteCount} is a variable set by the {\tt read()} (or
{\tt write()}) routine to indicate the number of bytes transferred.

\section{Some Basic Notes and Caveats}

It is assumed that RCI device routines do not interrupt each other. 
This is not normally
a problem, since RCI control tasks do not normally interrupt each other,
but it could happen if one routine is executed by an
AST or a trigger routine.

The concept of buffering is not precisely defined for RCI devices.
It is sort of assumed that the buffering, if any, 
is at most one deep; i.e., we cannot return from two successive writes
until the external process executes at least one read.

Routines which are capable of returning an error do so by returning
a negative value and placing an error code on the error stack.

\chapter{Additional Features}

\section{RCI Options}\label{options}

RCI has a set of primitives for setting and clearing various options
that affect the way the system behaves.
These primitives are:
\begin{verbatim}
        rciSetOptions (mask)
        rciClearOptions (mask)
        rciGetOptions (mask)
        rciPutOptions (mask)
\end{verbatim}
The first two routines set or clear, respectively, the options specified in
the bitmask argument {\tt mask}, and return another mask specifying 
the previous settings of those options.
{\tt rciGetOptions()} returns a mask obtained by logically anding
together all presently selected options and the argument mask; {\tt
rciGetOptions(\~{}0)} will hence return the set of all selected options.
{\tt rciPutOptions()} sets all RCI options to the values specified by
the argument {\tt mask}, and returns a mask describing all the previously
selected options.

At the moment, only the option {\tt EXIT\_ON\_ERROR} is implemented,
which causes planning level primitives
to print their error stack and force a program exit if they encounter an
error. 
This saves programmers from having to write code that tests for error
conditions on all the RCI planning level primitives. The option can be
selected with the call
\begin{verbatim}
        rciSetOptions (EXIT_ON_ERROR);
\end{verbatim} 
at the beginning of the program.

\section{RCI Parameters}

RCI has a facility for maintaining named sets of parameters and 
values, which can be used by application software in a manner similar to UNIX
environment variables. The feature is useful since parameters can be 
predefined in a file, providing a way to adjust the action of a program
without recompiling or adding command line options.

An RCI parameter has an alphanumeric name, and is associated with a value
that is either an {\it integer}, a {\it float}, a {\it string}, or an
{\it identifier}. The identifier, actually a special type of string, is
a sequence of alphanumerics (including {\tt \_}) that does not begin with a
number. 

Typically, parameters are defined in a special definition file
called {\tt .rciparams}, which has the following format:
\begin{verbatim}
        name = <set1> <param11> = <value11> <param12> = <value12>  ...
        name = <set2> <param21> = <value21> <param22> = <value22>  ...
                        .               .
                        .               .
                        .               .
\end{verbatim}

The keyword {\tt name} introduces a new parameter set, which is then
followed by parameter/value pairs. White space is ignored except as a 
delimiter, and the character {\tt \#} introduces a comment to the end of the
line. The type of a parameter value (float, integer, string, or identifier)
is determined at read time by inspection, with floats having
a decimal point and/or an exponent.
Integer values may be expressed in decimal, hex, or octal, using the
usual C language notation for these bases. Strings are delimited
either by white space, or by double quotes ({\tt ""}).
{\tt \#} characters can be placed in strings by
preceding them with a backslash.

The first time the RCI parameter package is referenced, the {\tt .rciparams}
file is read and all parameters defined there are remembered. It is possible
to set up a {\tt .rciparams} file in the current working directory, and in the
user's home directory, in addition to the system version located in
{\filefont \$RCCL/conf}. In the case of a
parameters set being multiply defined in two or more files, precedence is
assigned first to the working directory file, then to the home directory
file, and finally to the system file. When a parameter set is
redefined, the entire set is replaced, not just the individual
parameters within it.

Within an application program, a parameter set is opened in a way analogous
to opening a file:
\begin{verbatim}
        s = rciParameters (name, write);
\end{verbatim}
where {\tt name} is the name of the parameter set and {\tt write} is a boolean
value which is true if the parameter set should be writable from the program
and false otherwise. A handle is returned that is used when reading or
writing parameters. If the parameter set is not previously defined
(such as in the {\tt .rciparams} file), then either an empty set is created
if the set is opened to be writable, or the routine returns 0.

The handle returned by {\tt rciParameters} is used with the {\it getpar}
routines to access parameter values from a particular set:
\begin{verbatim}
        getparInteger (ivalp, key, handle)
        getparFloat (fvalp, key, handle)
        getparIdentifier (svalp, key, handle)
        getparString (svalp, key, handle)
\end{verbatim}

Each of these returns 1 if the set {\tt handle} contains a
parameter with the name {\tt key} and a type implied by the routine, and 0
otherwise. If the parameter is present, its value is returned through 
a pointer passed in as the first argument to the routine ({\tt ivalp},
{\tt fvalp}, or {\tt svalp}). The routine {\tt getparString()} will
consider an identifier to be a string, if necessary, and
{\tt getparFloat()} will consider an integer to be a float.

Alternatively, parameters may be set using the {\it setpar} routines:
\begin{verbatim}
        setparInteger (ival, key, handle)
        setparFloat (fval, key, handle)
        setparIdentifier (sval, key, handle)
        setparString (sval, key, handle)
\end{verbatim}
which return 1 if successful, or 0 if the parameter set is not writable.
The first argument to these routines is simply the value to be set. At the
moment, the {\tt setpar} routines have not been used in any applications.

A very simple example of the RCI parameter facility is given below, in which
some parameters are defined in the {\tt .rciparams} file and then printed out
by a main program.
\subsubsection*{.rciparams file}
\begin{verbatim}
        # test entry in the .rciparams file
        name = TESTSET  param1 = 0x1234  param2 = sampleString  
                                         param3 = 1.2
\end{verbatim}

\subsubsection*{test program}
\begin{verbatim}
   main()
   {
           int p, i;
           char *s;
           float f;
   
           p = rciParameters ("TESTSET", 0);
   
           getparInteger (&i, "param1", p);
           getparString (&s, "param2", p);
           getparFloat (&f, "param3", p);
   
           printf ("The contents of the parameter set are:\n");
           printf ("0x%x %s %f\n", i, s, f);
   }
\end{verbatim}

\section{The Parameter Set RCISYS}

A special RCI parameter set called {\tt RCISYS} is reserved by the
RCI system for setting certain site-specific parameters. 
The manual page {\tt RCISYS\_params(5)} should be consulted for
a description of the parameters currently implemented.

\section{The Vector Routines}

To make life easier when doing operations with vectors, a small package of
vector routines has been defined that copy, add, subtract, scale, print, and
read vectors, where a {\it vector} in this case is just an array of either
floats or doubles. These routines may be called from any part of an RCI 
program.

To add, element by element, two equal sized vectors of floats, the routine
\begin{verbatim}
        addVf (vr, v1, v2, size)
\end{verbatim}
can be used, where {\tt vr} is the result vector, {\tt v1} and {\tt v2} are
the input vectors, and {\tt size} is the number of elements in the vector.
The {\tt f} at the end of the routine name indicates that the procedure
is handles vectors of floats. An analogous routine, {\tt addVd}, exits
for vectors of doubles.

Similar routines exist to do other arithmetic operations:
\begin{verbatim}
        subtractVf (vr, v1, v2, size)
        scaleVf (vr, a, v1, size)
        combineVf (vr, a, v1, b, v2, size)
        dotVf (v1, v2, size);
        normVf (v1, size);
\end{verbatim}
{\tt subtractVf()} subtracts {\tt v1} from {\tt v2}, {\tt scaleVf()}
multiplies {\tt v1} by the scalar {\tt a}, {\tt combineVf()} forms the linear
combination
\[
{\bf v}_r =  a {\bf v}_1 + b {\bf v}_2,
\]
{\tt dotVf()} returns a float equal to the dot product of two vectors, and
{\tt normVf()} returns a float equal to the 2-norm of a vector.

To copy to vectors, we can use the routine
\begin{verbatim}
        copyVf (vr, v1, size);
\end{verbatim}
and to zero a vector, we can use
\begin{verbatim}
        zeroVf (vr, size);
\end{verbatim}

Converting vectors from float to double or double to float can be done using
the routines
\begin{verbatim}
        copyVfd (vd, vf, size);
        copyVdf (vf, vd, size);
\end{verbatim}
respectively, where {\tt vd} is a vector of doubles and {\tt vf} is a vector
of floats.

Reading a vector can be accomplished using either of
\begin{verbatim}
        scanVf (v, size);
        fscanVf (fp, v, size);
\end{verbatim}
which read in a vector of {\tt size} elements either from {\tt stdin} or
the stream {\tt fp}, respectively.

Similarly, printing a vector can be done using either of
\begin{verbatim}
        printVf (fmt, v, size);
        fprintVf (fp, fmt, v, size);
\end{verbatim}
which prints the contents of a vector of {\tt size} elements onto either
{\tt stdout} or the stream {\tt fp}, respectively. The format string in
the print routines is assumed to contain a single {\tt printf()} style 
floating point format ({\tt \%f} or {\tt \%g} style), which is used to print
each element in the vector, separated by a single space. Other characters
in the format string on either side of the floating point format appear
verbatim on either side of the vector. As an example, if we have a 
vector {\tt v} with the elements 1.1, 2.2, and 3.3, then the construction
\begin{verbatim}
        printVf ("--- %4.2f ---\n", v, 3);
\end{verbatim}
would yield as output
\begin{verbatim}
        --- 1.10 2.20 3.30 ---
\end{verbatim}

Each of the routines for float vectors, whose name ends in {\tt f}, 
has a counterpart for double vectors whose name ends in {\tt d}.

\chapter{Robot Support: Parameters and Computation Functions}

RCI provides a robot parameter ``database'', as well
as functions for doing various types of robot-specific computations.

RCI has an site-specific table of robots that the system ``knows about''
and parameter information is maintained
for these robots. To determine if a robot with a particular name is in fact
known to the RCI system, one can use the function {\tt find\_robot()}, which
returns the id number associated with a particular manipulator:
\begin{verbatim}
        id = find_robot ("<robotName>");
\end{verbatim}
{\tolerance=10000
The id number is just the table index plus 1.
If a robot is not known to RCI, then {\tt find\_robot()} returns 0.

Each robot has a defined {\it class}, which describes, generally,
what type of robot it is. Different classes are defined in the
file {\filefont h/robotClass.h}. Classes which are currently supported
include {\tt PUMA} (the PUMA), {\tt STAN} (the Stanford arm), and {\tt ELBOW}
(the elbow manipulator). 
The class for a particular robot can be obtained using the routine
\begin{verbatim}
      class = robot_class ("<robotName>");
\end{verbatim}

Robot-specific parameters and run-time variables are defined 
by three data structures:

\medskip
\begin{list}{}{}
\item[1.]{\tt JLS} -- contains parameters which define the robot at the joint
level, and includes such things as gear ratios, joint and velocity limits,
data for converting between joint coordinates and motor shaft coordinates,
and pointers to routines which perform these conversions.

\item[2.]{\tt KYN} -- contains kinematic and dynamic parameters for the robot,
as well as the routine interfaces for implementing various
kinematic and dynamic functions. 

\item[3.]{\tt VAR} -- scratch pad area for storing derived robot state
information at run time (such as the sines and cosines of the joint angles or
the coefficients of the Jacobian), so that it will not have to be recalculated
each time it is needed. The actual
definition of the
{\tt VAR} structure depends on the particular robot class.
\end{list}
\medskip

}
\section{{\tt JLS} Structure}

\subsection{description}

The {\tt JLS} structure provides a complete joint level definition of the
robot. A summary of the fields in the structure is

\medskip
\begin{list}{}{}
\item[$\diamondsuit$] The number of joints and joint couplings
\item[$\diamondsuit$] The joint {\it type} (revolute or prismatic)
\item[$\diamondsuit$] The forward and inverse gear ratio matrix
\item[$\diamondsuit$] Encoder to joint value conversion data
\item[$\diamondsuit$] Joint torque to motor torque conversion data
\item[$\diamondsuit$] Calibration parameters
\item[$\diamondsuit$] Joint travel, velocity, acceleration, jerk, and torque
limits
\item[$\diamondsuit$] Utility information such as the default set of park
joint values and scalars indicating the nominal velocity, acceleration, and
jerk 
\item[$\diamondsuit$] Conversion functions for mapping between encoders and
joint values, encoder velocity and joint velocity, and motor torque and joint
torque. 
\end{list}
\medskip

A complete description of all the fields in the structure is contained in the
manual page {\tt JLS(3)}.

The definition of the {\tt JLS} structure is constant for all robots.
The information used to instantiate the structure
for a particular robot is defined in the
the file {\filefont conf/<robotName>.jls}. Information
from this file is read, on demand, by the routine {\tt getJls()}.
In some versions of RCCL/RCI, the ascii file
{\tt <robotName>.jls} is automatically converted
into a binary file {\tt <robotName>.JLS} 
(using the program {\tt makejls}), and the binary 
file is then read by {\tt getJls()}.

Regular programs can obtain a pointer to a robot's
{\tt JLS} structure using the call
\begin{verbatim}
        jls = getJls ("<robotName>");
\end{verbatim}
{\tolerance=10000
which will instantiate and return a pointer to a {\tt JLS} structure for the
robot {\tt <robotName>}. 

RCI programs which want to access the {\tt JLS} structure from the
control level must use {\tt rciGetJls()}. For each robot name,
an initial call to {\tt rciGetJls()}
must first be made from the planning level, since this reads in information
from a file. Subsequent calls for the same robot may be made from anywhere
in the program.

\begin{quote}
{\bf NOTE}: On Sun4 and MicroVAX systems, the first call to 
{\tt getJls()} should also be made when control tasks are not active, because
of interactions with the memory locking code.
\end{quote}

A pointer to a {\tt JLS} structure
is automatically made available for any robot which is
attached to an RCI task (see section \ref{attachrobot}).

\subsection{joint to actuator conversion functions}

The {\tt JLS} structure provides pointers to several routines
which convert between the robot's joint and actuator coordinate systems.
Storing these functions in pointers allows different versions
of them to be implemented for different types of robots,
which in turn means they can be made to run quite quickly
(since loops can be unrolled and joint coupling calculations, if any, made
explicit). 

The conversion functions provided by the {\tt JLS} structure include:
\begin{verbatim}
        angleToEncoder (enc, ang, jls)       -- joint displacement
        encoderToAngle (ang, enc, jls)          conversion
        jointToEncoder (enc, jnt, jls)       -- joint velocity
        encoderToJoint (jnt, enc, jls)          conversion

        mtorqueToJtorque (jtor, mtor, jls)   -- torque conversion
        jtorqueToMtorque (mtor, jtor, jls)
\end{verbatim}

Notice that the routines take a pointer to the {\tt JLS}
structure itself as an argument; this is where they obtain their
parameter information.
For example, to convert a set
of joint values to encoders, one can use the following
construction:
\begin{verbatim}
        (*jls->angleToEncoder)(enc, ang, jls);
\end{verbatim}
If one is not concerned about execution speed, 
there are generic conversion routines, that will work for any robot,
which have the same names as the
above {\tt JLS} fields and which accept the same arguments.

}

In application software, one frequently wants to specify or display joint
angles in degrees, although they are often represented internally in
radians. Converting joint angle values back and forth between degrees
and radians is fairly common. Since not all joints of a robot are revolute,
general purpose code must consult the {\tt jtype} field
of the {\tt JLS} structure to determine the type of each joint:
the character {\tt'R'} denotes a revolute joint, while {\tt 'P'} denotes
a prismatic one. 

Two routines are provided to help do this:
\begin{verbatim}
        radianToDegree (deg, rad, jls)
        degreeToRadian (rad, deg, jls)
\end{verbatim}
Each of these applies the indicated conversion to the joint
values given by the second argument, and returns the output in the
first argument. Conversions are done {\it only} for joints which are revolute.
Information about the number of joints and the joint type is determined from 
the {\tt jls} structure.

\subsection{conversion program example}

To illustrate the use of the {\tt JLS} structure in a program by itself, we
present a program that converts encoder counts to joint values for any robot
known to the RCI system.
\begin{verbatim}
   #include "../h/cdefs.h"
   #include "../h/robotMath.h"
   #include "../h/robot_jls.h"
   
   float ang[MAXJNTS];
   int enc[MAXJNTS];
   
   char **argvec;

   main(argc, argv)
   int argc;
   char *argv[];
   {
           int j;
           JLS *jls;
   
           argvec = argv;
           argc--; argv++;
           if (argc != 1)
            { usageMsg (-1, "%s <robot-name>\n", argvec);
            }
           if ((jls = getJls (*argv)) == NULL)
            { printErrors ();
              exit (-1);
            }
           while (1)
            { if (scanVf (ang, jls->numJ) != 1)
               { exit (0);
               }
              degreeToRadian (ang, ang, jls);
              (*jls->angleToEncoder)(enc, ang, jls);
              for (j=0; j<jls->numJ; j++)
               { printf ("%6d ", enc[j]);
               }
              putchar ('\n');
            }
   }
\end{verbatim}

The program first reads in the name of the robot from the argument list. 
It then calls {\tt getJls()} to obtain a pointer to a {\tt JLS} structure for this
robot; if this call fails (probably because the named robot is unknown to RCI)
then the error stack is printed (see section \ref{estack}) and the program
exits. The rest of the program is just an infinite loop which reads in sets of
joint values using {\tt scanVf()}, converts them to radians using 
the routine {\tt degreeToRadian()}, converts them to encoder counts using the
{\tt JLS} {\tt angleToEncoder} routine, and then
prints them out.
The printing is done using a loop since {\tt enc} is an
array of integers and {\tt printVf()} works with arrays of floats, and
we have not implemented a {\tt printVi()} routine.

\section{{\tt KYN} Structure}

\subsection{description}

This data structure contains kinematic
parameters such as {\bf A} matrix offsets, dynamic parameters such as
inertias and friction coefficients, and a set of interface functions
for performing kinematic and dynamic computations.

The {\tt KYN} structure is defined as follows:
\begin{verbatim}
        typedef struct _KYN {
           GEN_KYN *gen;
           void *ext;
        } KYN;
\end{verbatim}

The {\tt gen} field points to a substructure of type
{\tt GEN\_KYN}, which contains parameters generic to
most serial link robots. This includes such things
as ``A'' matrix parameters
and joint friction coefficients. Dynamic parameters, such as
link inertias and masses, are in the process of being added.

The {\tt ext} field points to a data area whose definition depends
on the robot's class. This was done because certain
types of parameters, such as implicit
parameters which are precomputed for computational efficiency, can vary
widely from one robot type to another. Each class of robot hence 
defines its own extension to the {\tt KYN} structure; the one for the PUMA
robots, defined in {\tt puma\_kynvar.h}, is called {\tt PUMA\_KYN}.

Information for the {\tt KYN} structure is read into the program
from the ascii file {\tt \$RCCL/\-conf/\-<robotName>.kyn}.

Regular programs can obtain a pointer to robot's {\tt KYN} structure
using the call
\begin{verbatim}
        kyn = getKyn("<robotName>", &size);
\end{verbatim}
The second argument is an optional integer pointer
for returning the size of the class-specific structure
pointed to by the {\tt ext} field.

RCI programs which want to access the {\tt KYN} structure from the
control level must use {\tt rciGetKyn()}. For each robot name,
an initial call to {\tt rciGetKyn()}
must be made from the planning level, since this reads in information
from a file. Subsequent calls for the same robot may be made from anywhere
in the program.
A pointer to a {\tt KYN} structure
is automatically made available for any robot which is
attached to an RCI task (see section \ref{attachrobot}).

\subsection{kinematic and dynamic functions}\label{sec.kynfxns}

The {\tt KYN} structure is used as an argument to the following
generic functions for computing robot kinematics and dynamics:
\begin{verbatim}
        fwdKinematics (t6,c,j6,kyn,var)
        invKinematics (j6,t6,c,refj,kyn,jls,var)
        solveConf (c,j6,kyn)

        fwdJacob (dc,dj,j6,kyn)
        invJacob (dj,dc,j6,kyn,epsilon)
        fwdJacobT (t,f,j6,kyn)
        invJacobT (f,t,j6,kyn,epsilon)

        gravload (t,j6,kyn)

        strToConfig (c,s,kyn)
        configToStr (s,c,kyn)
\end{verbatim}
The {\tt kyn}, {\tt var}, and {\tt jls} arguments are
pointers to the robot's {\tt KYN}, {\tt VAR}, and {\tt JLS} data structures,
respectively. Detailed descriptions of each of these functions
can be found in the {\it RCI Reference Manual}.
The {\tt GEN\_KYN} component of the {\tt KYN} structure
contains pointers to internal
routines, specific to each robot class, which implement these
functions.
The robot class itself is described by the field {\tt class} in the {\tt
GEN\_KYN} structure. 

\section{{\tt VAR} Structure}

\subsection{description}

As mentioned in the previous section,
the {\tt VAR} structure is a place for storing terms that arise in kinematic
and dynamic robot computations so
that they do not have to be recomputed when used in other
computations. The definition of this structure depends very much
on the robot's class. The {\tt VAR} structure for the PUMA robot, called
{\tt PUMA\_VAR}, is defined in the file {\tt puma\_kynvar.h} and contains the
following elements:

\medskip
\begin{list}{}{}
\item[$\diamondsuit$]
The sines and cosines of the joint angles;
\item[$\diamondsuit$]
Some of the terms of the Jacobian;
\item[$\diamondsuit$]
Terms used in computing the inverse Jacobian;
\item[$\diamondsuit$]
The matrix U5 between link 4 and link 6.
\end{list}
\medskip

Programs are responsible for allocating their own {\tt VAR}
structures. The size required for a particular robot may be obtained
using the function {\tt getVarSize()}, so that allocation
may be done as follows:
\begin{verbatim}
        var = malloc (getVarSize("<robotName>"));
\end{verbatim}
The allocated space may be cast to the appropriate robot-specific structure.
If the allocation is done from the RCI control level, then {\tt rciMalloc()}
should be used instead. If the structure is to be globally available
to different RCI tasks, then {\tt allocMem()} should be used.

A {\tt VAR} structure is also automatically allocated
for each robot attached to an RCI task
(see section \ref{attachrobot}).

\subsection{kinematic and dynamic functions using the {\tt VAR} structure}

If the functions described in section \ref{sec.kynfxns}
are called multiple times with the robot located at the
same position, certain common terms, like the sines and cosines of the joint
angles, or coefficients of the Jacobian, will be recomputed when they
do not need to be. The {\tt VAR} structure is designed to help reduce this
problem.

Some of the routines described in section \ref{sec.kynfxns} have variants,
whose names end in {\tt Var}, that use the {\tt VAR} structure in place of
explicit joint values.
These routines currently include:
\begin{verbatim}
        fwdJacobVar (dc,dj,var,kyn)
        invJacobVar (dj,dc,var,kyn,epsilon)
        fwdJacobTVar (t,f,var,kyn)
        invJacobTVar (f,t,var,kyn,epsilon)
        gravloadVar (t,var,kyn)
\end{verbatim}

The terms in the {\tt VAR} structure must be updated for 
the correct robot position before these routines are called.
{\tt VAR} structures which are explicitly allocated by the user
must also be updated by the user.
There are two routines to update a {\tt VAR} structure:
\begin{verbatim}
        updateVar (var,ang,kyn)
        updateVarXsincos (var,ang,kyn)
\end{verbatim}
{\tt updateVar()} updates every entry in the structure. {\tt updateXsincos()}
updates every entry {\it except} for the the sines and cosines. This latter
routine is provided since it is frequently possible to update the sine and
cosine terms by using either {\tt invKinematics()} or {\tt fwdKinematics()}.

If the {\tt VAR} structure is the one allocated
when a robot is attached to a control task
(section \ref{attachrobot}), then this updating may be
done automatically by supplied control task software such as RCCL or 
CHASE. The user should {\bf not} modify this {\tt VAR} structure
unless sure that no other system software is doing so.

\chapter{Robot Support: Attaching Robots to RCI Tasks}

An RCI control task can attach one or more robots to itself. {\it Attaching}
a robot implies the following:

\medskip
\begin{list}{}{}
\item[1.]Robot parameter data structures ({\tt JLS}, {\tt KYN}, and {\tt VAR},
described above) are allocated and made available to the task.

\item[2.]A set of interface functions are provided through which the control
task can communicate with the robot. The interface functions, which are called
at the 
discretion of the control task, maintain a robot state ``blackboard''
(the HOW structure) which provides instantaneous information about the
state of the arm and various sensor devices associated with it. Control of the
arm is achieved using a set of command macros whose requests are dispatched
to the arm by the interface functions.
\end{list}

\section{Attaching the Robot}\label{attachrobot}

A robot is attached to an RCI task using the {\tt rciAttachRobot()} primitive,
which is called from the planning level:
\begin{verbatim}
        num = rciAttachRobot (td, "<robotName>", devAddr);
\end{verbatim}
attaches the robot {\tt robotName} to the task {\tt td} and returns a small
number which indexes the robot within that task
(this is {\bf not} the same id number returned
by {\tt find\_robot()}). The third argument, which is optional,
specifies the RCI I/O device which the robot 
interface functions will use to communicate with the robot (see section
\ref{formaldev} for a description of the RCI I/O devices). If the third
argument is omitted (by setting it to {\tt NULL}) the address of the I/O
device is taken from the file {\filefont \$RCCL/conf/robots}\footnote
{The {\tt robots} file is described in the manual {\it RCCL/RCI Startup and
Installation Guide}, as well as the manual page {\tt robots(5)}.}.

\begin{quote}
{\bf NOTE:} If you are running RCI in simulation mode
(see section \ref{simtools}) and you wish to
use the simulator driver {\tt sim}, then
the addressing information must be supplied through the {\tt devAddr} 
argument; it cannot be specified in the {\tt robots} file. The wrapper
routine {\tt simAttachRobot()} provides an easier way to handle this.
\end{quote}

{\tt rciAttachRobot()} returns -1 if it fails, and if no robots
are already 
attached to the task, the returned number will be 0.

A robot can be detached by calling {\tt rciDetachRobot()} from the planning
level:
\begin{verbatim}
        rciDetachRobot (td, num);
\end{verbatim}

Once a robot has been attached to a task, then any part of the RCI program
(planning or control level) can
obtain information about it using the {\tt RCI\_RBT} structure, 
which can be obtained from the task descriptor and the number
returned by {\tt rciAttachRobot()} with the macro call
\begin{verbatim}
        RCI_RBT *rbt;
        rbt = TASKROBOT(td, num)
\end{verbatim}
Each task can have up
the {\tt MAX\_TASKROBOTS} attached to it, and robot descriptors for these
are placed in a small array contained in the task descriptor. {\tt num}
is an index into that array.
If no other robots are attached to the task, then {\tt num} will
be 0:
\begin{verbatim}
        rbt = TASKROBOT(td, 0)
\end{verbatim}
It is sometimes also desirable to search through
all of the robots attached to a task, which can be done as follows:
\begin{verbatim}
        int n;
        for (n=0; n<MAX_TASKROBOTS; n++)
         { if (rbt = TASKROBOT(td, n))
            { 
                ...
            }
         }
\end{verbatim}
{\tt TASKROBOT()} returns {\tt NULL} if there is no robot at the
specified index.

Another way to obtain the robot descriptor is to use the function
{\tt getTaskRobot()}, which uses the name of the robot as a key
and is handy
for referencing a robot when the task it is attached to is unknown:
\begin{verbatim}
        rbt = getTaskRobot ("<robotName>")
\end{verbatim}
A similar routine, {\tt findTaskRobot()}, returns the robot descriptor
using the robot id (as returned by {\tt find\_robot()}) as a key.
The total number of robots attached to a task can be obtained with the macro
{\tt TASKNUMROBOTS(td)}.
A pointer {\tt dev} to the RCI I/O device being used by a particular robot
can be obtained with the macro {\tt ROBOT\_DEV(rbt)}.

The definition of the {\tt RCI\_RBT} structure is given below:
\begin{verbatim}
   typedef struct _RCI_RBT {
      int id;              /* robot identifier */
      JLS *jls;            /* robot joint level parameters */
      HOW *how;            /* robot state variable */
      CHG *chg;            /* robot command 'blackboard' */
      KYN *kyn;            /* kinematic params */
      void *var;           /* state variable area */
      int kynSize;         /* size of robot-specific KYN extension */
      int varSize;         /* size of robot-specific VAR */
   
      int class;           /* robot class */
      char *name;          /* pointer to robot name */
   
      int (*startup)();    /* robot startup function */
      int (*release)();    /* robot release function */
      int (*input)();      /* robot input function */
      int (*output)();     /* robot output function */
      int (*wakeup)();     /* robot wakeup function */
      int (*ready)();      /* robot ready function */
   
      int wakeupArg;       /* argument for wakeup function */
      int readyArg;        /* argument for ready function */
   
      void *dev;          /* pointer to the I/O device */
      int idev;            /* pointer to interrupt fd */
   
      int notice;          /* scratch area for interface functions */
   } RCI_RBT;
\end{verbatim}

The {\tt id} is the id number returned by {\tt find\_robot()}. The {\tt jls},
{\tt kyn}, and {\tt var} fields point to the {\tt JLS}, {\tt KYN}, and 
{\tt VAR} parameter
blocks discussed above, {\tt kynSize} gives the size of the
{\tt ext} component of the {\tt KYN} structure, 
and {\tt varSize} give the size
of the {\tt VAR} structures in bytes. 

{\tt class} describes the type of the robot, using one of the types defined in
{\tt robotClass.h}; the type is used to select the interface functions which
are assigned to the robot. {\tt name} is a pointer to the robot name.

The fields {\tt startup} through {\tt ready} are the interface functions,
which will be talked about in section \ref{robotinterface}.
{\tt wakeupArg} and {\tt readyArg}
are arguments used by the {\tt wakeup} and {\tt ready} interface functions.
{\tt dev} is a pointer to the RCI I/O device used by the interface functions,
{\tt idev} is a file descriptor of a UNIX device which can provide a
polling interrupt (section \ref{polling}) for a task which has this robot
attached, and {\tt notice} 
is a scratch register that can be used by the interface functions.

We shall now describe some of these features in more detail.

\section{The Robot Interface Functions}\label{robotinterface}

Each robot attached to an RCI task comes with 6 interface 
functions: {\tt startup}, {\tt input}, {\tt output},
{\tt release}, {\tt wakeup}, and {\tt ready}. 
The {\tt startup} function is called
by the task's {\it startup} and initiates 
interaction with the robot.
The {\it input} function is called 
from within the task's main {\it control} routine; it
reads information in from the robot, performs joint and velocity
limit checking, if required,
and instantiates the robot's HOW structure. The
{\tt output} function is also called from the robot's main
control routine; it is responsible for sending to the robot all
commands which have been specified since the last time it was
called. The {\tt release} function should be called
from the task's release function; it sends information to the
robot telling it that the control session is over. The 
{\tt wakeup} function is used to wake the robot up and
tell it to start collecting data
for the next control cycle; it is called by either the main control function 
or a trigger or AST function. The {\tt wakeup} function is used only
when the robot is being run in {\it slave} mode; i.e., RCI is
controlling the timing of the interaction cycles. When the robot has
finished collecting data and is ready to be read by the RCI task,
this condition may be detected with the {\tt ready} function.

\subsection{startup function}

This function should be called from within the user's {\it startup}
control routine. It takes two arguments: a task descriptor
and a robot descriptor. If it returns a negative number, this indicates
that it has detected an error and called {\tt rciAbort()}. 
\begin{verbatim}
        startControl(td)
        RCI_DESC *td;
        {
                RCI_RBT *rbt = TASKROBOT(td, 0);

                ...

                if ((rbt->startup)(td, rbt) < 0)
                 { return;
                 }
                ...
        }
\end{verbatim}

If the robot control task is attached to multiple robots, then
the startup function for each should be called during the user's
startup function:

\begin{verbatim}
        startControl(td)
        RCI_DESC *td;
        {
                RCI_RBT *rbt;
                int k;

                ...

                for (k=0; k<MAX_TASKROBOTS; k++)
                 { if (rbt = TASKROBOT(td, k))
                    { if ((rbt->startup)(td, rbt) < 0)
                       { return;
                       }
                    }
                 }

                ...
        }
\end{verbatim}

\subsection{robot input function}

The robot input function should be called from the user's main
control routine every time it is desired to update the HOW
blackboard associated with that robot.

The function takes two arguments: a pointer to the task descriptor,
and a pointer to the robot descriptor. If the function returns a 
negative value, this indicates that it has detected an error and asserted
an abort condition.
When called, the function will request a {\it read} from the robot,
using an RCI I/O driver {\tt read} routine.
If the robot is not ready, it will wait for the robot, up to
a length of time normally determined by the blocking time
assigned to the {\tt read} function. The interface function {\it ready} 
(described below) can be used by a control function to explicitly check if
a robot is ready.

Examples of the usage of the input function are given in section
\ref{rbtioexample}.

\subsection{robot output function}

The robot output function sends to the robot all commands which have
been specified for it since the last time the output function was called.
It assumes that a robot input function has been called a short time
previously.

The function takes two arguments: a pointer to the task descriptor,
and a pointer to the robot descriptor. If the function returns a 
negative value, this indicates that it has detected an error and 
called {\tt rciAbort()}.
When called, the function assumes that the robot is ready to receive
data, and will call {\tt rciAbort()} if this is not the case.

\subsection{example}\label{rbtioexample}

A simple example of using the input and output functions for all the
robots connected to an RCI task is given here:

\begin{verbatim}
   doControl(td, arg)
   RCI_DESC *td;
   int arg;
   {
           RCI_RBT *rbt;
           int k;

           ...

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k))
               { if ((*rbt->input)(td, rbt) < 0)
                  { return;
                  }
               }
            }

           ... do computations based on input data ...

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k))
               { if ((*rbt->output)(td, rbt) < 0)
                  { return;
                  }
               }
            }

           ... do more computation ...
   }
\end{verbatim}

\subsection{release function}

The robot release function should be called whenever the control
task wishes to let go of the robot, or releases itself. 

The function takes three arguments: a pointer to the task descriptor,
a pointer to the robot descriptor, and code describing the reason for
the release. If the function returns a 
negative value, this indicates that it has detected an error and
called {\tt rciAbort()}.

The release code value should be one of the following:

\begin{verbatim}
        RBT_NORMAL
        RBT_SOFTERROR
        RBT_HARDERROR
\end{verbatim}
{\tt RBT\_NORMAL} implies a normal release (such as occurs when
the task release function is called with the code {\tt RELEASE\_REQ}).
{\tt RBT\_SOFTERROR} means that something has gone wrong but we can still
leave the power on if requested by {\tt how->powerOnRelease}.
{\tt RBT\_HARDERROR} means that something has gone wrong and robot
power should be turned off.

The release function should be called for all active robots from the
task's own release function, as in the example below:

\begin{verbatim}
   releaseControl(td, arg, code)
   RCI_DESC *td;
   int arg, code;
   {
           RCI_RBT *rbt;
           int rcode;
           int k;

           ...

           rcode = (code == RELEASE_REQ ? RBT_NORMAL : RBT_HARDERROR);

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k))
               { (rbt->release)(td, rbt, rcode);
               }
            }

           ...
   }
\end{verbatim}

\subsection{ready and wakeup and the scheduling disciplines}

The code examples given above are incomplete in that they 
do not consider how the robot is told to start collecting
feedback data for a control cycle, or how a task may voluntarily determine
when this data is ready. This is accomplished using
the {\tt wakeup} and {\tt ready} functions, which are used
in different ways depending on the task's scheduling discipline.

The most straight-forward
scheduling method is the {\tt ON\_CLOCK} discipline, under which the
task is simply woken up at a regular time interval. When the task wakes
up, it can then signal each robot which is attached to it
using the robot's {\tt wakeup} function. The {\tt wakeup} function
takes one argument, which is contained in the {\tt wakeupArg}
field of the {\tt rbt} structure. The function can hence
be called using either the construct {\tt (*rbt->wakeup)(rbt->wakeupArg)},
or the equivalent macro {\tt ROBOT\_WAKEUP(rbt)}.

Once each robot has been woken up, it is necessary to wait for
it to collect its feedback data. 
The {\tt input} function will normally block
until this is the case (providing the wait is not too long), 
but if several robots
are attached to a task it may be desired to increase efficiency by
running each input function only when the robot is in fact ready.
The {\tt ready} function can be used to determine this.
The {\tt ready} function
takes one argument, which is contained in the {\tt readyArg}
field of the {\tt rbt} structure, and returns 1 if the robot is ready
to be read from and 0 otherwise. The function can
be called using either the construct {\tt (*rbt->ready)(rbt->readyArg)},
or the equivalent macro {\tt ROBOT\_READY(rbt)}.

Note that the arguments for the {\tt ready} and {\tt wakeup} calls
are different than for the other robot communication functions. The reason
for using only one argument is so that they can be used directly
as {\tt wakeup} or {\tt trigger} functions for an RCI task. Making
that argument a field in the {\tt rbt} structure means that it has
to be set; normally, this will be done by the {\tt startup}
function for that robot, and so it is {\bf illegal} to use the
{\tt ready} or {\tt wakeup} functions before the startup function
has been called (the results being, in that favorite DEC parlance,
unpredictable).

The extra code required to wake up each robot and then
wait for each to become ready before issuing its {\tt input} 
routine is given below:

\begin{verbatim}
   doControl(td, arg)
   RCI_DESC *td;
   int arg;
   {
           RCI_RBT *rbt;
           int k;

           /* signal each robot */

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k))
               { ROBOT_WAKEUP(rbt);
               }
            }
           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k))
               { while (!ROBOT_READY(rbt))
                    ;
                 (*rbt->input)(td, rbt);
               }
            }

           ... do robot output as in examples above ...

   }
\end{verbatim}

This may seem somewhat inefficient, and it is, since the task must wait
around for each robot to become ``ready'' after it has been signaled.
This overhead can be reduced if we use the {\tt ON\_FUNCTION}
discipline instead on the {\tt ON\_CLOCK} discipline and make
one of the robots a {\it master} device (i.e., it regulates
the control cycle timing intervals instead of the RCI task). 
To do this, we
need to set the {\tt wakeup} function for the task to be the
wakeup function for the robot; this should be done in the
{\tt startup} routine:

\begin{verbatim}
   RCI_RBT *mrbt;          /* already set to the 'master' robot */

   controlStartup(td, arg)
   RCI_DESC *td;
   int arg;
   {
           ... startup the robots as described above ...

           rciWakeupOn (td, mrbt->ready, mrbt->readyArg);
   }
\end{verbatim}

In the main control function, we can then signal the
other robots and let then collect data while we are executing the
input function for the master robot:

\begin{verbatim}
   RCI_RBT *mrbt;          /* set to the 'master' robot */

   doControl(td, arg)
   RCI_DESC *td;
   int arg;
   {
           RCI_RBT *rbt;
           int k;

           /* signal all the other robots */

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k) && rbt != mrbt)
               { ROBOT_WAKEUP(rbt);
               }
            }

           /* do the input for the master robot */

           (*mrbt->input)(td, mrbt);

           /* wait for and gather input from all other robots */

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k) && rbt != mrbt)
               { while (!ROBOT_READY(rbt))
                    ;
                 (*rbt->input)(td, rbt);
               }
            }

           ... do robot output as in examples above ...

   }
\end{verbatim}

A more symmetric approach is to run the task off of the RCI clock,
but indirectly, using the {\tt ON\_TRIGGER} scheduling discipline.
In this mode, RCI will call a specified trigger function at the
task's prescribed interval, which can be used to wake up all of
the task's robots; the task itself can then be set to wake up
when one of the robots becomes ready. The trigger function should
be set up in the {\tt startup} control function. As with the
{\tt ON\_FUNCTION} discipline, it is also necessary to specify
a wakeup function. The trigger is set using the {\tt rciSetTrigger()}
function, which takes two arguments: a pointer to the function,
and an integer argument with which the trigger is called.
It is necessary to reset the trigger during each control cycle:
this restriction is imposed since the trigger may use I/O devices
in ways that conflict with their use by the main control function, and
therefore it is important that the main function can set the trigger
at a point where it is known to be safe to do so. 

A trigger function and the code which enables it in the control
{\tt startup} routine is shown below. This time, there
is no need for a ``master'' robot.
\begin{verbatim}
   triggerFxn(td)
   RCI_DESC *td;
   {
           RCI_RBT *rbt;
           int k;

           /* wakeup all the robots */

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (rbt = TASKROBOT(td, k))
               { ROBOT_WAKEUP(rbt);
               }
            }
   }

   controlStartup(td, arg)
   RCI_DESC *td;
   int arg;
   {
           ... startup the robots as described above ...

           rciWakeupOn (td, mrbt->wakeup, mrbt->wakeupArg);
           rciSetTrigger (triggerFxn, td);
   }
\end{verbatim}

The corresponding code in the main control routine looks like this:

\begin{verbatim}
   doControl(td, arg)
   RCI_DESC *td;
   int arg;
   {
           RCI_RBT *rbt;
           unsigned long notdone;
           int k;

           /* wait for and gather input from all other robots
              (master robot, at least, will be ready) */

           for (k=0; k<MAX_TASKROBOTS; k++)
            { if (TASKROBOT(td, k))
               { notdone |= (1<<k);
               }
            }
           while (notdone)
            { 
              for (k=0; k<MAX_TASKROBOTS; k++)
               { if (rbt = TASKROBOT(td, k))
                  { if (ROBOT_READY(rbt))
                     { (*rbt->input)(td, rbt);
                       notdone &= ~(1<<k);
                     }
                  }
               }
            }

           ... do robot output as in examples above ...

           /* reset trigger */

           rciSetTrigger (triggerFxn, td);

   }
\end{verbatim}

Finally, as indicated earlier in the discussion on trigger functions,
it is necessary to disable any trigger functions before releasing:

\begin{verbatim}
   releaseControl(td, arg, code)
   RCI_DESC *td;
   int arg, code;
   {
           RCI_RBT *rbt;
           int rcode;
           int k;

           rciSetTrigger (NULLF, 0);

           ...
   }
\end{verbatim}

\section{The HOW Blackboard}

The HOW structure is used to store run-time feedback information, including
robot position and sense information, as well as data read back from various
types of input devices. Keeping this structure updated is the responsibility
of the {\tt input} interface function. 

Not all of the fields in the HOW structure are necessarily maintained
by a given robot / controller combination.
A brief description of the fields is given below; for a detailed description
see {\tt man how}:

\medskip
\begin{list}{}{}
\item[$\diamondsuit$] Information about the robot and what sensor and I/O
options are available to it. This information is read in once by the {\tt
startup} interface function, and remains constant for the duration of the
control session. The fields include:
\begin{verbatim}
        long options;
        char numAdc;
        char numDac;
        char numPioIn;
        char numPioOut;
        char numSlu;
\end{verbatim}
\item[]
{\tt options} is a mask describing which special sensor I/O features are
available (such as force/torque sensors, joysticks, etc.), {\tt numAdc} is the
number of analog-to-digital converter channels available, {\tt numDac} is the
number of digital-to-analog converter channels available, {\tt numPioIn} and
{\tt numPioOut} describe the number of parallel input and output ports
available (each port is the size of a {\tt short}, for historical
reasons), and {\tt numSlu} describes the number of serial line units
available.

\medskip
\item[$\diamondsuit$]
The field {\tt controlLevel} which indicates
whether the arm is being controlled 
at the joint level or the motor level, and the field 
{\tt torqueMode} which indicates which joints are being position controlled
and which are being torque/current controlled. Motor level control
basically means using variables which described the robot state {\it before}
the gear train (such as shaft encoders), while 
joint level control means using variables which describe it
{\it after} the gear train (such as joint angles).

\medskip
\item[$\diamondsuit$]
Several arrays describing the state of the robot at the motor shaft level,
including encoder count positions, motor torques, the last commanded position,
and the last commanded torques. These fields include:
\begin{verbatim}
        int enc[MAXJNTS];
        float encVel[MAXJNTS];
        int encSet[MAXJNTS];
        float mtorque[MAXJNTS];
        float mtorqueSet[MAXJNTS];
        float mtorqueBias[MAXJNTS];
\end{verbatim}
\item[]
{\tt enc} is the motor encoder position, {\tt encVel}
is the encoder velocity (encoders/sec), {\tt encSet} is the last
commanded encoder position, {\tt mtorque} is the observed motor shaft
torque,
{\tt mtorqueSet} is the last commanded motor shaft torque, and
{\tt mtorqueBias} is current feedforward current biases.

\medskip
\item[$\diamondsuit$]
Several arrays describing the state of the robot at the joint level. This
is simply the motor level information remapped across the gear system:
\begin{verbatim}
        float ang[MAXJNTS];
        float angVel[MAXJNTS];
        int angSet[MAXJNTS];
        float jtorque[MAXJNTS];
        float jtorqueSet[MAXJNTS];
        float jtorqueBias[MAXJNTS];
\end{verbatim}
\item[]
{\tt ang} is the joint position (radians or mm.), {\tt angVel}
is the joint velocity (radians or mm. /sec), {\tt angSet} is the last
commanded joint position, {\tt jtorque} is the observed joint torque,
{\tt jtorqueSet} is the last commanded joint torque, and
{\tt jtorqueBias} is current feedforward current biases.

\medskip
\item[$\diamondsuit$]
Fields describing the position/force characteristics of the hand:
\begin{verbatim}
        int hand;
        int handForce;
\end{verbatim}
\item[]
{\tt hand} gives the hand position as an integer (for simple open/close
grippers 1 indicates open and 0 indicates closed), and {\tt handForce}
describes the observed gripper force.

\medskip
\item[$\diamondsuit$]
Robot controller state and system information, including any control
parameters which have been assigned to the joints:
\begin{verbatim}
        int ctrlParams[HOW_MAXPARAM] [MAXJNTS];
        long integration;
        long calibMode;
        long markFound;
        char power;
        char calibrated;
\end{verbatim}
\item[]
{\tolerance=10000
{\tt ctrlParams} contains robot control parameters that have been set with the
{\tt POST\_CTRLPARAM()} and {\tt LOAD\_CTRLPARAM()} commands 
(section \ref{chg}),
and {\tt integration} is a mask describing which joints have integration
enabled in their position servo loop. The next two fields are used by
calibration 
programs: {\tt calibMode} is a bitmask describing which
joints are in calibration mode, and {\tt markFound} is a bitmask describing
which 
joints in calibration mode have located their index mark.
{\tt power} is a boolean indicating whether the arm power is on, and {\tt
calibrated} is a boolean that is set if the arm is calibrated (this variable
is actually set from RCI by the calibration program but stored in the robot
controller so that it is valid across different RCI programs). 

}
\medskip
\item[$\diamondsuit$]
Several fields indicating whether special I/O features are running
successfully once enabled:
\begin{verbatim}
        char torqueOK;
        char potOK;
        char pendantOK;
        char forceOK;
        char jstickOK;
        long adc;
        long slu;      
\end{verbatim}
\item[]The first five fields are set true if sense information is being
returned successfully by the torque sensors, potentiometers (used for
calibration), the teach pendant, the force/torque sensor, and the joystick.
{\tt adc} and {\tt slu} are bitmasks describing which ADC and serial line
channels are currently accepting input.

\medskip
\item[$\diamondsuit$]
Fields containing the input from various sensor and I/O devices:
\begin{verbatim}
        long pendantInput[HOW_PENDANT];
        float forceInput[6];
        int jstickInput[6];
        int adcInput[HOW_MAXADC];
        SLU sluInput[HOW_MAXSLU];
        short pioInput[HOW_MAXPIO];
\end{verbatim}
\item[]
These fields contain the input values from the teach pendant, force sensor,
joystick, ADC channels, and serial line channels whenever those input devices
are enabled. {\tt pioInput} contains readings from the parallel input port;
this is constantly available and does not have to be enabled.

\medskip
\item[$\diamondsuit$]
Fields which contain values which were last sent to various output
devices:
\begin{verbatim}
        short pioOutput[HOW_MAXPIO];
        int dacOutput[HOW_MAXDAC];
        SLU pendantMsg;
        long checking;
        char powerOnRelease;
\end{verbatim}
\item[]
{\tt pioOutput} and {\tt dacOutput} contain the values last sent to the
parallel output ports and DAC channels, respectively; {\tt pendantMsg}
contains the last message sent to the teach pendant; {\tt checking} 
is a bitmask describing
what sort of joint limit checking has been specified for the interface
functions to carry out, and {\tt powerOnRelease} indicates whether robot arm
power will be turned off or not when the control session is terminated.
\end{list}

\section{The CHG Macros}\label{chg}

Control of the robot arm is achieved using a set of command macros, which can
be called from anywhere in an RCI program. Invoking the macro places
information about 
the requested command into a invisible command blackboard (called
the CHG 
structure) which is scanned by the {\tt output} interface
function; this function then builds a buffer of commands and ships them off to
the robot. The name CHG is historical, coming from the original version of
RCCL, and stands for ``change''.

The CHG macros each take the {\tt RCI\_RBT} structure as their first
argument, with other arguments depending on the macro. A brief synopsis of the
available macros is given below; detailed information about each one is
contained in the manual pages. The available macros include:

\medskip
\begin{list}{}{}
\item[$\diamondsuit$]
Commands to control the robot at the motor shaft level (below the gear train):
\begin{verbatim}
        MOTOR_LEVEL_CONTROL (rbt)
        MOVE_ENCODER (rbt, enc, j)
        SET_MTORQUE (rbt, tor, j)
        SET_MTORQUE_BIAS (rbt, tor, j)
        SET_ENCODER (rbt, enc, j)
\end{verbatim}
\item[]
The first command puts RCI into a mode where it will accept motor level
commands; specifying motor level commands while operating at the joint control
level will produce an error. {\tt MOVE\_ENCODER()} requests the robot to move
joint {\tt j} to a particular encoder value over the course of the next
sample interval. {\tt SET\_MTORQUE()} puts joint {\tt j} into torque control
mode 
and requests a specific torque (or force for a prismatic joint) to be
applied. {\tt SET\_MTORQUE\_BIAS()} adds a feedforward bias torque
to the indicated joint when it is in position control mode.
{\tt SET\_ENCODER()}, used for calibration, 
sets the joint encoder to a specific value.

\medskip
\item[$\diamondsuit$]
Commands to control the robot at the joint level (above the gear train):
\begin{verbatim}
        JOINT_LEVEL_CONTROL (rbt)
        MOVE_ANGLE (rbt, ang, j)
        SET_JTORQUE (rbt, tor, j)
        SET_JTORQUE_BIAS (rbt, tor, j)
        SET_ANGLE (rbt, ang, j)
\end{verbatim}
\item[]
The first command puts RCI into a mode where it will accept joint level
commands; specifying joint level commands while operating at the motor control
level will produce an error. {\tt MOVE\_ANGLE()} requests the robot to move
joint {\tt j} to a particular joint value over the course of the next
sample interval. {\tt SET\_JTORQUE()} puts joint {\tt j} into torque control
mode 
and requests a specific torque (or force for a prismatic joint) to be
applied. {\tt SET\_JTORQUE\_BIAS()} adds a feedforward bias torque
to the indicated joint when it is in position control mode.
{\tt SET\_ANGLE()}, used for calibration, 
sets the joint value to a specific value (NOTE: this command is not
implemented on the PUMA robot).

\medskip
\item[$\diamondsuit$]
Commands to stop the arm immediately:
\begin{verbatim}
        SET_STOP (rbt, j)
        SET_STOP_ALL (rbt)
\end{verbatim}
\item[]
The first command stops joint {\tt j} where it is, while the second command
stops all joints. There is actually not much difference between issuing a {\tt
STOP} command and issuing move request to the current position, except that
the robot 
system may interpret the stop command as being a more urgent request; it might
also place the joint servo loop into a slightly different state than
a move
command (since the latter is typically followed by another move command).

\medskip
\item[$\diamondsuit$]
Commands to set the hand position or, alternatively, the hand force:
\begin{verbatim}
        SET_HANDPOS (rbt, pos)
        SET_HANDFORCE (rbt, force)
\end{verbatim}
\item[]
For open/close grippers, a hand position value of 1 means ``open'' and
0 means ``close''.

\medskip
\item[$\diamondsuit$]
Commands to set control parameters in the joint servos:
\begin{verbatim}
        POST_CTRLPARAM (rbt, param, value, j)
        LOAD_CTRLPARAMS (rbt)
\end{verbatim}
\item[]
It is assumed that the joint servos at the robot control level may have a
number of parameters which may be changed to suit different applications.
RCI makes no assumptions about what these parameters are; it just allows 
a program to be able to set up to {\tt HOW\_MAXPARM} of them
for each joint. Setting the values is done using both commands.
The first command sets parameter number {\tt param} on joint {\tt j}
to accept the indicated {\tt value}, although the values are not actually
sent down to the robot until the {\tt LOAD\_CTRLPARAMS()} macro is invoked.
This ensures that distinct sets of parameters can be loaded as a group.

\medskip
\item[$\diamondsuit$]
Commands to adjust the behavior of the joint servos, and turn on arm power:
\begin{verbatim}
        SET_INTEGRATION (rbt, mask)
        SET_CALIBMODE (rbt, mask)
        SET_CALIBFLAG (rbt, value)
        SET_POWER_ON (rbt)
        SET_POWER_OFF (rbt)
\end{verbatim}
\item[]
The first command enables integration in the servo loop
of the joints described by the bitmask {\tt mask}. {\tt SET\_CALIBMODE()}
puts the joints specified by {\tt mask} into calibration mode, while
{\tt SET\_CALIBFLAG()} is used to set a flag value in the robot controller to
some value indicating that the robot has been calibrated; it is useful to
store such a value in the robot controller since it then cannot become
corrupted by problems on the host machine. 
The last two macros turn arm power on and off.

\medskip
\item[$\diamondsuit$]
Commands to control the operation of the robot communication functions:
\begin{verbatim}
        SET_CHECKING (rbt, mask)
        SET_POWER_ON_RELEASE (rbt, on)
\end{verbatim}
\item[]
{\tt SET\_CHECKING()} enables various types of joint limit checking, as
specified by the bitmask {\tt mask}. If a particular type of checking is
enabled 
and one of the interface functions detects that a limit is exceeded, it will
call {\tt rciAbort()}. The last command is used to enable or disable 
a feature by which the {\tt release} interface function will {\bf not}
turn arm
power off at the end of the control session.

\medskip
\item[$\diamondsuit$]
Commands to enable the reading of sensor information into the {\tt HOW}
structure:
\begin{verbatim}
        SET_TORQUE_READ (rbt, on)
        SET_POT_READ (rbt, on)
        SET_PENDANT_READ (rbt, on)
        SET_FORCE_READ (rbt, on)
        SET_JSTICK_READ (rbt, on)
        SET_ADC_CHAN (rbt, mask)
        SET_SLU_CHAN (rbt, mask)
\end{verbatim}
\item[]
{\tolerance=10000
The first five commands enable (or disable) input from the joint
torque sensors, potentiometers, teach pendant, force/torque sensor, and
joystick, respectively. {\tt SET\_ADC\_CHAN()} and 
{\tt SET\_SLU\_CHAN()} enable input to be read from
the ADC or serial line channels specified by the bitmask {\tt mask}.

}

\medskip
\item[$\diamondsuit$]
Commands to send output to I/O devices:
\begin{verbatim}
        PUT_PIO (rbt, chan, value)
        PUT_DAC (rbt, chan, value)
        PUT_SLU (rbt, chan, buf, size)
        PUT_PENDANT_MSG (rbt, buf, size)

        SET_PIO (rbt, chan, mask)
        CLEAR_PIO (rbt, chan, mask)
\end{verbatim}
\item[]
{\tolerance=10000
{\tt PUT\_PIO()} and {\tt PUT\_DAC()} set an output value at the indicated
parallel port or DAC channel. {\tt PUT\_SLU()} sends a buffer of bytes to the
indicated serial line channel, and {\tt PUT\_PENDANT\_MSG()} sends a buffer of
bytes to the teach pendant message display (NOTE: the teach pendant message
display for the puma robots is actually a string; it is
a short integer, which we pretend is a 2 byte string so that it
conforms with this interface). {\tt SET\_PIO()} and {\tt CLEAR\_PIO()} 
set or clear specific bits, indicated by {\tt mask}), on a parallel port.

}
\end{list}

\section{Example: A Zero Gravity Program}

As a simple example of how to use the RCI robot support, we provide here
a program that puts a robot into a zero-gravity mode -- applying just enough
torque to each joint to balance the gravity loading, thereby making the robot
effectively weightless. This sort of program is useful in that it permits a
manipulator to be easily moved into various positions, for teaching or
inspection purposes, without having to use a teach pendant.

\subsubsection*{Planning Module}
\begin{verbatim}
   #include <stdio.h>
   #include <rci.h>
   
   extern startupFxn();
   extern zerogravFxn();
   extern releaseFxn();
   
   main(argc, argv)
   int argc;
   char **argv;
   {
           RCI_DESC *td;
           RCI_RBT *rbt;
           int *enable;
   
           if (argc != 2)
            { fprintf (stderr, "USAGE: zerograv <robotName>\n");
              exit (-1);
            }
           argc--; argv++;
   
           rciSetOptions (EXIT_ON_ERROR);
   
           td = rciCreate ("zerograv", 0x1);
           rciScheduling (td, ON_CLOCK, 0);
           rciRate (td, 30, 0);
           rciControlFxns (td, startupFxn, zerogravFxn, releaseFxn, 0);
   
           enable = (int*)allocMem ("enable", sizeof(int), 0);
   
           rciAttachRobot (td, *argv, 0);
   
           rciStart(~0);
           rciBlock(td);
   
           rbt = TASKROBOT(td, 0);
           if (!rbt->how->calibrated)
            { fprintf (stderr, "ERROR: robot is not calibrated\n");
              rciRelease(~0);
              exit (-1);
            }
   
           SET_POWER_ON (rbt);
           rciBlock(td);
           *enable = 1;
   
           printf ("Hit <CR> to exit:\n");
           while (getchar() != '\n')
              ;
           rciRelease(~0);
   }
\end{verbatim}

\subsubsection*{Control Module}
\begin{verbatim}
   #include <rci.h>
   
   startupFxn (td)
   RCI_DESC *td;
   {
           RCI_RBT *rbt = TASKROBOT (td, 0);
           (*rbt->startup)(td, rbt);
           JOINT_LEVEL_CONTROL(rbt);
   }
   
   zerogravFxn (td)
   RCI_DESC *td;
   {
           RCI_RBT *rbt = TASKROBOT (td, 0);
           HOW *how = rbt->how;
           KYN *kyn = rbt->kyn;
           void *var = rbt->var;
           int *enable = (int*)getMemByName ("enable");
   
           float load[MAXJNTS];
           int j;

           ROBOT_WAKEUP(rbt);
           while (!(ROBOT_READY(rbt)))
              ;
   
           (*rbt->input)(td, rbt);
   
           if (*enable)
            {
              gravload (load, how->ang, kyn);
              for (j = 0; j < rbt->jls->numJ; j++)
               { SET_JTORQUE (rbt, load[j], j);
               }
            }
   
           (*rbt->output) (td, rbt);
   }
   
   releaseFxn (td, arg, code)
   RCI_DESC *td;
   int arg, code;
   {
           RCI_RBT *rbt = TASKROBOT (td, 0);
           int rcode;
   
           rcode = (code == RELEASE_REQ) ? RBT_NORMAL : RBT_HARDERROR;
   
           (*rbt->release)(td, rbt, rcode);
   }
\end{verbatim}

{\tolerance=10000
The program first checks the argument list for consistency. It then sets
the {\tt EXIT\_ON\_ERROR} option to ensure that errors at the planning level
will be caught without having to check for them explicitly. A control task is
created, set to run {\tt ON\_CLOCK} at an interval of 30 msec., and given the
appropriate control functions.

}
To turn the zero gravity control on or off an enable flag is created using
a shared memory 
object named {\tt enable}; this flag is automatically set to zero by
the {\tt allocMem()} primitive. The task next attaches the robot specified
by the program command line, starts the control task running, and then
calls {\tt rciBlock()} to make sure that at least one control cycle has
elapsed and the HOW structure contains valid information. The HOW structure is
then used to check to see if the robot arm is calibrated; this is important
since an uncalibrated arm will result in bogus torque computations. 

The arm power is next turned on, {\tt rciBlock()} is called again to make sure
that the power-on command has been noticed, and that the zero gravity control
is enabled. Finally, the program goes into a loop waiting for a newline from
the user as a signal to terminate.

At the control level, the startup function simply calls the robot communication
startup function and enables joint level control. The control function obtains
pointers to the necessary parameter data structures, as well as the enable
flag, and then wakes the robot up (this cannot be done in advance since 
we are running {\tt ON\_CLOCK}). The control function waits for the
robot to respond to the wakeup and become ready. Technically, the wait loop
should contain a timeout, but we have omitted that here. Alternatively, the
wait loop could be omitted and {\tt rbt->input} could be called immediately,
assuming that the input function allowed its I/O driver to block long enough
for a response from the robot. 

After the information has been read in from the robot, the enable flag is
checked and, if set, the gravity loadings are computed and sent to
the robot as joint torque commands.
Note that the units for the torques are all the
same (Newton-meters); any necessary conversion is performed by RCI.

The release function just calls the robot communication release function, passing
it an appropriate code based on its own release code.

\chapter{Robot Support: Other Features}

\section{Miscellaneous Support Functions}

There are a couple of other functions which are useful in programming robot
control applications. The first is the function {\tt getDefaultRobot()}, which
returns the name of the robot named in the file {\filefont
\$RCCL/conf/defaultRobot}:
\begin{verbatim}
        name = getDefaultRobot();
\end{verbatim}
This eliminates the need for always specifying
the name of the robot to be controlled, and is useful at sites
that have only one robot.

Another routine is {\tt getRobotPosition()}, which returns a named position
associated with a particular robot from a file database. The position
is a set of joint values, stored for each robot in the file
{\filefont \$RCCL/conf/<robotName>.pos}, according to a format that looks
something like this:
\begin{verbatim}
        pos1  90.0  -45.0    0.0  180.0  180.0    0.0
        pos2 180.0    0.0    0.0   90.0   90.0    0.0 
                   .               .
                   .               .
\end{verbatim}
The robot has to be known to the RCI system, since the {\tt JLS} structure is
consulted when the file is read to determine the number of joints that robot
has. 
Referencing a position is done with the call
\begin{verbatim}
        getRobotPosition (jval, posName, robotName)
\end{verbatim} 
where {\tt jval} is an array of floats for returning the values in, {\tt
posName} is a string naming the position, and {\tt robotName} is the name of
the robot. The routine returns 1 if the named position is found, 0 if it is
not, and -1 in case of some unexpected error.

At the moment, each robot has only one position file in the
{\filefont \$RCCL/conf} directory; this should probably be changed so that
different users can define private sets of positions.

\section{Robot Task Simulation Tools}\label{simtools}

The RCI {\tt ON\_SIGNAL} scheduling discipline can be used to provide some
tools used for running robot control tasks in simulation mode. The basic idea
is to make 
it easy for an RCI control task to run in simulation mode, off of a UNIX
signal, connected, instead of to a real robot,
to another UNIX process that emulates the robot. Execution can then be single
stepped, sensor input can be faked through the simulator program, and the
whole thing can be run under a debugger. To this end, RCI provides
routines which allow an RCI program to establish a simulated connection to a
robot, and a robot simulator program to which such RCI programs can connect.
The simulator program provided with the RCCL/RCI distribution, which is
discussed in 
section \ref{robotsim}, provides graphical
and simple kinematic simulation. No dynamic simulation is
done, although this could be added.

The RCI simulation support routines are:
\begin{verbatim}
        simScheduling (td)
        simSetTimer (interval, cycleStartTime)
        simAttachRobot (td, robotName, addressString)
        simRobotsReady (td)
\end{verbatim}
The first routine sets the indicated task to run {\tt ON\_SIGNAL} using the 
UNIX {\tt SIGARLM} signal. This is designed to be used in conjunction with
{\tt simSetTimer()}, which requests a {\tt SIGALRM} to be delivered
to the process. {\tt simSetTimer()} is usually called near
the {\it end} of each control cycle, to schedule the signal that will
initiate the {\it next} control cycle. It takes two arguments:
{\tt interval}, which gives the desired sample interval (in
milliseconds), and {\tt cycleStartTime}, which is a pointer to a 
{\tt struct timeval} giving the time at which the current control cycle
began. The first argument is (ideally) the desired cycle interval as
specified by {\tt rciRate()}. The last argument is optional and may be
specified as {\tt NULL}. {\tt simSetTimer()} uses the information it is passed
to try and find the most reasonable time to schedule the next signal.
If {\tt cycleStartTime} is not given, then the signal is simply scheduled
for {\tt interval} milliseconds in the future. If {\tt cycleStartTime} is
provided, then the signal can be scheduled more intelligently. Ideally,
if the interval time is $t_i$, the cycle start time is $t_s$, and the current 
time is $t_c$, then the delay $\Delta t$ before the next signal is
delivered should be computed from 
\[
                \Delta t \;=\; t_i - (t_c - t_s)
\]
in order to preserve a sample interval of $t_i$. {\tt simSetTimer()} will do
this if possible. However, to prevent the system from being bogged down
by too short a sample interval, $\Delta t$ is also held to a minimum value
(typically around $1/2 t_i$). {\tt cycleStartTime} is provided as a {\tt
struct timeval} simply because this is typically the most convenient form
in which to obtain it from the system. One can do this using the UNIX function
{\tt gettimeofday()}, or, more 
portably, the RCI system interface function
\begin{verbatim}
        getSystemTime(timevalPtr)
\end{verbatim}
which, like {\tt gettimeofday()}, returns the current time through a pointer
to a {\tt struct timeval}. 

\begin{quote}
{\bf NOTE:} The UNIX timer resolution may well be coarser than a millisecond;
on many UNIX systems it is 10 milliseconds. The rates used when running
in simulation mode should generally be multiples of the UNIX timer
resolution.
\end{quote}

The routine {\tt simAttachRobot()} is a wrapper around {\tt rciAttachRobot()},
which specifies that instead of using the robot interface device described in
the file {\filefont \$RCCL/conf/robots}, 
the system should instead use the simulator
driver {\tt sim}. This is done using the device override argument {\tt
devAddr} for {\tt rciAttachRobot()}.
The {\tt sim} driver uses TCP Internet domain sockets to
communicate with another UNIX program which simulates the robot and
controller. An address for this connection is formed using (1) the name
of the robot, (2) the name of the simulator, and (3) the name
of the machine on which the simulator is running. {\tt simAttachRobot()}
arranges for this information to be passed to the {\tt sim} driver.
The name of the robot is taken from its second argument.
The name of the simulator and its machine are taken from 
the string {\tt addressString}, using a format described in
{\tt simAddress(5)}. If {\tt addressString} is {\tt NULL}, then
the simulator name is taken to be the current user name, and the
current machine is assumed.
For a full description of simulator addressing, see the manual page {\tt
simAttachRobot(3)}.

{\tt simRobotsReady()} is a special wakeup function which returns true
if any of the (simulated) robots attached to the RCI control task are ready to
communicate with the task. It is called when the control task is
woken up by the {\tt SIGALRM} signal. If the call fails (i.e., none of the
simulated robots are ready to communicate), then it simply reschedules the
signal for a later time. In this way, the {\tt SIGALRM} is used as a
{\it polling} interrupt. {\tt simRobotsReady()} computes the time
to the next signal to be one half of the nominal control interval (as set
by {\tt rciRate()}), which it obtains
from the task descriptor {\tt td}.

To help clarify all this, the following example program is given which
starts a control task running in simulation mode,
connected to a simulated robot whose name is specified in the 
program's argument list:

\subsubsection*{Planning module:}
\begin{verbatim}
   #include "../h/rci.h"
   
   extern int startupFxn();
   extern int controlFxn();
   extern int releaseFxn();
   
   main(argc, argv)
   int argc;
   char **argv;
   {
           RCI_DESC *td;
   
           argc--; argv++;
   
           td = rciCreate ("robottask", 0x1);
           rciRate (td, 1000, 0);
           rciControlFxns (td, startupFxn, controlFxn, releaseFxn, 0);
           simScheduling (td);
           simAttachRobot (td, *argv, (char*)NULL);
   
           rciStart (~0);
           while (getchar() != '\n')
              ;
           rciRelease (~0);
   }
\end{verbatim}

\subsubsection*{Control module:}
\begin{verbatim}
   #include "../h/rci.h"
   #include <sys/time.h>                   /* to get "struct timeval" */
   
   extern int simRobotsReady();
   
   startupFxn (td)
   RCI_DESC *td;
   {
           RCI_RBT *rbt = TASKROBOT(td, 0);
   
           if (td->tcb->scheduleDisp == ON_SIGNAL)
            { rciWakeupOn (td, simRobotsReady, (int)td);
              simSetTimer (td->tcb->interval, (struct timeval*)NULL);
            }
           (*rbt->startup)(td, rbt);
   }
   
   controlFxn (td)
   RCI_DESC *td;
   {
           RCI_RBT *rbt = TASKROBOT(td, 0);
           struct timeval cycleStartTime;
   
           getSystemTime(&cyclestarttime);
   
           (*rbt->input)(td, rbt);
           (*rbt->output)(td, rbt);
   
           /* ... presumably some time may elapse here ... */
   
           printf ("doing robot control\n");
   
           if (td->tcb->scheduleDisp == ON_SIGNAL)
            { simSetTimer (td->tcb->interval, &cycleStartTime);
            }
   }
   
   releaseFxn (td, arg, code)
   RCI_DESC *td;
   int arg, code;
   {
           RCI_RBT *rbt = TASKROBOT(td, 0);
   
           (*rbt->release)(td, rbt, code == RELEASE_REQ ? RBT_NORMAL : 
                                                          RBT_HARDERROR );
   }
\end{verbatim}

A few quick notes with regard to this example: {\tt simAttachRobot()} is
called with the third argument set to {\tt NULL}, so RCI will attempt to
connect to a simulator which is (a) running on the same machine, and
(b) identified by the name of the robot plus the name of the user.
(Again, see the man page for more details.)
The first polling signal is requested from inside {\tt startupFxn()},
and is requested to occur in exactly {\tt
tcb->interval} milliseconds since the second argument to
{\tt simSetTimer()} is given as {\tt NULL}. Subsequent calls to
{\tt simSetTimer()} are made from within {\tt controlFxn()} and supply the
second argument giving the time the control cycle started; this
enables {\tt simSetTimer()} to chose a reasonable time to schedule the next
signal. 

\section{The Robot Simulator}\label{robotsim}

The program {\tt robotsim} is a 3D graphics simulator for
the robots supported by the RCCL/RCI distribution. 
Starting the
simulator program, 
with the name of a particular robot to simulate, is equivalent to ``turning
on'' that robot. An RCI robot
control task running in simulation mode can then connect to this
simulated robot instead of to a real robot. When the RCI program exits (or
calls {\tt rciClose()}), another RCI program is free to connect to the
simulator and ``control the robot'', just as different RCI programs can (at
different times) be used to control the same real robot.
The simulator program preserves its state (where the robot is)
between control connections. 

Detailed information about the robot
simulator can be found in the manual page {\tt robotsim(1)}.

To give some idea how the simulator program is used, we shall present some
simple simulator sessions. When using the robot simulator, it can be
useful to use two windows, one which operates the
simulator and one which operates the RCI program. In the session detailed
below, the RCI program window is  on the left, and the simulator window is
on the right. Extra vertical space is added into the display on either
side to better illustrate the sequence of events.
\begin{verbatim}
                                   % robotsim Apollo
                                   Apollo Moper started

                                   Apollo listening
% move Apollo by 5 -sim
Task chase created
                                   Apollo active (slave)
Moving to joint values:
    5.000   89.998 -179.997   
   89.998   90.003   90.003 

                                   Apollo released
                                   Apollo listening
%
\end{verbatim}

{\tt Apollo} is the name of a robot known to RCI. The simulator is
started first, whereupon it prints some startup messages and then waits for
a program to connect to it. By default, the simulator starts with the robot
calibrated 
and in the park position.
The program {\tt move} is called to drive joint 1 of the simulated robot by
5 degrees. The option {\tt -sim} is built into most of the utility robot
programs and makes the program run in simulator mode. {\tt move} prints
the joint values it will move to, and then drives the robot to this position.
Other RCI programs can later be called which
reference the simulator, with {\tt robotsim} keeping its position between
programs.

One of the main advantages of the simulator is that it give the programmer the
ability to use the debugger with the control level functions, something which
is normally not possible when running in real-time. Break points can be set in
the control level routines, and interaction with the simulator will be
suspended at the same time.

The simulator can also produce log files containing the
joint (or Cartesian) coordinates for each robot control cycle. These
are particularly useful for checking open-loop trajectory algorithms.
See the references for the {\tt -jlf} and {\tt -clf} options in
the {\tt robotsim(1)} manual page.

It is also possible to run the simulator interactively, and to run it
in single step mode. This allows a user to artificially introduce sensor I/O
values for the RCI program to ``read back'', 
which is useful for debugging applications dependent
upon sensor conditions. For instance, suppose a robot program is written that
terminates when a certain force is detected at the end
effector. This situation can be artificially created as follows:
\begin{verbatim}
                                   % robotsim Apollo -i
                                   Apollo Moper started

                                   Apollo listening
                                   ROBOTSIM> autocycling off
% stopOnForce
Task control created
Enter force limits > 
10 10 10

                                   Apollo active (slave)
                                   ROBOTSIM> step 10
                                   ROBOTSIM> show robot

                                   0.28 seconds, exchange no. 10
                                   JNT ENCODER   ANGLE    MOTOR TORQUE 
                                    1   56108      0.15    0.00000   
                                    2   32767     90.00    0.02487   
                                    3   43514   -180.00   -0.04048   
                                    4   32768     90.00   -0.00437   
                                    5   40645     90.00   -0.00000   
                                    6   31647     90.00    0.00000   

                                   ROBOTSIM> set force fx 20
                                   ROBOTSIM> step 2
Force limit detected

                                   Apollo released
                                   Apollo listening
%
\end{verbatim}

When the simulator is run in interactive mode, it presents the user
with a prompt and allows keyboard commands to be entered. The commands
are entered through a keyboard menu interface known as the ``C-tree
matcher'', which allows the user to see the available commands
by hitting {\tt ?} and to do command matching by hitting {\tt <space>}.

The command {\tt autocycling off} turns off autocycling so that
control cycles can be explicitly regulated using the {\tt step}
command. Between cycles, state information about the
robot and the ``controller'' can be displayed, and sensor input
``values'' can be explicitly set using special commands.
In the example above, the control
program is first driven for 10 cycles before a simulated force is applied and
the robot is driven for another couple of cycles to allow the RCI program to
``see'' the force values and terminate accordingly. The command {\tt set
force} sets 
up external forces as they would be seen in the manipulator TOOL frame; the
simulator maintains its own definition of a TOOL frame.

\end{document}
\bye
