1 // tcas.hxx -- Traffic Alert and Collision Avoidance System (TCAS)
3 // Written by Thorsten Brehm, started December 2010.
5 // Copyright (C) 2010 Thorsten Brehm - brehmt (at) gmail com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #ifndef __INSTRUMENTS_TCAS_HXX
22 #define __INSTRUMENTS_TCAS_HXX
30 #include <simgear/props/props.hxx>
31 #include <simgear/sound/sample_openal.hxx>
32 #include <simgear/structure/subsystem_mgr.hxx>
33 #include "mk_viii.hxx" // FGVoicePlayer only
41 #include <Main/globals.hxx>
44 # pragma warning( push )
45 # pragma warning( disable: 4355 )
48 ///////////////////////////////////////////////////////////////////////////////
49 // TCAS //////////////////////////////////////////////////////////////////////
50 ///////////////////////////////////////////////////////////////////////////////
52 class TCAS : public SGSubsystem
57 AdvisoryClear = 0, /*< Clear of traffic */
58 AdvisoryIntrusion = 1, /*< Intrusion flag */
59 AdvisoryClimb = AdvisoryIntrusion|(1 << 1), /*< RA climb */
60 AdvisoryDescend = AdvisoryIntrusion|(1 << 2), /*< RA descend */
61 AdvisoryAdjustVSpeed = AdvisoryIntrusion|(1 << 3), /*< RA adjust vertical speed (TCAS II 7.0 only) */
62 AdvisoryMaintVSpeed = AdvisoryIntrusion|(1 << 4), /*< RA maintain vertical speed */
63 AdvisoryMonitorVSpeed = AdvisoryIntrusion|(1 << 5), /*< RA monitor vertical speed */
64 AdvisoryLevelOff = AdvisoryIntrusion|(1 << 6) /*< RA level off (TCAS II 7.1 only) */
69 OptionNone = 0, /*< no option modifier */
70 OptionIncreaseClimb = (1 << 0), /*< increase climb */
71 OptionIncreaseDescend = (1 << 1), /*< increase descend */
72 OptionCrossingClimb = (1 << 2), /*< crossing climb */
73 OptionCrossingDescent = (1 << 3) /*< crossing descent */
78 SwitchOff = 0, /*< TCAS switched off */
79 SwitchStandby = 1, /*< TCAS standby (no TA/RA) */
80 SwitchTaOnly = 2, /*< TCAS in TA-only mode (no RA) */
81 SwitchAuto = 3 /*< TCAS in TA/RA mode */
86 ThreatInvisible = -1,/*< Traffic is invisible to TCAS (i.e. no transponder) */
87 ThreatNone = 0, /*< Traffic is visible but no threat. */
88 ThreatProximity = 1, /*< Proximity intruder traffic (no threat). */
89 ThreatTA = 2, /*< TA-level threat traffic. */
90 ThreatRA = 3 /*< RA-level threat traffic. */
95 int threatLevel; /*< intruder threat level: 0=clear, 1=proximity,
96 2=intruder, 3=proximity intruder */
97 int RA; /*< resolution advisory */
98 int RAOption; /*< option flags for advisory */
103 float Tau; /*< vertical/horizontal protection range in seconds */
104 float DMOD; /*< horizontal protection range in nm */
105 float ALIM; /*< vertical protection range in ft */
110 double maxAltitude; /*< max altitude for this sensitivity level */
111 int sl; /*< sensitivity level */
112 Thresholds TA; /*< thresholds for TA-level threats */
113 Thresholds RA; /*< thresholds for RA-level threats */
126 float relativeAltitudeFt;
138 typedef map<string,TrackerTarget*> TrackerTargets;
148 } LocalInfo; /*< info structure for local aircraft */
150 // /////////////////////////////////////////////////////////////////////////////
151 // // TCAS::Timer //////////////////////////////////////////////////////////////
152 // /////////////////////////////////////////////////////////////////////////////
156 // double start_time;
162 // : running(false) {}
164 // inline void start () { running = true; start_time = globals->get_sim_time_sec(); }
165 // inline void stop () { running = false; }
166 // inline double elapsed () const { assert(running); return globals->get_sim_time_sec() - start_time; }
167 // inline double start_or_elapsed ()
179 /////////////////////////////////////////////////////////////////////////////
180 // TCAS::PropertiesHandler ///////////////////////////////////////////////
181 /////////////////////////////////////////////////////////////////////////////
183 class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
188 PropertiesHandler (TCAS *device) :
189 FGVoicePlayer::PropertiesHandler(), tcas(device) {}
191 PropertiesHandler (void) : FGVoicePlayer::PropertiesHandler() {}
194 /////////////////////////////////////////////////////////////////////////////
195 // TCAS::VoicePlayer ////////////////////////////////////////////////////////
196 /////////////////////////////////////////////////////////////////////////////
202 VoicePlayer (TCAS* tcas) :
203 FGVoicePlayer(&tcas->properties_handler, "tcas") {}
205 ~VoicePlayer (void) {}
211 Voice* pTrafficTraffic;
214 Voice* pClimbCrossing;
215 Voice* pClimbIncrease;
218 Voice* pDescendCrossing;
219 Voice* pDescendIncrease;
221 Voice* pAdjustVSpeed;
223 Voice* pMonitorVSpeed;
229 SGPropertyNode_ptr nodeSoundFilePrefix;
232 /////////////////////////////////////////////////////////////////////////////
233 // TCAS::Annunciator ////////////////////////////////////////////////////////
234 /////////////////////////////////////////////////////////////////////////////
239 Annunciator (TCAS* tcas);
240 ~Annunciator (void) {}
241 void bind (SGPropertyNode* node);
245 void trigger (const ResolutionAdvisory& newAdvisory, bool revertedRA);
246 void test (bool testOk);
248 bool isPlaying (void) { return voicePlayer.is_playing();}
252 ResolutionAdvisory previous;
253 FGVoicePlayer::Voice* pLastVoice;
254 VoicePlayer voicePlayer;
255 SGPropertyNode_ptr nodeGpwsAlertOn;
258 /////////////////////////////////////////////////////////////////////////////
259 // TCAS::AdvisoryCoordinator ////////////////////////////////////////////////
260 /////////////////////////////////////////////////////////////////////////////
262 class AdvisoryCoordinator
265 AdvisoryCoordinator (TCAS* _tcas);
266 ~AdvisoryCoordinator (void) {}
268 void bind (SGPropertyNode* node);
270 void update (int mode);
273 void add (const ResolutionAdvisory& newAdvisory);
278 ResolutionAdvisory current;
279 ResolutionAdvisory previous;
280 SGPropertyNode_ptr nodeTAWarning;
283 /////////////////////////////////////////////////////////////////////////////
284 // TCAS::Tracker ////////////////////////////////////////////////////////////
285 /////////////////////////////////////////////////////////////////////////////
290 Tracker (TCAS* _tcas);
295 void add (const string callsign, int detectedLevel);
296 bool active (void) { return haveTargets;}
297 bool newTraffic (void) { return newTargets;}
298 bool isTracked (string callsign) { if (!haveTargets) return false;else return _isTracked(callsign);}
299 bool _isTracked (string callsign);
300 int getThreatLevel (string callsign);
307 TrackerTargets targets;
310 /////////////////////////////////////////////////////////////////////////////
311 // TCAS::AdvisoryGenerator //////////////////////////////////////////////////
312 /////////////////////////////////////////////////////////////////////////////
314 class AdvisoryGenerator
317 AdvisoryGenerator (TCAS* _tcas);
318 ~AdvisoryGenerator (void) {}
320 void init (const LocalInfo* _pSelf, ThreatInfo* _pCurrentThreat);
322 void setAlarmThresholds (const SensitivityLevel* _pAlarmThresholds);
324 int resolution (int mode, int threatLevel, float distanceNm,
325 float altFt, float heading, float velocityKt);
328 float verticalSeparation (float newVerticalFps);
329 void determineRAsense (int& RASense, bool& isCrossing);
333 const LocalInfo* pSelf; /*< info structure for local aircraft */
334 ThreatInfo* pCurrentThreat; /*< info structure on current intruder/threat */
335 const SensitivityLevel* pAlarmThresholds;
338 /////////////////////////////////////////////////////////////////////////////
339 // TCAS::ThreatDetector /////////////////////////////////////////////////////
340 /////////////////////////////////////////////////////////////////////////////
345 ThreatDetector (TCAS* _tcas);
346 ~ThreatDetector (void) {}
351 bool checkTransponder (const SGPropertyNode* pModel, float velocityKt);
352 int checkThreat (int mode, const SGPropertyNode* pModel);
353 void checkVerticalThreat (void);
354 void horizontalThreat (float bearing, float distanceNm, float heading,
357 void setAlt (float altFt) { self.altFt = altFt;}
358 float getAlt (void) { return self.altFt;}
359 float getVelocityKt (void) { return self.velocityKt;}
360 int getRASense (void) { return currentThreat.RASense;}
363 void unitTest (void);
366 static const SensitivityLevel sensitivityLevels[];
371 SGPropertyNode_ptr nodeLat;
372 SGPropertyNode_ptr nodeLon;
373 SGPropertyNode_ptr nodeAlt;
374 SGPropertyNode_ptr nodeHeading;
375 SGPropertyNode_ptr nodeVelocity;
376 SGPropertyNode_ptr nodeVerticalFps;
378 LocalInfo self; /*< info structure for local aircraft */
379 ThreatInfo currentThreat; /*< info structure on current intruder/threat */
380 const SensitivityLevel* pAlarmThresholds;
386 double nextUpdateTime;
389 SGPropertyNode_ptr nodeModeSwitch;
390 SGPropertyNode_ptr nodeServiceable;
391 SGPropertyNode_ptr nodeSelfTest;
392 SGPropertyNode_ptr nodeDebugTrigger;
393 SGPropertyNode_ptr nodeDebugRA;
394 SGPropertyNode_ptr nodeDebugThreat;
396 PropertiesHandler properties_handler;
397 ThreatDetector threatDetector;
399 AdvisoryCoordinator advisoryCoordinator;
400 AdvisoryGenerator advisoryGenerator;
401 Annunciator annunciator;
404 void selfTest (void);
407 TCAS (SGPropertyNode* node);
409 virtual void bind (void);
410 virtual void unbind (void);
411 virtual void init (void);
412 virtual void update (double dt);
416 # pragma warning( pop )
419 #endif // __INSTRUMENTS_TCAS_HXX