%\documentstyle[12pt,final,twoside,times,sfheads]{rccldoc}
\documentclass [12pt]{report}
\usepackage{rccldoc}
\begin{document}
\tolerance=1000
\pagenumbering{roman}
\title{RCCL/RCI Startup and Installation Guide}
\author{John Lloyd}

\date{July 1992}
\maketitle

\begin{abstract}
This document describes the set up procedures for RCCL/RCI. The first section
explains how to run RCCL/RCI application programs.
Subsequent sections describe how to install the
system itself, add the necessary support to the UNIX kernel, and
configure the system to support different types of robots or interface
devices.

\par\vfill
\copyrightNotice
\end{abstract}

\parskip = 2ptplus3pt
\tableofcontents
\newpage
\pagenumbering{arabic}

\chapter{Introduction}
Section \ref{started.sec}
of this document describes what an RCCL/RCI user should
do in order to compile and run application programs. Sections
\ref{installation.sec} and \ref{kernmods}
explain how to compile the software and 
install the necessary kernel support.
Section \ref{configure.sec}
talks about configuring the system for a 
particular site:
how to set up the parameter data base for a particular robot, how
to run the calibration programs, how to attach a robot to a different
device, etc. An installation ``check list'' is given
in section \ref{summary.sec}. Section \ref{newrobots} describes how to
create a new {\it class} of robot for the
system.

\section{Documentation Conventions}

\subsection{Path name descriptions}

Most of the file names referred to in this document are generally 
contained either within the main RCCL distribution tree (normally denoted by
the environment variable {\tt RCCL}), or within the system kernel
tree (whose root directory is usually {\tt /sys}). For brevity, when
describing path names, the root directory portion will sometimes be omitted.
For example, {\filefont conf/site.conf} refers to 
{\filefont \$RCCL/conf/site.conf}.

\subsection{Manual page references}

A lot of detailed information about RCCL/RCI is found in the ``manual
pages'', a documentation set fashioned after the UNIX manual pages.
The documentation is available either on-line or in hardcopy. When
referring to a particular manual page in this document, the convention
``see {\tt someManPage(3)}'' will frequently be used.
This means look for the manual page with the title
{\tt someManPage}. The number in parentheses indicates the manual page
{\it section number}, which roughly follows the section 
numbering conventions of the UNIX manual. The hardcopy manual pages
(which ignore the section numbers) are found in either the
{\it RCCL Reference Manual} or the {\it RCI Reference Manual}.

\chapter{Getting Started}\label{started.sec}

The first thing an RCCL/RCI user must do is set up an environment.
This is best done by making a few entries in the
user's {\tt .cshrc} file.

\section{Environment Variables and the Path}\label{environment}

The following environment variables should be set:

\begin{desclist}
\item[\tt RCCL]
This environment variable should be set to the root directory of the RCCL
system. 

\item[\tt MANPATH]
This is a standard UNIX environment variable that defines a list of
directories that 
are searched by the {\tt man} command.
It should be set to contain {\filefont \$RCCL/man}, in addition to the
usual directory {\filefont /usr/man}. The format of {\tt MANPATH} is
described in the manual page for the {\tt man} command. 


\item[\tt CLD]
On MicroVAX-II systems only,
this environment variable should be set to {\filefont \$RCCL/bin/ld}.
It defines the location of a private copy of the loader that is used by the
{\tt rcc} command. Non-MicroVAX systems should not set this variable
since {\filefont \$RCCL/bin/ld} will not exist.

\end{desclist}

You should also add the directory {\filefont \$RCCL/bin} to your path, 
{\it ahead} of {\filefont /bin} and {\filefont /usr/bin}.


\subsection{Sample {\tt .cshrc} entries}

The following set of declarations in a {\tt .cshrc} file should do nicely
to set up the environment described above:

\section{Program Compilation}

You should now be able to compile RCCL or RCI programs.

\subsection{Using non-ansi compilers}

If you are compiling RCCL/RCI applications using a non-ansi C compiler,
you may need to define some special preprocessor symbols so that the
compiler can handle the RCCL/RCI include files.

\begin{desclist}

\bgroup
\catcode`\#=11

\item[\tt #define NO\_PROTOTYPES 1]
Define this if your compiler does not understand prototypes (which
applies to some compilers on SunOS and BSD systems).

\item[\tt #define const]
Define this if your compiler does not understand {\tt const} (which applies
to some compilers on SunOS and BSD systems).

\item[\tt #define void int]
Define this if your compiler does not understand {\tt void} (which applies
to some compilers on BSD systems).

\egroup

\end{desclist}

If made inside the application source code, these definitions
should {\it precede} any RCCL/RCI include files. You may want
to put whatever definitions you use in an include file of their own.

Alternatively, the definitions can be made directly
on the command line for {\tt cc} (or {\tt rcc}, described in the next 
section). Usually the {\tt -D}
option is used to do this. The arguments to define everything
would look like
\begin{verbatim}
      cc file.c -DNO_PROTOTYPES -Dconst= -Dvoid=int
\end{verbatim}

\subsection{The {\tt rcc} command}

RCCL/RCI programs should be compiled and loaded with the {\tt rcc} command,
which is like the {\tt cc} command except it does a few extra things:

\medskip
\begin{list}{}{}
\item[1.] Delimits the code and data segments used by the control tasks so the
system knows what portions 
must be either locked into memory,
or downloaded to an auxiliary process (for RCI tasks
running on auxiliary CPUs; see section \ref{auxCPU.sec}).

\item[2.] Automatically references the RCCL/RCI libraries and the math 
library.

\item[3.] Automatically names its output after the first module in the command
line (instead of {\tt a.out}).
\end{list}
\medskip

To support item 1, the user must place all modules containing code or data
referenced by the control level to the right of the special keyword
{\tt CTRL} in the command line. If compiled separately, these modules must 
also be compiled by the {\tt rcc} command with the usual {\tt -c}
option (again, placed in the command line
to the right of the {\tt CTRL} keyword). Modules whose code and data
will not be  accessed
at all by the control level can be compiled separately using {\tt cc}.
There is no restriction {\it per se} against referencing control level code or data
from the planning level.

{\tt rcc} supports all the usual options of {\tt cc} and can be
used in place of {\tt cc}, except that in the load phase, it will reference
the RCCL/RCI libraries, which may be inconvenient. 

The default compilation command used by {\tt rcc} is specified by the
entry to the right of the keyword {\tt cc} in the file
{\tt conf/.rcc}.
You can change the compilation command by modifying this entry.
It is probably best to do this using a private copy of
the {\tt .rcc} file in your home directory ({\tt rcc} will
check for a file there), to avoid disturbing the system 
configuration.

More information on {\tt rcc} can be found in the RCCL manual pages.

\subsection{{\tt rcc} examples}

Suppose the user wishes to compile the program {\tt test}, which consists of
the planning level module {\tt test.c} and the control module
{\tt testCtrl.c}. This program can be compiled as follows:
\begin{verbatim}
      % rcc test.c CTRL testCtrl.c 
\end{verbatim}
Alternatively, the compilation may be done separately, as in:
\begin{verbatim}
      % rcc -c test.c
      % rcc -c CTRL testCtrl.c
      % rcc test.o CTRL testCtrl.o 
\end{verbatim}
Also, {\tt test.c} could have been compiled using {\tt cc} directly.

Suppose there is a library {\tt support.a} that contains modules to be
used by the control level. Then this library must also be placed to the right
of the {\tt CTRL} keyword:
\begin{verbatim}
      % rcc test2.o CTRL test2Ctrl.o support.a 
\end{verbatim}

All the usual C options are available. For example,
a regular program {\tt foo} that
does not set up any RCI control tasks can be compiled with the
optimizer, according to:
\begin{verbatim}
      % rcc foo.c -O 
\end{verbatim}

\section{Turning on the Robot}

This section describes how to initialize the robot controller
so that it can connect to an RCI program. 

\begin{quote}
{\bf NOTE:} 
The discussion in this section refers only
to Unimate controllers and PUMA robots, since these are the
principle systems that the RCCL/RCI distribution currently provides
support for. If
your system is connected to a different type of robot or controller, then
the initialization procedure will probably be different, and you should
consult the local ``guru''. Or better yet, get the local ``guru'' to write a
local version of this document.
\end{quote}

\subsection{Loading the {\tt moper} program into the controller}
\label{down.sec}

An RCCL/RCI program communicates with the robot through a special
communication program
called {\tt moper}, which runs inside the Unimate controller
{\it in place of} the manufacturer supplied VAL software.
{\tt moper} takes care of communicating with all the devices attached to the
robot controller, such as the joint controllers, the teach pendant, 
and the force torque sensor (if attached).
A separate version of {\tt moper} is usually compiled
for each robot, and is given the same name as the robot.
The {\tt moper} programs live in the directory {\filefont \$RCCL/lsi11}, and
are created by a cross-compiler that usually lives in 
{\filefont \$RCCL/Xcompile}.
For example, if your robot is given the name {\tt RobotX}, then
its {\tt moper} program will probably reside in the file 
{\filefont lsi11/RobotX}.

{\tt moper} should be downloaded into the robot controller when the controller
is powered up. It is downloaded through the 
controller console line,
which should be connected to the host system through a serial port whose {\tt
getty} process has been switched off. The program {\tt down}, in
{\filefont \$RCCL/bin}, is used to do the download. 
For {\tt down} to work, the
controller should be turned on and VAL should be aborted so that the
controller's CPU is running ODT (the prom monitor for the
CPU). You know you are in ODT when the controller console
gives you an {\tt @} for a prompt, and
when you type {\tt <CR>}, you get an {\tt @?} for a response.

\subsubsection{Putting the controller into ODT}\label{intoODT.sec}

There are several ways to get the robot controller into ODT.
On any controller, if you are in VAL, you can get into ODT
simply by entering the command {\tt DONE}.

On Mark II and Mark III controllers, an easier way is to simply toggle
the ``run/halt'' switch after you power the controller up. On Mark II
controllers, 
this switch is located along the top edge. On Mark III controllers,
it is mounted on a bus card called ``interface board C'', which
is visible as soon as you open the front panel door. Remember to {\it toggle}
the switch, i.e., to turn it off and then back on again. If you don't turn it
back on the {\tt moper} software won't be able to run (in fact, nothing will
be able to run).

\begin{quote}
{\bf NOTE:} The ``run/halt'' switch is {\bf not} the black-knobbed 
three position rotary switch which appears on the front panel of the Mark I
and Mark II controllers (and which has the settings ``run'', ``halt'', and
``restart'').
\end{quote}

On Mark I controllers, the run/halt switch is switch S2 on the
clock terminator board. Getting to it
is a bit of a nuisance because you have to take the lid off the
controller. It is possible, however, to remove the switch from the
board and mount it on the front panel, as we have done.

On Mark II and Mark III controllers, VAL has to be loaded
into the system from a floppy disk, where it then remains in
static RAM. Since {\tt moper} overwrites VAL when it is loaded,
you have to reload VAL if you want to use it after {\tt moper} has been
running. When you power up the controller, you usually get a prompt asking
if you want to load VAL in from the disk. If {\tt moper} was previously
running when
the controller was shut off, then answering no ({\tt N}) to this question will
usually cause the boot program to crash, which will either
put you into {\tt ODT}, or (infrequently) cause the CPU to ``hang''. If
the CPU hangs, you can get into ODT by toggling the run/halt switch,
as described above.

\subsubsection{Downloading moper}

Once the controller is in ODT, you should download the {\tt moper} software by
running the program {\tt down}, which lives in {\filefont \$RCCL/bin}.
It is assumed that the controller console line is connected to a serial
port on the host system and that the login process {\tt getty} on this
line has been switched off. If you don't normally leave the console line
connected to the host, you will have to connect it before running
{\tt down}.

Assume that we have a robot called {\tt RobotX}, that is has a
{\tt moper} program that lives in {\filefont lsi11/RobotX}, and
that the controller console line is connected to a terminal device
corresponding to the special file {\filefont /dev/RobotX}. 
Then to load {\tt moper} into the controller, you
would generally call {\tt down} with the following arguments:
\begin{verbatim}
      % down -d /dev/RobotX -e 10000 -a 10000 \
             $RCCL/lsi11/RobotX -t
\end{verbatim}
{\tt -d /dev/robotX} specifies the serial line used for loading.
{\tt -e 10000} and {\tt -a 10000} specify moper's load and entry points,
and {\filefont \$RCCL/lsi11/RobotX} identifies the {\tt moper} program itself.
{\tt -t} tells {\tt down} to terminate when the load is completed; otherwise,
it will go into a {\it termlink} mode which directly links
your.00 screen and keyboard to the controller's console line.
You can break out of termlink mode by typing a tilde ({\tt \~{}}).

It is usually easiest to define an alias for the {\tt down} command, such as:
\begin{verbatim}
      % alias loadRobotX 'down -d /dev/RobotX
                          -e 10000 -a 10000 $RCCL/lsi11/RobotX -t'
\end{verbatim}
after which you can download {\tt moper} with the simple command
\begin{verbatim}
      % loadRobotX
\end{verbatim}
More information about {\tt down} can be found in the manual pages.

\subsubsection{Talking to moper}\label{mopertalk.sec}

After the {\tt moper} program has been loaded, it is possible
to communicate with it over the controller console serial line. 
While this usually isn't necessary, it is occasionally useful for
diagnostic purposes. Also, the same program that lets you communicate with
{\tt moper} can be used at any time to allow communication with whatever
happens to be running in the Unimate controller (for instance, VAL or ODT).
This means that you generally do not have to disconnect the controller
console line from the host system.

To connect to the controller console line, you use the program {\tt termlink}
to create a virtual terminal connection.
The necessary arguments to {\tt termlink} usually look like this:
\begin{verbatim}
      % termlink -d /dev/RobotX -s 9600 -T
\end{verbatim}
{\tt -d /dev/RobotX} specifies the name of the serial port
attached to the console line,
{\tt -s 9600} sets the communication speed to 9600 baud, and {\tt -T}
tells {\tt termlink} to switch off any {\tt getty} login process that might
happen to be running on that line. If {\tt termlink} does find a login process
on the line and shuts it off, it will turn it on again before exiting.

As with {\tt down}, {\tt termlink} is most easily used when wrapped in an
alias: 
\begin{verbatim}
      % alias talkRobotX 'termlink -d /dev/RobotX -s 9600 -T'
\end{verbatim}
The command {\tt talkRobotX} will put you into direct
communication with the controller console. Whatever you type will be sent
to the console, and whatever is printed to the console will go to your
terminal (or window). To break out of {\tt termlink}, you type {\tt \~{}},
which will put you into a command menu with the prompt
\begin{verbatim}
      termlink>
\end{verbatim}
from which you can exit by typing {\tt quit<CR>}, or any abbreviation thereof.
More information about {\tt termlink} can be found in the manual pages.

What you see when you run {\tt talkRobotX} (and hit {\tt <CR>} a few
times) depends on what is running
on the controller at the time. If the controller is turned off, you will get
(predictably) nothing. If the controller is running VAL, you will get the
VAL command line interpreter; if it is in ODT, you will get the {\tt @}
prompt, etc. 

If {\tt moper} is running, you will get a prompt consisting of the
character {\tt >}, although this prompt appears only when you type a command
character; it is not repeated if you just hit {\tt <CR>}. To see
if {\tt moper} is running, type {\tt ?}; if {\tt moper} is running, it will
print out a command menu for you. This command menu is mainly intended 
for running diagnostics and the like, although you might occasionally
find the {\tt h} command useful; it halts {\tt moper} and puts the CPU back
into ODT. 

To reenter {\tt moper} from ODT, type the ODT command
\begin{verbatim}
      10000G
\end{verbatim}
You should then get the response
\begin{verbatim}
      moper started

      listening
\end{verbatim}
which is the same thing {\tt moper} prints when it is first loaded into the
controller.

\begin{quote}
{\bf NOTE:} Don't halt and restart {\tt moper} frivolously. Restarting {\tt
moper} 
reinitializes the controller, which means the robot will have to be
recalibrated.
\end{quote}

\subsection{Calibrating the robot}

After you have powered up the robot controller and loaded in the {\tt moper}
software, you need to calibrate the robot arm.

PUMA robots are generally calibrated by running the RCI utility program
{\tt pumacal}. The basic form of this command is
\begin{verbatim}
      % pumacal [<robotName>]
\end{verbatim}
where, if {\tt <robotName>} is not given, a default name is
read from the file {\filefont conf/defaultRobot}.
A PUMA 260 robot usually needs to be in the nest when it is
calibrated. Alternatively, you can calibrate from the {\tt park}
position if you give {\tt pumacal} the option {\tt -atpark}:
\begin{verbatim}
      % pumacal -atpark [<robotName>]
\end{verbatim}

If you do use the {\tt -atpark} option to calibrate a PUMA 260,
make sure it actually {\it is} in the park position
(or within a couple of degrees of it).
The easiest way to ensure this is to move the robot to the park
position before you turn off the controller. This can be done with the
RCI utility program {\tt move}:
\begin{verbatim}
      % move [<robotName>] to park
\end{verbatim}

The actual definition of the park position, in terms of joint values, is
contained in the file {\filefont conf/<robotName>.pos}.

PUMA 560 and 760 robots use potentiometers to estimate their position
at calibration time, and so there is no need
for them to start from a specific location like the nest or park position.

\subsection{Summary of the controller startup procedure}

\begin{list}{}{}
\item[1.] Turn on the robot controller(s).

\item[2.] Put the controller CPU into ODT.

\item[3.] Download the {\tt moper} software into the PUMA controller using
the {\tt down} command, or an alias thereof.

\item[] If {\tt moper} has loaded correctly, then the teach pendant
(if connected) will beep and the {\tt CAL} LED will turn on.
No message should be displayed\footnotemark .
You can also check that {\tt moper} is
running by connecting to the 
console line with {\tt termlink} and typing a {\tt ?}, which should
give you a menu of commands.

\item[4.] Calibrate the robot using {\tt pumacal}.

\end{list}

\footnotetext
{The teach pendants that work with RCI are the large heavy orange ones
and the small black boxy ones.}

\subsection{When you need to reload or recalibrate}

Generally, you need to reload {\tt moper} and calibrate the
arm only when you power up the controller. The {\tt moper} software
will continue to run until you either power off the controller,
or tell it to halt by giving it the {\tt h} command. 

It is occasionally possible that {\tt moper} will crash, although this
is extremely unlikely unless you are configuring new {\tt moper} software.
If {\tt moper} {\it does} crash, it will generally exit to ODT. To restart
{\tt moper} in this case, enter the ODT command
\begin{verbatim}
      10000G
\end{verbatim}
as was described above. You will then need to recalibrate the arm. In even
rarer cases, {\tt moper} may {\it hang}. When this happens, you will
get no response. To break the program and get into ODT, you can use the 
run/halt switch that was described in section
\ref{intoODT.sec}. {\tt moper} can then be restarted.
In pathological cases, {\tt moper}'s internal data structures may be
corrupted so that the only way to get {\tt moper} to run again is to 
reload it from the host.

Exclusive of the above conditions, {\tt moper} will continue to run and the
robot will remain calibrated until the controller is switched off. This will
remain true even if you are having trouble on your host system. For instance,
it is generally unnecessary to reload {\tt moper} or recalibrate the robot
even if you get a UNIX system crash.

\section{Running Programs}

Once compiled, an RCCL or RCI program runs more or less like any other
UNIX program, except for the control level ``task'' which is executed
in the background. If the program needs to communicate with a robot
controller, it will establish the necessary connections automatically,
assuming that 
the controller is powered on and properly initialized.

\subsection{Robot arm power}

Usually, when an RCCL or RCI program starts up and begins to control
a robot, it will check to see if the
robot's arm power is on. If it is not, it will attempt to turn it on
automatically.

\begin{quote}
{\bf NOTE:} Please understand the difference between the controller power,
which is enabled when you turn on the controller, and the robot arm
power, which turns on the actuators. The controller
will usually have separate controls to turn the arm power on and off.
\end{quote}

Normally, on Unimate
controllers, the only way to turn on the arm power is to manually press
the power-on switch. This means that if an RCCL/RCI program tries to
turn on the power automatically, it will be unable to do so.
In this case, the program will simply print a message requesting
that you turn the power on, and then wait until you do so.

\begin{quote}
{\bf NOTE:} If you turn the arm power off while a program is running, it will
normally cause the program to freeze (and perhaps jolt the arm a bit), but RCI
will make no attempt to turn the power back on again.
\end{quote}

Because constantly turning the arm power on can be an inconvenience,
we suggest wiring the controller so that the arm power can be turned
on automatically by the RCI software. On the Unimate controller,
this usually entails choosing a bit from one of the controller's
output signals and attaching this to an input signal line that turns
on the arm power.
Details of how this can be done are given in the {\it RCCL/RCI
Hardware Installation Notes}.

An alternative to arranging for the power to turn on automatically
is to simply never turn it off. By default, RCI shuts off arm power
whenever control of the robot is released (e.g., when the program
exits). However, most of the utility programs (such
as {\tt pumacal} or {\tt move}) have {\tt -on} options that cause them
to leave the arm power on when they exit. In an RCCL program, you can
leave the power on by calling {\tt rcclRelease()} with an argument of
0, or by using {\tt rcclSetOptions()} to set
{\tt RCCL\_LEAVE\_POWER\_ON}. 
(You can also set the parameter {\tt leavePowerOn} to
``true'' in the {\tt RCCL} and {\tt sysprogs} parameter sets
of the {\tt .rciparams} file (see section \ref{params}).)
At the RCI level, you can arrange for power to be left on after
the control session has ended by using the macro 
{\tt SET\_POWER\_ON\_RELEASE()}. If no RCI program is
running, the robot arm power can be controlled using the RCI utility program
{\tt power}:
\begin{verbatim}
      % power [<robotName>] (-off|-on)
\end{verbatim}
The {\tt -off} option turns the arm power off, and the {\tt -on} option turns
it on.

On some systems, RCI may not even have the ability to turn the
robot power on and off, the way it does with Unimation controllers.
For such systems, you would most likely control the robot power
manually from the robot controller, independently of the execution
of RCCL/RCI applications.

\section{For the MicroVAX-II: Booting Auxiliary CPUs}

This section applies only to multi-CPU MicroVAX-II implementations.

If your program uses auxiliary CPUs, then it will
attempt to automatically load them with the control portion of the RCI 
program, booting them first if necessary.
However, if an auxiliary CPU is not
currently booted and it happens to be in monitor (or {\it console}) mode,
the RCI program will be unable to do this and will probably exit with an
error indicating such. To rectify the situation, you need to
put the CPU into a ``boot-wait'' by entering the command
{\tt B} on its console serial line.

If an auxiliary CPU is in console mode, it will give you a 
{\tt >>>} prompt on its console line when you type {\tt <CR>}.

Auxiliary CPUs on the MicroVAX generally go into console mode
whenever the MicroVAX system is powered up or rebooted, unless the
{\tt HALT} switch on the CPU's configuration module is turned off; see the
KA630 or KA620 User's Guide and/or the {\it RCCL/RCI Hardware
Installation Notes} for details.
%%% does the HW manual talk about just what the halt switch does?

\section{Using the Robot Simulator}

RCCL and RCI programs can also be run in simulation mode.
In this case, the control task actually runs in user mode, driven by a UNIX
signal, and instead of connecting to a real robot, the program connects to
another UNIX program that simulates the robot and its controller.

The default simulator program provided with RCI, called {\tt robotsim},
provides 3D graphic and kinematic simulation of one or more robots.
Several types of robot are supported (PUMA, Stanford arm, Elbow 
manipulator). Typically, you start up {\tt robotsim} with the name of the
robot(s) you want to 
emulate, and then leave it running in the background:
\begin{verbatim}
      % robotsim <robotName> 
\end{verbatim}
This is analogous
to ``turning on'' a robot controller. An RCI program
running in simulator mode connects to {\tt robotsim} instead of
a physical robot. Communication is based on Internet domain
sockets, which means that the simulator program
can be executed on a different machine.

{\tt robotsim} does not currently model very much in the way of dynamics
(except for gravity loading), and does no collision detection,
although it would not be difficult to add these features to the program.

The graphic display provided by {\tt robotsim} runs under either
X11, SunView, or the Silicon Graphics GL library. A wireframe display
is provided for X11 and SunView, and solid shaded graphics is 
provided for GL. The simulator is also capable of
running interactively, allowing control cycles to be explicitly single
stepped.

To see how to run RCCL programs in simulation mode, consult 
the {\it RCCL User's Guide}. 
To see how to run RCI programs in simulation mode, consult the
{\it RCI User's Guide}.
Detailed information on {\tt robotsim} and its features
can be found in the manual pages. 

\section{The {\tt .rciparams} File}\label{params}

This is a file containing parameter values that can be referenced
by RCCL/RCI programs. It defines a sort of ``environment'' for the
RCCL/RCI system, where parameter values can be changed without having
to recompile programs. Parameters are grouped
into named sets and can be accessed from software with 
special primitives (see {\tt rciParameters(3)}).

A few parameter set names are reserved by the system:

\medskip
\begin{list}{}{}
\item[$\diamondsuit$]
{\tt RCCL} identifies
run time parameters which are used by RCCL programs. These
include an option to force the program to run in simulator mode,
as well as options which control the robot's speed, the control task
timeout tolerance, the CPUs which the program may attempt to use, and
the control task sample rate. For details, see {\tt RCCL\_params(5)}.

\item[$\diamondsuit$]
{\tt RCISYS} is the name of a set of parameters that defines
some basic RCI system parameters.
For details, see {\tt RCISYS\_params(5)}.

\item[$\diamondsuit$]
{\tt sysprogs} is the name of a parameter set which is used by RCI
utility programs such as {\tt pumacal}, {\tt move}, and
{\tt free}.
For details, see {\tt sysprogs\_params(5)}.
\end{list}

\medskip

An RCCL/RCI program will look for a
{\tt .rciparams} file in three places: the 
directory {\filefont \$RCCL/conf}, the user's home directory, and the current
directory, remembering all parameter sets found
but allowing files read later to redefine parameter sets defined earlier.
The current directory is the most common place for a user to set up
a {\tt .rciparams} file.

\chapter{RCCL/RCI Installation}\label{installation.sec}

The following sections describe how to install RCCL/RCI. This generally
is a three step process.

\begin{list}{}{}
\item[1.] {\it Building the main software tree\/}. This
involves unpacking the tape, installing {\tt gnuMake}, 
setting up some configuration files, and running {\tt make}. Instructions for
this are given in this section. 

\item[2.] {\it Installing the necessary kernel support\/}. Exactly what this
involves depends on your system. If you are building a ``simulator only''
system, then you do not need to add any kernel support. 
VxWorks configurations are usually set for ``simulator only'' operation
on the host system and therefore don't need any kernel support either.
On the other hand, if
you are building a system for real-time operation
on the host system, you will need to
configure some special support into the system's UNIX kernel. 
Instructions for this are given in section 
\ref{kernmods}.
Real-time
support is currently provided for Sun4 Sparc systems running
SunOS 4.1 and 4.2, Silicon Graphics systems running IRIX,
and MicroVAX-II systems running 4.3 BSD. 

\item[3.] {\it Attach the required hardware to your system\/}. Depending on
what you intend to do with your system, you will probably need to attach some
external hardware. Typically, this will be to provide communication
with one or more robot controllers. On some systems,
special hardware can also be added to give
the RCI system a more accurate real-time clock. Most of the hardware
arrangements that are currently ``supported'', at least in terms of being
documented, involve connecting Unimation Mark X robot controllers to either
MicroVAX-II, Sun4 Sparc, Silicon Graphics IRIS, or VxWorks systems.
The MicroVAX-II system can be configured
to support multiple CPUs. An overview of the hardware work required for
these systems is given in the {\it RCCL/RCI Hardware Installation Notes}. 

\end{list}

There is no particular order to these steps.

\section{Installing the GNU {\tt make} Command}

At present, the RCCL/RCI {\tt Makefile}s assume
the use of the GNU {\tt make} utility.
This is because it provides some useful features (and bug-fixes)
not found in other versions of {\tt make}. GNU {\tt make} has been
ported at present to a wider range of platforms than are ever likely to
receive RCCL/RCI.

One feature which GNU {\tt make} provides, and which RCCL/RCI uses, is the
ability to include files from within the main {\tt Makefile}. This allows
us to place the include file dependencies, which are generated automatically
using {\tt make depend}, in a separate file called {\tt DependFile}, which
will not be destroyed when the {\tt Makefile} is rebuilt using {\tt imake}
({\tt imake} is described below).

GNU {\tt make} is provided by the Free Software Foundation. In case you 
presently do not have GNU {\tt make}, a copy is provided along with the
RCCL/RCI distribution, in the directory {\tt gnuMake}. 
You should install this before you do anything else.

To install GNU {\tt make}, you should first go into the {\tt gnuMake}
directory and read the copyright information
in the file {\tt COPYING}. You should then read the instructions in the file
{\tt README}, which will tell you to make the appropriate configuration
adjustments in {\tt Makefile}. You should then be able to build {\tt make}
with the command
\begin{verbatim}
      % make
\end{verbatim}
You do not need {\tt gcc} to compile GNU {\tt make} (at least, we didn't).

\begin{quote}
{\bf NOTE}:
There may be some conflicts between the native {\tt make} on your system
and GNU {\tt make}, mostly involving new features that have
been added by the vendor. You may want to call GNU {\tt make} by
a different name. On Sun systems, kernel compilation may 
not work with GNU {\tt make} because of the use of Sun-specific features
in the kernel {\tt Makefile}.
\end{quote}

\section{Setting up Your Environment}

You should set up an RCCL/RCI UNIX environment as described in section
\ref{environment}.

\section{Editing the Configuration File}

Before running {\tt make} on your system, you should edit the 
configuration file {\filefont conf/site.conf}. This allows you to set various
options describing the sort of system you want and what sort of platform you
are running on. 

The definitions in {\tt site.conf} are used by the C preprocessor, which is
invoked by the utility program {\tt imake} (described below). What the
available options are and what they do are described by comments
in the supplied version {\tt site.conf}. We do not describe the options
here because they are likely to change quickly with time.

Different versions of {\tt site.conf}, written for various
systems, are available in the {\filefont conf} directory under
the general name {\tt <SysType>.conf}.

\subsection{The {\tt imake} utility}

RCCL/RCI builds its {\tt Makefile}s automatically using the utility program
{\tt imake}, which was developed by 
Todd Brunhoff and Jim Fulton for the MIT X Windows Consortium.
{\tt imake} creates a {\tt Makefile} from a source file named
{\tt Imakefile} by running it through the C preprocessor
in conjunction with some pre-declared definition and template files. 

Since it is operated on by the C preprocessor, the {\tt Imakefile} may
contain preprocessor compilation directives and macros. This is particularly
useful for generating {\tt Makefile}s whose targets and/or actions depend on
the configuration parameters of the system.

The configuration files used by the RCCL flavour of {\tt imake} are
contained in {\filefont \$RCCL/conf}. The template file, which is responsible
for including all the other files, is called {\filefont Imake.tmpl}. 
The site-specific definitions are contained
in {\tt site.conf}. Defaults definitions (that get set if not previously
defined in {\tt site.conf}) are declared in {\tt defaults.conf}. 
Finally, the macro definitions that are used by most of the system's {\tt
Imakefile}s are contained in {\tt Imake.rules}.

Most RCCL/RCI directories will contain an {\tt Imakefile} in addition to a
{\tt Makefile}. The {\tt Makefile}s are created automatically by the system
when it is first built. If you wish to recreate a {\tt Makefile} within a
particular directory, then the best way to do this is to use the
command {\tt rmkmf}, which is a script that lives in {\filefont \$RCCL/bin}.
Running
\begin{verbatim}
      % rmkmf
\end{verbatim}
will attempt to turn any {\tt Imakefile} (or {\tt imakefile}) that lives in
the current directory into a {\tt Makefile}, using the configuration
files in {\filefont \$RCCL/conf}. Alternatively, you can give {\tt rmkmf} (1)
the name of the root directory in which to seek the {\tt conf} directory, and
(2) the name of the directory in which to
look for the {\tt Imakefile} and build the {\tt Makefile}:
\begin{verbatim}
      % rmkmf <rootDirectory> <currentDirectory>
\end{verbatim}
For example, the command
\begin{verbatim}
      % rmkmf $RCCL .
\end{verbatim}
should have the same effect as running {\tt rmkmf} with no arguments.

If you already have {\tt imake} as part of an X-windows distribution, this
should cause no conflict, although you should be careful to specify
{\filefont \$RCCL/conf} as the directory in which to locate the include files
({\tt rmkmf} will do this automatically).

More information on {\tt imake} can be found in the manual pages.

\section{Building the System}

Once the configuration file {\tt site.conf} has been prepared properly, you
can go to the RCCL root directory ({\tt \$RCCL}) and run the command
\begin{verbatim}
      % make World
\end{verbatim}
The system {\tt Makefile} will first build {\tt imake} and then use this to
rebuild itself and all the subordinate {\tt Makefile}s. It will then
clean the directories, build all the libraries and utility programs, and
install the manual pages. On MicroVAX-II systems, it will also 
compile the kernel for the auxiliary CPUs.

{\tt make World} will take about four hours or so on an unloaded 
MicroVAX-II, and about one hour on an unloaded Sun4.

\subsection{Commands defined in the main system {\tt Makefile}}

The system {\tt Makefile} contains the following commands which may be of
some use:

\begin{list}{}{}
\item[$\diamondsuit$] {\tt make clean} removes all executable, object, and
garbage files from the source tree.

\item[$\diamondsuit$] {\tt make depend} builds the include file dependencies
for all of the {\tt Makefile}s. These are kept in a separate file, called
{\tt DependFile}, which co-exists alongside the {\tt Makefile} and is included
by it.

\item[$\diamondsuit$] {\tt make libs} builds all of the system libraries,
except for those defined in {\tt locallib} and {\tt libCtree}. 

\item[$\diamondsuit$] {\tt make bins} builds all of the utility programs,
expect for those defined in {\tt localbin}. It does {\it not} build the
demo programs.

\item[$\diamondsuit$] {\tt make manpages} creates the online manual pages.
\end{list}

\section{Installing the Simulator Service}

In order to be able to run the simulator program {\tt robotsim}, it
is necessary to define a TCP/IP service port for it in the
{\filefont /etc/services} file of every machine on which it is to run.
If you are running yellow pages, then the service should be defined
in the corresponding yellow pages file instead.

The service name is {\tt RCISimMux}, and the port number
which we usually assign is 5347. The corresponding entry in the file looks
like this: 
\begin{verbatim}
      RCISimMux    5347/tcp   # RCI simulator service
\end{verbatim}
The port number should be unique. If 5347 has already been assigned on your
system, then select some other port number which has not been assigned. Be
sure to select a port number which is reserved for site-specific usage; the
comments in {\filefont /etc/services} should indicate which these are.

It may be convenient (or necessary) to consult your local system
administrator for help in defining the simulator service.

\chapter{Adding Real-time Support to the System Kernel}\label{kernmods}

\section{Introduction}

Because RCI provides the ability to create real-time tasks, 
it is necessary that the host system kernel be able to support
real-time tasks. Historically, the UNIX kernels available on
most workstations did not do this, although the situation is now
changing. 

Fortunately, the real-time support needed by RCI is rather minimal, 
and so on some systems (MicroVAXen and Sun4s) it is possible to patch
the needed features into the kernel. The MicroVAX patches require
kernel source code, whereas the Sun4 patches do not. The SGI IRIX
kernel already has sufficient real-time support for RCI, and
so it does not need any patching at all, although a
special RCI ``driver'' is added
to provide a convenient interface to certain kernel services.

If you are building a {\it simulator-only} version of RCCL/RCI,
then the real-time support features described here are
not needed, and you can skip to the next section.

The extra kernel support which is required on MicroVAX and Sun4
systems is described in section \ref{extra.sec}. Actual kernel
configuration procedures are described for the MicroVAX in section
\ref{MicroVAXkern.sec}, for the Sun4 in section \ref{Sun4kern.sec}, and
for SGI machines in \ref{SGIkern.sec}. The concepts are similar in most
cases, and so it may be useful to scan the documentation for systems
other than your own.

\subsection{Real-time support for MicroVAX and Sun4 systems}\label{extra.sec}

RCI control tasks are generally executed
upon the occurrence of a particular clock or device interrupt. 
Giving the task the necessary real-time response requires
that it be able to respond quickly to such events. 
Since neither BSD 4.3 nor SunOS 4.2 (the primary kernels
for MicroVAX and Sun4 systems) offer this capability directly,
we handle the situation ourselves by arranging for RCI
tasks to be run in system kernel mode, at high IPL, off of the
interrupt stack.

Doing this immediately presents three
technical difficulties:

\medskip
\begin{list}{}{}
\item[1.]
The control level code must be locked into physical memory so that it 
is not paged out when the clock or device interrupt driving
the control task occurs;

\item[2.]
Some support must be placed into the kernel trap handling code
so that exceptions which occur while the control task is running will
not produce a UNIX system crash;

\item[3.]
Executing process code from within an interrupt handler requires
that there be a way of quickly switching to and from
the process memory context.
\end{list}

The kernel support for MicroVAX and Sun4 systems handles these three things.
SunOS provides a memory locking primitive which more or less
takes care of item (1).

\subsection{Support for auxiliary CPUs}\label{auxCPU.sec}

In principle, RCI control tasks can be run on either the main UNIX
CPU (also known as the {\it arbiter} CPU),
or on auxiliary CPUs connected to the same backplane. 
Running tasks on dedicated auxiliary CPUs requires
a real-time kernel for those CPUs, plus a
special driver to interface this kernel to the UNIX system.

Support for using auxiliary CPUs is presently provided only for MicroVAX-II
systems. 
The auxiliary CPUs consist of KA630 (or KA620) MicroVAX CPU modules plugged
into the system Q-bus. They run a small real-time kernel which was written at
McGill University by Mike Parker, and are interfaced to UNIX through a
special device driver. The real-time kernel is part of the standard RCCL
distribution, and is located in the directory {\filefont \$RCCL/auxkernel}.

\section{MicroVAX-II Kernel Configuration}\label{MicroVAXkern.sec}

The real-time support for MicroVAXen is more complex than that for other
systems, since the operating system provides none of the required features and
it was necessary to add them ourselves. This included adding a set of system
calls to take care of memory locking, in addition to the support required to
quickly switch process memory contexts at interrupt level.

The modifications were made to a stock Berkeley 4.3 system, {\bf not}
a Mt.\ Xinu system or Ultrix. Adding the changes described to those systems
should not be much more difficult, but {\it you will need source code}.

\subsection{Doing it the easy way}

The easiest way to obtain the kernel support is to acquire a
modified 4.3 kernel from McGill. If you can send us your system
configuration file and your disk table sizing parameters, we can probably
build a bootable kernel that will run on your system.
%%% mention we'd also need driver code for any special drivers?

\subsection{Doing it yourself}

If obtaining a kernel from McGill is not possible, you can go through
the modifications we have made and install them yourself. This {\it will}
require that you have source code for your system.

Making the modifications yourself requires that you have a very
good understanding of low level UNIX system concepts, such as
device drivers, how to configure a kernel, and how to add system
calls. The documentation in this section is more
of a guide than a
recipe.

The kernel support for MicroVAXen is located in the directory
{\filefont \$RCCL/sys.uVAX}. This contains, basically, a copy of all the files
we either added or changed, located in the same places that they normally
occupy in the full source tree.
For more details on the modifications and how they are
implemented, see the supporting
document {\tt MicroVAX-II Kernel Support for RCI}.

The best approach to installing these changes on your system is
probably to do something like run {\tt diff} on the two source trees:
\begin{verbatim}
      % cd $RCCL
      % diff -r sys.uVAX /sys
\end{verbatim}
Much of the output will talk about files in {\tt sys} that are not included
in {\tt sys.uVAX}; you can forget about these. Ideally, the rest of the
output should be things that we have added and you should simply be able to
add yourself. There may be a few places where the indentation format for the
two files differs, in which case the {\tt diff} output will be very verbose
and not too interesting. The best thing to do here is probably to run
both files through {\tt indent} and then run {\tt diff} again.

\subsection{Support for RCI tasks running on the main UNIX CPU}

The changes as currently implemented are compiled into the kernel
by setting the following options in the system config file:
\begin{verbatim}
      options       MEMORYMAPPING
      options       KERNEL_USER_TRAPS
      options       LOCAL
      options       RCI
\end{verbatim}

{\tolerance=10000
An RCI control task running on the main UNIX (or {\it arbiter}) 
CPU executes at interrupt
level, which implies that it needs an interrupt to connect to.
This is provided by a UNIX device driver which contains the 
code necessary to run an RCI task inside its interrupt service routine.
That is about all the driver has to do; RCI tasks have direct access
to the I/O bus and do their data input and output directly. In fact,
the UNIX interrupt routine actually calls the RCI task monitor,
which uses polling functions to determine which of its tasks can
be run. The UNIX driver simply provides a {\it polling
interrupt}. Consequently, the code to do this is pretty much the same
for all the drivers. The file {\filefont rci\_template.c} in the
directory {\filefont sys/rciext} contains a template RCI
interrupt driver. Support routines are contained in the file
{\filefont sys/rciext/rci.c}.
An interrupt driver for the DEC DRV11-J parallel port
is found in {\filefont sys/vaxuba/drvj.c}, and an interrupt driver for the
DRV11 is found in {\filefont sys/vaxuba/pri.c}. The latter driver
is much more complicated than it presently needs to be because it contains
support code for the old RCCL system.

}
The interrupt drivers are presently written with an option to
access them as exclusive open devices (i.e., openable by only one process
at a time), which is usually desirable as a
check 
against multiple processes colliding over the same device (the other
way this is done is to maintain lock files in {\filefont \$RCCL/lock}).
An interrupt driver is opened exclusively if, typically,
bit 7 in its minor device number is set.

RCI control tasks running on the arbiter also make use 
of something called a {\it generic} RCI device. This is a
pseudo-device configured into the kernel which provides the following
services:

\medskip
\begin{list}{}{}
\item[$\diamondsuit$]
provide the addresses of various kernel objects such as the kernel
print routine and the virtual memory locations of the bus interfaces;

\item[$\diamondsuit$]
provide a way to execute RCI tasks directly at the request of the
planning program;

\item[$\diamondsuit$]
connect an RCI task to the system clock interrupt.
\end{list}

These services are used by the RCI system code to implement the RCI
interface seen by the programmer. Much of the functionality
of the driver is identical to that provided 
by the polling device drivers. The code for the
generic RCI device driver lives in {\filefont sys/rciext/genrci.c}.

A generic RCI device is configured into the kernel 
by placing it into {\tt cdevsw}, defining several units for
the pseudo-device {\tt genrci} in the kernel
config file,
and creating the character device files {\filefont /dev/genrci<n>},
each with the appropriate major device number and minor device number
{\tt <n>}. Every RCI program needs to open a generic RCI device. Since
these devices are exclusive open, the number of them provided
determines the
maximum number of RCI programs that may be run simultaneously.

Lastly, RCI control tasks running on the arbiter may make use
of a clock device to provide a time base independent of the
system clock. Providing a separate clock device 
allows (1) the setting of a time interval not provided by the system
clock, and (2) a separate count to be kept which allows recovery
from clock interrupts missed because of RCI control tasks
(RCI control tasks running on the arbiter must run non-interruptibly,
which can cause the system clock to miss ticks).

An RCI program looks for a clock device in {\filefont /dev/rciclk}. If this
device is present, it is assumed that the clock is available and will
remain active for at least as long as some process has it open. The clock
device implemented for the MicroVAX-II Q22-bus was built using a DRV11
parallel port and a small amount of timer logic. The hardware aspects of the
device are discussed in the document {\it RCCL/RCI Hardware Installation 
Notes}.
Its device driver lives in {\filefont sys/rciext/drvclk.c}.

Clock devices are not as necessary if the system contains auxiliary CPUs,
mainly because control tasks running on the auxiliaries do not have to run
non-interruptibly, and therefore their system clocks will not lose time.
A system clock running on one of the auxiliary CPUs can be broadcast to
other CPUs, including the arbiter, so that the arbiter system clock does
not have to be used.

\subsection{Support for RCI tasks running on auxiliary CPUS}

UNIX is interfaced to auxiliary CPUs using a special driver
(which is called the {\tt ka} driver because the MicroVAX processors
are named KA630s). The driver is mainly responsible for
managing and allocating shared memory space on the Q22-bus
which is used to provide inter-CPU communication.
It also provides a set of I/O controls
that boot an auxiliary CPU and exchanges messages with it.

The code for this driver lives in {\filefont sys/rciext/ka.c} and various other
{\tt ka*.h} files in the directory {\filefont sys/rciext}.

On MicroVAX-II systems, the {\tt ka} driver should be configured into
the system at Q-bus address 0177500 (this is the base address of
the processor mailbox registers). At boot time, the driver checks the
reserved mailbox locations to see what CPUs are actually present.
Up to four MicroVAX CPUS, including the arbiter,
can be placed onto the Q-bus (although there are restrictions on
{\bf where} you can place them; see the {\it RCCL/RCI Hardware Installation
Notes}).
Within the driver,
each CPU unit corresponds to a different minor device, with minor device 0
being used for CPU 0, minor device 1 being used for CPU 1, etc.
To allow the driver to be opened, 
four character devices named {\filefont /dev/ka<n>} should be created.
These are exclusive open devices. Four other character devices,
named {\filefont /dev/kaD<n>}, should be created
with bit 7 of their minor device number set to provide multiple open
capability\footnotemark.
\footnotetext
{Note that this is the opposite of the convention for polling interrupt
devices, where setting bit 7 in the minor device number indicates an
exclusive open device; this is a historical artifact.}

Information about the hardware aspects of installing auxiliary CPUs can
be found in the document {\it RCCL/RCI Hardware Installation Notes}. Once an
auxiliary 
CPU is in place and noticed by the {\tt ka} driver at boot time, 
the RCI system code will do
everything else for you --- a call to {\tt rciCreate()} requesting
a particular CPU will ask the {\tt ka} driver if the CPU is available,
cause that CPU to be booted, if necessary, and then load it with
a copy of the RCI program image. The minikernel that runs on the
auxiliary CPU is located in the directory {\filefont \$RCCL/auxkernel}, and
is created as part of the general system ``make''.

\subsection{Summary of the system configuration at McGill}

This section describes the MicroVAX-II system configuration as it is
currently implemented at the McGill University site.

The system configuration file contains the following entries related to 
RCI:

\begin{verbatim}
      options       MEMORYMAPPING
      options       KERNEL_USER_TRAPS
      options       LOCAL
      options       RCI

      # driver for auxiliary, microVAX CPUs
      device        ka0     at uba? csr 0177500
                                    vector kaintr

      # driver for the DRV11 port connected to the robot
      device        pri0    at uba? csr 0167770 flags 0300
                                    vector priintr

      # driver for the DRV11 based real-time clock module
      device        drvclk0 at uba? csr 0160400 flags 0100
                                    vector drvclkintr

      # general RCI interface devices
      pseudo-device   genrci        4
\end{verbatim}

The device {\tt pri0} is the polling interrupt device for the DEC DRV11
parallel port (used to communicate with our robot), 
and {\tt drvclk0} is the RCI clock device, which also happens
to be implemented with a DRV11. Because the DRV11 cannot force
itself to interrupt, vector information for any DRV11 based device is
passed to the driver probe routine using the {\tt flags}
field.

The special files located in {\tt /dev} are described in table
\ref{specialfiles}. Major device numbers are quoted verbatim, although these
will vary from system to system.

\begin{table}[htb]
\def\0{\phantom{0}}
\centerline{\tablebox{\halign{%
#\hfil&\hfil#\hfil&&\hfil#\hfil\cr
file name & major device & minor device \cr
\noalign{\medskip\hrule\medskip}
\tt /dev/ka0      & 70 & \0\00 \cr
\tt /dev/ka1      & 70 & \0\01 \cr
\tt /dev/ka2      & 70 & \0\02 \cr
\tt /dev/ka3      & 70 & \0\03 \cr
\noalign{\medskip}
\tt /dev/kaD0     & 70 & 128 \cr
\tt /dev/kaD1     & 70 & 129 \cr
\tt /dev/kaD2     & 70 & 130 \cr
\tt /dev/kaD3     & 70 & 131 \cr
\noalign{\medskip}
\tt /dev/genrci0 & 71 & 128 \cr
\tt /dev/genrci1 & 71 & 129 \cr
\tt /dev/genrci2 & 71 & 130 \cr
\tt /dev/genrci3 & 71 & 131 \cr
\noalign{\medskip}
\tt /dev/pri0     & 67 & \0\00 \cr
\tt /dev/priRCI0 & 67 & 128 \cr
\tt /dev/rciclk  & 74 & \0\00 \cr
}}}
\caption{Special files in {\filefont /dev} related to RCCL/RCI at the McGill
site} 
\label{specialfiles}
\end{table}

{\filefont /dev/ka<n>} are the exclusive open {\tt ka} devices
and {\filefont /dev/kaD<n>} are the multiple open ones. {\filefont /dev/pri0}
is multiple open, and {\filefont /dev/priRCI0} is exclusive open.

\section{Sun4 Kernel Configuration}\label{Sun4kern.sec}

The real-time support that was developed for SunOS 4.1 and 4.2
represented something of a breakthrough because it
can be installed on binary-only distributions. Installation is therefore
more of a ``drop in''.

At the time of this writing, Sun is preparing to upgrade its operating 
system to Solaris 2.0. It is unlikely that the RCI kernel patches will work
with Solaris 2.0, at least in their current form. Hopefully,
Solaris 2.0 may contain enough real-time
support so as to make the kernel patches unnecessary.

\subsection{What the reader should know}

The reader is assumed to be familiar with configuring system kernels, and with
installing device drivers. Documentation on these subjects is available as
part of the Sun documentation kit. The procedures are not really difficult,
but they can be time consuming.

\subsection{Unpacking the modules}

In the RCCL distribution tape, there is a directory labeled 
{\filefont sys.Sun4}, which in turn contains the subdirectories 
{\filefont rciext}, {\filefont sun4/conf}, and {\filefont sun}.

The {\tt rciext} directory contains the kernel-level support code for
RCI. A copy of this should be placed in the kernel root directory (which
is usually called {\tt /sys}),
alongside other directories such as {\tt os} and {\tt net}.

The other directories contain template files to help in configuring the
kernel. In particular, you should find the template files
\begin{verbatim}
      sys.Sun4/sun4/conf/CONFIG.RCI
      sys.Sun4/sun4/conf/files.RCI
      sys.Sun4/sun/conf.c.RCI
\end{verbatim}
The text below will make occasional references to these.

\subsection{Installing the modules}

After the directory {\tt rciext} has been copied to {\tt /sys}, you should
go there and check the {\tt Makefile}
to make sure that {\tt OBJD} (which
is defined near the top) is set to the
correct directory for system object modules. The default setting
in the distribution is {\filefont ../sun4/OBJ}. If you are configuring
RCI for a Sun4c, you will need to change this to
{\filefont ../sun4c/OBJ}.

When {\tt OBJD} is correctly set in the {\tt Makefile}, you should do
\begin{verbatim}
      % make install
\end{verbatim}
This will build some utility programs and insert some static patches into a
few of the kernel object modules.

\begin{quote}
{\bf CAUTION:} 
Copies of the original (unpatched) object files will be placed in the kernel
object directory ({\tt OBJD}) with the name extension {\tt .orig}. You {\bf do
not} want to delete  
these files, since if you do, {\tt make} may attempt to replace them with
the new (patched) versions. 
To play it safe, you should probably make a secondary copy of the {\tt .orig} 
files.
\end{quote}

\subsection{Editing the configuration files}\label{editconfig.sec}

\subsubsection{The main config file}\label{Sun4mainconfig.sec}

Options to compile in RCI kernel support must be added to the main system
config file, normally found in the directory {\filefont /sys/sun4/conf}
(or {\filefont sun4c/conf}). The file usually has the same name as the
system being configured; we will assume here that this is {\tt <SYSNAME>}.

The following option commands should be added to the config file:
\begin{verbatim}
      options LOCAL
      options RCI
\end{verbatim}

The following pseudo-device should also be defined:
\begin{verbatim}
      pseudo-device genrci 4
\end{verbatim}

The number of {\tt genrci} devices determines the number of RCI programs that
can be running simultaneously; four has always been more than adequate.

If you are going to be using a real-time clock for RCI (i.e., the XYCOM XVME
203 or 293), then you will also need to include the device driver for this:
\begin{verbatim}
      device  xyclk0 at vme16d16 ? csr <address> priority 5 \
              vector xyclkintr <vecnum>
\end{verbatim}
{\tt <address>} gives the device's address in the VME short I/O space.
Information on how to set this is given in the {\it RCCL/RCI Hardware
Installation Notes}.
See section \ref{sbus} if you have an S-bus machine.
The device's VME interrupt level is set in software by the driver
and {\tt 5} matches the value which the driver uses by default; to change this
value, edit the file {\filefont sys/rciext/xyclkreg.h}. The interrupt vector
number is also set by software to whatever value is specified by {\tt
<vecnum>}; 
this selection should be based on what vectors are available.

Finally, you need to configure in the driver for whatever interface devices
you will need. At the moment, only one driver is supplied with the
distribution; 
this is for a XYCOM XVME 240 parallel port used to communicate with a
Unimation robot controller. The configuration entry for this device
looks like this:
\begin{verbatim}
      device  xyd0 at vme16d16 ? csr <address> priority <ipl> \
              vector xydintr <vecnum>
\end{verbatim}
Again, {\tt <address>} gives the physical address of the device
in VME short I/O space; see the {\it RCCL/RCI Hardware Installation Notes}
for more information on how to set it. {\tt <ipl>} is the VME interrupt
priority level, which should match the value set on the board and which is
also described in the hardware manual.
The interrupt vector will be set by software to {\tt <vecnum>}.

\subsubsection{The ``files'' file}

The config directory should also contain a file called {\tt files.<SYSNAME>},
which gives the names and locations of source modules
which are specific to the system. If this file does not already exist, you
should create it. Add to this file all the entries defined in the
template file {\tt files.RCI}. If you have
written your own interface drivers, you
will need to add the filenames for them as well.

\subsubsection{The ``conf'' file}

The file {\tt conf.c}, located in the directory {\filefont /sys/sun}, contains
the configuration tables for the system device drivers. You need to add
entries to this table for the generic RCI driver, plus any other RCI drivers
which your system needs (such as for the {\tt xyclk} clock timer or the {\tt
xyd} parallel interface described above). All the drivers supplied with the
system (at least all 
the ones so far!) are {\it character} devices. Structures describing the
entry points and data structures for these 
devices need to be entered into the table {\tt cdevsw}, located
in {\tt conf.c}. Entries are usually placed at the end
of the existing table, and the table index (which appears in a comment at the 
right of each entry) denotes the {\it major} number for the device.

\begin{quote}
Take note of the major device numbers you assign; you will need them
when creating special files for the devices in {\tt /dev}.
\end{quote}

For each device structure there is usually a set of preprocessor definitions
that appear {\it before} the {\tt cdevsw} array.  These definitions
first reference an include file 
to determine if, in fact, the driver should be configured
into the current kernel. If not, some {\tt \#define} statements are used to 
``null-out'' the appropriate table entries. The include file in question
has the name {\tt <device>.h}, and is
created by {\filefont /etc/config} when it processes the kernel config file.

Sample table entries for the drivers supplied with the distribution are given
in the template file {\tt conf.c.RCI}.

\subsection{Building the kernel}

Once the configuration files have been set up, you may proceed with building
the system in the usual fashion:
\begin{verbatim}
      % cd /sys/sun4/conf     # (or /sys/sun4c/conf)
      % /etc/config <SYSNAME>
         ... this takes a few minutes ...
      % cd ../<SYSNAME>
      % /bin/make vmunix      # do not use GNU make
         ... this takes a few more minutes ...
\end{verbatim}

\begin{quote}
{\bf Important}: As the comment in the above example indicates,
GNU {\tt make} should not be used because the {\tt Makefile}
generated by {\filefont /etc/config} uses Sun-specific features
not found in GNU {\tt make}. In particular, it uses a
{\tt +=} operator.
\end{quote}

You can now move the completed kernel into {\tt /} and reboot. Saving the
previous kernel is {\bf highly} recommended in case the new
kernel will not boot; you might want to use the {\tt move} command
supplied in the {\tt rciext} directory with the RCI kernel software.

\subsection{Creating device entries}

The last thing you need to do is go to the directory {\tt /dev} and create
a special file for each device which you have configured into the system.

All devices provided with the distribution are character devices, and
their corresponding special files are created with the following usage
of the command {\tt mknod}:
\begin{verbatim}
      % /etc/mknod <filename> c <major> <minor>
\end{verbatim}
{\tt <filename>} is usually the same as the device driver name, plus a number
at the end indicating the unit number (which usually starts at 0). 
{\tt <major>} is the major device 
number (i.e., the index into the driver table {\tt cdevsw}), and {\tt <minor>}
is the minor device number. 

The minor device number is {\it usually} the unit number, except that
other bits may be set as well.
Because the number of units for a particular
device is limited to a small integer, the higher order bits of the minor
number can be used to pass other
information to the driver routines. In particular, RCI drivers are written so
that if bit 7 (i.e., {\tt 0x80}) of the minor number is set, then the device
behaves as an {\it exclusive open} device, which means it may be opened
by only one process at a time. This provides a reasonable safety check
against having more than one process try to do something like control the same
robot simultaneously.
To determine the minor number for an exclusive open RCI device, take its unit
number and then set bit 7 (or, equivalently, add 128). 

A special file {\tt genrciX} should be created for every RCI generic
pseudo-device. 
These devices should be exclusive open, so bit 7 of the minor number should
be set.
The commands to create four such devices, if the major number were 104, would
be: 
\begin{verbatim}
      % /etc/mknod /dev/genrci0 c 104 128
      % /etc/mknod /dev/genrci1 c 104 129
      % /etc/mknod /dev/genrci2 c 104 130
      % /etc/mknod /dev/genrci3 c 104 131
\end{verbatim}

If the {\tt xyclk} real-time clock device is present, then a special file
must be created for it as well. It is given the generic name {\tt
rciclk}, and since it is not an exclusive open device, the
minor number should be 0. The command to set this up may look like:
\begin{verbatim}
      % /etc/mknod /dev/rciclk c 105 0
\end{verbatim}

Finally, create a special file for each interface device. These devices should
be exclusive open, so, again, add 128 to the minor number. The corresponding
special file usually 
takes the name of the device driver, plus {\tt RCI}, plus the unit number.
For example, the special file for unit 0 of the {\tt xyd} interface can be
created with a command which looks like:
\begin{verbatim}
      % /etc/mknod /dev/xydRCI0 c 106 128
\end{verbatim}

After the special files have been created, make sure that they have
world read-write permission; you can use the command {\tt chmod} for this.

\subsection{If you have an S-bus machine}\label{sbus}

\subsubsection{Bus adaptors}

If you have an S-bus machine, and you want to interface it to VME devices,
then the approach we recommend is to get an S-bus to VME
adaptor. Several manufacturers make S-bus to VME adaptors, and we have 
had some experience with two: Performance Technologies, Inc, and
Bit-3 Corporation.

The Performance Technologies interface (called the PT-SBS915)
appears to be the more powerful
product, although it may also be more expensive. They can supply
some configuration software which makes the device completely transparent
to kernel configuration. If you do this, you can then follow the Sun4
kernel configuration procedure described above as though the system
is a VME-based Sun. The configuration software comes with a private version
of  {\tt /etc/config} that takes references to VME devices in the system
config file and introduces the necessary interface board software
into the kernel.

If you do not wish to buy the configuration software supplied by Performance 
Technologies, then you may be able to use a driver which was
written by John Bradley at the University of Pennsylvania. The driver,
contained in the directory {\filefont sys.Sun4/pti}, 
implements the {\tt xyclk} and {\tt xyd} drivers (described
in section \ref{Sun4mainconfig.sec}) directly on top of a
Performance Technologies interface board.

The current address for Performance Technologies is:
\begin{quote}
Performance Technologies, Incorporated \\
315 Science Parkway \\
Rochester, New York \\
USA 14620 \\
(716) 256-0200
\end{quote}

The Bit-3 interface does not (as far as we know) come with software that
makes its completely transparent. 
Consequently, you may have to write your own S-bus driver for it.

A driver for the Bit-3 interface was also written by John Bradley at the
University of Pennsylvania, although this is not supplied with
the RCCL distribution. You may be able to contact John Bradley directly
and arrange for a copy:
\begin{verbatim}
      bradley@grasp.cis.upenn.edu
\end{verbatim}
You many also be able to clone John Bradley's PTI driver
(in {\filefont sys.Sun4/pti}) into a workable Bit-3 driver.

The address for Bit-3 Corporation is:
\begin{quote}
Bit-3 Computer Corporation \\
8120 Penn Avenue South \\
Minneapolis, MN 55431-1393 \\
(612) 881-6955 \\
FAX: (612)881-9674
\end{quote}

In the next couple of sections, information is provided that might
be of general use if you are writing your own S-bus to VME
interface driver. 

\subsubsection{The VME bus map variables}

RCI currently provides application programs with direct access
to the VME bus through a couple of variables, {\tt rciIOpage} and
{\tt rciBus}, which are pointers to regions of virtual address space
which map the following subsections of the VME bus:

\begin{list}{}{}
\item[$\diamondsuit$]{\tt IOpage} -- all of the VME A16D16 subspace;
\item[$\diamondsuit$]{\tt bus} -- a two megabyte ({\tt 0x200000}) 
subsection of VME a24d16 space, 
starting at the subspace's midpoint (i.e., {\tt VME24\_BASE + 0x800000}).
\end{list}

The virtual address regions that map these subspaces are set up by the RCI
kernel software the first time any RCI device is opened after a system
reboot.

There is a routine
called {\tt createBusMaps()}, located in {\filefont sys/rciext/rci.c}, which 
allocates the necessary amount of kernel virtual space and maps it onto 
the two subsections of the VME bus. 
A system which uses a bus adaptor will have to
have this routine modified so that the bus maps are still set up correctly.

\begin{quote}
{\bf NOTE:} There is nothing particularly special about which parts
of the bus space are mapped by RCI. The assignment for {\tt rciIOpage} makes
sense since utility devices often
appear in VME A16D16 space. This space 
is also small (64K bytes), and so there is no reason not to map the whole
thing. The assignment for {\tt rciBus} is a bit more artificial. We chose to
map VME {\tt A24D16} space, since that is the second likeliest place to find
user devices. We mapped only part of it since the whole space is 16M bytes
long and
it was hard (back when we first did this) to get that much virtual address
space from the Sun kernel. 2M bytes seemed more reasonable, and we started
the map at the midpoint of the address space because Sun tends to use the
lower half for its own devices. But, in short, there's no serious
reason why you can't have {\tt rciBus} map
anything that's convenient (or set it to {\tt NULL} and
forget about it).
\end{quote}

\subsubsection{Bus adaptors and interrupts}

About the only other thing you need to worry about with a VME bus adaptor is
to ensure that interrupts get passed to the system correctly: RCI
usually 
uses device interrupts to help it schedule events. For instance,
the clock-timer
device (XVME 203) uses interrupts to provide RCI with its own private
timing base.

If for some reason a bus adaptor is absolutely incapable of 
providing interrupts, you can
probably still survive if you set the scheduling discipline for all RCI tasks
to {\tt ON\_CLOCK} (you'll recognize this term if you've read the RCI/RCCL
documentation). Under this scheduling discipline, an RCI task is simply run
periodically by the system clock; once woken up, it is then free to 
access or poll external devices as necessary. The penalty paid is one
of efficiency. For instance, if you run RCCL using {\tt ON\_CLOCK}, the
control task has to ``wake up'' the robot controller and then wait two or
three milliseconds for the controller to gather its feedback data and respond.
The latter delay can be avoided using the {\tt ON\_TRIGGER} scheduling
discipline, which uses interrupts.

\section{SGI IRIX Kernel Configuration}\label{SGIkern.sec}

The real-time support for SGI systems is even easier to
install than that for Sun4 systems. There are two reasons
for this: (1) the IRIX kernel provides more intrinsic real-time support,
and (2) the kernel
configuration procedure on the SGI is much more streamlined.

The supplied kernel support should work with IRIX 4.0.X,
although it will probably work with releases higher than this.
 
\subsection{What the reader should know}

The reader is assumed to be familiar with configuring system kernels.
Some familiarity with writing device drivers would also be
an asset. SGI provides documentation on writing device drivers
(although you have to ask for it specially), but
is somewhat weak on providing documentation on how to reconfigure
the kernel. Nevertheless, the procedure is straightforward, and
hopefully the instructions here are sufficient.

\subsection{Unpacking the modules}

In the RCCL distribution tape, there is a directory labeled 
{\filefont sys.SGI}, which in turn contains a subdirectory
{\filefont rciext}.

The {\tt rciext} directory contains the kernel-level support code for
RCI, and is also used as the base directory for re-configuring the kernel.
A copy of this directory should be made in {\filefont /usr/sysgen}.

The file
{\filefont rciext/README} contains a synopsis of the instructions given here.
In case of conflict, the {\filefont README} file will usually be
more accurate.

\subsection{Editing the system config file}

You need to edit the system configuration file to identify the various
device drivers to be loaded into the system. There is a generic
device driver for all RCI systems, plus specific device drivers
for each type of hardware interface. The standard distribution supplies
drivers for the XYCOM XVME 240 parallel port and the BIT3 411 VME to VME
bus adaptor. If you have different hardware, then you will need to
write your own device driver, and configure it into the kernel
in the same way as described below. The easiest way to write an
RCI device driver is to clone an existing one.

Information on the system configuration file can be obtained
from the system manual page {\tt system(4)}.

Start by creating a private configuration file:
copy the file {\filefont /usr/sysgen/system} to {\filefont /usr/sysgen/rciext}.
Then add the contents of {\filefont sys.SGI/master.d/system.RCI} to
the end of it. {\filefont system.RCI} contains the following entries:
\begin{verbatim}
      INCLUDE: genrci(4)

      VECTOR: module=xyd vector=<vect> ipl=<ipl> unit=0 base=<baddr>
              probe=<baddr+0x81> probe_size=1

      VECTOR: module=bit vector=0xff ipl=<ipl> unit=0 base=<baddr>
\end{verbatim}

Undesired entries should be commented out using a star ({\tt *}).

The {\tt genrci} entry declares the generic RCI device driver; this is
the standard kernel-level RCI interface and should always be included.

The {\tt xyd} entry describes the driver for a XYCOM XVME 240 parallel
port. Include this entry if your hardware configuration contains such a
device. {\tt <vect>} should be set to an unused interrupt vector. {\tt
<ipl>} should be set to the desired IPL level (4 is a reasonable value).
{\tt <baddr>} should be set to the memory address at which the system
can find the board. This will be the base address in the VME A16D16
(short I/O) space, added to the
system memory address for the VME A16D16 
space itself.  The value of the former depends on what you set the 
board to ({\tt 0x9000} is a common value), while the value of the
latter depends on your SGI system. The SGI device driver manual
documents the following values for various system types:

\bigskip
\centerline{\tablebox{\halign{%
\hfil#\hfil&\qquad\hfil#\hfil\cr
System CPU/type&VME A16 base address (supervisor)\cr
\noalign{\medskip\hrule\medskip}
R2300 & 0xbd000000\cr
IP4/6 & 0xbd000000\cr
IP5/7/9 & 0xb7c10000\cr
}}}
\noindent
Address information may be contained in the {\tt system} file
itself, as well.
The address associated with the probe field gives the address 
of a location used by the driver's probe routine; this should
be set to {\tt <baddr>} plus 0x81. 

The {\tt bit} entry describes a driver for a BIT3 411 VME to VME shared
memory board. Include this entry if your hardware configuration contains
such a device. 
The {\tt vector} field {\it must} be set to {\tt 0xff}, since this is the
only vector the device can generate. {\tt <ipl>} should be set to the 
desired IPL level, and {\tt <baddr>} should be set to the address
of the device's I/O registers in VME A16D16 space. 
The {\tt probe} and {\tt probe\_size} fields do not need to be set.

\subsection{Major device numbers}

Each of the device drivers configured into the kernel has a
synopsis file located in the directory
{\tt /usr/sysgen/master.d}. Each device
has a {\it prefix} and a {\it major device number} defined by
the fields {\tt PREFIX} and {\tt SOFT} in the synopsis file.
These are used by the kernel to keep track of the devices
internally, and are also used to generate the special files
which provide user level access to the devices (more on this
is given below).

The synopsis files for the supplied RCI device drivers
are packaged into the directory {\filefont rciext/master.RCI}
(and are later copied into {\tt master.d} by the {\tt make} command
which builds the system). If you have written a device driver
yourself, then you will have created your own synopsis file.

It is necessary that the prefix and major number for any
devices being introduced into a new kernel do not conflict
with existing devices. A conflict is unlikely, but the possibility
should be kept in mind.

\subsection{Editing the {\tt mem} file}

RCI, by default, maps a certain portion of the VME bus space into
user space for direct access by RCI applications. 
A description of the sections that are to be mapped 
must be placed in the file {\filefont /usr/sysgen/master.d/mem}.
Edit this file, and add to the array {\tt mmmap\_addrs} 
all the entries described in 
{\tt rciext/master.RCI/mem}
which are appropriate to your system.
There is documentation in {\tt master.RCI/mem} describing
what to include.

\subsection{Building the kernel}

Now you should be able to execute the following sequence:
\begin{verbatim}
      % cd /usr/sysgen/rciext
      % make unix.new
\end{verbatim}
to build a new UNIX kernel called {\filefont unix.new}.

\begin{quote}
{\bf NOTE}:
This procedure will
install new files in {\tt /usr/sysgen/master.d}, and create
symbolic links to {\tt /usr/include/sys} and {\tt /usr/sysgen/boot}
in the {\tt sysgen/rciext} directory.
\end{quote}

The new kernel can now be installed by copying it into {\filefont /unix}.
Saving a copy of the previous kernel is {\bf highly} recommended in case the
new kernel will not boot.

\begin{quote}
{\bf NOTE}:
When UNIX reboots, it may ask you if it should
reconfigure itself automatically. You should
answer no to this request, since the new UNIX has been
configured privately in the {\tt rciext} directory
and the auto-configure procedure will not know to 
look there.
\end{quote}

\subsection{Creating device entries}

You now need to go to the directory {\tt /dev} and create
a special file for each device which you have configured into the system.

All devices provided with the distribution are character devices, and
their corresponding special files are created with the following usage
of the command {\tt mknod}:
\begin{verbatim}
      % /etc/mknod <filename> c <major> <minor>
\end{verbatim}
{\tt <filename>} is usually the same as the device driver name, plus a number
at the end indicating the unit number (which usually starts at 0). 
{\tt <major>} is the major device 
number (the {\tt SOFT} entry in the synopsis file)
and {\tt <minor>} is the unit number. 

\begin{quote}
{\bf NOTE}: On SGI systems, we do not overload the minor device
number the way we do on Sun systems.
\end{quote}

A special file {\tt genrciX} should be created for every RCI generic
pseudo-device. The commands to set up four such devices, if the major number
were 60, would be:

\begin{verbatim}
      % /etc/mknod /dev/genrci0 c 60 0
      % /etc/mknod /dev/genrci1 c 60 1
      % /etc/mknod /dev/genrci2 c 60 2
      % /etc/mknod /dev/genrci3 c 60 3
\end{verbatim}

A special file must also be created for each interface device. 
The corresponding special file usually 
takes the name of the device driver (check the {\tt PREFIX} entry
in the synopsis file), plus a trailing ``{\tt RCI}'' and the unit number.
For example, the special file for unit 0 of the {\tt xyd} interface can be
created with a command which looks like:
\begin{verbatim}
      % /etc/mknod /dev/xydRCI0 c 61 0
\end{verbatim}

After the special files have been created, make sure that they have
world read-write permission; you can use the command {\tt chmod} for this.

\section{The {\tt rciCheck} Program}\label{rciCheck.sec}

After you have built the kernel and installed all the necessary devices,
you can verify that things are working correctly by compiling
and then running the program {\tt rciCheck}, located in 
{\filefont \$RCCL/rci}.
(You will need to have built the main RCCL directory first.) {\tt rciCheck}
can be built within the {\tt rci} directory using the command
\begin{verbatim}
      % make rciCheck
\end{verbatim}

The program will start up an RCI control task and run it through some
operations in 
an attempt to verify that the basic RCI kernel support is operational. It will
print some messages while it is doing this, and then terminate (if all goes
well) with an {\tt OK} message. The first time you run {\tt rciCheck}, you
should probably also run the script {\tt syncs} in the background.
{\tt syncs}, which is also located in {\filefont
\$RCCL/rci}, make continuous calls to the system disk-sync command,
thus reducing the chance of file system problems if the system does in fact
crash. 

{\tt rciCheck} should also be run with the {\tt -crash} option. This will
cause the program to go through the same initial checks, but at the end
it will terminate by forcing an exception within the control code. 
The purpose of this is to check out the control level exception handling
mechanism. 
On MicroVAX and Sun4 systems, this should result in a message 
like
\begin{verbatim}
      Program Crash on arbiter, generic RCI device
\end{verbatim}
followed by a numeric stack trace.
On SGI systems, you should simply get a message like
\begin{verbatim}
      Program crash in RCI control level. Check core file.
\end{verbatim}
On VxWorks, you should get a VxWorks exception message
and the suspension of the VxWorks task {\tt rciCtrl},
which implements the RCI control level.

\chapter{Configuring the RCCL/RCI Software}\label{configure.sec}

This section discusses configuring an RCCL/RCI system. Most
of this involves
specifying the parameters, operating characteristics, and interfaces for the
robots that are attached to the system. The system currently supports
robots of the type (or {\it class}) {\tt PUMA}, {\tt STAN} (the Stanford
arm), and {\tt ELBOW} (the ``elbow'' manipulator). Other types
may have been added since this writing. Adding a new class of robot to
the system is discussed in section \ref{newrobots}.

\begin{quote}
{\bf NOTE}: If you are setting up a VxWorks system, then you should
read the auxiliary document {\it RCCL/RCI on VxWorks} as well.
\end{quote}

\section{Review of Basic Concepts}\label{concepts.sec}

The robot support facilities used by RCCL/RCI are a component of the RCI
subsystem. Most of what is described here is also described in the
{\it RCI User's Guide} and the {\it RCI Reference Manual}.

\subsection{Robot classification}

A robot configured into the RCI system is given a symbolic name and
is associated with a particular {\it class} of robots
(such as {\tt PUMA}, {\tt STAN}, or {\tt ELBOW}).
Classes are defined in the file {\filefont h/robot\_class.h}. Each class of
robots is associated with 

\begin{enumerate}

\item
A set of robot-specific parameter structures (and functions to create them);

\item
A set of kinematic and dynamic computation functions.

\end{enumerate}

\subsection{Robot parameter structures}

Parameter information for a robot is defined by three
data structures.

\begin{enumerate}

i\tem
{\it The {\tt JLS} structure --} This contains a ``joint level'' description
of the robot, including such things as the gear ratios, joint and velocity
limits, encoder to joint value conversion factors, and joint level calibration
information. It also contains pointers to special functions
for doing operations such as mapping from actuator (encoder) values
to joint values (see section {\tt compfunc.sec}). 
The definition of the {\tt JLS} structure is 
identical for all
classes of robot, and is contained in {\filefont h/robot\_jls.h}. 
For more information on the {\tt JLS} structure and how
to obtain it, see {\tt JLS(3)} and {\tt getJls(3)}.

\item
{\it The {\tt KYN} structure --} This contains ``kinematic level'' information
for the robot in question.
The {\tt KYN} structure contains pointers to two data areas:
{\tt gen} and {\tt ext}.
{\tt gen} references a structure of type {\tt GEN\_KYN}, which defines
a fixed set of parameters which are applicable to most robot types.
The ``A'' matrix parameters, and some dynamic
modeling coefficients, fit into this category.
A field {\tt class} contains the class of the robot
as defined in {\filefont h/robotClass.h}.
The {\tt GEN\_KYN} structure also contains a set of
functions, whose implementation is specific to the robot class,
for doing various kinematic and dynamic computations (see section 
\ref{compfunc.sec}).
{\tt ext} references a separate data area whose definition is specific to
the robot class. This can include special-case parameters used by
the kinematic and dynamic computation
functions.
The {\tt KYN} {\tt ext} structure for a particular robot has the name
{\tt <class>\_KYN}, and is defined in {\filefont h/<class>\_kynvar.h}. 
For more information on the {\tt KYN} structure and how
to obtain it, see {\tt KYN(3)} and {\tt getKyn(3)}.

\item
{\it The {\tt VAR} structure --} The purpose of this structure
is to serve as a ``scratch pad'' for
robot computational routines. It provides a place to store
interim computational results, which can then be used by other routines to
save time. For instance, for many robots, the {\tt VAR} structure is used
to store the sines and cosines of the
joint angles, which are produced as a by-product of forward
and inverse kinematic computations.
These values can then be used
by other routines (usually during the same control cycle),
such as those which do Jacobian or dynamic computations.
The type of the {\tt VAR} structure depends on the
class of the particular robot. For any given class, the {\tt VAR}
type has the name
{\tt <class>\_VAR}, and is defined in {\filefont h/<class>\_kynvar.h}. 
A program must allocate its own {\tt VAR} structures for a particular robot,
using the size returned by the routine {\tt getVarSize()}.
For more information on the {\tt VAR} structure,
see {\tt VAR(3)} and {\tt getVarSize(3)}.

\end{enumerate}

\subsection{Computation Functions}\label{compfunc.sec}

\subsubsection{{\tt JLS} conversion functions}\label{jlsfunc.sec}

The {\tt JLS} structure contains pointers to functions that do
conversions between
joint and actuator coordinate systems.
These functions include:

\begin{verbatim}
      encoderToAngle (ang, enc, jls)
      angleToEncoder (enc, ang, jls)
      encoderToJoint (jnt, enc, jls)
      jointToEncoder (enc, jnt, jls)
      mtorqueToJtorque (jtor, mtor, jls)
      jtorqueToMtorque (mtor, jtor, jls) 
\end{verbatim}

{\tolerance=10000
Generic versions of these functions, which will work for all classes
of robots,
are defined in {\filefont robots/gen\_convert.c} and 
are documented in the {\it RCI Reference Manual}. The reason for having
class-specific versions as well is that they can be implemented much more
efficiently.

}

\subsubsection{Kinematic functions}\label{kynfunc.sec}

The {\tt GEN\_KYN} substructure of the {\tt KYN} structure
contains pointers to class-specific functions for
implementing the following generic routines:
\begin{verbatim}
      fwdKinematics (t6,cp,j6,kyn,var)
      invKinematics (j6,t6,c,refj,kyn,jls,var)
      solveConf (cp,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)

      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)

      updateVar (var,ang,kyn)
      updateVarXsincos (var,ang,kyn)
\end{verbatim}

The implementation functions take the same arguments
as the routines. Note that they all take a
pointer to the {\tt KYN} structure as an argument.
Each function has a manual page in the
{\it RCI Reference Manual} explaining
exactly what it does.

These function definitions are adequate for any six degree of freedom robot.
Controlling robots with more degrees of freedom will probably require that
the function set be generalized to allow the incorporation of strategies for
resolving kinematic redundancies.

\subsection{Robot communication functions}\label{rbtcomfunc.sec}

Each robot class defines a set of {\it communication} functions which is used
to handle the communication between the RCI 
control task and the robot controller. There are six of these
functions:

\begin{verbatim}
      startup (rbt)
      input (rbt)
      output (rbt)
      release (rbt)

      ready (arg)
      wakeup (arg)
\end{verbatim}

Their definitions are given in detail in the {\it RCI User's Guide} and also
in the manual page {\tt robotComfxns(7)}.

The job of the communication functions is to maintain the {\tt HOW} structure,
send commands to the robot, and perform limit checking. How this is done
is basically up to the functions themselves. 
Each of the first four functions
takes a pointer argument
to a robot descriptor {\tt rbt} (type {\tt RCI\_RBT}), 
which contains pointers to all the robot
parameter structures as well as the communication functions. The {\tt ready}
and {\tt wakeup} functions are called with argument values that are 
stored in the {\tt rbt} structure and are
set by the {\tt startup}
function\footnotemark.
\footnotetext
{This is done to allow these functions to be specified directly as the
trigger or wakeup functions for an RCI task.}

\subsection{RCI I/O driver}\label{RCIIOdev}

The robot communication functions usually perform
data transfers with the robot controller using an RCI {\it I/O driver},
which implements a standard set of communication routines for a
particular type of communication hardware.
This allows the robot interface functions to be independent of the
communication hardware. An RCI I/O driver contains
the following nine routines:

\begin{verbatim}
      read (dev, buf, size)
      write (dev, buf, size)
      readTest (dev)
      writeTest (dev)

      signal (dev, num)
      probe (dev)
      attach (dev)
      detach (dev)

      ioctl (dev, cmd, buf)  
\end{verbatim}

These routines are referred to by pointers in the data type
{\tt IO\_DEVICE}, which is defined in {\filefont h/IOdevice.h}.
Detailed specifications for the routines can be found in the
section on device drivers in the {\it RCI User's Guide}, and also
in the manual page {\tt IOdevice(7)}. A separate 
{\tt IO\_DEVICE} structure is assigned to each physical 
device associated with an RCI I/O driver.

RCI device routines do their I/O by accessing the system bus directly; 
they do not make use of any UNIX system calls. They can't because RCI tasks
execute independently of UNIX. Each RCI task executes at high priority
(possibly with interrupts disabled) and runs to completion. Tasks are normally
executed either periodically or on the occurrence of a specific event
interrupt. This implies that 
RCI device functions must do their work {\it immediately}; the device model
contains no buffering and no interrupt routines. It {\it is} possible to poll
the other end
using the {\tt readTest()} or {\tt writeTest()} routines. One of
these polling routines
can be given to the RCI scheduling monitor to use as a test to see whether or
not an RCI task is ready to run.

Each RCI device is usually given a short alphanumeric name and is
defined in a file called {\filefont drivers/XXXDriver.c}, where {\tt XXX}
denotes the driver name. An include file, defining bit codes 
and structures used by the driver, is usually located
at {\filefont h/XXXDevice.h}. A table of all the devices is contained in the
file {\filefont drivers/IOdriverTable.c}

\subsection{RCI UNIX devices to provide polling interrupts}

RCI tasks are usually run on the occurrence of either an RCI clock tick
or an external interrupt. If the RCI task is running on the UNIX
CPU, then external interrupts must first pass through the UNIX
interrupt mechanism. This involves catching the interrupt within
the handler of a UNIX device driver, which then gives control 
of the CPU to RCI. In terms of communication, the UNIX driver provides no
other function\footnotemark.
\footnotetext
{In fact, it would probably be possible to have RCI patch the system
vector table
directly, so that you wouldn't have to go through the UNIX
interrupt mechanism at all and no UNIX device drivers would be needed. 
We may do this in the future.}

The hardware associated with an RCI I/O driver is usually capable of
providing interrupts to the UNIX CPU. In order to use these
interrupts to wake up the RCI control task, an RCI UNIX driver should be
installed to catch them.
For instance, the XYCOM XVME 240 digital I/O module is commonly used to
communicate between Sun4 host systems and the Unimate robot controller.
The robot controller can wake up the RCI task by sending an interrupt
through the XVME 240; this interrupt is caught by the RCI UNIX driver for 
the XVME 240, which is called {\tt xyd} and which lives in 
{\filefont sys/rciext/xyd.c}.
Once the RCI task is running, the actual data communication is handled using
the {\tt xyd} RCI I/O driver, which is defined in 
{\filefont drivers/xydDriver.c}. 

\begin{quote}
{\bf NOTE}: It is important to understand the difference between the
two types of drivers just discussed. RCI I/O drivers are used by RCI
tasks to read and write data, are defined in the RCCL {\tt drivers}
directory, and are part of the RCCL/RCI library. UNIX RCI devices
are stripped down UNIX device drivers whose main purpose is to
catch external interrupts for waking up RCI control tasks. They
are configured into the running UNIX kernel.
\end{quote}

\subsection{Communication software in the robot controller}

For RCI to be able to communicate with a particular robot controller,
there must be a communication program running in the controller
which can talk to the RCI I/O driver and (one level higher) the 
robot communication functions. 

For Unimate Mark I, II, and III robot controllers, this communication program
is called {\tt moper}, and it is loaded into the Unimate controller where it
replaces the manufacturer supplied VAL software.

\section{Adding a Robot to the System}\label{addrobot.sec}

This section outlines, in some detail, the procedures necessary for
configuring a new robot 
into the RCCL/RCI system. It is assumed that the class of the robot is already
defined, which means the various interface functions described in section
\ref{concepts.sec} already exist.

\subsection{Updating the robot data table}\label{robotdatatab.sec}

The first thing one must do is assign the robot a name.
The robot should then be given an entry in {\tt rciRobotDataTable},
located in {\filefont robots/robotDataTab.c}. 
Each entry in this table contains the following fields:

\begin{list}{}{}

\item[1.]
The robot's name.

\item[2.]
The robot's class, as defined in {\filefont h/robotClass.h}.

\item[3.]
Two class-specific functions, named 
{\tt <class>\_jls} and {\tt <class>\_kyn}, which are
used internally by the system to help 
instantiate the robot's {\tt JLS} and {\tt KYN} structures.
(For details, see {\tt getJls(3)}.)

\item[4.]
The sizes of the two class-specific data types 
{\tt <class>\_KYN} and {\tt <class>\_VAR}, which are defined
in the file {\filefont h/<class>\_kynvar.h}. 

\item[5.]
The {\it startup}, {\it input}, {\it output}, and {\it release}
robot communication functions. These are often specific
to a robot's class, but because they tend to depend as much
on the robot's controller as on the robot itself, it is sometimes
useful to define separate interface functions.
If your robot is only going to be run with the
simulator {\tt robotsim}, or is being controlled by any
Unimation Mark I, II, or III controller,
then you can use the ``generic'' 
communication functions defined in {\filefont robots/gen\_comfxns.c}.

\end{list}

As an example, the {\tt rciRobotDataTable} entry for a PUMA robot attached to
a Unimation Mark X controller typically looks like this:

\begin{verbatim}
      "frank",  PUMA, puma_jls, puma_kyn,
                sizeof(PUMA_KYN), sizeof(PUMA_VAR),
                puma_startup, puma_input, 
                puma_output, puma_release
\end{verbatim}

An entry for a robot of class {\tt STAN} that
uses the generic communication functions
would look like
\begin{verbatim}
      "stan0",  STAN, stan_jls, stan_kyn,
                sizeof(STAN_KYN), sizeof(STAN_VAR),
                gen_startup, gen_input, 
                gen_output, gen_release
\end{verbatim}

After {\tt robotDataTab.c} has been updated, you should
run the command 
\begin{verbatim}
      % make libs
\end{verbatim}
in the {\tt robots} directory. 
This will compile the data table and reinstall it in the
RCCL/RCI library. The robot
will be given an ID number equal to its table index plus 1; this is the
number that is returned by the routine {\tt find\_robot()}.

\subsection{Updating the {\tt robots} file}\label{robotsfile.sec}

A file called {\tt robots}, in the directory {\filefont \$RCCL/conf},
describes the RCI I/O devices and the RCI UNIX devices 
which are used by the robots to communicate with their controllers.
The entry for each robot contains the following fields:
the name of the robot, the name of the RCI I/O driver used to exchange
information with the robot controller, the address of the device
associated with the driver, and the name of an
RCI UNIX device that provides a polling interrupt (needed only if RCI
is being run on the main UNIX CPU). Some optional arguments
may also be included for the RCI I/O driver.

Update this file as follows:

\begin{list}{}{}
\item[1.]
Specify the name of the robot with a field of the form
\begin{verbatim}
      name = <robotName> 
\end{verbatim}
\item[]
{\bf NOTE}: All of the remaining fields can be omitted if the
robot is only to be run in simulation mode.

\item[2.]
Specify the RCI device driver with a field of the form
\begin{verbatim}
      device = <driverName> 
\end{verbatim}
\item[]
{\tolerance=10000
{\tt <driverName>} should be one of the RCI I/O devices specified
in the file {\filefont IOdriverTable.c}. Commonly used devices
include {\tt pri}, which is for DRV11s on MicroVAX systems,
and {\tt xyd}, which is for XYCOM XVME 240s on Sun4 systems.

}
\item[3.]
Specify the device's address with a field of the form
\begin{verbatim}
      address = <number> 
\end{verbatim}
\item[]
The address is an integer that specifies the physical location of the device.
Usually, this will be a bus address. It can be specified in either
octal, decimal, or hex (using the conventional C syntax).

\item[4.]
Specify a UNIX device that provides a polling interrupt which can be used
by any RCI task controlling the robot. The field should be of the 
form
\begin{verbatim}
      interrupt = <UNIXdevice> 
\end{verbatim}
\item[]
This field can sometimes be omitted; it is necessary only when the robot is
controlled by an RCI task running on the main UNIX CPU.

\item[5.]
Specify any arguments needed by the device driver with fields of the form
\begin{verbatim}
      arg<n> = <argvalue> 
\end{verbatim}
\item[]
where {\tt <n>} is in the range 0 to $\hbox{\tt MAX\_DEVARGS}-1$
and {\tt <argvalue>} is an integer (in either decimal, octal, or hex).
These fields are necessary only if the device driver requires additional
argument information (which is {\bf not} the case with the
{\tt pri} or {\tt xyd} drivers). For instance, the driver for a shared memory
board with multiple address spaces might need
extra information: the {\tt address} field might describe the location of 
a control-status register, and additional arguments could give the
base addresses of the actual shared memory regions.
Argument values appear in
the {\tt args} field of the per-device {\tt dev} structure
(see {\tt IOdevice(7)}). They are set to {\tt UNDEF} if not defined
in the {\tt robots} file.
\end{list}

As an example, consider the following {\tt robots} file entry
for the robot ``frank'':

\begin{verbatim}
      robot=frank device=xyd address=0x9000
                  interrupt=/dev/xydRCI0
\end{verbatim}

This indicates that {\tt frank} is interfaced to its robot
controller using the driver {\tt xyd} for a device
located at {\tt 0x9000}, and a polling interrupt delivered by the
RCI UNIX device {\tt /dev/xydRCI0}.

As indicated above, only the robot name needs to be indicated if
the robot is to run only in simulation. In that case, the entry
\begin{verbatim}
      robot=frank
\end{verbatim}
would do quite nicely.

\begin{quote}
{\bf IMPORTANT:} For robots run on VxWorks systems, the
file {\tt conf/robots.vxw} is used instead of {\tt conf/robots}.
Also, some additional information fields are required to
specify interrupt information for the I/O device. See the
manual {\it RCCL/RCI on VxWorks}.
\end{quote}

More information on the {\tt robots} file can be found in the manual
pages.

\subsection{Creating a {\tt .jls} file}\label{jlsfile.sec}

The {\tt .jls} file for a robot, which lives in 
{\filefont conf/<robotName>.jls}, describes the information used
to build the robot's {\tt JLS} structure. 

On most versions of RCI, the ascii {\tt .jls} file is first compiled
into a binary file (which takes the prefix {\tt .JLS}), before being read by
application software. 
This compilation is done automatically using the program
{\tt makejls} whenever the {\tt .jls} file is seen to have 
been updated. The binary {\tt .JLS} file is {\bf not} used 
for VxWorks systems, because binary data may not be
compatible between the VxWorks host and target systems.
Use of the binary {\tt .JLS} file may be phased out altogether
in later RCCL/RCI releases.

Basically, the {\tt .jls} file contains information describing
a robot at the ``joint level'': the number of joints, the gear ratios,
joint range and velocity limits, etc. It also contains the information
necessary for {\it calibrating} the robot.

Detailed information 
on each particular field can be found in {\tt JLS(3)} and
{\tt makejls(3)}. General information on the format of the
file can be found in {\tt makejls(3)}.
The amount of information can be daunting, but
it should be understood that some fields are not 
always used, and so the corresponding information can be
set to zero.

A template {\tt .jls} file is contained in
{\filefont conf/template.jls}.

\subsubsection{Making a {\tt .jls} file for a PUMA robot}\label{jlspuma.sec}

Creating a {\tt .jls} file for a PUMA robot is fairly
easy because one can basically clone an existing file.

Assume that your new robot is named ``frank''. Then
go to the {\tt conf} directory and create the file {\tt frank.jls}
by copying either {\filefont puma260.jls}, {\filefont puma560.jls}, 
or {\filefont puma760.jls}, depending on whether {\tt frank} is a PUMA 260,
560, or 760.

At this point, {\tt frank.jls} should be {\it roughly} correct,
but the calibration information will be wrong. RCCL/RCI applications should
run, but the angles may be off by a few degrees. Current
control may be a bit off as well; this is used by programs
such as {\tt free}, {\tt zerograv}, and the 
{\it free joint} mode of {\tt teachdemo}.

To calibrate the {\tt .jls} file properly, you need to pay attention
to the following fields. Some fields may not apply to your system;
in that case, you can either leave the values alone, or set them
to zero.

\begin{desclist}

\item[\tt encCalvec]
These values are used by the robot calibration routine and should be measured
using the program {\tt primecal} 
(see section \ref{primecal}).

\item[\tt encHome]
This field is used only if your robot is a PUMA 260, in which case
it should contain the encoder values for the nest
position (only PUMA 260s have nests). Once the arm has been
initially calibrated (using {\tt primecal}, for instance), you
should put it into the nest, read back the encoder values, and then
enter them into this field. You can put the robot into the nest using
a program such as {\tt free} or {\tt zerograv}.
The contents of the field are used by the 
program {\tt pumacal} when calibrating the robot from the nest.

\item[{\tt potSlope}, {\tt potIntercept}]
For robots which have potentiometers (i.e., the PUMA 560 and 760), the
contents of these fields should be set to the values measured by the
program {\tt potcal}, which
should be run soon after the robot is first calibrated
using {\tt primecal} (see section \ref{potcal}).

\item[\tt mtorqueToCurrent, currentBias]
The values in these fields describe
the conversion used to turn a specified
actuator torque into an output DAC value. The values given in 
the generic files {\tt puma260.jls}, 
{\tt puma560.jls}, and {\tt puma760.jls}
are roughly correct for each robot, but
you may need to ``tune'' the values to get current controlled programs 
like {\tt zerograv} to work properly. 
See section \ref{curcalib.sec} for information on how to adjust these
these values ``by eye''.
Most supplied RCCL/RCI programs
do {\it not} use current control, so you may not want to worry about
this for now.

\item[\tt currentToMtorque]
This field needs to be set only if your system is instrumented
to measure motor currents or torques. This is usually done by
having the {\tt moper} software in the robot controller measure the
joint actuator torques using an analog-to-digital converter.
(For information on setting up the hardware to do this, see the
{\it RCCL/RCI Hardware Installation Notes}). The contents of this
field are used by RCI to convert the ADC values returned
by {\tt moper} into motor torques.
See section \ref{curcalib.sec} for information on how to determine these
values.

\item[\tt forGearRatios, encWheelSize]
The default information supplied in {\filefont puma260.jls},
{\filefont puma560.jls}, and {\filefont puma760.jls} is almost
always correct for these fields.
(A detailed description of what they represent is given in
section \ref{genjls.sec}.)
In pathological cases, however, the information may be wrong for one or more
joints. The symptoms of this
are that the corresponding joints don't seem to
move by the amount requested; for example, a motion request of 90 degrees
may in fact produce a motion of around 80 degrees. 
In these cases the proper values need to be obtained, either
from the manufacturer, or by measuring them using some ad-hoc
method. The program {\tt primecal} can be useful here, because
it allows joint motions to be specified in either angle {\it or} encoder
coordinates.

\end{desclist}

Finally, you may wish to set or change some of the maximum or 
nominal operating values described in section \ref{jlslim.sec}.

\subsubsection{Making a {\tt .jls} file for a simulated-only robot}
\label{jlssim.sec}

Robots of the class {\tt STAN} and {\tt SCARA} are currently supported
in simulator mode. To create a {\tt .jls} file for one of these,
you can simply copy one of the generic files {\tt scara.jls}
or {\tt stan.jls}.

If you are making a {\tt .jls} file from scratch,
and the robot will run {\it only} in simulation, then
much of the information
can often be faked if necessary:

\begin{desclist}

\item[\tt encCalvec, encHome, potSlope, potIntercept]
There is usually no need to worry about setting these fields
because simulated robots start up in a known position and are
therefore already ``calibrated''.

\item[\tt mtorqueToCurrent, currentBias, currentToMtorque]
These fields can usually be set to some reasonable ``fake''
values because (a) the simulator program may not do anything
interesting with current control commands, and (b) even if
it does, it will probably use the information in these
fields to do its own internal computations, thereby ensuring
that everything is consistent. Setting the values of
{\tt mtorqueToCurrent} to 1000.0 for large joints and
4000.0 for small joints usually works. {\tt currentBias}
values are set to 0, and the {\tt currentToMtorque} values
can be set to the inverse of the {\tt mtorqueToCurrent} values.

\item[\tt forGearRatios, encWheelSize, encOffset]
These fields describe the relationship between joint
and encoder coordinates (for more information, see
section \ref{genjls.sec}).
On a purely simulated robot one can often
fake these values,
providing the simulator program itself is using the {\tt JLS}
structure to obtain the same information. 
Setting the {\tt encWheelSize} values to 1000
and the {\tt forGearRatios} to 50.0 for rotary joints,
or .05 for prismatic joints, is often reasonable.
The number of gear couplings is usually set to zero.
About the only real constraint 
is to keep the joint values within the 
encoder range.
This means that for each joint, the
product of its {\tt encWheelSize} value, {\tt forGearRatios}
value, and range (in revolutions for a rotary joint or
millimeters for a prismatic joint) should not exceed
$2^N$, where $N$ is the number of encoder bits.
The {\tt encOffset} field should also be specified so that the
joint range midpoint is close to the encoder range midpoint
$2^{N-1}$. 

\end{desclist}

\subsubsection{Making a {\tt .jls} file for a general robot}\label{genjls.sec}

For any robot, the easiest way to create a {\tt .jls} file
is to clone an existing {\tt .jls} file for a robot of the same class.

If you are creating a {\tt .jls} file for a robot
from scratch, then you may have to pay more attention to the
fields at the top of the file, which define the number of
joints and their type, the number and locations of joint to actuator
couplings, the gear ratios, and the encoder wheel sizes. 
A good knowledge of the robot's mechanics is necessary
in order to set these fields correctly.

The {\tt forGearRatios}, {\tt encWheelSize}, and {\tt encOffset}
entries in the file describe the relationship between
joint and encoder coordinates.
(In some cases, the interface from RCI to the robot controller
may be based entirely on joint coordinates, and encoder values
may not play a role. In this case, these fields can be faked,
as described in section \ref{jlssim.sec}.)

The {\tt forGearRatios} field describes the (mostly
diagonal) coefficients of the gear ratio matrix that
maps joint coordinates to motor shaft coordinates
(e.g., joint revolutions to motor revolutions).
Let this matrix be called ${\bf G}$. 
{\tt encWheelSize} describes the number of encoder counts per motor
revolution. Let these form the coefficients of a diagonal
matrix ${\bf W}$. The relationship between joint coordinates
(given by a vector ${\bf j}$) and encoder coordinates (given by
a vector ${\bf e}$) can then be expressed as
\[
{\bf e} \;=\; {\bf W} \; {\bf G} \; {\bf j} + {\bf e}_0
\]
where ${\bf e}_0$ is an offset vector whose values are
determined by the entries in the {\tt encOffset} field. 
Each entry in this field consists of an encoder value,
followed by its corresponding joint value. 
This specifies one complete set of encoder values
${\bf e}'$ and corresponding joint values ${\bf j}'$.
${\bf e}_0$ is then computed from
\[
{\bf e}_0 \;=\; {\bf e}' - {\bf W} \; {\bf G} \; {\bf j}'
\]
${\bf e}'$ and ${\bf j}'$ are usually chosen so as to place
the joint range midpoint near the encoder range midpoint
(which is 32768 for a 16 bit encoder; note the encoder values
are always positive). This helps ensure
that all the joint values will remain within the range
of the encoders if the 
gear ratios or wheel size information is changed.

Sometimes, the robot controller interface may not support
position calibration. Calibration in these cases is
usually done locally by the robot controller without
any RCI involvement. In such situations, the calibration
information supplied by the 
{\tt encCalvec}, {\tt encHome}, {\tt potSlope}, and
{\tt potIntercept} fields can be left unspecified.

It is also necessary to furnish a {\it park} position and a
{\it best} position for the robot (in the fields {\tt parkAngles}
and {\tt bestAngles}, respectively). The park position
describes a default location for the robot to move to when it is
idle; this location may be used occasionally by RCCL/RCI software.
The ``best'' position is some location where the manipulator Jacobian
is well conditioned; this location is also referenced occasionally
by RCCL/RCI software. The park and best positions are frequently
defined to be the same.

\subsubsection{Setting limit values in the {\tt .jls} file}\label{jlslim.sec}

Several of the fields in the robot's {\tt JLS} structure
are used to specify various limit values. Other fields
are used to indicate the nominal operating values. These fields
can be tuned as necessary for a particular robot, and the values
can be referred to by application software.

\begin{desclist}

\item[{\tt jmin}, {\tt jmax}]
The maximum joint ranges (in degrees or millimeters). These are
used by the low-level RCI checking options {\tt CHK\_REQPOS}
and {\tt CHK\_MAXPOS}; see {\tt SET\_CHECKING(3)}.

\item[{\tt maxVel}, {\tt maxAcc}, {\tt maxJerk}]
These fields indicate the maximum allowed values on 
velocity, acceleration, and jerk for each joint.
{\tt maxVel} is used by the low-level RCI checking options
{\tt CHK\_REQVEL}
and {\tt CHK\_MAXVEL}; see {\tt SET\_CHECKING(3)}.
At the time of this writing, no supplied RCCL/RCI software makes use of the 
{\tt maxAcc} or {\tt maxJerk} fields (acceleration information is taken
from the {\tt nominalAcc} field; see below).

\item[{\tt maxMtorque}, {\tt maxJtorque}]
These fields indicate the
maximum allowed torques that may be applied to each joint at the
motor shaft and joint levels, respectively (i.e., before and after the gear
train).
{\tt maxMtorque} is
used by the low-level RCI checking options {\tt CHK\_REQTOR}
and {\tt CHK\_MAXTOR} (the latter only if current or torque
feedback is implemented); see {\tt SET\_CHECKING(3)}.
No supplied RCCL/RCI software makes use of the {\tt maxJtorque} field at the
time of this writing.

\item[{\tt nominalVel}, {\tt nominalAcc}, {\tt nominalJerk}]
These fields represent nominal ``desired'' values for the velocity,
acceleration, and jerk of the robot joints. Modifying the contents of these
fields can cause those programs which refer to them to change behaviour.
For instance, lowering the values
in {\tt nominalVel} will cause programs which obtain their velocity
setpoints from this field to move the robot more slowly.
The {\tt nominalVel} and {\tt nominalAcc} fields are
used by the RCCL and CHASE trajectory generators to determine
reasonable trajectory profiles.
No supplied software uses the {\tt nominalJerk} field at the
time of this writing.
\end{desclist}

\subsection{Creating a {\tt .kyn} file}\label{kynfile.sec}

The {\tt .kyn} file for a robot, which lives in 
{\filefont conf/<robotName>.kyn}, describes the information used
to build the robot's {\tt KYN} structure. 

As currently implemented, the {\tt .kyn} file contains
information pertaining to the kinematic and dynamic aspects
of the robot.
In principle, the contents of the {\tt .kyn} file depend on
the robot's class (since part of the {\tt KYN} structure
itself is class-specific).

For the {\tt PUMA}, {\tt STAN}, and {\tt ELBOW} classes,
this file contains (1) the ``A'' matrix parameters, (2)
the gravity loading coefficients, and (3) a rough friction model. 
Only those ``A'' matrix parameters
which are relevant to a particular class are specified; this is
also true of the gravity coefficients.
In the next release of RCCL/RCI (most likely),
joint inertia information will be included as well.

\subsubsection{Making a {\tt .kyn} file for a PUMA robot}\label{kynpuma.sec}

Creating a {\tt .kyn} file for a PUMA robot mostly involves
copying a file.

Assume that your new robot is named ``frank''. Then
go to the {\tt conf} directory and create the file {\tt frank.kyn}
by copying either {\filefont puma260.kyn}, {\filefont puma560.kyn}, 
or {\filefont puma760.kyn}, depending on whether {\tt frank} is a PUMA 260,
560, or 760.

Occasionally, the ``A'' matrix parameters in the file
are ``out'' by a few millimeters. This occurs because of
minor variations in different versions of PUMA robots.
If you happen to know a-priori the exact ``A'' matrix parameters
for your robot, then you should replace the default values in
the {\tt .kyn} file. Note also that there are two 
versions of the PUMA 760: the 761 and the 762. The parameters
in {\filefont puma760.kyn} are actually for a PUMA 762. The PUMA 761
has a longer forearm.

With regard to the gravity loading and friction information,
see section \ref{gravfric.sec}.

\subsubsection{Making a {\tt .kyn} file for a general robot}

As with the PUMA robot, the easiest way to create a {\tt .kyn}
file for a particular robot is to clone an existing
{\tt .kyn} file for a robot of the same class. It may
be necessary to change ``A'' matrix parameter values.

Generic {\tt .kyn} files for the Stanford and ``elbow'' manipulators
(classes {\tt STAN} and {\tt ELBOW}) are contained in the files
{\tt stan.kyn} and {\tt elbow.kyn}.

\subsubsection{Gravity loading and friction information}\label{gravfric.sec}

Within {\tt .kyn} files for the presently implemented robot classes, 
gravity loading terms are described by parameters of the
form {\tt CP<XX>}, where {\tt <XX>} indicates
joint and index numbers. Static, Coulomb, and viscous
friction terms are described by parameters of the form
{\tt STATF<n>}, {\tt COULF<n>}, and {\tt VISCF<n>}, where {\tt <n>}
is the associated joint number.

It is sometimes not possible to determine the gravity
loading and friction terms for a robot. In this case,
one can either use approximate values (often taken by copying the
information for an identical robot), or set the values to zero.
Static and Coulomb friction terms can often be set equal.
Do not worry too much about the gravity or friction information,
since very little of the supplied RCCL/RCI software actually uses it.
See section \ref{curcalib.sec}.

Unfortunately, no supplied software presently exists for auto-calibrating the 
gravity loading and friction terms.

\subsection{Creating a {\tt .pos} file}\label{posfile.sec}

The {\tt .pos} file for a robot, which lives in 
{\filefont conf/<robotName>.pos}, gives a list of named
positions in joints coordinates. These positions are referenced
by the routine {\tt getRobotPosition(3)}. The only position
which is routinely referenced by application software is
``{\tt rcclpark}'', which is the starting point for some
RCCL demo programs.

A {\tt .pos} file for a new PUMA can be created by copying
either {\tt puma260.pos}, {\tt puma560.pos}, or {\tt puma760.pos},
as appropriate.

\section{Other Configuration Files}

Other files contained in the directory {\filefont \$RCCL/conf} that you may
want to have a look at include:

\begin{desclist}
\item[\tt defaultRobot]
Contains the name returned by the routine {\tt getDefaultRobot()}. This is
used by some utility programs in case no robot name is specified in the
argument list. It is particularly useful on systems that have only one robot. 

\item[\tt .rcc]
The control file for the {\tt rcc} command (q.v.), containing the names
of all the libraries and include directories which are automatically
referenced by {\tt rcc}. It should not usually be necessary to change this
file, but it is good to know that it exists. The file can be overridden by
{\tt .rcc} files contained in the user's home directory or the current
directory. Its format is described in the manual page for {\tt rcc}.

\end{desclist}

\section{Configuring {\tt moper} for a Unimation Mark X Controller}

The name {\tt moper} identifies the communication software which is loaded
into a Unimation controller, where it replaces VAL and serves as a
communication interface between the robot joint servos
and RCI on the host computer. Code for the {\tt moper}
software is located in the directory {\filefont
\$RCCL/lsi11}. 

\begin{quote}
{\bf NOTE}: {\tt moper} will run on Unimation Mark I, II, and III
controllers. It will {\bf not} run on the newer Unival controller.
\end{quote}

\subsection{Creating a {\tt moper} for a new robot}\label{newmoper.sec}

This is definitely the most difficult aspect of configuring an
RCCL/RCI system, because RCI depends on the low level
joint servo interface inside the Unimation controller, and
some aspects of this interface tend to vary from controller to controller. 

The actual joint servo command interface is fairly consistent.
What varies is the joint servo control code, and the associated
control parameters. Normally, when VAL starts up on a particular
controller, it loads some control parameters into the joint
servos. Unfortunately, exiting VAL has the effect
(on Mark II and Mark III controllers) of resetting
the joint servos, and thereby clearing the loaded parameter 
values. Consequently, it is necessary for {\tt moper} to load the
servo parameters itself, and this requires knowing what they are
and where they are located. The servo parameters may
change depending on the version of the joint servo control
software.

In the instructions immediately below, the parameters are guessed
for a particular controller/robot combination, based
on commonly occurring values. This frequently works.
The alternative is
to determine the parameters exactly by methods
discussed in section \ref{jservos.sec}.

\subsubsection{Necessary system information}

Before creating the {\tt moper}, you need to know

\begin{enumerate}

\item
What sort of PUMA you have (i.e., 260, 560, or 760). This should
be clear.

\item
What sort of controller you have.
Mark III controllers are set in large
upright cabinets. Mark II controllers come in a silver box, with a
small row of switches along the top-front edge. Mark I controllers
come in a silver box without a row switches along the top. 

\item
What type of CPU you have. This will be either an
LSI11/03 (on Mark I controllers), an LSI11/23 (on early Mark II controllers),
or an LSI11/73 (on later Mark II, and all Mark III, controllers). If your
CPU is {\it not} an LSI11/73, you may want to consider upgrading;
see the {\it RCCL/RCI Hardware Installation Notes} for details.

\end{enumerate}

\subsubsection{Creating the {\tt moper} config file}

The {\tt moper} executable for a particular robot takes the same name as that
robot. All mopers are compiled from the same set of source files, except for
a robot-specific config file, {\tt <robotName>.c},
that contains routines and tables
specific to the robot in question. 

\begin{list}{}{}

\item[1.]
{\it Copy a template file} --
Go to the directory {\filefont \$RCCL/lsi11}, and create the
file {\tt <robotName>.c} by copying either {\tt puma260.c}, 
{\tt puma560.c}, or {\tt puma760.c}, as appropriate. For example,
if your robot's name is ``frank'', and it is a PUMA 560, then you would do
\begin{verbatim}
      % cp puma560.c frank.c
\end{verbatim}
\item[2.]
{\it Edit the Imakefile} --
Next, create an entry in the {\tt Imakefile} which will build
the moper program. Entries take the form
\begin{verbatim}
      pdp11Program(<robotName>, $(MOPER) <robotName>.s <hostIO>.s)
\end{verbatim}
\item[]
where {\tt <hostIO>} is the name of the driver which will interface
to the RCI I/O driver; unless you wish to specify your own driver
(as in section \ref{moperdriver.sec}), this will almost always be {\tt drv11}.
The entry for the robot {\tt frank} would look like
\begin{verbatim}
      pdp11Program(frank, $(MOPER) frank.s drv11.s)
\end{verbatim}

\item[3.]
{\it Do a test compilation} --
After you have edited the {\tt Imakefile}, rebuild the {\tt Makefile}
by running the command
\begin{verbatim}
      % rmkmf
\end{verbatim}
\item[]
and then build the {\tt moper} program by running
\begin{verbatim}
      % make <robotName>
\end{verbatim}
\item[]
You now have a {\tt moper} program named {\tt <robotName>}, although
it is probably {\bf not} ready to run; you still need to
configure the program as described in the next couple of sections.

\end{list}

\subsubsection{Adjusting the config file}

Now you should make some adjustments to the file
{\tt <robotName>.c}.

Before proceeding, take note that the three standard config files
come pre-configured as follows:
\centerline{\tablebox{\halign{%
#\hfil&\qquad\hfil#\hfil&\qquad\hfil#\hfil&\qquad\hfil#\hfil\cr
robot name&robot type&controller&cpu\cr
\noalign{\medskip\hrule\medskip}
{\tt puma260.c}&PUMA 260&Mark 1&LSI-11/73\cr
{\tt puma560.c}&PUMA 560&Mark 2&LSI-11/73\cr
{\tt puma760.c}&PUMA 760&Mark 3&LSI-11/73\cr
}}}

\begin{list}{}{}

\item[1.]
{\it Set the CPU} --
If you are {\bf not} using an LSI11/73, the include
file {\tt lsi11\_73.h} should be changed to 
either {\tt lsi11\_23.h} or {\tt lsi11\_03.h}, depending
on which CPU you have.

\item[2.]
{\it Set the ``hostIO'' address} --
This is the address and vector of the Q-bus interface device
which connects the controller to the RCI system. As indicated
above, this is almost always a DRV11. The address and vector
are specified as arguments to the routine {\tt hostDevice()}.
These arguments should be set to whatever values have been
set on the interface board. For details on setting the interface
board, see the {\it RCCL/RCI Hardware Installation Notes}.

\item[3.]
{\it Set the controller parameters} --
This is the tricky part. Basically, there is no really {\it good} way
to determine what these parameters are, since there are so many
versions of the joint servo code in the various controllers.
So an educated guess must be made based on the type of
controller and robot you have. 

\item[]
Below the comment ``{\tt parameter defs:}'', include
one of the pre-defined parameter definition files which takes
the form
\begin{verbatim}
      <controller>.<robotType>.c
\end{verbatim}
\item[]
{\tt <robotType>} should be either {\tt 260}, {\tt 560}, or
{\tt 760}, as appropriate. {\tt <controller>} should be {\tt mk1\_std}
for Mark I controllers or {\tt mk2\_std} for Mark II controllers.
For Mark III controllers, use {\tt mk3\_760} if you have a 
PUMA 760, or {\tt mk3\_std} otherwise.
For example, if you
have a PUMA 560 on a Mark II controller, you would specify
\begin{verbatim}
      #include "mk2_std.560.c"
\end{verbatim}
\item[]
{\bf NOTE: if these control values are incorrect
for your robot, it may track poorly, vibrate, or 
possibly jump. Be careful the first few times you start the robot
up. Also, there could be difficulties when changing
the control sample rate; change the sample rate and see what happens.
If you have problems, refer to section \ref{jservos.sec}.}

\item[4.]
Rebuild the new moper program.

\end{list}

Your {\tt moper} program should now be ready to load into
the Unimate controller using the {\tt down} command.

Start by making sure that the controller's console line
has been connected to a serial line unit on the
host system (see the {\it RCCL/RCI Hardware Installation Notes}
for information about this). 
Power on the controller and put its CPU into ODT as
described in section \ref{down.sec}. 
If the {\tt moper} executable 
is called {\tt RobotX}, and the console line
is connected to {\tt /dev/RobotX}, {\tt moper} can be
loaded using the command
\begin{verbatim}
      % down RobotX -e 10000 -a 10000 -d /dev/RobotX
\end{verbatim}
Notice that we have omitted the {\tt -t} option described in
section \ref{down.sec}, so that {\tt down} will go into direct
communication with the controller console after the load
is finished. This will allow us to see whatever messages are
printed by {\tt moper} after it is loaded. (To get out of 
{\tt down} at this point, type a tilde ({\tt \~{}}) character.)

If all goes well, then you should get a message similar to
\begin{verbatim}
      moper started

      listening
\end{verbatim}
If the teach pendant is connected, it should beep once or twice
to indicate that {\tt moper} is communicating with it as well.
The {\tt moper} program is now waiting for an RCCL/RCI program
to connect to it.

If things do not go well, one possibility is that
{\tt moper} will crash
with a ``panic'' message and put the CPU into ODT. This
almost always indicates that some Q-bus device specified
in the {\tt moper} config file does not exist. Test the 
specified device addresses (using ODT). In particular,
test the address specified by {\tt hostDevice()}.
You can test a device
address in ODT by entering it, in octal, followed by
a slash ({\tt /}). 
If there is nothing at that address, ODT will
print a {\tt ?}; otherwise, it will print the word contents
of the address.
On the LSI11/73 CPU, I/O addresses always have 22 bits, so
you need to add another couple of ``sevens'' to the leading
digits. For example, to test the address {\tt 0177560}, you
would enter
\begin{verbatim}
      17777560/
\end{verbatim}

Another thing that may happen is that you get an error message
about ``joint servo timeout'' or ``error initializing memory''.
This indicates that the joint servo control
parameters may be incorrect, and you should see section \ref{jservos.sec}

\subsection{General description of the {\tt moper} config file}

The file {\tt moper} config file {\tt <robotName>.c} contains a number
of parameters and switches which can be used to control
various aspects of {\tt moper}'s operation. It also contains
definitions and routines which manage the various sensor I/O
features available in {\tt moper}.

Most of these parameters should have the correct default settings
so that the robot will run. However, you may need to make changes
to configure certain types of sensor I/O into your {\tt moper}.

\subsubsection{Basic operating parameters}

The variable {\tt robotType} is set to the appropriate robot type as 
defined in {\tt armtypes.h}. The variables {\tt robotID} and {\tt moperID}
are not presently used for anything in particular, so you don't
need to worry about them.

The variable {\tt potsAvail} is set to 1 if the robot has
calibrating potentiometers (which is true for the PUMA 560 and 760 robots),
and 0 otherwise.

The variable {\tt pendantAvail} should be set to 
1 if the controller has a teach pendant, and 0 otherwise.

{\tt rbtComDelay} is a delay count used when the LSI-11 is
talking to the joint micro interface. Increase this value
if you find that {\tt moper} is getting timeouts while talking to the joint
servos.  
This may happen if a CPU upgrade was performed and the new, faster CPU 
runs quicker than the interface can handle. The value required 
will probably be in the range 1 to 5. A delay value
of 5 was needed in a PUMA 560 Mark II controller when an LSI-11/23 
was upgraded to an LSI-11/73.

{\tt rbtTimeout} is a spin-timeout count used by {\tt moper} when talking to
the joint servo interface. This should not be less than 400.

The next four variables control the automatic arm power-on software, and need
to be set properly if you have wired up your controller to allow arm power
to be turned on automatically
(see the description of this in the {\it RCCL/RCI Hardware Installation
Notes}). 
{\tt powerChan} identifies which of the controller's two standard 16-bit
output ports is being
used to provide the power-on bit.
{\tt powerBit} is a mask
identifying the bit within the port. {\tt powerNegative} should be
set ``true'' if the power-on action is active low; i.e., turning the
power on is achieved by clearing the bit. {\tt powerPulse} is used
if the power-on bit is to be pulsed instead of simply set; if {\tt powerPulse}
is set to a non-zero value, then the power-on bit will be asserted 
only for the length of time it takes the CPU to count to this value.

{\tt traceBit} is a mask which specifies a bit
to be set high whenever the {\tt moper} control functions
are active; this can be used for tracing on an oscilloscope. 
The output port used is the same one specified by {\tt powerChan}.
If you don't want
a tracing bit, then set {\tt traceBit} to 0.

{\tt intStretch} is
a parameter that can be used to stretch the position sample rate
expected by the joint processors. Normally, you set the value of this
variable to 1 (which means non-stretched).
Giving it a value of X will tell the joint micros
to interpolate the position commands sent to them over an interval that is
X times longer than the interval at which commands are really being sent. This
may make the robot move more smoothly at the expense of
a little bit of lag.

The parameter definition file (included after the
comment {\tt parameter defs:} contains a few variables that
describe the controller's clock:
{\tt varClkRate} should be set to 1 if the controller on-board clock needs
to be set up by software (which is true for the Mark II and Mark III
controllers), and 0 otherwise.
If {\tt varClkRate} is ``true'', then {\tt varClockParam} describes
a magic parameter
that is used to set up the clock\footnotemark.
\footnotetext
{You should be able to use the supplied parameter value.
The controller clock is usually generated by circuitry on the joint micro
interface board. Changing the clock rate involves sending a magic command to
the joint micro interface; this magic number is part of that magic command.}
{\tt baseClkRate} should be set to the base interval of the system clock, 
which is described in units of .1 msec.
Generally, you set this to 28 (i.e., 2.8 msec.) if
{\tt varClkRate} is ``true'', and 70 (7 msec.) otherwise.
{\tt jntClockRate} is the sample interval
of the control code running in the joint micro controllers, 
also in units of .1 milliseconds. From what we have seen, this should be set
to 18 (1.8 msec.) for the PUMA 760, and 9 (.9 msec) otherwise.

\subsubsection{Sensor I/O parameters and routines}

The remainder of the config file defines the sensor I/O
devices that are available for {\tt moper} (and are hence available
to the RCI interface; see {\tt HOW(3)}).

The first set of variables indicates specific
I/O features that are present. If any of these are
set ``true'', then make sure that the feature is
actually implemented by the corresponding
interface routines at the end of the file.

{\tt jstickAvail} should be set to 1 if the controller has a
joystick interface. {\tt
forceAvail} should be set to 1 if the controller 
is connected to a force/torque sensor. {\tt torqueAvail} should be
set to 1 if the
controller has implemented some way of reading back joint torques or currents
(see the description for this in the {\it RCCL/RCI Hardware Installation
Notes}).
{\tt numADC} is the number of general purpose analog-to-digital
converter channels that are connected to the controller. Most controllers
don't have any unless you add them explicitly, so this number will probably be
zero. 

The next set of variables describes the addresses of various I/O
interfaces available on the controller.

{\tt pioOutAddr} and {\tt pioInAddr} are tables
giving the addresses of all the 
16-bit parallel input and output ports
which can be used for general I/O. The number of each type available
is compiled automatically into {\tt numPioOut} and {\tt numPioIn} by
sizing the table. Most Unimate controllers come with a single high
density parallel port board that has 32 bits of input and
32 bits of output; this is the configuration supplied by default.
Note that the parallel port {\it board} may be present even if you don't have
any of the I/O relay modules.
{\tt DACAddr} is a similar table listing the available digital-to-analog
converter ports. Most systems don't usually come with any of these.

\begin{quote}
{\bf NOTE:} With any of these tables, if there are no entries, then the
table definition must be commented out and an 
explicitly null entry must be put in its place;
this is because the compiler can't size objects of zero size.
\end{quote}

The table {\tt serialDevs} describes all the serial line units connected
to the controller, {\tt except} for the console line and any line
which you provide your own interrupt handler for. 
The entry for each port gives its base address and
vector. The ports are assumed to look like those on a standard
DEC DLV, with a receive CSR, receive data buffer, transmit CSR,
and a transmit data buffer. 
Units which are included in
this table will be assigned interrupt service routines and an interface
control block by the {\tt moper} micro-kernel. Serial lines which do not 
need to make use of the micro-kernel interface should not be included in this
table. Usually the only thing you need to ask yourself with regard to this
table is whether your controller has a second serial board (many do). If so,
then you should uncomment the entries for it in the second half of the table.

RCI itself contains a general serial line interface as part of the
{\tt HOW} structure and CHG macros. {\tt moper} implements these general
interfaces using serial lines connected to the micro-kernel serial
line interface. These are configured using the table {\tt sluDesc}.
The entries consist of the channel number (a zero-based
array index into the table {\tt serialDevs}, described above), and the number
of bytes that should be allocated as buffers for storing read and write data.
The only time you will probably need to make changes here is if you take over
one of these serial line units for something else (such as a force torque
sensor).

The remainder of the file contains routines which implement various
sensor and I/O interfaces. The implementation of these interfaces will vary
from site to site depending on the hardware used. The functionality of each
interface 
as expected by the rest of {\tt moper} is fairly simple, however, and can be
explained here.

The force/torque sensor interface contains the following routines:

\begin{desclist}
\item[{\tt initForce()} --]
An initialization routine that is called once when {\tt moper} is first
started up.

\item[{\tt startForce()} --]
Called in response to an RCI command to start reading force values.

\item[{\tt stopForce()} --]
Called in response to an RCI command to stop reading force values.

\item[{\tt getForce(buf)} --]
Called once per control cycle, while force reading is turned on, to 
collect the force values. These are placed in an array of six
{\tt short}s whose address is passed in as a parameter. The order of the 
data expected is the usual x-y-z forces followed
by the x-y-z torques. The routine should return 1 if successful and
0 if the force readings are not available for some reason.
\end{desclist}

The interface routines used by {\tt moper} for the joystick interface are
analogous to the force sensor ones:

\begin{desclist}
\item[{\tt initJstick()} --]
An initialization routine that is called once when {\tt moper} is first
started up.

\item[{\tt startJstick()} --]
Called in response to an RCI command to start reading joystick values.

\item[{\tt stopJstick()} --]
Called in response to an RCI command to stop reading joystick values.

\item[{\tt getJstick(buf)} --]
Called once per control cycle, while joystick reading is turned on, to 
collect the values. These are placed in an array of
{\tt short}s whose address is passed in as a parameter. 
The routine should return 1 if successful and
0 if the joystick readings are not available for some reason.
\end{desclist}

The analog-to-digital conerter interface consists of a single
routine:
\begin{desclist}
\item[{\tt getAdc(chan,valuep)} --]
Called once per control cycle, while ADC input is activated
for the channel {\tt chan}. Reads the corresponding
ADC channel and places the result into the address given by {\tt valuep}.
\end{desclist}

The routines for the torque sensor interface are analogous to the
force sensor and joystick routines:

\begin{desclist}
\item[{\tt initTorque()} --]
An initialization routine that is called once when {\tt moper} is first
started up.

\item[{\tt startTorque()} --]
Called in response to an RCI command to start reading torque values.

\item[{\tt stopTorque()} --]
Called in response to an RCI command to stop reading torque values.

\item[{\tt getTorque(buf)} --]
Called once per control cycle, while torque reading is turned on, to 
collect the values. These are placed in an array of
{\tt short}s whose address is passed in as a parameter. 
The routine should return 1 if successful and
0 if the torque readings are not available for some reason.
\end{desclist}

The torque values returned by {\tt getTorque()} are not assumed to
be real torque values (they might be current readings for instance).
RCI will convert the values to real motor torques (Newton-meters)
using the conversion constants {\tt currentToMtorque} contained in the
JLS structure.

\subsubsection{Adding torque and force sensing}

By default, {\tt moper} provides
force sensor routines (as described in the previous section)
which can read data from a Lord F/T series force torque sensor 
(made by Lord Corporation).

The {\it RCCL/RCI Hardware Notes} has a section describing
how to hook this sensor up and configure {\tt moper} accordingly.
There is also a section which describes how to install
sensors for reading joint currents, which can be used
to provide an estimate of joint torques.

\subsection{Determining servo control parameters}\label{jservos.sec}

In some cases, the joint servo parameters specified for a 
particular controller/robot combination may turn out to 
be incorrect for your controller.

One thing you might do, before applying the methods described in
this section, is try a different parameter set. In particular,
if you have a PUMA 560, and the {\tt mk3\_std.560} seems to cause
problems, try {\tt mk2\_std.560} instead. If you have a Mark I controller,
try changing {\tt mk1\_std} to {\tt mk1\_old}.

\subsubsection{Disassembly of the joint servo EPROMs}

The first way to resolve this problem is to dump the
contents of the joint servo EPROMs, disassemble the code,
and see where the parameters actually are. The EPROMs
are identical for all the joint servos, so you only need
to dump one.

This is in fact not as difficult as it sounds, since the
code is no more than 2K bytes in length. Furthermore, actual
variations in the code structure tend to be rather
slight. It is, however, a tedious exercise if one has not done
it before. Therefore, we recommend that if you decide to do
this, you mail the EPROM dump to the author and we will
do the disassembly for you.

To dump the EPROMs, select one of the six joint servo
cards in the robot controller (which one doesn't matter;
they are all identical) and remove it. The card should
contain a Rockwell 6503 microprocessor, a 6532 RAM I/O timer
chip, a digital-to-analog converter chip, and an EPROM. The
EPROM will most likely be 4 Kbyte 2716, or equivalent. 
Dump the EPROM using a PROM developer, and create an
ascii hex dump of its contents. Although the EPROM
is 4 Kbytes, the top and bottom 2 Kbytes should be identical
(you might want to check this). E-mail the dump to
\begin{verbatim}
      lloyd@curly.mcrcim.mcgill.edu
\end{verbatim}

If you are interested in doing the disassembly yourself,
the disassembler is located in {\filefont \$RCCL/servoCode}.
Compile the programs {\tt disas} and {\tt reroll}. Take the
ascii hex dump, strip off any addresses at the beginning
of the line, and make sure it is in a 
single byte format
(like one of the {\tt .hex} files in the directory).
Then run it through the command
\begin{verbatim}
      % disas -1 0x800 < input | reroll > output
\end{verbatim}
A 6502 reference manual will be useful for interpreting
the result (the 6503 is a 6502 in a different package).
Numerous disassembled listings are available in the
{\tt servoCode} directory for comparison.

\subsubsection{Creating your own EPROMs}

An alternative approach is to create
your own EPROMs using a version of the joint servo code
that is already known. We have not actually tried this
technique, but it {\it ought} to work. The only caveat is
that VAL will probably not run with the new EPROMs.

First, select a suitable version of the joint
servo code. Check the directory {\filefont \$RCCL/servoCode}
for files ending in {\tt .hex}; these are ascii hex dumps
of different EPROMs. Pick the file that most closely matches the
controller, as indicated by the following table:

\centerline{\tablebox{\halign{%
#\hfil&\qquad#\hfil&\qquad\hfil#\hfil&\qquad\hfil#\hfil\cr
file name&robot controller type\cr
\noalign{\medskip\hrule\medskip}
{\tt mk1\_std.hex}&Mark I\cr
{\tt mk2\_std.hex}&Mark II\cr
{\tt mk3\_std.hex}&Mark III, with PUMA 260 or 560\cr
{\tt mk3\_760.hex}&Mark III, with PUMA 760\cr
}}}

Second, burn a new set of EPROMs. They are identical for
each joint servo, and you will need six.
The EPROM type is a 4 Kbyte 2716 (or equivalent).
Each {\tt .hex} file describes the top 2 Kbytes of the EPROM;
the bottom 2 Kbytes should be a duplicate of the top.
When the EPROMs are ready, use them to replace the existing
ones in each of the six digital joint servo boards
inside the robot controller.

Third, set the include file
that follows the comment ``{\tt parameter defs:}'' in 
the {\tt moper} config file to one appropriate for the EPROM
which you have chosen. The name of the include file
has the form
\begin{verbatim}
      <controller>.<robotType>.c
\end{verbatim}
{\tt <robotType>} should be the same as the root name of
the {\tt .hex} file that was chosen for the EPROMs. 
{\tt <robotType>} should be either {\tt 260}, {\tt 560}, or
{\tt 760}, as appropriate. For example, if you
have a PUMA 760 and a Mark III controller, you would
specify
\begin{verbatim}
      #include "mk3_760.760.c"
\end{verbatim}

\section{Testing the Robot Connection}\label{testing.sec}

Once you have configured RCI for a particular
robot, you should test its operation. 

The references to {\tt moper} in this section are specific to PUMA
robots running on Unimation controllers.

First, go to the directory {\tt \$RCCL/rci} and build the
program {\tt rbtcom}. Then run the command
\begin{verbatim}
      % rbtcom <robotName>
\end{verbatim}
This should initiate a connection to the robot, and start
a control session that does nothing except exchange data.
The robot power will {\it not} be turned on. {\tt rbtcom} is
interactive, driven by the {\it C-tree matcher}, and when working properly
should display the prompt {\tt RBTCOM>}. A description of the commands
is  beyond the scope of this document. However, the command
\begin{verbatim}
      RBTCOM> show
\end{verbatim}
should print out the number control cycles that have elapsed
since the program started. If you get up to a few thousand, everything
is probably all right. To get out of {\tt rbtcom}, enter
the command 
\begin{verbatim}
      RBTCOM> quit
\end{verbatim}

For PUMA robots, you may want to look at what {\tt moper}
prints out on the controller console line while 
{\tt rbtcom} is running. Connect to the console
line using the {\tt talkRobotX} alias described in section 
\ref{mopertalk.sec}, and watch the output. When {\tt rbtcom}
starts, {\tt moper} should print the message
\begin{verbatim}
      active
\end{verbatim}
When you quit {\tt rbtcom}, the message
\begin{verbatim}
      released
      listening
\end{verbatim}
should appear. The ``{\tt listening}'' part of the message
indicates that {\tt moper} is now waiting for a new RCI connection
from the host system.
If you abort {\tt rbtcom} (such as with an interrupt)
then {\tt moper} should print a message, similar to
\begin{verbatim}
      timeout: location (4,0)
      listening
\end{verbatim}
indicating that it has timed out, and is listening for
another RCI connection.

If {\tt rbtcom} fails, it should generate some error messages
as to what went wrong. Most errors are due to
(1) improper configuration of the robot with respect to RCI, or (2)
a bad interface connection to the controller. 

On PUMA robots, if {\tt moper} fails, it too should
generate some error messages. In most cases, when {\tt moper}
fails, it will simply go back to listening for RCI connections
from the host system. If it fails badly, then it will put the
controller CPU into ODT, which is distinguished by its familiar
{\tt @} prompt. {\tt moper} must then be restarted with the ODT
command
\begin{verbatim}
      10000G
\end{verbatim}
although the condition which caused the failure will probably repeat.
Errors which complain of trouble talking to the
joint servos indicate that the servo parameters defined
for {\tt moper} are incorrect; see section \ref{jservos.sec} in this case.
{\tt moper} itself implements a number of commands; for a list
of these, type {\tt ?} while {\tt moper} is running. 

Once {\tt rbtcom} is running, you can next run the program
{\tt primecal}. This is a ``standard'' program and so you don't have
to build it specially.

\begin{quote}
{\bf WARNING: {\tt primecal} will try to turn the robot power on. When
running it for the first time, or when first trying
to move the joints, be prepared to hit the
emergency switch.}
\end{quote}

Enter the command
\begin{verbatim}
      % primecal <robotName>
\end{verbatim}
When started, the program will either turn the robot arm power on by itself
(if this feature has been wired into the robot controller;
see the {\it RCCL/RCI Hardware Installation Notes}) or
wait for you to do so. 
Once the power is on, {\tt primecal} will enter into an
interactive loop, driven by the {\it C-tree matcher}, with the
prompt {\tt PRIMECAL>}. Commands can then be entered to move
individual joints. Try moving each of the robot's joints
to verify that this works properly.
Note that the robot is not yet calibrated, so you should use only
relative joint motions and visually check for joint limits.
For more information, see {\tt primecal(1)}.

If you detect problems while running {\tt primecal}, such as
rough joint motion or, in the worst case, the joints
just ``take off'', then the servo parameters set by {\tt moper}
are probably wrong and you should see section \ref{jservos.sec}.

Once these test programs work properly, you should be
able to calibrate your robot.

\section{Robot Calibration Programs}\label{calibrobot.sec}

This section describes the calibration programs which you will need to 
run in order to obtain proper values for some of the fields in the 
{\tt JLS} structure. 

The information in this section is focused on PUMA robots.

\subsection{The {\tt primecal} program}\label{primecal}

The program {\tt primecal} should be run on a new robot
to determine its calibration vector. {\tt primecal} was
written for PUMA type robots and other robots which use optical encoders.

The purpose of {\tt primecal} is to determine a set of
reference encoder values which are known to lie on
wheel index locations.
This set of values constitutes the 
{\tt encCalvec} field of the {\tt JLS} structure. 

\subsubsection{How {\tt primecal} works}

To understand what these numbers are used for, consider the robot calibration
problem as it applies to PUMA type robots: a joint has just been powered up,
and the encoder count associated with the joint is gibberish. To determine 
the correct encoder count, we need to determine the exact joint position. 
How do we do this? We start by getting a {\it rough}
estimate of the joint position,
either by knowing approximately where the robot is (in the nest, or at the
park position) or by using a course position indicator such
as the joint potentiometers. 
The PUMA 260 does not have potentiometers and so for that robot we
must use
the former method. 
Now, each optical encoder wheel has a certain
number of marks $w$ on it, plus a single special mark called the ``zero
index''. If the estimate of the joint position is accurate to
within $\pm 1/2 w$, we can use the
zero index location to figure out {\it exactly} where we are. 
We travel until we reach
a zero index (and update our joint position estimate
accordingly). Let our estimated joint position be
given by $\hat e$. Assume next that we know of some
reference position, $r$, which lies on a zero index and whose
encoder position is known exactly. Then, since we
have just arrived at a zero index location ourselves,
the distance between our real position
$e$ and this reference position must be $n w$, where $n$ is some integer.
But since our estimated position $\hat e$ is no more than $\pm 1/2w$ from the
real value $e$, $n$ can be computed from
\[
        n = \hbox{nint}( (\hat e - r)/w),
\]
and the real encoder position can then be computed from $n$:
\[
        e = n w + r
\]
This is the method used by the program {\tt pumacal}. The task of 
{\tt primecal} is to determine the reference values $r$.

\subsubsection{Running {\tt primecal}}

{\tt primecal} is an interactive program and
it contains commands that allow you to move the robot around until it is
at some position which you happen to know exactly. Typically, for PUMA robots,
this is the ``ready'' position, where links 2 and 3 are pointing straight
up.
When you have placed the robot at a known position, enter the command
{\tt primecal}. The program will then
ask for the known joint angles, which it uses to compute the correct encoder
values for the present position. These encoder values are then loaded into the
joint servos explicitly, thus effecting a direct, ``brute-force''
calibration of the robot.
Next, the program will move all the joints until each one of them finds a
zero index. The encoder values at this new zero index position
constitute a reference value such as the one described above.

For historical reasons, the program actually outputs a
different set of reference values, formed by adding a multiple of
$w$ to each of the measured values to make it the smallest number
greater than or equal to 32768\footnotemark.
The resulting set of new $r$ values
constitutes the calibration vector, which is printed out by the program, and
also printed into the file {\tt primecal.out}. These values should be entered
into the {\tt encCalvec} field of the robot's {\tt .jls} file.

\footnotetext
{32768 is special only because it corresponds to the mid-range value for
16 bit encoders. Because of this, it is usually defined to be the mid-range
point for the joint angles as well.} 

More information on {\tt primecal} can be found in the manual pages.

\subsection{The {\tt potcal} program}\label{potcal}

Robots that use potentiometers to estimate their location when
calibrating must have their potentiometers calibrated
to determine, for each joint, the linear relationship 
between the pot reading $p$ and the estimated encoder value $\hat e$:
\[
        \hat e = m p + b
\]
The set of slope values $m$ constitute the {\tt potSlope} field 
and the set of intercept values $b$ constitute the {\tt potIntercept}
field in the {\tt JLS} structure. {\tt potcal} measures both of these
by taking numerous potentiometer readings across the range of each
joint. 

\subsubsection{Running {\tt potcal}}

It is necessary that the robot be calibrated before running {\tt potcal}.
This presents a bit of a chicken-and-egg problem if the robot is normally
calibrated  using the pots. The initial calibration has to be done using
{\tt primecal}. After this has been done, the robot will remain in calibration
until the controller is either turned off or the {\tt moper} program is
halted. {\tt potcal} may be run at any time during this period. If one does
wish to power down the robot in between, then one can move the robot to the
park position before powering down, and then recalibrate later by specifying
the option {\tt -atpark} to {\tt pumacal}.

{\tt potcal}, like {\tt primecal}, is an interactive program. The user can
position the robot so 
that the calibration of the different joints can proceed uninterrupted.
Calibration ``sweeps'' are requested one joint at a time
using the {\tt calibrate} command
(except for the wrist, where all the wrist joints may be calibrated together).
When doing a sweep, the joint is moved from $\theta_m - \theta_s$
to $\theta_m + \theta_s$, where $\theta_m$ is the joint mid-range point
and $\theta_s$ is the interactively specified sweep angle. After the sweep is
done, 
the measured slope and intercept are printed out, both on the screen
and into the file {\tt primecal.out}. These values 
should be entered into the {\tt potSlope} and {\tt potIntercept} fields of the
robot's {\tt .jls} file.

More information on {\tt potcal} can be found in the manual pages.

\subsection{Manually calibrating for current control}\label{curcalib.sec}

This section describes how to adjust the system for proper 
current control, so that the actual torques resulting from
the RCI torque control commands ({\tt SET\_JTORQUE()} and {\tt
SET\_MTORQUE()}) are in fact close to the desired result.

Current control is used by some of the supplied RCCL/RCI software,
mostly to put joints into a ``zero gravity'' mode, where they
move freely but with enough current applied to keep them from falling
under there own weight. This feature is provided in the program
{\tt zerograv}, and in the ``free joint'' mode of the routine
{\tt rcclTeach()} (and its wrapper program, {\tt teachdemo}).
Other programs that presently use current control are
{\tt free} (which frees joints {\it without} gravity compensation),
and the demo programs {\filefont demo.rci/zerogDemo} and 
{\filefont demo.rci/gravity}.

The techniques described here are quite ad-hoc,
because most systems are not instrumented for measuring
joint currents or torques and, consequently, no software
is supplied for doing automatic current calibration\footnotemark .
In the absence of proper sensors, all
we can really do is adjust the necessary values
``by eye'' until programs such as {\tt free} and {\tt zerograv}
appear to work correctly.

\footnotetext
{It is, however, possible to add sensors that read the joint currents (see
the {\it RCCL/RCI Hardware Installation Notes}). These values
can then be used to update the {\tt jtorque} and {\tt mtorque}
fields of the {\tt HOW} structure.} 

The fields in the {\tt JLS} structure that are
concerned with current control are {\tt currentBias} and 
{\tt mtorqueToCurrent}.

\subsubsection{Adjusting the {\tt currentBias} field}

Ideally, all the elements in this field are 0, and in fact
this is true for most PUMA controllers. However,
a few controllers have the problem that a {\it requested} output
current of 0 will not in fact result in an actual output current of 0.
To check this condition on your robot,
run the program {\tt free}, and individually free (i.e., zero the
current) on each of the joints. If some joints do not go
limp, but still appear to have current applied to them,
then the controller has an amplifier balance problem that
can be corrected with entries in the {\tt currentBias} field.

\begin{quote}
{\bf IMPORTANT:} When you limp the robot, remember that some of the joints 
may fall under their own weight. Be sure to hold the joints in question.
To detect residual current, move such a joint to a stable position (such as
straight up or straight down) and see if it either moves or
resists motion differently in different directions.
\end{quote}

If you have an amplifier balance problem, you should try to measure its
magnitude by finding out what commanded torque {\it actually produces}
an output
torque of zero. Go to the directory {\filefont \$RCCL/rci}, and make the
program {\tt rbttest} (the command {\tt make rbttest} should do nicely). Now
run this program with the command
\begin{verbatim}
      % rbttest <robotName> 
\end{verbatim}
This is an interactive program, driven by
the {\it C-tree matcher}, that allows you to enter RCI commands to the
robot one at a time.
There is no ``trajectory generator'' associated
with {\tt rbttest}; only commands which you explicitly type at the keyboard 
will be sent to the robot. 
The program should give you the prompt {\tt RBTTEST> },
and you should then enter the command {\tt start}:
\begin{verbatim}
      RBTTEST> start
\end{verbatim}
This initiates communication with the robot controller.
To put a joint into ``torque'' mode with a 
particular torque setting, enter the command
\begin{verbatim}
      RBTTEST> set mtorque <joint> <torvalue>
\end{verbatim}
where
{\tt <joint>} is the number of the joint you want to control 
(1 through 6, usually), and {\tt <torvalue>} is a floating point number 
giving the magnitude of the torque
you wish to apply to the motor (in Newton-meters). You probably want to
start with a fairly small number, such as .001, and then work up by one or two
orders of magnitude until you see some effect. Remember that this is an
{\it actuator-level} torque.

\begin{quote}
\bf Be very careful when doing this! If you accidentally enter a large number
for the commanded torque, the joint will respond accordingly. Remember also
that since you presumably have a current balance problem to begin with, the
joint will move (or at least feel a bias force) when you specify a commanded
torque of zero.
\end{quote}

It is easier to do this with a partner: one person can 
handle the robot joint(s), and another can handle the keyboard.
You may want to flip a coin for the keyboard.
The idea is to find a commanded torque value that balances the current bias.
For joints where there is no current
balance problem, this value will be zero. When you find the correct
commanded torque value, compute the corresponding DAC value
by multiplying the torque by the value of {\tt mtorqueToCurrent} for the joint
in question. {\tt mtorqueToCurrent} is a field in the {\tt JLS}
structure containing multipliers to convert motor torques into output
DAC values; you can 
find it in the robot's {\tt .jls} file.
This final value should be entered in the {\tt currentBias} field of the 
{\tt .jls} file.

\subsubsection{Adjusting the {\tt mtorqueToCurrent} field}

This section assumes that the {\tt currentBias} is properly set.

\begin{quote}
{\bf IMPORTANT}: Make sure that gravity loading terms are actually
defined for your robot in its {\tt .kyn} file. You need to have
some {\it rough} estimate of these terms to start with. If they are zero,
or if the {\tt mtorqueToCurrent} values in the {\tt JLS} structure
are zero, then {\tt zerograv} will simply cause the robot to fall
under its own weight.
\end{quote}

Run the program {\tt zerograv}, taking care to be
ready to shut off power
or abort the program if the robot suddenly moves. The desired
behaviour of {\tt zerograv} is that the robot stays still,
but can be freely moved into any position with only the friction of
the joints resisting. If this is in fact the case, then no 
further adjustments should be necessary. On the other hand,
if the robot tends to
drift or fall, then the {\tt mtorqueToCurrent} values
and/or the gravity loading terms need adjusting; the former
is discussed here.

To calibrate the {\tt mtorqueToCurrent} field, place the
robot in the vertical (i.e., ``ready'') position. Remove any
heavy end effectors because the gravity model will not know
about these. Now move the individual joints from side to side.
If a joint tends to drift (either down or up) in a manner
independent of which side of the vertical it is on,
then adjust the corresponding {\tt mtorqueToCurrent} value.
The value should be
increased if the joint tends to fall down, and decreased
if the joint tends to fall up. Make the adjustments slowly at first. 
To make each adjustment, edit the  appropriate entry in the
robot's {\tt .jls} file, save the file, and then restart the program.

If you can't seem to get {\tt zerograv} to behave no matter how
you adjust the {\tt mtorqueToCurrent} field, then the gravity
loading terms are probably wrong (see section \ref{gravcal.sec}).

\subsection{Manually calibrating gravity and friction terms}
\label{gravcal.sec}

At present, the supplied RCCL/RCI software only uses
a robot's gravity loading and friction model in the
``zerograv'' software described in \ref{curcalib.sec}, and
peripherally in the robot simulator program {\tt robotsim}.
Friction information is used in the ``zerograv'' software
to compute a restoring force for implementing
soft joint limits.

\subsubsection{Adjusting gravity terms}

Calibrating the gravity terms is tricky since the relationship
between them and the applied output torque is much more complicated.
If you don't have an approximate model to begin with, there
is probably no good way to get this right manually. 

If you run the program {\tt zerograv}, and the robot drifts in a way that
seems to depend specifically on joint position, then the gravity terms
probably need adjusting. You can adjust the gravity terms
the same way you adjust the {\tt mtorqueToCurrent} values:
change the appropriate {\tt CP} values in the {\tt .kyn} file, save the file,
and restart the program. Make the changes slowly at first. 

\subsubsection{Adjusting Coulomb friction terms}

Whereas gravity terms are difficult to determine without
the right software, friction terms are fairly easy to estimate.

Again, the program {\tt zerograv} can be used. Start it up
with the option {\tt -friction}. Note that the program is
interactive, with command completion provided by the
{\it C-tree matcher}.

The command 
\begin{verbatim}
      show
\end{verbatim}
will show each joint's current position, as well as
a Coulomb friction value. The initial value is read in
from the robot's {\tt KYN} structure. 

If you now select some joint $j$, and enter the command
\begin{verbatim}
      frictionComp <j> on
\end{verbatim}
the Coulomb friction information for that joint will be used
to reduce friction when the joint is moving. That is, if you move
the joint in a certain direction, then its Coulomb friction value
will be used to give you a ``boost'' so that the joint moves
more easily. Note that the joint ``sticks'' when you change
directions; this can't be avoided because only the joint's velocity is being
used as feedback.

You can change the Coulomb friction value for a joint using the
command 
\begin{verbatim}
      set frictionComp <j>
\end{verbatim}
Try different values until the friction compensation seems right.
Ideally, this will be when pushing a joint
causes it to move freely and continues to glide gently
throughout its range until it bounces off of its limit stop.
In practice, things may not be so well behaved because friction
is quite irregular and can depend on position.

When you have a set of ``good'' friction values, use them
to instantiate the {\tt COULF} terms in the robot's {\tt .kyn}
file. The {\tt zerograv} program will {\bf not} do this automatically.

Friction compensation for a joint can be turned off using the
command 
\begin{verbatim}
      frictionComp <j> off
\end{verbatim}

\section{Adding a New Device to the System}\label{adddev.sec}

If you want to use a new type of communication device to connect the host
system to the robot controller, and no driver software is supplied for
this device in
the system distribution, then you will need to write the appropriate 
device drivers for it
yourself. For instance, you may want to replace the XVME 240 to DRV11
interface (commonly used between Sun4 hosts and Unimate controllers)
with a shared memory link.

\subsection{The RCI I/O driver}

Creating a new RCI device involves writing a driver for it
and placing it in the directory {\filefont \$RCCL/drivers}.

{\tolerance=10000
Device drivers are usually given a short alphanumeric name and are
defined in a file {\filefont drivers/XXXDriver.c}, where {\tt XXX}
denotes the driver name. An include file, defining bit codes 
and structures used by the driver, is usually located
at {\filefont h/XXXDevice.h}.

}

Each driver must implement the nine routines described in section
\ref{RCIIOdev}. Consult the manual page {\tt IOdevice(7)} for an overview of
what these routines do. The easiest way to actually write the driver is
to clone an existing one. The {\it RCCL/RCI Hardware Installation Notes}
suggests which supplied drivers are likely to resemble
the actual drivers needed for some particular types of hardware.

\begin{quote}
{\bf NOTE}: Drivers used by VxWorks systems require a couple
of other routines to manage device interrupts (to
take the place of the UNIX RCI driver). See the document {\it RCCL/RCI
on VxWorks}.
\end{quote}

\subsubsection{Installing the RCI driver}

After you have written the driver, it must be compiled into the system.
This is done as follows. The name of the driver, along
with pointers to its functions,
must be placed in the array {\tt IOdriverTable} in the file
{\filefont drivers/IOdriverTable.c}. After this has been done, running
the command
\begin{verbatim}
      % make libs
\end{verbatim}
in the {\tt drivers} directory will install the driver
in the RCCL/RCI library.

\subsection{The counterpart driver in {\tt moper}}\label{moperdriver.sec}

Every RCI communication driver needs to interact with
some counterpart software in the robot controller. 
Adding a new RCI driver usually
implies writing a driver for the robot controller as well.

The {\tt moper} software supplied for the Unimate controller contains
a set of interface routines that have the general name {\tt host<func>}.
The RCI driver {\tt read} routine talks to the
{\tt moper} routine {\tt hostWrite()}, the RCI driver {\tt write} routine
talks to the {\tt moper} routine {\tt hostRead()}, etc. These
``{\tt hostIO}''
routines are defined in a module (located in {\filefont \$RCCL/lsi11})
whose name is usually related to the hardware.
Two {\tt hostIO} drivers are supplied with the 
system: {\tt drv11.c}, which interfaces to a DRV11, and {\tt drvj.c}, which
interfaces to a DRV11-J, but is untested.

To install a driver into the {\tt moper} for a particular robot,
edit the {\tt Imakefile} in {\filefont \$RCCL/lsi11} and replace the driver in
the {\tt moper}'s build directive.
Note that
build objects in this {\tt Imakefile} are
specified as {\tt .s} files instead of {\tt .o} files;
this is a quirk of the fact that the loader for the cross-compiler works with
assembly files instead of object files.
If your robot's name is {\tt frank}, then the {\tt Imakefile} build directive
for its {\tt moper} will probably look like
\begin{verbatim}
      pdp11Program(frank,$(MOPER) frank.s drv11.s)
\end{verbatim}
{\tt drv11.s} is the old driver module; this should be
replaced with the new driver. If the new driver lives in
{\tt newdriver.c}, then 
the build directive should then be modified to
\begin{verbatim}
      pdp11Program(frank,$(MOPER) frank.s newdriver.s)
\end{verbatim}
Afterwards, the {\tt Makefile} should be rebuilt from the
{\tt Imakefile} by running the command
{\tt rmkmf}.

\subsection{The RCI UNIX driver}

If you provide your own interface driver, and you are not
running on VxWorks, you will probably also need to
write an RCI UNIX driver to handle any interrupts which the device sends
to the host system.

The RCI UNIX driver is usually very simple, consisting of an {\tt open}
routine, a {\tt close} routine, an {\tt ioctl} routine that provides some
interface functions common to all RCI devices, and an interrupt handler that
catches 
incoming interrupts and hands control over to RCI. The driver does not have to
do anything else; all actual communication is done by the RCI device driver.
The UNIX driver can be most easily written by cloning an existing one, such as
{\filefont rciext/xyd.c}, which is the UNIX driver for the XVME 240,
or the general RCI driver ``template'' 
provided in {\filefont rciext/rci\_template.c}.

This driver will need to be configured into UNIX in the same way as all
other system device drivers (see section \ref{editconfig.sec}).

\subsection{Debugging a driver}

The program {\tt drivertest}, in the {\tt drivers} directory,
is an interactive program designed
to help test drivers by providing an interface where each of the
driver routines can be called individually. It creates an RCI task
and uses this to execute the different routines.
While no specific documentation exists for {\tt drivertest}, 
a rather complete description of the {\tt pri} driver, the {\tt moper}
driver that interfaces with it, and how {\tt drivertest} can be
used to debug both of them, is presented in the
file {\filefont doc/priDriver.doc}.

\chapter{Installation Summaries}\label{summary.sec}

This section provides some sample ``check lists'' for installing
RCCL/RCI with the most commonly used equipment.
 
\section{Real-time Installation for VME-based Hosts with PUMA Robots}

This encompasses VME-based hosts (Sun4, SGI IRIS, or VxWorks)
with connections to PUMA robots controlled by Mark I, II,
or III controllers. Each robot controller is assumed to be connected
to the host system by a DEC DRV11 and a XYCOM XVME 240.

The hardware aspects of the installation are detailed
in the {\it RCCL/RCI Hardware Installation Notes}. For
VxWorks installations, the manual {\it RCCL/RCI on VxWorks} should
also be consulted.

\section{Hardware}

\begin{enumerate}

\item
{\it Equipment needed --}
You need a robot, a controller, and a host system. For each robot controller,
you need a DEC DRV11 and a XYCOM XVME 240. If you want hardware clock
support on the Sun system, you also need a XYCOM XVME 203 or 293.
S-bus based Suns should be attached to a VME card cage using a
PT-SBS915 S-bus to VME adaptor, {\it with} configuration software.

\item
{\it Cable interface --}
Build a cable interface to connect each DRV11 and XVME 240.

\item
{\it Hookup --}
Jumper each XVME 240 appropriately and plug it into the host system
VME bus. Jumper each DRV11 and plug it into the Unimate controller
Q-bus. Connect the two boards via the cable connector. Attach
the console serial line from the robot controller to a serial port
on the host system. If you have an XVME 203 or 293 for the Sun system,
jumper this and plug it into the VME bus.

\item
{\it Controller customization --}
Upgrade the LSI11 to an LSI11-73, if necessary.
Wire up the ``auto power on'' circuit, if you desire this feature.

\end{enumerate}

\section{Software}

\begin{enumerate}

\item
{\it Build RCCL distribution --}
See section \ref{installation.sec}.
Unpack the tape, install GNU {\tt make}, edit the file {\tt conf/site.conf},
and run ``{\tt make World}''. Install the simulator network service.

\item
{\it Install kernel support, if necessary --}
On Sun4 or SGI systems, add kernel support as described in either section
\ref{Sun4kern.sec} or \ref{SGIkern.sec}.
Include the UNIX
{\tt genrci} drivers, the {\tt xyd} driver, and (for Sun4 systems
with a XVME 203 or 293) the {\tt xyclk} driver. Create special files
for the drivers in {\tt /dev}. Verify RCI installation with 
{\tt rciCheck} (section \ref{rciCheck.sec}).

\item
{\it Configure controller serial line connection --}
See the {\it RCCL/RCI Hardware Installation Notes}.
Locate the file in {\tt /dev} that controls the serial device
connected to the robot controller. Verify the connection with
{\tt termlink}. 

\item
{\it Configure RCI for each robot --}
For each robot, give it a name and an entry in
{\tt robots/robotDataTab.c} (section \ref{robotdatatab.sec}) 
and {\tt conf/robots}
(section \ref{robotsfile.sec}). For VxWorks, use {\tt robots.vxw} instead
of {\tt robots}. Create a {\tt .jls}, {\tt .kyn}, and
{\tt .pos} file for each robot 
(sections \ref{jlspuma.sec}, \ref{kynpuma.sec}, and \ref{posfile.sec}).

\item
{\it Configure {\tt moper} for each robot --}
For each robot, create a {\tt moper} for it in the {\tt lsi11}
directory, and adjust its configuration file 
(section \ref{newmoper.sec}). Build the
new {\tt moper} and load it into the robot controller over the
serial line.

\item
{\it Test the robot connections --}
With {\tt moper} running in your controller, run the 
test programs {\tt rbtcom} and {\tt primecal} as described
in section \ref{testing.sec}.

\item
{\it Calibrate the robots --}
Calibrate each robot using {\tt primecal} and {\tt potcal} as
described in sections \ref{primecal} and \ref{potcal}. If you want to
use current control programs such as {\tt zerograv}, then 
do the calibrations described in section \ref{curcalib.sec} and 
\ref{gravcal.sec}
as well.

\end{enumerate}

\section{Installation for Simulator-only Systems}

\begin{enumerate}

\item
{\it Build RCCL distribution --}
See section \ref{installation.sec}.
Unpack tape, install GNU {\tt make}, edit the file {\tt conf/site.conf},
and run ``{\tt make World}''. Install the simulator network service.

\item
{\it Configure RCI for each robot --}
For each robot, give it a name and an entry in
{\tt robots/robotDataTab.c} (section \ref{robotdatatab.sec}) 
and {\tt conf/robots} (section \ref{robotsfile.sec}). 
Create a {\tt .jls}, {\tt .kyn}, and {\tt .pos} file for each robot 
(sections \ref{jlsfile.sec}, \ref{kynfile.sec}, and \ref{posfile.sec}). 

\item
{\it Test the robot connections --}
Start the simulator program {\tt robotsim} with the name
of the robot you want to simulate. Try to ``move'' this
robot using the command {\tt move} with the {\tt -sim}
option.

\end{enumerate}

\chapter{Adding New Classes of Robots to the System}\label{newrobots}

If you wish to add a new {\it class} of robot to the system, then you will
need to write implementations of the functions described in section
\ref{concepts.sec}.

The basic procedure for adding a new robot class looks something like this:

\medskip
\begin{list}{}{}
\item[1.]
Define a class for the robot in the file {\filefont h/robotClass.h}.

\item[2.]
Define the {\tt <CLASS>\_KYN} and {\tt <CLASS>\_VAR} structures for the 
robot type, and place these definitions in a file {\filefont
h/<class>\_kynvar.h}. 

\item[3.]
Create a new directory for the robot class, which bears the same name as
that class. Functions specific to the class will be placed in this
directory. The easiest way to create this new directory may be to clone
one for an existing robot class. The directory for functions
specific to the PUMA class of robots is called {\tt PUMA}.

\item[4.]
Write the functions {\tt <class>\_jls()} and {\tt <class>\_kyn()}
used for instantiating {\tt JLS} and {\tt KYN} structures.
(See section \ref{waccess.sec} for details.)

\item[5.]
Write class-specific implementations of the 
conversion functions described in section \ref{jlsfunc.sec}.
(See section \ref{wjlsfunc.sec} for details.)

\item[6.]
Write class-specific implementations of the kinematic functions
described in section \ref{kynfunc.sec}.
(See section \ref{wkynfunc.sec} for details.)

\item[7.]
(If necessary) Write the robot communication functions,
described in section \ref{rbtcomfunc.sec}, which
provide the interface to the robot controller.
(See section \ref{wrbtfunc.sec} for details.)

\item[8.]
(If necessary) Add interface device software to be used by the
the robot communication functions in communicating with the
robot controller. This could include an RCI I/O driver, and/or
an RCI UNIX device as described in section \ref{adddev.sec}.

\item[9.]
(If necessary) Create the necessary interface software
on the robot controller (this is a {\tt moper} equivalent). 
(See section \ref{wmoper.sec} for details.)

\end{list}

Some of these steps are now discussed in more detail.

\section{Writing {\tt JLS} and {\tt KYN} Access Functions}\label{waccess.sec}

The functions {\tt <class>\_jls()} and {\tt <class>\_kyn()} are
used by the system functions {\tt getJls()} and
{\tt getKyn()} to help instantiate the {\tt JLS} and
{\tt KYN} structures. {\tt <class>\_jls()} sets the {\tt JLS}
structure pointers for the functions described in section 
\ref{jlsfunc.sec}. {\tt <class>\_kyn()} sets the {\tt KYN} structure 
pointers for the functions described in section \ref{kynfunc.sec},
and also reads in data from the robot's {\tt .kyn} file.

Instructions on how to write these functions, the arguments they
should expect, and how they are loaded into the system are
given in the ``Installation'' section of the manual page {\tt getJls(3)}.

The functions for the PUMA robot live in {\filefont puma/puma\_jls.c}
and {\filefont puma/puma\_kynvar.c}.

\section{Writing the {\tt JLS} Conversion Routines}\label{wjlsfunc.sec}

These are implementation functions for the
routines described in \ref{jlsfunc.sec}.

All of the parameters needed to perform these computations are defined by data
fields in the {\tt JLS} structure itself, and generic functions, which will
work for any robot, are defined in the file {\filefont robots/gen\_convert.c}.
It is possible to simply use these functions instead of providing private ones
for the robot class.
However, it is usually better, for speed reasons, to write class-specific
functions. This permits loops to be unrolled and joint coupling
computations to be optimized. The class-specific functions are given
the same names as the generic functions, only prefixed with
the name of the class (in lower case) and an underscore ({\tt <class>\_}).

The functions for the PUMA robot live in {\filefont puma/puma\_convert.c}.

\section{Writing the Kinematic Routines}\label{wkynfunc.sec}

These are implementation functions for the
routines described in \ref{kynfunc.sec}.
They take the same arguments as the generic routines.
Information on each one is given in the {\it RCI Reference Manual}.

The implementation function takes the same name as the generic routine,
except the first letter is
capitalized and then the name of the robot class (in lower case)
is prefixed onto the front. For example,
the {\tt fwdJacob} routine for the PUMA is called {\tt pumaFwdJacob()}.

The functions for the PUMA robot are located in
{\filefont pumaKinematic.c}, 
{\filefont pumaJacobian.c}, {\filefont pumaConfig.c}, and {\filefont
pumaGravload.c}, in the {\filefont puma} directory.

Within the {\filefont puma} directory there are some programs which test the
kinematic routines. It may be useful to create versions of these
for any new robot classes which are defined. Each testing
program automatically cycles through a large set of joint angles and applies
various combinations of forward and inverse routines, checking that the
numbers which go in are close to the numbers that come out. Test
angles are chosen to be far from, near, or at singularities.
For testing the routines at or near singularities, the programs make use of
some support routines defined in the file 
{\filefont pumaSingular.c}, which detect when a robot is near a singularity,
or explicitly set the robot to be a certain distance from a singularity.
Documentation for these routines is contained at the top of the file.

\section{Writing the Robot Communication Functions}\label{wrbtfunc.sec}

These are the routines described in \ref{rbtcomfunc.sec}.

Information on what these functions do is provided in
the manual page {\tt robotComfxns(7)}. 
They generally take the names 
\begin{verbatim}
      <pfx>_startup
      <pfx>_input
      <pfx>_output
      <pfx>_release
      <pfx>_ready
      <pfx>_wakeup
\end{verbatim}
where {\tt <pfx>} is some distinguishing prefix. If the
functions are defined for a particular class of
robots, the prefix is the class name.
The functions for the PUMA robot are located in
{\filefont puma/puma\_comfxns.c}.

It may not be necessary to define these functions
for a particular class of robots. 
Their implementation tends to depend much more on the
robot controller, and how it interfaces to RCI, than on
anything to do with the robot's class. 
Conversely, different robots of the same class
may use different sets of communication functions,
depending on what controller they are attached to.

\begin{quote}
{\bf NOTE}:
There is a set of ``generic'' communication functions,
named with the prefix {\tt gen} and 
defined in {\filefont robots/gen\_comfxns.c}. These
will work for any robot which is either controlled by a Unimation Mark I, II,
or III controller, or run in simulation mode with the program {\tt robotsim}.
\end{quote}

The communication functions used by a particular robot 
are declared in {\tt rciRobotDataTable} (see section
\ref{robotdatatab.sec}). 

\section{Interface Software in the Target Controller}\label{wmoper.sec}

When adding a new type of robot to the RCCL/RCI system, it will probably 
be necessary to write {\tt moper} equivalent software that runs on the robot
controller and interacts with the robot
communication functions running on the
host system. To this end, it may be convenient to clone the PUMA version of
{\tt moper}, or parts of it. To help in doing this,
a brief overview of the ``moper'' software is given here.

{\tt moper} is really just a data concentrator. It wakes up once every control
cycle (upon a signal from either the host system or its own timer, depending
on whether it is running in ``slave'' or ``master'' mode), and
gathers data from the robot joints and the various sensor devices 
that are attached to it. It collects this data into one packet, ships
it up to the host, and then waits for the host to reply with a packet of
commands. The commands are then distributed, as required,
to the joints and the I/O devices, ending the control cycle.
It is useful to use {\tt moper} to do this communication because 
many of the interfaces (particularly those involving serial lines)
are interrupt driven, and it may not be particularly convenient to do large
amounts of interrupt driven I/O on the RCI host system. This is
particularly true if the host system consists of only the UNIX CPU.

A description of the principal modules comprising {\tt moper} is given in
the file {\filefont lsi11/README}.

Moper makes use of a minimal number of system services provided
by a ``microkernel'' that was written for the LSI-11. These services
are mainly connect-to-interrupt, timer services, and support
for {\tt printf()} and {\tt scanf()}. Porting
moper to a different system would largely be an exercise in replacing these
services with system calls on the target system. The microkernel
interface is defined in the file {\filefont doc/microkernel.doc}.
The modules related to the microkernel are also described in
{\filefont lsi11/README}.

\end{document}
