Ndirect.c
Go to the documentation of this file.
00001 /*
00002  * Ndirect.c
00003  *
00004  * Implementation file for direct connection to robot, bypassing the need for
00005  * the Nserver program.
00006  *
00007  * Copyright 1991-1998, Nomadic Technologies, Inc.
00008  *
00009  */
00010 
00011 char cvsid_host_client_Ndirect_c[] = "$Header: /home/cvs/host/client/direct.c,v 1.4 1999/11/12 07:28:19 jake Exp $";
00012 
00013 /* includes */
00014 
00015 #include <arpa/inet.h>
00016 #include <fcntl.h>
00017 #include <termios.h>
00018 #include <signal.h>
00019 #include <memory.h>
00020 #include <errno.h>
00021 #include <netdb.h>
00022 #include <netinet/in.h>
00023 #include <stdarg.h>
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <sys/types.h>          
00027 #include <sys/socket.h>
00028 #include <sys/time.h>           
00029 
00030 #include "Nclient.h"
00031 
00032 /* defines */
00033 
00034 /* from command type.h  */
00035 
00036 #define AC 1
00037 #define SP 2
00038 #define PR 3
00039 #define PA 4
00040 #define VM 5
00041 #define MV 43
00042 #define CT 6
00043 #define GS 7
00044 #define NAK 8
00045 #define ST 9
00046 #define LP 10
00047 #define TK 11
00048 #define DP 12
00049 #define ZR 13
00050 #define CONF_IR 14
00051 #define CONF_SN 15
00052 #define CONF_CP 16
00053 #define CONF_LS 17
00054 #define CONF_TM 18
00055 #define GET_IR 19
00056 #define GET_SN 20
00057 #define GET_RC 21
00058 #define GET_RV 22
00059 #define GET_RA 23
00060 #define GET_CP 24
00061 #define GET_LS 25
00062 #define SETUP_LS 26
00063 #define GET_BP 27
00064 
00065 #define CONF_SG 28
00066 #define GET_SG 29
00067 
00068 #define DA 30
00069 #define WS 31
00070 
00071 #define ADD_OBS 32
00072 #define DELETE_OBS 33
00073 #define MOVE_OBS 34
00074 
00075 #define CONF_SER  35
00076 #define PLACE_ROBOT 36
00077 
00078 #define NUM_COMMANDS 36
00079 
00080 #define SPECIAL 128
00081 
00082 /* error types */
00083 #define SERIAL_OPEN_ERROR 1
00084 #define SERIAL_WRITE_ERROR 2
00085 #define SERIAL_READ_ERROR 3
00086 #define SERIAL_PKG_ERROR 4
00087 #define SERIAL_TIMEOUT_ERROR 5
00088 
00089 /* serial setting */
00090 #define RE_XMIT 0            /* not re-transmit when failed */
00091 #define NORMAL_TIMEOUT     1 /* 1 second */
00092 #define CONNECT_TIMEOUT   10 /* 10 seconds */
00093 #define SPECIAL_TIMEOUT   30 /* used for user define package */
00094 
00095 /* 
00096  * Define the length of the user buffer (Maximal short).
00097  * Due to Protocol bytes, the effective length is 65526 
00098  */
00099 
00100 #define USER_BUFFER_LENGTH      0xFFFF
00101 
00102 /* from pos.h */
00103 
00104 /* 
00105  * these macros enable the user to determine if the pos-attachment
00106  * is desired for a specific sensor, the argument is Smask[ SMASK_POS_DATA ]
00107  * to avoid overlap with Nclient.h suffix I for internal
00108  */
00109 
00110 #define POS_INFRARED_PI(x)  ( ( (x) & POS_INFRARED ) ? 1 : 0 )
00111 #define POS_SONAR_PI(x)     ( ( (x) & POS_SONAR    ) ? 1 : 0 )
00112 #define POS_BUMPER_PI(x)    ( ( (x) & POS_BUMPER   ) ? 1 : 0 )
00113 #define POS_LASER_PI(x)     ( ( (x) & POS_LASER    ) ? 1 : 0 )
00114 #define POS_COMPASS_PI(x)   ( ( (x) & POS_COMPASS  ) ? 1 : 0 )
00115 
00116 
00117 /* from datatype.h */
00118 
00119 /* to build a long out ouf four bytes */
00120 
00121 #define LONG_B(x,y,z,q) ((((x) << 24) & 0xFF000000) | \
00122                          (((y) << 16) & 0x00FF0000) | \
00123                          (((z) <<  8) & 0x0000FF00) | \
00124                          ( (q)        & 0x000000FF) )
00125 
00126 /*
00127  * The voltages have different ranges to account for the fact that the
00128  * CPU measurement is taken after lossage on the slip-ring.
00129  */
00130 
00131 #define RANGE_CPU_VOLTAGE        12.0
00132 #define RANGE_MOTOR_VOLTAGE      12.85
00133 
00134 /********************
00135  *                  *
00136  * Type definitions *
00137  *                  *
00138  ********************/
00139 
00140 /*
00141  * PosDataAll is a struct that contains the Pos information for
00142  * all sensors. It is used to pass/store the Pos info within the 
00143  * server. It contains the laser, although the laser is not
00144  * used in the dual ported ram.
00145  */
00146 
00147 typedef struct _PosDataAll
00148 {
00149   PosData infrared [INFRAREDS];
00150   PosData sonar    [SONARS   ];
00151   PosData bumper;
00152   PosData laser;
00153   PosData compass;
00154 
00155 } PosDataAll;
00156 
00157 
00158 /********************
00159  *                  *
00160  * Global Variables *
00161  *                  *
00162  ********************/
00163 
00164 long State[NUM_STATE];        /* State reading */
00165 int  Smask[NUM_MASK];         /* Sensor mask */
00166 int  Laser[2*NUM_LASER+1];    /* Laser reading */
00167 
00168 
00169 /* connect_type == 1 ---> serial */
00170 /* connect_type == 2 ---> socket */
00171 int    connect_type           = 1;
00172 int    model;
00173 char  *device;
00174 int    conn_value;
00175 int    DEFAULT_SERIAL_BAUD    = 38400;
00176 int    DEFAULT_ROBOT_TCP_PORT = 65001;
00177 double LASER_CALIBRATION[8]   = { -0.003470,  0.000008, 0.011963,  0.001830,
00178                                   27.5535913, 0.000428, 0.031102, -0.444624 };
00179 double LASER_OFFSET[2]        = { 0, 0 };
00180 
00181 /* dummy variables to stay compatible with Nclient.c */
00182 
00183 char   SERVER_MACHINE_NAME[80] = "";
00184 int    SERV_TCP_PORT           = -1;
00185 char   Host_name[255]          = "";
00186 
00187 /*******************
00188  *                 *
00189  * Local Variables *
00190  *                 *
00191  *******************/
00192 
00193 static int             Fd=-1;
00194 static unsigned char   buf[BUFSIZE];
00195 static unsigned char   *bufp, *bufe;
00196 static int             errorp = 0;
00197 static int             wait_time;
00198 static int             usedSmask[NUM_MASK];       /* mask vector */
00199 static int             Robot_id = -1;
00200 
00201 /* although called special, it is the user buffer */
00202 static unsigned char   *special_buffer;
00203 static unsigned short  special_answer_size;
00204 
00205 /* this is where all the incoming posData is stored */
00206 static PosDataAll posDataAll;
00207 static unsigned long posDataTime;
00208 
00209 /* for the voltages of motor/CPU as raw data */
00210 static unsigned char voltageCPU;
00211 static unsigned char voltageMotor;
00212 
00213 /* the laser mode */
00214 static int laser_mode = 51;
00215 
00216 /*******************
00217  *                 *
00218  * Functions (fwd) *
00219  *                 *
00220  *******************/
00221 
00222 /* function declarations */
00223 
00224 int open_serial(char *port, unsigned short baud);
00225 int conf_ser(unsigned char port, unsigned short baud);
00226 static long posLongExtract    ( unsigned char *inbuf );
00227 static unsigned long posUnsignedLongExtract( unsigned char *inbuf );
00228 static int posPackageProcess  ( unsigned char *inbuf, PosData *posData );
00229 static int timePackageProcess ( unsigned char *inbuf, unsigned long *timeS );
00230 static int voltPackageProcess ( unsigned char *inbuf,
00231                                 unsigned char *voltCPU,
00232                                 unsigned char *voltMotor);
00233 static float voltConvert   ( unsigned char reading , float range );
00234 
00235 
00236 
00237 /*******************************************************
00238  *                                                     *
00239  * Helper functions for manipulating bytes and numbers *
00240  *                                                     *
00241  *******************************************************/
00242 
00243 static int low_half(unsigned char num)
00244 {
00245   return (num % 16);
00246 }
00247 
00248 static int high_half(unsigned char num)
00249 {
00250   return (num / 16);
00251 }
00252 
00253 /*
00254 static unsigned char high_byte_signed(int n)
00255 {
00256   int sign_num;
00257   
00258   if (n < 0) sign_num = 128; else sign_num = 0;
00259   return (sign_num + (abs(n) / 256));
00260 }
00261 */
00262 /*
00263 static unsigned char low_byte_signed(int n)
00264 {
00265   return (abs(n) % 256);
00266 }
00267 */
00268 /*
00269 static unsigned char high_byte_unsigned(int n)
00270 {
00271   return (n / 256);
00272 }
00273 */
00274 /*
00275 static unsigned char low_byte_unsigned(int n)
00276 {
00277   return (n % 256);
00278 }
00279 */
00280 static void signed_int_to_two_bytes(int n, unsigned char *byte_ptr)
00281 {
00282   int sign_num;
00283   
00284   *byte_ptr = (unsigned char)(abs(n) % 256);
00285   byte_ptr++;
00286   if (n < 0) sign_num = 128; else sign_num = 0;
00287   *byte_ptr = (unsigned char)(sign_num + (abs(n) / 256));
00288 }
00289 
00290 static void unsigned_int_to_two_bytes(int n, unsigned char *byte_ptr)
00291 {
00292   *byte_ptr = (unsigned char)(abs(n) % 256);
00293   byte_ptr++;
00294   *byte_ptr = (unsigned char)(abs(n) / 256);
00295 }
00296 
00297 static int two_bytes_to_signed_int(unsigned char low_byte,
00298                                    unsigned char high_byte)
00299 {
00300   int num;
00301   
00302   if (high_byte > 127)
00303     num = (-256 * (high_byte - 128)) - low_byte;
00304   else
00305     num = 256 * high_byte + low_byte;
00306   return (num);
00307 }
00308 
00309 static unsigned int two_bytes_to_unsigned_int(unsigned char low_byte,
00310                                               unsigned char high_byte)
00311 {
00312   unsigned int num;
00313   
00314   num = 256 * high_byte + low_byte;
00315   return (num);
00316 }
00317 
00318 static long combine_bumper_vector(unsigned char b1,
00319                                   unsigned char b2,
00320                                   unsigned char b3)
00321 {
00322   long num;
00323   
00324   num = b1 + (b2 * 256) + (b3 * 65536);
00325   return (num);
00326 }
00327 
00328 static unsigned char bits_to_byte(char bt0, char bt1, char bt2, char bt3,
00329                                   char bt4, char bt5, char bt6, char bt7)
00330 {
00331   unsigned char  rbyte;
00332   
00333   rbyte = (unsigned char)(bt0 + (2*bt1) + (4*bt2) + (8*bt3) + (16*bt4) +
00334                           (32*bt5) + (64*bt6) + (128*bt7));
00335   return (rbyte);
00336 }
00337 
00338 static int serial_ready (int fd, int wait)
00339 {
00340   fd_set          lfdvar;
00341   int             ready;
00342   struct timeval  timeout;
00343   
00344   FD_ZERO(&lfdvar);
00345   FD_SET(fd, &lfdvar);
00346   
00347   timeout.tv_sec = wait;
00348   timeout.tv_usec = 0;
00349   
00350   ready = select(fd+1, &lfdvar, NULL, NULL, &timeout);
00351   return(ready);
00352 }
00353 
00354 /* 
00355  * creates a package by adding initial byte, checksum, and end byte
00356  * and send the package to robot
00357  */
00358 static int Write_Pkg(int fd, unsigned char *outbuf)
00359 {
00360   int i, outbufLen, chk_sum; 
00361   int nleft, nwritten;
00362   
00363   /* create a package */
00364   outbuf[0] = 1;
00365   chk_sum = 0;
00366   outbufLen = outbuf[1]+1;
00367   for (i=0; i<=outbufLen; i++)
00368     chk_sum = chk_sum + outbuf[i];
00369   chk_sum = chk_sum % 256;
00370   outbufLen++;
00371   outbuf[outbufLen] = chk_sum;
00372   outbufLen++;
00373   outbuf[outbufLen] = 92;
00374   outbufLen++;
00375 
00376   /* send package */
00377   for (nleft = outbufLen; nleft > 0; ) {
00378     nwritten = write(fd, outbuf, nleft);
00379     if (nwritten <= 0) {
00380       errorp = SERIAL_WRITE_ERROR;
00381       return(FALSE);
00382     }
00383     nleft = nleft - nwritten;
00384     outbuf = outbuf + nwritten;
00385   }
00386   return(TRUE);
00387 }
00388 
00389 
00390 /* 
00391  * read response from the robot 
00392  */
00393 static unsigned char buf_fill(int fd, int conn_type)
00394 {
00395   int n;
00396   
00397   if (conn_type == 1) 
00398   {
00399     n = read(fd, buf, BUFSIZE);
00400     if (n < 0) {
00401       printf("error reading serial port\n");
00402       errorp = SERIAL_READ_ERROR;
00403       return(0);
00404     }
00405     else {
00406       if (n == 0) {
00407         printf("serial port read timeout error\n");
00408         errorp = SERIAL_TIMEOUT_ERROR;
00409         return(0);
00410       }
00411     }
00412   } else {
00413     if (serial_ready(Fd, 100)) {
00414       n = read(Fd, buf, BUFSIZE);
00415       if (n < 0) {
00416         printf("TCP/IP communication broken.\n");
00417         errorp = SERIAL_READ_ERROR;
00418         return 0;
00419       } else {
00420         if (n == 0) {
00421           printf("TCP/IP select/read error\n");
00422           errorp = SERIAL_READ_ERROR;
00423           return(0);
00424         }
00425       }
00426     } else {
00427       printf("TCP/IP read timeout error.\n");
00428       errorp = SERIAL_TIMEOUT_ERROR;
00429       return 0;
00430     }
00431   }
00432   
00433   bufp = &buf[1];
00434   bufe = buf + n;
00435   return(buf[0]);
00436 }
00437 
00438 static unsigned char GETC(int fd, int conn_type)
00439 {
00440   if (bufp<bufe)
00441     return(*bufp++);
00442   return(buf_fill(fd, conn_type));
00443 }
00444 
00445 /*
00446  * getting package from robot and 
00447  * check for package error: initial byte = 1, end byte = 92, check sum
00448  */
00449 static int Read_Pkg(int fd, int conn_type, unsigned char *inbuf)
00450 {
00451   int i, length, chk_sum;
00452   unsigned char ichar, ichar2;
00453 
00454   if (!(serial_ready (fd, wait_time))) {
00455     errorp = SERIAL_TIMEOUT_ERROR;
00456     return(FALSE);
00457   }
00458 
00459   errorp = 0;
00460   
00461   /* read the begin packet character, it should be 1 */
00462   ichar = (unsigned char)GETC(fd, conn_type);
00463   if (!errorp) {
00464     if (ichar != 1) {
00465       printf("start byte error: %u\n", ichar);
00466       errorp = SERIAL_PKG_ERROR;
00467     }
00468     else {
00469       chk_sum = 1;
00470     }
00471   }
00472   
00473   if (!errorp) {
00474     /* read length, it should be >0 */
00475     ichar = GETC(fd, conn_type); 
00476     if (!errorp) {
00477       chk_sum = chk_sum + (int)ichar;
00478     }
00479     ichar2 = GETC(fd, conn_type);
00480     if (!errorp) {
00481       length = two_bytes_to_unsigned_int (ichar, ichar2);
00482       if (length < 1) {
00483         printf("length byte error\n");
00484         errorp = SERIAL_PKG_ERROR;
00485       }
00486       else {
00487         chk_sum = chk_sum + (int)ichar2;
00488       }
00489     }
00490   }
00491   
00492   /* get the data portion of the message */
00493   i = 0;
00494   while ((!errorp) && (i<=length)) {
00495     ichar = GETC(fd, conn_type);
00496     if (!errorp) {
00497       inbuf[i] = ichar;
00498       /* printf("%u\n",  ichar); */
00499       chk_sum = chk_sum + (int)(ichar);
00500     }
00501     i++;
00502   }
00503   
00504   if (!errorp) {
00505     /* check chk_sum and end_pkg */
00506     if (((chk_sum - inbuf[length-1] - 92) % 256) != inbuf[length-1]) {
00507       printf("check sum error\n");
00508       errorp = SERIAL_PKG_ERROR;
00509     }
00510     
00511     if (inbuf[length] != 92) {
00512       printf("packet end error\n");
00513       errorp = SERIAL_PKG_ERROR;
00514     }
00515   }
00516   
00517   if ((errorp) && (errorp != SERIAL_TIMEOUT_ERROR)) {
00518     printf("emptying buffer\n");
00519     buf_fill(Fd, conn_type);  /* read everything else in the serial line into
00520                     buffer */
00521     bufp = bufe; /* and flush it */
00522   }
00523   
00524   if (errorp)
00525     return(FALSE);
00526   else
00527     return (TRUE);
00528 }
00529 
00530 /*********************************************************
00531  *
00532  *   Laser Calibration Stuff 
00533  *
00534  *********************************************************/
00535 
00536 /* Transformation function accordingly to the calibration */
00537 /* xi1 = pixel; yi1 = scanline */
00538 static void ProjectPhy(double xi1, double yi1, double *x, double *y)
00539 {
00540   double xi,yi;
00541   double den;           
00542   
00543   xi = xi1 - 254.5;
00544   yi = yi1 - 240.5; 
00545   
00546   den = (LASER_CALIBRATION[0]*xi + LASER_CALIBRATION[1]*yi + 1);
00547   
00548   *x = (LASER_CALIBRATION[2]*xi + LASER_CALIBRATION[3]*yi +
00549         LASER_CALIBRATION[4])/den + LASER_OFFSET[0];
00550   *y = (LASER_CALIBRATION[5]*xi + LASER_CALIBRATION[6]*yi +
00551         LASER_CALIBRATION[7])/den + LASER_OFFSET[1];
00552 }  
00553 
00554 static void convert_laser(int *laser)
00555 {
00556   int i, num_points, offset, interval;
00557   double line_num;
00558   double laserx[483], lasery[483];
00559   
00560   num_points = laser[0];
00561   interval = NUM_LASER/(num_points-1);
00562   offset = 3 + (NUM_LASER-(num_points * interval))/2;
00563   for (i=1; i<=num_points; i++) {
00564     line_num = (double)(offset+(i-1)*interval);
00565     ProjectPhy((double)laser[i], line_num, &laserx[i], &lasery[i]); 
00566   }
00567   for (i=1; i<=num_points; i++) {
00568     laser[2*i-1] = (int)(laserx[i]*10.0);
00569     laser[2*i] = (int)(lasery[i]*10.0);
00570   }
00571   return;
00572 }
00573 
00574 /*********************************************************
00575  *
00576  *   Processing different types of packages received from the robot 
00577  *
00578  *********************************************************/
00579 
00580 /* process the response received from the robot which
00581    encodes the state of the robot according to the mask */
00582 
00583 static void Process_State_Pkg(unsigned char inbuf[BUFSIZE])
00584 {
00585   int i, byte_count = 1;
00586   int low_half_used = FALSE;
00587   
00588   /* infrared */
00589   for (i = STATE_IR_0 ; i <= STATE_IR_15; i++)
00590     if (usedSmask[i] > 0) 
00591       {
00592         if (low_half_used == FALSE)
00593           {
00594             State[i] = low_half(inbuf[byte_count]);
00595             low_half_used = TRUE;
00596           }
00597         else
00598           {
00599             State[i] = high_half(inbuf[byte_count]);
00600             byte_count++;
00601             low_half_used = FALSE;
00602           }
00603       }
00604   if (low_half_used == TRUE)
00605     byte_count++;
00606   
00607   /*
00608    * if the pos attachment was required we read it
00609    */
00610   
00611   if (POS_INFRARED_PI(usedSmask[SMASK_POS_DATA]))
00612     for (i = 0; i < INFRAREDS; i++)
00613       if (usedSmask[SMASK_IR_1 + i] > 0) 
00614         byte_count += posPackageProcess(&inbuf[byte_count], 
00615                                         &(posDataAll.infrared[i]));
00616   
00617   /* sonars */
00618   for (i = STATE_SONAR_0; i <= STATE_SONAR_15; i++) {
00619     if ( usedSmask[i] > 0 ) 
00620       {
00621         State[i] = inbuf[byte_count];
00622         byte_count++;
00623       }
00624   }
00625   
00626   /*
00627    * if the pos attachment was required we read it
00628    */
00629   
00630   if (POS_SONAR_PI(usedSmask[SMASK_POS_DATA]))
00631     for (i = 0; i < SONARS; i++) 
00632       if (usedSmask[SMASK_SONAR_1 + i] > 0)
00633         byte_count += posPackageProcess(&inbuf[byte_count], 
00634                                         &(posDataAll.sonar[i]));
00635 
00636   if (usedSmask[ SMASK_BUMPER ] > 0)
00637   {
00638     if (model == MODEL_SCOUT)
00639     {
00640       State[ STATE_BUMPER ] = combine_bumper_vector(inbuf[byte_count + 0], 
00641                                                     inbuf[byte_count + 1],
00642                                                     inbuf[byte_count + 2]);
00643     }
00644     else
00645     {
00646       State[ STATE_BUMPER ] = combine_bumper_vector(inbuf[byte_count + 2], 
00647                                                     inbuf[byte_count + 1],
00648                                                     inbuf[byte_count + 0]);
00649     }
00650     
00651     byte_count = byte_count + 3;
00652     
00653     /*
00654      * if the position attachment was requested for the bumper
00655      * we have to unpack the package. 
00656      */
00657     
00658     if (POS_BUMPER_PI(usedSmask[SMASK_POS_DATA]))
00659       byte_count += posPackageProcess(&inbuf[byte_count], 
00660                                       &(posDataAll.bumper));
00661   }
00662   
00663   /* the position data */
00664   
00665   if (usedSmask[SMASK_CONF_X] > 0)
00666   {
00667     State[STATE_CONF_X] =  two_bytes_to_signed_int(inbuf[byte_count],
00668                                                    inbuf[byte_count+1]);
00669     byte_count = byte_count + 2;
00670   }
00671   
00672   if (usedSmask[SMASK_CONF_Y] > 0)
00673   {
00674     State[STATE_CONF_Y] = two_bytes_to_signed_int(inbuf[byte_count],
00675                                                   inbuf[byte_count+1]);
00676     byte_count = byte_count + 2;
00677   }
00678   
00679   if (usedSmask[SMASK_CONF_STEER] > 0)
00680   {
00681     State[STATE_CONF_STEER] = two_bytes_to_signed_int(inbuf[byte_count], 
00682                                                       inbuf[byte_count+1]);
00683     byte_count = byte_count + 2;
00684   }
00685   
00686   if (usedSmask[SMASK_CONF_TURRET] > 0)
00687   {
00688     State[STATE_CONF_TURRET] = two_bytes_to_signed_int(inbuf[byte_count], 
00689                                                        inbuf[byte_count+1]);
00690     byte_count = byte_count + 2;
00691   }
00692   
00693   /* the velocities */
00694   
00695   if (usedSmask[SMASK_VEL_TRANS] > 0)
00696   {
00697     State[STATE_VEL_TRANS] = two_bytes_to_signed_int(inbuf[byte_count], 
00698                                                      inbuf[byte_count+1]);
00699     byte_count = byte_count + 2;
00700   }
00701   
00702   if (usedSmask[SMASK_VEL_STEER] > 0)
00703   {
00704     State[SMASK_VEL_STEER] = two_bytes_to_signed_int(inbuf[byte_count],
00705                                                      inbuf[byte_count+1]);
00706     byte_count = byte_count + 2;
00707   }
00708   
00709   if (usedSmask[SMASK_VEL_TURRET] > 0)
00710   {
00711     State[STATE_VEL_TURRET] = two_bytes_to_signed_int(inbuf[byte_count],
00712                                                       inbuf[byte_count+1]);
00713     byte_count = byte_count + 2;
00714   }
00715   
00716   /* the compass value */
00717 
00718   if (usedSmask[SMASK_COMPASS] > 0)
00719   {
00720     State[STATE_COMPASS] = two_bytes_to_signed_int(inbuf[byte_count],
00721                                                    inbuf[byte_count+1]);
00722     byte_count = byte_count + 2;
00723       
00724     /*
00725      * if the position attachment was requested for the compass
00726      * we have to unpack the package. 
00727      */
00728     
00729     if (POS_COMPASS_PI(usedSmask[SMASK_POS_DATA]))
00730       byte_count += posPackageProcess(&inbuf[byte_count], 
00731                                       &(posDataAll.compass));
00732   }
00733 
00734   /* laser */
00735   if (usedSmask[SMASK_LASER] > 0)
00736   {
00737     /* the number of points */
00738     Laser[0] = two_bytes_to_unsigned_int(inbuf[byte_count],
00739                                          inbuf[byte_count+1]);
00740     byte_count = byte_count + 2;
00741     
00742     /* check the laser mode */
00743     if ((laser_mode&0x1e) == 0) /* Line mode */
00744     {
00745       if (Laser[0] > NUM_LASER/2)
00746       {
00747         printf("error in processing laser reply (1).\n");
00748         errorp = SERIAL_READ_ERROR;
00749         Laser[0] = 0;
00750         return;
00751       }
00752       for (i=1; i<=4*Laser[0]; i++) 
00753       {
00754         Laser[i] = two_bytes_to_signed_int(inbuf[byte_count],
00755                                            inbuf[byte_count+1]);
00756         byte_count = byte_count+2;
00757       }
00758     }
00759     else /* Points of some kind */
00760     {
00761       if (Laser[0] > NUM_LASER) 
00762       {
00763         printf("error in processing laser reply (2).\n");
00764         errorp = SERIAL_READ_ERROR;
00765         Laser[0] = 0;
00766         return;
00767       }
00768       for (i=1; i<=Laser[0]; i++) 
00769       {
00770         Laser[i] = two_bytes_to_unsigned_int(inbuf[byte_count],
00771                                              inbuf[byte_count+1]);
00772         byte_count = byte_count+2;
00773       }
00774     }
00775     if ((laser_mode&0x1e) == 19)
00776       convert_laser(Laser);
00777     
00778     /*
00779      * if the position attachment was requested for the laser
00780      * we have to get it from somewhere else 
00781      */
00782     
00783     if (POS_LASER_PI(usedSmask[SMASK_POS_DATA]))
00784       byte_count += posPackageProcess(&inbuf[byte_count], 
00785                                       &(posDataAll.laser));
00786   }
00787   /* motor active */
00788   State[STATE_MOTOR_STATUS] = (long)inbuf[byte_count++];  
00789 
00790   /* process the 6811 time */
00791   byte_count += timePackageProcess(&inbuf[byte_count], &posDataTime);
00792 
00793   /* process the voltages of motor/CPU */
00794   byte_count += voltPackageProcess(&inbuf[byte_count], 
00795                                    &voltageCPU, &voltageMotor);
00796 }
00797 
00798 /* process the response from the robot which encodes the
00799    active infrared reading */
00800 
00801 static void Process_Infrared_Pkg(unsigned char inbuf[BUFSIZE])
00802 {
00803   int i, byte_count = 1;
00804   int low_half_used = FALSE;
00805 
00806   /* 
00807    * the ir datum from one sensor is only a nibble, 
00808    * two of them are merged into one byte 
00809    */
00810   
00811   for (i = STATE_IR_0 ; i <=  STATE_IR_15; i++)
00812     if (low_half_used == FALSE) 
00813       {
00814         State[i] = low_half(inbuf[byte_count]);
00815         low_half_used = TRUE;
00816       }
00817     else 
00818       {
00819         State[i] = high_half(inbuf[byte_count]);
00820         byte_count++;
00821         low_half_used = FALSE;
00822       }
00823 
00824   /* align with next byte */
00825   if ( low_half_used )
00826     byte_count++;
00827 
00828   /*
00829    * if the pos attachment was required we read it
00830    */
00831 
00832   if ( POS_INFRARED_PI ( usedSmask[ SMASK_POS_DATA ] ) )
00833   {
00834     for (i=0; i<16; i++)
00835       byte_count += posPackageProcess ( &inbuf[byte_count], 
00836                                         &( posDataAll.infrared[i] ) );
00837   }
00838 
00839   /* extract the time data for the 6811 */
00840   byte_count += timePackageProcess ( &inbuf[byte_count], &posDataTime );
00841 }
00842 
00843 /* process the response from the robot which encodes the
00844    active sonar reading */
00845 
00846 static void Process_Sonar_Pkg(unsigned char inbuf[BUFSIZE])
00847 {
00848   int i, byte_count = 1;
00849 
00850   /*
00851    * read the sensory data from the buffer
00852    */
00853 
00854   for (i = STATE_SONAR_0; i <= STATE_SONAR_15; i++) 
00855     {
00856       State[i] = inbuf[byte_count];
00857       byte_count++;
00858     }
00859 
00860   /*
00861    * if the pos attachment was required we read it
00862    */
00863 
00864   if ( POS_SONAR_PI ( usedSmask[ SMASK_POS_DATA ]) )
00865     for (i=0; i<16; i++) 
00866       byte_count += posPackageProcess ( &inbuf[byte_count], 
00867                                         &( posDataAll.sonar[i] ) );
00868     
00869   /* extract the time data for the 6811 */
00870   byte_count += timePackageProcess ( &inbuf[byte_count], &posDataTime );
00871 }
00872 
00873 /* process the response from the robot which encodes the
00874    configuration of the robot */
00875 
00876 static void Process_Configuration_Pkg(unsigned char inbuf[BUFSIZE])
00877 {
00878   int byte_count = 1;
00879   
00880   State[ STATE_CONF_X ] = two_bytes_to_signed_int(inbuf[byte_count],
00881                                                   inbuf[byte_count+1]);
00882   byte_count = byte_count + 2;
00883   
00884   State[ STATE_CONF_Y ] = two_bytes_to_signed_int(inbuf[byte_count],
00885                                                   inbuf[byte_count+1]);
00886   byte_count = byte_count + 2;
00887   
00888   State[ STATE_CONF_STEER ] = two_bytes_to_signed_int(inbuf[byte_count],
00889                                                       inbuf[byte_count+1]);
00890   byte_count = byte_count + 2;
00891   
00892   State[ STATE_CONF_TURRET ] = two_bytes_to_signed_int(inbuf[byte_count],
00893                                                        inbuf[byte_count+1]);
00894 }
00895 
00896 static void Process_Velocity_Pkg(unsigned char inbuf[BUFSIZE])
00897 {
00898   int byte_count = 1;
00899   
00900   State[ STATE_VEL_TRANS ] = two_bytes_to_signed_int(inbuf[byte_count],
00901                                                      inbuf[byte_count+1]);
00902   byte_count = byte_count + 2;
00903   
00904   State[ STATE_VEL_STEER ] = two_bytes_to_signed_int(inbuf[byte_count],
00905                                                      inbuf[byte_count+1]);
00906   byte_count = byte_count + 2;
00907   
00908   State[ STATE_VEL_TURRET ] = two_bytes_to_signed_int(inbuf[byte_count],
00909                                                       inbuf[byte_count+1]);
00910 }
00911 
00912 static void Process_Acceleration_Pkg(unsigned char inbuf[BUFSIZE])
00913 {
00914 }
00915 
00916 /* process the response from the robot which encodes the
00917    compass reading of the robot */
00918 
00919 static void Process_Compass_Pkg(unsigned char inbuf[BUFSIZE])
00920 {
00921   int byte_count = 1;
00922   
00923   State[ STATE_COMPASS ] = two_bytes_to_unsigned_int(inbuf[byte_count],
00924                                                      inbuf[byte_count+1]);
00925   byte_count +=2;
00926 
00927   /*
00928    * if the position attachment was requested for the compass
00929    * we have to unpack the package. 
00930    */
00931 
00932   if ( POS_COMPASS_PI ( usedSmask[ SMASK_POS_DATA ] ) )
00933     byte_count += posPackageProcess ( &inbuf[byte_count], 
00934                                       &( posDataAll.compass ) );
00935 
00936   /* extract the time data for the 6811 */
00937   byte_count += timePackageProcess ( &inbuf[byte_count], &posDataTime );
00938 }
00939 
00940 /* process the response from the robot which encodes the
00941    compass reading of the robot */
00942 
00943 static void Process_Compass_Conf_Pkg(unsigned char inbuf[BUFSIZE])
00944 {
00945   int byte_count = 1;
00946   
00947   printf("compass calibration score x: %d y: %d z: %d\n",
00948          inbuf[byte_count], 
00949          inbuf[byte_count+1], 
00950          inbuf[byte_count+2]);
00951 }
00952 
00953 /* process the response from the robot which encodes the
00954    bumper reading of the robot */
00955 
00956 static void Process_Bumper_Pkg(unsigned char inbuf[BUFSIZE])
00957 {
00958   int byte_count = 1;
00959   
00960   if (model == MODEL_SCOUT)
00961   {
00962     State[ STATE_BUMPER ] = combine_bumper_vector(inbuf[byte_count + 0], 
00963                                                   inbuf[byte_count + 1],
00964                                                   inbuf[byte_count + 2]);
00965   }
00966   else
00967   {
00968     State[ STATE_BUMPER ] = combine_bumper_vector(inbuf[byte_count + 2], 
00969                                                   inbuf[byte_count + 1],
00970                                                   inbuf[byte_count + 0]);
00971   }
00972   
00973   byte_count +=3;
00974 
00975   /*
00976    * if the position attachment was requested for the bumper
00977    * we have to unpack the package. 
00978    */
00979 
00980   if ( POS_BUMPER_PI ( usedSmask[ SMASK_POS_DATA ] ) )
00981     byte_count += posPackageProcess ( &inbuf[byte_count], 
00982                                       &( posDataAll.bumper ) );
00983 
00984   /* extract the time data for the 6811 */
00985   byte_count += timePackageProcess ( &inbuf[byte_count], &posDataTime );
00986 }
00987 
00988 static void Process_Laser_Point_Pkg(unsigned char inbuf[BUFSIZE])
00989 {
00990   int i, byte_count = 1;
00991   
00992   Laser[0]=two_bytes_to_unsigned_int(inbuf[byte_count],inbuf[byte_count+1]);
00993   byte_count = byte_count+2;
00994   for (i=1; i<=Laser[0]; i++) {
00995     Laser[i] = two_bytes_to_signed_int(inbuf[byte_count], inbuf[byte_count+1]);
00996     byte_count = byte_count+2;
00997   }
00998   convert_laser(Laser);
00999 
01000   Laser[0] = inbuf[byte_count] + 256 * inbuf[byte_count+1];
01001   byte_count = byte_count + 2;
01002   
01003   if ( Laser[0] > NUM_LASER ) {
01004     printf("error in processing laser point reply\n");
01005     errorp = SERIAL_READ_ERROR;
01006     Laser[0] = 0;
01007     return;
01008   }
01009   for (i=1; i<=Laser[0]; i++) {
01010     Laser[i] = two_bytes_to_unsigned_int(inbuf[byte_count], 
01011                                          inbuf[byte_count+1]);
01012     byte_count = byte_count+2;
01013   }
01014   if ((laser_mode == 51) || (laser_mode == 50) || (laser_mode == 19))
01015     convert_laser(Laser);
01016 
01017   /*
01018    * if the position attachment was requested for the laser
01019    * we have to unpack the package. 
01020    */
01021 
01022   if ( POS_LASER_PI ( usedSmask[ SMASK_POS_DATA ] ) )
01023     byte_count += posPackageProcess ( &inbuf[byte_count], 
01024                                       &( posDataAll.laser ) );
01025 
01026   /* extract the time data for the 6811 */
01027   byte_count += timePackageProcess ( &inbuf[byte_count], &posDataTime );
01028 }
01029 
01030 static void Process_Laser_Line_Pkg(unsigned char inbuf[BUFSIZE])
01031 { 
01032   int i, byte_count = 1;
01033   
01034   Laser[0] = inbuf[byte_count] + 256 * inbuf[byte_count+1];
01035   byte_count = byte_count + 2;
01036 
01037   if (Laser[0] > NUM_LASER) {
01038     printf("error in processing laser line reply\n");
01039     errorp = SERIAL_READ_ERROR;
01040     Laser[0] = 0;
01041     return;
01042   }
01043   for (i=1; i<=4*Laser[0]; i++) {
01044     Laser[i] = two_bytes_to_signed_int(inbuf[byte_count], 
01045                                        inbuf[byte_count+1]);
01046     byte_count = byte_count+2;
01047   }
01048 
01049   /*
01050    * if the position attachment was requested for the laser
01051    * we have to unpack the package. 
01052    */
01053 
01054   if ( POS_LASER_PI ( usedSmask[ SMASK_POS_DATA ] ) )
01055     byte_count += posPackageProcess ( &inbuf[byte_count], 
01056                                       &( posDataAll.laser ) );
01057 
01058   /* extract the time data for the 6811 */
01059   byte_count += timePackageProcess ( &inbuf[byte_count], &posDataTime );
01060 }
01061 
01062 /* process the response from the robot which encodes special information */
01063 
01064 static void Process_Special_Pkg(unsigned char inbuf[BUFSIZE])
01065 {
01066   int data_size, i, byte_count = 1;
01067   
01068   data_size = two_bytes_to_unsigned_int(inbuf[1],inbuf[2]);
01069   special_answer_size = ( unsigned short ) data_size;
01070 
01071   if (data_size > MAX_USER_BUF) 
01072     data_size = MAX_USER_BUF;
01073 
01074   if ( special_buffer != (unsigned char *)NULL)
01075     {
01076       for (i=0; i<data_size; i++) 
01077         {
01078           special_buffer[i] = inbuf[i+1];
01079           byte_count++;
01080         }
01081     }
01082   else
01083     printf("Data buffer for user package is NULL pointer\n");
01084 }
01085 
01086 static int Process_Robot_Resp(unsigned char inbuf[BUFSIZE])
01087 {
01088   switch (inbuf[0]) { /* type of the returned package */
01089   case AC:
01090   case SP:
01091   case PR:
01092   case PA:
01093   case VM:
01094   case MV:
01095   case CT:
01096   case GS:
01097   case ST:
01098   case LP:
01099   case DP:
01100   case DA:
01101   case WS:
01102   case ZR:
01103   case TK:
01104   case CONF_IR:
01105   case CONF_SN:
01106   case CONF_LS:
01107   case CONF_TM:
01108   case CONF_SG:
01109   case CONF_SER:
01110   case SETUP_LS:
01111     Process_State_Pkg(inbuf);
01112     break;
01113   case CONF_CP:
01114     Process_Compass_Conf_Pkg(inbuf);
01115     break;
01116   case NAK: /* Nak */
01117     printf("Nak\n");
01118     break;
01119   case GET_IR: /* Infrared */
01120     Process_Infrared_Pkg(inbuf);
01121     break;
01122   case GET_SN: /* Sonar */
01123     Process_Sonar_Pkg(inbuf);
01124     break;
01125   case GET_RC: /* Configuration */
01126     Process_Configuration_Pkg(inbuf);
01127     break;
01128   case GET_RV: /* Velocity */
01129     Process_Velocity_Pkg(inbuf);
01130     break;
01131   case GET_RA: /* Acceleration */
01132     Process_Acceleration_Pkg(inbuf);
01133     break;
01134   case GET_CP: /* Compass */
01135     Process_Compass_Pkg(inbuf);
01136     break;
01137   case GET_LS: /* Laser */
01138     Process_Laser_Point_Pkg(inbuf);
01139     break;
01140   case GET_BP: /* Bumper */
01141     Process_Bumper_Pkg(inbuf);
01142     break;
01143   case GET_SG: /* Laser line mode */
01144     Process_Laser_Line_Pkg(inbuf);
01145     break;
01146   case SPECIAL: /* User */
01147     Process_Special_Pkg(inbuf);
01148     break;
01149   default:
01150     printf("Invalid Robot Response\n");
01151     return(FALSE);
01152     break;
01153   }
01154   return(TRUE);
01155 }
01156 
01157 static int Comm_Robot(int fd, unsigned char command[BUFSIZE])
01158 {
01159   unsigned char response[BUFSIZE];
01160   int respondedp;
01161   int re_xmitp, i;
01162   fd_set          lfdvar;
01163   struct timeval  timeout;
01164 
01165   if (fd == -1) {
01166     fprintf(stderr,
01167             "Trying again to reestablish connection with the robot...\n"
01168             "                          ");
01169     fflush(stderr);
01170     for (i = 0; (i < 2) &&
01171          (connect_robot(Robot_id, model, device, conn_value) == FALSE);
01172          i++)
01173     {
01174       sleep(5);
01175       fprintf(stderr, "Trying again...           ");
01176       fflush(stderr);
01177     }
01178     if (i == 2 &&
01179         connect_robot(Robot_id, model, device, conn_value) == FALSE)
01180     {
01181       fprintf(stderr, "Failed to reestablish connection.  Command aborted.\n");
01182       return FALSE;
01183     }
01184     fprintf(stderr, "Successful!  Continuing with command.\n");
01185   }
01186   re_xmitp = RE_XMIT;
01187   FD_ZERO(&lfdvar);
01188   FD_SET(fd, &lfdvar);
01189   
01190   timeout.tv_sec = 0;
01191   timeout.tv_usec = 0;
01192   
01193   while (select(fd+1, &lfdvar, NULL, NULL, &timeout) != 0)
01194   {
01195     /* Flush buffer */
01196     respondedp = read(fd, response, BUFSIZE);
01197     /* Check for errors, such as lost connection. */
01198     if (respondedp <= 0 && errno != EWOULDBLOCK)
01199     {
01200       close(fd);
01201       Fd = -1;
01202       fprintf(stderr,
01203               "Lost communication with robot.\nAttempting to reconnect...");
01204       fflush(stderr);
01205       for (i = 0; (i < 2) &&
01206            (connect_robot (Robot_id, model, device, conn_value) == FALSE);
01207            i++)
01208       {
01209         sleep(5);
01210         fprintf(stderr, "Trying again...           ");
01211         fflush(stderr);
01212       }
01213       if (i == 2 &&
01214           connect_robot (Robot_id, model, device, conn_value) == FALSE)
01215       {
01216         fprintf(stderr, "Unable to reconnect to robot.  Command aborted.\n");
01217         return FALSE;
01218       }
01219       else
01220       {
01221         fprintf(stderr, "Successful!  Continuing with command.\n");
01222       }
01223     }
01224   }
01225   
01226   Write_Pkg(fd, command);
01227   while (!(respondedp = Read_Pkg(fd, connect_type, response)) && (RE_XMIT)) {
01228     Write_Pkg(fd, command);
01229   }
01230   if (!respondedp) {
01231     printf("Last command packet transmitted:\n");
01232     for (i = 0; i < command[1]+4; i++)
01233       printf("%2.2x ", command[i]);
01234     printf("\n");
01235 
01236     return(FALSE);
01237   }
01238   else {
01239     if (Process_Robot_Resp (response)) {
01240       return(TRUE);
01241     }
01242     else {
01243       printf("error in robot response\n");
01244       return(FALSE); 
01245     }
01246   }
01247 }
01248 
01249 /************************************
01250  *                                  *
01251  * Robot Serial Interface Functions *
01252  *                                  *
01253  ************************************/
01254 
01255 /* 
01256  * First some helper functions 
01257  */
01258 void stuff_length_type(int length, int ptype, unsigned char *byte_ptr);
01259 void stuff_length_type(int length, int ptype, unsigned char *byte_ptr)
01260 {
01261      byte_ptr++; /* skip the first byte of the buffer, which is 
01262                     reserved for begin_pkg character */
01263 
01264      unsigned_int_to_two_bytes(length, byte_ptr);
01265      byte_ptr++; byte_ptr++;
01266      *byte_ptr = ptype;
01267 }
01268 
01269 void stuff_two_signed_int(int length, int ptype, int num1, int num2,
01270                           unsigned char *byte_ptr);
01271 void stuff_two_signed_int(int length, int ptype, int num1, int num2,
01272                           unsigned char *byte_ptr)
01273 {
01274      byte_ptr++; /* skip the first byte of the buffer, which is 
01275                     reserved for begin_pkg character */
01276 
01277      unsigned_int_to_two_bytes(length, byte_ptr);
01278      byte_ptr++; byte_ptr++;
01279      *byte_ptr = ptype;
01280      byte_ptr++;
01281      signed_int_to_two_bytes(num1, byte_ptr);
01282      byte_ptr++; byte_ptr++;
01283      signed_int_to_two_bytes(num2, byte_ptr);
01284 }
01285 
01286 void stuff_three_unsigned_int(int length, int ptype, int num1, int num2,
01287                               int num3, unsigned char *byte_ptr);
01288 void stuff_three_unsigned_int(int length, int ptype, int num1, int num2,
01289                               int num3, unsigned char *byte_ptr)
01290 {
01291      byte_ptr++; /* skip the first byte of the buffer, which is 
01292                     reserved for begin_pkg character */
01293 
01294      unsigned_int_to_two_bytes(length, byte_ptr);
01295      byte_ptr++; byte_ptr++;
01296      *byte_ptr = ptype;
01297      byte_ptr++;
01298      unsigned_int_to_two_bytes(num1, byte_ptr);
01299      byte_ptr++; byte_ptr++;
01300      unsigned_int_to_two_bytes(num2, byte_ptr);
01301      byte_ptr++; byte_ptr++;
01302      unsigned_int_to_two_bytes(num3, byte_ptr);
01303 }
01304 
01305 void stuff_three_signed_int(int length, int ptype, int num1, int num2,
01306                             int num3, unsigned char *byte_ptr);
01307 void stuff_three_signed_int(int length, int ptype, int num1, int num2,
01308                             int num3, unsigned char *byte_ptr)
01309 {
01310      byte_ptr++; /* skip the first byte of the buffer, which is 
01311                     reserved for begin_pkg character */
01312 
01313      unsigned_int_to_two_bytes(length, byte_ptr);
01314      byte_ptr++; byte_ptr++;
01315      *byte_ptr = ptype;
01316      byte_ptr++;
01317      signed_int_to_two_bytes(num1, byte_ptr);
01318      byte_ptr++; byte_ptr++;
01319      signed_int_to_two_bytes(num2, byte_ptr);
01320      byte_ptr++; byte_ptr++;
01321      signed_int_to_two_bytes(num3, byte_ptr);
01322 }
01323 
01324 /***************
01325  * FUNCTION:     posLongExtract
01326  * PURPOSE:      compose a long out of four bytes
01327  * ARGUMENTS:    unsigned char *inbuf : the pointer to the four bytes
01328  * ALGORITHM:    bit manipulation
01329  * RETURN:       long
01330  * SIDE EFFECT:  
01331  * CALLS:        
01332  * CALLED BY:    
01333  ***************/
01334 static long posLongExtract( unsigned char *inbuf )
01335 {
01336   long tmp;
01337   
01338   tmp = (long) LONG_B(inbuf[3],inbuf[2],inbuf[1],inbuf[0]);
01339   
01340   if ( tmp & (1L << 31) )
01341     return ( -(tmp & ~(1L << 31) ) );
01342   else
01343     return ( tmp );
01344 }
01345 
01346 
01347 /***************
01348  * FUNCTION:     posUnsignedLongExtract
01349  * PURPOSE:      compose an unsigned long out of four bytes
01350  * ARGUMENTS:    unsigned char *inbuf : the pointer to the four bytes
01351  * ALGORITHM:    bit manipulation
01352  * RETURN:       usigned long
01353  * SIDE EFFECT:  
01354  * CALLS:        
01355  * CALLED BY:    
01356  ***************/
01357 static unsigned long posUnsignedLongExtract( unsigned char *inbuf )
01358 {
01359   return ( (unsigned long) LONG_B(inbuf[3],inbuf[2],inbuf[1],inbuf[0]) );
01360 }
01361 
01362 
01363 /***************
01364  * FUNCTION:     posPackageProcess
01365  * PURPOSE:      processes the part of the package with pos information
01366  * ARGUMENTS:    unsigned char *inbuf : pointer to the data in chars
01367  *               PosData *posData : this is were the posData are written to
01368  * ALGORITHM:    regroup the bytes and assign variables
01369  * RETURN:       int (the number of bytes read from the buffer)
01370  * SIDE EFFECT:  
01371  * CALLS:        
01372  * CALLED BY:    
01373  ***************/
01374 static int posPackageProcess ( unsigned char *inbuf, PosData *posData )
01375 {
01376   int i = 0;
01377 
01378   /* copy the stuff from the buffer into the posData for the current robot */
01379   posData->config.configX      = posLongExtract(inbuf + i++ * sizeof(long));
01380   posData->config.configY      = posLongExtract(inbuf + i++ * sizeof(long));
01381   posData->config.configSteer  = posLongExtract(inbuf + i++ * sizeof(long));
01382   posData->config.configTurret = posLongExtract(inbuf + i++ * sizeof(long));
01383   posData->config.velTrans     = posLongExtract(inbuf + i++ * sizeof(long));
01384   posData->config.velSteer     = posLongExtract(inbuf + i++ * sizeof(long));
01385   posData->config.velTurret    = posLongExtract(inbuf + i++ * sizeof(long));
01386   posData->config.timeStamp    = posUnsignedLongExtract(inbuf + i++ * 
01387                                                         sizeof(long));
01388   posData->timeStamp           = posUnsignedLongExtract(inbuf + i++ * 
01389                                                         sizeof(long));
01390   
01391   return ( i * sizeof(long) );
01392 }
01393 
01394 
01395 /***************
01396  * FUNCTION:     timePackageProcess
01397  * PURPOSE:      processes the part of the package with the 6811 time
01398  * ARGUMENTS:    unsigned char *inbuf : pointer to the data in chars
01399  *               unsigned long *time : this is were the time is written to
01400  * ALGORITHM:    ---
01401  * RETURN:       static int 
01402  * SIDE EFFECT:  
01403  * CALLS:        
01404  * CALLED BY:    
01405  ***************/
01406 static int timePackageProcess ( unsigned char *inbuf, unsigned long *timeS )
01407 {
01408   *timeS = posUnsignedLongExtract( inbuf );
01409 
01410   return ( 4 );
01411 }
01412 
01413 
01414 /***************
01415  * FUNCTION:     voltPackageProcess
01416  * PURPOSE:      processes the part of the package with the voltages
01417  * ARGUMENTS:    unsigned char *inbuf : pointer to the data in chars
01418  *               unsigned long *time : this is were the time is written to
01419  * ALGORITHM:    ---
01420  * RETURN:       static int 
01421  * SIDE EFFECT:  
01422  * CALLS:        
01423  * CALLED BY:    
01424  ***************/
01425 static int voltPackageProcess ( unsigned char *inbuf, 
01426                                 unsigned char *voltCPU,
01427                                 unsigned char *voltMotor)
01428 {
01429   int i = 0;
01430 
01431   /* read the raw voltages out of the buffer */
01432   *voltCPU   = *(inbuf + i++);
01433   *voltMotor = *(inbuf + i++);
01434   
01435   return ( i );
01436 }
01437 
01438 /*****************************
01439  *                           *
01440  * Robot Interface Functions *
01441  *                           *
01442  *****************************/
01443 
01444 /*
01445  * dummy function to maintain compatibility with Nclient
01446  *
01447  * create_robot - requests the server to create a robot with
01448  *                id = robot_id and establishes a connection with
01449  *                the robot. This function is disabled in this
01450  *                version of the software.
01451  * 
01452  * parameters:
01453  *    long robot_id -- id of the robot to be created. The robot
01454  *                     will be referred to by this id. If a process
01455  *                     wants to talk (connect) to a robot, it must
01456  *                     know its id.
01457  */
01458 int create_robot ( long robot_id )
01459 {
01460   Robot_id = robot_id;
01461   return ( TRUE );
01462 }
01463 
01464 /* Helper function for connect_robot */
01465 static char *convertAddr ( char *name, char *addr )
01466 {
01467   int addrInt[10];
01468 
01469   sscanf(name, "%d.%d.%d.%d", 
01470          &(addrInt[0]), &(addrInt[1]), &(addrInt[2]), &(addrInt[3]));
01471   addr[0] = addrInt[0];
01472   addr[1] = addrInt[1];
01473   addr[2] = addrInt[2];
01474   addr[3] = addrInt[3];
01475   return ( addr );
01476 }
01477 
01478 int open_serial(char *port, unsigned short baud)
01479 {
01480   struct termios info;  
01481 
01482   if (Fd != -1)
01483     close(Fd);
01484   if ((Fd=open(port, O_RDWR|O_NONBLOCK)) < 0)
01485     {
01486       perror("Error opening serial port");
01487       return 0;
01488     }
01489   
01490   if (tcgetattr(Fd, &info) < 0) 
01491     {
01492       perror("Error using TCGETS in ioctl.");
01493       close(Fd);
01494       Fd = -1;
01495       return 0;
01496     }
01497   
01498   /* restore old values to unhang the bastard, if hung */
01499   info.c_iflag=1280;
01500   info.c_oflag=5;
01501   info.c_cflag=3261;
01502   info.c_lflag=35387;
01503   
01504   if (tcsetattr(Fd, TCSANOW, &info) < 0) 
01505     { 
01506       perror("Error using TCSETS in ioctl.");
01507       close(Fd);
01508       Fd = -1;
01509       return 0;
01510     } 
01511   close(Fd);
01512   
01513   if ((Fd = open(port, O_RDWR)) == -1) {
01514     perror("Error opening serial port");
01515     errorp = SERIAL_OPEN_ERROR;
01516     return(FALSE);
01517   }
01518   
01519   if (tcgetattr(Fd,&info) < 0) {
01520     perror("Error using TCGETS in ioctl.");
01521     errorp = SERIAL_OPEN_ERROR;
01522     close(Fd);
01523     Fd = -1;
01524     return(FALSE);
01525   }
01526   
01527   if (baud != 4800 && baud != 9600 && baud != 19200 && baud != 38400)
01528   {
01529     if (baud != 0)
01530     {
01531       fprintf(stderr, "Invalid baud rate %d, using %d\n", baud,
01532               DEFAULT_SERIAL_BAUD);
01533     }
01534     baud = DEFAULT_SERIAL_BAUD;
01535   }
01536   
01537   info.c_iflag = 0;
01538   info.c_oflag = 0;
01539   info.c_lflag = 0;
01540   switch (baud) { /* serial port rate */
01541   case 4800:
01542     info.c_cflag = B4800 | CS8 | CREAD | CLOCAL;
01543     break;
01544   case 9600:
01545     info.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
01546     break;
01547   case 19200:
01548     info.c_cflag = B19200 | CS8 | CREAD | CLOCAL;
01549     break;
01550   case 38400:
01551     info.c_cflag = B38400 | CS8 | CREAD | CLOCAL;
01552     break;
01553   default:
01554     break;
01555   }
01556   /* set time out on serial read */
01557 #if 1
01558   info.c_cc[VMIN] = 0;
01559   info.c_cc[VTIME] = 10;
01560 #endif 
01561   wait_time = NORMAL_TIMEOUT;
01562   
01563   if (tcsetattr(Fd,TCSANOW,&info) < 0) { 
01564     perror("Error using TCSETS in ioctl.");
01565     errorp = SERIAL_OPEN_ERROR;
01566     close(Fd);
01567     Fd = -1;
01568     return(FALSE);
01569   }
01570   
01571   printf("Robot <-> Host serial communication setup\n");
01572   printf("(%d baud using %s)\n", baud, port);
01573   return 1;
01574 }
01575 
01576 /*
01577  * connect_robot - requests the server to connect to the robot
01578  *                 with id = robot_id. In order to talk to the server,
01579  *                 the SERVER_MACHINE_NAME and SERV_TCP_PORT must be
01580  *                 set properly. If a robot with robot_id exists,
01581  *                 a connection is established with that robot. If
01582  *                 no robot exists with robot_id, no connection is
01583  *                 established. In this single robot version, the robot_id
01584  *                 is unimportant. You can call connect_robot with any
01585  *                 robot_id, it will connect to the robot.
01586  *
01587  * parameters:
01588  *    long robot_id -- robot's id. In this multiple robot version, in order
01589  *                     to connect to a robot, you must know it's id.
01590  *         model    -- robot type: 0 = Nomad 200, 1 = Nomad 150, 2 = Scout
01591  *         *dev     -- hostname for TCP, device file for serial ("/dev/" prefix
01592  *                     or ":" suffix means serial)
01593  *         conn     -- TCP port for TCP, baud rate for serial
01594  */
01595 int connect_robot(long robot_id, ...)
01596 {
01597   static char first = 1;
01598   struct hostent *hp;
01599   struct sockaddr_in serv_addr;
01600   int ret, retlen, i;
01601   unsigned char ir_mask[16],sn_mask[16],cf_mask[4],vl_mask[3];
01602   unsigned char cp_mask,bp_mask,ls_mask,pos_mask, byte;
01603   char addr[10];
01604 
01605   va_list args;
01606   
01607   if (first)
01608   {
01609     fprintf(stderr, "Ndirect version 2.7\n");
01610     fprintf(stderr, "Copyright 1991-1998, Nomadic Technologies, Inc.\n");
01611     first = 0;
01612   }
01613   
01614   va_start(args, robot_id);
01615   model = va_arg(args, int);
01616   device = va_arg(args, char *);
01617   conn_value = va_arg(args, int);
01618   if (strncmp(device, "/dev", 4) != 0 && device[strlen(device)-1] != ':')
01619   {
01620     connect_type = 2;
01621   }
01622   va_end(args);
01623   
01624   if (connect_type == 1) 
01625   {
01626     open_serial(device, conn_value);
01627     
01628     /* Send init_sensors to make sure that server and robot are synchronized */
01629     if (model == MODEL_N200)
01630     {
01631       init_sensors();
01632     }
01633     else
01634     {
01635       usedSmask[0] = 0;
01636       /* IR */
01637       for (i = 1; i < 17; i++)
01638         usedSmask[i] = 0;
01639       /* Sonar */
01640       for (i = 17; i < 33; i++)
01641         usedSmask[i] = 1;
01642       /* Bumper */
01643       usedSmask[33] = 1;
01644       /* Conf */
01645       for (i = 34; i < 38; i++)
01646         usedSmask[i] = 1;
01647       /* Velocity */
01648       for (i = 38; i < 41; i++)
01649         usedSmask[i] = 1;
01650       /* Motor */
01651       usedSmask[41] = 1;
01652       /* Laser */
01653       usedSmask[42] = 0;
01654       /* Compass */
01655       usedSmask[43] = 1;
01656     }
01657   } else {
01658     if (device[0] == 0)
01659       device = (char*)"localhost";
01660     if ( ((hp = gethostbyname(device)) == NULL))
01661     {
01662       convertAddr(device, addr);
01663       if (addr[0] != 0 || addr[1] != 0 || addr[2] != 0 || addr[3] != 0)
01664       {
01665         memset((char *) &serv_addr, 0, sizeof(serv_addr));
01666         memcpy((char *) &(serv_addr.sin_addr), addr, 4);
01667       }
01668       else
01669       {
01670         fprintf(stderr, "Machine %s not valid.\n", device);
01671         return FALSE;
01672       }
01673     }
01674     else
01675     {
01676       memset((char *) &serv_addr, 0, sizeof(serv_addr));
01677       memcpy((char *) &(serv_addr.sin_addr), hp->h_addr, hp->h_length);
01678     }
01679     
01680     serv_addr.sin_family = AF_INET;            /* address family */
01681     
01682     /* TCP port number */
01683     if (conn_value == 0)
01684     {
01685       conn_value = DEFAULT_ROBOT_TCP_PORT;
01686     }
01687     serv_addr.sin_port = htons(conn_value);
01688     
01689     if ((Fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
01690       fprintf(stderr, "Error: in open_socket_to_send_data, socket failed.\n");
01691       return FALSE;
01692     }
01693     fcntl(Fd, F_SETFL, O_NDELAY);
01694     if (connect(Fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
01695       if (errno == EINPROGRESS) {
01696         fd_set          lfdvar;
01697         struct timeval  timeout;
01698         
01699         FD_ZERO(&lfdvar);
01700         FD_SET(Fd, &lfdvar);
01701         
01702         timeout.tv_sec = (long)CONNECT_TIMEOUT;
01703         timeout.tv_usec = (long)0;
01704         
01705         if (select(Fd+1, NULL, &lfdvar, NULL, &timeout) == 0) {
01706           fprintf(stderr, "Error: connect timed out.\n");
01707           close(Fd);
01708           Fd = -1;
01709           return FALSE;
01710         } else {
01711           errno = 0;
01712           retlen = 4;
01713           if (getsockopt(Fd, SOL_SOCKET, SO_ERROR, (char *)&ret, &retlen) == 0)
01714           {
01715             if (ret != 0)
01716               errno = ret;
01717             if (errno != 0)
01718             {
01719               perror("Error: connect failed");
01720               close(Fd);
01721               Fd = -1;
01722               return FALSE;
01723             }
01724           }
01725         }
01726       } else {
01727         perror("Error: connect failed");
01728         close(Fd);
01729         Fd = -1;
01730         return FALSE;
01731       }
01732     }
01733     
01734     wait_time = NORMAL_TIMEOUT;
01735     
01736     printf("Robot <-> Host TCP/IP communication setup\n");
01737     printf("(machine %s on port %d)\n", device, conn_value);
01738     
01739     /* Read configuration data */
01740     if (model == MODEL_N200)
01741     {
01742       byte = GETC(Fd, connect_type);
01743       ir_mask[ 0] = byte & (1 << 0) ? 1 : 0;
01744       ir_mask[ 1] = byte & (1 << 1) ? 1 : 0;
01745       ir_mask[ 2] = byte & (1 << 2) ? 1 : 0;
01746       ir_mask[ 3] = byte & (1 << 3) ? 1 : 0;
01747       ir_mask[ 4] = byte & (1 << 4) ? 1 : 0;
01748       ir_mask[ 5] = byte & (1 << 5) ? 1 : 0;
01749       ir_mask[ 6] = byte & (1 << 6) ? 1 : 0;
01750       ir_mask[ 7] = byte & (1 << 7) ? 1 : 0;
01751       byte = GETC(Fd, connect_type);
01752       ir_mask[ 8] = byte & (1 << 0) ? 1 : 0;
01753       ir_mask[ 9] = byte & (1 << 1) ? 1 : 0;
01754       ir_mask[10] = byte & (1 << 2) ? 1 : 0;
01755       ir_mask[11] = byte & (1 << 3) ? 1 : 0;
01756       ir_mask[12] = byte & (1 << 4) ? 1 : 0;
01757       ir_mask[13] = byte & (1 << 5) ? 1 : 0;
01758       ir_mask[14] = byte & (1 << 6) ? 1 : 0;
01759       ir_mask[15] = byte & (1 << 7) ? 1 : 0;
01760       byte = GETC(Fd, connect_type);
01761       sn_mask[ 0] = byte & (1 << 0) ? 1 : 0;
01762       sn_mask[ 1] = byte & (1 << 1) ? 1 : 0;
01763       sn_mask[ 2] = byte & (1 << 2) ? 1 : 0;
01764       sn_mask[ 3] = byte & (1 << 3) ? 1 : 0;
01765       sn_mask[ 4] = byte & (1 << 4) ? 1 : 0;
01766       sn_mask[ 5] = byte & (1 << 5) ? 1 : 0;
01767       sn_mask[ 6] = byte & (1 << 6) ? 1 : 0;
01768       sn_mask[ 7] = byte & (1 << 7) ? 1 : 0;
01769       byte = GETC(Fd, connect_type);
01770       sn_mask[ 8] = byte & (1 << 0) ? 1 : 0;
01771       sn_mask[ 9] = byte & (1 << 1) ? 1 : 0;
01772       sn_mask[10] = byte & (1 << 2) ? 1 : 0;
01773       sn_mask[11] = byte & (1 << 3) ? 1 : 0;
01774       sn_mask[12] = byte & (1 << 4) ? 1 : 0;
01775       sn_mask[13] = byte & (1 << 5) ? 1 : 0;
01776       sn_mask[14] = byte & (1 << 6) ? 1 : 0;
01777       sn_mask[15] = byte & (1 << 7) ? 1 : 0;
01778       byte = GETC(Fd, connect_type);
01779       bp_mask    = byte & (1 << 0) ? 1 : 0;
01780       cf_mask[0] = byte & (1 << 1) ? 1 : 0;
01781       cf_mask[1] = byte & (1 << 2) ? 1 : 0;
01782       cf_mask[2] = byte & (1 << 3) ? 1 : 0;
01783       cf_mask[3] = byte & (1 << 4) ? 1 : 0;
01784       vl_mask[0] = byte & (1 << 5) ? 1 : 0;
01785       vl_mask[1] = byte & (1 << 6) ? 1 : 0;
01786       vl_mask[2] = byte & (1 << 7) ? 1 : 0;
01787       byte = GETC(Fd, connect_type);
01788       cp_mask = byte & 1;
01789       byte = GETC(Fd, connect_type);
01790       ls_mask = byte & 1;
01791       pos_mask = byte >> 1;
01792       
01793       usedSmask[0] = pos_mask;
01794       for (i = 0; i < 16; i++)
01795         usedSmask[i+1] = ir_mask[i];
01796       for (i = 0; i < 16; i++)
01797         usedSmask[i+17] = sn_mask[i];
01798       usedSmask[33] = bp_mask;
01799       for (i = 0; i < 4; i++)
01800         usedSmask[i+34] = cf_mask[i];
01801       for (i = 0; i < 3; i++)
01802         usedSmask[i+38] = vl_mask[i];
01803       usedSmask[42] = ls_mask;
01804       usedSmask[43] = cp_mask;
01805       
01806       /* get laser mode, num_points, processing */
01807       byte = GETC(Fd, connect_type);
01808       laser_mode = byte;
01809       byte = GETC(Fd, connect_type);
01810       byte = GETC(Fd, connect_type);
01811       byte = GETC(Fd, connect_type);
01812     }
01813     else
01814     {
01815       usedSmask[0] = 0;
01816       /* IR */
01817       for (i = 1; i < 17; i++)
01818         usedSmask[i] = 0;
01819       /* Sonar */
01820       for (i = 17; i < 33; i++)
01821         usedSmask[i] = 1;
01822       /* Bumper */
01823       usedSmask[33] = 1;
01824       /* Conf */
01825       for (i = 34; i < 38; i++)
01826         usedSmask[i] = 1;
01827       /* Velocity */
01828       for (i = 38; i < 41; i++)
01829         usedSmask[i] = 1;
01830       /* Motor */
01831       usedSmask[41] = 1;
01832       /* Laser */
01833       usedSmask[42] = 0;
01834       /* Compass */
01835       usedSmask[43] = 1;
01836     }
01837   }
01838   
01839   return TRUE;
01840 }
01841 
01842 /*
01843  * dummy function to maintain compatibility with Nclient
01844  *
01845  * disconnect_robot - requests the server to close the connect with robot
01846  *                    with id = robot_id. 
01847  *
01848  * parameters:
01849  *    long robot_id -- robot's id. In order to disconnect a robot, you
01850  *                     must know it's id.
01851  */
01852 int disconnect_robot(long robot_id)
01853 {
01854   Robot_id = -1;
01855   return ( TRUE );
01856 }
01857 
01858 /* 
01859  * ac - sets accelerations of the robot. Currently it has no effect in 
01860  *      simulation mode.
01861  *
01862  * parameters:
01863  *    int t_ac, s_ac, r_ac -- the translation, steering, and turret
01864  *                            accelerations. t_ac is in 1/10 inch/sec^2
01865  *                            s_ac and r_ac are in 1/10 degree/sec^2.
01866  */
01867 int ac(int t_ac, int s_ac, int r_ac)
01868 {
01869   unsigned char outbuf[BUFSIZE];
01870   
01871   stuff_three_unsigned_int(8, AC, t_ac, s_ac, r_ac, outbuf);
01872   return(Comm_Robot(Fd, outbuf));  
01873 }
01874 
01875 /*
01876  * sp - sets speeds of the robot, this function will not cause the robot to
01877  *      move. However, the set speed will be used when executing a pr()
01878  *      or a pa().
01879  *
01880  * parameters:
01881  *    int t_sp, s_sp, r_sp -- the translation, steering, and turret
01882  *                            speeds. t_sp is in 1/10 inch/sec and
01883  *                            s_sp and r_sp are in 1/10 degree/sec.
01884  */
01885 int sp(int t_sp, int s_sp, int r_sp)
01886 {
01887   unsigned char outbuf[BUFSIZE];
01888   
01889   stuff_three_unsigned_int(8, SP, t_sp, s_sp, r_sp, outbuf);
01890   return(Comm_Robot(Fd, outbuf));
01891 }
01892 
01893 /*
01894  * pr - moves the motors of the robot by a relative distance, using the speeds
01895  *      set by sp(). The three parameters specify the relative distances for
01896  *      the three motors: translation, steering, and turret. All the three
01897  *      motors move concurrently if the speeds are not set to zero and the 
01898  *      distances to be traveled are non-zero. Depending on the timeout 
01899  *      period set (by function conf_tm(timeout)), the motion may 
01900  *      terminate before the robot has moved the specified distances
01901  *
01902  * parameters:
01903  *    int t_pr, s_pr, r_pr -- the specified relative distances of the
01904  *                            translation, steering, and turret motors.
01905  *                            t_pr is in 1/10 inch and s_pr and r_pr are
01906  *                            in 1/10 degrees.
01907  */
01908 int pr(int t_pr, int s_pr, int r_pr)
01909 {
01910   unsigned char outbuf[BUFSIZE];
01911   
01912   stuff_three_signed_int(8, PR, t_pr, s_pr, r_pr, outbuf);
01913   return(Comm_Robot(Fd, outbuf));
01914 }
01915 
01916 /*
01917  * pa - moves the motors of the robot to the specified absolute positions 
01918  *      using the speeds set by sp().  Depending on the timeout period set 
01919  *      (by conf_tm()), the motion may terminate before the robot has 
01920  *      moved to the specified positions.
01921  *
01922  * parameters:
01923  *    int t_pa, s_pa, r_pa -- the specified absolute positions of the
01924  *                            translation, steering, and turret motors.
01925  *                            t_pa is in 1/10 inch and s_pa and r_pa are
01926  *                            in 1/10 degrees.
01927  */
01928 int pa(int t_pa, int s_pa, int r_pa);
01929 int pa(int t_pa, int s_pa, int r_pa)
01930 {
01931   unsigned char outbuf[BUFSIZE];
01932   
01933   if (model != MODEL_N200)
01934   {
01935     return FALSE;
01936   }
01937   
01938   stuff_three_signed_int(8, PA, t_pa, s_pa, r_pa, outbuf);
01939   return(Comm_Robot(Fd, outbuf));
01940 }
01941 
01942 /*
01943  * vm - velocity mode, command the robot to move at translational
01944  *      velocity = tv, steering velocity = sv, and rotational velocity =
01945  *      rv. The robot will continue to move at these velocities until
01946  *      either it receives another command or this command has been
01947  *      timeout (in which case it will stop its motion).
01948  *
01949  * parameters: 
01950  *    int t_vm, s_vm, r_vm -- the desired translation, steering, and turret
01951  *                            velocities. tv is in 1/10 inch/sec and
01952  *                            sv and rv are in 1/10 degree/sec.
01953  */
01954 int vm(int t_v, int s_v, int r_v)
01955 {
01956   unsigned char outbuf[BUFSIZE];
01957   
01958   stuff_three_signed_int(8, VM, t_v, s_v, r_v, outbuf);
01959   return(Comm_Robot(Fd, outbuf));
01960 }
01961 
01962 /*
01963  * mv - move, send a generalized motion command to the robot.
01964  *      For each of the three axis (translation, steering, and
01965  *      turret) a motion mode (t_mode, s_mode, r_mode) can be 
01966  *      specified (using the values MV_IGNORE, MV_AC, MV_SP,
01967  *      MV_LP, MV_VM, and MV_PR defined above):
01968  *
01969  *         MV_IGNORE : the argument for this axis is ignored
01970  *                     and the axis's motion will remain 
01971  *                     unchanged.
01972  *         MV_AC :     the argument for this axis specifies
01973  *                     an acceleration value that will be used
01974  *                     during motion commands.
01975  *         MV_SP :     the argument for this axis specifies
01976  *                     a speed value that will be used during
01977  *                     position relative (PR) commands.
01978  *         MV_LP :     the arguemnt for this axis is ignored
01979  *                     but the motor is turned off.
01980  *         MV_VM :     the argument for this axis specifies
01981  *                     a velocity and the axis will be moved
01982  *                     with this velocity until a new motion
01983  *                     command is issued (vm,pr,mv) or 
01984  *                     recieves a timeout.
01985  *         MV_PR :     the argument for this axis specifies
01986  *                     a position and the axis will be moved
01987  *                     to this position, unless this command
01988  *                     is overwritten by another (vm,pr,mv).
01989  *
01990  * parameters: 
01991  *    int t_mode - the desired mode for the tranlation axis
01992  *    int t_mv   - the value for that axis, velocity or position,
01993  *                 depending on t_mode
01994  *    int s_mode - the desired mode for the steering axis
01995  *    int s_mv   - the value for that axis, velocity or position,
01996  *                 depending on t_mode
01997  *    int r_mode - the desired mode for the turret axis
01998  *    int r_mv   - the value for that axis, velocity or position,
01999  *                 depending on t_mode
02000  */
02001 int mv(int t_mode, int t_mv, int s_mode, 
02002        int s_mv, int r_mode, int r_mv) 
02003 {
02004   unsigned char outbuf[BUFSIZE];
02005   unsigned char *ptr;
02006 
02007   ptr = outbuf;
02008   
02009   /* skip the first byte for begin package */
02010   ptr++;
02011 
02012   /* the length into the packet (# of ints * sizeof(int)) */
02013   unsigned_int_to_two_bytes ( 6 * 2 + 2, ptr ); ptr += 2;
02014 
02015   /* the packet type */
02016   *(ptr++) = MV;
02017 
02018   /* translational axis - mode and value */
02019   unsigned_int_to_two_bytes ( t_mode , ptr ); ptr += 2;
02020   signed_int_to_two_bytes   ( t_mv   , ptr ); ptr += 2;
02021 
02022   /* steering axis - mode and value */
02023   unsigned_int_to_two_bytes ( s_mode , ptr ); ptr += 2;
02024   signed_int_to_two_bytes   ( s_mv   , ptr ); ptr += 2;
02025 
02026   /* turret  axis - mode and value */
02027   unsigned_int_to_two_bytes ( r_mode , ptr ); ptr += 2;
02028   signed_int_to_two_bytes   ( r_mv   , ptr ); ptr += 2;
02029 
02030   return ( Comm_Robot(Fd, outbuf) );
02031 }
02032 
02033 /*
02034  * ct - send the sensor mask, Smask, to the robot. You must first change
02035  *      the global variable Smask to the desired communication mask before
02036  *      calling this function. 
02037  *
02038  *      to avoid inconsistencies usedSmask is used in all other function.
02039  *      once ct is called the user accessible mask Smask is used to 
02040  *      redefine usedSmask. This avoids that a returning package is encoded
02041  *      with a different mask than the one it was sent with, in case
02042  *      the mask has been changed on the client side, but has not been 
02043  *      updated on the server side.
02044  */
02045 int ct()
02046 {
02047   int i;
02048   unsigned char b0, b1, b2, b3, b4, b5, b6;
02049   unsigned char outbuf[BUFSIZE], *byte_ptr;
02050 
02051   if (model != MODEL_N200)
02052   {
02053     return FALSE;
02054   }
02055   
02056   for ( i = 0; i < NUM_MASK; i++ )
02057     usedSmask[i] = Smask[i];
02058   
02059   /* first encode Mask */
02060   b0 = bits_to_byte (Smask[1], Smask[2], Smask[3], Smask[4],
02061                      Smask[5], Smask[6], Smask[7], Smask[8]);
02062   b1 = bits_to_byte (Smask[9], Smask[10], Smask[11], Smask[12],
02063                      Smask[13], Smask[14], Smask[15], Smask[16]);
02064   b2 = bits_to_byte (Smask[17], Smask[18], Smask[19], Smask[20],
02065                      Smask[21], Smask[22], Smask[23], Smask[24]);
02066   b3 = bits_to_byte (Smask[25], Smask[26], Smask[27], Smask[28],
02067                      Smask[29], Smask[30], Smask[31], Smask[32]);
02068   b4 = bits_to_byte (Smask[33], Smask[34], Smask[35], Smask[36],
02069                      Smask[37], Smask[38], Smask[39], Smask[40]);
02070   b5 = bits_to_byte (Smask[42], 0, 0, 0, 0, 0, 0, 0);
02071   /* we pack the pos mask into b6 */
02072   b6 = bits_to_byte(Smask[43], 
02073                     POS_INFRARED_PI(Smask[ SMASK_POS_DATA ]),
02074                     POS_SONAR_PI   (Smask[ SMASK_POS_DATA ]), 
02075                     POS_BUMPER_PI  (Smask[ SMASK_POS_DATA ]), 
02076                     POS_LASER_PI   (Smask[ SMASK_POS_DATA ]), 
02077                     POS_COMPASS_PI (Smask[ SMASK_POS_DATA ]),
02078                     0,0);
02079   
02080   stuff_length_type (9, CT, outbuf);
02081   byte_ptr = outbuf + 4;
02082   *byte_ptr = b0;
02083   byte_ptr++;
02084   *byte_ptr = b1;
02085   byte_ptr++;
02086   *byte_ptr = b2;
02087   byte_ptr++;
02088   *byte_ptr = b3;
02089   byte_ptr++;
02090   *byte_ptr = b4;
02091   byte_ptr++;
02092   *byte_ptr = b5;
02093   byte_ptr++;
02094   *byte_ptr = b6;
02095   return(Comm_Robot(Fd, outbuf));
02096 }
02097 
02098 /*
02099  * gs - get the current state of the robot according to the mask (of 
02100  *      the communication channel)
02101  */
02102 int gs()
02103 {
02104   unsigned char outbuf[BUFSIZE];
02105   
02106   stuff_length_type (2, GS, outbuf);
02107   return(Comm_Robot(Fd, outbuf));
02108 }
02109 
02110 /*
02111  * st - stops the robot (the robot holds its current position)
02112  */
02113 int st()
02114 {
02115   unsigned char outbuf[BUFSIZE];
02116   
02117   stuff_length_type (2, ST, outbuf);
02118   return(Comm_Robot(Fd, outbuf));
02119 }
02120 
02121 /*
02122  * lp - set motor limp (the robot may not hold its position).
02123  */
02124 int lp ()
02125 {
02126   unsigned char outbuf[BUFSIZE];
02127   
02128   stuff_length_type (2, LP, outbuf);
02129   return(Comm_Robot(Fd, outbuf));
02130 }
02131 
02132 /*
02133  * tk - sends the character stream, talk_string, to the voice synthesizer
02134  *      to make the robot talk.
02135  *
02136  * parameters:
02137  *    char *talk_string -- the string to be sent to the synthesizer.
02138  */
02139 int tk(char *talk_string)
02140 {
02141   unsigned char outbuf[BUFSIZE], *byte_ptr;
02142   int tkfd, i, length;
02143   
02144   if (model == MODEL_N200)
02145   {
02146     length = 3 + strlen(talk_string);
02147     stuff_length_type (length, TK, outbuf);
02148     byte_ptr = outbuf + 4;
02149     for (i=3; i<length; i++) {
02150       *byte_ptr = talk_string[i-3];
02151       byte_ptr++;
02152     }
02153     *byte_ptr = 0; /* null terminate the string */
02154     return(Comm_Robot(Fd, outbuf));
02155   }
02156   else
02157   {
02158     tkfd = open("/dev/dbtk", O_RDWR);
02159     if (tkfd >= 0)
02160     {
02161       write(tkfd, talk_string, strlen(talk_string));
02162       write(tkfd, "\n", 1);
02163       close(tkfd);
02164       
02165       return TRUE;
02166     }
02167   }
02168   
02169   return FALSE;
02170 }
02171 
02172 /*
02173  * dp - define the current position of the robot as (x,y)
02174  * 
02175  * parameters:
02176  *    int x, y -- the position to set the robot to.
02177  */
02178 int dp(int x, int y)
02179 {
02180   unsigned char outbuf[BUFSIZE];
02181   
02182   stuff_two_signed_int (6, DP, x, y, outbuf);
02183   return(Comm_Robot(Fd, outbuf));
02184 }
02185 
02186 /*
02187  * zr - zeroing the robot, align steering and turret with bumper zero.
02188  *      The position, steering and turret angles are all set to zero.
02189  *      This function returns when the zeroing process has completed.
02190  */
02191 int zr()
02192 {
02193   unsigned char outbuf[BUFSIZE];
02194   int temp;
02195   
02196   wait_time =  120;   /* maximum of 2 minutes */
02197   /* zr() takes maximum of 120 seconds */
02198   stuff_length_type (2, ZR, outbuf);
02199   temp = Comm_Robot(Fd, outbuf);
02200   wait_time = NORMAL_TIMEOUT;
02201   return(temp);
02202 }
02203 
02204 /*
02205  * conf_ir - configure infrared sensor system.
02206  *
02207  * parameters: 
02208  *    int history -- specifies the percentage dependency of the current 
02209  *                   returned reading on the previous returned reading.
02210  *                   It should be set between 0 and 10: 0 = no dependency 
02211  *                   10 = full dependency, i.e. the reading will not change
02212  *    int order[16] --  specifies the firing sequence of the infrared 
02213  *                      (#0 .. #15). You can terminate the order list by a 
02214  *                      "255". For example, if you want to use only the 
02215  *                      front three infrared sensors then set order[0]=0,
02216  *                      order[1]=1, order[2]=15, order[3]=255 (terminator).
02217  */
02218 int conf_ir(int history, int order[16])
02219 {
02220   unsigned char outbuf[BUFSIZE], *byte_ptr;
02221   int i;
02222   
02223   if (model != MODEL_N200)
02224   {
02225     return FALSE;
02226   }
02227   
02228   stuff_length_type (19, CONF_IR, outbuf);
02229   byte_ptr = outbuf + 4;
02230   if (history > 10)
02231     history = 10;
02232   *byte_ptr = (unsigned char)history;
02233   for (i=0; i<16; i++) {
02234     byte_ptr++;
02235     *byte_ptr = (unsigned char)order[i];
02236   }
02237   return(Comm_Robot(Fd, outbuf));
02238 }
02239 
02240 /*
02241  * conf_sn - configure sonar sensor system.
02242  *
02243  * parameters:
02244  *    int rate -- specifies the firing rate of the sonar in 4 milli-seconds 
02245  *                interval; 
02246  *    int order[16] -- specifies the firing sequence of the sonar (#0 .. #15).
02247  *                     You can terminate the order list by a "255". For 
02248  *                     example, if you want to use only the front three 
02249  *                     sensors, then set order[0]=0, order[1]=1, order[2]=15, 
02250  *                     order[3]=255 (terminator).
02251  */
02252 int conf_sn(int rate, int order[16])
02253 {
02254   unsigned char outbuf[BUFSIZE], *byte_ptr;
02255   int i;
02256   
02257   stuff_length_type (19, CONF_SN, outbuf);
02258     byte_ptr = outbuf + 4;
02259     *byte_ptr = (unsigned char)rate;
02260   for (i=0; i<16; i++) {
02261     byte_ptr++;
02262     *byte_ptr = (unsigned char)order[i];
02263   }
02264   return(Comm_Robot(Fd, outbuf));
02265 }
02266 
02267 /*
02268  * conf_cp - configure compass system.
02269  * 
02270  * parameters:
02271  *    int mode -- specifies compass on/off: 0 = off ; 1 = on; 2 = calibrate.
02272  *                When you call conf_cp (2), the robot will rotate slowly 360
02273  *                degrees. You must wake till the robot stop rotating before
02274  *                issuing another command to the robot (takes ~3 minutes).
02275  */
02276 int conf_cp(int mode)
02277 {
02278   unsigned char outbuf[BUFSIZE], *byte_ptr;
02279   
02280   if (model != MODEL_N200)
02281   {
02282     return FALSE;
02283   }
02284   
02285   stuff_length_type (3, CONF_CP, outbuf);
02286   byte_ptr = outbuf + 4;
02287   *byte_ptr = (unsigned char)mode;
02288   return(Comm_Robot(Fd, outbuf));
02289 }
02290 
02291 /*
02292  * conf_ls - configure laser sensor system:
02293  *
02294  * parameters:
02295  *    unsigned int mode -- specifies the on-board processing mode of the laser 
02296  *                         sensor data which determines the mode of the data 
02297  *                         coming back: 
02298  *                           the first bit specifies the on/off;
02299  *                           the second bit specifies point/line mode;
02300  *                           the third to fifth bits specify the 
02301  *                           returned data types: 
02302  *                             000 = peak pixel, 
02303  *                             001 = rise pixel, 
02304  *                             010 = fall pixel, 
02305  *                             011 = magnitude,
02306  *                             100 = distance;
02307  *                           the sixth bit specifies data integrity checking.
02308  *
02309  *   unsigned int threshold -- specifies the inverted acceptable brightness
02310  *                             of the laser line. 
02311  *
02312  *   unsigned int width -- specifies the acceptable width in terms
02313  *                         of number of pixels that are brighter than the 
02314  *                         set threshold.
02315  *  
02316  *   unsigned int num_data -- specifies the number of sampling points. 
02317  *   unsigned int processing --  specifies the number of neighboring 
02318  *                               pixels for averaging
02319  *
02320  * If you don't understand the above, try this one:
02321  *   conf_ls(51, 20, 20, 20, 4)
02322  */
02323 int conf_ls(unsigned int mode, unsigned int threshold, unsigned int width,
02324             unsigned int num_data, unsigned int processing)
02325 {
02326   unsigned char outbuf[BUFSIZE], *byte_ptr;
02327   
02328   if (model != MODEL_N200)
02329   {
02330     return FALSE;
02331   }
02332   
02333   laser_mode = mode;
02334   stuff_length_type (8, CONF_LS, outbuf);
02335   byte_ptr = outbuf + 4;
02336   if (mode == 51) 
02337     *byte_ptr = 35; /* special case */
02338   else
02339     *byte_ptr = (unsigned char)mode;
02340   byte_ptr++;
02341   *byte_ptr = (unsigned char)threshold;
02342   byte_ptr++;
02343   *byte_ptr = (unsigned char)width;
02344   byte_ptr++;
02345   unsigned_int_to_two_bytes(num_data, byte_ptr);
02346   byte_ptr = byte_ptr + 2;
02347   *byte_ptr = (unsigned char)processing;
02348   return(Comm_Robot(Fd, outbuf));
02349 }
02350 
02351 /*
02352  * conf_tm - sets the timeout period of the robot in seconds. If the
02353  *           robot has not received a command from the host computer
02354  *           for more than the timeout period, it will abort its 
02355  *           current motion
02356  * 
02357  * parameters:
02358  *    unsigned int timeout -- timeout period in seconds. If it is 0, there
02359  *                            will be no timeout on the robot.
02360  */
02361 int conf_tm(unsigned char timeout)
02362 {
02363   unsigned char outbuf[BUFSIZE], *byte_ptr;
02364   
02365   stuff_length_type (3, CONF_TM, outbuf);
02366   byte_ptr = outbuf + 4;
02367   *byte_ptr = (unsigned char)timeout;
02368   return(Comm_Robot(Fd, outbuf));
02369 }
02370 
02371 int conf_ser(unsigned char port, unsigned short baud)
02372 {
02373   unsigned char *outbuf, lbuf[BUFSIZE];
02374   
02375   if (model == MODEL_N200)
02376   {
02377     return FALSE;
02378   }
02379   
02380   outbuf=lbuf;
02381   stuff_length_type(5, CONF_SER, outbuf);
02382   outbuf+=4;
02383   *outbuf=port;
02384   outbuf++;
02385   unsigned_int_to_two_bytes(baud, outbuf);
02386   return(Comm_Robot(Fd, lbuf));
02387 }
02388 
02389 /*
02390  * get_ir - get infrared data, independent of mask. However, only 
02391  *          the active infrared sensor readings are valid. It updates
02392  *          the State vector.
02393  */
02394 int get_ir()
02395 {
02396   unsigned char outbuf[BUFSIZE];
02397   
02398   if (model != MODEL_N200)
02399   {
02400     return FALSE;
02401   }
02402   
02403   stuff_length_type (2, GET_IR, outbuf);
02404   return(Comm_Robot(Fd, outbuf));
02405 }
02406 
02407 /*
02408  * get_sn - get sonar data, independent of mask. However, only 
02409  *          the active sonar sensor readings are valid. It updates
02410  *          the State vector.
02411  */
02412 int get_sn()
02413 {
02414   unsigned char outbuf[BUFSIZE];
02415   
02416   stuff_length_type (2, GET_SN, outbuf);
02417   return(Comm_Robot(Fd, outbuf));
02418 }
02419 
02420 /*
02421  * get_rc - get robot configuration data (x, y, th, tu), independent of 
02422  *          mask. It updates the State vector.
02423  */
02424 int get_rc() 
02425 {
02426   unsigned char outbuf[BUFSIZE];
02427   
02428   stuff_length_type (2, GET_RC, outbuf);
02429   return(Comm_Robot(Fd, outbuf));
02430 }
02431 
02432 /*
02433  * get_rv - get robot velocities (translation, steering, and turret) data,
02434  *          independent of mask. It updates the State vector.
02435  */
02436 int get_rv() 
02437 {
02438   unsigned char outbuf[BUFSIZE];
02439   
02440   stuff_length_type (2, GET_RV, outbuf);
02441   return(Comm_Robot(Fd, outbuf));
02442 }
02443 
02444 /*
02445  * get_ra - get robot acceleration (translation, steering, and turret) data,
02446  *          independent of mask. It updates the State vector.
02447  */
02448 int get_ra() 
02449 {
02450   unsigned char outbuf[BUFSIZE];
02451   
02452   stuff_length_type (2, GET_RA, outbuf);
02453   return(Comm_Robot(Fd, outbuf));
02454 }
02455 
02456 /*
02457  * get_cp - get compass data, independent of mask. However, the
02458  *          data is valid only if the compass is on. It updates the
02459  *          State vector.
02460  */
02461 int get_cp()
02462 {
02463   unsigned char outbuf[BUFSIZE];
02464   
02465   if (model != MODEL_N200)
02466   {
02467     return FALSE;
02468   }
02469   
02470   stuff_length_type (2, GET_CP, outbuf);
02471   return(Comm_Robot(Fd, outbuf));
02472 }
02473 
02474 /*
02475  * get_ls - get laser data point mode, independent of mask. However the
02476  *          data is valid only of the laser is on. It updates the Laser 
02477  *          vector.
02478  */
02479 int get_ls()
02480 {
02481   unsigned char outbuf[BUFSIZE];
02482   
02483   if (model != MODEL_N200)
02484   {
02485     return FALSE;
02486   }
02487   
02488   stuff_length_type (2, GET_LS, outbuf);
02489   return(Comm_Robot(Fd, outbuf));
02490 }
02491 
02492 /*
02493  * get_bp - get bumper data, independent of mask. It updates the State
02494  *          vector.
02495  */
02496 int get_bp()
02497 {
02498   unsigned char outbuf[BUFSIZE];
02499   
02500   stuff_length_type (2, GET_BP, outbuf);
02501   return(Comm_Robot(Fd, outbuf));
02502 }
02503 
02504 /*
02505  * conf_sg - configure laser sensor system line segment processing mode:
02506  *
02507  * parameters:
02508  *    unsigned int threshold -- specifies the threshold value for least-square
02509  *                             fitting. When the error term grows above the 
02510  *                             threshold, the line segment will be broken
02511  *    unsigned int min_points -- specifies the acceptable number of points
02512  *                              to form a line segment.
02513  *    unsigned int gap -- specifies the acceptable "gap" between two segments
02514  *                        while they can still be treated as one (in 1/10 inch)
02515  *
02516  * If you don't understand the above, try this one:
02517  *    conf_sg(50, 4, 30)
02518  */
02519 int conf_sg(unsigned int threshold, unsigned int min_points, unsigned int gap)
02520 {
02521   unsigned char outbuf[BUFSIZE], *byte_ptr;
02522   
02523   if (model != MODEL_N200)
02524   {
02525     return FALSE;
02526   }
02527   
02528   stuff_length_type (5, CONF_SG, outbuf);
02529   byte_ptr = outbuf + 4;
02530   *byte_ptr = (unsigned char)threshold;
02531   byte_ptr++;
02532   *byte_ptr = (unsigned char)min_points;
02533   byte_ptr++;
02534   *byte_ptr = (unsigned char)gap;
02535   return(Comm_Robot(Fd, outbuf));
02536 }
02537 
02538 /*
02539  * get_sg - get laser data line mode, independent of mask. It updates
02540  *          the laser vector.
02541  */
02542 int get_sg()
02543 {
02544   unsigned char outbuf[BUFSIZE];
02545   
02546   if (model != MODEL_N200)
02547   {
02548     return FALSE;
02549   }
02550   
02551   stuff_length_type (2, GET_SG, outbuf);
02552   return(Comm_Robot(Fd, outbuf));
02553 }
02554 
02555 /*
02556  * da - define the current steering angle of the robot to be th
02557  *      and the current turret angle of the robot to be tu.
02558  * 
02559  * parameters:
02560  *    int th, tu -- the steering and turret orientations to set the
02561  *                  robot to.
02562  */
02563 int da(int th, int tu)
02564 {
02565   unsigned char outbuf[BUFSIZE];
02566   
02567   stuff_two_signed_int (6, DA, th, tu, outbuf);
02568   return(Comm_Robot(Fd, outbuf));
02569 }
02570 
02571 /*
02572  * ws - waits for stop of motors of the robot. This function is intended  
02573  *      to be used in conjunction with pr() and pa() to detect the desired
02574  *      motion has finished
02575  *
02576  * parameters:
02577  *    unsigned char t_ws, s_ws, r_ws -- These three parameters specify 
02578  *                                      which axis or combination of axis 
02579  *                                      (translation, steering, and turret) 
02580  *                                      to wait. 
02581  *    unsigned char timeout -- specifies how long to wait before timing out 
02582  *                             (return without stopping the robot).
02583  */
02584 int ws(unsigned char t_ws, unsigned char s_ws,
02585        unsigned char r_ws, unsigned char timeout)
02586 {
02587   unsigned char outbuf[BUFSIZE], *byte_ptr;
02588   int ret;
02589   
02590   stuff_length_type (6, WS, outbuf);
02591   byte_ptr = outbuf + 4;
02592   if (t_ws > 1) t_ws = 1;
02593   *byte_ptr = t_ws;
02594   byte_ptr++;
02595   if (s_ws > 1) s_ws = 1;
02596   *byte_ptr = s_ws;
02597   byte_ptr++;
02598   if (r_ws > 1) r_ws = 1;
02599   *byte_ptr = r_ws;
02600   byte_ptr++;
02601   *byte_ptr = timeout;
02602   
02603   wait_time =  timeout + NORMAL_TIMEOUT;
02604   ret = Comm_Robot(Fd, outbuf);
02605   wait_time = NORMAL_TIMEOUT;
02606   
02607   return ret;
02608 }
02609 
02610 /*
02611  * dummy function to maintain compatibility with Nclient
02612  *
02613  * get_rpx - get the position of all nearby robots
02614  */
02615 int get_rpx(long *robot_pos)
02616 {
02617   *robot_pos = -1;
02618 
02619   return ( FALSE );
02620 }
02621 
02622 /*****************************
02623  *                           *
02624  * World Interface Functions *
02625  *                           *
02626  * all dummy: compatibility  *
02627  *****************************/
02628 /*
02629  * add_obstacle - creates an obstacle and adds it to the obstacle list
02630  *                of the robot environment. 
02631  * 
02632  * parameters:
02633  *    long obs[2*MAX_VERTICES+1] -- 
02634  *                The first element of obs specifies the number of 
02635  *                vertices of the polygonal obstacle (must be no greater 
02636  *                than MAX_VERTICES). The subsequent elements of obs 
02637  *                specifies the x and y coordinates of the vertices, 
02638  *                in counter-clockwise direction.
02639  */
02640 int add_obstacle(long obs[2*MAX_VERTICES+1])
02641 {
02642   obs[0] = obs[0];
02643   return ( TRUE );
02644 }
02645 
02646 /*
02647  * add_Obs - is the same as add_obstacle, for backward compatibility
02648  */
02649 int add_Obs(long obs[2*MAX_VERTICES+1])
02650 {
02651   return(add_obstacle(obs));
02652 }
02653 
02654 /*
02655  * delete_obstacle - deletes an obstacle specified by obs from the robot 
02656  *                   environment 
02657  * parameters:
02658  *    long obs[2*MAX_VERTICES+1] -- 
02659  *                The first element of obs specifies the number of 
02660  *                vertices of the polygonal obstacle (must be no greater 
02661  *                than MAX_VERTICES). The subsequent elements of obs 
02662  *                specifies the x and y coordinates of the vertices, 
02663  *                in counter-clockwise direction.
02664  */
02665 int delete_obstacle(long obs[2*MAX_VERTICES+1])
02666 {
02667   obs[0] = obs[0];
02668   return ( TRUE );
02669 }
02670 
02671 /*
02672  * delete_Obs - is the same as delete_obstacle, for backward compatibility
02673  */
02674 int delete_Obs(long obs[2*MAX_VERTICES+1])
02675 {
02676   return(delete_obstacle(obs));
02677 }
02678 
02679 /*
02680  * move_obstacle - moves the obstacle obs by dx along x direction and 
02681  *                 dy along y direction. obs is modified.
02682  *
02683  * parameters:
02684  *    long obs[2*MAX_VERTICES+1] -- 
02685  *                The first element of obs specifies the number of 
02686  *                vertices of the polygonal obstacle (must be no greater 
02687  *                than MAX_VERTICES). The subsequent elements of obs 
02688  *                specifies the x and y coordinates of the vertices, 
02689  *                in counter-clockwise direction.
02690  *    long dx, dy -- the x and y distances to translate the obstacle
02691  */
02692 int move_obstacle(long obs[2*MAX_VERTICES+1], long dx, long dy)
02693 {
02694   obs[0] = obs[0];
02695   dx = dx;
02696   dy = dy;
02697   return ( TRUE );
02698 }
02699 
02700 /*
02701  * move_Obs - is the same as move_obstacle, for backward compatibility
02702  */
02703 int move_Obs(long obs[2*MAX_VERTICES+1], long dx, long dy)
02704 {
02705   return(move_obstacle(obs, dx, dy));
02706 }
02707 
02708 /*
02709  * new_world - deletes all obstacles in the current robot world
02710  */
02711 int new_world(void)
02712 {
02713   return ( TRUE );
02714 }
02715 
02716 /*******************************
02717  *                             *
02718  * Miscellaneous robot control *
02719  *                             *
02720  *******************************/
02721 
02722 /*
02723  * init_mask - initialize the sensor mask, Smask.
02724  */
02725 void init_mask(void)
02726 {
02727   int i;
02728   
02729   Smask[ SMASK_POS_DATA ] = 0;
02730   for (i=1; i<44; i++)
02731     Smask[i] = 1;
02732 }
02733 
02734 /*
02735  * init_sensors - initialize the sensor mask, Smask, and send it to the
02736  *                robot. It has no effect on the sensors 
02737  */
02738 int init_sensors()
02739 {
02740   int i;
02741   
02742   Smask[ SMASK_POS_DATA ] = 0;
02743   for (i=1; i<44; i++)
02744     Smask[i] = 1;
02745   return ( ct() );
02746 }
02747 
02748 /*
02749  * place_robot - places the robot at configuration (x, y, th, tu). 
02750  *               In simulation mode, it will place both the Encoder-robot
02751  *               and the Actual-robot at this configuration. In real robot
02752  *               mode, it will call dp(x, y) and da(th, tu).
02753  * 
02754  * parameters:
02755  *    int x, y -- x-y position of the desired robot configuration
02756  *    int th, tu -- the steering and turret orientation of the robot
02757  *                  desired configuration
02758  */
02759 int place_robot(int x, int y, int th, int tu)
02760 {
02761   if (dp(x, y) != TRUE || da(th, tu) != TRUE)
02762     return FALSE;
02763   
02764   return TRUE;
02765 }
02766 
02767 /*
02768  * special_request - sends a special request (stored in user_send_buffer) 
02769  *                   to the robot and waits for the robot's response (which
02770  *                   will be stored in user_receive_buffer). 
02771  * 
02772  * parameters:
02773  *    unsigned char *user_send_buffer -- stores data to be sent to the robot
02774  *                                       Should be a pointer to an array of
02775  *                                       MAX_USER_BUF elements
02776  *    unsigned char *user_receive_buffer -- stores data received from the robot
02777  *                                          Should be a pointer to an array of 
02778  *                                       MAX_USER_BUF elements
02779  */
02780 int special_request(unsigned char *user_send_buffer,
02781                     unsigned char *user_receive_buffer)
02782 {
02783   unsigned char outbuf[MAX_USER_BUF], *byte_ptr;
02784   int i, length, temp;
02785   
02786   length = 2 + user_send_buffer[0] + 256 * user_send_buffer[1];
02787   if (length>USER_BUFFER_LENGTH-5)
02788   {
02789     printf("Data + protocol bytes exceeding %d, truncating\n",
02790            USER_BUFFER_LENGTH);
02791     /* num_data already includes the 4 bytes of user packets protocol */
02792     length  = USER_BUFFER_LENGTH-5; 
02793   }
02794   stuff_length_type(length, SPECIAL, outbuf);
02795     
02796   byte_ptr = outbuf + 4;
02797   for (i=0; i<length; i++) 
02798     {
02799       *byte_ptr = (unsigned char)user_send_buffer[i];
02800       byte_ptr++;
02801     }
02802     
02803   /* 
02804    * Comm_Robot will process the returned package and write the 
02805    * data into special_buffer that we assign to be the buffer
02806    * that the caller provided.
02807    */
02808 
02809   special_buffer = user_receive_buffer;
02810 
02811   wait_time = SPECIAL_TIMEOUT;
02812   temp = Comm_Robot(Fd, outbuf);
02813   wait_time = NORMAL_TIMEOUT;
02814   return ( temp );
02815 }
02816 
02817 /*******************************
02818  *                             *
02819  * Graphic Interface Functions *
02820  *                             *
02821  *******************************/
02822 
02823 /*
02824  * dummy function - to maintain compatibility with Nclient
02825  *
02826  * draw_robot - this function allows the client to draw a robot at
02827  *              configuration x, y, th, tu (using the robot world 
02828  *              coordinates). 
02829  * 
02830  * parameters:
02831  *    long x, y -- the x-y position of the robot.
02832  *    int th, tu -- the steering and turret orientation of the robot
02833  *    int mode - the drawing mode. If mode = 1, the robot is drawn in 
02834  *              BlackPixel using GXxor (using GXxor you can erase the trace 
02835  *              of robotby drawing over it). If mode = 2, the robot is 
02836  *              drawn in BlackPixel using GXxor and in addition, a small arrow
02837  *              is drawn at the center of the robot using GXcopy (using this 
02838  *              mode you can leave a trace of small arrow). If mode = 3, 
02839  *              the robot is drawn in BlackPixel using GXcopy. When mode > 3,
02840  *              the robot is drawn in color using GXxor.
02841  */
02842 int draw_robot(long x, long y, int th, int tu, int mode)
02843 {
02844   x = x;
02845   y = y;
02846   th = th;
02847   tu = tu;
02848   mode = mode;
02849   return ( TRUE );
02850 }
02851 
02852 /*
02853  * dummy function - to maintain compatibility with Nclient
02854  *
02855  * draw_line - this function allows the client to draw a line from
02856  *             (x_1, y_1) to (x_2, y_2) (using the robot world coordinates). 
02857  *
02858  * parameters:
02859  *    long x_1, y_1, x_2, y_2 -- the two end-points of the line
02860  *    int mode -- the mode of drawing: when mode is 1, the drawing is 
02861  *                done in BlackPixel using GXcopy; when mode is 2, the drawing
02862  *                is done in BlackPixel using GXxor, when mode > 2, the drawing
02863  *                is done in color using GXxor.
02864  */
02865 int draw_line(long x_1, long y_1, long x_2, long y_2, int mode)
02866 {
02867   x_1 = x_1;
02868   y_1 = y_1;
02869   x_2 = x_2;
02870   y_2 = y_2;
02871   mode = mode;
02872   return ( TRUE );
02873 }
02874 
02875 /*
02876  * dummy function - to maintain compatibility with Nclient
02877  *
02878  * draw_arc - this function allows the client to draw arc which is part
02879  *            of an ellipse (using the robot world coordinates). 
02880  *
02881  * parameters:
02882  *    long x_0, y_0, w, h -- (x_0, y_0) specifies the upper left corner of the 
02883  *                          rectangle bounding the ellipse while w and h
02884  *                          specifies the width and height of the bounding 
02885  *                          rectangle, respectively.
02886  *    int th1, th2 -- th1 and th2 specifies the angular range of the arc.
02887  *    int mode -- the mode of drawing: when mode is 1, the drawing is 
02888  *                done in BlackPixel using GXcopy; when mode is 2, the drawing
02889  *                is done in BlackPixel using GXxor, when mode > 2, the drawing
02890  *                is done in color using GXxor.
02891  */
02892 int draw_arc(long x_0, long y_0, long w, long h, int th1, int th2, int mode)
02893 {
02894   x_0 = x_0;
02895   y_0 = y_0;
02896   w   = w;
02897   h   = h;
02898   th1 = th1;
02899   th2 = th2;
02900   mode = mode;
02901   return ( TRUE );
02902 }
02903 
02904 /*************************************
02905  *                                   *
02906  * Miscellaneous Interface Functions *
02907  *                                   *
02908  *************************************/
02909 
02910 /*
02911  * dummy function - to maintain compatibility with Nclient
02912  *
02913  * server_is_running - this function queries the server to see
02914  *                     if it is up and running.  If so, this function
02915  *                     returns a TRUE, otherwise it returns FALSE.
02916  *                     This function is replaced by connect_robot, but 
02917  *                     is defined here for backward compatibility
02918  */
02919 int server_is_running()
02920 {
02921   return(connect_robot(1));
02922 }
02923 
02924 /*
02925  * dummy function - to maintain compatibility with Nclient
02926  *
02927  * quit_server - this function allows the client to quit the server
02928  *               assuming this feature is enabled in the setup file
02929  *               of the server
02930  */
02931 int quit_server(void)
02932 {
02933   return ( TRUE );
02934 }
02935 
02936 /*
02937  * dummy function - to maintain compatibility with Nclient
02938  *
02939  * real_robot - this function allows the client to switch to
02940  *              real robot mode in the server
02941  */
02942 int real_robot(void)
02943 {
02944   return ( TRUE );
02945 }
02946 
02947 /*
02948  * dummy function - to maintain compatibility with Nclient
02949  *
02950  * simulated_robot - this function allows the client to switch to
02951  *                   simulated robot mode in the server
02952  */
02953 int simulated_robot(void)
02954 {
02955   return ( TRUE );
02956 }
02957 
02958 /*
02959  * dummy function - to maintain compatibility with Nclient
02960  *
02961  * predict_sensors - this function predicts the sensor reading of
02962  *                   the robot assuming it is at position (x, y)
02963  *                   and orientation th and tu using the map of the
02964  *                   simulated robot environment. The predicted sensor
02965  *                   data values are stored in "state" and "laser".
02966  * 
02967  * parameters:
02968  *    int x, y, th, tu -- the configuration of the robot
02969  *    long *state -- where to put the predicted state data
02970  *    int *laser -- where to put the predicted laser data
02971  */
02972 int predict_sensors(int x, int y, int th, int tu, long *state, int *laser)
02973 {
02974   x   = x;
02975   y   = y;
02976   th  = th;
02977   tu  = tu;
02978   state[0] = state[0];
02979   laser[0] = laser[0];
02980   return ( TRUE );
02981 }
02982 
02983 /* 
02984  * dummy function in Ndirect: needs server 
02985  *
02986  * motion_check - this function computes the intersection of a path
02987  *                specified by the parameters: type, a1, ..., a7 with
02988  *                the obstacles in the robot's environment. If there is
02989  *                collision, the function returns 1 and the x-y configuration
02990  *                of the robot is stored in collide[0] and collide[1] while
02991  *                collide[2] stores the inward normal of the obstacle edge
02992  *                that the robot collides with (this information can be
02993  *                used to calculate which bumper is hit.). If there is no
02994  *                collision, the function returns 0.
02995  *
02996  * parameters:
02997  *    long type - 0 if the path is a line segment
02998  *                1 if the path is an arc of circle
02999  *    double a1 a2 - x-y coordinates of the first point of the path (the path
03000  *                   is directional).
03001  *    depending on the value of type, a3 - a7 have different meanings.
03002  *    if (type == 0), line segment mode
03003  *      double a3 a4 are the x-y coordinates of the second point of the path
03004  *      a5, a6, a7 have no meaning
03005  *    if (type == 1), arc of circle mode
03006  *      double a3 is the angle (in radiance) of the vector connecting the 
03007  *                center of the circle to the first end-point of the arc
03008  *      double a4 is the angle of the vector connecting the center
03009  *                of the circle to the second end-point of the arc
03010  *      double a5 is the radius of the circle
03011  *      double a6 a7 are the x-y coordinate of the center of the circle
03012  */
03013 int motion_check(long type, double a1, double a2, double a3, double a4,
03014                  double a5, double a6, double a7, double collide[3])
03015 {
03016   type = type;
03017   a1   = a1;
03018   a2   = a2;
03019   a3   = a3;
03020   a4   = a4;
03021   a4   = a5;
03022   a4   = a6;
03023   a4   = a7;
03024   collide[0] = collide[0];
03025   return ( FALSE );
03026 }
03027 
03028 /*
03029  * dummy function in Ndirect: needs server 
03030  *
03031  * get_robot_conf - interactively getting the robot's conf, by clicking
03032  *                  the mouse in the server's Robot window
03033  * 
03034  * parameters:
03035  *    long *conf -- should be an array of 4 long integers. The configuration
03036  *                  of the robot is returned in this array.
03037  */
03038 int get_robot_conf(long *conf)
03039 {
03040   conf[0] = conf[0];
03041   return ( TRUE );
03042 }
03043 
03044 /*******************************************
03045  *                                         *
03046  * The following are helper functions for  *
03047  * developing user defined host <-> robot  *
03048  * communication                           *
03049  *                                         *
03050  *******************************************/
03051 
03052 /*
03053  *  init_receive_buffer - sets the index to 4 which is the point
03054  *  at which data should begin to be extracted
03055  * 
03056  *  parameters:
03057  *     unsigned short *index -- is the buffer index
03058  */
03059 int init_receive_buffer(unsigned short *index)
03060 {
03061   *index = 4;
03062   return(*index);
03063 }
03064 
03065 /*
03066  *  extract_receive_buffer_header - extracts the header information:
03067  *  length, serial_number, and packettype from the beginning of the
03068  *  receive buffer.
03069  *
03070  *  parameters:
03071  *     unsigned short *length -- is the returns the number of chars in the buffer
03072  *
03073  *     unsigned char *serial_number -- returns the serial number to be
03074  *                                     assigned to the packet
03075  *     unsigned char *packet_type -- returns the type number to be
03076  *                                   assigned to the packet
03077  *     unsigned char *buffer -- is the receive buffer
03078  */
03079 int extract_receive_buffer_header(unsigned short *length, 
03080                                   unsigned char *serial_number, 
03081                                   unsigned char *packet_type, 
03082                                   unsigned char *buffer)
03083 {
03084   unsigned short data;
03085   
03086   data = buffer[0] << 0;
03087   data |= buffer[1] << 8;
03088   *length = data;
03089   *serial_number = buffer[2];
03090   *packet_type = buffer[3];
03091   return(*length);
03092 }
03093 
03094 /*
03095  *  init_send_buffer - sets the index to 4 which is the point
03096  *  at which data should be inserted
03097  *
03098  *  parameters:
03099  *     int *index -- is the buffer index
03100  */
03101 int init_send_buffer(unsigned short *index)
03102 {
03103   *index = 4;
03104   return(*index);
03105 }
03106 
03107 /*
03108  *  stuff_send_buffer_header - loads the header information,
03109  *  length,serial_number, and packettype into the beginning of the
03110  *  buffer.  It should be called after the data has been stuffed,
03111  *  i.e. index represents the length of the packet.
03112  *
03113  *  parameters:
03114  *     unsigned short index -- is the buffer index which holds the number of chars
03115  *                  in the buffer
03116  *     unsigned char serial_number -- holds the serial number to be
03117  *                                    assigned to the packet
03118  *     unsigned char packet_type -- holds the type number to be
03119  *                                 assigned to the packet
03120  *
03121  *     unsigned char *buffer -- is the send buffer
03122  */
03123 int stuff_send_buffer_header(unsigned short index, unsigned char serial_number, 
03124                              unsigned char packet_type, unsigned char *buffer)
03125 {
03126   buffer[0] = (index >> 0) & 0xff;
03127   buffer[1] = (index >> 8) & 0xff;
03128   buffer[2] = serial_number;
03129   buffer[3] = packet_type;
03130   return(index);
03131 }
03132 
03133 /*
03134  *  stuffchar -  stuffs a 1 byte char into the send buffer
03135  *
03136  *  parameters:
03137  *     signed char data -- is the char to be stuffed
03138  *     unsigned char *buffer -- is the send buffer
03139  *     unsigned short *index -- is the buffer index which will be incremented
03140  *                              to reflect the bytes stuffed into the buffer
03141  */
03142 int stuffchar(signed char data, unsigned char *buffer, unsigned short *index)
03143 {
03144   if (data < 0)
03145   {
03146     data *= -1;
03147     data |= 0x80;
03148   }
03149   
03150   buffer[*index]   = data;
03151   *index += 1;
03152   return(*index);
03153 }
03154 
03155 /*
03156  *  stuff2byteint - stuffs a short int(2 bytes) into the send buffer
03157  *
03158  *  parameters:
03159  *     signed int data -- is the value which will be split apart and stuffed
03160  *                        bytewise into the send buffer
03161  *     unsigned char *buffer -- is the send buffer
03162  *     unsigned short *index -- is the buffer index which will be incremented
03163  *                              to reflect the bytes stuffed into the buffer
03164  */
03165 int stuff2byteint(signed short data,
03166                   unsigned char *buffer, unsigned short *index)
03167 {
03168   if (data < 0)
03169   {
03170     data *= -1;
03171     data |= 0x8000;
03172   }
03173   
03174   buffer[*index]   = (data >> 0) & 0xff;
03175   *index += 1;
03176   buffer[*index]   = (data >> 8) & 0xff;
03177   *index += 1;
03178   
03179   return(*index);
03180 }
03181 
03182 /*
03183  *  stuff4byteint - stuffs a long int(4 bytes) into the send buffer
03184  *
03185  *  parameters:
03186  *     signed long data -- is the value which will be split apart and stuffed
03187  *                         bytewise into the send buffer
03188  *     unsigned char *buffer -- is the send buffer
03189  *     unsigned short *index -- is the buffer index which will be incremented
03190  *                              to reflect the bytes stuffed into the buffer
03191  */
03192 int stuff4byteint(signed long data,
03193                   unsigned char *buffer, unsigned short *index)
03194 {
03195   if (data < 0)
03196   {
03197     data *= -1;
03198     data |= 0x80000000L;
03199   }
03200   
03201   buffer[*index] = (data >> 0) & 0xff;
03202   *index += 1;
03203   buffer[*index] = (data >> 8) & 0xff;
03204   *index += 1;
03205   buffer[*index] = (data >> 16) & 0xff;
03206   *index += 1;
03207   buffer[*index] = (data >> 24) & 0xff;
03208   *index += 1;
03209   
03210   return(*index);
03211 }
03212 
03213 /*
03214  *  stuffuchar -  stuffs an unsigned char into the send buffer
03215  *
03216  *  parameters:
03217  *     unsigned char data -- is the char to be stuffed
03218  *     unsigned char *buffer -- is the send buffer
03219  *     unsigned short *index -- is the buffer index which will be incremented
03220  *                              to reflect the bytes stuffed into the buffer
03221  */
03222 int stuffuchar(unsigned char data, unsigned char *buffer, unsigned short *index)
03223 {
03224   buffer[*index]   = data;
03225   
03226   *index += 1;
03227   
03228   return(*index);
03229 }
03230 
03231 /*
03232  *  stuff2byteuint - stuffs an unsigned short int(2 bytes) into the send buffer
03233  *
03234  *  parameters:
03235  *     unsigned short data -- is the value which will be split apart and 
03236  *                            stuffed bytewise into the send buffer
03237  *     unsigned char *buffer -- is the send buffer
03238  *     unsigned short *index -- is the buffer index which will be incremented
03239  *                              to reflect the bytes stuffed into the buffer
03240  */
03241 int stuff2byteuint(unsigned short data,
03242                    unsigned char *buffer, unsigned short *index)
03243 {
03244   buffer[*index]   = (data >> 0) & 0xff;
03245   *index += 1;
03246   buffer[*index]   = (data >> 8) & 0xff;
03247   *index += 1;
03248   
03249   return(*index);
03250 }
03251 
03252 /*
03253  *  stuff4byteuint - stuffs an unsigned long int(4 bytes) into the send buffer
03254  *
03255  *  parameters:
03256  *     unsigned long data -- is the value which will be split apart and stuffed
03257  *                           bytewise into the send buffer
03258  *     unsigned char *buffer -- is the send buffer
03259  *     unsigned short *index -- is the buffer index which will be incremented
03260  *                              to reflect the bytes stuffed into the buffer
03261  */
03262 int stuff4byteuint(unsigned long data,
03263                    unsigned char *buffer, unsigned short *index)
03264 {
03265   buffer[*index] = (data >> 0) & 0xff;
03266   *index += 1;
03267   buffer[*index] = (data >> 8) & 0xff;
03268   *index += 1;
03269   buffer[*index] = (data >> 16) & 0xff;
03270   *index += 1;
03271   buffer[*index] = (data >> 24) & 0xff;
03272   *index += 1;
03273   
03274   return(*index);
03275 }
03276 
03277 /*
03278  *  stuffdouble - stuffs a double(8 bytes) into the send buffer
03279  *
03280  *  parameters:
03281  *     double data -- is the value which will be split apart and stuffed
03282  *                    bytewise into the send buffer
03283  *     unsigned char *buffer -- is the send buffer
03284  *     unsigned short *index -- is the buffer index which will be incremented
03285  *                              to reflect the bytes stuffed into the buffer
03286  */
03287 int stuffdouble(double data, unsigned char *buffer, unsigned short *index)
03288 {
03289   unsigned long long *tempp, temp;
03290   
03291   /* Assume that double is 64 bits and "long long" is 64 bits. */
03292   tempp = (unsigned long long *)&data;
03293   temp = *tempp;
03294   
03295   buffer[*index] = (temp >> 0) & 0xff;
03296   *index += 1;
03297   buffer[*index] = (temp >> 8) & 0xff;
03298   *index += 1;
03299   buffer[*index] = (temp >> 16) & 0xff;
03300   *index += 1;
03301   buffer[*index] = (temp >> 24) & 0xff;
03302   *index += 1;
03303   buffer[*index] = (temp >> 32) & 0xff;
03304   *index += 1;
03305   buffer[*index] = (temp >> 40) & 0xff;
03306   *index += 1;
03307   buffer[*index] = (temp >> 48) & 0xff;
03308   *index += 1;
03309   buffer[*index] = (temp >> 56) & 0xff;
03310   *index += 1;
03311   
03312   return(*index);
03313 }
03314 
03315 /*
03316  *  extractchar -  extracts a char from the receive buffer
03317  *
03318  *  parameters:
03319  *     unsigned char *buffer -- is the receive buffer which holds the data
03320  *     unsigned short *index -- is the receive buffer index which will be
03321  *                              incremented to reflect the position of the
03322  *                              next piece of data to be extracted
03323  */
03324 signed char extractchar(unsigned char *buffer, unsigned short *index)
03325 {
03326   char data;
03327   
03328   data = buffer[*index];
03329   *index += 1;
03330   
03331   if (data & 0x80)
03332   {
03333     data &= 0x7f;
03334     data *= -1;
03335   }
03336   return(data);
03337 }
03338 
03339 /*
03340  *  extract2byteint -  extracts a short int(2 bytes) from the receive buffer
03341  *
03342  *  parameters:
03343  *     unsigned char *buffer -- is the receive buffer which holds the data
03344  *     unsigned short *index -- is the receive buffer index which will be
03345  *                              incremented to reflect the position of the
03346  *                              next piece of data to be extracted
03347  */
03348 signed short extract2byteint(unsigned char *buffer, unsigned short *index)
03349 {
03350   signed short data;
03351   
03352   data = (signed short)buffer[*index] << 0;
03353   *index += 1;
03354   data |= (signed short)buffer[*index] << 8;
03355   *index += 1;
03356   
03357   if (data & 0x8000)
03358   {
03359     data &= 0x7fff;
03360     data *= -1;
03361   }
03362   
03363   return(data);
03364 }
03365 
03366 /*
03367  *  extract4byteint -  extracts a long int(4 bytes) from the receive buffer
03368  *
03369  *  parameters:
03370  *     unsigned char *buffer -- is the receive buffer which holds the data
03371  *     unsigned short *index -- is the receive buffer index which will be
03372  *                              incremented to reflect the position of the
03373  *                              next piece of data to be extracted
03374  */
03375 signed long extract4byteint(unsigned char *buffer, unsigned short *index)
03376 {
03377   signed long data;
03378   
03379   data = (signed long)buffer[*index] << 0;
03380   *index += 1;
03381   data |= (signed long)buffer[*index] << 8;
03382   *index += 1;
03383   data |= (signed long)buffer[*index] << 16;
03384   *index += 1;
03385   data |= (signed long)buffer[*index] << 24;
03386   *index += 1;
03387   
03388   if (data & 0x80000000)
03389   {
03390     data &= 0x7fffffff;
03391     data *= -1;
03392   }
03393   
03394   return(data);
03395 }
03396 
03397 /*
03398  *  extractuchar -  extracts an unsigned char from the receive buffer
03399  *
03400  *  parameters:
03401  *     unsigned char *buffer -- is the receive buffer which holds the data
03402  *     unsigned short *index -- is the receive buffer index which will be
03403  *                              incremented to reflect the position of the
03404  *                              next piece of data to be extracted
03405  */
03406 unsigned char extractuchar(unsigned char *buffer, unsigned short *index)
03407 {
03408   unsigned char data;
03409   
03410   data = buffer[*index];
03411   
03412   *index += 1;
03413   
03414   return(data);
03415 }
03416 
03417 /*
03418  *  extract2byteuint -  extracts an unsigned short int(2 bytes) from the 
03419  *                      receive buffer
03420  *
03421  *  parameters:
03422  *     unsigned char *buffer -- is the receive buffer which holds the data
03423  *     unsigned short *index -- is the receive buffer index which will be
03424  *                              incremented to reflect the position of the
03425  *                              next piece of data to be extracted
03426  */
03427 unsigned short extract2byteuint(unsigned char *buffer, unsigned short *index)
03428 {
03429   unsigned short data;
03430   
03431   data = (unsigned short)buffer[*index] << 0;
03432   *index += 1;
03433   data |= (unsigned short)buffer[*index] << 8;
03434   *index += 1;
03435   
03436   return(data);
03437 }
03438 
03439 /*
03440  *  extract4byteuint -  extracts an unsigned long int(4 bytes) from the 
03441  *                      receive buffer
03442  *
03443  *  parameters:
03444  *     unsigned char *buffer -- is the receive buffer which holds the data
03445  *     unsigned short *index -- is the receive buffer index which will be
03446  *                              incremented to reflect the position of the
03447  *                              next piece of data to be extracted
03448  */
03449 unsigned long extract4byteuint(unsigned char *buffer, unsigned short *index)
03450 {
03451   unsigned long data;
03452   
03453   data = (unsigned long)buffer[*index] << 0;
03454   *index += 1;
03455   data |= (unsigned long)buffer[*index] << 8;
03456   *index += 1;
03457   data |= (unsigned long)buffer[*index] << 16;
03458   *index += 1;
03459   data |= (unsigned long)buffer[*index] << 24;
03460   *index += 1;
03461   
03462   return(data);
03463 }
03464 
03465 /*
03466  *  extractdouble -  extracts a double(8 bytes) from the receive buffer
03467  *
03468  *  parameters:
03469  *     unsigned char *buffer -- is the receive buffer which holds the data
03470  *     unsigned short *index -- is the receive buffer index which will be
03471  *                              incremented to reflect the position of the
03472  *                              next piece of data to be extracted
03473  */
03474 double extractdouble(unsigned char *buffer, unsigned short *index)
03475 {
03476   double data;
03477   unsigned long long *tempp, temp;
03478   
03479   /* Assume that double is 64 bits and long long is 64 bits. */
03480   
03481   temp = (unsigned long long)buffer[*index] << 0;
03482   *index += 1;
03483   temp |= (unsigned long long)buffer[*index] << 8;
03484   *index += 1;
03485   temp |= (unsigned long long)buffer[*index] << 16;
03486   *index += 1;
03487   temp |= (unsigned long long)buffer[*index] << 24;
03488   *index += 1;
03489   temp |= (unsigned long long)buffer[*index] << 32;
03490   *index += 1;
03491   temp |= (unsigned long long)buffer[*index] << 40;
03492   *index += 1;
03493   temp |= (unsigned long long)buffer[*index] << 48;
03494   *index += 1;
03495   temp |= (unsigned long long)buffer[*index] << 56;
03496   *index += 1;
03497   
03498   tempp = (unsigned long long *)&data;
03499   *tempp = temp;
03500   
03501   return(data);
03502 }
03503 
03504 /************************************************
03505  *                                              *
03506  * Global variable access functions for Allegro * 
03507  * Common Lisp interface                        *
03508  *                                              *
03509  ************************************************/
03510 
03511 int get_state(long state[NUM_STATE])
03512 {
03513   int i;
03514   
03515   for (i=0;i<NUM_STATE;i++) 
03516     state[i] = State[i];
03517   return(TRUE);
03518 }
03519 
03520 int get_laser(int laser[2*NUM_LASER+1])
03521 {
03522   int i;
03523 
03524   for (i=0;i<=Laser[0];i++) 
03525     laser[i] = Laser[i];
03526   return(TRUE);
03527 }
03528 
03529 int get_mask(int mask[NUM_MASK])
03530 {
03531   int i;
03532 
03533   for (i=0;i<44;i++) 
03534     mask[i] = usedSmask[i];
03535   return(TRUE);
03536 }
03537 
03538 int set_mask(int mask[NUM_MASK])
03539 {
03540   int i;
03541 
03542   for (i=0;i<NUM_MASK;i++) 
03543     Smask[i] = mask[i];
03544   return(TRUE);
03545 }
03546 
03547 int set_server_machine_name(char *sname)
03548 {
03549   strcpy(SERVER_MACHINE_NAME, sname);
03550   strcpy(Host_name, "");
03551   return(TRUE);
03552 }
03553 
03554 int set_serv_tcp_port(int port)
03555 {
03556   SERV_TCP_PORT = port;
03557   return(TRUE);
03558 }
03559 
03560 
03561 /*
03562  *
03563  * 
03564  *         PosData Attachment
03565  *         ===================
03566  *    
03567  *    Here all procudures are defined that deal with the 
03568  * 
03569  *    attachment of PosData to sensory readings.
03570  * 
03571  *
03572  */
03573 
03574 
03575 /***************
03576  * FUNCTION:     posDataRequest
03577  * PURPOSE:      request position information for sensors
03578  * ARGUMENTS:    int posRequest : 
03579  *               The argument of this function specifies the sensors 
03580  *               for which the position information (PosData) should 
03581  *               be attached to the sensory reading.
03582  *               Its value is obtained by ORing the desired defines. 
03583  * EXAMPLE:      To attach PosData to sonars and laser:
03584  *               posDataRequest ( POS_SONAR | POS_LASER );
03585  * ALGORITHM:    currently sets the global variable Smask[0] and
03586  *               then calls ct() to transmit the change to the server
03587  * RETURN:       TRUE if the argument was correct, else FALSE
03588  * SIDE EFFECT:  Smask[ SMASK_POS_DATA ]
03589  * CALLS:        
03590  * CALLED BY:    
03591  ***************/
03592 int posDataRequest ( int posRequest )
03593 {
03594   /* check if the argument is okay */
03595   if ( posRequest & 
03596       !( POS_INFRARED | POS_SONAR | POS_BUMPER | POS_LASER | POS_COMPASS ) )
03597     return ( FALSE );
03598 
03599   /* The value in Smask[ SMASK_POS_DATA ] is passed through entire system */
03600   Smask[ SMASK_POS_DATA ] = posRequest;
03601   ct();
03602 
03603   return ( TRUE );
03604 }
03605 
03606 /***************
03607  * FUNCTION:     posDataCheck
03608  * PURPOSE:      return the sensors for which the PosData attachment
03609  *               is currently requested. 
03610  * ARGUMENTS:    None
03611  * ALGORITHM:    returns the mask that is not globally accessibe and 
03612  *               that is set by ct() to be the value of Smask[0]
03613  * RETURN:       int, see posDataRequest
03614  *               the macros POS_*_P can be used to examine the value
03615  * SIDE EFFECT:  
03616  * CALLS:        
03617  * CALLED BY:    
03618  ***************/
03619 int posDataCheck ( void )
03620 {
03621   return ( usedSmask[ SMASK_POS_DATA ] );
03622 }
03623 
03624 /***************
03625  * FUNCTION:     posInfraredRingGet
03626  * PURPOSE:      copy the PosData for all infrareds to accessible memory
03627  * ARGUMENTS:    PosData posData [INFRAREDS] :
03628  *               an array of PosData structures that is filled with 
03629  *               PosData. The position information for each infrared
03630  *               containts the configuration of the robot at the time 
03631  *               of the sensory reading and a timestamp for the 
03632  *               configuration and the senosry reading .
03633  * ALGORITHM:    copies blocks of memory
03634  * RETURN:       int, return always TRUE
03635  * SIDE EFFECT:  
03636  * CALLS:        
03637  * CALLED BY:    
03638  ***************/
03639 int posInfraredRingGet ( PosData posData[INFRAREDS] )
03640 {
03641   /* copy the whole thing in one block */
03642   memcpy ( posData, posDataAll.infrared, INFRAREDS * sizeof ( PosData ) );
03643 
03644   return ( TRUE );
03645 }
03646 
03647 
03648 /***************
03649  * FUNCTION:     posInfraredGet
03650  * PURPOSE:      copy the PosData for a specific infrared to accessible 
03651  *               memory
03652  * ARGUMENTS:    int infraredNumber : the number of the infrared
03653  *               PosData *posData : the memory location that the information
03654  *                                  will be copied to 
03655  * ALGORITHM:    copies block of memory
03656  * RETURN:       int, always returns TRUE
03657  * SIDE EFFECT:  
03658  * CALLS:        
03659  * CALLED BY:    
03660  ***************/
03661 int posInfraredGet     ( PosData *posData , int infraredNumber)
03662 {
03663   /* copy the whole thing in one block */
03664   memcpy ( posData, &posDataAll.infrared[infraredNumber], sizeof ( PosData ) );
03665 
03666   return ( TRUE );
03667 }
03668 
03669 /***************
03670  * FUNCTION:     posSonarRingGet
03671  * PURPOSE:      copy the PosData for all sonars to accessible memory
03672  * ARGUMENTS:    PosData posData [SONARS] :
03673  *               an array of PosData structures that is filled with 
03674  *               PosData. The position information for each sonar
03675  *               containts the configuration of the robot at the time 
03676  *               of the sensory reading and a timestamp for the 
03677  *               configuration and the senosry reading .
03678  * ALGORITHM:    copies blocks of memory
03679  * RETURN:       int, return always TRUE
03680  * SIDE EFFECT:  
03681  * CALLS:        
03682  * CALLED BY:    
03683  ***************/
03684 int posSonarRingGet    ( PosData posData[SONARS] )
03685 {
03686   /* copy the whole thing in one block */
03687   memcpy ( posData, posDataAll.sonar, SONARS * sizeof ( PosData ) );
03688 
03689   return ( TRUE );
03690 }
03691 
03692 /***************
03693  * FUNCTION:     posSonarGet
03694  * PURPOSE:      copy the PosData for a specific sonar to accessible memory
03695  * ARGUMENTS:    int infraredNumber : the number of the sonar
03696  *               PosData *posData : the memory location that the information
03697  *                                  will be copied to 
03698  * ALGORITHM:    copies block of memory
03699  * RETURN:       int, always returns TRUE
03700  * SIDE EFFECT:  
03701  * CALLS:        
03702  * CALLED BY:    
03703  ***************/
03704 int posSonarGet        ( PosData *posData , int sonarNumber)
03705 {
03706   /* copy the whole thing in one block */
03707   memcpy ( posData, &posDataAll.sonar[sonarNumber], sizeof ( PosData ) );
03708 
03709   return ( TRUE );
03710 }
03711 
03712 /***************
03713  * FUNCTION:     posBumperGet
03714  * PURPOSE:      copy PosData for the bumper to accessible memory
03715  * ARGUMENTS:    PosData *posData : where the data is copied to 
03716  * ALGORITHM:    copies a block of memory
03717  * RETURN:       int, always returns TRUE
03718  * SIDE EFFECT:  
03719  * CALLS:        
03720  * CALLED BY:    
03721  * NOTE:         The bumper differs from other sensors in that the 
03722  *               posData is only updated after one of the bumper sensors 
03723  *               change its value from zero to one. This means that the 
03724  *               posData for the bumper always contains the position and 
03725  *               timeStamps of the latest hit, or undefined information 
03726  *               if the bumper was not hit yet.
03727  ***************/
03728 int posBumperGet       ( PosData *posData )
03729 {
03730   /* copy the whole thing in one block */
03731   memcpy ( posData, &posDataAll.bumper, sizeof ( PosData ) );
03732 
03733   return ( TRUE );
03734 }
03735 
03736 /***************
03737  * FUNCTION:     posLaserGet
03738  * PURPOSE:      copy PosData for the laser to accessible memory
03739  * ARGUMENTS:    PosData *posData : where the data is copied to 
03740  * ALGORITHM:    copies a block of memory
03741  * RETURN:       int, always returns TRUE
03742  * SIDE EFFECT:  
03743  * CALLS:        
03744  * CALLED BY:    
03745  * NOTE:         The laser is updated at a frequency of 30Hz.
03746  ***************/
03747 int posLaserGet        ( PosData *posData )
03748 {
03749   /* copy the whole thing in one block */
03750   memcpy ( posData, &posDataAll.laser, sizeof ( PosData ) );
03751 
03752   return ( TRUE );
03753 }
03754 
03755 /***************
03756  * FUNCTION:     posCompassGet
03757  * PURPOSE:      copy PosData for the compass to accessible memory
03758  * ARGUMENTS:    PosData *posData : where the data is copied to 
03759  * ALGORITHM:    copies a block of memory
03760  * RETURN:       int, always returns TRUE
03761  * SIDE EFFECT:  
03762  * CALLS:        
03763  * CALLED BY:    
03764  * NOTE:         The compass is updated ad a frequency of 10Hz.
03765  ***************/
03766 int posCompassGet      ( PosData *posData )
03767 {
03768   /* copy the whole thing in one block */
03769   memcpy ( posData, &posDataAll.compass, sizeof ( PosData ) );
03770 
03771   return ( TRUE );
03772 }
03773 
03774 /***************
03775  * FUNCTION:     posTimeGet
03776  * PURPOSE:      get the PosData time (Intellisys 100) in milliseconds
03777  * ARGUMENTS:    None
03778  * ALGORITHM:    ---
03779  * RETURN:       int 
03780  * SIDE EFFECT:  
03781  * CALLS:        
03782  * CALLED BY:    
03783  * NOTE:         Use POS_TICKS_TO_MS and POS_MS_TO_TICKS to convert
03784  *               between ticks and milliseconds. Overflow after 49 days.
03785  ***************/
03786 int posTimeGet         ( void )
03787 {
03788   return ( (int) posDataTime );
03789 }
03790 
03791 /***************
03792  * FUNCTION:     voltCpuGet
03793  * PURPOSE:      get the voltage of the power supply for the CPU
03794  * ARGUMENTS:    None
03795  * ALGORITHM:    ---
03796  * RETURN:       float (the voltage in volt)
03797  * SIDE EFFECT:  
03798  * CALLS:        
03799  * CALLED BY:    
03800  ***************/
03801 float voltCpuGet         ( void )
03802 {
03803   return ( voltConvert ( voltageCPU , RANGE_CPU_VOLTAGE ) );
03804 }
03805 
03806 /***************
03807  * FUNCTION:     voltMotorGet
03808  * PURPOSE:      get the voltage of the power supply for the motors
03809  * ARGUMENTS:    None
03810  * ALGORITHM:    ---
03811  * RETURN:       float (the voltage in volt)
03812  * SIDE EFFECT:  
03813  * CALLS:        
03814  * CALLED BY:    
03815  ***************/
03816 float voltMotorGet         ( void )
03817 {
03818   return ( voltConvert ( voltageMotor , RANGE_MOTOR_VOLTAGE ) );
03819 }
03820 
03821 /***************
03822  * FUNCTION:     voltConvert
03823  * PURPOSE:      convert from the DA reading to the right voltage range
03824  * ARGUMENTS:    unsigned char reading: the reading of the da
03825  * ALGORITHM:    ---
03826  * RETURN:       float (the voltage in volt)
03827  * SIDE EFFECT:  
03828  * CALLS:        
03829  * CALLED BY:    
03830  ***************/
03831 static float voltConvert ( unsigned char reading , float range )
03832 {
03833   /* 
03834    * original reading is [0...255] and represents [2...5]volt.
03835    * the 5 volt value is converted to 12V by multiplying (range/5)
03836    */
03837   return ( ( 2.0 +  ( ( (float) (reading*3) ) / 255.0 ) ) * ( range / 5.0 ) );
03838 }
03839 
03840 
03841 /****************************************************************/
03842 
03843 
03844 
03845 long arm_zr(short override)
03846 {
03847   long result;
03848 
03849   short b_index, b_length;
03850   unsigned char serial_number;
03851   unsigned char packet_type;
03852   unsigned char user_send_buffer[256];
03853   unsigned char user_receive_buffer[256];
03854 
03855   init_send_buffer(&b_index);
03856 
03857   stuff2byteuint(override, user_send_buffer, &b_index);
03858   stuff_send_buffer_header(b_index, 0, ARM_ZR, user_send_buffer);
03859   
03860   special_request(user_send_buffer, user_receive_buffer);
03861 
03862   init_receive_buffer(&b_index);
03863   extract_receive_buffer_header(&b_length, &serial_number, &packet_type,
03864                                 user_receive_buffer);
03865 
03866   result=extract4byteuint(user_receive_buffer, &b_index);
03867   return result;
03868 }
03869 
03870 long arm_ws(short l, short g, long timeout, long *time_remain)
03871 {
03872   long result;
03873 
03874   short b_index, b_length;
03875   unsigned char serial_number;
03876   unsigned char packet_type;
03877   unsigned char user_send_buffer[256];
03878   unsigned char user_receive_buffer[256];
03879 
03880   init_send_buffer(&b_index);
03881 
03882   stuff2byteuint(l, user_send_buffer, &b_index);
03883   stuff2byteuint(g, user_send_buffer, &b_index);
03884   stuff4byteuint(timeout, user_send_buffer, &b_index);
03885   stuff_send_buffer_header(b_index, 0, ARM_WS, user_send_buffer);
03886   
03887   special_request(user_send_buffer, user_receive_buffer);
03888 
03889   init_receive_buffer(&b_index);
03890   extract_receive_buffer_header(&b_length, &serial_number, &packet_type,
03891                                 user_receive_buffer);
03892 
03893   result=extract4byteuint(user_receive_buffer, &b_index);
03894   if (time_remain)
03895     *time_remain=extract4byteuint(user_receive_buffer, &b_index);
03896 
03897   return result;
03898 }
03899 
03900 
03901 long arm_mv(long l_mode, long l_v, long g_mode, long g_v)
03902 {
03903   long result;
03904 
03905   short b_index, b_length;
03906   unsigned char serial_number;
03907   unsigned char packet_type;
03908   unsigned char user_send_buffer[256];
03909   unsigned char user_receive_buffer[256];
03910 
03911   init_send_buffer(&b_index);
03912 
03913   stuff4byteuint(l_mode, user_send_buffer, &b_index);
03914   stuff4byteuint(l_v, user_send_buffer, &b_index);
03915   stuff4byteuint(g_mode, user_send_buffer, &b_index);
03916   stuff4byteuint(g_v, user_send_buffer, &b_index);
03917   stuff_send_buffer_header(b_index, 0, ARM_MV, user_send_buffer);
03918   
03919   special_request(user_send_buffer, user_receive_buffer);
03920 
03921   init_receive_buffer(&b_index);
03922   extract_receive_buffer_header(&b_length, &serial_number, &packet_type,
03923                                 user_receive_buffer);
03924 
03925   result=extract4byteuint(user_receive_buffer, &b_index);
03926 
03927   return result;
03928 }


scout_ndirect
Author(s): Gonçalo Cabrita and Pedro Sousa
autogenerated on Mon Jan 6 2014 11:25:23