156 double ClosestDistanceM2 = 99e9;
157 double ClosestLond=0.0, ClosestLatd=0.0;
158 int ClosestRelVerticalM=0;
159 int ClosestThreatLevel=-1;
162 double latd =
mFdm.get_Latitude() * SGD_RADIANS_TO_DEGREES;
163 double lond =
mFdm.get_Longitude() * SGD_RADIANS_TO_DEGREES;
168 double altitude_ft =
mFdm.get_Altitude();
171 SGPropertyNode* pAi =
fgGetNode(
"/ai/models",
true);
172 simgear::PropertyList aircraftList = pAi->getChildren(
"aircraft");
173 for (simgear::PropertyList::iterator
i = aircraftList.begin();
i != aircraftList.end(); ++
i)
175 SGPropertyNode* pModel = *
i;
176 if ((pModel)&&(pModel->nChildren()))
178 double GroundSpeedKt = pModel->getDoubleValue(
"velocities/true-airspeed-kt", 0.0);
179 int threatLevel = pModel->getIntValue(
"tcas/threat-level", -99);
181 if (threatLevel == -99)
184 threatLevel = (GroundSpeedKt>1) ? 0 : -1;
188 if (threatLevel >= 0)
191 double targetLatd = pModel->getDoubleValue(
"position/latitude-deg", 0.0);
192 double targetLond = pModel->getDoubleValue(
"position/longitude-deg", 0.0);
196 double RelNorthAngleDeg = targetLatd - latd;
197 double RelNorth = ((2*SG_PI*SG_POLAR_RADIUS_M) / 360.0) * RelNorthAngleDeg;
199 double RelEastAngleDeg = targetLond - lond;
200 double RelEast = ((2*SG_PI*SG_EQUATORIAL_RADIUS_M) / 360.0) *
201 abs(cos(latd*SGD_DEGREES_TO_RADIANS)) * RelEastAngleDeg;
203#ifdef FLARM_DEBUGGING
205 double distanceM = sqrt(RelNorth*RelNorth+RelEast*RelEast);
206 pModel->setDoubleValue(
"flarm/distance", distanceM);
207 pModel->setIntValue(
"flarm/alive", pModel->getIntValue(
"flarm/alive",0)+1);
212 double FlarmRangeM =
mFlarmConfig->getIntValue(
"RANGE", 25500);
213 double DistanceM2 = RelNorth*RelNorth+RelEast*RelEast;
214 if (DistanceM2 < FlarmRangeM*FlarmRangeM)
219 double distanceM = sqrt(RelNorth*RelNorth+RelEast*RelEast);
220 printf(
"%3u: id %3u, %s, distance: %.1fkm, North: %.1f, East: %.1f, speed: %.1f kt\n",
222 pModel->getIntValue(
"id"),
223 pModel->getStringValue(
"callsign",
"<no name>"),
224 distanceM/1000.0, RelNorth/1e3, RelEast/1e3, GroundSpeedKt);
228 int RelVerticalM = (pModel->getDoubleValue(
"position/altitude-ft", 0.0)-altitude_ft)* SG_FEET_TO_METER;
229 int Track = pModel->getDoubleValue(
"orientation/true-heading-deg", 0.0);
230 int ClimbRateMs = pModel->getDoubleValue(
"velocities/vertical-speed-fps", 0.0) * (SG_FPS_TO_KT * SG_KT_TO_MPS);
233 unsigned int ID = pModel->getIntValue(
"id") & 0x00FFFFFF;
235 snprintf( nmea, 256,
"$PFLAA,%u,%i,%i,%i,2,%06X,%u,,%i,%i,%u",
236 threatLevel, (
int)RelNorth, (
int)RelEast, RelVerticalM, ID,
237 Track, (
int) (GroundSpeedKt*SG_KT_TO_MPS), ClimbRateMs, AcftType);
240 if (DistanceM2 < ClosestDistanceM2)
242 ClosestDistanceM2 = DistanceM2;
243 ClosestThreatLevel = threatLevel;
244 ClosestRelVerticalM = RelVerticalM;
245 ClosestLatd = targetLatd;
246 ClosestLond = targetLond;
257 if (ClosestThreatLevel < 0)
260 snprintf( nmea, 256,
"$PFLAU,%u,1,1,1,0,,0,,", TargetCount);
265 double az2, bearing, distanceM;
266 geo_inverse_wgs_84(latd, lond, ClosestLatd, ClosestLond, &bearing, &az2, &distanceM);
269 double heading =
mFdm.get_Psi_deg();
271 SG_NORMALIZE_RANGE(bearing, -180.0, 180.0);
275 if (ClosestThreatLevel >= 2)
278 if (ClosestThreatLevel == 1)
280 snprintf( nmea, 256,
"$PFLAU,%u,1,1,1,%u,%.0f,%u,%u,%u",
281 TargetCount, ClosestThreatLevel, bearing, AlertMode, ClosestRelVerticalM, (
unsigned int) distanceM);
294 if ( tokens[0] ==
"PFLAE" )
300 const std::string& request = tokens[1];
301 SG_LOG( SG_IO, SG_DEBUG,
" PFLAE request = " << request );
305 snprintf( nmea, 256,
"$PFLAE,A,0,0");
307 SG_LOG( SG_IO, SG_DEBUG,
" PFLAE reply= " << nmea );
311 if ( tokens[0] ==
"PFLAV" )
317 const std::string& request = tokens[1];
318 SG_LOG( SG_IO, SG_DEBUG,
" PFLAV version request = " << request );
322 snprintf( nmea, 256,
"$PFLAV,A,2.00,6.00,");
324 SG_LOG( SG_IO, SG_DEBUG,
" PFLAV reply= " << nmea );
328 if ( tokens[0] ==
"PFLAS" )
336 const std::string& request = tokens[1];
337 SG_LOG( SG_IO, SG_DEBUG,
" PFLAS status/debug request = " << request );
342 const char* FlrmDebugReply = (
343 "------------------------------------------\r\n"
344 "FlightGear " FLIGHTGEAR_VERSION
"\r\n"
345 "Revision " REVISION
"\r\n"
346 "------------------------------------------\r\n");
348 SG_LOG( SG_IO, SG_DEBUG,
" PFLAS reply = " << FlrmDebugReply );
352 if ( tokens[0] ==
"PFLAC" )
362 const std::string& request = tokens[1];
364 SG_LOG( SG_IO, SG_DEBUG,
" PFLAC config request = " << request );
367 const std::string& keyword = tokens[2];
368 SG_LOG( SG_IO, SG_DEBUG,
" PFLAC config request = " << keyword );
371 SGPropertyNode* configNode =
mFlarmConfig->getChild(keyword,0,
false);
380 snprintf( nmea, 256,
"$PFLAC,A,%s,%s",
381 keyword.c_str(), configNode->getStringValue().c_str());
393 if (keyword ==
"NMEAOUT")
396 int value = (int)
atof(tokens[3].c_str());
431 configNode->setStringValue(tokens[3]);
434 snprintf( nmea, 256,
"$PFLAC,A,%s,%s",
435 keyword.c_str(), configNode->getStringValue().c_str());
443 snprintf( nmea, 256,
"$PFLAC,A,ERROR");
452 SG_LOG( SG_IO, SG_DEBUG,
" Unsupported message = " << tokens[0] );