【转】android hal 层GPS 研究总结

/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

欢迎交流。

<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 !"); */
        }
    }
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值