\input rccluginit.latex

\chapter{Introduction}

Multi-RCCL is a C package for implementing task level robot control
applications under UNIX.
It provides data types useful for robotics applications,
such as vectors and spatial coordinate 
transformations, in combination with routines to specify robot arm motions.
Movements can be requested to target positions
in either Cartesian or
joint coordinates, and several arms can be operated from the same 
program. Arm trajectories are created by a special
background task which runs at a fixed sample rate (usually 50 to 200 Hz.,
depending on the system). Application routines can be defined which
modify the trajectories based on real-time sensor inputs.

The output from the trajectory task consists of a set 
of joint-level position commands, which are assumed to be
implemented by some low level servo controller (such as the
1 Khz PID controllers for the PUMA). RCCL cannot be used to implement
algorithms at the joint servo level, although people doing such work might
find it interesting to place RCCL {\bf on top} of such a system\footnote{RCCL could then be used to drive the servo level. This has in fact been
done at the Jet Propulsion Laboratory. Interfacing RCCL to a lower level
system entails some code work and is beyond the scope of this manual, but is
not technically difficult. Consult the {\it RCI User's Guide} and the
{\it RCCL/RCI Startup and Installation Guide} for details on what the low
level interface looks like.}.
Depending on the control rates required, it is sometimes possible
to implement servo level algorithms in RCI (the level beneath RCCL);
those interested should consult the {\it RCI User's Guide}.

\section{History}

RCCL (which stands for Robot Control C Library) was originally
written at Purdue University in 1983 by Vincent Hayward ([Hayward and Paul
1986]). This might be called Release 1.0. A slightly enhanced version 
(Release 2.0) was
produced at McGill University in 1985 ([Lloyd 1985]).
Significant changes were undertaken between 1987 and 1988,
when the multi-robot and multi-CPU capabilities were added
([Lloyd, Parker, and McClain 1988]). This work was mainly
undertaken at McGill University and at the General Electric
Advanced Technology Laboratory (New Jersey) under contract to
the Jet Propulsion Laboratory (JPL). The version delivered to
JPL in the fall of 1988 was defined to be Release 3.0.
The work done in creating the current Release 4.0 consisted
mostly of fixing bugs, improving the documentation, and doing
a general ``cleanup''. This was done mostly during the fall of
1989.

Multi-RCCL is the ``official'' name applied to RCCL releases 3.0 and 4.0.

\section{Required Background}

It is always difficult to describe
the necessary background 
for using a technically oriented system like RCCL.
One should certainly be familiar with the C programming 
language 
[Kernighan and Ritchie 1978],
and also with the UNIX operating system.
A thorough understanding of the robot control and programming techniques
described by Paul in [Paul 1981]
is also highly desirable. Paul's book
is particularly important, since RCCL is in many ways just an
implementation of the ideas described there (although one can
probably omit chapters 6, 7, and 10 on first reading).
Some concepts relating to real-time programming might also
be useful; for instance, it would be good if the user were familiar
with the terms ``data access collision'' and
``re-entrant code''. 
There are many books available on this subject;
this author's favorite is [Allworth 1981].

\section{System Architecture}

An RCCL program, when it runs, sets up a real-time background task
that generates the trajectories
necessary to satisfy the motion requests specified by the main
part of the program. The background task, which we will generally refer to as
the {\it trajectory generator\/}, executes independently of the
main program at a periodic sample rate (50 Hz.\ is common), and
is mostly invisible to the RCCL programmer. However, there
are ways for an RCCL program to provide application routines that are executed
within the trajectory generator.
Such routines are run in real-time, periodically, at the same
rate used by the trajectory generator, and 
can be used for applications involving control or
sensor feedback.

\begin{figure}[tbh]
%\rect 4truein by 5truein%
\boxedsizedfig{4truein}{5truein}%
{\psfig{figure=figs/tgen.eps}}%
{The main RCCL program and the trajectory generator.}%
\label{tgen}%
\end{figure}


The main RCCL program, which executes like any other UNIX program, is
often referred to as the {\it planning level},
or {\it planning task}. The trajectory generator,
plus any application
routines running within it, is usually referred
to as the {\it control level\/}. Communication between the planning
and control level is implemented using shared memory (see figure \ref{tgen}).

The trajectory generator is implemented using RCI (Real-time Control
Interface), which is a facility for spawning high-priority
real-time tasks from a UNIX program (see the {\it RCI User's Guide}).
The code that implements the trajectory task is loaded into
the RCCL program along with all the other library routines.
However, the task is {\bf not} a UNIX process, and does not
have access to the UNIX system services. As a consequence,
RCCL routines executing at the control level
do not have access to UNIX system services either.
The restrictions which apply to control level functions are
summarized in section \ref{restrictions}.

\begin{figure}[tbhp]
\boxedfullpagefig
{\psfig{figure=figs/tasks.eps}}%
{RCCL system, connected to two robots, with trajectory
tasks running on two CPUs.}%
\label{tasks}%
\end{figure}


Some implementations of RCI permit control tasks to be
run on auxiliary CPUs attached to the same backplane
as the UNIX CPU. If this is the case, then the
trajectory generator can be split into several control tasks,
each one running on a separate CPU. Figure \ref{tasks} shows
this for a system with one auxiliary CPU available. 
One trajectory task is created per CPU, and the computation is divided up on
a per-robot basis, i.e., any given
robot is still controlled by only one trajectory
task, but the computation for several robots can be done concurrently by
tasks on different CPUs.
All the tasks run in sync,
at the same rate, and so to the planning level they look very much like
one task. The increase in available CPU power can be used
in two ways: (1) to run the trajectory
generator at a faster rate, and (2) to permit the execution of 
more complex control level applications. Extra CPUs can also be used to drive
{\it virtual\/} manipulators, which are not attached to any physical robot
(see section \ref{virtual}).

To run a trajectory task on an auxiliary CPU, the system
simply copies the necessary parts of the RCCL program into that
CPU and executes it using a small kernel that is provided
by RCI (it is assumed that the auxiliary CPUs are instruction
compatible with the host CPU). This happens automatically:
as an RCCL program identifies the different robots it wants to 
control, the system assigns each robot to a trajectory task,
and (in the absence of explicit requests from the RCCL program)
tries to spread the total number of trajectory tasks out among
as many CPUs as are available.
At present, multi-CPU capabilities exist only for MicroVAX systems.

Each trajectory task drives one or more robots. To exchange information with
a robot, it uses a communication driver (provided by RCI) to speak to an
interface device provided for that robot on the system backplane. 
Generally, this interface in connected to a low level servo controller,
which implements simple joint-level position (and possibly torque) commands.
Robot state and sensor information is read in from the servo controller
at the beginning of every control cycle, and setpoints and
commands are written out to it at some point during the control cycle. A more
detailed description of this sequence of operations
is given in section \ref{sequencing}.

Within an RCCL program, most of these details concerning
trajectory generation are hidden from the user. Communication with the
trajectory generator is done through functions and a few special data
structures. The control level application functions
that a program can set up fall into the following classes:
\bigskip
\begin{list}{}{}
\item [$\bullet$]
{\it transform functions} --
These are special functions which are specifically intended to modify
spatial coordinate frames. They provide an easy way to
integrate sensor information into a program, and are used to implement things
such as tracking (see section \ref{bindings}).

\item [$\bullet$]
{\it Monitor functions} -- these are general
purpose functions that can be set up to do pretty
much anything (see section \ref{monitors}).
\end{list}
\bigskip

We repeat that the programmer should read section \ref{restrictions}
before writing control level functions.

\section{Using the System}\label{using}

Using RCCL to control a robot consists of setting up a few environment
variables (section \ref{unixenv}), starting up the robot controller
(and calibrating it if necessary; section \ref{startup}),
compiling an RCCL program, and running it.
Depending on the specific installation, it may also be necessary to
turn the robot arm power on after the program is started; the 
system will prompt the user to do so if this is the case.

RCCL programs should be compiled with the special system
command {\tt rcc}, instead of the usual UNIX command {\tt cc}.
This is a special ``front-end'' to the C compiler
that takes care of a few things necessary for the system
to be able to create the control tasks.
It is used almost identically to the {\tt cc} command, except
that modules containing control level functions
have to be specified in a particular way (section \ref{rcc}).

\section{A Simple Program Example}\label{simple}

We will get things rolling immediately by presenting a simple RCCL program.
The description of things might not be clear on first reading, but everything
presented here is described in much greater detail later on.
The program moves the robot to a suitable
starting position, then moves in
a straight line to a nearby target
point, and finally returns to the starting position. 

The program looks like this:
\medskip
\cverbatimfile{exampleCode/simple.560.c}
{\it 
\rightskip=0ptplus1fil
NOTE -- this example has been coded for the PUMA 560 robot,
and lives at \hfil\break {\filefont \$RCCL/demo.rccl/simple.560.c}. 
An equivalent program for the PUMA 260 is contained
in {\tt simple.260.c}. To run this program, set up your RCCL
environment as described in section \ref{unixenv}, start up the robot
and controller (section \ref{startup}), compile the program using
the {\tt rcc} command (section \ref{rcc}), and execute it.

}
\medskip

\begin{figure}[tbh]
%\rect 4.25truein by 5truein%
\boxedsizedfig{4.25truein}{5truein}%
{\psfig{figure=figs/simpleprog.idr}}%
{Moving to position ``pos'' using Cartesian
interpolated motion, and moving back using joint interpolated motion.}%
\label{simpleprog}%
\end{figure}


Figure \ref{simpleprog} shows the two motions which are performed
after robot has moved to the starting position.
Two coordinate frames are illustrated:
the base frame of the robot's {\bf T6} transform\footnote{This is the $4 \times 4$ transformation from the robot's base frame to a
coordinate frame located in its last link.
It will be described in detail later.}, situated in its
shoulder, and  
the ${\rm T6}$ coordinate frame itself, situated in the last link.

The include file {\tt <rccl.h>}
contains C structure type definitions and external
entry points the same way the include file {\tt <stdio.h>} does.
It provides the necessary definitions for the
RCCL functions, structures, and variables.
The file {\tt "manex.560.h"} contains declarations specific to
the PUMA 560 demo programs used in this manual.

The program will make use of two $4\times4$ homogeneous transforms
described by the {\tt TRSF} data type. The variables
{\tt p} and {\tt t} are declared as pointers to these
transforms, using the pointer type {\tt TRSF_PTR} (\cref{1}) (which
is equivalent to {\tt TRSF*}).
The program will describe the target
for one of its motions using a {\it position equation}, which is
described by a data type {\tt POS}. {\tt pos} is
declared as a pointer to the position equation using the
type {\tt POS_PTR} (\cref{2})
(which is equivalent to {\tt POS*}).
Within the program, the robot is described by a {\tt MANIP}
structure, pointed to by {\tt mnp} (\cref{3})
(the equivalent type {\tt MANIP_PTR} is also available).
The first step is to move the robot to a known initial position;
this position is described by a
set of joint angles stored in the variable {\tt rcclpark},
which is a {\tt JNTS} data type (\cref{4}) (these data types
are not generally allocated by system routines, so we have to provide
our own; that is why {\tt rcclpark} is the actual structure
rather than a pointer).
Finally, a string describing the name of the robot to be
controlled is stored in the variable {\tt robotName} (\cref{5}).

The first command is a call to {\tt rcclSetOptions()}
to set the option {\tt RCCL_ERROR_EXIT} (\cref{6}). When
this option is set, most RCCL primitives will
simply print out diagnostic messages and abort 
the program upon encountering a run-time error.
This saves the programmer from having
to explicitly check each primitive's return value for
an error condition (typically indicated by {\tt NULL} or
{\tt -1}, depending on whether the primitive normally
returns a pointer or not), and is useful for top level
applications or code development.

The next thing the program does (at \cref{7})
is get the name of the robot it is
going to control and the initial position it will move it to.
{\tt getDefaultRobot()} returns the name of the
system default robot, which is stored in the file
{\filefont \$RCCL/conf/defaultRobot}. With this name, the program then
uses {\tt getRobotPosition()} to 
look up the joint angles corresponding to the name {\tt "rcclpark"}.
This routine checks the file {\filefont \$RCCL/conf/<robotName>.pos} for the
named set of angles and returns 1 if found and 0 otherwise
(not finding the position is not considered to be an
error {\it per se}, so the function's return value is checked explicitly).
The joint angles are read into the {\tt v} field of {\tt rcclpark},
which is just an array of floats describing the joint values.

Next, the program allocates and instantiates the $4\times 4$ transforms
(\cref{8}).
The transform pointed to by {\tt t} is used to specify a target position
relative to 
the end effector coordinates of the {\tt "rcclpark"} position.
It is created with a call to {\tt allocTransXyz()},
which allocates a {\tt TRSF} data type,
gives it the name {\tt "T"}, 
sets it to have a translational component of
$-300.0$, 0.0, and 75.0, and returns a pointer to it.
The rotational component is set to the identity matrix. 
The routine's second argument allows
the programmer to specify
the memory pool from which the transform is allocated; 
this is normally left undefined (by specifying {\tt UNDEF}),
as is done here.

The transform {\tt p} is set equal to the value of the manipulator's
{\bf T6} transform
at the initial position. Although it is possible to determine this
value directly by reading it back when the robot arrives
at the initial position (which will
be done in later examples), we here set it explicitly.
The transform is created
using {\tt allocTransRot()}, is given the name {\tt "P"}, and is built
of translational component of {\tt P_X}, {\tt P_Y}, and
{\tt P_Z} (defined in {\tt manex.560.h}) along the corresponding axes
and a rotational component equal to a rotation of 180.0 degrees
about the $x$ axis.
({\tt xunit} is a built-in variable of type
{\tt VECT}
%\index {unit vectors}{}
whose value describes the unit vector
$(1, 0, 0)$.
Since transform {\tt "P"} is referenced to the same base frame
as {\bf T6} (i.e., the robot shoulder), 
this rotation causes the $z$ axis of
the frame following {\tt "P"} to point downward (see the figure).)

The two transforms are now used in a call to {\tt makePosition()}
%\index {\tt makePosition()}{}%
(\cref{9}), which constructs a kinematic position equation
(as described in [Paul 1981]) and returns a pointer to it.
{\tt makePosition()\/} accepts a variable number of arguments, the first being
the name of the position. The remaining arguments,
up to the special argument {\tt EQ}, are transforms making up
the left hand side of the position equation. 
The arguments after {\tt EQ} are transforms making up the right hand side.
The argument list is terminated by {\tt NULL}.
The manipulator {\bf T6} transform is indicated by the 
special argument {\tt T6}.
The call to {\tt makePosition()} in this example
declares the following equation:
\[
{\bf T6}\;=\;{\bf B}\;{\bf T}
\]
If we interpret this as a target for a robot motion, we can say that
the robot should be moved until its {\bf T6} transform satisfies the
equation. In this case, {\bf T6} will be set equal to {\bf B}
(the value of {\bf T6} at the park position) multiplied by the 
transform {\bf T}.

The next group of functions initialize and turn on the trajectory generator
(\cref{10}).
{\tt rcclCreate()}
allocates the structures necessary
to control a particular robot.
It takes two arguments: a string
describing the name of a robot
to be controlled and a bit mask specifying which CPUs may be used
to run that robot's trajectory generator. 
This last argument
is relevant only for RCCL/RCI systems with multi-CPU capability
and may left undefined (as is done here)
by specifying 0. {\tt rcclCreate()} returns
a pointer to a {\tt MANIP} data structure which is
used by the rest of the program to reference 
and control the robot in question.
{\tt rcclStart()} starts the trajectory generator task running;
motion requests will not have any effect unless this is done.

The program is now ready to move the robot. The first motion
request is made with {\tt movej()}, which
requests that the manipulator move to the joint angles
contained in {\tt rcclpark} (\cref{11}).

RCCL allows motion targets to be specified using either
joint coordinates (as is done here with {\tt movej()}) or
Cartesian coordinates (as will be done next, with {\tt move()}).
Furthermore, if the motion target is specified in Cartesian coordinates,
the system offers a choice as to how the {\it path\/} to that
target is computed.
By default, RCCL computes the path to the target using
{\it joint\/}
interpolated motions.
%\index {joint mode}{}
%\index {\tt setMod()}{}
This can be changed to
{\it Cartesian}
straight line motion
by calling {\tt setMod (mnp, 'c')} (\cref{12}).
In this mode, the
%\index {Cartesian mode}{}
manipulator TOOL
frame (equivalent in this program to {\bf T6})
is moved along a straight line in Cartesian coordinates to the
target position. 
The difficulty with Cartesian mode is that sometimes a straight
line path from A to B cannot be followed, typically because it
would place the robot in an impossible position.
What we usually do (and have done here)
is to use joint mode for our initial motion; local Cartesian motions
are then less likely to fail.

The next call (to {\tt move()}) tells the robot to move to
a target point defined by solving the position equation {\tt pos}
for {\bf T6} (\cref{13}). The following
call to
{\tt stop()} instructs the robot to stop there
for 1 second (specified as 1000 milliseconds) before continuing.

Finally, we request a move back to the initial position
with another call to {\tt movej()} (\cref{14}) 
(moves requested with {\tt movej()}
are always computed in joint mode, regardless of the 
interpolation mode selected by {\tt setMod()}).

Motion requests are not synchronized with the actual motion
of the arm. Instead, they simply place a motion request packet on
a queue, where they wait to be serviced by the trajectory generator as
soon as possible.
After the calls to {\tt movej()} and
{\tt move()} in the program have
returned, the robot has probably not even completed the first {\tt movej()}
request. To synchronize the main program with the
motion of the arm, different methods are available.
The simplest of these, used
in the example here, is to wait for the manipulator to finish
servicing all of its motion requests and come to rest. This is
accomplished by the macro {\tt waitForCompleted(mnp)} (\cref{15}).

The last call in the program, {\tt rcclRelease()} (\cref{16}),
turns the trajectory generator off. It takes a binary argument
which, if true, specifies that the robot arm power should
be turned off as well.

\newpage
\done
