motorpacket.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 "motorpacket.h"
00028 #include <stdlib.h> /* for abs() */
00029 #include <unistd.h>
00030 
00031 int ErraticMotorPacket::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 ErraticMotorPacket::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 ErraticMotorPacket::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 
00075   // of the odometry updates
00076   // Integers from robot are little-endian
00077   newxpos = buffer[cnt] + 0x100*(buffer[cnt+1]&0x0F);
00078 
00079   if (xpos!=INT_MAX) {
00080     change = (int) rint(PositionChange( rawxpos, newxpos ) * RobotParams[param_idx]->DistConvFactor);
00081     //printf("xchange: %i ", change);
00082     if (abs(change)>100)
00083       ;//PLAYER_WARN1("invalid odometry change [%d]; odometry values are tainted", change);
00084     else
00085       xpos += change;
00086   }
00087   else {
00088     //printf("xpos was INT_MAX\n");
00089                 xpos = 0;
00090         }
00091   rawxpos = newxpos;
00092   cnt += 3;
00093 
00094   
00095   newypos = buffer[cnt] + 0x100*(buffer[cnt+1]&0x0F);
00096 
00097   if (ypos!=INT_MAX) {
00098     change = (int) rint(PositionChange( rawypos, newypos ) * RobotParams[param_idx]->DistConvFactor);
00099     if (abs(change)>100)
00100       ;//PLAYER_WARN1("invalid odometry change [%d]; odometry values are tainted", change);
00101     else
00102       ypos += change;
00103   }
00104   else
00105     ypos = 0;
00106   rawypos = newypos;
00107   cnt += 3;
00108 
00109         //if (debug_mode)
00110   //  printf("Just parsed, new xpos: %i ypos: %i\n", xpos, ypos);
00111 
00112   //  angle = (short)
00113   //    rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00114   //     M_PI/2048.0 * 180.0/M_PI);
00115   angle = (short)(buffer[cnt] | (buffer[cnt+1] << 8)); // keep as 4096 / full turn
00116 
00117   cnt += sizeof(short);
00118 
00119   lvel = (short)
00120     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00121          RobotParams[param_idx]->VelConvFactor);
00122   cnt += sizeof(short);
00123 
00124   rvel = (short)
00125     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00126          RobotParams[param_idx]->VelConvFactor);
00127   cnt += sizeof(short);
00128 
00129   battery = buffer[cnt];
00130   cnt += sizeof(unsigned char);
00131   
00132   lwstall = buffer[cnt] & 0x01;
00133   cnt += sizeof(unsigned char);
00134   
00135   rwstall = buffer[cnt] & 0x01;
00136   cnt += sizeof(unsigned char);
00137 
00138   control = (short)
00139     rint(((short)(buffer[cnt] | (buffer[cnt+1] << 8))) *
00140          RobotParams[param_idx]->AngleConvFactor);
00141   cnt += sizeof(short);
00142 
00143         return true;
00144 }
00145 
00146 // Spits out information that was previously parsed
00147 void ErraticMotorPacket::Fill(player_erratic_data_t* data)
00148 {
00149   // Odometry data
00150   {
00151     // initialize position to current offset
00152     data->position.pos.px = (double)(this->xpos - this->x_offset) / 1e3;
00153     data->position.pos.py = (double)(this->ypos - this->y_offset) / 1e3;
00154     // now transform current position by rotation if there is one
00155     // and add to offset
00156     if(this->angle_offset != 0) 
00157       {
00158         double rot = ATOR(this->angle_offset);    // convert rotation to radians
00159         double ax = data->position.pos.px;
00160         double ay = data->position.pos.py;
00161         data->position.pos.px =  ax * cos(rot) + ay * sin(rot);
00162         data->position.pos.py = -ax * sin(rot) + ay * cos(rot);
00163         data->position.pos.pa = ATOR(angle - this->angle_offset);
00164       }
00165     else
00166       data->position.pos.pa = ATOR(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