sip.cc

00001 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:1; -*-
00002 
00022 #include <stdio.h>
00023 #include <limits.h>
00024 #include <math.h>  /* rint(3) */
00025 #include <sys/types.h>
00026 #include <netinet/in.h>
00027 #include "sip.h"
00028 #include <stdlib.h> /* for abs() */
00029 #include <unistd.h>
00030 
00031 int erSIP::PositionChange( unsigned short from, unsigned short to ) 
00032 {
00033   int diff1, diff2;
00034 
00035   /* find difference in two directions and pick shortest */
00036   if ( to > from ) {
00037     diff1 = to - from;
00038     diff2 = - ( from + 4096 - to );
00039   }
00040   else {
00041     diff1 = to - from;
00042     diff2 = 4096 - from + to;
00043   }
00044 
00045   if ( abs(diff1) < abs(diff2) ) 
00046     return(diff1);
00047   else
00048     return(diff2);
00049 
00050 }
00051 
00052 void erSIP::Print() 
00053 {
00054   printf("lwstall:%d rwstall:%d\n", lwstall, rwstall);
00055 
00056   printf("status: 0x%x", status);
00057   printf("battery: %d\n", battery);
00058   printf("xpos: %d ypos:%d ptu:%hu timer:%hu\n", xpos, ypos, ptu, timer);
00059   printf("angle: %d lvel: %d rvel: %d control: %d\n", angle, lvel, rvel, control);
00060 }
00061 
00062 // Parses and absorbs a standard packet from the robot
00063 bool erSIP::Parse( unsigned char *buffer, int length ) 
00064 {
00065   int cnt = 0, change;
00066   unsigned short newxpos, newypos;
00067 
00068         // Check type and length
00069         if (length < 20) return false;
00070 
00071   status = buffer[cnt];
00072   cnt += sizeof(unsigned char);
00073 
00074   // This driver does its own integration, and only cares for the lower bits of the odometry updates
00075         // Integers from robot are little-endian
00076   newxpos = buffer[cnt] + 0x100*(buffer[cnt+1]&0x0F);
00077 
00078   if (xpos!=INT_MAX) {
00079     change = (int) rint(PositionChange( rawxpos, newxpos ) * RobotParams[param_idx]->DistConvFactor);
00080     //printf("xchange: %i ", change);
00081     if (abs(change)>100)
00082       ;//PLAYER_WARN1("invalid odometry change [%d]; odometry values are tainted", change);
00083     else
00084       xpos += change;
00085   }
00086   else {
00087     //printf("xpos was INT_MAX\n");
00088                 xpos = 0;
00089         }
00090   rawxpos = newxpos;
00091   cnt += 3;
00092 
00093   
00094   newypos = buffer[cnt] + 0x100*(buffer[cnt+1]&0x0F);
00095 
00096   if (ypos!=INT_MAX) {
00097     change = (int) rint(PositionChange( rawypos, newypos ) * RobotParams[param_idx]->DistConvFactor);
00098     if (abs(change)>100)
00099       ;//PLAYER_WARN1("invalid odometry change [%d]; odometry values are tainted", change);
00100     else
00101       ypos += change;
00102   }
00103   else
00104     ypos = 0;
00105   rawypos = newypos;
00106   cnt += 3;
00107 
00108         //if (debug_mode)
00109         //      printf("Just parsed, new xpos: %i ypos: %i\n", xpos, ypos);
00110 
00111   angle = (short)
00112     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00113          M_PI/2048.0 * 180.0/M_PI);
00114   cnt += sizeof(short);
00115 
00116   lvel = (short)
00117     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00118          RobotParams[param_idx]->VelConvFactor);
00119   cnt += sizeof(short);
00120 
00121   rvel = (short)
00122     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00123          RobotParams[param_idx]->VelConvFactor);
00124   cnt += sizeof(short);
00125 
00126   battery = buffer[cnt];
00127   cnt += sizeof(unsigned char);
00128   
00129   lwstall = buffer[cnt] & 0x01;
00130   cnt += sizeof(unsigned char);
00131   
00132   rwstall = buffer[cnt] & 0x01;
00133   cnt += sizeof(unsigned char);
00134 
00135   control = (short)
00136     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00137          RobotParams[param_idx]->AngleConvFactor);
00138   cnt += sizeof(short);
00139 
00140         return true;
00141 }
00142 
00143 // Spits out information that was previously parsed
00144 void erSIP::Fill(player_erratic_data_t* data)
00145 {
00146         // Odometry data
00147         {
00148                 // initialize position to current offset
00149                 data->position.pos.px = this->x_offset / 1e3;
00150                 data->position.pos.py = this->y_offset / 1e3;
00151                 // now transform current position by rotation if there is one
00152                 // and add to offset
00153                 if(this->angle_offset != 0) 
00154                 {
00155                         double rot = DTOR(this->angle_offset);    // convert rotation to radians
00156                         data->position.pos.px +=  ((this->xpos/1e3) * cos(rot) - 
00157                                 (this->ypos/1e3) * sin(rot));
00158                         data->position.pos.py +=  ((this->xpos/1e3) * sin(rot) + 
00159                                 (this->ypos/1e3) * cos(rot));
00160                         data->position.pos.pa = DTOR(this->angle_offset + angle);
00161                 }
00162                 else 
00163                 {
00164                         data->position.pos.px += this->xpos / 1e3;
00165                         data->position.pos.py += this->ypos / 1e3;
00166                         data->position.pos.pa = DTOR(this->angle);
00167                 }
00168                 data->position.vel.px = (((this->lvel) + (this->rvel) ) / 2) / 1e3;
00169                 data->position.vel.py = 0.0;
00170                 data->position.vel.pa = (0.596*(double)(this->rvel - this->lvel) /
00171                         (2.0/RobotParams[param_idx]->DiffConvFactor));
00172                 data->position.stall = (unsigned char)(this->lwstall || this->rwstall);
00173         }
00174 
00175   // Battery data
00176         {
00177           data->power.valid = PLAYER_POWER_MASK_VOLTS | PLAYER_POWER_MASK_PERCENT;
00178         data->power.volts = this->battery / 1e1;
00179         data->power.percent = 1e2 * (data->power.volts / VIDERE_NOMINAL_VOLTAGE);
00180         }
00181 }
00182 

Last updated 12 September 2005 21:38:45