1
0
Fork 0

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."
This commit is contained in:
mfranz 2006-04-19 17:36:41 +00:00
parent 30adde04bf
commit b6cf140f98
4 changed files with 167 additions and 19 deletions

View file

@ -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<FGAIAircraft,bool>(*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)

View file

@ -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
};

View file

@ -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<SGPropertyNode_ptr> 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<SGPropertyNode_ptr> 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

View file

@ -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;