Пример #1
0
/**
 * Calculates location, altitude, average climb speed and
 * looks up the callsign of each target
 */
void
DeviceBlackboard::ProcessFLARM()
{
  const NMEA_INFO &basic = Basic();
  FLARM_STATE &flarm = SetBasic().flarm;
  const FLARM_STATE &last_flarm = LastBasic().flarm;

  // if (FLARM data is available)
  if (!flarm.available || flarm.traffic.empty())
    return;

  fixed FLARM_NorthingToLatitude(0);
  fixed FLARM_EastingToLongitude(0);

  if (basic.LocationAvailable) {
    // Precalculate relative east and north projection to lat/lon
    // for Location calculations of each target
    Angle delta_lat = Angle::degrees(fixed(0.01));
    Angle delta_lon = Angle::degrees(fixed(0.01));

    GeoPoint plat = basic.Location;
    plat.Latitude += delta_lat;
    GeoPoint plon = basic.Location;
    plon.Longitude += delta_lon;

    fixed dlat = Distance(basic.Location, plat);
    fixed dlon = Distance(basic.Location, plon);

    if (positive(fabs(dlat)) && positive(fabs(dlon))) {
      FLARM_NorthingToLatitude = delta_lat.value_degrees() / dlat;
      FLARM_EastingToLongitude = delta_lon.value_degrees() / dlon;
    }
  }

  // for each item in traffic
  for (unsigned i = 0; i < flarm.traffic.size(); i++) {
    FLARM_TRAFFIC &traffic = flarm.traffic[i];

    // if we don't know the target's name yet
    if (!traffic.HasName()) {
      // lookup the name of this target's id
      const TCHAR *fname = FlarmDetails::LookupCallsign(traffic.id);
      if (fname != NULL)
        traffic.name = fname;
    }

    // Calculate distance
    traffic.distance = hypot(traffic.relative_north, traffic.relative_east);

    // Calculate Location
    traffic.location_available = basic.LocationAvailable;
    if (traffic.location_available) {
      traffic.location.Latitude =
          Angle::degrees(traffic.relative_north * FLARM_NorthingToLatitude) +
          basic.Location.Latitude;

      traffic.location.Longitude =
          Angle::degrees(traffic.relative_east * FLARM_EastingToLongitude) +
          basic.Location.Longitude;
    }

    // Calculate absolute altitude
    traffic.altitude_available = basic.GPSAltitudeAvailable;
    if (traffic.altitude_available)
      traffic.altitude = traffic.relative_altitude + basic.GPSAltitude;

    // Calculate average climb rate
    traffic.climb_rate_avg30s_available = traffic.altitude_available;
    if (traffic.climb_rate_avg30s_available)
      traffic.climb_rate_avg30s =
        flarmCalculations.Average30s(traffic.id, basic.Time, traffic.altitude);

    // The following calculations are only relevant for targets
    // where information is missing
    if (traffic.track_received || traffic.turn_rate_received ||
        traffic.speed_received || traffic.climb_rate_received)
      continue;

    // Check if the target has been seen before in the last seconds
    const FLARM_TRAFFIC *last_traffic = last_flarm.FindTraffic(traffic.id);
    if (last_traffic == NULL || !last_traffic->valid)
      continue;

    // Calculate the time difference between now and the last contact
    fixed dt = traffic.valid.GetTimeDifference(last_traffic->valid);
    if (positive(dt)) {
      // Calculate the immediate climb rate
      if (!traffic.climb_rate_received)
        traffic.climb_rate =
          (traffic.relative_altitude - last_traffic->relative_altitude) / dt;
    } else {
      // Since the time difference is zero (or negative)
      // we can just copy the old values
      if (!traffic.climb_rate_received)
        traffic.climb_rate = last_traffic->climb_rate;
    }

    if (positive(dt) &&
        traffic.location_available &&
        last_traffic->location_available) {
      // Calculate the GeoVector between now and the last contact
      GeoVector vec = last_traffic->location.distance_bearing(traffic.location);

      if (!traffic.track_received)
        traffic.track = vec.Bearing;

      // Calculate the turn rate
      if (!traffic.turn_rate_received)
        traffic.turn_rate =
          (traffic.track - last_traffic->track).as_delta().value_degrees() / dt;

      // Calculate the speed [m/s]
      if (!traffic.speed_received)
        traffic.speed = vec.Distance / dt;
    } else {
      // Since the time difference is zero (or negative)
      // we can just copy the old values
      if (!traffic.track_received)
        traffic.track = last_traffic->track;

      if (!traffic.turn_rate_received)
        traffic.turn_rate = last_traffic->turn_rate;

      if (!traffic.speed_received)
        traffic.speed = last_traffic->speed;
    }
  }
}
Пример #2
0
/**
 * Parses a PFLAA sentence
 * (Data on other moving objects around)
 * @param String Input string
 * @param params Parameter array
 * @param nparams Number of parameters
 * @param GPS_INFO GPS_INFO struct to parse into
 * @return Parsing success
 * @see http://flarm.com/support/manual/FLARM_DataportManual_v4.06E.pdf
 */
bool
NMEAParser::PFLAA(NMEAInputLine &line, NMEA_INFO *GPS_INFO)
{
  FLARM_STATE &flarm = GPS_INFO->flarm;

  isFlarm = true;

  // calculate relative east and north projection to lat/lon

  Angle delta_lat = Angle::degrees(fixed(0.01));
  Angle delta_lon = Angle::degrees(fixed(0.01));

  GeoPoint plat = GPS_INFO->Location;
  plat.Latitude += delta_lat;
  GeoPoint plon = GPS_INFO->Location;
  plon.Longitude += delta_lon;

  fixed dlat = Distance(GPS_INFO->Location, plat);
  fixed dlon = Distance(GPS_INFO->Location, plon);

  fixed FLARM_NorthingToLatitude(0);
  fixed FLARM_EastingToLongitude(0);

  if (positive(fabs(dlat)) && positive(fabs(dlon))) {
    FLARM_NorthingToLatitude = delta_lat.value_degrees() / dlat;
    FLARM_EastingToLongitude = delta_lon.value_degrees() / dlon;
  }

  // PFLAA,<AlarmLevel>,<RelativeNorth>,<RelativeEast>,<RelativeVertical>,
  //   <IDType>,<ID>,<Track>,<TurnRate>,<GroundSpeed>,<ClimbRate>,<AcftType>
  FLARM_TRAFFIC traffic;
  traffic.AlarmLevel = line.read(0);
  traffic.RelativeNorth = line.read(fixed_zero);
  traffic.RelativeEast = line.read(fixed_zero);
  traffic.RelativeAltitude = line.read(fixed_zero);
  traffic.IDType = line.read(0);

  // 5 id, 6 digit hex
  char id_string[16];
  line.read(id_string, 16);
  traffic.ID.parse(id_string, NULL);

  traffic.TrackBearing = Angle::degrees(line.read(fixed_zero));
  traffic.TurnRate = line.read(fixed_zero);
  traffic.Speed = line.read(fixed_zero);
  traffic.ClimbRate = line.read(fixed_zero);
  traffic.Type = (FLARM_TRAFFIC::AircraftType)line.read(0);

  FLARM_TRAFFIC *flarm_slot = flarm.FindTraffic(traffic.ID);
  if (flarm_slot == NULL) {
    flarm_slot = flarm.AllocateTraffic();
    if (flarm_slot == NULL)
      // no more slots available
      return false;

    flarm_slot->ID = traffic.ID;

    flarm.NewTraffic = true;
    InputEvents::processGlideComputer(GCE_FLARM_NEWTRAFFIC);
  }

  // set time of fix to current time
  flarm_slot->Time_Fix = GPS_INFO->Time;

  // PFLAA,<AlarmLevel>,<RelativeNorth>,<RelativeEast>,<RelativeVertical>,
  //   <IDType>,<ID>,<Track>,<TurnRate>,<GroundSpeed>,<ClimbRate>,<AcftType>
  flarm_slot->AlarmLevel = traffic.AlarmLevel;
  flarm_slot->RelativeNorth = traffic.RelativeNorth;
  flarm_slot->RelativeEast = traffic.RelativeEast;
  flarm_slot->RelativeAltitude = traffic.RelativeAltitude;
  flarm_slot->IDType = traffic.IDType;
  flarm_slot->TrackBearing = traffic.TrackBearing;
  flarm_slot->TurnRate = traffic.TurnRate;
  flarm_slot->Speed = traffic.Speed;
  flarm_slot->ClimbRate = traffic.ClimbRate;
  flarm_slot->Type = traffic.Type;

  // 1 relativenorth, meters
  flarm_slot->Location.Latitude = Angle::degrees(flarm_slot->RelativeNorth
                                        * FLARM_NorthingToLatitude) + GPS_INFO->Location.Latitude;

  // 2 relativeeast, meters
  flarm_slot->Location.Longitude = Angle::degrees(flarm_slot->RelativeEast
                                         * FLARM_EastingToLongitude) + GPS_INFO->Location.Longitude;

  // alt
  flarm_slot->Altitude = flarm_slot->RelativeAltitude + GPS_INFO->GPSAltitude;

  flarm_slot->Average30s = flarmCalculations.Average30s(flarm_slot->ID,
                                                        GPS_INFO->Time,
                                                        flarm_slot->Altitude);

  // QUESTION TB: never returns true?!
  return false;
}
Пример #3
0
BOOL NMEAParser::PFLAA(TCHAR *String, TCHAR **params, size_t nparams, NMEA_INFO *pGPS)
{
  int flarm_slot = 0;

  isFlarm = true;

  // 5 id, 6 digit hex
  long ID;
  swscanf(params[5],TEXT("%lx"), &ID);
//  unsigned long uID = ID;

  flarm_slot = FLARM_FindSlot(pGPS, ID);
  if (flarm_slot<0) {
    // no more slots available,
	#ifdef DEBUG_LKT
	StartupStore(_T("... NO SLOTS for Flarm traffic, too many ids!%s"),NEWLINE);
	#endif
	return FALSE;
  }

  // before changing timefix, see if it was an old target back locked in!
  CheckBackTarget(pGPS, flarm_slot);
  // and then set time of fix to current time
  pGPS->FLARM_Traffic[flarm_slot].Time_Fix = pGPS->Time;

  TCHAR nString[MAX_NMEA_LEN+1];
  unsigned int i, j;
  for (i=0, j=0; i<_tcslen(String); i++) {
	// if not a comma, copy and proceed
	if (String[i] != _T(',')) {
		nString[j++]=String[i];
		continue;
	}
	// there was a comma, but the next one is not a comma, so ok..
	if (String[i+1] != _T(',') ) {
		nString[j++]=String[i];
		continue;
	}
	// We have a bad ,, case that scanf cannot bear with, so we add a 0
	nString[j++] = String[i];
	nString[j++] = _T('0');
  }
  nString[j]=_T('\0');

  //#ifdef DEBUG_LKT
  //StartupStore(_T("PFLAA: %s%s"),nString,NEWLINE);
  //#endif

  _stscanf(nString,
	  TEXT("%hu,%lf,%lf,%lf,%hu,%lx,%lf,%lf,%lf,%lf,%hu"),
	  &pGPS->FLARM_Traffic[flarm_slot].AlarmLevel, // unsigned short 0
	  &pGPS->FLARM_Traffic[flarm_slot].RelativeNorth, //  1	
	  &pGPS->FLARM_Traffic[flarm_slot].RelativeEast, //   2
	  &pGPS->FLARM_Traffic[flarm_slot].RelativeAltitude, //  3
	  &pGPS->FLARM_Traffic[flarm_slot].IDType, // unsigned short     4
	  &pGPS->FLARM_Traffic[flarm_slot].ID, // 6 char hex
	  &pGPS->FLARM_Traffic[flarm_slot].TrackBearing, // double       6
	  &pGPS->FLARM_Traffic[flarm_slot].TurnRate, // double           7
	  &pGPS->FLARM_Traffic[flarm_slot].Speed, // double              8 m/s
	  &pGPS->FLARM_Traffic[flarm_slot].ClimbRate, // double          9 m/s
	  &pGPS->FLARM_Traffic[flarm_slot].Type); // unsigned short     10
  // 1 relativenorth, meters  
  pGPS->FLARM_Traffic[flarm_slot].Latitude = 
    pGPS->FLARM_Traffic[flarm_slot].RelativeNorth *FLARM_NorthingToLatitude + pGPS->Latitude;
  // 2 relativeeast, meters
  pGPS->FLARM_Traffic[flarm_slot].Longitude = 
    pGPS->FLARM_Traffic[flarm_slot].RelativeEast *FLARM_EastingToLongitude + pGPS->Longitude;

  // we need to compare with BARO altitude FLARM relative Alt difference!
  if (pGPS->BaroAltitude>0) // just to be sure
	pGPS->FLARM_Traffic[flarm_slot].Altitude = pGPS->FLARM_Traffic[flarm_slot].RelativeAltitude + pGPS->BaroAltitude;
  else
	pGPS->FLARM_Traffic[flarm_slot].Altitude = pGPS->FLARM_Traffic[flarm_slot].RelativeAltitude + pGPS->Altitude;



  pGPS->FLARM_Traffic[flarm_slot].Average30s = flarmCalculations.Average30s(
	  pGPS->FLARM_Traffic[flarm_slot].ID,
	  pGPS->Time,
	  pGPS->FLARM_Traffic[flarm_slot].Altitude);

  TCHAR *name = pGPS->FLARM_Traffic[flarm_slot].Name;
  //TCHAR *cn = pGPS->FLARM_Traffic[flarm_slot].Cn;
  // If there is no name yet, or if we have a pending update event..
  if (!_tcslen(name) || pGPS->FLARM_Traffic[flarm_slot].UpdateNameFlag ) {

	#ifdef DEBUG_LKT
	if (pGPS->FLARM_Traffic[flarm_slot].UpdateNameFlag ) {
		StartupStore(_T("... UpdateNameFlag for slot %d\n"),flarm_slot);
	} else {
		StartupStore(_T("... First lookup name for slot %d\n"),flarm_slot);
	}
	#endif

	pGPS->FLARM_Traffic[flarm_slot].UpdateNameFlag=false; // clear flag first
	TCHAR *fname = LookupFLARMDetails(pGPS->FLARM_Traffic[flarm_slot].ID);
	if (fname) {
		LK_tcsncpy(name,fname,MAXFLARMNAME);

		//  Now we have the name, so lookup also for the Cn
		// This will return either real Cn or Name, again
		TCHAR *cname = LookupFLARMCn(pGPS->FLARM_Traffic[flarm_slot].ID);
		if (cname) {
			int cnamelen=_tcslen(cname);
			if (cnamelen<=MAXFLARMCN) {
				_tcscpy( pGPS->FLARM_Traffic[flarm_slot].Cn, cname);
			} else {
				// else probably it is the Name again, and we create a fake Cn
				pGPS->FLARM_Traffic[flarm_slot].Cn[0]=cname[0];
				pGPS->FLARM_Traffic[flarm_slot].Cn[1]=cname[cnamelen-2];
				pGPS->FLARM_Traffic[flarm_slot].Cn[2]=cname[cnamelen-1];
				pGPS->FLARM_Traffic[flarm_slot].Cn[3]=_T('\0');
			}
		} else {
			_tcscpy( pGPS->FLARM_Traffic[flarm_slot].Cn, _T("Err"));
		}

		#ifdef DEBUG_LKT
		StartupStore(_T("... PFLAA Name to FlarmSlot=%d ID=%lx Name=<%s> Cn=<%s>\n"),
			flarm_slot,
	  		pGPS->FLARM_Traffic[flarm_slot].ID,
			pGPS->FLARM_Traffic[flarm_slot].Name,
			pGPS->FLARM_Traffic[flarm_slot].Cn);
		#endif
	} else {
		// Else we NEED to set a name, otherwise it will constantly search for it over and over..
		name[0]=_T('?');
		name[1]=_T('\0');
		pGPS->FLARM_Traffic[flarm_slot].Cn[0]=_T('?');
		pGPS->FLARM_Traffic[flarm_slot].Cn[1]=_T('\0');
		
		#ifdef DEBUG_LKT
		StartupStore(_T("... New FlarmSlot=%d ID=%lx with no name, assigned a \"?\"\n"),
			flarm_slot,
	  		pGPS->FLARM_Traffic[flarm_slot].ID);
		#endif
	}
  }

  #ifdef DEBUG_LKT
  StartupStore(_T("... PFLAA pGPS slot=%d ID=%lx name=<%s> cn=<%s> rAlt=%.0f Track=%.0f Speed=%.0f Climb=%.1f Baro=%f FlAlt=%f\n"),
	flarm_slot,
	pGPS->FLARM_Traffic[flarm_slot].ID,
	pGPS->FLARM_Traffic[flarm_slot].Name,
	pGPS->FLARM_Traffic[flarm_slot].Cn,
	pGPS->FLARM_Traffic[flarm_slot].RelativeAltitude,
	pGPS->FLARM_Traffic[flarm_slot].TrackBearing,
	pGPS->FLARM_Traffic[flarm_slot].Speed,
	pGPS->FLARM_Traffic[flarm_slot].ClimbRate,
	pGPS->BaroAltitude,
	pGPS->FLARM_Traffic[flarm_slot].Altitude);
  #endif

  //  update Virtual Waypoint for target FLARM
  if (flarm_slot == LKTargetIndex) {
	WayPointList[RESWP_FLARMTARGET].Latitude   = pGPS->FLARM_Traffic[LKTargetIndex].Latitude;
	WayPointList[RESWP_FLARMTARGET].Longitude  = pGPS->FLARM_Traffic[LKTargetIndex].Longitude;
	WayPointList[RESWP_FLARMTARGET].Altitude   = pGPS->FLARM_Traffic[LKTargetIndex].Altitude;
  }


  return FALSE;
}
Пример #4
0
//
// The purpose of simulating flarm traffic is NOT to play a videogame against flarm objects:
// we only need some traffic to display for testing on ground during simulations.
//
// >>>>> This is accessing directly the GPS_INFO main struct, writing inside it. <<<<<
// Called by LKSimulator, already locking FlightData . No worry.
//
void SimFlarmTraffic(long ID, double offset)
{
  int flarm_slot = 0;
  bool newtraffic=false;

  GPS_INFO.FLARM_Available=true;
  LastFlarmCommandTime=GPS_INFO.Time; // useless really, we dont call UpdateMonitor from SIM
  

  flarm_slot = FLARM_FindSlot(&GPS_INFO, ID);

  if (flarm_slot<0) return;
  if ( GPS_INFO.FLARM_Traffic[flarm_slot].Status == LKT_EMPTY) {
	newtraffic=true;
  }

  // before changing timefix, see if it was an old target back locked in!
  CheckBackTarget(&GPS_INFO, flarm_slot);
  // and then set time of fix to current time
  GPS_INFO.FLARM_Traffic[flarm_slot].Time_Fix = GPS_INFO.Time;

/*
	  TEXT("%hu,%lf,%lf,%lf,%hu,%lx,%lf,%lf,%lf,%lf,%hu"),
	  &GPS_INFO.FLARM_Traffic[flarm_slot].AlarmLevel, // unsigned short 0
	  &GPS_INFO.FLARM_Traffic[flarm_slot].RelativeNorth, //  1	
	  &GPS_INFO.FLARM_Traffic[flarm_slot].RelativeEast, //   2
	  &GPS_INFO.FLARM_Traffic[flarm_slot].RelativeAltitude, //  3
	  &GPS_INFO.FLARM_Traffic[flarm_slot].IDType, // unsigned short     4
	  &GPS_INFO.FLARM_Traffic[flarm_slot].ID, // 6 char hex
	  &GPS_INFO.FLARM_Traffic[flarm_slot].TrackBearing, // double       6
	  &GPS_INFO.FLARM_Traffic[flarm_slot].TurnRate, // double           7
	  &GPS_INFO.FLARM_Traffic[flarm_slot].Speed, // double              8 m/s
	  &GPS_INFO.FLARM_Traffic[flarm_slot].ClimbRate, // double          9 m/s
	  &GPS_INFO.FLARM_Traffic[flarm_slot].Type); // unsigned short     10
*/

  // If first time seen this traffic, place it nearby
  if ( newtraffic ) {
	GPS_INFO.FLARM_Traffic[flarm_slot].RelativeNorth=2;
	GPS_INFO.FLARM_Traffic[flarm_slot].RelativeEast=2;
	GPS_INFO.FLARM_Traffic[flarm_slot].Latitude  = SimNewCoordinate(GPS_INFO.Latitude, offset);
	GPS_INFO.FLARM_Traffic[flarm_slot].Longitude = SimNewCoordinate(GPS_INFO.Longitude,offset);
	GPS_INFO.FLARM_Traffic[flarm_slot].Altitude = SimNewAltitude(GPS_INFO.Altitude);

	GPS_INFO.FLARM_Traffic[flarm_slot].TrackBearing= (double) rand()/91.276;
	GPS_INFO.FLARM_Traffic[flarm_slot].AlarmLevel=0;
	GPS_INFO.FLARM_Traffic[flarm_slot].ID=ID;
	GPS_INFO.FLARM_Traffic[flarm_slot].TurnRate=0;
	GPS_INFO.FLARM_Traffic[flarm_slot].Speed= SimNewSpeed(GPS_INFO.Speed);

	GPS_INFO.FLARM_Traffic[flarm_slot].Status = LKT_REAL;
  } else {
	GPS_INFO.FLARM_Traffic[flarm_slot].Latitude  += (double)(rand()/20000000.0)*(rand()>15000?1:-1);
	GPS_INFO.FLARM_Traffic[flarm_slot].Longitude += (double)(rand()/20000000.0)*(rand()>15000?1:-1);
	GPS_INFO.FLARM_Traffic[flarm_slot].Altitude += (double)(rand()/2200.0)*(rand()>15000?1:-1);
  }
  GPS_INFO.FLARM_Traffic[flarm_slot].RelativeAltitude = GPS_INFO.FLARM_Traffic[flarm_slot].Altitude - GPS_INFO.Altitude;

  //
  GPS_INFO.FLARM_Traffic[flarm_slot].Average30s = flarmCalculations.Average30s(
	  GPS_INFO.FLARM_Traffic[flarm_slot].ID,
	  GPS_INFO.Time,
	  GPS_INFO.FLARM_Traffic[flarm_slot].Altitude);

  TCHAR *name = GPS_INFO.FLARM_Traffic[flarm_slot].Name;
  //TCHAR *cn = GPS_INFO.FLARM_Traffic[flarm_slot].Cn;
  // If there is no name yet, or if we have a pending update event..
  if (!_tcslen(name) || GPS_INFO.FLARM_Traffic[flarm_slot].UpdateNameFlag ) {

	#ifdef DEBUG_SIMLKT
	if (GPS_INFO.FLARM_Traffic[flarm_slot].UpdateNameFlag ) {
		StartupStore(_T("... UpdateNameFlag for slot %d\n"),flarm_slot);
	} else {
		StartupStore(_T("... First lookup name for slot %d\n"),flarm_slot);
	}
	#endif

	GPS_INFO.FLARM_Traffic[flarm_slot].UpdateNameFlag=false; // clear flag first
	TCHAR *fname = LookupFLARMDetails(GPS_INFO.FLARM_Traffic[flarm_slot].ID);
	if (fname) {
		LK_tcsncpy(name,fname,MAXFLARMNAME);

		//  Now we have the name, so lookup also for the Cn
		// This will return either real Cn or Name, again
		TCHAR *cname = LookupFLARMCn(GPS_INFO.FLARM_Traffic[flarm_slot].ID);
		if (cname) {
			int cnamelen=_tcslen(cname);
			if (cnamelen<=MAXFLARMCN) {
				_tcscpy( GPS_INFO.FLARM_Traffic[flarm_slot].Cn, cname);
			} else {
				// else probably it is the Name again, and we create a fake Cn
				GPS_INFO.FLARM_Traffic[flarm_slot].Cn[0]=cname[0];
				GPS_INFO.FLARM_Traffic[flarm_slot].Cn[1]=cname[cnamelen-2];
				GPS_INFO.FLARM_Traffic[flarm_slot].Cn[2]=cname[cnamelen-1];
				GPS_INFO.FLARM_Traffic[flarm_slot].Cn[3]=_T('\0');
			}
		} else {
			_tcscpy( GPS_INFO.FLARM_Traffic[flarm_slot].Cn, _T("Err"));
		}

		#ifdef DEBUG_SIMLKT
		StartupStore(_T("... PFLAA Name to FlarmSlot=%d ID=%lx Name=<%s> Cn=<%s>\n"),
			flarm_slot,
	  		GPS_INFO.FLARM_Traffic[flarm_slot].ID,
			GPS_INFO.FLARM_Traffic[flarm_slot].Name,
			GPS_INFO.FLARM_Traffic[flarm_slot].Cn);
		#endif
	} else {
		// Else we NEED to set a name, otherwise it will constantly search for it over and over..
		name[0]=_T('?');
		name[1]=_T('\0');
		GPS_INFO.FLARM_Traffic[flarm_slot].Cn[0]=_T('?');
		GPS_INFO.FLARM_Traffic[flarm_slot].Cn[1]=_T('\0');
		
		#ifdef DEBUG_SIMLKT
		StartupStore(_T("... New FlarmSlot=%d ID=%lx with no name, assigned a \"?\"\n"),
			flarm_slot,
	  		GPS_INFO.FLARM_Traffic[flarm_slot].ID);
		#endif
	}
  }

  //  update Virtual Waypoint for target FLARM
  if (flarm_slot == LKTargetIndex) {
	WayPointList[RESWP_FLARMTARGET].Latitude   = GPS_INFO.FLARM_Traffic[LKTargetIndex].Latitude;
	WayPointList[RESWP_FLARMTARGET].Longitude  = GPS_INFO.FLARM_Traffic[LKTargetIndex].Longitude;
	WayPointList[RESWP_FLARMTARGET].Altitude   = GPS_INFO.FLARM_Traffic[LKTargetIndex].Altitude;
  }

}
Пример #5
0
/**
 * Parses a PFLAA sentence
 * @param String Input string
 * @param params Parameter array
 * @param nparams Number of parameters
 * @param GPS_INFO GPS_INFO struct to parse into
 * @return Parsing success
 * @see http://flarm.com/support/manual/FLARM_DataportManual_v4.06E.pdf
 */
bool NMEAParser::PFLAA(const TCHAR *String,
                       const TCHAR **params, size_t nparams,
                       NMEA_INFO *GPS_INFO)
{
  int flarm_slot = 0;

  isFlarm = true;

  // 5 id, 6 digit hex
  long ID;
  _stscanf(params[5],TEXT("%lx"), &ID);
  //  unsigned long uID = ID;

  flarm_slot = FLARM_FindSlot(GPS_INFO, ID);
  if (flarm_slot<0) {
    // no more slots available,
    return false;
  }

  // set time of fix to current time
  GPS_INFO->FLARM_Traffic[flarm_slot].Time_Fix = GPS_INFO->Time;

  _stscanf(String,
	  TEXT("%hu,%lf,%lf,%lf,%hu,%lx,%lf,%lf,%lf,%lf,%hu"),
	  &GPS_INFO->FLARM_Traffic[flarm_slot].AlarmLevel, // unsigned short 0
	  &GPS_INFO->FLARM_Traffic[flarm_slot].RelativeNorth, // double?     1
	  &GPS_INFO->FLARM_Traffic[flarm_slot].RelativeEast, // double?      2
	  &GPS_INFO->FLARM_Traffic[flarm_slot].RelativeAltitude, // double   3
	  &GPS_INFO->FLARM_Traffic[flarm_slot].IDType, // unsigned short     4
	  &GPS_INFO->FLARM_Traffic[flarm_slot].ID, // 6 char hex
	  &GPS_INFO->FLARM_Traffic[flarm_slot].TrackBearing, // double       6
	  &GPS_INFO->FLARM_Traffic[flarm_slot].TurnRate, // double           7
	  &GPS_INFO->FLARM_Traffic[flarm_slot].Speed, // double              8
	  &GPS_INFO->FLARM_Traffic[flarm_slot].ClimbRate, // double          9
	  &GPS_INFO->FLARM_Traffic[flarm_slot].Type); // unsigned short     10

  // 1 relativenorth, meters
  GPS_INFO->FLARM_Traffic[flarm_slot].Location.Latitude =
    GPS_INFO->FLARM_Traffic[flarm_slot].RelativeNorth
    *FLARM_NorthingToLatitude + GPS_INFO->Location.Latitude;

  // 2 relativeeast, meters
  GPS_INFO->FLARM_Traffic[flarm_slot].Location.Longitude =
    GPS_INFO->FLARM_Traffic[flarm_slot].RelativeEast
    *FLARM_EastingToLongitude + GPS_INFO->Location.Longitude;

  // alt
  GPS_INFO->FLARM_Traffic[flarm_slot].Altitude =
    GPS_INFO->FLARM_Traffic[flarm_slot].RelativeAltitude +
    GPS_INFO->Altitude;

#ifdef FLARM_AVERAGE
  GPS_INFO->FLARM_Traffic[flarm_slot].Average30s =
    flarmCalculations.Average30s(
				 GPS_INFO->FLARM_Traffic[flarm_slot].ID,
				 GPS_INFO->Time,
				 GPS_INFO->FLARM_Traffic[flarm_slot].Altitude);
#endif

  // QUESTION TB: never returns true?!
  return false;
}