From b6cf140f988e2fc72a5143e32dff7d56a8af929a Mon Sep 17 00:00:00 2001 From: mfranz Date: Wed, 19 Apr 2006 17:36:41 +0000 Subject: [PATCH] Vivian MEAZZA: "Add Air to Air TACAN. With this facility TACAN equipped aircraft can measure the range and bearing of TACAN equipped AI Aircraft. ATM there is only one assigned - callsign ESSO1 on TACAN channel 039X, but this can be easily expanded to include other c/s channel # pairs - just ask me if you want more." --- src/AIModel/AIAircraft.cxx | 14 +++- src/AIModel/AIAircraft.hxx | 6 ++ src/Instrumentation/tacan.cxx | 150 ++++++++++++++++++++++++++++++---- src/Instrumentation/tacan.hxx | 16 +++- 4 files changed, 167 insertions(+), 19 deletions(-) diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 736786f62..a7ffc210d 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -96,6 +96,8 @@ void FGAIAircraft::readFromScenario(SGPropertyNode* scFileNode) { setPerformance(scFileNode->getStringValue("class", "jet_transport")); setFlightPlan(scFileNode->getStringValue("flightplan"), scFileNode->getBoolValue("repeat", false)); + setCallSign(scFileNode->getStringValue("callsign")); + setTACANChannelID(scFileNode->getStringValue("TACAN-channel-ID")); } bool FGAIAircraft::init() { @@ -109,6 +111,8 @@ void FGAIAircraft::bind() { props->tie("controls/gear/gear-down", SGRawValueMethods(*this, &FGAIAircraft::_getGearDown)); + props->setStringValue("callsign", callsign.c_str()); + props->setStringValue("navaids/tacan/channel-ID", TACAN_channel_id.c_str()); } void FGAIAircraft::unbind() { @@ -971,7 +975,15 @@ void FGAIAircraft::getGroundElev(double dt) { //cerr << "Target altitude : " << tgt_altitude << endl; } } - + +void FGAIAircraft::setCallSign(const string& s) { + callsign = s; +} + +void FGAIAircraft::setTACANChannelID(const string& id) { + TACAN_channel_id = id; +} + void FGAIAircraft::doGroundAltitude() { if (fabs(altitude - (tgt_altitude+groundOffset)) > 1000.0) diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index 7da23ab42..1fc46f1a3 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -73,6 +73,9 @@ public: void ClimbTo(double altitude); void TurnTo(double heading); void ProcessFlightPlan( double dt, time_t now ); + void setCallSign(const string& ); + void setTACANChannelID(const string& ); + void getGroundElev(double dt); void doGroundAltitude(); void loadNextLeg (); @@ -106,12 +109,15 @@ private: string acType; string company; + int spinCounter; double prevSpeed; double prev_dist_to_go; bool _getGearDown() const; bool reachedWaypoint; + string callsign; // The callsign of this tanker. + string TACAN_channel_id; // The TACAN channel of this tanker }; diff --git a/src/Instrumentation/tacan.cxx b/src/Instrumentation/tacan.cxx index 4a6818cc7..a6a607793 100755 --- a/src/Instrumentation/tacan.cxx +++ b/src/Instrumentation/tacan.cxx @@ -124,7 +124,8 @@ TACAN::init () _bearing_node = node->getChild("indicated-bearing-true-deg", 0, true); SGPropertyNode *cnode = fgGetNode("/ai/models/carrier", num, true ); _carrier_name_node = cnode->getChild("name", 0, true); - + SGPropertyNode *tnode = fgGetNode("/ai/models/aircraft", num, true ); + _tanker_callsign_node = tnode->getChild("callsign", 0, true); } void @@ -133,10 +134,21 @@ TACAN::update (double delta_time_sec) double az2 = 0; double bearing = 0; double distance = 0; - double carrier_az2= 0; + double carrier_az2 = 0; double carrier_bearing = 0; double carrier_distance = 0; + double tanker_az2 = 0; + double tanker_bearing = 0; + double tanker_distance = 0; double frequency_mhz = 0; + double mobile_bearing = 0; + double mobile_distance = 0; + double mobile_elevation_ft = 0; + double mobile_range_nm = 0; + double mobile_bias = 0; + string mobile_name = ""; + bool mobile_valid = false; + string _channel, _last_channel, _channel_1, _channel_2,_channel_3, _channel_4; // If it's off, don't waste any time. @@ -204,6 +216,18 @@ TACAN::update (double delta_time_sec) _carrier_lon, &carrier_bearing, &carrier_az2, &carrier_distance); + //calculate the bearing and range of the tanker from the aircraft + SG_LOG( SG_INSTR, SG_DEBUG, "tanker_lat " << _tanker_lat); + SG_LOG( SG_INSTR, SG_DEBUG, "tanker_lon " << _tanker_lon); + SG_LOG( SG_INSTR, SG_DEBUG, "tanker_name " << _tanker_name); + SG_LOG( SG_INSTR, SG_DEBUG, "tanker_valid " << _tanker_valid); + geo_inverse_wgs_84(altitude_m, + latitude_deg, + longitude_deg, + _tanker_lat, + _tanker_lon, + &tanker_bearing, &tanker_az2, &tanker_distance); + //calculate the bearing and range of the station from the aircraft geo_inverse_wgs_84(altitude_m, @@ -213,17 +237,63 @@ TACAN::update (double delta_time_sec) _transmitter_lon, &bearing, &az2, &distance); + //select the nearest valid mobile transmitter + if ( _carrier_valid && _tanker_valid ){ + if( carrier_distance <= tanker_distance ){ + SG_LOG( SG_INSTR, SG_DEBUG, " select carrier (dist) " ); + mobile_bearing = carrier_bearing; + mobile_distance = carrier_distance; + mobile_elevation_ft = _carrier_elevation_ft; + mobile_range_nm = _carrier_range_nm; + mobile_bias = _carrier_bias; + mobile_name = _carrier_name; + }else{ + SG_LOG( SG_INSTR, SG_DEBUG, " select tanker (dist) " ); + mobile_bearing = tanker_bearing; + mobile_distance = tanker_distance; + mobile_elevation_ft = _tanker_elevation_ft; + mobile_range_nm = _tanker_range_nm; + mobile_bias = _tanker_bias; + mobile_name = _tanker_name; + } + mobile_valid = true; + } + else if ( _carrier_valid && !_tanker_valid ){ + SG_LOG( SG_INSTR, SG_DEBUG, " select carrier " ); + mobile_bearing = carrier_bearing; + mobile_distance = carrier_distance; + mobile_elevation_ft = _carrier_elevation_ft; + mobile_range_nm = _carrier_range_nm; + mobile_bias = _carrier_bias; + mobile_name = _carrier_name; + mobile_valid = true; + } + else if ( !_carrier_valid && _tanker_valid ){ + SG_LOG( SG_INSTR, SG_DEBUG, " select tanker " ); + mobile_bearing = tanker_bearing; + mobile_distance = tanker_distance; + mobile_elevation_ft = _tanker_elevation_ft; + mobile_range_nm = _tanker_range_nm; + mobile_bias = _tanker_bias; + mobile_name = _tanker_name; + mobile_valid = true; + }else{ + mobile_valid = false; + } + + + //select the nearer - if ( carrier_distance <= distance && _carrier_valid) { - SG_LOG( SG_INSTR, SG_DEBUG, "carrier_distance_nm " << carrier_distance); - SG_LOG( SG_INSTR, SG_DEBUG, "distance_nm " << distance); - bearing = carrier_bearing; - distance = carrier_distance; - _transmitter_elevation_ft = _carrier_elevation_ft; - _transmitter_range_nm = _carrier_range_nm; - _transmitter_bias = _carrier_bias; - _transmitter_name = _carrier_name; + if ( mobile_distance <= distance && mobile_valid) { + SG_LOG( SG_INSTR, SG_DEBUG, "mobile_distance_m " << mobile_distance); + SG_LOG( SG_INSTR, SG_DEBUG, "distance_m " << distance); + bearing = mobile_bearing; + distance = mobile_distance; + _transmitter_elevation_ft = mobile_elevation_ft; + _transmitter_range_nm = mobile_range_nm; + _transmitter_bias = mobile_bias; + _transmitter_name = mobile_name; _name_node->setStringValue(_transmitter_name.c_str()); } @@ -263,7 +333,7 @@ TACAN::update (double delta_time_sec) } // If we can't find a valid station set everything to zero - if (!_transmitter_valid && !_carrier_valid) { + if (!_transmitter_valid && !mobile_valid ) { _in_range_node->setBoolValue(false); _distance_node->setDoubleValue(0); _speed_node->setDoubleValue(0); @@ -279,6 +349,7 @@ void TACAN::search (double frequency_mhz, double longitude_rad, double latitude_rad, double altitude_m) { + int number, i; SG_LOG( SG_INSTR, SG_DEBUG, "tacan freq " << frequency_mhz ); @@ -298,14 +369,13 @@ TACAN::search (double frequency_mhz, double longitude_rad, SGPropertyNode * branch = fgGetNode("ai/models", true); vector carrier = branch->getChildren("carrier"); - int number = carrier.size(); + number = carrier.size(); SG_LOG( SG_INSTR, SG_DEBUG, "carrier " << number ); - int i; for ( i = 0; i < number; ++i ) { string str2 ( carrier[i]->getStringValue("name", "")); - // SG_LOG( SG_INSTR, SG_DEBUG, "carrier name " << str2 ); + SG_LOG( SG_INSTR, SG_DEBUG, "carrier name " << str2 ); SG_LOG( SG_INSTR, SG_DEBUG, "strings 1 " << str1 << " 2 " << str2 ); unsigned int loc1= str1.find( str2, 0 ); @@ -334,6 +404,56 @@ TACAN::search (double frequency_mhz, double longitude_rad, SG_LOG( SG_INSTR, SG_DEBUG, " carrier transmitter invalid " << _carrier_valid ); } + //try any tankers second + FGNavRecord *tanker_tacan + = globals->get_carrierlist()->findStationByFreq( frequency_mhz ); + + _tanker_valid = (tanker_tacan != NULL); + + + if ( _tanker_valid ) { + SG_LOG( SG_INSTR, SG_DEBUG, "tanker transmitter valid start " << _tanker_valid ); + + string str3( tanker_tacan->get_name() ); + + SGPropertyNode * branch = fgGetNode("ai/models", true); + vector tanker = branch->getChildren("aircraft"); + + number = tanker.size(); + + SG_LOG( SG_INSTR, SG_DEBUG, "tanker number " << number ); + + for ( i = 0; i < number; ++i ) { + string str4 ( tanker[i]->getStringValue("callsign", "")); + SG_LOG( SG_INSTR, SG_DEBUG, "tanker callsign " << str4 ); + + SG_LOG( SG_INSTR, SG_DEBUG, "strings 3 " << str3 << " 4 " << str4 ); + unsigned int loc1= str3.find( str4, 0 ); + if ( loc1 != string::npos && str4 != "" ) { + SG_LOG( SG_INSTR, SG_DEBUG, " string found" ); + _tanker_lat = tanker[i]->getDoubleValue("position/latitude-deg"); + _tanker_lon = tanker[i]->getDoubleValue("position/longitude-deg"); + _tanker_elevation_ft = tanker[i]->getDoubleValue("position/altitude-ft"); + _tanker_range_nm = tanker_tacan->get_range(); + _tanker_bias = tanker_tacan->get_multiuse(); + _tanker_name = tanker_tacan->get_name(); + _tanker_valid = 1; + SG_LOG( SG_INSTR, SG_DEBUG, " tanker transmitter valid " << _tanker_valid ); + break; + } else { + _tanker_valid = 0; + SG_LOG( SG_INSTR, SG_DEBUG, " tanker transmitter invalid " << _tanker_valid ); + } + } + + SG_LOG( SG_INSTR, SG_DEBUG, "tanker name " << _tanker_name); + SG_LOG( SG_INSTR, SG_DEBUG, "lat " << _tanker_lat << "lon " << _tanker_lon); + SG_LOG( SG_INSTR, SG_DEBUG, "elev " << _tanker_elevation_ft); + SG_LOG( SG_INSTR, SG_DEBUG, "range " << _tanker_range_nm); + + } else { + SG_LOG( SG_INSTR, SG_DEBUG, " tanker transmitter invalid " << _tanker_valid ); + } // try the TACAN/VORTAC list next FGNavRecord *tacan diff --git a/src/Instrumentation/tacan.hxx b/src/Instrumentation/tacan.hxx index d6a649beb..85cd7aba1 100755 --- a/src/Instrumentation/tacan.hxx +++ b/src/Instrumentation/tacan.hxx @@ -73,13 +73,16 @@ private: SGPropertyNode_ptr _carrier_name_node; SGPropertyNode_ptr _channel_node; + SGPropertyNode_ptr _tanker_callsign_node; + double _last_distance_nm; double _last_frequency_mhz; double _time_before_search_sec; - + bool _carrier_valid; + bool _tanker_valid; bool _transmitter_valid; - + Point3D _transmitter; double _transmitter_lat, _transmitter_lon; double _transmitter_elevation_ft; @@ -87,7 +90,7 @@ private: double _transmitter_bearing_deg; double _transmitter_bias; string _transmitter_name; - + double _carrier_lat, _carrier_lon; double _carrier_elevation_ft; double _carrier_range_nm; @@ -95,6 +98,13 @@ private: double _carrier_bias; string _carrier_name; + double _tanker_lat, _tanker_lon; + double _tanker_elevation_ft; + double _tanker_range_nm; + double _tanker_bearing_deg; + double _tanker_bias; + string _tanker_name; + string name; int num;