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:
parent
30adde04bf
commit
b6cf140f98
4 changed files with 167 additions and 19 deletions
|
@ -96,6 +96,8 @@ void FGAIAircraft::readFromScenario(SGPropertyNode* scFileNode) {
|
||||||
setPerformance(scFileNode->getStringValue("class", "jet_transport"));
|
setPerformance(scFileNode->getStringValue("class", "jet_transport"));
|
||||||
setFlightPlan(scFileNode->getStringValue("flightplan"),
|
setFlightPlan(scFileNode->getStringValue("flightplan"),
|
||||||
scFileNode->getBoolValue("repeat", false));
|
scFileNode->getBoolValue("repeat", false));
|
||||||
|
setCallSign(scFileNode->getStringValue("callsign"));
|
||||||
|
setTACANChannelID(scFileNode->getStringValue("TACAN-channel-ID"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAIAircraft::init() {
|
bool FGAIAircraft::init() {
|
||||||
|
@ -109,6 +111,8 @@ void FGAIAircraft::bind() {
|
||||||
props->tie("controls/gear/gear-down",
|
props->tie("controls/gear/gear-down",
|
||||||
SGRawValueMethods<FGAIAircraft,bool>(*this,
|
SGRawValueMethods<FGAIAircraft,bool>(*this,
|
||||||
&FGAIAircraft::_getGearDown));
|
&FGAIAircraft::_getGearDown));
|
||||||
|
props->setStringValue("callsign", callsign.c_str());
|
||||||
|
props->setStringValue("navaids/tacan/channel-ID", TACAN_channel_id.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIAircraft::unbind() {
|
void FGAIAircraft::unbind() {
|
||||||
|
@ -971,7 +975,15 @@ void FGAIAircraft::getGroundElev(double dt) {
|
||||||
//cerr << "Target altitude : " << tgt_altitude << endl;
|
//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()
|
void FGAIAircraft::doGroundAltitude()
|
||||||
{
|
{
|
||||||
if (fabs(altitude - (tgt_altitude+groundOffset)) > 1000.0)
|
if (fabs(altitude - (tgt_altitude+groundOffset)) > 1000.0)
|
||||||
|
|
|
@ -73,6 +73,9 @@ public:
|
||||||
void ClimbTo(double altitude);
|
void ClimbTo(double altitude);
|
||||||
void TurnTo(double heading);
|
void TurnTo(double heading);
|
||||||
void ProcessFlightPlan( double dt, time_t now );
|
void ProcessFlightPlan( double dt, time_t now );
|
||||||
|
void setCallSign(const string& );
|
||||||
|
void setTACANChannelID(const string& );
|
||||||
|
|
||||||
void getGroundElev(double dt);
|
void getGroundElev(double dt);
|
||||||
void doGroundAltitude();
|
void doGroundAltitude();
|
||||||
void loadNextLeg ();
|
void loadNextLeg ();
|
||||||
|
@ -106,12 +109,15 @@ private:
|
||||||
|
|
||||||
string acType;
|
string acType;
|
||||||
string company;
|
string company;
|
||||||
|
|
||||||
int spinCounter;
|
int spinCounter;
|
||||||
double prevSpeed;
|
double prevSpeed;
|
||||||
double prev_dist_to_go;
|
double prev_dist_to_go;
|
||||||
|
|
||||||
bool _getGearDown() const;
|
bool _getGearDown() const;
|
||||||
bool reachedWaypoint;
|
bool reachedWaypoint;
|
||||||
|
string callsign; // The callsign of this tanker.
|
||||||
|
string TACAN_channel_id; // The TACAN channel of this tanker
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,8 @@ TACAN::init ()
|
||||||
_bearing_node = node->getChild("indicated-bearing-true-deg", 0, true);
|
_bearing_node = node->getChild("indicated-bearing-true-deg", 0, true);
|
||||||
SGPropertyNode *cnode = fgGetNode("/ai/models/carrier", num, true );
|
SGPropertyNode *cnode = fgGetNode("/ai/models/carrier", num, true );
|
||||||
_carrier_name_node = cnode->getChild("name", 0, 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
|
void
|
||||||
|
@ -133,10 +134,21 @@ TACAN::update (double delta_time_sec)
|
||||||
double az2 = 0;
|
double az2 = 0;
|
||||||
double bearing = 0;
|
double bearing = 0;
|
||||||
double distance = 0;
|
double distance = 0;
|
||||||
double carrier_az2= 0;
|
double carrier_az2 = 0;
|
||||||
double carrier_bearing = 0;
|
double carrier_bearing = 0;
|
||||||
double carrier_distance = 0;
|
double carrier_distance = 0;
|
||||||
|
double tanker_az2 = 0;
|
||||||
|
double tanker_bearing = 0;
|
||||||
|
double tanker_distance = 0;
|
||||||
double frequency_mhz = 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;
|
string _channel, _last_channel, _channel_1, _channel_2,_channel_3, _channel_4;
|
||||||
|
|
||||||
// If it's off, don't waste any time.
|
// If it's off, don't waste any time.
|
||||||
|
@ -204,6 +216,18 @@ TACAN::update (double delta_time_sec)
|
||||||
_carrier_lon,
|
_carrier_lon,
|
||||||
&carrier_bearing, &carrier_az2, &carrier_distance);
|
&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
|
//calculate the bearing and range of the station from the aircraft
|
||||||
geo_inverse_wgs_84(altitude_m,
|
geo_inverse_wgs_84(altitude_m,
|
||||||
|
@ -213,17 +237,63 @@ TACAN::update (double delta_time_sec)
|
||||||
_transmitter_lon,
|
_transmitter_lon,
|
||||||
&bearing, &az2, &distance);
|
&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
|
//select the nearer
|
||||||
if ( carrier_distance <= distance && _carrier_valid) {
|
if ( mobile_distance <= distance && mobile_valid) {
|
||||||
SG_LOG( SG_INSTR, SG_DEBUG, "carrier_distance_nm " << carrier_distance);
|
SG_LOG( SG_INSTR, SG_DEBUG, "mobile_distance_m " << mobile_distance);
|
||||||
SG_LOG( SG_INSTR, SG_DEBUG, "distance_nm " << distance);
|
SG_LOG( SG_INSTR, SG_DEBUG, "distance_m " << distance);
|
||||||
bearing = carrier_bearing;
|
bearing = mobile_bearing;
|
||||||
distance = carrier_distance;
|
distance = mobile_distance;
|
||||||
_transmitter_elevation_ft = _carrier_elevation_ft;
|
_transmitter_elevation_ft = mobile_elevation_ft;
|
||||||
_transmitter_range_nm = _carrier_range_nm;
|
_transmitter_range_nm = mobile_range_nm;
|
||||||
_transmitter_bias = _carrier_bias;
|
_transmitter_bias = mobile_bias;
|
||||||
_transmitter_name = _carrier_name;
|
_transmitter_name = mobile_name;
|
||||||
_name_node->setStringValue(_transmitter_name.c_str());
|
_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 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);
|
_in_range_node->setBoolValue(false);
|
||||||
_distance_node->setDoubleValue(0);
|
_distance_node->setDoubleValue(0);
|
||||||
_speed_node->setDoubleValue(0);
|
_speed_node->setDoubleValue(0);
|
||||||
|
@ -279,6 +349,7 @@ void
|
||||||
TACAN::search (double frequency_mhz, double longitude_rad,
|
TACAN::search (double frequency_mhz, double longitude_rad,
|
||||||
double latitude_rad, double altitude_m)
|
double latitude_rad, double altitude_m)
|
||||||
{
|
{
|
||||||
|
int number, i;
|
||||||
|
|
||||||
SG_LOG( SG_INSTR, SG_DEBUG, "tacan freq " << frequency_mhz );
|
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);
|
SGPropertyNode * branch = fgGetNode("ai/models", true);
|
||||||
vector<SGPropertyNode_ptr> carrier = branch->getChildren("carrier");
|
vector<SGPropertyNode_ptr> carrier = branch->getChildren("carrier");
|
||||||
|
|
||||||
int number = carrier.size();
|
number = carrier.size();
|
||||||
|
|
||||||
SG_LOG( SG_INSTR, SG_DEBUG, "carrier " << number );
|
SG_LOG( SG_INSTR, SG_DEBUG, "carrier " << number );
|
||||||
|
|
||||||
int i;
|
|
||||||
for ( i = 0; i < number; ++i ) {
|
for ( i = 0; i < number; ++i ) {
|
||||||
string str2 ( carrier[i]->getStringValue("name", ""));
|
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 );
|
SG_LOG( SG_INSTR, SG_DEBUG, "strings 1 " << str1 << " 2 " << str2 );
|
||||||
unsigned int loc1= str1.find( str2, 0 );
|
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 );
|
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
|
// try the TACAN/VORTAC list next
|
||||||
FGNavRecord *tacan
|
FGNavRecord *tacan
|
||||||
|
|
|
@ -73,13 +73,16 @@ private:
|
||||||
SGPropertyNode_ptr _carrier_name_node;
|
SGPropertyNode_ptr _carrier_name_node;
|
||||||
SGPropertyNode_ptr _channel_node;
|
SGPropertyNode_ptr _channel_node;
|
||||||
|
|
||||||
|
SGPropertyNode_ptr _tanker_callsign_node;
|
||||||
|
|
||||||
double _last_distance_nm;
|
double _last_distance_nm;
|
||||||
double _last_frequency_mhz;
|
double _last_frequency_mhz;
|
||||||
double _time_before_search_sec;
|
double _time_before_search_sec;
|
||||||
|
|
||||||
bool _carrier_valid;
|
bool _carrier_valid;
|
||||||
|
bool _tanker_valid;
|
||||||
bool _transmitter_valid;
|
bool _transmitter_valid;
|
||||||
|
|
||||||
Point3D _transmitter;
|
Point3D _transmitter;
|
||||||
double _transmitter_lat, _transmitter_lon;
|
double _transmitter_lat, _transmitter_lon;
|
||||||
double _transmitter_elevation_ft;
|
double _transmitter_elevation_ft;
|
||||||
|
@ -87,7 +90,7 @@ private:
|
||||||
double _transmitter_bearing_deg;
|
double _transmitter_bearing_deg;
|
||||||
double _transmitter_bias;
|
double _transmitter_bias;
|
||||||
string _transmitter_name;
|
string _transmitter_name;
|
||||||
|
|
||||||
double _carrier_lat, _carrier_lon;
|
double _carrier_lat, _carrier_lon;
|
||||||
double _carrier_elevation_ft;
|
double _carrier_elevation_ft;
|
||||||
double _carrier_range_nm;
|
double _carrier_range_nm;
|
||||||
|
@ -95,6 +98,13 @@ private:
|
||||||
double _carrier_bias;
|
double _carrier_bias;
|
||||||
string _carrier_name;
|
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;
|
string name;
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue