1 // tcas.hxx -- Traffic Alert and Collision Avoidance System (TCAS) 2 // 3 // Written by Thorsten Brehm, started December 2010. 4 // 5 // Copyright (C) 2010 Thorsten Brehm - brehmt (at) gmail com 6 // 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. 11 // 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. 16 // 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 20 21 #ifndef __INSTRUMENTS_TCAS_HXX 22 #define __INSTRUMENTS_TCAS_HXX 23 24 #include <assert.h> 25 26 #include <vector> 27 #include <deque> 28 #include <map> 29 30 #include <simgear/props/props.hxx> 31 #include <simgear/structure/subsystem_mgr.hxx> 32 #include <Sound/voiceplayer.hxx> 33 34 using std::vector; 35 using std::deque; 36 using std::map; 37 38 class SGSampleGroup; 39 40 #include <Main/globals.hxx> 41 42 #ifdef _MSC_VER 43 # pragma warning( push ) 44 # pragma warning( disable: 4355 ) 45 #endif 46 47 /////////////////////////////////////////////////////////////////////////////// 48 // TCAS ////////////////////////////////////////////////////////////////////// 49 /////////////////////////////////////////////////////////////////////////////// 50 51 class TCAS : public SGSubsystem 52 { 53 typedef enum 54 { 55 AdvisoryClear = 0, /*< Clear of traffic */ 56 AdvisoryIntrusion = 1, /*< Intrusion flag */ 57 AdvisoryClimb = AdvisoryIntrusion|(1 << 1), /*< RA climb */ 58 AdvisoryDescend = AdvisoryIntrusion|(1 << 2), /*< RA descend */ 59 AdvisoryAdjustVSpeed = AdvisoryIntrusion|(1 << 3), /*< RA adjust vertical speed (TCAS II 7.0 only) */ 60 AdvisoryMaintVSpeed = AdvisoryIntrusion|(1 << 4), /*< RA maintain vertical speed */ 61 AdvisoryMonitorVSpeed = AdvisoryIntrusion|(1 << 5), /*< RA monitor vertical speed */ 62 AdvisoryLevelOff = AdvisoryIntrusion|(1 << 6) /*< RA level off (TCAS II 7.1 only) */ 63 } EnumAdvisory; 64 65 typedef enum 66 { 67 OptionNone = 0, /*< no option modifier */ 68 OptionIncreaseClimb = (1 << 0), /*< increase climb */ 69 OptionIncreaseDescend = (1 << 1), /*< increase descend */ 70 OptionCrossingClimb = (1 << 2), /*< crossing climb */ 71 OptionCrossingDescent = (1 << 3) /*< crossing descent */ 72 } EnumAdvisoryOption; 73 74 typedef enum 75 { 76 SwitchOff = 0, /*< TCAS switched off */ 77 SwitchStandby = 1, /*< TCAS standby (no TA/RA) */ 78 SwitchTaOnly = 2, /*< TCAS in TA-only mode (no RA) */ 79 SwitchAuto = 3 /*< TCAS in TA/RA mode */ 80 } EnumModeSwitch; 81 82 typedef enum 83 { 84 ThreatInvisible = -1,/*< Traffic is invisible to TCAS (i.e. no transponder) */ 85 ThreatNone = 0, /*< Traffic is visible but no threat. */ 86 ThreatProximity = 1, /*< Proximity intruder traffic (no threat). */ 87 ThreatTA = 2, /*< TA-level threat traffic. */ 88 ThreatRA = 3 /*< RA-level threat traffic. */ 89 } EnumThreatLevel; 90 91 typedef struct 92 { 93 int threatLevel; /*< intruder threat level: 0=clear, 1=proximity, 94 2=intruder, 3=proximity intruder */ 95 int RA; /*< resolution advisory */ 96 int RAOption; /*< option flags for advisory */ 97 } ResolutionAdvisory; 98 99 typedef struct 100 { 101 float Tau; /*< vertical/horizontal protection range in seconds */ 102 float DMOD; /*< horizontal protection range in nm */ 103 float ALIM; /*< vertical protection range in ft */ 104 } Thresholds; 105 106 typedef struct 107 { 108 double maxAltitude; /*< max altitude for this sensitivity level */ 109 int sl; /*< sensitivity level */ 110 Thresholds TA; /*< thresholds for TA-level threats */ 111 Thresholds RA; /*< thresholds for RA-level threats */ 112 } SensitivityLevel; 113 114 typedef struct 115 { 116 std::string callsign; 117 bool verticalTA; 118 bool verticalRA; 119 bool horizontalTA; 120 bool horizontalRA; 121 bool isTracked; 122 float horizontalTau; 123 float verticalTau; 124 float relativeAltitudeFt; 125 float verticalFps; 126 int RASense; 127 } ThreatInfo; 128 129 typedef struct 130 { 131 int threatLevel; 132 double TAtimestamp; 133 double RAtimestamp; 134 } TrackerTarget; 135 136 typedef map<std::string,TrackerTarget*> TrackerTargets; 137 138 typedef struct 139 { 140 double lat; 141 double lon; 142 float pressureAltFt; 143 float radarAltFt; 144 float heading; 145 float velocityKt; 146 float verticalFps; 147 } LocalInfo; /*< info structure for local aircraft */ 148 149 ///////////////////////////////////////////////////////////////////////////// 150 // TCAS::PropertiesHandler /////////////////////////////////////////////// 151 ///////////////////////////////////////////////////////////////////////////// 152 153 class PropertiesHandler : public FGVoicePlayer::PropertiesHandler 154 { 155 public: PropertiesHandler(TCAS *)156 PropertiesHandler (TCAS *) : 157 FGVoicePlayer::PropertiesHandler() {} 158 PropertiesHandler(void)159 PropertiesHandler (void) : FGVoicePlayer::PropertiesHandler() {} 160 }; 161 162 ///////////////////////////////////////////////////////////////////////////// 163 // TCAS::VoicePlayer //////////////////////////////////////////////////////// 164 ///////////////////////////////////////////////////////////////////////////// 165 166 class VoicePlayer : 167 public FGVoicePlayer 168 { 169 public: VoicePlayer(TCAS * tcas)170 VoicePlayer (TCAS* tcas) : 171 FGVoicePlayer(&tcas->properties_handler, "tcas") {} 172 ~VoicePlayer(void)173 ~VoicePlayer (void) {} 174 175 void init (void); 176 177 struct 178 { 179 Voice* pTrafficTraffic; 180 Voice* pClimb; 181 Voice* pClimbNow; 182 Voice* pClimbCrossing; 183 Voice* pClimbIncrease; 184 Voice* pDescend; 185 Voice* pDescendNow; 186 Voice* pDescendCrossing; 187 Voice* pDescendIncrease; 188 Voice* pClear; 189 Voice* pAdjustVSpeed; 190 Voice* pMaintVSpeed; 191 Voice* pMonitorVSpeed; 192 Voice* pLevelOff; 193 Voice* pTestOk; 194 Voice* pTestFail; 195 } Voices; 196 private: 197 SGPropertyNode_ptr nodeSoundFilePrefix; 198 }; 199 200 ///////////////////////////////////////////////////////////////////////////// 201 // TCAS::Annunciator //////////////////////////////////////////////////////// 202 ///////////////////////////////////////////////////////////////////////////// 203 204 class Annunciator 205 { 206 public: 207 Annunciator (TCAS* tcas); ~Annunciator(void)208 ~Annunciator (void) {} 209 void bind (SGPropertyNode* node); 210 void init (void); 211 void update (void); 212 213 void trigger (const ResolutionAdvisory& newAdvisory, bool revertedRA); 214 void test (bool testOk); 215 void clear (void); isPlaying(void)216 bool isPlaying (void) { return voicePlayer.is_playing();} 217 218 private: 219 TCAS* tcas; 220 ResolutionAdvisory previous; 221 FGVoicePlayer::Voice* pLastVoice; 222 VoicePlayer voicePlayer; 223 SGPropertyNode_ptr nodeGpwsAlertOn; 224 }; 225 226 ///////////////////////////////////////////////////////////////////////////// 227 // TCAS::AdvisoryCoordinator //////////////////////////////////////////////// 228 ///////////////////////////////////////////////////////////////////////////// 229 230 class AdvisoryCoordinator 231 { 232 public: 233 AdvisoryCoordinator (TCAS* _tcas); ~AdvisoryCoordinator(void)234 ~AdvisoryCoordinator (void) {} 235 236 void bind (SGPropertyNode* node); 237 void init (void); 238 void reinit (void); 239 void update (int mode); 240 241 void clear (void); 242 void add (const ResolutionAdvisory& newAdvisory); 243 244 private: 245 TCAS* tcas; 246 double lastTATime; 247 ResolutionAdvisory current; 248 ResolutionAdvisory previous; 249 SGPropertyNode_ptr nodeTAWarning; 250 }; 251 252 ///////////////////////////////////////////////////////////////////////////// 253 // TCAS::Tracker //////////////////////////////////////////////////////////// 254 ///////////////////////////////////////////////////////////////////////////// 255 256 class Tracker 257 { 258 public: 259 Tracker (TCAS* _tcas); ~Tracker(void)260 ~Tracker (void) {} 261 262 void update (void); 263 264 void add (const std::string callsign, int detectedLevel); active(void)265 bool active (void) { return haveTargets;} newTraffic(void)266 bool newTraffic (void) { return newTargets;} isTracked(std::string callsign)267 bool isTracked (std::string callsign) { if (!haveTargets) return false;else return _isTracked(callsign);} 268 bool _isTracked (std::string callsign); 269 int getThreatLevel (std::string callsign); 270 271 private: 272 double currentTime; 273 bool haveTargets; 274 bool newTargets; 275 TrackerTargets targets; 276 }; 277 278 ///////////////////////////////////////////////////////////////////////////// 279 // TCAS::AdvisoryGenerator ////////////////////////////////////////////////// 280 ///////////////////////////////////////////////////////////////////////////// 281 282 class AdvisoryGenerator 283 { 284 public: 285 AdvisoryGenerator (TCAS* _tcas); ~AdvisoryGenerator(void)286 ~AdvisoryGenerator (void) {} 287 288 void init (const LocalInfo* _pSelf, ThreatInfo* _pCurrentThreat); 289 290 void setAlarmThresholds (const SensitivityLevel* _pAlarmThresholds); 291 292 int resolution (int mode, int threatLevel, float distanceNm, 293 float altFt, float heading, float velocityKt); 294 295 private: 296 float verticalSeparation (float newVerticalFps); 297 void determineRAsense (int& RASense, bool& isCrossing); 298 299 private: 300 TCAS* tcas; 301 const LocalInfo* pSelf; /*< info structure for local aircraft */ 302 ThreatInfo* pCurrentThreat; /*< info structure on current intruder/threat */ 303 const SensitivityLevel* pAlarmThresholds; 304 }; 305 306 ///////////////////////////////////////////////////////////////////////////// 307 // TCAS::ThreatDetector ///////////////////////////////////////////////////// 308 ///////////////////////////////////////////////////////////////////////////// 309 310 class ThreatDetector 311 { 312 public: 313 ThreatDetector (TCAS* _tcas); ~ThreatDetector(void)314 ~ThreatDetector (void) {} 315 316 void init (void); 317 void update (void); 318 319 bool checkTransponder (const SGPropertyNode* pModel, float velocityKt); 320 int checkThreat (int mode, const SGPropertyNode* pModel); 321 void checkVerticalThreat (void); 322 void horizontalThreat (float bearing, float distanceNm, float heading, 323 float velocityKt); 324 setPressureAlt(float altFt)325 void setPressureAlt (float altFt) { self.pressureAltFt = altFt;} getPressureAlt(void)326 float getPressureAlt (void) { return self.pressureAltFt;} 327 setRadarAlt(float altFt)328 void setRadarAlt (float altFt) { self.radarAltFt = altFt;} getRadarAlt(void)329 float getRadarAlt (void) { return self.radarAltFt;} 330 getVelocityKt(void)331 float getVelocityKt (void) { return self.velocityKt;} getRASense(void)332 int getRASense (void) { return currentThreat.RASense;} 333 334 private: 335 void unitTest (void); 336 337 private: 338 static const SensitivityLevel sensitivityLevels[]; 339 340 TCAS* tcas; 341 #ifdef FEATURE_TCAS_DEBUG_THREAT_DETECTOR 342 int checkCount; 343 #endif // of FEATURE_TCAS_DEBUG_THREAT_DETECTOR 344 345 SGPropertyNode_ptr nodeLat; 346 SGPropertyNode_ptr nodeLon; 347 SGPropertyNode_ptr nodePressureAlt; 348 SGPropertyNode_ptr nodeRadarAlt; 349 SGPropertyNode_ptr nodeHeading; 350 SGPropertyNode_ptr nodeVelocity; 351 SGPropertyNode_ptr nodeVerticalFps; 352 353 LocalInfo self; /*< info structure for local aircraft */ 354 ThreatInfo currentThreat; /*< info structure on current intruder/threat */ 355 const SensitivityLevel* pAlarmThresholds; 356 }; 357 358 private: 359 std::string name; 360 int num; 361 double nextUpdateTime; 362 int selfTestStep; 363 364 SGPropertyNode_ptr nodeModeSwitch; 365 SGPropertyNode_ptr nodeServiceable; 366 SGPropertyNode_ptr nodeSelfTest; 367 SGPropertyNode_ptr nodeDebugTrigger; 368 SGPropertyNode_ptr nodeDebugRA; 369 SGPropertyNode_ptr nodeDebugThreat; 370 371 PropertiesHandler properties_handler; 372 ThreatDetector threatDetector; 373 Tracker tracker; 374 AdvisoryCoordinator advisoryCoordinator; 375 AdvisoryGenerator advisoryGenerator; 376 Annunciator annunciator; 377 378 private: 379 void selfTest (void); 380 381 public: 382 TCAS (SGPropertyNode* node); 383 384 // Subsystem API. 385 void bind() override; 386 void init() override; 387 void reinit() override; 388 void unbind() override; 389 void update(double dt) override; 390 391 // Subsystem identification. staticSubsystemClassId()392 static const char* staticSubsystemClassId() { return "tcas"; } 393 394 /* configuration options */ 395 int _verticalRange; 396 int _lateralRange; 397 int _proxVertRange; 398 int _proxLatRange; 399 int _incDesInhbAlt; 400 int _DesInhbAlt; 401 int _RAInhbAlt; 402 int _TAInhbAlt; 403 int _intruderInhbAlt; 404 bool _intruderInhbSelfAltToggle; 405 int _intruderInhbSelfAlt; 406 }; 407 408 #ifdef _MSC_VER 409 # pragma warning( pop ) 410 #endif 411 412 #endif // __INSTRUMENTS_TCAS_HXX 413