From 8114d1d8998f48e61e2bd4a73d8223961ad4dc17 Mon Sep 17 00:00:00 2001 From: durk Date: Wed, 30 Dec 2009 14:11:16 +0000 Subject: [PATCH 1/4] Conditional compilation of ATCDCL module. Use --disable-atcdcl to try building flightgear without ATCDCL code. --- configure.ac | 19 ++++++++++++++++++- src/AIModel/AIAircraft.cxx | 9 --------- src/ATC/trafficcontrol.cxx | 8 ++++---- src/ATC/trafficcontrol.hxx | 1 - src/Airports/apt_loader.cxx | 23 +++++++++++++++++++---- src/Airports/groundnetwork.cxx | 7 +++++++ src/Main/Makefile.am | 9 ++++++++- src/Main/fg_init.cxx | 21 +++++++++++++++++---- src/Makefile.am | 9 ++++++++- 9 files changed, 81 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index 6ae6d7438..1c1fa9613 100644 --- a/configure.ac +++ b/configure.ac @@ -158,6 +158,17 @@ else fi AM_CONDITIONAL(ENABLE_SP_FDM, test "x$enable_sp_fdms" != "xno") +# Specify whether we want to compile ATCDCL. +# default to with_atcdcl=yes +AC_ARG_ENABLE(atcdcl, [ --enable-atcdcl Compile and link the depricated atc/ai module], [enable_atcdcl="$enableval"] ) +if test "x$enable_atcdcl" != "xno"; then + AC_DEFINE([ENABLE_ATCDCL], 1, [Define to include old ATC/AI module]) +else + AC_DEFINE([ENABLE_ATCDCL], 0, [Define to include old ATC/AI module]) +fi +AM_CONDITIONAL(ENABLE_ATCDCL, test "x$enable_atcdcl" != "xno") + + dnl EXPERIMENTAL generic event driven input device # defaults to no @@ -202,6 +213,7 @@ fi AC_CHECK_HEADER(pthread.h) AM_CONDITIONAL(WITH_THREADS, test "x$with_threads" = "xyes") + dnl Used by JSBSim to conditionally compile in fgfs interface code AC_DEFINE([FGFS], 1, [Define so that JSBSim compiles in 'library' mode]) @@ -283,7 +295,7 @@ AC_SEARCH_LIBS(clock_gettime, rt) base_LIBS="$LIBS" dnl Check for SDL or glut if enabled. -AC_ARG_ENABLE(osgviewer, [ --enable-osgviewer Configure to use osgViewer(default)], [enable_osgviewer="$enableval"]) +AC_ARG_ENABLE(osgviewer, [ --enable-osgviewer Configure to use osgViewer(default)], [enable_osgviewer="$enableval"]) AC_ARG_ENABLE(sdl, [ --enable-sdl Configure to use SDL], [enable_sdl="$enableval"]) AC_ARG_ENABLE(glut, [ --enable-glut Configure to use GLUT], [enable_glut="$enableval"]) AM_CONDITIONAL(USE_SDL, test "x$enable_sdl" = "xyes") @@ -880,3 +892,8 @@ else echo "Include special purpose flight models: no" fi +if test "x$enable_atcdcl" != "xno"; then + echo "Build depricated ATC/AI module: yes" +else + echo "Build depricated ATC/AI module: no" +fi diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 68d7f46c4..eb8469fde 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -447,15 +447,6 @@ void FGAIAircraft::announcePositionToController() { case 4: //Take off tower controller if (trafficRef->getDepartureAirport()->getDynamics()) { controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController(); - //if (trafficRef->getDepartureAirport()->getId() == "EHAM") { - //string trns = trafficRef->getCallSign() + " at runway " + fp->getRunway() + - // ". Ready for departure. " + trafficRef->getFlightType() + " to " + - // trafficRef->getArrivalAirport()->getId(); - //fgSetString("/sim/messages/atc", trns.c_str()); - // if (controller == 0) { - //cerr << "Error in assigning controller at " << trafficRef->getDepartureAirport()->getId() << endl; - //} - //} } else { cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl; } diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index 57f718812..a04b6fc81 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -264,7 +264,7 @@ bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other, if (other.intentions.size()) { for (intVecIterator j = other.intentions.begin(); j != other.intentions.end(); j++) - { + { // cerr << "Current segment 1 " << (*i) << endl; if ((*i) > 0) { if ((opp = net->findSegment(*i)->opposite())) @@ -402,7 +402,7 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m // Assign SID, if necessery (TODO) case MSG_PERMIT_ENGINE_START: taxiFreqStr = formatATCFrequency3_2(taxiFreq); - + heading = rec->getAircraft()->getTrafficRef()->getCourse(); fltType = rec->getAircraft()->getTrafficRef()->getFlightType(); rwyClass= rec->getAircraft()->GetFlightPlan()->getRunwayClassFromTrafficType(fltType); @@ -453,10 +453,8 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m // Display ATC message only when one of the radios is tuned // the relevant frequency. // Note that distance attenuation is currently not yet implemented - //cerr << "Transmitting " << text << " at " << stationFreq; if ((onBoardRadioFreqI0 == stationFreq) || (onBoardRadioFreqI1 == stationFreq)) { fgSetString("/sim/messages/atc", text.c_str()); - //cerr << "Printing Message: " << endl; } } @@ -466,6 +464,8 @@ string FGATCController::formatATCFrequency3_2(int freq) { return string(buffer); } +// TODO: Set transponder codes according to real-world routes. +// The current version just returns a random string of four octal numbers. string FGATCController::genTransponderCode(string fltRules) { if (fltRules == "VFR") { return string("1200"); diff --git a/src/ATC/trafficcontrol.hxx b/src/ATC/trafficcontrol.hxx index 7ca8e88bf..ef984efca 100644 --- a/src/ATC/trafficcontrol.hxx +++ b/src/ATC/trafficcontrol.hxx @@ -45,7 +45,6 @@ typedef vector::iterator intVecIterator; class FGAIFlightPlan; // forward reference class FGGroundNetwork; // forward reference -//class FGAISchedule; // forward reference class FGAIAircraft; // forward reference /************************************************************************************** diff --git a/src/Airports/apt_loader.cxx b/src/Airports/apt_loader.cxx index af9319ae3..3dfcdf059 100644 --- a/src/Airports/apt_loader.cxx +++ b/src/Airports/apt_loader.cxx @@ -45,7 +45,9 @@ #include "simple.hxx" #include "runways.hxx" #include "pavement.hxx" -#include +#if ENABLE_ATCDCL +# include +#endif #include @@ -75,7 +77,12 @@ public: last_apt_type("") {} + +#ifdef ENABLE_ATCDCL void parseAPT(const string &aptdb_file, FGCommList *comm_list) +#else + void parseAPT(const string &aptdb_file) +#endif { sg_gzifstream in( aptdb_file ); @@ -461,7 +468,7 @@ private: pvt->addNode(pos, num == 113); } } - +#if ENABLE_ATCDCL void parseATISLine(FGCommList *comm_list, const vector& token) { if ( rwy_count <= 0 ) { @@ -505,19 +512,27 @@ private: << " type: " << a.type ); #endif } +#endif }; + // Load the airport data base from the specified aptdb file. The // metar file is used to mark the airports as having metar available // or not. bool fgAirportDBLoad( const string &aptdb_file, +#if ENABLE_ATCDCL FGCommList *comm_list, const std::string &metar_file ) +#else + const std::string &metar_file ) +#endif { APTLoader ld; - +#if ENABLE_ATCDCL ld.parseAPT(aptdb_file, comm_list); - +#else + ld.parseAPT(aptdb_file); +#endif // // Load the metar.dat file and update apt db with stations that // have metar data. diff --git a/src/Airports/groundnetwork.cxx b/src/Airports/groundnetwork.cxx index 8bdd947fc..7600033ce 100644 --- a/src/Airports/groundnetwork.cxx +++ b/src/Airports/groundnetwork.cxx @@ -508,6 +508,13 @@ void FGGroundNetwork::signOff(int id) { void FGGroundNetwork::update(int id, double lat, double lon, double heading, double speed, double alt, double dt) { + // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to + // Transmit air-to-ground "Ready to taxi request: + // Transmit ground to air approval / hold + // Transmit confirmation ... + // Probably use a status mechanism similar to the Engine start procedure in the startup controller. + + TrafficVectorIterator i = activeTraffic.begin(); // Search search if the current id has an entry // This might be faster using a map instead of a vector, but let's start by taking a safe route diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 0994d859a..996c63e11 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -9,6 +9,13 @@ else SP_FDM_LIBS = endif +if ENABLE_ATCDCL +ATCDCL_LIBS = $(top_builddir)/src/ATCDCL/libATCDCL.a +else +ATCDCL_LIBS = +endif + + if WITH_THREADS THREAD_LIBS = -lsgthreads $(thread_LIBS) else @@ -82,7 +89,7 @@ fgfs_SOURCES = bootstrap.cxx fgfs_LDADD = \ libMain.a \ $(top_builddir)/src/Aircraft/libAircraft.a \ - $(top_builddir)/src/ATCDCL/libATCDCL.a \ + $(ATCDCL_LIBS) \ $(top_builddir)/src/Cockpit/libCockpit.a \ $(top_builddir)/src/Cockpit/built_in/libBuilt_in.a \ $(top_builddir)/src/FDM/libFlight.a \ diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 26a7987f4..ded6765fc 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -73,8 +73,13 @@ #include #include -#include -#include + +#if ENABLE_ATCDCL +# include +# include +# include "ATCDCL/commlist.hxx" +#endif + #include #include #include @@ -82,7 +87,8 @@ #include #include #include -#ifdef ENABLE_SP_FDM + +#if ENABLE_SP_FDM #include #include #include @@ -130,7 +136,7 @@ #include "renderer.hxx" #include "viewmgr.hxx" #include "main.hxx" -#include "ATCDCL/commlist.hxx" + #ifdef __APPLE__ # include @@ -973,9 +979,16 @@ fgInitNav () // Initialise the frequency search map BEFORE reading // the airport database: + + + +#if ENABLE_ATCDCL current_commlist = new FGCommList; current_commlist->init( globals->get_fg_root() ); fgAirportDBLoad( aptdb.str(), current_commlist, p_metar.str() ); +#else + fgAirportDBLoad( aptdb.str(), p_metar.str() ); +#endif FGNavList *navlist = new FGNavList; FGNavList *loclist = new FGNavList; diff --git a/src/Makefile.am b/src/Makefile.am index 178419eb0..39b081ac1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,16 @@ +if ENABLE_ATCDCL +ATCDCL_DIR = ATCDCL +else +ATCDCL_DIR = +endif + + SUBDIRS = \ Include \ Aircraft \ Airports \ ATC \ - ATCDCL \ + $(ATCDCL_DIR) \ Autopilot \ Cockpit \ Environment \ From d8ae90801acd1ea051d2f46dc434b649ea53ba2f Mon Sep 17 00:00:00 2001 From: durk Date: Tue, 5 Jan 2010 20:04:54 +0000 Subject: [PATCH 2/4] Some additional changes to ensure that FlightGear at least compiles after configuring with --disable-atcdcl. Some substitution code is added in ATC/atcutils.cxx and ATC/atcutils.hxx. Note that the new code doesn't run properly yet. Instead, it is just meant to identify which parts need replacement. Getting that to work will be the next step. --- src/ATC/Makefile.am | 1 + src/ATC/atcutils.cxx | 372 ++++++++++++++++++++++++++++ src/ATC/atcutils.hxx | 185 ++++++++++++++ src/Airports/apt_loader.cxx | 24 +- src/Airports/apt_loader.hxx | 2 +- src/Instrumentation/KLN89/kln89.cxx | 14 +- src/Main/fg_init.cxx | 11 +- 7 files changed, 586 insertions(+), 23 deletions(-) create mode 100644 src/ATC/atcutils.cxx create mode 100644 src/ATC/atcutils.hxx diff --git a/src/ATC/Makefile.am b/src/ATC/Makefile.am index 32e4ced92..35756c958 100644 --- a/src/ATC/Makefile.am +++ b/src/ATC/Makefile.am @@ -1,6 +1,7 @@ noinst_LIBRARIES = libATC.a libATC_a_SOURCES = \ + atcutils.cxx atcutils.hxx \ trafficcontrol.cxx trafficcontrol.hxx INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/ATC/atcutils.cxx b/src/ATC/atcutils.cxx new file mode 100644 index 000000000..12747c480 --- /dev/null +++ b/src/ATC/atcutils.cxx @@ -0,0 +1,372 @@ +// commlist.cxx -- comm frequency lookup class +// +// Written by David Luff and Alexander Kappes, started Jan 2003. +// Based on navlist.cxx by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + + + +#include +#include +#include +#include +#include +#include +#include + +#include "atcutils.hxx" + +#if !ENABLE_ATCDCL + + +FGCommList *current_commlist; + + +// Constructor +FGCommList::FGCommList( void ) { + sg_srandom_time(); +} + + +// Destructor +FGCommList::~FGCommList( void ) { +} + + +// load the navaids and build the map +bool FGCommList::init( const SGPath& path ) { +/* + SGPath temp = path; + commlist_freq.erase(commlist_freq.begin(), commlist_freq.end()); + commlist_bck.erase(commlist_bck.begin(), commlist_bck.end()); + temp.append( "ATC/default.atis" ); + LoadComms(temp); + temp = path; + temp.append( "ATC/default.tower" ); + LoadComms(temp); + temp = path; + temp.append( "ATC/default.ground" ); + LoadComms(temp); + temp = path; + temp.append( "ATC/default.approach" ); + LoadComms(temp); + return true;*/ +} + + +bool FGCommList::LoadComms(const SGPath& path) { +/* + sg_gzifstream fin( path.str() ); + if ( !fin.is_open() ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() ); + exit(-1); + } + + // read in each line of the file + fin >> skipcomment; + + while ( !fin.eof() ) { + ATCData a; + fin >> a; + if(a.type == INVALID) { + SG_LOG(SG_GENERAL, SG_DEBUG, "WARNING - INVALID type found in " << path.str() << '\n'); + } else { + // Push all stations onto frequency map + commlist_freq[a.freq].push_back(a); + + // Push non-atis stations onto bucket map as well + // In fact, push all stations onto bucket map for now so FGATCMgr::GetFrequency() works. + //if(a.type != ATIS and/or AWOS?) { + // get bucket number + SGBucket bucket(a.geod); + int bucknum = bucket.gen_index(); + commlist_bck[bucknum].push_back(a); + //} + } + + fin >> skipcomment; + } + + fin.close(); + return true; +*/ +} + + +// query the database for the specified frequency, lon and lat are in +// degrees, elev is in meters +// If no atc_type is specified, it returns true if any non-invalid type is found +// If atc_type is specifed, returns true only if the specified type is found +bool FGCommList::FindByFreq(const SGGeod& aPos, double freq, + ATCData* ad, atc_type tp ) +{ +/* + comm_list_type stations; + stations = commlist_freq[kHz10(freq)]; + comm_list_iterator current = stations.begin(); + comm_list_iterator last = stations.end(); + + // double az1, az2, s; + SGVec3d aircraft = SGVec3d::fromGeod(aPos); + const double orig_max_d = 1e100; + double max_d = orig_max_d; + double d; + // TODO - at the moment this loop returns the first match found in range + // We want to return the closest match in the event of a frequency conflict + for ( ; current != last ; ++current ) { + d = distSqr(aircraft, current->cart); + + //cout << " dist = " << sqrt(d) + // << " range = " << current->range * SG_NM_TO_METER << endl; + + // TODO - match up to twice the published range so we can model + // reduced signal strength + // NOTE The below is squared since we match to distance3Dsquared (above) to avoid a sqrt. + if ( d < (current->range * SG_NM_TO_METER + * current->range * SG_NM_TO_METER ) ) { + //cout << "matched = " << current->ident << endl; + if((tp == INVALID) || (tp == (*current).type)) { + if(d < max_d) { + max_d = d; + *ad = *current; + } + } + } + } + + if(max_d < orig_max_d) { + return true; + } else { + return false; + } +*/ +} + +int FGCommList::FindByPos(const SGGeod& aPos, double range, comm_list_type* stations, atc_type tp) +{ +/* + // number of relevant stations found within range + int found = 0; + stations->erase(stations->begin(), stations->end()); + + // get bucket number for plane position + SGBucket buck(aPos); + + // get neigboring buckets + int bx = (int)( range*SG_NM_TO_METER / buck.get_width_m() / 2) + 1; + int by = (int)( range*SG_NM_TO_METER / buck.get_height_m() / 2 ) + 1; + + // loop over bucket range + for ( int i=-bx; i<=bx; i++) { + for ( int j=-by; j<=by; j++) { + buck = sgBucketOffset(aPos.getLongitudeDeg(), aPos.getLatitudeDeg(), i, j); + long int bucket = buck.gen_index(); + comm_map_const_iterator Fstations = commlist_bck.find(bucket); + if (Fstations == commlist_bck.end()) continue; + comm_list_const_iterator current = Fstations->second.begin(); + comm_list_const_iterator last = Fstations->second.end(); + + + // double az1, az2, s; + SGVec3d aircraft = SGVec3d::fromGeod(aPos); + double d; + for(; current != last; ++current) { + if((current->type == tp) || (tp == INVALID)) { + d = distSqr(aircraft, current->cart); + // NOTE The below is squared since we match to distance3Dsquared (above) to avoid a sqrt. + if ( d < (current->range * SG_NM_TO_METER + * current->range * SG_NM_TO_METER ) ) { + stations->push_back(*current); + ++found; + } + } + } + } + } + return found; +*/ +} + + +// Returns the distance in meters to the closest station of a given type, +// with the details written into ATCData& ad. If no type is specifed simply +// returns the distance to the closest station of any type. +// Returns -9999 if no stations found within max_range in nautical miles (default 100 miles). +// Note that the search algorithm starts at 10 miles and multiplies by 10 thereafter, so if +// say 300 miles is specifed 10, then 100, then 1000 will be searched, breaking at first result +// and giving up after 1000. +double FGCommList::FindClosest(const SGGeod& aPos, ATCData& ad, atc_type tp, double max_range) { +/* + int num_stations = 0; + int range = 10; + comm_list_type stations; + comm_list_iterator itr; + double distance = -9999.0; + + while(num_stations == 0) { + num_stations = FindByPos(aPos, range, &stations, tp); + if(num_stations) { + double closest = max_range * SG_NM_TO_METER; + double tmp; + for(itr = stations.begin(); itr != stations.end(); ++itr) { + ATCData ad2 = *itr; + const FGAirport *a = fgFindAirportID(ad2.ident); + if (a) { + tmp = dclGetHorizontalSeparation(ad2.geod, aPos); + if(tmp <= closest) { + closest = tmp; + distance = tmp; + ad = *itr; + } + } + } + //cout << "Closest station is " << ad.ident << " at a range of " << distance << " meters\n"; + return(distance); + } + if(range > max_range) { + break; + } + range *= 10; + } + return(-9999.0); +*/ +} + + +// Find by Airport code. +// This is basically a wrapper for a call to the airport database to get the airport +// position followed by a call to FindByPos(...) +bool FGCommList::FindByCode( const string& ICAO, ATCData& ad, atc_type tp ) { +/* + const FGAirport *a = fgFindAirportID( ICAO); + if ( a) { + comm_list_type stations; + int found = FindByPos(a->geod(), 10.0, &stations, tp); + if(found) { + comm_list_iterator itr = stations.begin(); + while(itr != stations.end()) { + if(((*itr).ident == ICAO) && ((*itr).type == tp)) { + ad = *itr; + //cout << "FindByCode returns " << ICAO + // << " type: " << tp + // << " freq: " << itr->freq + // << endl; + return true; + } + ++itr; + } + } + } + return false; +*/ +} + +// TODO - this function should move somewhere else eventually! +// Return an appropriate sequence number for an ATIS transmission. +// Return sequence number + 2600 if sequence is unchanged since +// last time. +int FGCommList::GetAtisSequence( const string& apt_id, + const double tstamp, const int interval, const int special) +{ +/* + atis_transmission_type tran; + + if(atislog.find(apt_id) == atislog.end()) { // New station + tran.tstamp = tstamp - interval; +// Random number between 0 and 25 inclusive, i.e. 26 equiprobable outcomes: + tran.sequence = int(sg_random() * LTRS); + atislog[apt_id] = tran; + //cout << "New ATIS station: " << apt_id << " seq-1: " + // << tran.sequence << endl; + } + +// calculate the appropriate identifier and update the log + tran = atislog[apt_id]; + + int delta = int((tstamp - tran.tstamp) / interval); + tran.tstamp += delta * interval; + if (special && !delta) delta++; // a "special" ATIS update is required + tran.sequence = (tran.sequence + delta) % LTRS; + atislog[apt_id] = tran; + //if (delta) cout << "New ATIS sequence: " << tran.sequence + // << " Delta: " << delta << endl; + return(tran.sequence + (delta ? 0 : LTRS*1000)); +*/ +} +/***************************************************************************** + * FGKln89AlignedProjection + ****************************************************************************/ + +FGKln89AlignedProjection::FGKln89AlignedProjection() { + _origin.setLatitudeRad(0); + _origin.setLongitudeRad(0); + _origin.setElevationM(0); + _correction_factor = cos(_origin.getLatitudeRad()); +} + +FGKln89AlignedProjection::FGKln89AlignedProjection(const SGGeod& centre, double heading) { + _origin = centre; + _theta = heading * SG_DEGREES_TO_RADIANS; + _correction_factor = cos(_origin.getLatitudeRad()); +} + +FGKln89AlignedProjection::~FGKln89AlignedProjection() { +} + +void FGKln89AlignedProjection::Init(const SGGeod& centre, double heading) { + _origin = centre; + _theta = heading * SG_DEGREES_TO_RADIANS; + _correction_factor = cos(_origin.getLatitudeRad()); +} + +SGVec3d FGKln89AlignedProjection::ConvertToLocal(const SGGeod& pt) { + // convert from lat/lon to orthogonal + double delta_lat = pt.getLatitudeRad() - _origin.getLatitudeRad(); + double delta_lon = pt.getLongitudeRad() - _origin.getLongitudeRad(); + double y = sin(delta_lat) * SG_EQUATORIAL_RADIUS_M; + double x = sin(delta_lon) * SG_EQUATORIAL_RADIUS_M * _correction_factor; + + // Align + if(_theta != 0.0) { + double xbar = x; + x = x*cos(_theta) - y*sin(_theta); + y = (xbar*sin(_theta)) + (y*cos(_theta)); + } + + return SGVec3d(x, y, pt.getElevationM()); +} + +SGGeod FGKln89AlignedProjection::ConvertFromLocal(const SGVec3d& pt) { + // de-align + double thi = _theta * -1.0; + double x = pt.x()*cos(thi) - pt.y()*sin(thi); + double y = (pt.x()*sin(thi)) + (pt.y()*cos(thi)); + + // convert from orthogonal to lat/lon + double delta_lat = asin(y / SG_EQUATORIAL_RADIUS_M); + double delta_lon = asin(x / SG_EQUATORIAL_RADIUS_M) / _correction_factor; + + return SGGeod::fromRadM(_origin.getLongitudeRad()+delta_lon, _origin.getLatitudeRad()+delta_lat, pt.z()); +} + +#endif // #ENABLE_ATCDCL \ No newline at end of file diff --git a/src/ATC/atcutils.hxx b/src/ATC/atcutils.hxx new file mode 100644 index 000000000..e26d204b0 --- /dev/null +++ b/src/ATC/atcutils.hxx @@ -0,0 +1,185 @@ +// atcutils.hxx +// +// This file contains a collection of classes from David Luff's +// AI/ATC code that are shared by non-AI parts of FlightGear. +// more specifcially, it contains implementations of FGCommList and +// FGATCAlign +// +// Written by David Luff and Alexander Kappes, started Jan 2003. +// Based on navlist.hxx by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +/***************************************************************** +* +* FGCommList is used to store communication frequency information +* for the ATC and AI subsystems. Two maps are maintained - one +* searchable by location and one searchable by frequency. The +* data structure returned from the search is the ATCData struct +* defined in ATC.hxx, containing location, frequency, name, range +* and type of the returned station. +* +******************************************************************/ + +#ifndef _FG_ATCUTILS_HXX +#define _FG_ATCUTILS_HXX + + + +#include + +#include +#include +#include + +//#include "ATC.hxx" +//#include "atis.hxx" + +#if !ENABLE_ATCDCL + +class SGPath; +class ATCData; + +// Possible types of ATC type that the radios may be tuned to. +// INVALID implies not tuned in to anything. +enum atc_type { + AWOS, + ATIS, + GROUND, + TOWER, + APPROACH, + DEPARTURE, + ENROUTE, + INVALID /* must be last element; see ATC_NUM_TYPES */ +}; + + +// A list of ATC stations +typedef std::list < ATCData > comm_list_type; +typedef comm_list_type::iterator comm_list_iterator; +typedef comm_list_type::const_iterator comm_list_const_iterator; + +// A map of ATC station lists +typedef std::map < int, comm_list_type > comm_map_type; +typedef comm_map_type::iterator comm_map_iterator; +typedef comm_map_type::const_iterator comm_map_const_iterator; + + +class FGCommList { + +public: + + FGCommList(); + ~FGCommList(); + + // load all comm frequencies and build the map + bool init( const SGPath& path ); + + // query the database for the specified frequency, lon and lat are + // If no atc_type is specified, it returns true if any non-invalid type is found. + // If atc_type is specifed, returns true only if the specified type is found. + // Returns the station closest to the supplied position. + // The data found is written into the passed-in ATCData structure. + bool FindByFreq(const SGGeod& aPos, double freq, ATCData* ad, atc_type tp = INVALID ); + + // query the database by location, lon and lat are in degrees, elev is in meters, range is in nautical miles. + // Returns the number of stations of the specified atc_type tp that are in range of the position defined by + // lon, lat and elev, and pushes them into stations. + // If no atc_type is specifed, returns the number of all stations in range, and pushes them into stations + // ** stations is erased before use ** + int FindByPos(const SGGeod& aPos, double range, comm_list_type* stations, atc_type tp = INVALID ); + + // Returns the distance in meters to the closest station of a given type, + // with the details written into ATCData& ad. If no type is specifed simply + // returns the distance to the closest station of any type. + // Returns -9999 if no stations found within max_range in nautical miles (default 100 miles). + // Note that the search algorithm starts at 10 miles and multiplies by 10 thereafter, so if + // say 300 miles is specifed 10, then 100, then 1000 will be searched, breaking at first result + // and giving up after 1000. + // !!!Be warned that searching anything over 100 miles will pause the sim unacceptably!!! + // (The ability to search longer ranges should be used during init only). + double FindClosest(const SGGeod& aPos, ATCData& ad, atc_type tp = INVALID, double max_range = 100.0 ); + + // Find by Airport code. + bool FindByCode( const std::string& ICAO, ATCData& ad, atc_type tp = INVALID ); + + // Return the sequence letter for an ATIS transmission given transmission time and airport id + // This maybe should get moved somewhere else!! + int GetAtisSequence( const std::string& apt_id, const double tstamp, + const int interval, const int flush=0); + + // Comm stations mapped by frequency + //comm_map_type commlist_freq; + + // Comm stations mapped by bucket + //comm_map_type commlist_bck; + + // Load comms from a specified path (which must include the filename) +private: + + bool LoadComms(const SGPath& path); + +//----------- This stuff is left over from atislist.[ch]xx and maybe should move somewhere else + // Add structure and map for storing a log of atis transmissions + // made in this session of FlightGear. This allows the callsign + // to be allocated correctly wrt time. + //typedef struct { + // double tstamp; + // int sequence; + //} atis_transmission_type; + + //typedef std::map < std::string, atis_transmission_type > atis_log_type; + //typedef atis_log_type::iterator atis_log_iterator; + //typedef atis_log_type::const_iterator atis_log_const_iterator; + + //atis_log_type atislog; +//----------------------------------------------------------------------------------------------- + +}; + + +extern FGCommList *current_commlist; + +// FGATCAlignedProjection - a class to project an area local to a runway onto an orthogonal co-ordinate system +// with the origin at the threshold and the runway aligned with the y axis. +class FGKln89AlignedProjection { + +public: + FGKln89AlignedProjection(); + FGKln89AlignedProjection(const SGGeod& centre, double heading); + ~FGKln89AlignedProjection(); + + void Init(const SGGeod& centre, double heading); + + // Convert a lat/lon co-ordinate (degrees) to the local projection (meters) + SGVec3d ConvertToLocal(const SGGeod& pt); + + // Convert a local projection co-ordinate (meters) to lat/lon (degrees) + SGGeod ConvertFromLocal(const SGVec3d& pt); + +private: + SGGeod _origin; // lat/lon of local area origin (the threshold) + double _theta; // the rotation angle for alignment in radians + double _correction_factor; // Reduction in surface distance per degree of longitude due to latitude. Saves having to do a cos() every call. + +}; + +#endif // #if ENABLE_ATCDCL + +#endif // _FG_ATCUTILS_HXX + + diff --git a/src/Airports/apt_loader.cxx b/src/Airports/apt_loader.cxx index 3dfcdf059..8984214d9 100644 --- a/src/Airports/apt_loader.cxx +++ b/src/Airports/apt_loader.cxx @@ -47,6 +47,8 @@ #include "pavement.hxx" #if ENABLE_ATCDCL # include +#else + #include #endif #include @@ -78,11 +80,8 @@ public: {} -#ifdef ENABLE_ATCDCL + void parseAPT(const string &aptdb_file, FGCommList *comm_list) -#else - void parseAPT(const string &aptdb_file) -#endif { sg_gzifstream in( aptdb_file ); @@ -162,7 +161,9 @@ public: } else if ( line_id == 0 ) { // ?? } else if ( line_id == 50 ) { + parseATISLine(comm_list, simgear::strutils::split(line)); + } else if ( line_id >= 51 && line_id <= 56 ) { // other frequency entries (ignore) } else if ( line_id == 110 ) { @@ -468,7 +469,7 @@ private: pvt->addNode(pos, num == 113); } } -#if ENABLE_ATCDCL + void parseATISLine(FGCommList *comm_list, const vector& token) { if ( rwy_count <= 0 ) { @@ -485,6 +486,7 @@ private: // 50 11770 AWOS 3 // This code parallels code found in "operator>>" in ATC.hxx; // FIXME: unify the code. +#if ENABLE_ATCDCL ATCData a; a.geod = SGGeod::fromDegFt(rwy_lon_accum / (double)rwy_count, rwy_lat_accum / (double)rwy_count, last_apt_elev); @@ -503,6 +505,8 @@ private: SGBucket bucket(a.geod); int bucknum = bucket.gen_index(); comm_list->commlist_bck[bucknum].push_back(a); +#else +#endif #if 0 SG_LOG( SG_GENERAL, SG_ALERT, "Loaded ATIS/AWOS for airport: " << a.ident @@ -512,7 +516,7 @@ private: << " type: " << a.type ); #endif } -#endif + }; @@ -520,19 +524,11 @@ private: // metar file is used to mark the airports as having metar available // or not. bool fgAirportDBLoad( const string &aptdb_file, -#if ENABLE_ATCDCL FGCommList *comm_list, const std::string &metar_file ) -#else - const std::string &metar_file ) -#endif { APTLoader ld; -#if ENABLE_ATCDCL ld.parseAPT(aptdb_file, comm_list); -#else - ld.parseAPT(aptdb_file); -#endif // // Load the metar.dat file and update apt db with stations that // have metar data. diff --git a/src/Airports/apt_loader.hxx b/src/Airports/apt_loader.hxx index 54596e8d8..7e2405638 100644 --- a/src/Airports/apt_loader.hxx +++ b/src/Airports/apt_loader.hxx @@ -35,8 +35,8 @@ class FGCommList; // Load the airport data base from the specified aptdb file. The // metar file is used to mark the airports as having metar available // or not. + bool fgAirportDBLoad( const std::string &aptdb_file, FGCommList *comm_list, const std::string &metar_file ); - #endif // _FG_APT_LOADER_HXX diff --git a/src/Instrumentation/KLN89/kln89.cxx b/src/Instrumentation/KLN89/kln89.cxx index c028e17ae..0f7345f32 100644 --- a/src/Instrumentation/KLN89/kln89.cxx +++ b/src/Instrumentation/KLN89/kln89.cxx @@ -43,7 +43,12 @@ #include "kln89_symbols.hxx" #include +#if ENABLE_ATCDCL #include +#else +#include "kln89_align.hxx" +#endif + #include
#include #include @@ -676,12 +681,17 @@ void KLN89::DrawMap(bool draw_avs) { double mapScaleMeters = _mapScale * (_mapScaleUnits == 0 ? SG_NM_TO_METER : 1000); // TODO - use an aligned projection when either DTK or TK up! +#if ENABLE_ATCDCL FGATCAlignedProjection mapProj(SGGeod::fromRad(_gpsLon, _gpsLat), _mapHeading); - +#else + FGKln89AlignedProjection mapProj(SGGeod::fromRad(_gpsLon, _gpsLat), _mapHeading); +#endif double meter_per_pix = (_mapOrientation == 0 ? mapScaleMeters / 20.0f : mapScaleMeters / 29.0f); - SGGeod bottomLeft = mapProj.ConvertFromLocal(SGVec3d(gps_max(-57.0 * meter_per_pix, -50000), gps_max((_mapOrientation == 0 ? -20.0 * meter_per_pix : -11.0 * meter_per_pix), -25000), 0.0)); SGGeod topRight = mapProj.ConvertFromLocal(SGVec3d(gps_min(54.0 * meter_per_pix, 50000), gps_min((_mapOrientation == 0 ? 20.0 * meter_per_pix : 29.0 * meter_per_pix), 25000), 0.0)); + + + // Draw Airport labels first (but not one's that are waypoints) // Draw Airports first (but not one's that are waypoints) diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index ded6765fc..3a8a078c1 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -78,6 +78,8 @@ # include # include # include "ATCDCL/commlist.hxx" +#else +# include "ATC/atcutils.hxx" #endif #include @@ -982,13 +984,9 @@ fgInitNav () -#if ENABLE_ATCDCL current_commlist = new FGCommList; current_commlist->init( globals->get_fg_root() ); fgAirportDBLoad( aptdb.str(), current_commlist, p_metar.str() ); -#else - fgAirportDBLoad( aptdb.str(), p_metar.str() ); -#endif FGNavList *navlist = new FGNavList; FGNavList *loclist = new FGNavList; @@ -1623,10 +1621,11 @@ bool fgInitSubsystems() { // Initialise the ATC Manager //////////////////////////////////////////////////////////////////// +#if ENABLE_ATCDCL SG_LOG(SG_GENERAL, SG_INFO, " ATC Manager"); globals->set_ATC_mgr(new FGATCMgr); globals->get_ATC_mgr()->init(); - + //////////////////////////////////////////////////////////////////// // Initialise the AI Manager //////////////////////////////////////////////////////////////////// @@ -1634,7 +1633,7 @@ bool fgInitSubsystems() { SG_LOG(SG_GENERAL, SG_INFO, " AI Manager"); globals->set_AI_mgr(new FGAIMgr); globals->get_AI_mgr()->init(); - +#endif //////////////////////////////////////////////////////////////////// // Initialise the AI Model Manager //////////////////////////////////////////////////////////////////// From 16dd34839fc4b8eb419a8681fe0bdf51f46b20cd Mon Sep 17 00:00:00 2001 From: durk Date: Sun, 17 Jan 2010 07:48:04 +0000 Subject: [PATCH 3/4] Replacement code for ATCDCL functions are in ATC/atcutils.[ch]xx. Thanks to Alex Buzin for reporting. --- src/Instrumentation/KLN89/kln89.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Instrumentation/KLN89/kln89.cxx b/src/Instrumentation/KLN89/kln89.cxx index 0f7345f32..7b08ba735 100644 --- a/src/Instrumentation/KLN89/kln89.cxx +++ b/src/Instrumentation/KLN89/kln89.cxx @@ -46,7 +46,7 @@ #if ENABLE_ATCDCL #include #else -#include "kln89_align.hxx" +#include "ATC/atcutils.hxx" #endif #include
From 546d3e265d7d3678c89c9125326a18487e43f5a7 Mon Sep 17 00:00:00 2001 From: durk Date: Sun, 17 Jan 2010 07:55:19 +0000 Subject: [PATCH 4/4] And this time, fix it more properly. :-) --- src/Instrumentation/KLN89/kln89.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Instrumentation/KLN89/kln89.cxx b/src/Instrumentation/KLN89/kln89.cxx index 7b08ba735..b074e2295 100644 --- a/src/Instrumentation/KLN89/kln89.cxx +++ b/src/Instrumentation/KLN89/kln89.cxx @@ -46,7 +46,7 @@ #if ENABLE_ATCDCL #include #else -#include "ATC/atcutils.hxx" +#include #endif #include