00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArGPS.h"
00030
00031 #include "Aria.h"
00032 #include <iostream>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00090 AREXPORT ArGPS::ArGPS() :
00091
00092
00093 myHavePosition(false),
00094 myHaveSpeed(false),
00095 myGPSPositionTimestamp(0),
00096 myFixType(NoFix),
00097 myNumSatellitesTracked(0),
00098 myHaveAltitude(false),
00099 myHaveDGPSStation(false),
00100 myHavePositionError(false),
00101 myHaveVerticalPositionError(false),
00102 myHaveCompassHeading(false),
00103 myHaveHDOP(false),
00104 myHaveVDOP(false),
00105 myHavePDOP(false),
00106
00107
00108 myDevice(NULL),
00109
00110
00111 myGPRMCHandler(this, &ArGPS::handleGPRMC),
00112 myGPGGAHandler(this, &ArGPS::handleGPGGA),
00113 myPGRMEHandler(this, &ArGPS::handlePGRME),
00114 myPGRMZHandler(this, &ArGPS::handlePGRMZ),
00115 myHCHDGHandler(this, &ArGPS::handleHCHDG),
00116 myGPGSAHandler(this, &ArGPS::handleGPGSA),
00117
00118
00119 MaxNumFields(50),
00120 MaxFieldSize(128),
00121 ignoreChecksum(false),
00122 checksumBufOffset(0),
00123 inChecksum(false),
00124 inMessage(false),
00125 currentChecksum(0),
00126 gotCR(false)
00127 {
00128 myHandlers["GPRMC"] = &myGPRMCHandler;
00129 myHandlers["GPGGA"] = &myGPGGAHandler;
00130 myHandlers["PGRME"] = &myPGRMEHandler;
00131 myHandlers["PGRMZ"] = &myPGRMZHandler;
00132 myHandlers["HCHDG"] = &myHCHDGHandler;
00133 myHandlers["GPGSA"] = &myGPGSAHandler;
00134 }
00135
00136 AREXPORT ArGPS::~ArGPS()
00137 {
00138 memset(checksumBuf, 0, 3);
00139 }
00140
00141
00142
00143
00144
00145
00146 AREXPORT bool ArGPS::connect()
00147 {
00148 if (!myDevice)
00149 {
00150 ArLog::log(ArLog::Terse, "GPS Error: Cannot connect, device connection invalid.");
00151 return false;
00152 }
00153
00154 if (myDevice->getStatus() != ArDeviceConnection::STATUS_OPEN)
00155 {
00156 ArLog::log(ArLog::Terse, "GPS Error: Cannot connect, device connection not open.");
00157 return false;
00158 }
00159
00160
00161 return true;
00162 }
00163
00164
00165
00166 AREXPORT bool ArGPS::blockingConnect(unsigned long connectTimeout)
00167 {
00168 ArTime start;
00169 start.setToNow();
00170 if (!connect()) return false;
00171 while ((unsigned long)start.mSecSince() <= connectTimeout)
00172 {
00173 if (read() & ReadUpdated)
00174 return true;
00175 ArUtil::sleep(100);
00176
00177 }
00178 return false;
00179 }
00180
00181
00182
00183 void ArGPS::nextField()
00184 {
00185 currentMessage.push_back(currentField);
00186 currentField = "";
00187 if (currentMessage.size() > MaxNumFields)
00188 endMessage();
00189 }
00190
00191 void ArGPS::endMessage()
00192 {
00193 inMessage = false;
00194 inChecksum = false;
00195 currentField = "";
00196 gotCR = false;
00197 }
00198
00199 void ArGPS::beginChecksum()
00200 {
00201 checksumBufOffset = 0;
00202 inChecksum = true;
00203 }
00204
00205 void ArGPS::beginMessage()
00206 {
00207 currentMessage.clear();
00208 inChecksum = false;
00209 inMessage = true;
00210 currentField = "";
00211 gotCR = false;
00212 currentChecksum = 0;
00213 }
00214
00215
00216 AREXPORT int ArGPS::read()
00217 {
00218 if (!myDevice) return ReadError;
00219 char buf[256];
00220
00221 int result = 0;
00222
00223
00224 while(true)
00225 {
00226 int n = myDevice->read(buf, sizeof(buf));
00227
00228 if (n < 0)
00229 {
00230 return result|ReadError;
00231 }
00232
00233 if (n == 0)
00234 {
00235 return result|ReadFinished;
00236 }
00237
00238
00239
00240 for (int i = 0; i < n; i++)
00241 {
00242
00243 if (buf[i] == '$')
00244 {
00245 beginMessage();
00246 continue;
00247 }
00248
00249
00250 if (!inMessage)
00251 continue;
00252
00253
00254 if (buf[i] == '\r')
00255 {
00256 gotCR = true;
00257 continue;
00258 }
00259 if (buf[i] == '\n')
00260 {
00261 if (gotCR)
00262 {
00263 endMessage();
00264 HandlerMap::iterator h = myHandlers.find(currentMessage[0]);
00265 if (h != myHandlers.end())
00266 {
00267
00268 h->second->invoke(¤tMessage);
00269 result |= ReadUpdated;
00270 }
00271 }
00272
00273
00274 endMessage();
00275 continue;
00276 }
00277
00278
00279 if (inChecksum)
00280 {
00281 checksumBuf[checksumBufOffset++] = buf[i];
00282 if (checksumBufOffset > 1)
00283 {
00284 int checksumRec = (int) strtol(checksumBuf, NULL, 16);
00285
00286 if (checksumRec != currentChecksum) {
00287 ArLog::log(ArLog::Normal, "GPS: Warning: Skipping message with incorrect checksum.");
00288
00289 endMessage();
00290 }
00291 }
00292 continue;
00293 }
00294
00295
00296
00297 if (buf[i] == '*')
00298 {
00299 nextField();
00300 if (!ignoreChecksum)
00301 beginChecksum();
00302 continue;
00303 }
00304
00305
00306
00307 currentChecksum ^= buf[i];
00308
00309
00310 if (buf[i] == ',')
00311 {
00312 nextField();
00313 continue;
00314 }
00315
00316
00317
00318
00319
00320
00321 currentField += buf[i];
00322 if (currentField.size() > MaxFieldSize)
00323 {
00324 endMessage();
00325 continue;
00326 }
00327 }
00328 }
00329 return result;
00330 }
00331
00332
00333
00334
00335
00336 void ArGPS::handleGPRMC(MessageVector* message)
00337 {
00338
00339 if (message->size() < 3 || (*message)[2] != "A") return;
00340
00341 if (!readFloatFromStringVec(message, 3, &myLatitude, &gpsDegminToDegrees)) return;
00342
00343 if (message->size() < 5) return;
00344 if ((*message)[4] == "S") myLatitude *= -1;
00345
00346 if (!readFloatFromStringVec(message, 5, &myLongitude, &gpsDegminToDegrees)) return;
00347
00348 if (message->size() < 7) return;
00349 if ((*message)[6] == "W") myLongitude *= -1;
00350
00351
00352 myHavePosition = true;
00353 myGPSPositionTimestamp = atoi((*message)[1].c_str());
00354
00355 myHaveSpeed = readFloatFromStringVec(message, 7, &mySpeed, &knotsToMPS);
00356
00357 }
00358
00359
00360 void ArGPS::handleGPGGA(MessageVector* message)
00361 {
00362 if (message->size() < 7) return;
00363 switch(atoi((*message)[6].c_str()))
00364 {
00365 case 0:
00366 myFixType = BadFix;
00367 break;
00368 case 1:
00369 myFixType = GPSFix;
00370 break;
00371 case 2:
00372 myFixType = DGPSFix;
00373 break;
00374 case 3:
00375 myFixType = PPSFix;
00376 break;
00377 case 4:
00378 myFixType = RTKinFix;
00379 break;
00380 case 5:
00381 myFixType = FloatRTKinFix;
00382 break;
00383 case 6:
00384 myFixType = DeadReckFix;
00385 break;
00386 case 7:
00387 myFixType = ManualFix;
00388 break;
00389 case 8:
00390 myFixType = SimulatedFix;
00391 break;
00392 default:
00393 myFixType = UnknownFixType;
00394 }
00395
00396 readUShortFromStringVec(message, 7, &myNumSatellitesTracked);
00397 myHaveHDOP = readFloatFromStringVec(message, 8, &myHDOP);
00398 myHaveAltitude = readFloatFromStringVec(message, 9, &myAltitude);
00399 myHaveDGPSStation = readUShortFromStringVec(message, 14, &myDGPSStationID);
00400 }
00401
00402
00403
00404 void ArGPS::handlePGRME(MessageVector* message)
00405 {
00406
00407
00408 myHavePositionError = readFloatFromStringVec(message, 1, &myPositionError);
00409 myHaveVerticalPositionError = readFloatFromStringVec(message, 3, &myVerticalPositionError);
00410 }
00411
00412
00413 void ArGPS::handlePGRMZ(MessageVector* message)
00414 {
00415
00416
00417
00418
00419 if (myHaveAltitude && message->size() >= 3 && strcasecmp((*message)[2].c_str(), "f") == 0)
00420 myAltitude = feetToMeters(myAltitude);
00421 }
00422
00423
00424 void ArGPS::handleHCHDG(MessageVector* message)
00425 {
00426 myHaveCompassHeading = readFloatFromStringVec(message, 1, &myCompassHeading);
00427 }
00428
00429
00430 void ArGPS::handleGPGSA(MessageVector* message)
00431 {
00432
00433
00434
00435 myHavePDOP = readFloatFromStringVec(message, 15, &myPDOP);
00436 myHaveHDOP = readFloatFromStringVec(message, 16, &myHDOP);
00437 myHaveVDOP = readFloatFromStringVec(message, 17, &myVDOP);
00438 }
00439
00440 AREXPORT const char* ArGPS::getFixTypeName() const
00441 {
00442 switch (getFixType())
00443 {
00444 case NoFix: return "None";
00445 case BadFix: return "Bad";
00446 case GPSFix: return "GPS";
00447 case DGPSFix: return "DGPS";
00448 case PPSFix: return "PPS";
00449 case RTKinFix: return "RT Kinematic";
00450 case FloatRTKinFix: return "Float. RT Kinematic";
00451 case DeadReckFix: return "Dead Reckoning";
00452 case ManualFix: return "Manual";
00453 case SimulatedFix: return "Simulated";
00454 default: return "Unknown";
00455 }
00456 }
00457
00458 AREXPORT void ArGPS::logData() const
00459 {
00460 ArLog::log(ArLog::Normal, "GPS Fix=%s Num. Satellites=%d", getFixTypeName(), getNumSatellitesTracked());
00461
00462 if (havePosition())
00463 {
00464 ArLog::log(ArLog::Normal, "GPS Latitude=%0.4fdeg Longitude=%0.4fdeg Timestamp=%d", getLatitude(), getLongitude(), getGPSPositionTimestamp());
00465
00466 }
00467
00468 if (haveSpeed())
00469 ArLog::log(ArLog::Normal, "GPS Speed=%0.4fm/s (%0.4fmi/h)", getSpeed(), mpsToMph(getSpeed()));
00470
00471 if (haveAltitude())
00472 ArLog::log(ArLog::Normal, "GPS Altitude=%0.4fm (%0.4fft)", getAltitude(), metersToFeet(getAltitude()));
00473
00474 if (haveCompassHeading())
00475 ArLog::log(ArLog::Normal, "GPS Compass Heading=%0.4fdeg", getCompassHeading());
00476
00477 if (havePositionError())
00478 ArLog::log(ArLog::Normal, "GPS Position Error Estimate=%0.4fm", getPositionError());
00479
00480 if (haveVerticalPositionError())
00481 ArLog::log(ArLog::Normal, "GPS Vertical Position Error Estimate=%0.4fm", getVerticalPositionError());
00482
00483 if (havePDOP())
00484 ArLog::log(ArLog::Normal, "GPS PDOP=%0.4f", getPDOP());
00485 if (haveHDOP())
00486 ArLog::log(ArLog::Normal, "GPS HDOP=%0.4f", getHDOP());
00487 if (haveVDOP())
00488 ArLog::log(ArLog::Normal, "GPS VDOP=%0.4f", getVDOP());
00489
00490 if (haveDGPSStation())
00491 ArLog::log(ArLog::Normal, "GPS DGPS Station ID=%d", getDGPSStationID());
00492
00493 }
00494
00495 AREXPORT void ArGPS::printData() const
00496 {
00497 printf("GPS: ");
00498 if (!havePosition())
00499 {
00500 printf("Pos:-");
00501 }
00502 else
00503 {
00504 printf("Pos:% 2.6f,% 2.6f", getLatitude(), getLongitude());
00505 }
00506
00507 if (!haveSpeed())
00508 printf(" Spd:-");
00509 else
00510 printf(" Spd:%4.4fm/s (%3.4fmi/h)", getSpeed(), mpsToMph(getSpeed()));
00511
00512 if (!haveAltitude())
00513 printf(" Alt:-");
00514 else
00515 printf(" Alt:%4.2fm (%4.2fft)", getAltitude(), metersToFeet(getAltitude()));
00516
00517 if (!haveCompassHeading())
00518 printf(" Head:-");
00519 else
00520 printf(" Head:%3.1fdeg", getCompassHeading());
00521
00522 printf(" NSats:%2d", getNumSatellitesTracked());
00523
00524 if (!havePositionError())
00525 printf(" ErrEst:-");
00526 else
00527 printf(" ErrEst:%2.4fm", getPositionError());
00528
00529 if (haveHDOP())
00530 printf(" HDOP:%1.2f", getHDOP());
00531 else
00532 printf(" HDP:-");
00533
00534 printf(" Fix:%-10s", getFixTypeName());
00535 printf(" (%d)", getGPSPositionTimestamp());
00536 }
00537
00538
00539 double ArGPS::gpsDegminToDegrees(double degmin)
00540 {
00541 double degrees;
00542 double minutes = modf(degmin / 100.0, °rees) * 100.0;
00543 return degrees + (minutes / 60.0);
00544 }
00545
00546
00547 double ArGPS::knotsToMPS(double knots)
00548 {
00549 return(knots * 0.514444444);
00550 }
00551
00552
00553 bool ArGPS::readFloatFromString(std::string& str, double* target, double (*convf)(double))
00554 {
00555 if (str.length() == 0) return false;
00556 if (convf)
00557 *target = (*convf)(atof(str.c_str()));
00558 else
00559 *target = atof(str.c_str());
00560 return true;
00561 }
00562
00563 bool ArGPS::readUShortFromString(std::string& str, unsigned short* target, unsigned short (*convf)(unsigned short))
00564 {
00565 if (str.length() == 0) return false;
00566 if (convf)
00567 *target = (*convf)(atof(str.c_str()));
00568 else
00569 *target = (unsigned short) atoi(str.c_str());
00570 return true;
00571 }
00572
00573
00574 bool ArGPS::readFloatFromStringVec(std::vector<std::string>* vec, size_t i, double* target, double (*convf)(double))
00575 {
00576 if (vec->size() < (i+1)) return false;
00577 return readFloatFromString((*vec)[i], target, convf);
00578 }
00579
00580 bool ArGPS::readUShortFromStringVec(std::vector<std::string>* vec, size_t i, unsigned short* target, unsigned short (*convf)(unsigned short))
00581 {
00582 if (vec->size() < (i+1)) return false;
00583 return readUShortFromString((*vec)[i], target, convf);
00584 }
00585
00586