home *** CD-ROM | disk | FTP | other *** search
- /*LINTLIBRARY*/
-
- #include <sys/types.h>
- #include <sys/drc.h>
- #include <signal.h>
- #include <sgtty.h>
- #include "../h/exiod.h"
- #include "../h/unim.h"
- #include "../h/which.h"
- #include "../h/rtc.h"
- #ifdef PUMA
- #include "../h/pumadata.h"
- #endif
- #ifdef STAN
- #include "../h/standata.h"
- #endif
-
-
- struct chg chg; /* global control structure */
- struct how how; /* global robot state structure */
- int terminate = NO; /* shuts up the pack routine */
- char *mess; /* printed by release */
-
- static short obuff[COMSIZE] = {4, VERSION, ARMTYPE};
- static unsigned short ref[6] = {ECCL1, ECCL2, ECCL3, ECCL4, ECCL5, ECCL6};
- static unsigned short max[6] = {ECMX1, ECMX2, ECMX3, ECMX4, ECMX5, ECMX6};
- static unsigned short min[6] = {ECMN1, ECMN2, ECMN3, ECMN4, ECMN5, ECMN6};
- static unsigned short mvl[6] = {EMXV1, EMXV2, EMXV3, EMXV4, EMXV5, EMXV6};
- static unsigned short mxdc[6] = {MXDC1, MXDC2, MXDC3, MXDC4, MXDC5, MXDC6};
- static unsigned short mxoc[6] = {MXOC1, MXOC2, MXOC3, MXOC4, MXOC5, MXOC6};
- static short idx[6] = {XCCL1, XCCL2, XCCL3, XCCL4, XCCL5, XCCL6};
- #ifdef ADC
- static int nch = NJOINTS;
- static int adcmap[ADC] =
- {0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
- #endif
- static int rate;
- static int inserf = NO;
- static int active = NO;
- static int first = YES;
- static int cbrkset = NO;
- static int checking = YES;
- static struct sgttyb mode;
-
- /*
- * set of macros to test requests contained in the chg structure
- * and fill the output buffer on a byte basis in order to save
- * maximum space.
- */
-
- #define IRQST(x) *(k = &chg. x [i].set)
-
- #define STUFFI(x,C) if (stack > top - 4)\
- goto fatal;\
- *stack++ = C | i;\
- v = chg. x [i].vali;\
- *stack++ = v >> 8;\
- *stack++ = v & 0xff;\
- *k = NO;
-
- #define CMDI(x,C) if(IRQST(x)) {STUFFI(x,C)}
-
- #define ARQST(x) *(k = &chg. x .set)
-
- #define STUFFA(x,C) if (stack > top - 14)\
- goto fatal;\
- *stack++ = C;\
- for (i = 0; i < NJOINTS; ++i) {\
- v = chg. x . vala[i];\
- *stack++ = v >> 8;\
- *stack++ = v & 0xff;\
- } *k = NO;
-
- #define CMDA(x,C) if(ARQST(x)) {STUFFA(x,C)}
-
- #define GRQST(x) *(k = &chg. x .set)
-
- #define STUFFG(x,C) if (stack > top - 4)\
- goto fatal;\
- *stack++ = C;\
- v = chg. x .valg;\
- *stack++ = v >> 8;\
- *stack++ = v & 0xff;\
- *k = NO;
-
- #define CMDG(x,C) if(GRQST(x)) {STUFFG(x,C)}
-
- #define RQSTE(x) *(k = &chg. x)
-
- #define STUFFE(C) if (stack > top - 2)\
- goto fatal;\
- *stack++ = C;\
- *k = NO;
-
- #define CMDE(x,C) if (RQSTE(x)) {STUFFE(C)}
-
- /*
- * to avoid the use of the terrible scanf
- */
-
- #define GETCHAR(c) while ((c = getchar()) == ' ' \
- || c == '\t' || c == '\n') ;
-
- #define QUERY(c) GETCHAR(c) \
- while (c != 'y' && c != 'n') { \
- GETCHAR(c); \
- }
-
- /*
- * the pack function is called after execution of the interrupt
- * user function 1 to translate the requests expressed in the
- * chg structure into the communication language understandable
- * by the lsi code.
- * If for a reason or another, the flag terminate is raised,
- * the user interrupt functions will no longer be called and
- * pack will refuse to send anything but a rate command witc neg val which
- * cause the lsi code to stop interrupting the vax and turn off
- * the arm power.
- */
-
-
- static pack() /*::*/
- {
- register int i;
- register unsigned short v;
- register char *k;
- register char *stack = (char *)(obuff + 1); /* for byte count */
- register char *top = (char *)(obuff + COMSIZE);
- register int inc;
- register unsigned short mcc;
-
- if (terminate) {
- terminated: chg.end = YES;
- CMDE(end, END_E)
- goto checksum ;
- }
-
- for (i = 0; i < NJOINTS; ++i) {
- switch (IRQST(i_motion)) {
- case NO :
- break;
-
- case POS :
- inc = chg.i_motion[i].vali - how.pos[i];
- inc = (inc < 0) ? -inc : inc;
- if (checking) {
- if (inc > mvl[i] * rate) {
- goto toofast;
- }
- inc = chg.i_motion[i].vali;
- if (inc > max[i] || inc < min[i]) {
- goto toofar;
- }
- }
- STUFFI(i_motion,POS_I)
- break;
-
- case CUR :
- mcc = chg.i_motion[i].vali;
- mcc = (mcc > 0100000) ? -mcc : mcc;
- if (mcc > mxdc[i]) {
- goto toostrong;
- }
- STUFFI(i_motion,CUR_I)
- break;
-
- case STOP :
- STUFFI(i_motion,STOPP_I);
- break;
-
- case STOPCAL :
- STUFFI(i_motion,STOPM_I);
- break;
- default :
- goto fatal;
- }
- }
-
- switch (ARQST(a_motion)) {
- case NO :
- break;
-
- case POS :
- if (checking) {
- for (i = 0; i < NJOINTS; ++i) {
- inc = chg.a_motion.vala[i] - how.pos[i];
- inc = (inc < 0) ? -inc : inc;
- if (inc > mvl[i] * rate) {
- goto toofast;
- }
- inc = chg.a_motion.vala[i];
- if (inc > max[i] || inc < min[i]) {
- goto toofar;
- }
- }
- }
- STUFFA(a_motion,POS_A)
- break;
-
- case CUR :
- for (i = 0; i < NJOINTS; ++i) {
- mcc = chg.a_motion.vala[i];
- mcc = (mcc > 0100000) ? -mcc : mcc;
- if (mcc > mxdc[i]) {
- goto toostrong;
- }
- }
- STUFFA(a_motion,CUR_A)
- break;
- case STOP :
- STUFFA(a_motion,STOPP_A);
- break;
- case STOPCAL :
- STUFFA(a_motion,STOPM_A);
- break;
- default :
- goto fatal;
- }
-
- CMDG(g_hand, HAND_G)
- #ifdef ADC
- if (chg.g_adco.set) {
- ++nch;
- }
- CMDG(g_adco, ADCO_G)
- #endif
- CMDG(g_rate, RATE_G)
- if (chg.g_rate.set) {
- rate = (1 << chg.g_rate.valg) * HARDCLOCK;
- }
- CMDE(stop, STOP_E)
- CMDE(calib, CALIB_E)
-
- checksum:
- i = stack - (char *)(obuff + 1); /* byte count */
- if (i % 2) {
- i++;
- *stack++ = -1;
- }
-
- if (stack > top - 2) /* room for checksum ?*/
- goto fatal;
-
- return(i); /* return byte count */
-
- fatal :
- stack = (char *)(obuff + 1);
- top = (char *)(obuff + COMSIZE);
- mess = "** too many commands";
- terminate = YES;
- goto terminated;
-
- toofast :
- stack = (char *)(obuff + 1);
- terminate = YES;
- mess = "** too large position increment";
- goto terminated;
-
- toofar :
- stack = (char *)(obuff + 1);
- terminate = YES;
- mess = "** out of range";
- goto terminated;
-
- toostrong :
- stack = (char *)(obuff + 1);
- terminate = YES;
- mess = "** too much current";
- goto terminated;
- }
-
-
- /*
- * - set up the driver
- * - have the SIGINT caught to terminate interaction
- * - have the SIGHUP caught on device error
- *
- * On IT :
- * 1) The driver gets a buffer from the controller
- * 2) User fn1 is called and is meant to process the arm state
- * 3) Commands are put in buffer by pack
- * 3) The driver sends a buffer to the controller (previous commands)
- * 4) User fn2 is called and is meant to compute next command
- *
- * One may code any sequence of 'control-release' in the user programs
- * Each of these sequence corresponds to a sequence
- * 'interrupt/send state/execute commands - turn off armpower in the lsi'
- *
- */
-
- static dummy(){}
-
- #define BAD 2
- #define TOOF 3
-
- static struct drcROBOT drcROBOT = {
- (caddr_t) obuff, /* this write buffer, first word is byte cnt */
- (caddr_t) &how, /* this is read buffer */
- sizeof(how), /* # of bytes to read */
- dummy,
- dummy
- };
-
-
- static int fdr;
- static int (* userfn1)();
- static int (* userfn2)();
- static int exch1 = 0;
- static int exch2 = 0;
- static int hang;
-
- control(fn1, fn2) /*::*/
- int (* fn1)(), (* fn2)();
- {
- int count;
- int release();
- int ondrcerr();
- int onintr1();
- int onintr2();
- int ex;
-
- if (active) {
- terminate = YES;
- mess = "** exit";
- release("** channel not released");
- exit(4);
- }
- userfn1 = fn1;
- userfn2 = fn2;
- drcROBOT.R_routine = onintr1;
- drcROBOT.R_routine2 = onintr2;
-
- (void) signal(SIGINT, release);
- (void) signal(SIGHUP, ondrcerr);
-
- terminate = NO;
- active = YES;
- mess = "";
- ex = exch2 = exch1 = 0;
- rate = (1 << DEFAULTRATE) * HARDCLOCK;
-
- if ((fdr = open("/dev/drc0", 2)) < 0) {
- printf("Can't open /dev/drc0 for write\n");
- exit(1);
- }
- if ((count=write(fdr, (char *)&drcROBOT,
- sizeof (struct drcROBOT))) != sizeof (struct drcROBOT)) {
- printf("write error initing drcROBOT, count:%d\n", count);
- exit(2);
- }
- printf("** channel opened, turn on ARM POWER\n");
- while (exch2 == ex) {
- nap(10);
- }
- }
-
- adcopen(ch) /*::*/
- int ch;
- {
- #ifdef ADC
- if (!active || ch < NJOINTS || ch >= ADC || adcmap[ch] >= 0) {
- return(-1);
- }
- chg.g_adco.set = YES;
- chg.g_adco.valg = ch;
- while (chg.g_adco.set) {
- nap(1);
- }
- return(adcmap[ch] = nch - 1);
- #else
- return(-1);
- #endif
- }
-
-
-
-
- static onintr1()
- {
- register short chks;
- register short *sp;
- register int i;
- register short inc;
- static short old[NJOINTS];
-
- if (inserf) {
- mess = "** interrupt occurred before end of user function";
- terminate = TOOF;
- return;
- }
- inserf = YES;
- if (terminate == TOOF || terminate == BAD) {
- inserf = NO;
- return;
- }
- sp = (short *)how.pos;
- chks = how.exio;
- for (i = 0; i < NJOINTS; ++i) {
- chks += *sp++;
- }
- #ifdef ADC
- for (i = 0; i < nch; ++i) {
- chks += *sp++;
- }
- #endif
- if(*sp != chks) {
- terminate = BAD;
- mess = "** bad checksum";
- return;
- }
- ++exch1;
- if (checking) {
- #ifdef ADC
- for (i = 0; i < NJOINTS; ++i) {
- inc = how.adcr[i];
- inc = (inc < 0) ? -inc : inc;
- if (inc > mxoc[i]) {
- mess = "** too large observed current";
- terminate = YES;
- break;
- }
- }
- #endif
- if (exch1 == 1) {
- for (i = 0; i < NJOINTS; ++i) {
- old[i] = how.pos[i];
- }
- }
- else {
- for (i = 0; i < NJOINTS; ++i) {
- inc = how.pos[i] - old[i];
- inc = (inc < 0) ? -inc : inc;
- if (inc > mvl[i] * rate) {
- mess = "** too large observed velocity";
- terminate = YES;
- break;
- }
- inc = old[i] = how.pos[i];
- if (inc > max[i] || inc < min[i]) {
- mess = "** joint(s) out of range";
- terminate = YES;
- break;
- }
- }
- }
- }
- if (exch1 != 1) {
- if (!(terminate || (hang = !(how.exio & ARMPWR)))) {
- (* userfn1)(); /* process arm state */
- }
- *obuff = pack(); /* byte count */
- i = *obuff / 2;
- chks = 0;
- for (sp = obuff + 1; i--;)
- chks += *sp++;
- *sp = chks;
- *obuff += 2; /* for chks */
- }
- else {
- obuff[0] = 4 + 4 * NJOINTS;
- obuff[1] = VERSION;
- obuff[2] = ARMTYPE;
- for (i = 0; i < NJOINTS; ++i) {
- obuff[3 + i] = ref[i];
- obuff[3 + NJOINTS + i] = idx[i];
- }
- }
- }
-
-
-
- static onintr2()
- {
- if (terminate) {
- inserf = NO;
- return;
- }
- if (!hang) {
- ++exch2;
- (* userfn2)(); /* command arm */
- }
- inserf = NO;
- }
-
-
- static ondrcerr()
- {
- int i;
-
- (void) close(fdr);
- printf("**** driver error...exch1 = %d exch2 = %d\n", exch1, exch2);
- printf("obuff:\n");
- for (i = 0; i < COMSIZE; ++i)
- printf("0x%x ",obuff[i] & 0xffff);
- printf("\nhow:\n");
- printf("exio 0x%x\n", how.exio & 0xffff);
- printf("pos:\n");
- for (i = 0; i < NJOINTS; ++i)
- printf("%u ",how.pos[i] & 0xffff);
- #ifdef ADC
- printf("\nadc :");
- for (i = 0; i < nch; ++i)
- printf(" 0%o\n", how.adcr[i] & 0xffff);
- #endif
- printf("\nterminate %d\n", terminate);
- exit(3);
- }
-
-
- release(s)
- char *s;
- {
- int c;
-
- terminate = YES;
- active = NO;
- nap(10);
- #ifdef ADC
- nch = NJOINTS;
- for (c = NJOINTS; c < ADC; ++c) {
- adcmap[c] = -1;
- }
- #endif
- (void) close(fdr);
- if ((int)s == SIGINT) {
- printf("\n** Interrupted\n");
- printf("%s\n", mess);
- }
- else {
- printf("%s\n", s);
- printf("%s\n", mess);
- }
- printf("** exch1 = %d exch2 = %d\n", exch1, exch2);
- if ((int)s == SIGINT) {
- if (cbrkset) {
- mode.sg_flags &= ~CBREAK;
- ioctl(1, TIOCSETP, &mode);
- }
- printf("** attempt an automatic home return ? ");
- QUERY(c);
- if (c == 'y') {
- home();
- }
- exit(1);
- }
- }
-
-
- /*
- * manual stepping mode
- */
-
- #define GO(x ,y) printf("%c=%c%c" ,'\033' ,' '+x ,' '+y)
-
- #define CALREQ 2
- #define BS '\010'
- #define CR '\015'
- #define MAXMAG 100
- #define HANDSTEP 10
-
- static int enough = NO;
- static int mag = 0;
- static int poshd = 0;
- static unsigned short ideal[NJOINTS];
- static int offset[NJOINTS] = {0, 0, 0, 0, 0, 0};
-
-
-
- stepmode() /*::*/
- {
- int dummy(), soft();
- int c;
- int sig = YES;
-
- enough = NO;
- first = YES;
- checking = NO;
- mag = 0;
- poshd = 0;
- for (c = 0; c < NJOINTS; ++c) {
- offset[c] = 0;
- }
-
- if (gtty(1, &mode) < 0) {
- printf("** can't gtty\n");
- exit(1);
- }
- control(dummy, soft);
- while(first) {
- nap(10);
- }
- mode.sg_flags |= CBREAK;
- ioctl(1, TIOCSETP, &mode);
- cbrkset = YES;
- GO(22, 0);
- printf(
- "faster(.) slower(,) reverse(-) joints[1-6] hand(o/c) exit(return)\n\n");
- printf(
- "** exit ? (y/n) _ calibrate ? (y/n) _ sure ? (y/n) _");
-
- GO(22, 0);
- printf("* ");
- for (c = 0; c < 6 ; ++c) {
- GO(22, ((c + 1) * 8));
- printf("%6u", how.pos[c]);
- }
- while (!enough) {
- putchar(CR);
- putchar(':');
- c = getchar();
- putchar(BS);
- switch (c) {
- case '1' :
- case '2' :
- case '3' :
- case '4' :
- case '5' :
- case '6' :
- offset[c -= '1'] += (sig) ? mag : -mag;
- GO(22, ((c + 1) * 8));
- printf("%6u", how.pos[c]);
- break;
- #ifdef PUMA
- case 'o' :
- poshd = 'o';
- break;
- case 'c' :
- poshd = 'c';
- break;
- #endif
- #ifdef STAN
- case 'o' :
- poshd += HANDSTEP;
- break;
- case 'c' :
- poshd -= HANDSTEP;
- break;
- #endif
- case '.' :
- (mag < MAXMAG) ? ++mag : mag;
- break;
- case ',' :
- (mag) ? --mag : mag;
- break;
- case '-' :
- sig = !sig;
- break;
- case '\n' :
- printf("** exit ? (y/n) ");
- if (getchar() == 'y') {
- printf(" calibrate ? (y/n) ");
- if (getchar() == 'y') {
- printf(" sure ? (y/n) ");
- if (getchar() == 'y') {
- chg.calib = YES;
- enough = CALREQ;
- nap(20);
- }
- else {
- GO(22, 0);
- }
- }
- else {
- printf(" sure ? (y/n) ");
- if (getchar() == 'y') {
- enough = YES;
- }
- else {
- GO(22, 0);
- }
- }
- }
- else {
- GO(22, 1);
- }
- break;
- default :
- break;
- }
- }
- mode.sg_flags &= ~CBREAK;
- ioctl(1, TIOCSETP, &mode);
- cbrkset = NO;
- release("\n** end of step mode");
- checking = YES;
- if (enough == CALREQ) {
- printf("** calibrating\n");
- sleep(5);
- }
- }
-
-
-
- static soft()
- {
- register int i;
-
- if (enough) {
- return;
- }
- if (first) {
- first = NO;
- for (i = 0; i < NJOINTS; ++i) {
- ideal[i] = how.pos[i];
- }
- }
- for (i = 0; i < NJOINTS; ++i) {
- if (how.pos[i] <= MAXMAG) {
- ideal[i] = chg.i_motion[i].vali = 077777;
- chg.i_motion[i].set = STOPCAL;
- }
- if (how.pos[i] >= 65535-MAXMAG) {
- ideal[i] = chg.i_motion[i].vali = 077777;
- chg.i_motion[i].set = STOPCAL;
- }
- if (offset[i] > 0) {
- offset[i] -= mag;
- ideal[i] -= mag;
- }
- if (offset[i] < 0) {
- offset[i] += mag;
- ideal[i] += mag;
- }
- chg.a_motion.vala[i] = ideal[i];
- }
- chg.a_motion.set = POS;
- chg.g_hand.valg = poshd;
- chg.g_hand.set = YES;
- }
-
-
- /*
- * Automatic home position return
- */
-
- #define SMALL 100
- #define STABTIM 50
-
- static home()
- {
- int dummy(), back();
-
- first = YES;
- checking = NO;
- printf("** attempting a home return\n");
- control(dummy, back);
- while (!terminate) {
- nap(10);
- }
- nap(10);
- (void) close(fdr);
- printf("** back home, calibrated\n");
- checking = YES;
- nap(10);
- }
-
-
-
- static back()
- {
- extern struct how how;
- extern struct chg chg;
- extern int terminate;
- static int finish;
- static int count;
- static unsigned short where[NJOINTS],
- inc[NJOINTS],
- half[NJOINTS],
- done[NJOINTS];
- register int i;
-
- if (first) {
- first = NO;
- for (i = 0; i < NJOINTS; ++i) {
- where[i] = how.pos[i];
- if (where[i] > ref[i]) {
- half[i] = (where[i] - ref[i]) / 2 + ref[i];
- half[i] -= SMALL;
- }
- else {
- half[i] = ref[i] - (ref[i] - where[i]) / 2;
- half[i] += SMALL;
- }
- finish = NO;
- count = STABTIM;
- inc[i] = 0;
- }
- }
- if (!finish) {
- for (i = 0, finish = YES; i < NJOINTS; ++i) {
- if (where[i] > ref[i]) {
- done[i] = where[i] - ref[i] < SMALL;
- }
- else {
- done[i] = ref[i] - where[i] < SMALL;
- }
- if (!done[i]) {
- finish = NO;
- }
- }
- }
- else {
- if (--count == 0) {
- terminate = YES;
- }
- }
- for (i = 0; i < NJOINTS; ++i) {
- if (!done[i]) {
- if (where[i] > ref[i]) {
- if (where[i] > half[i]) {
- --inc[i];
- }
- else {
- ++inc[i];
- }
- }
- if (where[i] < ref[i]) {
- if (where[i] < half[i]) {
- ++inc[i];
- }
- else {
- --inc[i];
- }
- }
- }
- else {
- where[i] = ref[i];
- }
- where[i] += inc[i];
- chg.a_motion.vala[i] = where[i];
- }
- chg.a_motion.set = POS;
- }
-