Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

AshtechG12_GPS_PhysicalDevice.cpp

Go to the documentation of this file.
00001 /************************************************************************************************/
00002 /*! \file AshtechG12_GPS_PhysicalDevice.h
00003 *  \brief Get the Satellite Position
00004 *  \author $Author: jayhawk_hokie $
00005 *  \version $Revision: 1.1 $
00006 *  \date    $Date: 2007/08/31 16:10:54 $
00007 ************************************************************************************************/
00008 /*!
00009 *
00010 ************************************************************************************************/
00011 
00012 #include "AshtechG12_GPS_PhysicalDevice.h"
00013 
00014 
00015 //////////////////////////////////////////
00016 /// Commands for G12 GPS Receiver
00017 /////////////////////////////////////////
00018 
00019 /*! \brief Default constructor. Object will be useless until <code>Connect()</code>
00020  *   is called.
00021  */
00022 //AshtechG12_GPS_PhysicalDevice::AshtechG12_GPS_PhysicalDevice(){}
00023 
00024 /*! \brief Default constructor. Object will be useless until <code>Connect()</code>
00025  *   is called.
00026  */
00027 AshtechG12_GPS_PhysicalDevice::AshtechG12_GPS_PhysicalDevice( )
00028     : m_clientSocket( NULL )
00029 {
00030 }
00031 
00032 /*! \brief Constructs the device and calls Connect().  This method has no return
00033  *  value so failures in the Connect() method may not be reported.  If
00034  * failures must be handled, you should use the default constructor and
00035  * call Connect() explicitly.
00036  *
00037  * @param serverName argument is the hostname or dotted decimal IP address at
00038  * which GPS Receiver is to be found.  The port number is presumed to be the
00039  * default port.
00040  */
00041 AshtechG12_GPS_PhysicalDevice::AshtechG12_GPS_PhysicalDevice( const char *serverName )
00042    : m_clientSocket( NULL )
00043 {
00044         Connect( serverName );
00045 }
00046 
00047 
00048 /*! \brief Constructs the device and calls Connect().  This method has no return
00049  *  value so failures in the Connect() method may not be reported.  If
00050  * failures must be handled, you should use the default constructor and
00051  * call Connect() explicitly.
00052  *
00053  * @param serverName argument is the hostname or dotted decimal IP address at
00054  * which GPS Receiver is to be found.  The port number is presumed to be the
00055  * default port.
00056  * @param port
00057  */
00058 AshtechG12_GPS_PhysicalDevice::AshtechG12_GPS_PhysicalDevice( const char *serverName, int port )
00059    : m_clientSocket( NULL )
00060 {
00061         Connect( serverName, port );
00062 }
00063 
00064 /*! \brief Destroys the AshtechG12_GPS_PhysicalDevice.
00065  */
00066 AshtechG12_GPS_PhysicalDevice::~AshtechG12_GPS_PhysicalDevice( )
00067 {
00068         delete m_clientSocket;
00069 }
00070 
00071 
00072 /*! \brief Attempts to connect the physical device to GPS Receiver.
00073  *
00074  * @param serverName argument is the hostname or dotted decimal IP address at
00075  * which SimGEN is to be found.  The port number is presumed to be the
00076  * default port.
00077  * @return 0 on success or -1 on failure.
00078  */
00079 int AshtechG12_GPS_PhysicalDevice::Connect( const char *serverName )
00080 {
00081         return this->Connect( serverName, DEFAULT_PORT );
00082 }
00083 
00084 
00085 /*! \brief Attempts to connect the physical device to GPS Receiver.
00086  *
00087  * @param serverName argument is the hostname or dotted decimal IP address at
00088  * which GPS Receiver is to be found.
00089  * @param portNumber argument is the port to access on the server.
00090  * @return 0 on success or -1 on failure.
00091  */
00092 int AshtechG12_GPS_PhysicalDevice::Connect( const char *serverName, int portNumber )
00093 {
00094         int returnValue = -1;
00095 
00096         try
00097         {
00098 
00099                 if ( m_clientSocket != NULL)
00100                 {
00101                         delete m_clientSocket;
00102                 }
00103 
00104                 m_clientSocket = new ClientSocket;
00105 
00106                 m_clientSocket -> Connect( serverName, portNumber );
00107         }
00108         catch ( SocketException& error )
00109         {
00110                 std::cout << "Exception was caught: " << error.description( ) << "\n";
00111                 return( returnValue );
00112         }
00113         returnValue = 0;
00114         return( returnValue );
00115 }
00116 
00117 
00118 int AshtechG12_GPS_PhysicalDevice::Send_i( const char *data )
00119 {
00120         return this->Send_i(data, strlen(data));
00121 }
00122 
00123 
00124 int AshtechG12_GPS_PhysicalDevice::Send_i( const char *data, unsigned int len )
00125 {
00126         int returnValue = -1;
00127 
00128         /* Record the time of this transmission. */
00129         //m_lastSendTime = Now( );
00130         
00131         string strData;
00132 
00133         strData.assign(data,  data + len );
00134 
00135         try
00136         {
00137                 *m_clientSocket << strData;
00138         }
00139         catch ( SocketException& error )
00140         {
00141                 std::cout << "Exception was caught: " << error.description( ) << "\n";
00142                 return( returnValue );
00143         }
00144 
00145         returnValue = strData.length( );
00146         return ( returnValue );
00147 }
00148 
00149 
00150 
00151 /*! \brief Send Command to GPS Receiver through the GPS Server.
00152  *  @param sock
00153  *  @param buf
00154  *  @return 0=success, -1=failure
00155  *
00156 int AshtechG12_GPS_PhysicalDevice::SendInfo(int sock, char* buf)
00157 {
00158         int echolen = strlen(buf);
00159         int status = 0; // status of send command 
00160         if (send(sock, buf, echolen, 0) != echolen) {
00161                 status = -1;
00162                 }
00163         return (status);
00164 }
00165 */
00166 
00167 int AshtechG12_GPS_PhysicalDevice::Recv_i( char buf[], unsigned int len )
00168 {
00169 
00170         int returnValue = -1;
00171 
00172         std::string buffer;
00173 
00174         try
00175         {
00176                 *m_clientSocket >> buffer;
00177         }
00178         catch ( SocketException& error )
00179         {
00180                 std::cout << "Exception was caught: " << error.description( ) << "\n";
00181                 return( returnValue );
00182         }
00183 
00184         returnValue = buffer.length( );
00185         char* tmp = new char [ len-1 ];
00186         strcpy( tmp, buffer.c_str() );
00187 
00188         for( int i=0; i<returnValue+1; i++ )
00189         {
00190                 buf[i] =  tmp[i];
00191 
00192         }
00193 
00194         delete [ ] tmp;
00195         buf[ returnValue+1 ] ='\0';
00196 
00197         return ( returnValue );
00198 }
00199 
00200 
00201 /*! \brief Receive Data from Server
00202  *  @param sock
00203  *  @param buf
00204  *  @parm bufsize 
00205  *  @return 0=success, -1=failure
00206  *
00207 int AshtechG12_GPS_PhysicalDevice::RecvInfo(int sock, char *buf, int bufsize){
00208         int bytes = 0;
00209         int status = 0; // status of send command 
00210         if ((bytes = recv(sock, buf, bufsize-1, 0)) < 1) {
00211                 status = -1;
00212                 }
00213         buf[bufsize-1] = '\0';        // Assure null terminated string
00214         return (status);
00215         }
00216 */
00217 
00218 
00219 /*! \brief Sends the $PASHQ,POS command to the G12. Queries the G12 for its present
00220  *   position.
00221  *  @param pos The position object to be populated from the G12's state
00222  *  @param sock
00223  *  @return 0=success, -1=command failure, -2=ambiguous response, -3=serial read error
00224  */
00225 //int AshtechG12_GPS_PhysicalDevice::GetCurrentPosition( Position &pos, int sock )
00226 int AshtechG12_GPS_PhysicalDevice::GetCurrentPosition( Position &pos )
00227 {
00228         int BUFSIZE=200;
00229         int sendStatus;
00230         int recvStatus;
00231         int posStatus;
00232         int status=0;
00233         char *RESPONSE = (char*)malloc(sizeof(char)*BUFSIZE);
00234         /// Command to be sent to GPS Receiver
00235         const char *COMMAND = "$PASHQ,POS\r\n\0";
00236         /// Send Command to GPS Receiver Server
00237         if ( (sendStatus = Send_i( COMMAND ) ) <= 0) 
00238         {
00239                 status = -1;
00240         }
00241         //if ((sendStatus = SendInfo(sock, COMMAND)) != 0) {
00242         //      status = -1;
00243         //        }
00244 
00245         /// Retrieve Command from GPS Receiver Server
00246         if ( ( recvStatus = Recv_i( RESPONSE, BUFSIZE ) ) <= 0 ) 
00247         {
00248                 status = -2;
00249         }
00250         //if ((recvStatus = RecvInfo(sock, RESPONSE, BUFSIZE)) != 0) {
00251         //      status = -2;
00252         //      }
00253 
00254         /// Parse RESPONSE Character Array 
00255         if ( ( posStatus = pos.SetFromPOS_Message( RESPONSE ) ) != 0) 
00256         {
00257                 status = -3;
00258         }
00259         
00260         // Free Mememory
00261         // free(COMMAND); // causing seg fault
00262         free(RESPONSE);
00263 
00264         return (status);
00265 //      return pos.SetFromPOS_Message(buf);
00266 }
00267 
00268 /*! \brief Verifies that a message string matches its embedded checksum. The
00269  *   complete, including header and terminating linefeed, should be passed.
00270  *  @param message The complete message for which checksum is computed
00271  *  @return 0=success,-1=bad checksum,-2=unable to extract checksum
00272  */
00273 int AshtechG12_GPS_PhysicalDevice::ValidateChecksum(const char *message)
00274 {
00275         if (message == NULL)
00276         {
00277                 cout << " ERROR Checksum" << endl;
00278                 //ACE_ERROR_RETURN((LM_ERROR,
00279                 //      "(%N:%l): Can't read checksum from NULL pointer!\n"), -2);
00280         }
00281 
00282         int msgBodyLen=strlen(message)-5;
00283         if (msgBodyLen < 0)
00284         {
00285                 cout << " ERROR Checksum" << endl;
00286                 //ACE_ERROR_RETURN((LM_ERROR,
00287                 //      "(%N:%l): Can't read checksum: message too short!\n"), -2);
00288         }
00289 
00290         int checksum;
00291     if (sscanf(message+msgBodyLen, "*%2x\r\n", &checksum) != 1)
00292         {
00293                 return -2;
00294         }
00295 
00296     // Checksum starts at message[1] because the leading '$' is omitted.
00297         unsigned char computedChecksum=0;
00298         for (int i=1; i < msgBodyLen; ++i)
00299         {
00300                 computedChecksum ^= (unsigned char)message[i];
00301         }
00302 
00303         if (checksum != computedChecksum)
00304         {
00305                 return -1;
00306         }
00307 
00308         return 0;
00309 }
00310 
00311 /**
00312 *  Receives an acknowledge or not-acknowledge reply to a synchronous command.
00313 * This method will throw away all input leading up to the first dollar-sign
00314 * before parsing reply.  It assumes the port is not sending any query replies
00315 * concurrently.
00316 * @return 0=acknowledge, -1=not-acknowledge, -2=other(unknown) reply, -3=error while reading
00317 */
00318 /*
00319 int AshtechG12_GPS_PhysicalDevice::RecvAckNak()
00320 {
00321         static char ACK[] = "$PASHR,ACK*3D\r\n";
00322         static char NAK[] = "$PASHR,NAK*30\r\n";
00323         char buf[16];
00324         
00325         int status;
00326         do
00327         {
00328                 status = m_pPortA->recv_n(buf, 1);
00329                 if (status == -1)
00330                 {
00331                         return -3;
00332                 }
00333         } while (buf[0] != '$');
00334         
00335         status = m_pPortA->recv_n(buf+1, sizeof(buf)-2);
00336         if (status == -1)
00337         {
00338                 return -3;
00339         }
00340         buf[status+1]='\0';
00341         
00342         if (!strcmp(ACK, buf))
00343         {
00344                 return 0;
00345         }
00346         else if (!strcmp(NAK, buf))
00347         {
00348                 return -1;
00349         }
00350         
00351         return -2;
00352 }
00353 */
00354 
00355 /*
00356 /// Set Dynamics Limits of GPS Receiver
00357 /// For satellite suggested values (1000 m/s, 10 m/s^2)
00358 int AshtechG12_GPS_PhysicalDevice::SendDynamicLimitsSetCmd(int vel, int accel)
00359 {
00360         char buf[23];
00361         sprintf(buf, "$PASHS,DYN,%d,%d\r\n", vel, accel);
00362         return (1); // RecvAckNak();
00363 }
00364 */
00365 
00366 
00367 
00368 AshtechG12_GPS_PhysicalDevice::Position::Position()
00369         : m_RTCM('\0'), m_numSatellites(0), m_UTC_Timetag(0.0F), m_latitude(0.0F),
00370           m_latitudeSector('N'), m_longitude(0.0F), m_longitudeSector('E'),
00371           m_altitude(0.0F), m_groundTrack(0.0F), m_groundSpeed(0.0F),
00372           m_verticalVelocity(0.0F), m_PDOP(0.0F), m_HDOP(0.0F), m_VDOP(0.0F),
00373           m_TDOP(0.0F)
00374 {
00375 }
00376 
00377 
00378 AshtechG12_GPS_PhysicalDevice::Position::Position(const Position &other)
00379         : m_RTCM(other.m_RTCM), m_numSatellites(other.m_numSatellites),
00380           m_UTC_Timetag(other.m_UTC_Timetag), m_latitude(other.m_latitude),
00381           m_latitudeSector(other.m_latitudeSector),
00382           m_longitude(other.m_longitude),
00383           m_longitudeSector(other.m_longitudeSector),
00384           m_altitude(other.m_altitude), m_groundTrack(other.m_groundTrack),
00385           m_groundSpeed(other.m_groundSpeed),
00386           m_verticalVelocity(other.m_verticalVelocity), m_PDOP(other.m_PDOP),
00387           m_HDOP(other.m_HDOP), m_VDOP(other.m_VDOP), m_TDOP(other.m_TDOP)
00388 {
00389 }
00390 
00391 
00392 AshtechG12_GPS_PhysicalDevice::Position::Position(const char *message)
00393         : m_RTCM('\0'), m_numSatellites(0), m_UTC_Timetag(0.0F), m_latitude(0.0F),
00394           m_latitudeSector('N'), m_longitude(0.0F), m_longitudeSector('E'),
00395           m_altitude(0.0F), m_groundTrack(0.0F), m_groundSpeed(0.0F),
00396           m_verticalVelocity(0.0F), m_PDOP(0.0F), m_HDOP(0.0F), m_VDOP(0.0F),
00397           m_TDOP(0.0F)
00398 {
00399         SetFromPOS_Message(message);
00400 }
00401 
00402 
00403 int AshtechG12_GPS_PhysicalDevice::Position::SetFromPOS_Message(const char *message)
00404 {
00405         static const char       MSG_HEADER[]="$PASHR,POS,";
00406         static const int        NUM_FIELDS=17;
00407         static const int        MAX_FIELD_LEN=12;
00408         static const unsigned int MIN_MSG_LEN=sizeof(MSG_HEADER)+NUM_FIELDS+4;
00409 
00410         if (AshtechG12_GPS_PhysicalDevice::ValidateChecksum(message) != 0)
00411         {
00412                 cerr << "ERROR Checksum" << endl;
00413         }
00414 
00415     if ( strlen( message ) < MIN_MSG_LEN )
00416     {
00417                 cerr << "ERROR String Length" << endl;
00418     }
00419 
00420         if (!memcmp(MSG_HEADER, message, sizeof(MSG_HEADER)))
00421         {
00422                 cerr << "ERROR Message Header" << endl;
00423         }
00424         
00425         char tokens[NUM_FIELDS][MAX_FIELD_LEN]; 
00426         const char *tokPtr=message+strlen(MSG_HEADER);
00427 
00428         for (int i = 0; i < NUM_FIELDS; ++i)
00429         {
00430                 int tokLen=strcspn(tokPtr, ",*");
00431                 memcpy(tokens[i], tokPtr, tokLen);
00432                 tokens[i][tokLen] = '\0';
00433                 tokPtr+=tokLen+1;
00434 
00435                 if (tokPtr == NULL)
00436                 {
00437                         cerr << " ERROR Nothing in tokPtr" << endl;
00438                 }
00439         }
00440 
00441         if (*(tokPtr-1) != '*')
00442         {
00443                 cerr << "ERROR: Malformed GPS Position message " << message << endl;
00444         }
00445 
00446         int tmpInt;
00447         float ddmmPointmmmmm;
00448 
00449         if (sscanf(tokens[0], "%d", &tmpInt) == 1)
00450         {
00451                 //m_RTCM = (unsigned char)tmpInt;       
00452                 m_RTCM = tmpInt;        
00453         }
00454         if (sscanf(tokens[1], "%d", &tmpInt) == 1)
00455         {
00456                 m_numSatellites = tmpInt;
00457         }
00458         sscanf(tokens[2],  "%f", &m_UTC_Timetag);
00459         if (sscanf(tokens[3], "%f", &ddmmPointmmmmm) == 1)
00460         {
00461                 float minutes=fmod(ddmmPointmmmmm, 100);
00462                 m_latitude=(ddmmPointmmmmm-minutes)/100 + minutes/60;
00463         }
00464         sscanf(tokens[4],  "%c", &m_latitudeSector);
00465         if (sscanf(tokens[5], "%f", &ddmmPointmmmmm) == 1)
00466         {
00467                 float minutes=fmod(ddmmPointmmmmm, 100);
00468                 m_longitude=(ddmmPointmmmmm-minutes)/100 + minutes/60;
00469         }
00470         sscanf(tokens[6],  "%c", &m_longitudeSector);
00471         sscanf(tokens[7],  "%f", &m_altitude);
00472         // tokens[8] is reserved and should be ""
00473         sscanf(tokens[9],  "%f", &m_groundTrack);
00474         sscanf(tokens[10], "%f", &m_groundSpeed);
00475         sscanf(tokens[11], "%f", &m_verticalVelocity);
00476         sscanf(tokens[12], "%f", &m_PDOP);
00477         sscanf(tokens[13], "%f", &m_HDOP);
00478         sscanf(tokens[14], "%f", &m_VDOP);
00479         sscanf(tokens[15], "%f", &m_TDOP);
00480         // tokens[16] is firmware version code
00481 
00482         return 0;
00483 }
00484 
00485 
00486 void AshtechG12_GPS_PhysicalDevice::Position::toString(std::string &str) const
00487 {
00488         std::ostringstream ss;
00489 
00490         ss  <<  "{ "
00491                 "RTCM: "                        << static_cast<int>(m_RTCM) << ", "
00492                 "Satellites: "          << static_cast<int>(m_numSatellites) << ", "
00493                 "Timetag: "                     << m_UTC_Timetag << ", "
00494                 "Latitude: "            << m_latitude  << " " << m_latitudeSector << ", "
00495                 "Longitude: "           << m_longitude << " " << m_longitudeSector << ", "
00496                 "Altitude: "            << m_altitude << ", "
00497                 "Ground Track: "        << m_groundTrack << ", "
00498                 "Ground Speed: "        << m_groundSpeed << ", "
00499                 "Vert. Velocity: "      << m_verticalVelocity << ", "
00500                 "PDOP: "                        << m_PDOP << ", "
00501                 "HDOP: "                        << m_HDOP << ", "
00502                 "VDOP: "                        << m_VDOP << ", "
00503                 "TDOP: "                        << m_TDOP
00504                 << " }";
00505 
00506         str=ss.str();
00507 }
00508 
00509 
00510 std::string AshtechG12_GPS_PhysicalDevice::Position::toString() const
00511 {
00512         std::string retVal;
00513         toString(retVal);
00514 
00515         return retVal;
00516 }
00517 
00518 
00519 AshtechG12_GPS_PhysicalDevice::Position & 
00520         AshtechG12_GPS_PhysicalDevice::Position::operator =(
00521                 const AshtechG12_GPS_PhysicalDevice::Position &other
00522         )
00523 {
00524         if (this != &other)
00525         {
00526                 memcpy(this, &other, sizeof(Position));
00527         }
00528 
00529         return *this;
00530 }
00531 
00532 
00533 bool AshtechG12_GPS_PhysicalDevice::Position::operator ==(
00534                 const AshtechG12_GPS_PhysicalDevice::Position &other
00535         ) const
00536 {
00537         if (this == &other)
00538         {
00539                 return true;
00540         }
00541 
00542         return !memcmp(this, &other, sizeof(Position));
00543 }
00544 
00545 
00546 /*
00547  * Generic reply format (in regular expression syntax):
00548  *  $PASHR.*\*[:hex:][:hex:]\r\n
00549  *
00550  * Typical response strings:
00551  *  $PASHR,NAK*30
00552  *  $PASHR,ACK*3D
00553  *  $PASHR,POS,0,12,1776.12,1234.5,N,2345.6,W,30000.1,,120.3,200.5,12.2,1.2,2.3,3.4,4.5,v1.1*7b
00554  */
00555 
00556 // Do not change the comments below - they will be added automatically by CVS
00557 /*****************************************************************************
00558 *       $Log: AshtechG12_GPS_PhysicalDevice.cpp,v $
00559 *       Revision 1.1  2007/08/31 16:10:54  jayhawk_hokie
00560 *       Initial Submission.
00561 *
00562 *
00563 *
00564 *
00565 *
00566 ******************************************************************************/
00567 

Generated on Wed Sep 5 12:54:17 2007 for DSACSS Operational Code by  doxygen 1.3.9.1