diff --git a/src/ATC/ATCdisplay.cxx b/src/ATC/ATCdisplay.cxx new file mode 100644 index 000000000..c3a91ba75 --- /dev/null +++ b/src/ATC/ATCdisplay.cxx @@ -0,0 +1,136 @@ +// ATCdisplay.cxx - routines to display ATC output - graphically for now +// +// Written by David Luff, started October 2001. +// +// Copyright (C) 2001 David C Luff - david.luff@nottingham.ac.uk +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include
+#include + +#include "ATCdisplay.hxx" + + +FGATCDisplay *current_atcdisplay; + + +// Constructor +FGATCDisplay::FGATCDisplay( void ) { + rep_msg = false; + dsp_offset1 = 0; + dsp_offset2 = 0; +} + + +// Destructor +FGATCDisplay::~FGATCDisplay( void ) { +} + +void FGATCDisplay::init( void ) { +} + + +// update - this actually draws the visuals and should be called from the main Flightgear rendering loop. +void FGATCDisplay::update() { + + if(rep_msg) { + float fps = general.get_frame_rate(); + + //cout << "In FGATC::update()" << endl; + SGPropertyNode *xsize_node = fgGetNode("/sim/startup/xsize"); + SGPropertyNode *ysize_node = fgGetNode("/sim/startup/ysize"); + int iwidth = xsize_node->getIntValue(); + int iheight = ysize_node->getIntValue(); + + //TODO - if the string is bigger than the buffer the program exits - we really ought to have a robust check here + char buf[256]; + //float fps = visibility/1600; + // sprintf(buf,"%-4.1f %7.0f %7.0f", fps, tris, culled); +// sprintf(buf,"%s %-5.1f", "visibility ", visibility); + sprintf(buf,"%s", rep_msg_str.c_str()); + + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + gluOrtho2D( 0, iwidth, 0, iheight ); + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + + glDisable( GL_DEPTH_TEST ); + glDisable( GL_LIGHTING ); + + glColor3f( 0.9, 0.4, 0.2 ); + +// guiFnt.drawString( buf, +// int(iwidth - guiFnt.getStringWidth(buf) - 10 - (int)dsp_offset), +// (iheight - 20) ); + guiFnt.drawString( buf, + int(iwidth - 10 - dsp_offset1), + (iheight - 20) ); + guiFnt.drawString( buf, + int(iwidth - 10 - dsp_offset2), + (iheight - 20) ); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_LIGHTING ); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + // Try to scroll at a frame rate independent speed + // 40 pixels/second looks about right for now + if(dsp_offset1 >= dsp_offset2) { + dsp_offset1+=(40.0/fps); + dsp_offset2 = dsp_offset1 - (rep_msg_str.size() * 10) - 100; + if(dsp_offset1 > (iwidth + (rep_msg_str.size() * 10))) + dsp_offset1 = 0; + } else { + dsp_offset2+=(40.0/fps); + dsp_offset1 = dsp_offset2 - (rep_msg_str.size() * 10) - 100; + if(dsp_offset2 > (iwidth + (rep_msg_str.size() * 10))) + dsp_offset2 = 0; + } + + } +} + + +void FGATCDisplay::RegisterRepeatingMessage(string msg) { + rep_msg = true; + rep_msg_str = msg; + return; +} + +void FGATCDisplay::ChangeRepeatingMessage(string newmsg) { + //Not implemented yet + return; +} + +void FGATCDisplay::CancelRepeatingMessage() { + rep_msg = false; + rep_msg_str = ""; + dsp_offset1 = 0; + dsp_offset2 = 0; + return; +} diff --git a/src/ATC/ATCdisplay.hxx b/src/ATC/ATCdisplay.hxx new file mode 100644 index 000000000..5577c0603 --- /dev/null +++ b/src/ATC/ATCdisplay.hxx @@ -0,0 +1,83 @@ +// ATCdisplay.hxx - class to manage the graphical display of ATC messages. +// - The idea is to separate the display of ATC messages from their +// - generation so that the generation may come from any source. +// +// Written by David Luff, started October 2001. +// +// Copyright (C) 2001 David C Luff - david.luff@nottingham.ac.uk +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef _FG_ATC_DISPLAY_HXX +#define _FG_ATC_DISPLAY_HXX + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +SG_USING_STD(vector); +SG_USING_STD(string); + +struct atcMessage { + string msg; + bool repeating; + int id; +}; + +// ASSUMPTION - with two radios the list won't be long so we don't need to map the id's +typedef vector atcMessageList; +typedef vector::iterator atcMessageListIterator; + +class FGATCDisplay { + +private: + bool rep_msg; // Flag to indicate there is a repeating transmission to display + float dsp_offset1; // Used to set the correct position of scrolling display + float dsp_offset2; + string rep_msg_str; // The repeating transmission to play + atcMessageList msgList; + atcMessageListIterator msgList_itr; + +public: + FGATCDisplay(); + ~FGATCDisplay(); + + void init(); + + // Display any registered messages + void update(); + + // Register a single message for display when possible + void RegisterSingleMessage(string msg); // OK - I know passing a string in and out is probably not good but it will have to do for now. + +/* For now we will assume only one repeating message at once */ + // This is not really robust + + // Register a continuously repeating message + void RegisterRepeatingMessage(string msg); + + // Change a repeating message - assume that the message changes after the string has finished for now + void ChangeRepeatingMessage(string newmsg); + + // Cancel the current repeating message + void CancelRepeatingMessage(); +}; + +extern FGATCDisplay *current_atcdisplay; + +#endif // _FG_ATC_DISPLAY_HXX diff --git a/src/ATC/Makefile.am b/src/ATC/Makefile.am new file mode 100644 index 000000000..7ec05a3ad --- /dev/null +++ b/src/ATC/Makefile.am @@ -0,0 +1,7 @@ +noinst_LIBRARIES = libATC.a + +libATC_a_SOURCES = \ + atis.cxx atis.hxx atislist.hxx atislist.cxx \ + ATCdisplay.hxx ATCdisplay.cxx + +INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/ATC/atis.cxx b/src/ATC/atis.cxx new file mode 100644 index 000000000..6d49f7a0d --- /dev/null +++ b/src/ATC/atis.cxx @@ -0,0 +1,156 @@ +// atis.cxx - routines to generate the ATIS info string +// +// Written by David Luff, started October 2001. +// +// Copyright (C) 2001 David C Luff - david.luff@nottingham.ac.uk +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +SG_USING_STD(string); + +//#include STL_IOSTREAM +//#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) +//SG_USING_STD(cout); +//#endif + +//#include +//#include +//#include +#include + +//#ifndef FG_OLD_WEATHER +//#include +//#else +//# include +//#endif + +#include
+#include + +#include "atis.hxx" + +// Constructor +FGATIS::FGATIS() { +} + +// Destructor +FGATIS::~FGATIS() { +} + +string FGATIS::get_transmission() { +//void FGATIS::get_transmission() { + + string transmission = ""; + double visibility; + double temperature; + char buf[10]; + +// Only update every so-many loops - FIXME - possibly register this with the event scheduler +// Ack this doesn't work since the static counter is shared between all instances of FGATIS +// OK, for now the radiostack is handling only calling this every-so-often but that is not really +// a proper solution since the atis knows when the transmission is going to change not the radio. + //static int i=0; + //if(i == 0) { + transmission = ""; + + // Start with the transmitted station name. + transmission += name; + + // Add the recording identifier + // TODO - this is hardwired for now - ultimately we need to start with a random one and then increment it with each recording + transmission += " Charlie"; + + // Output the recording time. - we'll just output the last whole hour for now. + string time_str = fgGetString("sim/time/gmt-string"); + // FIXME - this only gets GMT time but that appears to be all the clock outputs for now + //cout << "in atis.cxx, time = " << time_str << endl; + transmission = transmission + " Weather " + time_str.substr(0,3) + "00 hours Zulu"; + + // Get the temperature + // Hardwire the temperature for now - is the local weather database running yet? + transmission += " Temperature 25 degrees Celcius"; + + // Get the pressure / altimeter + + // Get the visibility + visibility = fgGetDouble("/environment/visibility-m"); + sprintf(buf, "%d", int(visibility/1600)); + transmission += " Visibility "; + transmission += buf; + transmission += " miles"; + + // Get the cloudbase + if(fgGetBool("/environment/clouds/status")) { + double cloudbase = fgGetDouble("/environment/clouds/altitude-ft"); + // For some reason the altitude returned doesn't seem to correspond to the actual cloud altitude. + char buf3[10]; + cout << "cloudbase = " << cloudbase << endl; + sprintf(buf3, "%i", int(cloudbase)); + transmission = transmission + " Cloudbase " + buf3 + " feet"; + } + + // Based on the airport-id and wind get the active runway + //FGRunway *r; + SGPath path( globals->get_fg_root() ); + path.append( "Airports" ); + path.append( "runways.mk4" ); + FGRunways runways( path.c_str() ); + + //Set the heading to into the wind + double hdg = fgGetDouble("/environment/wind-from-heading-deg"); + double speed = fgGetDouble("/environment/wind-speed-knots"); + + //cout << "in atis.cxx, hdg = " << hdg << " speed = " << speed << endl; + + //If no wind use 270degrees + if(speed == 0) { + hdg = 270; + transmission += " Winds light and variable"; + } else { + //add a description of the wind to the transmission + char buf2[48]; + sprintf(buf2, "%s %i %s %i %s", " Winds ", int(speed), " knots from ", int(hdg), " degrees"); + transmission += buf2; + } + + string rwy_no = runways.search(ident, hdg); + if(rwy_no != "NN") { + transmission += " Landing and departing runway "; + transmission += rwy_no; + //cout << "in atis.cxx, r.rwy_no = " << rwy_no << " r.id = " << r->id << " r.heading = " << r->heading << endl; + } + + // Anything else? + + // TODO - unhardwire the identifier + transmission += " Advise controller on initial contact you have Charlie"; + + //} + +// i++; +// if(i == 600) { +// i=0; +// } + + return(transmission); +} \ No newline at end of file diff --git a/src/ATC/atis.hxx b/src/ATC/atis.hxx new file mode 100644 index 000000000..5809c1b59 --- /dev/null +++ b/src/ATC/atis.hxx @@ -0,0 +1,160 @@ +// atis.hxx -- ATIS class +// +// Written by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + +#ifndef _FG_ATIS_HXX +#define _FG_ATIS_HXX + +#include + +#include +#include +#include +#include +#include + +#ifdef SG_HAVE_STD_INCLUDES +# include +#include +#elif defined( SG_HAVE_NATIVE_SGI_COMPILERS ) +# include +#elif defined( __BORLANDC__ ) +# include +#else +# include +#include +#endif + +#if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS ) +SG_USING_STD(istream); +#endif + +#include + +SG_USING_STD(string); + +//DCL - a complete guess for now. +#define FG_ATIS_DEFAULT_RANGE 30 + +class FGATIS { + + char type; + double lon, lat; + double elev; + double x, y, z; + int freq; + int range; + string ident; // Code of the airport its at. + string name; // Name transmitted in the broadcast. + string info; // The actual ATIS transmission + // This is not stored in default.atis but is generated + // from the prevailing conditions when required. + + // for failure modeling + string trans_ident; // transmitted ident + bool atis_failed; // atis failed? + +public: + + FGATIS(void); + ~FGATIS(void); + + inline char get_type() const { return type; } + inline double get_lon() const { return lon; } + inline double get_lat() const { return lat; } + inline double get_elev() const { return elev; } + inline double get_x() const { return x; } + inline double get_y() const { return y; } + inline double get_z() const { return z; } + inline int get_freq() const { return freq; } + inline int get_range() const { return range; } + inline const char *get_ident() { return ident.c_str(); } + inline string get_trans_ident() { return trans_ident; } + string get_transmission(void); +// void get_transmission(); + + /* inline void set_type( char t ) { type = t; } + inline void set_lon( double l ) { lon = l; } + inline void set_lat( double l ) { lat = l; } + inline void set_elev( double e ) { elev = e; } + inline void set_freq( int f ) { freq = f; } + inline void set_range( int r ) { range = r; } + inline void set_dme( bool b ) { dme = b; } + inline void set_ident( char *i ) { strncpy( ident, i, 5 ); } */ + + friend istream& operator>> ( istream&, FGATIS& ); +}; + + +inline istream& +operator >> ( istream& in, FGATIS& a ) +{ + double f; + char ch; + + static bool first_time = true; + static double julian_date = 0; + static const double MJD0 = 2415020.0; + if ( first_time ) { + julian_date = sgTimeCurrentMJD( 0 ) + MJD0; + first_time = false; + } + + in >> a.type; + + if ( a.type == '[' ) + return in >> skipeol; + + in >> a.lat >> a.lon >> a.elev >> f >> a.range + >> a.ident; + + a.name = ""; + in >> ch; + a.name += ch; + while(1) { + //in >> noskipws + in.unsetf(ios::skipws); + in >> ch; + a.name += ch; + if((ch == '"') || (ch == 0x0A)) { + break; + } // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the " + } + in.setf(ios::skipws); + //cout << "atis.name = " << a.name << '\n'; + + a.freq = (int)(f*100.0 + 0.5); + + // cout << a.ident << endl; + + // generate cartesian coordinates + Point3D geod( a.lon * SGD_DEGREES_TO_RADIANS, a.lat * SGD_DEGREES_TO_RADIANS, a.elev ); + Point3D cart = sgGeodToCart( geod ); + a.x = cart.x(); + a.y = cart.y(); + a.z = cart.z(); + + a.trans_ident = a.ident; + a.atis_failed = false; + + return in >> skipeol; +} + +#endif // _FG_ATIS_HXX diff --git a/src/ATC/atislist.cxx b/src/ATC/atislist.cxx new file mode 100644 index 000000000..54f5ae0ee --- /dev/null +++ b/src/ATC/atislist.cxx @@ -0,0 +1,149 @@ +// atislist.cxx -- navaids management class +// +// Written by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include "atislist.hxx" + + +FGATISList *current_atislist; + + +// Constructor +FGATISList::FGATISList( void ) { +} + + +// Destructor +FGATISList::~FGATISList( void ) { +} + + +// load the navaids and build the map +bool FGATISList::init( SGPath path ) { + FGATIS a; + + atislist.erase( atislist.begin(), atislist.end() ); + + sg_gzifstream in( path.str() ); + if ( !in.is_open() ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() ); + exit(-1); + } + + // read in each line of the file + + in >> skipeol; + in >> skipcomment; + +#ifdef __MWERKS__ + + char c = 0; + while ( in.get(c) && c != '\0' && a.get_type() != '[' ) { + in.putback(c); + in >> a; + if ( a.get_type() != '[' ) { + atislist[a.get_freq()].push_back(a); + } + in >> skipcomment; + } + +#else + + double min = 100000; + double max = 0; + + while ( ! in.eof() && a.get_type() != '[' ) { + in >> a; + //cout << "id = " << a.get_ident() << endl; + //cout << " type = " << a.get_type() << endl; + //cout << " lon = " << a.get_lon() << endl; + //cout << " lat = " << a.get_lat() << endl; + //cout << " elev = " << a.get_elev() << endl; + //cout << " freq = " << a.get_freq() << endl; + //cout << " range = " << a.get_range() << endl; + if ( a.get_type() != '[' ) { + atislist[a.get_freq()].push_back(a); + } + in >> skipcomment; + + if ( a.get_type() != 'N' ) { + if ( a.get_freq() < min ) { + min = a.get_freq(); + } + if ( a.get_freq() > max ) { + max = a.get_freq(); + } + } + } + + // cout << "min freq = " << min << endl; + // cout << "max freq = " << max << endl; + +#endif + + return true; +} + + +// query the database for the specified frequency, lon and lat are in +// degrees, elev is in meters +bool FGATISList::query( double lon, double lat, double elev, double freq, + FGATIS *a ) +{ + atis_list_type stations = atislist[(int)(freq*100.0 + 0.5)]; + + atis_list_iterator current = stations.begin(); + atis_list_iterator last = stations.end(); + + // double az1, az2, s; + Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) ); + Point3D station; + double d; + for ( ; current != last ; ++current ) { + //cout << "testing " << current->get_ident() << endl; + station = Point3D(current->get_x(), current->get_y(), current->get_z()); + //cout << "aircraft = " << aircraft << endl; + //cout << "station = " << station << endl; + + d = aircraft.distance3Dsquared( station ); + + //cout << " dist = " << sqrt(d) + // << " range = " << current->get_range() * SG_NM_TO_METER << endl; + + // match up to twice the published range so we can model + // reduced signal strength + if ( d < (2 * current->get_range() * SG_NM_TO_METER + * 2 * current->get_range() * SG_NM_TO_METER ) ) { + //cout << "matched = " << current->get_ident() << endl; + *a = *current; + return true; + } + } + + return false; +} diff --git a/src/ATC/atislist.hxx b/src/ATC/atislist.hxx new file mode 100644 index 000000000..284a95627 --- /dev/null +++ b/src/ATC/atislist.hxx @@ -0,0 +1,69 @@ +// atislist.hxx -- atis management class +// +// Written by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + +#ifndef _FG_ATISLIST_HXX +#define _FG_ATISLIST_HXX + + +#include +#include + +#include +#include + +#include "atis.hxx" + +SG_USING_STD(map); +SG_USING_STD(vector); + + +class FGATISList { + + // convenience types + typedef vector < FGATIS > atis_list_type; + typedef atis_list_type::iterator atis_list_iterator; + typedef atis_list_type::const_iterator atis_list_const_iterator; + + // typedef map < int, atis_list_type, less > atis_map_type; + typedef map < int, atis_list_type > atis_map_type; + typedef atis_map_type::iterator atis_map_iterator; + typedef atis_map_type::const_iterator atis_map_const_iterator; + + atis_map_type atislist; + +public: + + FGATISList(); + ~FGATISList(); + + // load all atis and build the map + bool init( SGPath path ); + + // query the database for the specified frequency, lon and lat are + // in degrees, elev is in meters + bool query( double lon, double lat, double elev, double freq, FGATIS *a ); +}; + + +extern FGATISList *current_atislist; + + +#endif // _FG_ATISLIST_HXX