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


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