home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-03-02 | 31.1 KB | 1,127 lines |
- .ND
- .FS
- This work was partially supported by a Grant from the CNRS
- project ARA (Automatique et Robotique Avanc\o"e\'"e), France, and
- by the Ransburg Chair of Robotics.
- This material is also based on work supported by the National
- Science Foundation under the Grant No. MEA-8119884.
- Any opinions, findings, conclusions, or recommendations
- expressed in this publication are those of the authors
- and do not necessarily reflect the views of the National
- Science Foundation.
- Facilities to perform this research are provided by the Purdue University
- CIDMAC
- project.
- .FE
- .ce 1
- Robot Real Time Control User's Manual
- .sp 7
- .ce 1
- Vincent Hayward
- .sp 5
- .ce 3
- School of Electrical Engineering
- Purdue University
- West Lafayette, Indiana, 47907
- .sp 5
- .ce 1
- TR-EE 83-42
- .sp 5
- .ce 1
- October 1983
- .bp
- .EQ
- delim $$
- .EN
- .NH
- Overview
- .PP
- This manual describes how to implement real time programs
- to control the robots situated in room B20 at Potter Building.
- The Stanford and the Puma 600 arms can be equally used.
- The system consist of :
- .IP *
- an executable module, called the superviser, which is to be
- loaded down to the robot controller's lsi11 processor;
- .IP *
- a UNIX library containing several entry points:
- .RS
- .IP -
- a function
- .B control()
- which permits to open the robot channel
- and makes the vax sensitive to controller's interrupts;
- .IP -
- a function
- .B release()
- which shuts off the arm and closes the channel;
- .IP -
- a function
- .B adcopen()
- for specifying analog to digital conversions.
- .IP -
- a "C" structure
- .B how
- describing the robot state
- updated at sample time intervals;
- .IP -
- a "C" structure
- .B chg
- describing the different commands that
- are likely to be sent to the arm controller;
- .IP -
- a flag
- .B terminate
- to indicate when the real-time interaction
- should terminate;
- .IP -
- a pointer to a string
- .B mess
- that will be printed at the termination
- of the real-time interaction;
- .IP -
- a function
- .B stepmode()
- that permits to manually move each joint
- from the terminal;
- .IP -
- mapping functions:
- .B
- enctoang(), rngtoang(),
- .R
- etc... (see appendix).
- .RE
- .IP *
- an include file
- .B rtc.h
- describing the structures
- .B how
- and
- .B chg
- ;
- .NH
- Real Time Considerations
- .PP
- Real time programming offers several peculiar aspects which
- have to be mentioned here.
- A real time program consists of two parts.
- The main function, executed in time sharing, allows
- the program to communicate with the rest of the system.
- It can contain system calls, as disk or terminal
- input-output, etc ...
- The interrupt routines, activated upon controller interrupt,
- are executed in kernel mode for efficiency.
- Their execution time must be limited and therefore, they
- .B cannot
- perform
- .B any
- type of system call (read(2), write, fork(2),
- signal(2), exec(2), brk(2) and so on).
- .PP
- Any machine error as floating point exception or bad memory reference
- occurring during the execution of
- the interrupt functions will produce a system crash.
- The program cannot grow it's allocated region therefore any
- calls like fork(2), open(2), malloc(2) must not be invoked when
- the channel is open.
- However, this type of calls can be performed before opening
- the channel ,which is a minor burden.
- If you need to use dynamic memory allocation, the package provides
- alternative entry points (see Appendix) to perform similar functions
- (alloc/free) but within a pre-allocated pool of memory.
- Since the capacity is limited, caution must be taken
- to insure that the allocations are successful.
- .PP
- The interrupt functions are called from the robot interface
- package without any argument and are executed at very high priority.
- Therefore, they can only communicated with the rest of the program
- via global variables, which makes the programming more difficult.
- A systematic use of structured data types and of the 'lint' program
- is strongly recommanded.
- .PP
- The package makes use of SIGINT (signal(2)) to terminate the
- real time interaction and to shut off the arm. The real time
- driver makes use of SIGHUP (signal(2)) to signal a hardware
- error to the package. Therefore, SIGINT and SIGHUP must
- .B not
- be caught by the user.
- Interaction can be terminated either by setting the global
- variable
- .B terminate
- to 'YES' from the main program or from the interrupt
- functions.
- The same effect is achieved by typing a 'break' or often a 'rub' on the
- terminal (see stty(2)).
- The main function must remain active throughout the execution
- of the real time program.
- You will have to code something like :
- .DS L
-
- while(!terminate) {
- /* do time sharing */
- }
- release("finished");
- .DE
- .PP
- The termination will be properly produced either by a 'break'
- at the terminal or by setting
- .B terminate
- to YES anywhere
- in the program.
- .NH
- The 'How' Structure
- .PP
- The
- .B how
- structure describes the current state of the arm and
- is updated at interrupt time.
- .DS L
- struct how {
- unsigned short
- exio, /* state of the extern io register */
- pos[NJOINTS]; /* current positions */
- short
- adcr[ADC]; /* adc readings */
- };
- .DE
- .PP
- The content of the external i/o register reflects the state
- of the switches on the front panel.
- Normal usage of the interface does not require to pay any attention to
- the register's content.
- Positions are specified in
- .B encoder
- values.
- See appendix for mapping the encoders values
- onto the trigonometric circle, or on a physical linear scale.
- The
- .B how
- structure can be read either synchronously
- by the interrupt code or asynchronously by the main program.
- The first 'NJOINTS' elements of the 'adcr' array are by default
- the adc readings reflecting the motor currents of the manipulator's joints.
- The 'adcr' values are in adc readings and have to be scaled by mean
- of some calibration program.
- .NH
- The 'Chg' Structure
- .PP
- The
- .B chg
- structure describes the commands that the user wants
- to be executed by the robot controller.
- It is made of sub-structures which correspond to the four following
- cases:
- .IP -
- A command is to be sent individually to a particular joint processor.
- Their name is of the form 'i_name'. For each concerned command,
- the structure 'chg' contains an array of these structures, one per
- joint.
- Each of the 'i_name' structure contains one value field.
-
- .IP -
- The same command is to be send to all the joint processors.
- Their name is of the form 'a_name'.
- For each concerned command, the structure 'chg' contains an instance
- of a 'a_name' structure, but the value field is an array.
- Using one 'a_command' is equivalent to use 'NJOINTS' 'i_commands', but
- is more concise, and more efficient as far as the transmission time
- and the command execution time are concerned.
-
- .IP -
- The same command is to be sent to all the joint processors, but
- the same value is to be set in each joint processor.
- They are named 'g_name' commands.
- A 'g_command' contains one value field.
-
- .IP -
- The last case is a command which does not need any transmitted value.
- .PP
- The following shows the structure
- .B chg
- and the various combinations
- of commands:
- .DS L
- struct i {
- char set; /* flag to be set if i_command requested */
- unsigned short vali; /* corresponding value */
- };
-
- struct a {
- char set ; /* flag to be set if a_command requested */
- unsigned short vala[NJOINTS]; /* corresponding values */
- };
-
- struct g {
- char set; /* flag to be set if g_command requested */
- unsigned short valg; /* corresponding value */
- };
-
-
- struct chg {
- struct i i_motion[NJOINTS]; /* case POS - CUR - STOP */
- struct a a_motion;
-
- struct g g_hand; /* command hand */
- struct g g_rate; /* rate in 2 ** value * 7 ms */
-
- char end; /* termination */
- char stop; /* stop on the spot */
- };
- .DE
- .PP
- The actual chg structure in the rtc.h file may exhibit other instances
- of 'a', 'i', or 'g' structures.
- However, the following briefly describes the commands you are concerned with.
- .IP "motion : " 11
- Specify a position servo if the flag is raised with 'POS' value.
- Specify a motor current if the flag is raised with 'CUR' value.
- .FS
- The values of POS, CUR, STOP, STOPCAL, NJOINTS, ADC, YES, NO,
- are '#defined' and must not be redefined.
- .FE
- .IP "rate : " 11
- Modify the sampling rate, or in other terms, the interrupt interval
- time, it is expressed in powers of two times 7 milli-second.
- .IP "stop : " 11
- Let the joint processor servo on the last position value.
- .IP "hand : " 11
- Control the hand.
- Meaning dependent on particular experiments.
- .NH
- Sequence of operations
- .NH 2
- Opening the Channel
- .PP
- The package provides the
- .B control
- function to open the robot's
- device and initialize the communication. This function takes
- two arguments which are pointers to the functions that you
- want to be executed on interrupt.
- The purpose of these two functions is explained in the next
- paragraph.
- Before you tell the controller to start interrupting the vax,
- you must make sure that the device is opened and your program
- is waiting for interrupts.
- Once the channel is opened, the user must not catch the
- SIGINT and SIGHUP signals (see signal(2)).
- The minimum code will look like:
- .DS L
- #include "rtc.h" /* include communication declarations */
- /* global variables */
- ...
-
- main()
- {
- int fn1(), fn2(); /* declare real time functions */
-
- control(fn1, fn2); /* open channel */
- while (!terminate) /* wait for the end */
- nap(10);
- release("all done");
- }
-
- fn1()
- {
- }
-
- fn2()
- {
- extern struct how how;
- extern struct chg chg;
-
- ... /* read arm state in how */
- ... /* compute next point, put commands in chg */
- }
-
- .DE
- .PP
- While the program is 'pausing' or 'napping' you will start the
- superviser program by depressing the 'ARM POWER' push button and
- the interaction will take place.
- A 'break' at the terminal will cause the
- .B release
- function to be automatically called and
- the message "** Interrupted" printed on the terminal.
- However, it can be a good idea to systematically terminate your
- programs to a call to
- .B release.
- Failing to issue this call by one mean or another will leave the
- device opened and therefore unable to be re-opened.
- So, make sure that 'exit's in your programs are preceded by
- a call to
- .B release
- as shown in paragraph 2.
- The function
- .B release
- expects a character
- string argument as message to be printed when the channel is
- explicitly closed.
- .PP
- Note that a valid organization can be:
- .DS L
- #include "rtc.h" /* include communication declarations */
-
- ... /* global variables */
-
- main()
- {
- int fn1(), fn2(); /* declare real time functions */
-
- control(fn1, fn2); /* open channel */
- pause(); /* wait for the program to be broken */
- }
-
- fn1()
- {
- }
-
- fn2()
- {
- extern struct how how;
- extern struct chg chg;
-
- ... /* read arm state in how */
- ... /* compute next point, put commands in chg */
- }
-
- .DE
- .PP
- If analog to digital conversions are needed, the
- .B adcopen
- function allows
- to select the physical adc channels.
- The function
- .B adcopen
- must be called from the time sharing code after
- a call to
- .B control.
- This function transmits to the lsi a request as to send back to your
- program the readings of the selected adc channel.
- The function
- .B adcopen
- returns an integer that is the index in
- the array 'adcr' of the corresponding channel.
- The first 6 channels are used to measure the motor currents,
- channels 0 through 5 are
- therefore opened by default and cannot be reopened.
- Motor currents can be
- read in positions 0 to 5 of the array 'adcr'.
- The function
- .B adcopen
- returns -1 if the
- channel is already opened, or the argument invalid, or
- .B control
- is not
- active. Up to 10 channels can be used (6 through 15).
- .PP
- Example :
- A sensor is wired to channel 7, in order to use it the code may look like:
- .DS L
- #define SENSORCHANNEL 7
-
- int sensor = -1;
-
- main()
- {
- blabla;
- ...
- control(f1, f2);
- sensor = adcopen(SENSORCHANNEL);
- while (!terminate) {
- nap(10);
- }
- release("happy");
- }
-
- f1()
- {
- }
-
- f2()
- {
- if (sensor < 0) { /* not ready yet */
- return;
- }
- pos = how.adcr[sensor] * factor;
- nextpoint = f(pos);
- }
- .DE
- .NH 2
- What Happens on Interrupt
- .PP
- In order to provide for parallel processing in the vax and
- in the lsi11, the following scheduling occurs:
- .TS
- allbox, tab(@);
- c c c.
- @LSI @VAX
- Interrupt Time --> @gather arm state @may still be computing
- @interrupt vax @acknowledge
- @send buffer @get buffer
- @wait for vax @call user's fn1
- @ @set up command buffer
- @get commands @send command buffer
- @execute commands @call user's fn2
- .TE
- .PP
- Three schemes are possible.
- The first one spreads the computations among fn1 and fn2.
- It is used to provide the fastest response to sensing feedback,
- while providing the maximum computing time.
- The second case only uses fn2 and provides the maximum computing time.
- The third case provides for best control if the computing time is
- short by using fn1 only.
- At the first interaction, fn1 is not called.
- .NH
- Examples
-
- The Marsh-mallow Program :
- .PP
- This program merely reads the actual positions of the joints at time $t$
- and drive them at time $t+1$ with the read values.
- If a torque is exerted on a joint when the positions are measured,
- the actual position is:
- .EQ
- P sub a ~=~ P sub d ~+~ E
- .EN
- .PP
- Where $P sub a$ is the measured position, $P sub d$ is the desired
- position, and $E$ the position servo error.
- One can assume that the error is proportional to the exerted torque.
- .EQ
- E~=~k~T
- .EN
- Where $k$ is a spring constant depending on the gain of the servo and
- the sample rate.
- $T$ is the exerted torque.
- Let us compute the velocity by subtracting the differential position
- between two successive sample times when the actual position at
- time $t$ is specified as desired position at time $t+1$.
- .EQ
- P sub a sub {t+1} ~=~ P sub a sub {t}~+~ k~T sub {t+1}
- .EN
- .EQ
- DELTA P sub a ~=~ P sub a sub {t+1} - P sub a sub {t} ~=~ k~T sub {t}
- .EN
- .PP
- The velocity is proportional to the torque which make the manipulator
- act like a highly damped free system.
- .DS L
- #include "rtc.h"
-
- int enough = NO;
-
- main()
- {
- extern int terminate;
- int dummy(), soft();
-
- control(dummy, soft);
- printf("press return to end ");
- getchar();
- enough = YES;
- while (!terminate)
- sleep(1);
- release("done");
- }
-
-
- dummy()
- {
- }
-
-
- soft()
- {
- extern struct chg chg;
- extern struct how how;
- register int i;
-
- if (enough) {
- terminate = YES;
- return;
- }
- chg.a_motion.set = POS;
- for (i = 0; i < NJOINTS; ++i) {
- chg.a_motion.vala[i] = how.pos[i];
- }
- }
- .DE
- The Free Program :
- .PP
- This second example makes use of the torques to motor currents mapping
- to overcome the gravity loadings of the manipulator joints.
- .DS L
- #include "rtc.h"
-
- extern struct how how;
- extern struct chg chg;
-
- main()
- {
- extern int terminate;
- int dummy(), freej();
-
- control(dummy, freej);
- for (; ; ) {
- pause();
- }
- }
-
- dummy(){}
-
- static freej()
- {
- double sin(), cos();
-
- static int first = YES;
- static unsigned short old[NJOINTS];
- short cur[NJOINTS];
- double jpos[NJOINTS], gtor[NJOINTS];
- double c2, c23, s23, c4, s4, c5, s5;
- register int i;
-
- if (first) {
- first = NO;
- for (i = 0; i < NJOINTS; ++i) {
- old[i] = how.pos[i];
- }
- return;
- }
- enctoang(jpos, how.pos);
- c2 = cos(jpos[1]);
- c23 = cos(jpos[1] + jpos[2]);
- s23 = sin(jpos[1] + jpos[2]);
- c4 = cos(jpos[3]);
- s4 = sin(jpos[3]);
- c5 = cos(jpos[4]);
- s5 = sin(jpos[4]);
- gravload(gtor, c2, c23, s23, c4, s4, c5, s5);
- tortodac(cur, gtor, how.pos, old);
- for (i = 0; i < NJOINTS; ++i) {
- chg.a_motion.vala[i] = cur[i];
- old[i] = how.pos[i];
- }
- chg.a_motion.set = CUR;
- }
-
-
- gravload(l, c2, c23, s23, c4, s4, c5, s5)
- double *l;
- double c2, c23, s23, c4, s4, c5, s5;
- {
- l[0] = 0.;
- l[2] = CP32 * s23 + CP31 * c23;
- l[1] = l[2] + CP21 * c2;
- l[3] = -(CP50 * s23 * s4 * s5);
- l[4] = CP50 * (s23 * c4 * c5 + c23 * s5);
- l[5] = 0.;
- }
-
- .DE
- .NH
- Calibration, stepping mode, and automatic home return
- .PP
- It is time to insist on the fact that when the controller is
- powered up, the encoders counters contain random values that have
- no relation with the physical configuration of the arm.
- At least once after powering up the controller, the arm
- .B has
- to be calibrated.
- This is achieved by calling
- .B stepmode()
- before doing anything.
- When you exit from this mode, you are prompted for calibration.
- The arm must then it a position close to the home position.
- The calibration moves each joint if the arm, reset the counters
- and move each joint again to the home position.
- You must do it at least once, and in whichever configuration
- you could leave the arm,
- it is not necessary to do it before the next power up.
- If your program terminates leaving the arm away from its
- home position, you can either bring it back using the stepping
- mode and calibrate it again, or merely break any program at any point
- which cause the package to prompt you if you want
- an automatic home return.
- The return will be always successful, unless you seriously damaged
- the arm.
- .PP
- The ARM POWER switch is the only physical communication that the
- controller has with the rest of the universe.
- The sequence of operation is always the same :
-
- .IP 1
- Power is off and the controller keeps monitoring the ARM POWER button;
- .IP 2
- You run you program, it can then open files, do system calls etc.
- It can either :
- .RS
- .IP 2.1
- exit.
- .IP 2.2
- call
- .B stepmode;
- .IP 2.3
- call
- .B control;
- .RE
- .IP 3
- The channel is opened, and the vax is waiting for interrupts.
- You press ARM POWER, and the controller starts interrupting the vax.
- .IP 4
- The vax receives interrupts and executes one of the three programs :
- .RS
- .IP 4.1
- If you are in stepping mode, you can move individually each joint,
- when done, the channel is closed;
- .IP 4.2
- If you asked for home return after a break, the arm will return and the whole
- programs exits.
- .IP 4.3
- Otherwise, your program issued a call to
- .B control
- and your
- interrupt functions are executed.
- When your program is done, it must call
- .B release;
- .RE
- .IP 5
- The channel is closed, goto step 1.
-
- .PP
- You can code an unlimited number of 'control-release' pairs, if you need
- either to use different interrupt functions or perform system calls
- at a given moment.
- .PP
- The interface constantly monitors if the arm power is on.
- If for any reason, the arm power is turned off, the controller
- will still continue to run, but the vax will ignore interrupts
- and the arm will remains in the state it was at the moment
- power was turned off (and brakes set).
- Turning on the arm power again, will resume the execution.
- This may cause some jerky motions if the arm was
- stopped in the middle of a trajectory.
- .NH
- Error handling
- .PP
- The problem is to cleanly terminate a program when something
- goes wrong.
- If the error is detected in the main program, a proper exit at any place
- in the code can be :
- .DS L
- if (panic) {
- terminate = YES;
- release("why ...");
- exit(1);
- }
- .DE
- If the error is detected in the interrupt functions,
- .B release
- and
- .B exit
- cannot be called but
- .B terminate
- can be set and
- the interrupt function must return (in this case from interrupt).
- The package will cease to execute your interrupt functions.
- The main program remains active, arm power is turned off and
- everything seems frozen.
- The only resource is then to break the program
- and perform an automatic home position return
- if you wish.
- The string to which the
- .B mess
- variable is pointing to will
- be printed before the final exit. This is the only debugging
- tool in the real-time environment.
- Attention !, if the error is detected inside a function called
- from the main interrupt function, caution must be taken to
- cause a cascade of returns.
- The following shows a few possibilities.
- .DS L
- fn() /* interrupt function */
- {
- /* do whatever */
- if (panic) {
- mess = "why ...";
- terminate = YES;
- return;
- }
- /* do whatever */
- if (fn1())
- return;
- /* do whatever */
- fn2();
- if (terminate)
- return;
- }
-
- fn1()
- {
- /* do whatever */
- if (panic) {
- terminate = YES;
- mess = "why ...";
- return(YES);
- }
- /* do whatever */
- fn2();
- if (terminate)
- return(YES);
- /* do whatever */
- return(NO);
- }
-
- fn2()
- {
- /* do whatever */
- if (panic) {
- terminate = YES;
- mess = "why ...";
- return;
- }
- /* do whatever */
- }
- .DE
- .PP
- Any message issued by the package is preceded by two stars, ex:
- "** Channel opened, turn on ARM POWER", so you can distinguish them from your
- own messages.
- .PP
- The package also performs checks on the validity of the
- data send to and received from the controller.
- Following is a list of all the messages:
- .IP 1)
- Error messages :
- .RS
- .IP
- "** too many commands", this will occur there are more commands
- specified than the output buffer can contain.
- .IP
- "** too large position increment", this means that ,in position mode,
- one joint has been specified a value too far from the last read position.
- .IP
- "** out of range", means that a specified value would drive a joint
- out of range.
- .IP
- "** too much current", means that you specified too a large value in
- current mode.
- .IP
- "** too large observed current", a driving current is too high, probably
- because the arm ran into an obstacle in position mode.
- .IP
- "** too large observed velocity", the velocity resulting from incorrect
- current or position specifications is too high.
- .IP
- "** joint(s) out of range", the position resulting from incorrect
- current or position specifications drives the arm out of range.
- .IP
- "** channel not released", the channel has not been released before
- a reopen via 'control()'.
- .IP
- "** bad checksum", result of a hardware failure.
- .IP
- "** interrupt occurred before end of user function",
- result of too lengthy computations. Most of the time you will get :
- .IP
- "**** hardware failure", the channel cannot initialize.
- .IP
- "**** driver error...exch = %d\n", something wrong, number of exchanges.
- .IP
- "** can't gtty", if the tty could'nt be put in cbreak mode during
- the stepping mode.
- .RE
- .IP 2)
- Informative messages.
- .RS
- .IP
- "** Interrupted", when you break the program.
- .IP
- "** exch = %d", total number of times fn2 has been called.
- .IP
- "** end of step mode", self explanatory.
- .IP
- "** calibrating", while U wait for the arm to be calibrated.
- .IP
- "** attempting a home return", self explanatory.
- .IP
- "** back home, calibrated", ....
- .IP
- "** channel opened, turn on ARM POWER", informs that the vax is ready
- to receive interrupts.
- .RE
- .IP 3)
- Prompts
- .RS
- .IP
- "** attempt an automatic home return ?", what you get when the
- program is broken, answer `y' or `n'.
- .IP
- "** exit ? (y/n) _ calibrate ? (y/n) _ sure ? (y/n) _ ",
- exit of the stepping mode.
- .RE
- .NH
- Appendix
- .PP
- Additional entry points are provided :
-
- .IP -
- .B
- enctoang(a, e)
- .R
- is a function whose first argument is an array of 'NJOINTS'
- .B doubles
- and whose second argument is an array of 'NJOINTS'
- .B shorts.
- The function converts the encoders values contained in the second
- argument to angles expressed in
- .B radians
- within the range [-$pi$ ,+$pi$] relative to
- the solution coordinate frames described in [Paul2 81] for the Puma
- arm and in [Paul3 81] for the Stanford arm.
-
- .IP -
- .B
- angtoenc(e, a)
- .R
- is a function which performs the inverse transformation.
- The first argument is an array of 'NJOINTS'
- .B shorts
- and the second
- argument is an array of 'NJOINTS'
- .B doubles.
- This function returns a non zero integer code when one or more
- angle is out of range.
- The bits are referenced by their octal value.
- Bit 01 is set if joint 1 is out of range, bit 02 for joint 2, bit 04
- for joint 3, and so on.
-
- .IP -
- .B
- enctorng(r, e) and rngtoenc(e, r)
- .R
- perform the same functions
- as above but angles are expressed in the [0 - range] interval.
- In that case, an angle is zero when the corresponding joints
- is at its limit position turning counterclockwise.
-
- .IP -
- .B
- angtorng(r, a) and rngtoang(a, r)
- .R
- perform the mappings of
- angles to ranges and vice-versa. Both arguments are arrays
- of doubles.
-
- .IP -
- .B
- tortodac(d, t, v, o)
- .R
- performs torques to dac values mapping.
- Where 'd' is an array of 'NJOINTS'
- .B shorts,
- the resulting dac values, computed from the array 'd' of 'NJOINTS'
- .B doubles,
- the desired torques in
- .B N-mm.
- The arrays 'v' and 'o' are sets of 'NJOINTS'
- encoder values, 'v'
- is the current value of the joint positions, and 'o' the previous.
- This is needed to decide the current velocity of each joint [Zhang 83].
-
- .IP -
- .B
- adctotor(t, a, v, o)
- .R
- performs the inverse operation, where 't' are
- the torques stored in an array of
- .B doubles
- computed from 'a' the measured adc values, an array of 'NJOINTS'
- .B shorts.
- The arrays 'v' and 'o' serve the same purpose as before.
-
- .PP
- Memory allocation substitutes, work as described in Chap 2 of
- the UNIX manual, use :
- .TS
- tab(@);
- c c c.
- malloc_l @for @malloc
- free_l @for @free
- realloc_l @for @realloc
- calloc_l @for @calloc
- cfree_l @for @cfree
- .TE
- .EQ
- delim ^^
- .EN
- .NH
- Utility programs
- .PP
- A program called
- .B calib
- is made available, it contains :
- .DS L
- main()
- {
- stepmode();
- }
- .DE
- It allows to calibrate the arm after power up, such as calling stepmode
- in the development programs is not mandatory.
- Use :
- .DS L
- calib
- .DE
- .PP
- A program called
- .B play
- reads a file of encoder values and ship them
- to the controller to be executed.
- Each setpoint is a record of seven 16 bits words.
- The first six words are the encoder values for the joints
- one through six.
- The seventh 16 bits word specifies the hand position.
- For historical reasons, it is expressed on the 12
- high order bits.
- With the pneumatic gripper, the character 'o' placed in those 12 bits,
- opens it, 'c' closes it.
- Play uses the file as a circular buffer and will play
- the sequence of points over and over.
- Both ends of the sequence must match.
- Use :
- .DS L
- play file
- .DE
- The programs promts : "more ? (y/n)", if 'n' is answered, the arm will
- stop at the end of the current cycle.
- If 'y' is answered, it becomes possible to change the rate at which
- the points are send by factor of two.
- .PP
- The programs
- .B mkenc
- reads a file of points in formated form and
- makes a file of 'playable' encoders values created as '@@@.out' in
- the current directory.
- The points must be expressed in
- .B radians
- relative to the solution coordinate
- frames (it uses 'angtoenc').
- An error message is printed on the standard error file each time
- a value is specified closer than five degrees off the joint limits.
- Use :
- .DS L
- mkenc file or mkenc < file
- .DE
- where "file" contains lines like :
- .DS L
- 0.00 -1.57 3.14 0 1.57 0
- 0.00 -1.57 3.14 0 1.57 0
- 0.00 -1.57 3.14 0 1.57 0
- 0.00 -1.57 3.14 0 1.57 0
- .DE
- .PP
- The shell file
- .B dl
- performs the downloading of the superviser
- down to the controller, use :
- .DS L
- dl moper
- .DE
- for the Puma.
- .PP
- One more detail, a file called 'llib-rtc'
- in the style of 'llib-lc' describes the
- form of the calls and external variables.
- This can be used for 'linting' your programs and checking the proper
- list of arguments.
- Use :
- .DS L
- lint myprog.c -v llib-rtc
- .DE
- where 'llib-rtc' may have to be preceded
- by some leading path (see below).
- .PP
- Finally, use the math library '-lnm' for efficiency.
- .NH
- Files
- .PP
- Currently are set up for the Puma manipulator :
- .DS L
- /b/rccl/l/rtc.a the library
- /b/rccl/h/rtc.h the include file
- /b/rccl/l/llib-rtc lint description of the library
- /b/rccl/s/calib calibration program (merely a call to stepmode)
- /b/rccl/s/play the play program
- /b/rccl/s/mkenc make encoder values
- /b/rccl/s/dl down load the controller
- /b/rccl/s/moper the superviser
- .DE
- .PP
- In order to save typing errors there are some usefull short hands
- to specify the leading paths.
- As an example we list here the commands necessary to compile, link
- and execute a real time program.
- We will first set the PATH shell variable such as the list
- of search directories also include '/b/rccl/s' (this can be done in
- the '.profile' or '.cshrc' startup files) :
- .DS L
- PATH=$PATH:/b/rccl/s (for sh users)
- export PATH
-
- set path=($path /b/rccl/s) (for csh users)
- .DE
- We can know use
- .B calib,
- .B play,
- and
- .B dl
- as regular commands.
- .PP
- Then we may like to create shell variables to specify the libraries (
- can be done in '.profile' or '.cshrc').
- .DS L
- rtc=/b/rccl/l/rtc.a (for sh users)
- rtclint="-v /b/rccl/l/llib-rtc"
-
- set rtc=/b/rccl/l/rtc.a (for csh users)
- set rtclint=(-v /b/rccl/l/llib-rtc)
- .DE
- .PP
- The last detail is to specify the include files :
- .DS L
- rtc="-I/b/rccl/h /b/rccl/l/rtc.a" (for sh users)
- rtclint="-I/b/rccl/h -v /b/rccl/l/llib-rtc"
-
- set rtc=(-I/b/rccl/h /b/rccl/l/rtc.a) (for csh users)
- set rtclint=(-I/b/rccl/h -v /b/rccl/l/llib-rtc)
- .DE
- Now the compile and link can be done as :
- .DS L
- cc myprog.c $rtc -lnm
- .DE
- and the lint :
- .DS L
- lint myprog.c $rtclint
- .DE
- If the controller has been downloaded and the arm calibrated, just type :
- .DS L
- a.out
- .DE
- When you get the message "** channel opened, turn on ARM POWER",
- turn on ARM POWER and good luck.
- .NH
- References
- .IP
- Paul , R., P., Shimano, B. , Mayer, E., G.,
- "Kinematic Control Equations for Simple Manipulators",
- IEEE Transactions on Systems, Man, and Cybernetics, Vol. SMC-11,
- No 6, June 1981.
- .IP
- Paul, R. P., "Robot Manipulators: Mathematics, Programming,
- and Control", MIT Press 1981.
- .IP
- Zhang, H., Paul, R. P.,
- "Determination of Simplified Dynamics of Puma Manipulator", Purdue University.
-