Ejemplo n.º 1
0
BOOL NMEAParser::GGA(TCHAR *String, TCHAR **params, size_t nparams, NMEA_INFO *pGPS)
{

  GGAAvailable = TRUE;
  GPSCONNECT = TRUE;     // 091208

  // this will force gps invalid but will NOT assume gps valid!
  nSatellites = (int)(min(16.0, StrToDouble(params[6], NULL)));
  if (nSatellites==0) {
	gpsValid = false;
  }

  double ggafix = StrToDouble(params[5],NULL);
  if ( ggafix==0 || ggafix>5 ) {
	#ifdef DEBUG_GPS
	if (ggafix>5) StartupStore(_T("------ GGA DEAD RECKON fix skipped%s"),NEWLINE);
	#endif
	gpsValid=false;
  } else {
	gpsValid=true;
  }

  if (!activeGPS) return TRUE;

  pGPS->SatellitesUsed = nSatellites; // 091208
  pGPS->NAVWarning = !gpsValid; // 091208

  GGAtime=StrToDouble(params[0],NULL);
  // Even with invalid fix, we might still have valid time
  // I assume that 0 is invalid, and I am very sorry for UTC time 00:00 ( missing a second a midnight).
  // is better than risking using 0 as valid, since many gps do not respect any real nmea standard
  //
  // Update 121215: do not update time with GGA if RMC is found, because at 00UTC only RMC will set the date change!
  // Remember that we trigger update of calculations when we get GGA.
  // So what happens if the gps sequence is GGA and then RMC?
  //    2359UTC:
  //           GGA , old date, trigger gps calc
  //           RMC,  old date
  //    0000UTC:
  //           GGA, old date even if new date will come for the same quantum,
  //                GGAtime>0, see (*)
  //                BANG! oldtime from RMC is 2359, new time from GGA is 0, time is in the past!
  //
  // If the gps is sending first RMC, this problem does not appear of course.
  //
  // (*) IMPORTANT> GGAtime at 00UTC will most likely be >0! Because time is in hhmmss.ss  .ss is always >0!!
  // We check GGAtime, RMCtime, GLLtime etc. for 0 because in case of error the gps will send 000000.000 !!
  //
  if ( (!RMCAvailable && (GGAtime>0)) || ((GGAtime>0) && (GGAtime == RMCtime))  ) {  // RMC already came in same time slot

	#if DEBUGSEQ
	StartupStore(_T("... GGA update time = %f RMCtime=%f\n"),GGAtime,RMCtime); // 31C
	#endif
	double ThisTime = TimeModify(GGAtime, pGPS);

	if (!TimeHasAdvanced(ThisTime, pGPS)) {
		#if DEBUGSEQ
		StartupStore(_T(".... GGA time not advanced, skip\n")); // 31C
		#endif
		return FALSE;
	}
  }
  if (gpsValid) {
	double tmplat;
	double tmplon;
	tmplat = MixedFormatToDegrees(StrToDouble(params[1], NULL));
	tmplat = NorthOrSouth(tmplat, params[2][0]);
	tmplon = MixedFormatToDegrees(StrToDouble(params[3], NULL));
	tmplon = EastOrWest(tmplon,params[4][0]);
	if (!((tmplat == 0.0) && (tmplon == 0.0))) {
		pGPS->Latitude = tmplat;
		pGPS->Longitude = tmplon;
	} 
	else {
		#ifdef DEBUG_GPS
		StartupStore(_T("++++++ GGA gpsValid with invalid posfix!%s"),NEWLINE);
		#endif
		gpsValid=false;
	}
  }
 
  // GGA is marking now triggering end of data, so OK to use baro
  // Even with invalid fix we might have valid baro data of course

  // any NMEA sentence with time can now trigger gps update: the first to detect new time will make trigger.
  // we assume also that any sentence with no time belongs to current time.
  // note that if no time from gps, no use of vario and baro data, but also no fix available.. so no problems

  if(RMZAvailable)
  {
	UpdateBaroSource(pGPS, isFlarm? BARO__RMZ_FLARM:BARO__RMZ, NULL, RMZAltitude);
  }
  else if(RMAAvailable) {
	UpdateBaroSource(pGPS,  BARO__RMA,NULL, RMAAltitude);
  }

  // If  no gps fix, at this point we trigger refresh and quit
  if (!gpsValid) { 
	#if DEBUGSEQ
	StartupStore(_T("........ GGA no gps valid, triggerGPS!\n")); // 31C
	#endif
	TriggerGPSUpdate(); 
	return FALSE;
  }

  // "Altitude" should always be GPS Altitude.
  pGPS->Altitude = ParseAltitude(params[8], params[9]);
  pGPS->Altitude += (GPSAltitudeOffset/1000); // BUGFIX 100429
  
  double GeoidSeparation;

  if (_tcslen(params[10])>0) {
    // No real need to parse this value,
    // but we do assume that no correction is required in this case
    GeoidSeparation = ParseAltitude(params[10], params[11]);
  } else {
	if (UseGeoidSeparation) {
		GeoidSeparation = LookupGeoidSeparation(pGPS->Latitude, pGPS->Longitude);
		pGPS->Altitude -= GeoidSeparation;
	}
  }

  // if RMC would be Triggering update, we loose the relative altitude, which is coming AFTER rmc! 
  // This was causing old altitude recorded in new pos fix.
  // 120428:
  // GGA will trigger gps if there is no RMC,  
  // or if GGAtime is the same as RMCtime, which means that RMC already came and we are last in the sequence
  if ( !RMCAvailable || (GGAtime == RMCtime)  )  {
	#if DEBUGSEQ
	StartupStore(_T("... GGA trigger gps, GGAtime==RMCtime\n")); // 31C
	#endif
	TriggerGPSUpdate(); 
  }
  return TRUE;

} // END GGA
Ejemplo n.º 2
0
JNIEXPORT void JNICALL
Java_org_xcsoar_InternalGPS_setLocation(JNIEnv *env, jobject obj,
                                        jlong time, jint n_satellites,
                                        jdouble longitude, jdouble latitude,
                                        jboolean hasAltitude, jdouble altitude,
                                        jboolean hasBearing, jdouble bearing,
                                        jboolean hasSpeed, jdouble speed,
                                        jboolean hasAccuracy, jdouble accuracy,
                                        jboolean hasAcceleration, jdouble acceleration)
{
  jfieldID fid_index = env->GetFieldID(env->GetObjectClass(obj),
                                       "index", "I");
  unsigned index = env->GetIntField(obj, fid_index);

  mutexBlackboard.Lock();

  NMEA_INFO &basic = device_blackboard.SetRealState(index);
  basic.Connected.Update(fixed(MonotonicClockMS()) / 1000);

  BrokenDateTime date_time = BrokenDateTime::FromUnixTimeUTC(time / 1000);
  fixed second_of_day = fixed(date_time.GetSecondOfDay()) +
    /* add the millisecond fraction of the original timestamp for
       better accuracy */
    fixed((unsigned)(time % 1000)) / 1000u;

  if (second_of_day < basic.Time && date_time > basic.DateTime)
    /* don't wrap around when going past midnight in UTC */
    second_of_day += fixed(24u * 3600u);

  basic.Time = second_of_day;
  basic.DateTime = date_time;

  basic.gps.SatellitesUsed = n_satellites;
  basic.gps.real = true;
  basic.gps.AndroidInternalGPS = true;
  basic.Location = GeoPoint(Angle::degrees(fixed(longitude)),
                            Angle::degrees(fixed(latitude)));
  if (n_satellites > 0)
    basic.LocationAvailable.Update(basic.Time);
  else
    basic.LocationAvailable.Clear();

  if (hasAltitude) {
    fixed GeoidSeparation = LookupGeoidSeparation(basic.Location);
    basic.GPSAltitude = fixed(altitude) - GeoidSeparation;
    basic.GPSAltitudeAvailable.Update(basic.Time);
  } else
    basic.GPSAltitudeAvailable.Clear();

  if (hasBearing) {
    basic.track = Angle::degrees(fixed(bearing));
    basic.track_available.Update(basic.Time);
  } else
    basic.track_available.Clear();

  if (hasSpeed) {
    basic.GroundSpeed = fixed(speed);
    basic.GroundSpeedAvailable.Update(basic.Time);
  }

  if (hasAccuracy)
    basic.gps.HDOP = fixed(accuracy);

  if (hasAcceleration) {
    // TODO: use ACCELERATION_STATE::complement() ?!?
    basic.acceleration.Available = true;
    basic.acceleration.Gload = fixed(acceleration);
  }

  device_blackboard.Merge();
  mutexBlackboard.Unlock();
}
Ejemplo n.º 3
0
BOOL NMEAParser::GGA(TCHAR *String, TCHAR **params, size_t nparams, NMEA_INFO *GPS_INFO)
{

  if (ReplayLogger::IsEnabled()) {
        return TRUE;
  }

  GGAAvailable = TRUE;
  GPSCONNECT = TRUE;     // 091208

  // this will force gps invalid but will NOT assume gps valid!
  nSatellites = (int)(min(16.0, StrToDouble(params[6], NULL)));
  if (nSatellites==0) {
	gpsValid = false;
  }

  double ggafix = StrToDouble(params[5],NULL);
  if ( ggafix==0 || ggafix>5 ) {
	#ifdef DEBUG_GPS
	if (ggafix>5) StartupStore(_T("------ GGA DEAD RECKON fix skipped%s"),NEWLINE);
	#endif
	gpsValid=false;
  } else {
	gpsValid=true;
  }

  // don't set any GPS_INFO if not activeGPS!!
  if (!activeGPS) return TRUE;

  GPS_INFO->SatellitesUsed = nSatellites; // 091208
  GPS_INFO->NAVWarning = !gpsValid; // 091208

//  // GPS_INFO->SatellitesUsed = (int)(min(16,StrToDouble(params[6], NULL))); 091205 091208 moved up
//  GPS_INFO->SatellitesUsed = nSatellites; // 091205

  double ggatime=StrToDouble(params[0],NULL);
  // Even with invalid fix, we might still have valid time
  // I assume that 0 is invalid, and I am very sorry for UTC time 00:00 ( missing a second a midnight).
  // is better than risking using 0 as valid, since many gps do not respect any real nmea standard
  if (ggatime>0) { 
	#ifdef NEWTRIGGERGPS
	double ThisTime = TimeConvert(ggatime, GPS_INFO);
	#else
	double ThisTime = TimeModify(ggatime, GPS_INFO);
	#endif

	#ifndef NEWTRIGGERGPS
	if (!TimeHasAdvanced(ThisTime, GPS_INFO))
		return FALSE;
	#endif

	#ifdef NEWTRIGGERGPS
		// is time advanced to a new quantum?
		if (ThisTime >NmeaTime) {
			// yes so lets trigger the gps event
			TriggerGPSUpdate();
			Sleep(50); // 091208
			NmeaTime=ThisTime;
			TimeSet(GPS_INFO); // 091208
			TimeHasAdvanced(ThisTime, GPS_INFO); // 091208
			StartupStore(_T(".............. trigger from GGA\n"));
		}
	#endif
  }
  if (gpsValid) {
	double tmplat;
	double tmplon;
	tmplat = MixedFormatToDegrees(StrToDouble(params[1], NULL));
	tmplat = NorthOrSouth(tmplat, params[2][0]);
	tmplon = MixedFormatToDegrees(StrToDouble(params[3], NULL));
	tmplon = EastOrWest(tmplon,params[4][0]);
	if (!((tmplat == 0.0) && (tmplon == 0.0))) {
		GPS_INFO->Latitude = tmplat;
		GPS_INFO->Longitude = tmplon;
	} 
	else {
		#ifdef DEBUG_GPS
		StartupStore(_T("++++++ GGA gpsValid with invalid posfix!%s"),NEWLINE);
		#endif
		gpsValid=false;
	}
  }
 
  // GGA is marking now triggering end of data, so OK to use baro
  // Even with invalid fix we might have valid baro data of course

  // any NMEA sentence with time can now trigger gps update: the first to detect new time will make trigger.
  // we assume also that any sentence with no time belongs to current time.
  // note that if no time from gps, no use of vario and baro data, but also no fix available.. so no problems
  if(RMZAvailable) {
	GPS_INFO->BaroAltitudeAvailable = true;
	GPS_INFO->BaroAltitude = RMZAltitude;
  }
  else if(RMAAvailable) {
	GPS_INFO->BaroAltitudeAvailable = true;
	GPS_INFO->BaroAltitude = RMAAltitude;
  }

#ifndef NEWTRIGGERGPS
  if (!gpsValid) { // 091108 addon BUGFIX GCA
	// in old mode, GGA had priority over RMC for triggering, so this was needed in case of no signal 
	TriggerGPSUpdate(); // 091205 TESTFIX
	return FALSE; // 091108 addon BUGFIX GCA
  }
#endif

  // "Altitude" should always be GPS Altitude.
  GPS_INFO->Altitude = ParseAltitude(params[8], params[9]);
  GPS_INFO->Altitude += (GPSAltitudeOffset/1000); // BUGFIX 100429
  
  double GeoidSeparation;

  if (_tcslen(params[10])>0) {
    // No real need to parse this value,
    // but we do assume that no correction is required in this case
    GeoidSeparation = ParseAltitude(params[10], params[11]);
  } else {
	if (UseGeoidSeparation) {
		GeoidSeparation = LookupGeoidSeparation(GPS_INFO->Latitude, GPS_INFO->Longitude);
		GPS_INFO->Altitude -= GeoidSeparation;
	}
  }

#ifndef NEWTRIGGERGPS
  // if RMC would be Triggering update, we loose the relative altitude, which is coming AFTER rmc! 
  // This was causing old altitude recorded in new pos fix.
  TriggerGPSUpdate(); 
#endif
  return TRUE;
}