1
0
Fork 0

Initial revision of ATIS module contributed by Dave Luff.

This commit is contained in:
curt 2001-11-07 17:55:04 +00:00
parent e19d456716
commit 20f0d3f83e
7 changed files with 760 additions and 0 deletions

136
src/ATC/ATCdisplay.cxx Normal file
View file

@ -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 <config.h>
#endif
#include <simgear/misc/props.hxx>
#include <Include/general.hxx>
#include <Main/fg_props.hxx>
#include <GUI/gui.h>
#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;
}

83
src/ATC/ATCdisplay.hxx Normal file
View file

@ -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 <config.h>
#endif
#include <vector>
#include <string>
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<atcMessage> atcMessageList;
typedef vector<atcMessage>::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

7
src/ATC/Makefile.am Normal file
View file

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

156
src/ATC/atis.cxx Normal file
View file

@ -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 <config.h>
#endif
#include <simgear/compiler.h>
#include <string>
SG_USING_STD(string);
//#include STL_IOSTREAM
//#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
//SG_USING_STD(cout);
//#endif
//#include <simgear/debug/logstream.hxx>
//#include <simgear/misc/sgstream.hxx>
//#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx>
//#ifndef FG_OLD_WEATHER
//#include <WeatherCM/FGLocalWeatherDatabase.h>
//#else
//# include <Weather/weather.hxx>
//#endif
#include <Main/fg_props.hxx>
#include <Airports/runways.hxx>
#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);
}

160
src/ATC/atis.hxx Normal file
View file

@ -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 <stdio.h>
#include <simgear/compiler.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/magvar/magvar.hxx>
#include <simgear/timing/sg_time.hxx>
#ifdef SG_HAVE_STD_INCLUDES
# include <istream>
#include <iomanip>
#elif defined( SG_HAVE_NATIVE_SGI_COMPILERS )
# include <iostream.h>
#elif defined( __BORLANDC__ )
# include <iostream>
#else
# include <istream.h>
#include <iomanip.h>
#endif
#if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS )
SG_USING_STD(istream);
#endif
#include <string>
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

149
src/ATC/atislist.cxx Normal file
View file

@ -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 <config.h>
#endif
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#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;
}

69
src/ATC/atislist.hxx Normal file
View file

@ -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 <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include <map>
#include <vector>
#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<int> > 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