正文  设备功能 > GPS/LBS/定位 >

android hal层GPS研究总结

/Eclair/hardware/libhardware_legacy/include/hardware_legacy/gps.h typedef struct { /** C...

/Eclair/hardware/libhardware_legacy/include/hardware_legacy/gps.h
typedef struct {
    /** Contains GpsLocationFlags bits. */
    uint16_t        flags;
    /** Represents latitude in degrees. */
    double          latitude;
    /** Represents longitude in degrees. */
    double          longitude;
    /** Represents altitude in meters above the WGS 84 reference
     * ellipsoid. */
    double          altitude;
    /** Represents speed in meters per second. */
    float           speed;
    /** Represents heading in degrees. */
    float           bearing;
    /** Represents expected accuracy in meters. */
    float           accuracy;
    /** Timestamp for the location fix. */
    GpsUtcTime      timestamp;
} GpsLocation;
 
flags是标识
#define GPS_LOCATION_HAS_LAT_LONG   0x0001, flags 的bit0为1时,标识位置信息有经纬度的信息
/** GpsLocation has valid altitude. */
#define GPS_LOCATION_HAS_ALTITUDE   0x0002,flags 的bit1为1时,标识位置信息有高度的信息,以下标识位类似。
/** GpsLocation has valid speed. */
#define GPS_LOCATION_HAS_SPEED      0x0004
/** GpsLocation has valid bearing. */
#define GPS_LOCATION_HAS_BEARING    0x0008
/** GpsLocation has valid accuracy. */
#define GPS_LOCATION_HAS_ACCURACY   0x0010
typedef void (* gps_status_callback)(GpsStatus* status);
可以使用这个函数提交标识信息。
timestamp时间戳
是一个64位的无符号的整数。它原本的定义是,UTC时间从1970年01月01日00:00:00至现在的秒数。但是在android的Java语言中Date的构造函数必须输入毫秒值,但得到的十进制是秒,所以要乘以1000。
bearing
对应着RMC的第8(从0起)个数据断。对地航向(course over ground)
typedef struct {
        /** Number of SVs currently visible. */
        int         num_svs;
        /** Contains an array of SV information. */
        GpsSvInfo   sv_list[GPS_MAX_SVS];
        /** Represents a bit mask indicating which SVs
         * have ephemeris data.
         */
        uint32_t    ephemeris_mask;
        /** Represents a bit mask indicating which SVs
         * have almanac data.
         */
        uint32_t    almanac_mask;
        /**
         * Represents a bit mask indicating which SVs
         * were used for computing the most recent position fix.
         */
        uint32_t    used_in_fix_mask;
} GpsSvStatus;
 
used_in_fix_mask
如果收到如下数据报$GPGSA,A,3,07,19,08,03,16,11,06,,,,,,2.8,1.5,2.3*38
     07 , 19 ,  08  ,03  ,  16 , 11 ,  06 是有用的卫星编号(prn)used_in_fix_mask的
bit  6  , 18 ,   7   , 2  ,   15  , 10 ,   5  为1,其它位为0.(bit0也是0)

ephemeris_mask,almanac_mask
这两个掩码,与GSV信息密切相关。
比如收到如下的信息。(为了便于数据分析我多加了转行)
$GPGSV,3,1,11,
19,79,359,30, 
13,47,260,22,
03,46,029,31,
23,40,217,24*7B
卫星编号(prn)19,13,03,23
$GPGSV,3,2,11,
11,37,180,,
06,33,036,29,
16,30,050,35,
07,27,324,25*7A
卫星编号(prn)11,6,16,07
$GPGSV,3,3,11,
24,17,178,,
08,03,319,
28,31,02,133,*4C
卫星编号(prn)24,08,28
ephemeris_mask和almanac_mask的bit(18,12,02,22,10,5,15,06, 23,07,27)为1,其它位为0(bit从第0位开始),
掩码的值与卫星编号是紧密相关的。
总之,要对NEMA数据格式有深刻的了解。
贴出主要代码:Eclair/hardware/libhardware_legacy/gps/gps_qemu.c
欢迎交流。
Java代码 
<pre name="code" class="cpp">static void 
nmea_reader_parse( NmeaReader* r ) 
{D("%s,%d,%s\n",__FILE__,__LINE__,__FUNCTION__); 
   /* we received a complete sentence, now parse it to generate
    * a new GPS fix...
    */ 
    NmeaTokenizer tzer[1]; 
    Token tok; 
 
   D("Received: '%.*s'", r->pos, r->in); 
    if (r->pos < 9) { 
        D("Too short. discarded."); 
        return; 
    } 
 
    nmea_tokenizer_init(tzer, r->in, r->in + r->pos); 
#if GPS_DEBUG 
    { 
        int n; 
        for (n = 0; n < tzer->count; n++) { 
            Token tok = nmea_tokenizer_get(tzer,n); 
        } 
    } 
#endif 
 
    tok = nmea_tokenizer_get(tzer, 0); 
    if (tok.p + 5 > tok.end) { 
        return; 
    } 
 
    /* ignore first two characters.*/ 
    tok.p += 2; 
    if ( !memcmp(tok.p, "GGA", 3) ) { 
        /* GPS fix */D("may%s,%d,%s,gGA\n",__FILE__,__LINE__,__FUNCTION__); 
     
        Token tok_time = nmea_tokenizer_get(tzer,1); 
        Token tok_latitude = nmea_tokenizer_get(tzer,2); 
        Token tok_latitudeHemi = nmea_tokenizer_get(tzer,3); 
        Token tok_longitude = nmea_tokenizer_get(tzer,4); 
        Token tok_longitudeHemi = nmea_tokenizer_get(tzer,5); 
        Token tok_altitude = nmea_tokenizer_get(tzer,9); 
        Token tok_altitudeUnits = nmea_tokenizer_get(tzer,10); 
 
        nmea_reader_update_time(r, tok_time); 
        nmea_reader_update_latlong(r, tok_latitude, 
                                      tok_latitudeHemi.p[0], 
                                      tok_longitude, 
                                      tok_longitudeHemi.p[0]); 
        nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits); 
    }else if ( !memcmp(tok.p, "GLL", 3) ) { 
    Token tok_fixstaus = nmea_tokenizer_get(tzer,6); 
    if (tok_fixstaus.p[0] == 'A') { 
     Token tok_latitude = nmea_tokenizer_get(tzer,1); 
     Token tok_latitudeHemi = nmea_tokenizer_get(tzer,2); 
     Token tok_longitude = nmea_tokenizer_get(tzer,3); 
     Token tok_longitudeHemi = nmea_tokenizer_get(tzer,4); 
     Token tok_time = nmea_tokenizer_get(tzer,5); 
     nmea_reader_update_time(r, tok_time); 
     nmea_reader_update_latlong(r, tok_latitude, tok_latitudeHemi.p[0], tok_longitude, tok_longitudeHemi.p[0]); 
    } 
    } 
    #ifdef Svpnd_Version 
    else if ( !memcmp(tok.p, "GSV", 3) ) { 
D("may%s,%d,%s,gsV\n",__FILE__,__LINE__,__FUNCTION__); 
    Token tok_noSatellites = nmea_tokenizer_get(tzer, 3); 
    int noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end); 
       D("%d,inview=%d,\n",__LINE__,noSatellites);   
    if (noSatellites > 0) { 
     Token tok_noSentences = nmea_tokenizer_get(tzer, 1); 
     Token tok_sentence     = nmea_tokenizer_get(tzer, 2); 
     
     int sentence = str2int(tok_sentence.p, tok_sentence.end); 
     int totalSentences = str2int(tok_noSentences.p, tok_noSentences.end); 
   D("%d,gsv_index=%d,gsv_total=%d\n",__LINE__,sentence,totalSentences);   
     int curr; 
     int i; 
              
     if (sentence == 1) { 
D("msg_index=%d\n",sentence); 
   //  r->sv_status_changed = 0; 
     r->sv_status.num_svs = 0; 
    r->sv_status.ephemeris_mask=0ul; 
    r->sv_status.almanac_mask=0ul; 
     } 
     
        curr = r->sv_status.num_svs; 
    
        i = 0; 
     
        while (i < 4 && r->sv_status.num_svs < noSatellites){ 
         Token    tok_prn = nmea_tokenizer_get(tzer, i * 4 + 4); 
         Token    tok_elevation = nmea_tokenizer_get(tzer, i * 4 + 5); 
         Token    tok_azimuth = nmea_tokenizer_get(tzer, i * 4 + 6); 
         Token    tok_snr = nmea_tokenizer_get(tzer, i * 4 + 7); 
     
         r->sv_status.sv_list[curr].prn = str2int(tok_prn.p, tok_prn.end); 
         r->sv_status.sv_list[curr].elevation = str2float(tok_elevation.p, tok_elevation.end); 
         r->sv_status.sv_list[curr].azimuth = str2float(tok_azimuth.p, tok_azimuth.end); 
         r->sv_status.sv_list[curr].snr = str2float(tok_snr.p, tok_snr.end); 
         r->sv_status.ephemeris_mask|=(1ul << (r->sv_status.sv_list[curr].prn-1)); 
    r->sv_status.almanac_mask|=(1ul << (r->sv_status.sv_list[curr].prn-1));          
    r->sv_status.num_svs += 1; 
 D("**********curr=%d\n",curr); 
  
   D("%d,prn=%d:snr=%f\n",__LINE__,r->sv_status.sv_list[curr].prn,r->sv_status.sv_list[curr].snr); 
         curr += 1; 
     
         i += 1; 
     } 
     
     if (sentence == totalSentences) { 
D("msg=%d,msgindex=%d",totalSentences,sentence); 
        #ifdef Svpnd_Version 
r->callback.sv_status_cb=_gps_state->callbacks.sv_status_cb; 
 
     if (r->sv_status_changed !=0) { 
           if (r->callback.sv_status_cb) { 
         
        #if GPS_DEBUG 
        D("%d,SV_STATSU,change=%d\n",__LINE__,r->sv_status_changed); 
        int nums=r->sv_status.num_svs; 
        D("num_svs=%d,emask=%x,amask=%x,inusemask=%x\n",r->sv_status.num_svs,r->sv_status.ephemeris_mask,r->sv_status.almanac_mask,r->sv_status.used_in_fix_mask); 
        D("************88\n");       
        while(nums) 
        { 
        nums--; 
        D("prn=%d:snr=%f\n",r->sv_status.sv_list[nums].prn,r->sv_status.sv_list[nums].snr); 
         
        }D("************88\n"); 
        #endif 
                 r->callback.sv_status_cb( &(r->sv_status) ); 
               r->sv_status_changed = 0; 
             }else { 
                D("no callback, keeping status data until needed !"); 
           } 
 
        } 
     #endif 
     } 
     
     D("%s: GSV message with total satellites %d", __FUNCTION__, noSatellites);  
     
    }          
     
    } 
    #endif 
     
    else if ( !memcmp(tok.p, "GSA", 3) ) { 
    #ifdef Svpnd_Version 
        /* do something ? */ 
        { 
D("may%s,%d,%s,gsa\n",__FILE__,__LINE__,__FUNCTION__); 
        Token tok_fixStatus = nmea_tokenizer_get(tzer, 2); 
        int i; 
 
        if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1') { 
 
            Token tok_accuracy = nmea_tokenizer_get(tzer, 15);//position dilution of precision dop 
 
            nmea_reader_update_accuracy(r, tok_accuracy); 
 
            r->sv_status.used_in_fix_mask = 0ul; 
    D("\n"); 
            for (i = 3; i <= 14; ++i){ 
 
                Token tok_prn = nmea_tokenizer_get(tzer, i); 
                int prn = str2int(tok_prn.p, tok_prn.end); 
        D("gsa,prn=%d,",prn); 
                if (prn > 0){ 
                    r->sv_status.used_in_fix_mask |= (1ul << ( prn-1)); 
                    r->sv_status_changed = 1; 
                    
               } 
 
           }D("\n"); 
     D("%s: fix mask is %x", __FUNCTION__, r->sv_status.used_in_fix_mask); 
      //   D(" [log hit][%s:%d] fix.flags=0x%x ", __FUNCTION__, __LINE__, r->fix.flags);  
       } 
 
       D(" [log hit][%s:%d] fix.flags=0x%x ", __FUNCTION__, __LINE__, r->fix.flags); 
 
    } 
    #endif 
        /* do something ? */ 
    } else if ( !memcmp(tok.p, "RMC", 3) ) { 
     
        Token tok_time = nmea_tokenizer_get(tzer,1); 
        Token tok_fixStatus = nmea_tokenizer_get(tzer,2); 
        Token tok_latitude = nmea_tokenizer_get(tzer,3); 
        Token tok_latitudeHemi = nmea_tokenizer_get(tzer,4); 
        Token tok_longitude = nmea_tokenizer_get(tzer,5); 
        Token tok_longitudeHemi = nmea_tokenizer_get(tzer,6); 
        Token tok_speed = nmea_tokenizer_get(tzer,7); 
        Token tok_bearing = nmea_tokenizer_get(tzer,8); 
        Token tok_date = nmea_tokenizer_get(tzer,9); 
 
        D("in RMC, fixStatus=%c", tok_fixStatus.p[0]); 
       if (tok_fixStatus.p[0] == 'A') 
        { 
            nmea_reader_update_date( r, tok_date, tok_time ); 
 
            nmea_reader_update_latlong( r, tok_latitude, 
                                           tok_latitudeHemi.p[0], 
                                           tok_longitude, 
                                           tok_longitudeHemi.p[0] ); 
 
            nmea_reader_update_bearing( r, tok_bearing ); 
            nmea_reader_update_speed ( r, tok_speed ); 
         #ifdef Svpnd_Version 
r->callback.location_cb=_gps_state->callbacks.location_cb; 
r->callback.nmea_cb=_gps_state->callbacks.nmea_cb; 
r->callback.status_cb=_gps_state->callbacks.status_cb; 
if (r->callback.status_cb) { 
D("report,status,flags=%d\n",r->fix.flags); 
            r->callback.status_cb( (struct GpsStatus *)&(r->fix.flags) ); 
        } 
     if (r->callback.location_cb) { 
D("location_cb report:r->fix.flags=%d,r->latitude=%f,r->longitude=%f,r->altitude=%f,r->speed=%f,r->bearing=%f,r->accuracy=%f\n",r->fix.flags,r->fix.latitude,r->fix.longitude,r->fix.altitude,r->fix.speed,r->fix.bearing,r->fix.accuracy); 
            r->callback.location_cb( &r->fix ); 
D("%d,cc=%d",__LINE__,cc); 
        r->fix.flags = 0; 
         
        } 
if (r->callback.nmea_cb) { 
D("report,timestamp=%llx,%llu\n",r->fix.timestamp,r->fix.timestamp); 
            r->callback.nmea_cb( r->fix.timestamp,r->in,r->pos ); 
         
            
        } 
 
    #else 
r->callback=_gps_state.callbacks->location_cb; 
//r->callback.nmea_cb=_gps_state->callbacks.nmea_cb; 
        if (r->callback) {D("if2 (r->callback.location_cb)\n"); 
             r->callback( &r->fix ); 
             r->fix.flags = 0; 
         } 
        #endif 
        } 
    } 
    else if ( !memcmp(tok.p, "VTG", 3) ) { 
     Token tok_fixStatus = nmea_tokenizer_get(tzer,9); 
     if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != 'N') { 
     Token tok_bearing = nmea_tokenizer_get(tzer,1); 
     Token tok_speed = nmea_tokenizer_get(tzer,5); 
     nmea_reader_update_bearing( r, tok_bearing ); 
     nmea_reader_update_speed ( r, tok_speed ); 
     } 
    } 
    else if ( !memcmp(tok.p, "ZDA", 3) ) { 
     Token tok_time; 
     Token tok_year = nmea_tokenizer_get(tzer,4); 
     if (tok_year.p[0] != '\0') { 
     Token tok_day = nmea_tokenizer_get(tzer,2); 
     Token tok_mon = nmea_tokenizer_get(tzer,3); 
     nmea_reader_update_cdate( r, tok_day, tok_mon, tok_year ); 
     } 
     tok_time = nmea_tokenizer_get(tzer,1); 
     if (tok_time.p[0] != '\0') 
     nmea_reader_update_time(r, tok_time); 
    } 
    else { 
     tok.p -= 2; 
     D("unknown sentence '%.*s", tok.end-tok.p, tok.p); 
    }D("%s,%d,\n",__FILE__,__LINE__); 
    if (r->fix.flags!=0) { 
#if GPS_DEBUG 
    D("%d,flags=%d\n",__LINE__,r->fix.flags); 
        char temp[256]; 
        char* p = temp; 
        char* end = p + sizeof(temp); 
        struct tm utc; 
 
        p += snprintf( p, end-p, "sending fix" ); 
        if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) { 
            p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude); 
        } 
        if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) { 
            p += snprintf(p, end-p, " altitude=%g", r->fix.altitude); 
        } 
        if (r->fix.flags & GPS_LOCATION_HAS_SPEED) { 
            p += snprintf(p, end-p, " speed=%g", r->fix.speed); 
        } 
        if (r->fix.flags & GPS_LOCATION_HAS_BEARING) { 
            p += snprintf(p, end-p, " bearing=%g", r->fix.bearing); 
        } 
        if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) { 
            p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy); 
        } 
        gmtime_r( (time_t*) &r->fix.timestamp, &utc ); 
        p += snprintf(p, end-p, " time=%s", asctime( &utc ) ); 
        D(temp); 
//added by mayzhang for debug 
 
D("******************************1\n%s,%d:%s,may callback\n***************************\n",__FILE__,__LINE__,__FUNCTION__); 
#endif 
 
D("******************************2\n%s,%d:%s,may callback\n***************************\n",__FILE__,__LINE__,__FUNCTION__); 
   } 
         
        else { 
             /* D("no callback, keeping data until needed !"); */ 
        } 
    } 

作者“极客网络”