// trafficcontrol.hxx - classes to manage AIModels based air traffic control // Written by Durk Talsma, started September 2006. // // 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. // // $Id$ #ifndef _TRAFFIC_CONTROL_HXX_ #define _TRAFFIC_CONTROL_HXX_ #ifndef __cplusplus # error This library requires C++ #endif #include #include #include #include #include // There is probably a better include than sg_geodesy to get the SG_NM_TO_METER... #include #include #include #include #include #include using std::string; using std::vector; typedef vector intVec; typedef vector::iterator intVecIterator; class FGAIFlightPlan; // forward reference class FGGroundNetwork; // forward reference class FGAIAircraft; // forward reference class FGAirportDynamics; /************************************************************************************** * class FGATCInstruction * like class FGATC Controller, this class definition should go into its own file * and or directory... For now, just testing this stuff out though... *************************************************************************************/ class FGATCInstruction { private: bool holdPattern; bool holdPosition; bool changeSpeed; bool changeHeading; bool changeAltitude; bool resolveCircularWait; double speed; double heading; double alt; public: FGATCInstruction(); bool hasInstruction (); bool getHoldPattern () { return holdPattern; }; bool getHoldPosition () { return holdPosition; }; bool getChangeSpeed () { return changeSpeed; }; bool getChangeHeading () { return changeHeading; }; bool getChangeAltitude() { return changeAltitude; }; double getSpeed () { return speed; }; double getHeading () { return heading; }; double getAlt () { return alt; }; bool getCheckForCircularWait() { return resolveCircularWait; }; void setHoldPattern (bool val) { holdPattern = val; }; void setHoldPosition (bool val) { holdPosition = val; }; void setChangeSpeed (bool val) { changeSpeed = val; }; void setChangeHeading (bool val) { changeHeading = val; }; void setChangeAltitude(bool val) { changeAltitude = val; }; void setResolveCircularWait (bool val) { resolveCircularWait = val; }; void setSpeed (double val) { speed = val; }; void setHeading (double val) { heading = val; }; void setAlt (double val) { alt = val; }; }; /************************************************************************************** * class FGTrafficRecord *************************************************************************************/ class FGTrafficRecord { private: int id, waitsForId; int currentPos; int leg; int frequencyId; int state; bool allowTransmission; time_t timer; intVec intentions; FGATCInstruction instruction; double latitude, longitude, heading, speed, altitude, radius; string runway; //FGAISchedule *trafficRef; FGAIAircraft *aircraft; public: FGTrafficRecord(); void setId(int val) { id = val; }; void setRadius(double rad) { radius = rad;}; void setPositionAndIntentions(int pos, FGAIFlightPlan *route); void setRunway(string rwy) { runway = rwy;}; void setLeg(int lg) { leg = lg;}; int getId() { return id;}; int getState() { return state;}; void setState(int s) { state = s;} FGATCInstruction getInstruction() { return instruction;}; bool hasInstruction() { return instruction.hasInstruction(); }; void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt); bool checkPositionAndIntentions(FGTrafficRecord &other); int crosses (FGGroundNetwork *, FGTrafficRecord &other); bool isOpposing (FGGroundNetwork *, FGTrafficRecord &other, int node); bool onRoute(FGGroundNetwork *, FGTrafficRecord &other); bool getSpeedAdjustment() { return instruction.getChangeSpeed(); }; double getLatitude () { return latitude ; }; double getLongitude() { return longitude; }; double getHeading () { return heading ; }; double getSpeed () { return speed ; }; double getAltitude () { return altitude ; }; double getRadius () { return radius ; }; int getWaitsForId () { return waitsForId; }; void setSpeedAdjustment(double spd); void setHeadingAdjustment(double heading); void clearSpeedAdjustment () { instruction.setChangeSpeed (false); }; void clearHeadingAdjustment() { instruction.setChangeHeading(false); }; bool hasHeadingAdjustment() { return instruction.getChangeHeading(); }; bool hasHoldPosition() { return instruction.getHoldPosition(); }; void setHoldPosition (bool inst) { instruction.setHoldPosition(inst); }; void setWaitsForId(int id) { waitsForId = id; }; void setResolveCircularWait() { instruction.setResolveCircularWait(true); }; void clearResolveCircularWait() { instruction.setResolveCircularWait(false); }; string getRunway() { return runway; }; //void setCallSign(string clsgn) { callsign = clsgn; }; void setAircraft(FGAIAircraft *ref) { aircraft = ref;}; void updateState() { state++; allowTransmission=true; }; //string getCallSign() { return callsign; }; FGAIAircraft *getAircraft() { return aircraft;}; int getTime() { return timer; }; int getLeg() { return leg; }; void setTime(time_t time) { timer = time; }; bool pushBackAllowed(); bool allowTransmissions() { return allowTransmission; }; void suppressRepeatedTransmissions () { allowTransmission=false; }; void allowRepeatedTransmissions () { allowTransmission=true; }; void nextFrequency() { frequencyId++; }; int getNextFrequency() { return frequencyId; }; intVec& getIntentions() { return intentions; }; int getCurrentPosition() { return currentPos; }; }; typedef vector TrafficVector; typedef vector::iterator TrafficVectorIterator; typedef vector TimeVector; typedef vector::iterator TimeVectorIterator; /*********************************************************************** * Active runway, a utility class to keep track of which aircraft has * clearance for a given runway. **********************************************************************/ class ActiveRunway { private: string rwy; int currentlyCleared; double distanceToFinal; TimeVector estimatedArrivalTimes; public: ActiveRunway(string r, int cc) { rwy = r; currentlyCleared = cc; distanceToFinal = 6.0 * SG_NM_TO_METER; }; string getRunwayName() { return rwy; }; int getCleared () { return currentlyCleared; }; double getApproachDistance() { return distanceToFinal; }; //time_t getEstApproachTime() { return estimatedArrival; }; //void setEstApproachTime(time_t time) { estimatedArrival = time; }; time_t requestTimeSlot(time_t eta); }; typedef vector ActiveRunwayVec; typedef vector::iterator ActiveRunwayVecIterator; /** * class FGATCController * NOTE: this class serves as an abstraction layer for all sorts of ATC controllers. *************************************************************************************/ class FGATCController { private: bool initialized; protected: bool available; time_t lastTransmission; double dt_count; osg::Group* group; string formatATCFrequency3_2(int ); string genTransponderCode(string fltRules); bool isUserAircraft(FGAIAircraft*); public: typedef enum { MSG_ANNOUNCE_ENGINE_START, MSG_REQUEST_ENGINE_START, MSG_PERMIT_ENGINE_START, MSG_DENY_ENGINE_START, MSG_ACKNOWLEDGE_ENGINE_START, MSG_REQUEST_PUSHBACK_CLEARANCE, MSG_PERMIT_PUSHBACK_CLEARANCE, MSG_HOLD_PUSHBACK_CLEARANCE, MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY, MSG_INITIATE_CONTACT, MSG_ACKNOWLEDGE_INITIATE_CONTACT, MSG_REQUEST_TAXI_CLEARANCE, MSG_ISSUE_TAXI_CLEARANCE, MSG_ACKNOWLEDGE_TAXI_CLEARANCE, MSG_HOLD_POSITION, MSG_ACKNOWLEDGE_HOLD_POSITION, MSG_RESUME_TAXI, MSG_ACKNOWLEDGE_RESUME_TAXI } AtcMsgId; typedef enum { ATC_AIR_TO_GROUND, ATC_GROUND_TO_AIR } AtcMsgDir; FGATCController(); virtual ~FGATCController(); void init(); virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, double lat, double lon, double hdg, double spd, double alt, double radius, int leg, FGAIAircraft *aircraft) = 0; virtual void signOff(int id) = 0; virtual void updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt) = 0; virtual bool hasInstruction(int id) = 0; virtual FGATCInstruction getInstruction(int id) = 0; double getDt() { return dt_count; }; void setDt(double dt) { dt_count = dt;}; void transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir, bool audible); string getGateName(FGAIAircraft *aircraft); virtual void render(bool) = 0; virtual string getName() = 0; private: AtcMsgDir lastTransmissionDirection; }; /****************************************************************************** * class FGTowerControl *****************************************************************************/ class FGTowerController : public FGATCController { private: TrafficVector activeTraffic; ActiveRunwayVec activeRunways; FGAirportDynamics *parent; public: FGTowerController(FGAirportDynamics *parent); virtual ~FGTowerController() {}; virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, double lat, double lon, double hdg, double spd, double alt, double radius, int leg, FGAIAircraft *aircraft); virtual void signOff(int id); virtual void updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt); virtual bool hasInstruction(int id); virtual FGATCInstruction getInstruction(int id); virtual void render(bool); virtual string getName(); bool hasActiveTraffic() { return activeTraffic.size() != 0; }; TrafficVector &getActiveTraffic() { return activeTraffic; }; }; /****************************************************************************** * class FGStartupController * handle *****************************************************************************/ class FGStartupController : public FGATCController { private: TrafficVector activeTraffic; //ActiveRunwayVec activeRunways; FGAirportDynamics *parent; public: FGStartupController(FGAirportDynamics *parent); virtual ~FGStartupController() {}; virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, double lat, double lon, double hdg, double spd, double alt, double radius, int leg, FGAIAircraft *aircraft); virtual void signOff(int id); virtual void updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt); virtual bool hasInstruction(int id); virtual FGATCInstruction getInstruction(int id); virtual void render(bool); virtual string getName(); bool hasActiveTraffic() { return activeTraffic.size() != 0; }; TrafficVector &getActiveTraffic() { return activeTraffic; }; // Hpoefully, we can move this function to the base class, but I need to verify what is needed for the other controllers before doing so. bool checkTransmissionState(int st, time_t now, time_t startTime, TrafficVectorIterator i, AtcMsgId msgId, AtcMsgDir msgDir); }; /****************************************************************************** * class FGTowerControl *****************************************************************************/ class FGApproachController : public FGATCController { private: TrafficVector activeTraffic; ActiveRunwayVec activeRunways; FGAirportDynamics *parent; public: FGApproachController(FGAirportDynamics * parent); virtual ~FGApproachController() { }; virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, double lat, double lon, double hdg, double spd, double alt, double radius, int leg, FGAIAircraft *aircraft); virtual void signOff(int id); virtual void updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt); virtual bool hasInstruction(int id); virtual FGATCInstruction getInstruction(int id); virtual void render(bool); virtual string getName(); ActiveRunway* getRunway(string name); bool hasActiveTraffic() { return activeTraffic.size() != 0; }; TrafficVector &getActiveTraffic() { return activeTraffic; }; }; #endif // _TRAFFIC_CONTROL_HXX