Research on Application and Development of GPS Beidou dual-mode technology-Data Structure extension and gps Development
Research on Application and Development of GPS Beidou dual-mode technology-Data Structure Extension
Or from gps. starting with the h header file, the structure of GpsSvStatus needs to be transformed. At that time, GpsSvStatus was designed to store gps satellite information, but now we need to store dual-mode data, so we need to expand this data structure. How can we expand it?
Of course, the cost is a little lower, and it cannot be completely re-launched. What I think of is to add a variable for the number of Beidou satellites, and the epemeris, almanac, and mask of BeiDou, in the past, all the Members in the data structure were stored using gps, so they were independent of each other. However, the sv_list author was lazy and shared, just doubling the array, the second half stores Beidou satellite information, so the first step is complete. The basic information is as follows:
/** Maximum number of SVs for gps_sv_status_callback(). */-#define GPS_MAX_SVS 32+#define GPS_MAX_SVS 64 /** Requested operational mode for GPS operation. */ typedef uint32_t GpsPositionMode;@@ -306,6 +306,25 @@ typedef struct { * were used for computing the most recent position fix. */ uint32_t used_in_fix_mask;++ /** Number of bd SVs currently visible. */+ int bd_num_svs; ++ /** Represents a bit mask indicating which SVs+ * have ephemeris data.+ */+ uint32_t bd_ephemeris_mask;++ /** Represents a bit mask indicating which SVs+ * have almanac data.+ */+ uint32_t bd_almanac_mask;++ /**+ * Represents a bit mask indicating which SVs+ * were used for computing the most recent position fix.+ */+ uint32_t bd_used_in_fix_mask; } GpsSvStatus;
The parsing itself is not very difficult, and it is fixed. Let's take a look at how GSV is parsed! As follows:
if ( !memcmp(tok.p, "GSV", 3) ) { int noSatellites; Token satellite_to_view;is_beidou = !memcmp(ptr, "BD", 2); satellite_to_view = nmea_tokenizer_get(tzer, 3); noSatellites = str2int(satellite_to_view.p, satellite_to_view.end); ALOGV(">>>is_beidou (%d) GSV satellite_to_view=%d", is_beidou, noSatellites); if (noSatellites > 0 ) { //tmp int sentence, totalSentences, curr, i, bd_cur; Token num_of_msg; Token no; num_of_msg = nmea_tokenizer_get(tzer, 1); no = nmea_tokenizer_get(tzer, 2); sentence = str2int(no.p, no.end); totalSentences = str2int(num_of_msg.p, num_of_msg.end); D(">>>gsv_index=%d,gsv_total=%d",sentence, totalSentences); if (sentence == 1 && !is_beidou) { r->sv_status.num_svs = 0; r->sv_status.ephemeris_mask = 0ul; r->sv_status.almanac_mask = 0ul; r->sv_status.bd_num_svs= 0; r->sv_status.bd_ephemeris_mask= 0ul; r->sv_status.bd_almanac_mask= 0ul;} curr = r->sv_status.num_svs;bd_cur = r->sv_status.bd_num_svs + 32; i = 0; while (i < 4 && (r->sv_status.num_svs < noSatellites || (is_beidou && r->sv_status.bd_num_svs < noSatellites))) { int prn; 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); prn = str2int(tok_prn.p, tok_prn.end); if (prn <= 0) { i += 1; continue; } if(is_beidou) { if(prn > 400) prn -= 400;//M8 BD base 400r->sv_status.sv_list[bd_cur].prn = prn;r->sv_status.sv_list[bd_cur].elevation = str2float(tok_elevation.p, tok_elevation.end);r->sv_status.sv_list[bd_cur].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);r->sv_status.sv_list[bd_cur].snr = str2float(tok_snr.p, tok_snr.end);r->sv_status.bd_ephemeris_mask|= (1ul << (prn-1));r->sv_status.bd_almanac_mask|= (1ul << (prn-1));r->sv_status.bd_num_svs+= 1;// bd num r->sv_status.num_svs += 1;//total num if(r->sv_status.sv_list[bd_cur].snr > 0) ALOGV("**bd_cur=%d num_svs:%d prn:%d snr=%f\n", bd_cur, r->sv_status.num_svs, r->sv_status.sv_list[bd_cur].prn,r->sv_status.sv_list[bd_cur].snr); bd_cur += 1; } else { r->sv_status.sv_list[curr].prn = prn; 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 << (prn-1)); r->sv_status.almanac_mask |= (1ul << (prn-1)); r->sv_status.num_svs += 1;if(r->sv_status.sv_list[curr].snr > 0) ALOGV("##curr=%d num_svs:%d prn:%d snr=%f\n", curr, r->sv_status.num_svs, r->sv_status.sv_list[curr].prn,r->sv_status.sv_list[curr].snr); curr += 1; } i += 1; }
Other GGA models have the same dual-mode. Next let's take a look at the situation of each satellite reported by android_location_GpsLocationProvider_read_sv_status in JNI. It shows that its interface also needs to be transformed and should be extended, as shown below:
@@ -465,17 +465,34 @@ static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, job jfloat* elev = env->GetFloatArrayElements(elevArray, 0); jfloat* azim = env->GetFloatArrayElements(azumArray, 0); jint* mask = env->GetIntArrayElements(maskArray, 0);+ int i, j; int num_svs = sGpsSvStatus.num_svs;- for (int i = 0; i < num_svs; i++) {+ int bd_num_svs = sGpsSvStatus.bd_num_svs;++ //gps info+ for (i = 0; i < (num_svs - bd_num_svs); i++) { prns[i] = sGpsSvStatus.sv_list[i].prn; snrs[i] = sGpsSvStatus.sv_list[i].snr; elev[i] = sGpsSvStatus.sv_list[i].elevation; azim[i] = sGpsSvStatus.sv_list[i].azimuth; }++ //bd info+ for (j = 0; j < bd_num_svs; j++) {+ prns[i+j] = sGpsSvStatus.sv_list[32+j].prn;+ snrs[i+j] = sGpsSvStatus.sv_list[32+j].snr;+ elev[i+j] = sGpsSvStatus.sv_list[32+j].elevation;+ azim[i+j] = sGpsSvStatus.sv_list[32+j].azimuth;+ }+ mask[0] = sGpsSvStatus.ephemeris_mask; mask[1] = sGpsSvStatus.almanac_mask; mask[2] = sGpsSvStatus.used_in_fix_mask;+ mask[3] = bd_num_svs; + mask[4] = sGpsSvStatus.bd_ephemeris_mask;+ mask[5] = sGpsSvStatus.bd_almanac_mask;+ mask[6] = sGpsSvStatus.bd_used_in_fix_mask;
This JNI interface directly gets the location provider of gps, and also needs to be extended
@@ -1285,7 +1285,9 @@ public class GpsLocationProvider implements LocationProviderInterface { try { listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],- mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);+ mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK],+ mSvMasks[BD_SVS_NUM], mSvMasks[BD_EPHEMERIS_MASK],+ mSvMasks[BD_ALMANAC_MASK],mSvMasks[BD_USED_FOR_FIX_MASK]); } catch (RemoteException e) { Log.w(TAG, "RemoteException in reportSvInfo"); mListeners.remove(listener);@@ -1296,22 +1298,33 @@ public class GpsLocationProvider implements LocationProviderInterface { } if (VERBOSE) {- Log.v(TAG, "SV count: " + svCount ++ Log.d(TAG, "SV count: " + svCount + " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) + " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK])); for (int i = 0; i < svCount; i++) {- Log.v(TAG, "sv: " + mSvs[i] ++ if(i < (svCount - mSvMasks[BD_SVS_NUM])){+ Log.d(TAG, "sv: " + mSvs[i] + " snr: " + mSnrs[i]/10 + " elev: " + mSvElevations[i] + " azimuth: " + mSvAzimuths[i] + ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") + ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") + ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));+ } else {++ Log.d(TAG, "BD sv: " + mSvs[i] ++ " BD snr: " + mSnrs[i]/10 ++ " BD elev: " + mSvElevations[i] ++ " BD azimuth: " + mSvAzimuths[i] ++ ((mSvMasks[BD_EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") ++ ((mSvMasks[BD_ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") ++ ((mSvMasks[BD_USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));+ } } } // return number of sets used in fix instead of total- updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));+ updateStatus(mStatus, (Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK] + Integer.bitCount(mSvMasks[BD_USED_FOR_FIX_MASK])))); if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 && System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {@@ -1895,17 +1908,21 @@ public class GpsLocationProvider implements LocationProviderInterface { } // for GPS SV statistics- private static final int MAX_SVS = 32;+ private static final int MAX_SVS = 64; private static final int EPHEMERIS_MASK = 0; private static final int ALMANAC_MASK = 1; private static final int USED_FOR_FIX_MASK = 2;+ private static final int BD_SVS_NUM = 3;+ private static final int BD_EPHEMERIS_MASK = 4;+ private static final int BD_ALMANAC_MASK = 5;+ private static final int BD_USED_FOR_FIX_MASK = 6; // preallocated arrays, to avoid memory allocation in reportStatus() private int mSvs[] = new int[MAX_SVS]; private float mSnrs[] = new float[MAX_SVS]; private float mSvElevations[] = new float[MAX_SVS]; private float mSvAzimuths[] = new float[MAX_SVS];- private int mSvMasks[] = new int[3];+ private int mSvMasks[] = new int[7]; private int mSvCount; // preallocated to avoid memory allocation in reportNmea() private byte[] mNmeaBuffer = new byte[120];
This is already part of java, and more than half of it has been completed. Later I will talk about the processing in the second half, and there are also a lot of channels in it.