Installation Instructions

RWRCCL/RCI Startup and Installation Guide
Matthew Stein
January 2004
Roger Williams University
School of Engineering, Computing and Construction Management
Bristol, RI 02809
Based on the original documentation of John Lloyd 1992. McGill University.

This document describes the set up procedures for RWRCCL/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.
Copyright 2004 by Matthew R. Stein.
Permission to use, copy, modify, and distribute this document, and the RWRCCL/RCI software, is granted for non-commercial and research purposes only, and providing that (1) no fee is charged except the minimum necessary to cover copying and shipping expenses, and (2) all copyright notices are preserved and the authors are fully acknowledged. All other rights are reserved. The commercial sale of RWRCCL/RCI, its supporting documentation, or a system which contains RWRCCL/RCI as a component, is prohibited unless permission is obtained from the authors.

1. Introduction

Section 2 of this document describes what an RWRCCL/RCI user should do in order to compile and run application programs. Sections 3 and 4 explain how to compile the software and what is required to install the necessary kernel support. Section 5 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 6. Section 7 describes how to create a new class of robot for the system.

1.1 Documentation Conventions

1.1.1 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 RCCL), or within the system kernel tree (whose root directory is usually /sys). For brevity, when describing path names, the root directory portion will sometimes be omitted. For example, conf/site.conf refers to $RCCL/conf/site.conf.

1.1.2 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 someManPage(3) will frequently be used. This means look for the manual page with the title someManPage. The number in parentheses indicates the manual page 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 RCCL Reference Manual or the RCI Reference Manual.

2. Getting Started

The first thing an RWRCCL/RCI user must do is set up an environment. This is best done by making a few entries in the user's .cshrc file or the /etc/profile file on linux machines

2.1 Environment Variables and the Path
The following environment variables should be set:

RCCL This environment variable should be set to the root directory of the RCCL system.

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

2.1.1 Sample .cshrc entries

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

setenv RCCL ~/rccl.new
setenv MANPATH $RCCL/man:/usr/man
set path=(. $RCCL/bin /bin /usr/bin ... )

2.2 Program Compilation

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

2.2.1 Using non-ansi compilers

The Linux installation assumes you are using the gcc supplied with the Linux operating system. Use of other compilers is at your own risk.

2.2.2 The rcc command

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

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 4.1.2).

2. Automatically references the RCCL/RCI libraries and the math library.

3. Automatically names its output after the first module in the command line (instead of a.out).

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 CTRL in the command line. If compiled separately, these modules must also be compiled by the rcc command with the usual -c option (again, placed in the command line to the right of the CTRL keyword). Modules whose code and data will not be accessed at all by the control level can be compiled separately using cc. There is no restriction per se against referencing control level code or data from the planning level.

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

The default compilation command used by rcc is specified by the entry to the right of the keyword cc in the file 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 .rcc file in your home directory (rcc will check for a file there), to avoid disturbing the system configuration.
More information on rcc can be found in the RCCL manual pages.

2.2.3 rcc examples

Suppose the user wishes to compile the program test, which consists of the planning level module test.c and the control module testCtrl.c. This program can be compiled as follows:

% rcc test.c CTRL testCtrl.c

Alternatively, the compilation may be done separately, as in:

% rcc -c test.c
% rcc -c CTRL testCtrl.c
% rcc test.o CTRL testCtrl.o

Also, test.c could have been compiled using gcc directly.

Suppose there is a library support.a that contains modules to be used by the control level. Then this library must also be placed to the right of the CTRL keyword:
% rcc test2.o CTRL test2Ctrl.o support.a
All the usual C options are available. For example, a regular program foo that does not set up any RCI control tasks can be compiled with the optimizer, according to:
% rcc foo.c -O

2.3 Turning on the Robot

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

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, or better still become the local guru yourself, so you don't need a document at all :-).

2.3.1 Loading the moper program into the kernel

For Real-Time linux the moper modules must be loaded into the kernel prior to execution using the privileged insmod command. These modules resides in kernel space suspended until a write on a real-time FIFO activates them. As a consequence, there is no real performance penalty for having the modules loaded at boot time. Here are examples entries in my /etc/rc.d/rc.local file.
This file is the accepted location under Linux for the addition of local commands to be executed at boot time.

# more rc.local
#!/bin/sh
#
# /etc/rc.d/rc.local: Local system initialization script.
#
# Put any local setup commands in here:
/pkg/rwrccl/bin/insrci
/pkg/rwrccl/bin/inssim
#

The insrci and inssim files are small shell scripts that call insmod. For reference, here is the contents of insrci on my system.

# insrci
#!/bin/sh
insmod /usr/src/rtlinux3.1/modules/rtl.o
insmod /usr/src/rtlinux3.1/modules/rtl_time.o
insmod /usr/src/rtlinux3.1/modules/mbuff.o
if [ -f /usr/src/rtlinux3.1/modules/rtl_posixio.o ]; then
insmod /usr/src/rtlinux3.1/modules/rtl_posixio.o
fi
insmod /usr/src/rtlinux3.1/modules/rtl_fifo.o
insmod /usr/src/rtlinux3.1/modules/rtl_sched.o
if [ -f /usr/src/rtlinux3.1/modules/psc.o ]; then
insmod /usr/src/rtlinux3.1/modules/psc.o
fi
insmod /pkg/rwrccl/bin/pumaInterface.o
insmod /pkg/rwrccl/bin/moperx.o
exit 0

#!/bin/sh
#inssim
insmod $RCCL/bin/simdevice.o > /dev/null
Now the absolute path locations of the RTLinux modules are configured in the site.conf file, and are just included here as an example. The insrci file is generated during the Make World process, so there is no need to hand-configure this file based on this example.

2.3.2 Calibrating the robot

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

PUMA robots are generally calibrated by running the RCI utility program pumacal. The basic form of this command is

% pumacal [<robotName>]

where, if <robotName> is not given, a default name is read from the file conf/defaultRobot. A PUMA 260 robot usually needs to be in the nest when it is calibrated. Alternatively, you can calibrate from the park position if you give pumacal the option -atpark:

% pumacal -atpark [<robotName>]

If you do use the -atpark option to calibrate a PUMA 260, make sure it actually 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 move:

% move [<robotName>] to park

The actual definition of the park position, in terms of joint values, is contained in the file 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.

2.3.3 Summary of the controller startup procedure

1. Turn on the robot controller(s).

2. Load the moper software into the kernel.

3. Calibrate the robot using pumacal.

2.3.2 Manual Calibration

For reasons not entirely clear to us, we have not been able to read the A/D converter values representing the potentiometers. At RWU were were able to work around this problem easily enough, so we did not pursue this problem indefinitely. Our not so perfect solution is to hand calibrate the robot whenever power is turned on. We do this by manually releasing the brakes using the break release toggle on the top of the controller and the break release button on the base of the Puma 560. It is much easier when two people are available, but in a pinch this can be done alone. Using the break release we manually move the robot into the ready position using the structure of the robot as a reference. In the park position Joint 1 is aligned with the motor, Joint 2 is straight up, the right side of joint 3 (when viewed from the joint 3 side of joint 2) is flush with the side of joint 2. Joint 4 is flush with the end of joint 3, joint 5 is straight up and joint 6 is aligned with a mark on joint 5.

Once manually placed in the ready position we invoke the pumaInttest program in the RTLinux directory and zero the encoders using the "Z" command. Then, exit pumaInttest and run primecal with the angles "0 -90 90 0 0 0" as the current robot position. Primecal moves the robot slightly (searching for index) then exits, setting the robot's calibration bit.

2.3.4 When you need to reload or recalibrate

Generally, you need to load moper and calibrate the arm only when you power up the controller. The TRC004 registers will hold the encoder values as long as the chassis power is on, independent of the arm power. So it has often been the case that it is necessary to calibrate only once in several months.

It is occasionally possible that moper or the Linux PC will crash, although this is extremely unlikely unless you are configuring new moper software. If moper does crash, it is possible to simply reboot the machine without recalibrating.

2.4 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.

2.4.1 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.

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.

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.
The teach pendants that work with RCI are the large heavy orange ones and the small black boxy ones.

2.6 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 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 robotsim with the name of the robot(s) you want to emulate, and then leave it running in the background:

% robotsim <robotName>

This is analogous to turning on a robot controller. An RCI program running in simulator mode connects to 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.

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 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 RCCL User's Guide. To see how to run RCI programs in simulation mode, consult the RCI User's Guide. Detailed information on robotsim and its features can be found in the manual pages.

2.7 The .rciparams File

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 rciParameters(3)).
A few parameter set names are reserved by the system:

* 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 RCCL_params(5).

* RCISYS is the name of a set of parameters that defines some basic RCI system parameters. For details, see RCISYS_params(5).

* sysprogs is the name of a parameter set which is used by RCI utility programs such as pumacal, move, and free. For details, see sysprogs_params(5).

An RCCL/RCI program will look for a .rciparams file in three places: the directory $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 .rciparams file.

3. RCCL/RCI Installation

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

1. Attach the required hardware to your system.

2. Installing the necessary kernel support.

3. Building the main software tree. This involves unpacking the tar, setting up some configuration files, and running make. Instructions for this are given in this section.

There is no particular order to these steps.

3.1 Setting up Your Environment

You should set up an RCCL/RCI UNIX environment as described in section 2.1.

3.3 Editing the Configuration File

Before running make on your system, you should edit the configuration file 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 site.conf are used by the C preprocessor, which is invoked by the utility program imake (described below). What the available options are and what they do are described by comments in the supplied version site.conf. We do not describe the options here because they are likely to change quickly with time.
Different versions of site.conf, written for various systems, are available in the conf directory under the general name <SysType>.conf.

3.3.1 The imake utility

RCCL/RCI builds its Makefiles automatically using the utility program imake, which was developed by Todd Brunhoff and Jim Fulton for the MIT X Windows Consortium a long time ago. imake creates a Makefile from a source file named 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 Imakefile may contain preprocessor compilation directives and macros. This is particularly useful for generating Makefiles whose targets and/or actions depend on the configuration parameters of the system.
imake is now standard in Linux distributions, or at least I presume so as I did not have to install it when I loaded Slackware 8.1 onto my machine. But if you Linux distribution does not include
imake, you must install the appropriate package.

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

Most RCCL/RCI directories will contain an Imakefile in addition to a Makefile. The Makefiles are created automatically by the system when it is first built. If you wish to recreate a Makefile within a particular directory, then the best way to do this is to use the command rmkmf, which is a script that lives in $RCCL/bin. Running

% rmkmf

will attempt to turn any Imakefile (or imakefile) that lives in the current directory into a Makefile, using the configuration files in $RCCL/conf. Alternatively, you can give rmkmf (1) the name of the root directory in which to seek the conf directory, and (2) the name of the directory in which to look for the Imakefile and build the Makefile:

% rmkmf <rootDirectory> <currentDirectory>

For example, the command

% rmkmf $RCCL .

should have the same effect as running rmkmf with no arguments.

If you already have imake as part of an X-windows distribution, this should cause no conflict, although you should be careful to specify $RCCL/conf as the directory in which to locate the include files (rmkmf will do this automatically).
More information on imake can be found in the manual pages.

3.4 Building the System

Once the configuration file site.conf has been prepared properly, you can go to the RCCL root directory ($RCCL) and run the command

% make World

The system Makefile will use imake to rebuild itself and all the subordinate Makefiles. It will then clean the directories, build all the libraries and utility programs, and install the manual pages. (Original text: make World will take about four hours or so on an unloaded MicroVAX-II, and about one hour on an unloaded Sun4.) My, how times have changed. make World takes about 15 minutes on my 600Mhz system.

3.4.1 Commands defined in the main system Makefile
The system Makefile contains the following commands which may be of some use:
* make clean removes all executable, object, and garbage files from the source tree.

* make depend builds the include file dependencies for all of the Makefiles. These are kept in a separate file, called DependFile, which co-exists alongside the Makefile and is included by it.

* make libs builds all of the system libraries, except for those defined in locallib and libCtree.

* make bins builds all of the utility programs, expect for those defined in localbin. It does not build the demo programs.

* make manpages once created the online manual pages, but now doesn't.

3.5 Installing the Simulator Service

In order to be able to run the simulator program robotsim, it is necessary to define a TCP/IP service port for it in the /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 RCISimMux, and the port number which we usually assign is 5347. The corresponding entry in the file looks like this:

RCISimMux 5347/tcp # RCI simulator service

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 /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.

For the Linux installation, the simulator installation requires the steps above plus one additional step. The simulator itself is a simple unix-based program and required no modification. However, programs connecting to the simulator use RCI for trajectory control and timing. This function is replaced by the RTLinux process that also controls the joint-level servo. The simulation module (simdevice.o) is a RTlinux module that generates psuedo-real time interrupts as previously done by RCI but does not control the joint servos, as we would neither need nor want to be controlling the real robot while running the simulator. The module simdevice.o must be loaded into the kernel for the simulator to work. This module will be automatically loaded at boot time as described in section 2.3.1.

4. Adding Real-time Support to the System Kernel

4.1 Introduction
A significant departure from the original RCCL/RCI installation is that special configuration of the kernel for RCI is no longer required. We are once again impressed that Vince Hayward and John Lloyd worked through these issues themselves for the purpose of making their own robots work. They modified the standard unix kernel so that they could run specific processes in near-real time (by giving themselves top priority on the scheduling queue).

Since their work in the early 1990's, this effort has been frequently duplicated, and as a result one may download open source kernel modifications that perform the same function. For this installation we chose RTLinux, one of several real-time packages available at the time. After verifying that RTLinux worked and was adequate for our needs, we continued with this package and did not evaluate any other packages. We therefore have little to say about the relative value of RTLinux vs. other packages but can say unequivocally that this package has worked perfectly for us.

4.2 RTLinux Installation
Adding real-time support for the kernel therefore requires following the instructions included in the RTLinux distribution. A few notes based on our experiences are perhaps worthwhile

- The RTLinux version must match your kernel version, as described in the README file included below. This may limit your kernel choices and it is possible it may be necessary to install an older kernel than that currently executing.
- There is an equivalent "xconfig" for RTLinux that allows specification of some RTLinux options. We selected "Enable Floating Point" on this menu but we were still unable to perform many floating point operations in the real-time kernel module.
- We performed the installation while using Slackware 8.1 as our linux system In fact, the choice of Slackware (v.s. RedHat, Mandrake, etc.) was made because the RTLinux site indicated it was developed in Slackware, as we wanted to limit potential incompatibility problems.

Included below are the README and RELEASENOTES files from our RTLinux distribution for reference. These indicate potential sources of the package.
README
This version of Open RTLinux is considered stable. It supports both Linux 2.2.x
and Linux 2.4.x kernel series. Please see the RELEASENOTE file to find out
what's new in this version.
RTLinux is a hard real-time extension to Linux.
More information can be found at http://www.rtlinux.org/
and http://www.fsmlabs.com/
The installation instructions are in doc/html/Installation/Installation.html
file. The doc/html/GettingStarted document contains a brief introduction to
RTLinux as well as sources of help and a quick API reference.
If you are upgrading from previous versions of RTL, please read the
file UPGRADING.
Please send bug reports in to support@fsmlabs.com
Finite State Machine Labs Inc. (FSMLabs) created and maintains
RTLinux.
RELEASENOTES
RTLinux/Open 3.1 is now available from: ftp://ftp.rtlinux.com/pub/rtlinux/v3/
New in 3.1
* Both v2.4.4 and v2.2.19 kernels are supported
* RTLinux modules are compiled correctly when module versioning is enabled
* POSIX support fixes and enhancements
* RT-threads can be created from other RT-threads with preallocated memory
* Compatibility mode fixes (rt_get_time and others)
* CLOCK_GPOS is a new POSIX clock that converges to the Linux system clock
* The interrupt focus feature is also supported with 2.2.x kernels
* CLOCK_REALTIME is now the same as CLOCK_RTL_SCHED
* The new rtl_posixio RTF_SETSIZE ioctl can be used to change the fifo size
Note on POSIX clocks. There are 3 clocks available to the RTLinux programs:
- CLOCK_MONOTONIC. This essentially a scaled CPU cycle counter. It expresses
time passed since system bootup. The main use
- CLOCK_REALTIME. This is the clock used for thread scheduling. sem_timedwait,
nanosleep, pthread_make_periodic_np and others use time values relative to
this clock. In oneshot (default) mode, time shown by this clock is the same
as that of CLOCK_MONOTONIC. In periodic mode, CLOCK_REALTIME becomes local
to the CPU.
- CLOCK_GPOS. This clock always converges to the Linux system clock and thus
is subject to ntpd adjustments etc.

5. Configuring the RWRCCL/RCI Software

This section discusses configuring an RWRCCL/RCI system. Much of this section is unchanged from the original RCCL installation, as it was the goal to retain the higher-level functions of RCCL. This section 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 class) PUMA, although the original system supported STAN (the Stanford arm), and ELBOW (the elbow manipulator) and others.

5.1 Review of Basic Concepts

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

5.1.1 Robot classification

A robot configured into the RCI system is given a symbolic name and is associated with a particular class of robots (such as PUMA, STAN, or ELBOW). Classes are defined in the file h/robot_class.h. Each class of robots is associated with
1. A set of robot specific parameter structures (and functions to create them);
2. A set of kinematic and dynamic computation functions.

5.1.2 Robot parameter structures

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

1. The 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 compfunc.sec). The definition of the JLS structure is identical for all classes of robot, and is contained in h/robot_jls.h. For more information on the JLS structure and how to obtain it, see JLS(3) and getJls(3).

2. The KYN structure
This contains kinematic level information for the robot in question. The KYN structure contains pointers to two data areas: gen and ext. gen references a structure of type 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 class contains the class of the robot as defined in h/robotClass.h. The 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 5.1.3). 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 KYN ext structure for a particular robot has the name <class>_KYN, and is defined in h/<class>_kynvar.h. For more information on the KYN structure and how to obtain it, see KYN(3) and getKyn(3).

3. The 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 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 VAR structure depends on the class of the particular robot. For any given class, the VAR type has the name <class>_VAR, and is defined in h/<class>_kynvar.h. A program must allocate its own VAR structures for a particular robot, using the size returned by the routine getVarSize(). For more information on the VAR structure, see VAR(3) and getVarSize(3).

5.1.3 Computation Functions

5.1.3.1 JLS conversion functions

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

encoderToAngle (ang, enc, jls) angleToEncoder (enc, ang, jls) encoderToJoint (jnt, enc, jls) jointToEncoder (enc, jnt, jls) mtorqueToJtorque (jtor, mtor, jls)
jtorqueToMtorque (mtor, jtor, jls)

Generic versions of these functions, which will work for all classes of robots, are defined in robots/gen_convert.c and are documented in the RCI Reference Manual. The reason for having class-specific versions as well is that they can be implemented much more efficiently.

5.1.3.2 Kinematic functions

The GEN_KYN substructure of the KYN structure contains pointers to class-specific functions for implementing the following generic routines:

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)

The implementation functions take the same arguments as the routines. Note that they all take a pointer to the KYN structure as an argument. Each function has a manual page in the 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.

5.1.4 Robot communication functions

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

startup (rbt)
input (rbt)
output (rbt)
release (rbt)

ready (arg)
wakeup (arg)

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

The job of the communication functions is to maintain the 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 rbt (type RCI_RBT), which contains pointers to all the robot parameter structures as well as the communication functions. The ready and wakeup functions are called with argument values that are stored in the rbt structure and are set by the startup function.

5.1.6 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. The RCI clock tick is provided by the RTLinux module running in real-time. The "interrupt" is in reality a write to a Real-Time FIFO fifo on which the RCI process is (should be) blocked reading. If the process is in the blocked reading state, then the write by the real-time process will cause the read to return an the RCI process to execute as soon as permitted by the linux scheduler. Note that this is not true real-time, and this may produce some noticeable consequences.

34 5. CONFIGURING THE RCCL/RCI SOFTWARE

defined in the RCCL 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.

5.1.7 Communication software in the robot controller

For RCI communicates with a the joint level servo module (moper) through a small block of shared memory. This memory block contains joint positions, joint setpoints, digital signal states and the ability to specify digital I/O writes.

5.2 Adding a Robot to the System

This section outlines, in some detail, the procedures necessary for configuring a new robot into the RWRCCL/RCI system. It is assumed that the class of the robot is already defined, which means the various interface functions described in section 5.1 already exist.

5.2.1 Updating the robot data table

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

1. The robot's name.

2. The robot's class, as defined in h/robotClass.h.

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

4. The sizes of the two class-specific data types <class>_KYN and <class>_VAR, which are defined in the file h/<class>_kynvar.h.

5. The startup, input, output, and 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.

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

"frank", PUMA, puma_jls, puma_kyn,
sizeof(PUMA_KYN), sizeof(PUMA_VAR),
puma_startup, puma_input,
puma_output, puma_release

An entry for a robot of class STAN that uses the generic communication functions would look like

"stan0", STAN, stan_jls, stan_kyn,
sizeof(STAN_KYN), sizeof(STAN_VAR),
gen_startup, gen_input,
gen_output, gen_release

After robotDataTab.c has been updated, you should run the command

% make libs

in the 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 find_robot().

5.2.2 Updating the robots file

A file called robots, in the directory $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:

1. Specify the name of the robot with a field of the form

name = <robotName>

NOTE: All of the remaining fields can be omitted if the robot is only to be run in simulation mode.

2. Specify the RCI device driver with a field of the form

device = <driverName>

<driverName> should be one of the RCI I/O devices specified in the file IOdriverTable.c. Commonly used devices include pri, which is for DRV11s on MicroVAX systems, and xyd, which is for XYCOM XVME 240s on Sun4 systems.
3. Specify the device's address with a field of the form
address = <number>

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). For the RWRCCL, the device is "tri" for the Trident card and the address is the base address of the trident card as configured. Below is the entry in the robots file for the current installation

# The PUMA 560 at Roger Williams University (Trident/RTLinux):
robot = puma device = tri address = 0x300

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

interrupt = <UNIXdevice>

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.

5. Specify any arguments needed by the device driver with fields of the form

arg<n> = <argvalue>

where <n> is in the range 0 to MAX_DEVARGS 1 and <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 not the case with the pri or xyd drivers). For instance, the driver for a shared memory board with multiple address spaces might need extra information: the 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 args field of the per-device dev structure (see IOdevice(7)). They are set to UNDEF if not defined in the robots file.

As an example, consider the following robots file entry for the robot frank:

robot=frank device=xyd address=0x9000
interrupt=/dev/xydRCI0

This indicates that frank is interfaced to its robot controller using the driver xyd for a device located at 0x9000, and a polling interrupt delivered by the RCI UNIX device /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

robot=frank

would do quite nicely.

5.2.3 Creating a .jls file

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

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

Basically, the .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 calibrating the robot.

Detailed information on each particular field can be found in JLS(3) and makejls(3). General information on the format of the file can be found in 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 .jls file is contained in conf/template.jls.

5.2.3.1 Making a .jls file for a PUMA robot

Creating a .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 conf directory and create the file frank.jls by copying either puma260.jls, puma560.jls, or puma760.jls, depending on whether frank is a PUMA 260, 560, or 760.

At this point, frank.jls should be 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 free, zerograv, and the free joint mode of teachdemo.

To calibrate the .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.

encCalvec These values are used by the robot calibration routine and should be measured using the program primecal (see section 5.6.1).

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 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 free or zerograv. The contents of the field are used by the program pumacal when calibrating the robot from the nest.

potSlope, 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 potcal, which should be run soon after the robot is first calibrated using primecal (see section 5.6.2).

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 puma260.jls, puma560.jls, and puma760.jls are roughly correct for each robot, but you may need to ?tune? the values to get current controlled programs like zerograv to work properly. See section 5.6.3 for information on how to adjust these these values ?by eye?. Most supplied RCCL/RCI programs do not use current control, so you may not want to worry about this for now.

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 moper software in the robot controller measure the joint actuator torques using an analogto-digital converter. (For information on setting up the hardware to do this, see the RCCL/RCI Hardware Installation Notes). The contents of this field are used by RCI to convert the ADC values returned by moper into motor torques. See section 5.6.3 for information on how to determine these values.

forGearRatios, encWheelSize
The default information supplied in puma260.jls, puma560.jls, and puma760.jls is almost always correct for these fields. (A detailed description of what they represent is given in section 5.2.3.3.) 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 primecal can be useful here, because it allows joint motions to be specified in either angle or encoder coordinates.

Finally, you may wish to set or change some of the maximum or nominal operating values described in section 5.2.3.4.

5.2.3.2 Making a .jls file for a simulated-only robot

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

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

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?.

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 mtorqueToCurrent to 1000.0 for large joints and 4000.0 for small joints usually works. currentBias values are set to 0, and the currentToMtorque values can be set to the inverse of the mtorqueToCurrent values.

forGearRatios, encWheelSize, encOffset
These fields describe the relationship between joint and encoder coordinates (for more information, see section 5.2.3.3). On a purely simulated robot one can often fake these values, providing the simulator program itself is using the JLS structure to obtain the same information. Setting the encWheelSize values to 1000 and the 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 encWheelSize value, forGearRatios value, and range (in revolutions for a rotary joint or millimeters for a prismatic joint) should not exceed 2N , where N is the number of encoder bits. The encOffset field should also be specified so that the joint range midpoint is close to the encoder range midpoint 2N?1.

5.2.3.3 Making a .jls file for a general robot

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

If you are creating a .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 forGearRatios, encWheelSize, and 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 5.2.3.2.)

The 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 G. encWheelSize describes the number of encoder counts per motor revolution. Let these form the coefficients of a diagonal matrix W. The relationship between
joint coordinates (given by a vector j) and encoder coordinates (given by a vector e) can then be expressed as
e = W G j + e0

where e0 is an offset vector whose values are determined by the entries in the 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 e0 and corresponding joint values j0. e0 is then computed from
e0 = e0 ? W G j0

e0 and j0 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 encCalvec, encHome, potSlope, and potIntercept fields can be left unspecified.

It is also necessary to furnish a park position and a best position for the robot (in the fields parkAngles and 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.

5.2.3.4 Setting limit values in the .jls file

Several of the fields in the robot's 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.

jmin, jmax The maximum joint ranges (in degrees or millimeters). These are used by the low-level RCI checking options CHK_REQPOS and CHK_MAXPOS; see SET_CHECKING(3).

maxVel, maxAcc, maxJerk
These fields indicate the maximum allowed values on velocity, acceleration, and jerk for each joint. maxVel is used by the low-level RCI checking options CHK_REQVEL and CHK_MAXVEL; see SET_CHECKING(3). At the time of this writing, no supplied RCCL/RCI software makes use of the maxAcc or maxJerk fields (acceleration information is taken from the nominalAcc field; see below).

maxMtorque, 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). maxMtorque is used by the low-level RCI checking

options CHK_REQTOR and CHK_MAXTOR (the latter only if current or torque feedback is implemented); see SET_CHECKING(3). No supplied RCCL/RCI software makes use of the maxJtorque field at the time of this writing.

nominalVel, nominalAcc, 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 behavior. For instance, lowering the values in nominalVel will cause programs which obtain their velocity setpoints from this field to move the robot more slowly. The nominalVel and nominalAcc fields are used by the RCCL and CHASE trajectory generators to determine reasonable trajectory profiles. No supplied software uses the nominalJerk field at the time of this writing.

5.2.4 Creating a .kyn file

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

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

For the PUMA, STAN, and 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.

5.2.4.1 Making a .kyn file for a PUMA robot

Creating a .kyn file for a PUMA robot mostly involves copying a file.

Assume that your new robot is named ?frank?. Then go to the conf directory and create the file frank.kyn by copying either puma260.kyn, puma560.kyn, or puma760.kyn, depending on whether 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 .kyn file. Note also that there are two versions of the PUMA 760: the 761 and the 762. The parameters in 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 5.2.4.3.

5.2.4.2 Making a .kyn file for a general robot

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

Generic .kyn files for the Stanford and ?elbow? manipulators (classes STAN and ELBOW) are contained in the files stan.kyn and elbow.kyn.

5.2.4.3 Gravity loading and friction information

Within .kyn files for the presently implemented robot classes, gravity loading terms are described by parameters of the form CP<XX>, where <XX> indicates joint and index numbers. Static, Coulomb, and viscous friction terms are described by parameters of the form STATF<n>, COULF<n>, and VISCF<n>, where <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 5.6.3.

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

5.2.5 Creating a .pos file

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

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

5.3 Other Configuration Files

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

defaultRobot
Contains the name returned by the routine 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.

.rcc The control file for the rcc command (q.v.), containing the names of all the libraries and include directories which are automatically referenced by 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 .rcc files contained in the user's home directory or the current directory. Its format is described in the manual page for rcc.

5.4 Configuring moper for a Unimation Mark X Controller

The name 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 moper software is located in the directory $RCCL/lsi11.

For sappy, historical reasons the joint-level servo program in RWRCCL was also named moper, however it only partially duplicates the original moper function.

5.4.1 Creating a moper for a new robot

This is definitely the most difficult aspect of configuring an RWRCCL/RCI system, because RCI depends on the low level joint servo interface running in real-time.

The actual joint servo command interface is fairly consistent. What varies is the joint servo control code, and the associated control parameters. The associated control gains are dependent on the joint servo rate, ultimately the rate your system is capable of supporting.

5.4.1.1 Necessary system information

Before creating the moper, you need to know

1. What sort of robot you have (i.e., PUMA, etc.). This should be clear.

2. What sort of controller you have.

3. What type of CPU you have.

5.4.1.2 Modify the program
The moper program for RWRCCL is in the jls directory, a new directory in the RWRCCL distribution, replacing the LSI11 directory. The file moperx.c contains the RTLinux joint-level servo code. The code uses parameters in the mk2_std.560.lin.c file and uses low level communication routines in the pumaInterface.c file. The interior block of the program performs simple-minded P-D control of each joint with some setpoint interpolation for smoother trajectory following.

It should not be too hard to modify this program and add better servo control. Our limiting factor was the inability of our CPU to support floating-point operations in the real-time process. However, our 660MHz PIII is slow even by the standards of the date of this writing.

There is no simple modifications to a configuration file as was common in the RCCL system. To use a new robot will require a re-write of this file suited to your current needs.

5.4.1.3 Rebuild the new moper program.

Remake the moperx module with a the make command

% make

Your moper program should now be ready to load into the kernel using the insmod command.

Start by making removing the current moperx.o module (if inserted)

% rmmod moperx

Note that the watchdog timer of the Trident TRC004 card will illuminate red once the moperx module is removed.

Insert the new moperx.o module

%insmod moperx.o

The watchdog counter is reset every read/write to the trident card, and the LED will illuminate green when the timer is being refreshed. Therefore the first check that a new moperx module is executing correctly is the illumination of the green LED.

5.4.3 Determining servo control parameters

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 mk3_std.560 seems to cause problems, try mk2_std.560 instead. If you have a Mark I controller, try changing mk1_std to mk1_old.

Enter the command

% primecal <robotName>

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 RCCL/RCI Hardware Installation Notes) or wait for you to do so. Once the power is on, primecal will enter into an interactive loop, driven by the C-tree matcher, with the prompt 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 primecal(1).

If you detect problems while running primecal, such as rough joint motion or, in the worst case, the joints just ?take off?, then the servo parameters set by moper are probably wrong and you should see section 5.4.3.
Once these test programs work properly, you should be able to calibrate your robot.

5.6 Robot Calibration Programs

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 JLS structure.
The information in this section is focused on PUMA robots.

5.6.1 The primecal program

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

The purpose of 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 encCalvec field of the JLS structure.

5.6.1.1 How 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 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 ?1=2w, we can use the zero index location to figure out 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 ?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 nw, where n is some integer. But since our estimated position ?e is no more than ?1=2w from the real value e, n can be computed from

n = nint(( ?e ? r)=w);

and the real encoder position can then be computed from n:

e = nw + r

This is the method used by the program pumacal. The task of primecal is to determine the reference values r.

5.6.1.2 Running primecal

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 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 32768x. The resulting set of new r values constitutes the calibration vector, which is printed out by the program, and also printed into the file primecal.out. These values should be entered into the encCalvec field of the robot's .jls file.
More information on primecal can be found in the manual pages.

5.6.2 The potcal program

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 ?e:
?e = mp + b

The set of slope values m constitute the potSlope field and the set of intercept values b constitute the potIntercept field in the JLS structure. potcal measures both of these by taking numerous potentiometer readings across the range of each joint.

5.6.2.1 Running potcal

It is necessary that the robot be calibrated before running potcal. This presents a bit of a chickenand-egg problem if the robot is normally calibrated using the pots. The initial calibration has to be done using primecal. After this has been done, the robot will remain in calibration until the controller is either turned off or the moper program is halted. 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 -atpark to pumacal.

potcal, like 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 calibrate command (except for the wrist, where all the wrist joints may be calibrated together). When doing a sweep, the joint is moved from ?m ? ?s to ?m + ?s, where ?m is the joint mid-range point and ?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 primecal.out. These values should be entered into the potSlope and potIntercept fields of the robot's .jls file.
x32768 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 potcal can be found in the manual pages.

5.6.3 Manually calibrating for current control

This section describes how to adjust the system for proper current control, so that the actual torques resulting from the RCI torque control commands (SET_JTORQUE() and 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 zerograv, and in the ?free joint? mode of the routine rcclTeach() (and its wrapper program, teachdemo). Other programs that presently use current control are free (which frees joints without gravity compensation), and the demo programs demo.rci/zerogDemo and 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{. In the absence of proper sensors, all we can really do is adjust the necessary values ?by eye? until programs such as free and zerograv appear to work correctly.
The fields in the JLS structure that are concerned with current control are currentBias and mtorqueToCurrent.

5.6.3.1 Adjusting the 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 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 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 currentBias field.

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.

If you have an amplifier balance problem, you should try to measure its magnitude by finding out what commanded torque actually produces an output torque of zero. Go to the directory $RCCL/rci, and make the program rbttest (the command make rbttest should do nicely). Now run this program with the command
% rbttest <robotName>
{It is, however, possible to add sensors that read the joint currents (see the RCCL/RCI Hardware Installation Notes). These values can then be used to update the jtorque and mtorque fields of the HOW structure.

This is an interactive program, driven by the C-tree matcher, that allows you to enter RCI commands to the robot one at a time. There is no ?trajectory generator? associated with rbttest; only commands which you explicitly type at the keyboard will be sent to the robot. The program should give you the prompt RBTTEST> , and you should then enter the command start:

RBTTEST> start

This initiates communication with the robot controller. To put a joint into ?torque? mode with a particular torque setting, enter the command

RBTTEST> set mtorque <joint> <torvalue>

where <joint> is the number of the joint you want to control (1 through 6, usually), and <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 actuator-level torque.

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.

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 mtorqueToCurrent for the joint in question. mtorqueToCurrent is a field in the JLS structure containing multipliers to convert motor torques into output DAC values; you can find it in the robot's .jls file. This final value should be entered in the currentBias field of the .jls file.

5.6.3.2 Adjusting the mtorqueToCurrent field

This section assumes that the currentBias is properly set.

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

Run the program zerograv, taking care to be ready to shut off power or abort the program if the robot suddenly moves. The desired behavior of 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 mtorqueToCurrent values and/or the gravity loading terms need adjusting; the former is discussed here.

To calibrate the 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 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 .jls file, save the file, and then restart the program.

If you can't seem to get zerograv to behave no matter how you adjust the mtorqueToCurrent field, then the gravity loading terms are probably wrong (see section 5.6.4).

5.6.4 Manually calibrating gravity and friction terms

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

5.6.4.1 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 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 mtorqueToCurrent values: change the appropriate CP values in the .kyn file, save the file, and restart the program. Make the changes slowly at first.

5.6.4.2 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 zerograv can be used. Start it up with the option -friction. Note that the program is interactive, with command completion provided by the C-tree matcher.
The command

show

will show each joint's current position, as well as a Coulomb friction value. The initial value is read in from the robot's KYN structure.
If you now select some joint j, and enter the command
frictionComp <j> on

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

set frictionComp <j>

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 COULF terms in the robot's .kyn file. The zerograv program will not do this automatically.
Friction compensation for a joint can be turned off using the command
frictionComp <j> off

5.7 Adding a New Device to the System

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.

5.7.1 The RCI I/O driver

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

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

Each driver must implement the nine routines described in section 5.1.5. Consult the manual page 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 RCCL/RCI Hardware Installation Notes suggests which supplied drivers are likely to resemble the actual drivers needed for some particular types of hardware.

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
RCCL/RCI on VxWorks.

NOTE: The driver for the trident TRC004 card has been added to this directory with device name "trident"

5.7.1.1 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 IOdriverTable in the file drivers/IOdriverTable.c. After this has been done, running the command
% make libs
in the drivers directory will install the driver in the RCCL/RCI library.

5.7.3 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 open routine, a close routine, an 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 rciext/xyd.c, which is the UNIX driver for the XVME 240, or the general RCI driver ?template? provided in 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 4.3.4).

5.7.4 Debugging a driver

The program drivertest, in the 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 drivertest, a rather complete description of the pri driver, the moper driver that interfaces with it, and how drivertest can be used to debug both of them, is presented in the file doc/priDriver.doc.

6. Installation Summaries

This section provides some sample check lists for installing RCCL/RCI with the most commonly used equipment.

6.1 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 RCCL/RCI Hardware Installation Notes. For VxWorks installations, the manual RCCL/RCI on VxWorks should also be consulted.

6.2 Hardware

1. 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 adapter, with configuration software.

2. Cable interface ? Build a cable interface to connect each DRV11 and XVME 240.

3. 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.

4. Controller customization ? Upgrade the LSI11 to an LSI11-73, if necessary. Wire up the ?auto power on? circuit, if you desire this feature.

6.3 Software

1. Build RCCL distribution ? See section 3. Unpack the tape, install GNU make, edit the file conf/site.conf, and run ?make World?. Install the simulator network service.

2. Install kernel support, if necessary ? On Sun4 or SGI systems, add kernel support as described in either section 4.3 or 4.4. Include the UNIX genrci drivers, the xyd driver, and (for Sun4 systems with a XVME 203 or 293) the xyclk driver. Create special files for the drivers in /dev. Verify RCI installation with rciCheck (section 4.5).

3. Configure controller serial line connection ? See the RCCL/RCI Hardware Installation Notes. Locate the file in /dev that controls the serial device connected to the robot controller. Verify the connection with termlink.

4. Configure RCI for each robot ? For each robot, give it a name and an entry in robots/robotDataTab.c (section 5.2.1) and conf/robots (section 5.2.2). For VxWorks, use robots.vxw instead of robots. Create a .jls, .kyn, and .pos file for each robot (sections 5.2.3.1, 5.2.4.1, and 5.2.5).

5. Configure moper for each robot ? For each robot, create a moper for it in the lsi11 directory, and adjust its configuration file (section 5.4.1). Build the new moper and load it into the robot controller over the serial line.

6. Test the robot connections ? With moper running in your controller, run the test programs rbtcom and primecal as described in section 5.5.

7. Calibrate the robots ? Calibrate each robot using primecal and potcal as described in sections 5.6.1 and 5.6.2. If you want to use current control programs such as zerograv, then do the calibrations described in section 5.6.3 and 5.6.4 as well.

6.4 Installation for Simulator-only Systems

1. Build RCCL distribution ? See section 3. Unpack tape, install GNU make, edit the file conf/site.conf, and run ?make World?. Install the simulator network service.

2. Configure RCI for each robot ? For each robot, give it a name and an entry in robots/robotDataTab.c (section 5.2.1) and conf/robots (section 5.2.2). Create a .jls, .kyn, and .pos file for each robot (sections 5.2.3, 5.2.4, and 5.2.5).

3. Test the robot connections ? Start the simulator program robotsim with the name of the robot you want to simulate. Try to ?move? this robot using the command move with the -sim option.

7. Adding New Classes of Robots to the System

If you wish to add a new class of robot to the system, then you will need to write implementations of the functions described in section 5.1.

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

1. Define a class for the robot in the file h/robotClass.h.

2. Define the <CLASS>_KYN and <CLASS>_VAR structures for the robot type, and place these definitions in a file h/<class>_kynvar.h.

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 PUMA.

4. Write the functions <class>_jls() and <class>_kyn() used for instantiating JLS and KYN structures. (See section 7.1 for details.)

5. Write class-specific implementations of the conversion functions described in section 5.1.3.1. (See section 7.2 for details.)

6. Write class-specific implementations of the kinematic functions described in section 5.1.3.2. (See section 7.3 for details.)

7. (If necessary) Write the robot communication functions, described in section 5.1.4, which provide the interface to the robot controller. (See section 7.4 for details.)

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 5.7.

9. (If necessary) Create the necessary interface software on the robot controller (this is a moper equivalent). (See section 7.5 for details.)

Some of these steps are now discussed in more detail.

7.1 Writing JLS and KYN Access Functions

The functions <class>_jls() and <class>_kyn() are used by the system functions getJls() and getKyn() to help instantiate the JLS and KYN structures. <class>_jls() sets the JLS structure pointers for the functions described in section 5.1.3.1. <class>_kyn() sets the KYN structure pointers for the functions described in section 5.1.3.2, and also reads in data from the robot's .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 getJls(3).
The functions for the PUMA robot live in puma/puma_jls.c and puma/puma_kynvar.c.

7.2 Writing the JLS Conversion Routines

These are implementation functions for the routines described in 5.1.3.1.

All of the parameters needed to perform these computations are defined by data fields in the JLS structure itself, and generic functions, which will work for any robot, are defined in the file 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 (<class>_).
The functions for the PUMA robot live in puma/puma_convert.c.

7.3 Writing the Kinematic Routines

These are implementation functions for the routines described in 5.1.3.2. They take the same arguments as the generic routines. Information on each one is given in the 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 fwdJacob routine for the PUMA is called pumaFwdJacob().

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

Within the 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 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.

7.4 Writing the Robot Communication Functions

These are the routines described in 5.1.4.
Information on what these functions do is provided in the manual page robotComfxns(7). They generally take the names

<pfx>_startup
<pfx>_input
<pfx>_output
<pfx>_release
<pfx>_ready
<pfx>_wakeup

where <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 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.

NOTE: There is a set of ?generic? communication functions, named with the prefix gen and defined in 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 robotsim.

The communication functions used by a particular robot are declared in rciRobotDataTable (see section 5.2.1).

7.5 Interface Software in the Target Controller

When adding a new type of robot to the RCCL/RCI system, it will probably be necessary to write 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 moper, or parts of it. To help in doing this, a brief overview of the moper software is given here.

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 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 moper is given in the file 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 printf() and 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 doc/microkernel.doc. The modules related to the microkernel are also described in lsi11/README.

RWRCCL/RCI Release 6.2, January 06, 2004