2012-11-28 82 views
2

我正在開發一個C++應用程序,它應該使用gpsd檢索收到的類型爲$ GPGGA的NMEA語句。這個想法是每秒從gpsd讀取一次,並解析最後一個$ GPGGA收到的句子,提取我感興趣的兩個字段:質量指標和參考站點ID。我使用C++ libgpsmm庫,定期調用gpsmm::read()gpsmm::data(),直接訪問客戶端數據緩衝區。首先,我使用gpsfake和僞造的GPS日誌(指定gpsfake選項「-c 0.5」,以便每秒鐘有兩個句子)做了幾次測試。當兩個gpsd請求之間的時間小於或等於400ms時,結果是OK的。如果我用更多的時間嘗試,結果是意想不到的,在每次閱讀中都有一段NMEA句子,其中包含大量重複數據以及一些截短的句子。當我嘗試使用每秒寫入40個句子的真實GPS時,情況會更糟糕:在這種情況下,讀取之間的時間應該爲〜10ms或更少,以便獲得正確的結果。gpsd客戶端數據緩衝區

以下是打印收到的NMEA句子的一個更簡單的程序。它運行良好,模擬甚至是真正的GPS。但是,如果我取消註釋usleep()調用,這會使程序每秒檢查一次緩衝區,但客戶端數據緩衝區不會給出合理的結果。

#include <iostream> 

#include "libgpsmm.h" 

using namespace std; 

#define WAITING_TIME 5000000 
#define RETRY_TIME 5 
#define ONE_SECOND 1000000 

int main(void) 
{ 
    for(;;){ 
     //For version 3.7 
     gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT); 

     if (gps_rec.stream(WATCH_ENABLE|WATCH_NMEA) == NULL) { 
      cout << "No GPSD running. Retry to connect in " << RETRY_TIME << " seconds." << endl; 
      usleep(RETRY_TIME * ONE_SECOND); 
      continue; // It will try to connect to gpsd again 
     } 

     const char* buffer = NULL; 

     for (;;) { 
      struct gps_data_t* newdata; 

      if (!gps_rec.waiting(WAITING_TIME)) 
       continue; 

      if ((newdata = gps_rec.read()) == NULL) { 
       cerr << "Read error.\n"; 
       break; 
      } else { 
       buffer = gps_rec.data(); 

       // We print the NMEA sentences! 
       cout << "***********" << endl; 
       cout << buffer << endl;    

       //usleep(1000000); 
      } 
     } 
    } 
} 

這裏是具有usleep()函式輸出呼叫評論(即連續地讀取數據。):

$  ./GPSTest1 
*********** 
{"class":"VERSION","release":"3.7","rev":"3.7","proto_major":3,"proto_minor":7} 
*********** 
{"class":"WATCH","enable":true,"json":false,"nmea":true,"raw":0,"scaled":false,"timing":false} 
*********** 
$GPGGA,202010.00,3313.9555651,S,06019.3785868,W,4,09,1.0,39.384,M,16.110,M,10.0,*46<CR><LF> 
*********** 
$GPGGA,202011.00,3313.9555664,S,06019.3785876,W,4,09,1.0,39.386,M,16.110,M,11.0,*4D<CR><LF> 
*********** 
$GPGGA,202012.00,3313.9555668,S,06019.3785882,W,4,09,1.0,39.394,M,16.110,M,12.0,*49<CR><LF> 
*********** 
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,4,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF> 
*********** 
$GPGGA,202014.00,3313.9555670,S,06019.3785907,W,4,09,1.0,39.409,M,16.110,M,14.0,*4F<CR><LF> 
*********** 
$GPGGA,202015.00,3313.9555657,S,06019.3785905,W,4,09,1.0,39.395,M,16.110,M,15.0,*4A<CR><LF> 

這是當線被註釋的輸出(即,緩衝檢查每秒一次):

$ ./GPSTest2 
*********** 
{"class":"VERSION","release":"3.7","rev":"3.7","proto_major":3,"proto_minor":7} 
*********** 
{"class":"DEVICE","path":"/dev/pts/0","activated":"2012-11-05T23:48:38.110Z","driver":"Generic NMEA","native":0,"bps":4800,"parity":"N","stopbits":1,"cycle":1.00} 
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF> 
0} 
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF> 
":"Generic NMEA","native":0,"bps":4800,"parity":"N","stopbits":1,"cycle":1.00} 
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF> 

*********** 
$GPGGA,202013.00,3313.9555673,S,06019.3785911,W,1,09,1.0,39.395,M,16.110,M,13.0,*49<CR><LF> 
*********** 
$GPGGA,202016.00,3313.9555642,S,06019.3785894,W,1,09,1.0,39.402,M,16.110,M,16.0,*4E<CR><LF> 
$GPGGA,202017.00,3313.9555643,S,06019.3785925,W,1,09,1.0,39.404,M,16.110,M,17.0,*42<CR><LF> 
$GPGGA,202017.00,3313.9555643,S,06019.3785925,W,1,09,1.0,39.404,M,16.110,M,17.0,*42<CR><LF> 
$GPGGA,202017.00,3313.9555643,S,06019.3785925,W,1,09,1.0,39.404,M,16.110,M,17.0,*42<CR><LF> 
*********** 

任何建議?起初,我試圖直接分析gps_data_t結構,但在結構的所有領域中,與NMEA句子中的搜索相比,似乎很難確定質量指標和參考站ID。

回答

1

我不熟悉gpsd服務,但是您描述的內容看起來很像接收緩衝區被損壞(覆蓋)。 GPS接收器不斷地輸出NMEA信息,當你的應用程序正在休眠時,這些字符將會累積在緩衝區中,如果接收到太多字符,則緩衝區將被覆蓋。

要麼增加串口接收緩衝區大小(如果可能的話),要麼可能在喚醒後清空緩衝區,然後等待下一個GGA消息(最壞的情況下可能會達到1秒)。

GPS接收機應該配置爲以1Hz(每秒一次)輸出信息,在這種情況下,該設備應該只輸出每秒約8次的讀數。如果你看到40個功放,那麼你的接收機似乎會以5Hz左右的頻率輸出信息,這聽起來像是爲了你特別感興趣的矯枉過正。

+0

感謝您的回答,timrorr! 一些評論: 1)我想過增加緩衝區大小之前......但我無法在libgps所做的所有定義中識別它,我認爲必須有一種通常的方法來獲得我想要的。 2)喚醒後清除緩衝區並不能解決我的問題,因爲我的真實應用程序無法阻止等待消息,因爲它必須同時處理其他消息。 3)我正在使用20Hz的GPS接收機:我每秒接收10個GGA,10個TVG和1個ZDA。 – pabloderosario

+0

當然,解決我的問題的最好方法是將GPS數據採集和消耗這些信息分爲兩個不同的線程。這樣,緩衝區不會被破壞,而且也不需要更多的讀取。 – pabloderosario

相關問題