A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
// FGAIAircraft - FGAIBase-derived class creates an AI airplane
2003-11-28 15:48:05 +00:00
//
// Written by David Culp, started October 2003.
//
// Copyright (C) 2003 David P. Culp - davidculp2@comcast.net
//
// 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
2006-02-21 01:16:04 +00:00
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2003-11-28 15:48:05 +00:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2005-02-10 09:01:51 +00:00
# include <simgear/route/waypoint.hxx>
2003-11-28 15:48:05 +00:00
# include <Main/fg_props.hxx>
# include <Main/globals.hxx>
2005-02-10 09:01:51 +00:00
# include <Main/viewer.hxx>
2003-11-28 15:48:05 +00:00
# include <Scenery/scenery.hxx>
2005-02-10 09:01:51 +00:00
# include <Scenery/tilemgr.hxx>
2008-08-14 18:13:39 +00:00
# include <Airports/dynamics.hxx>
2010-10-20 17:54:16 +01:00
# include <Airports/simple.hxx>
2005-02-10 09:01:51 +00:00
2003-11-28 15:48:05 +00:00
# include <string>
# include <math.h>
2004-12-05 09:34:03 +00:00
# include <time.h>
2009-10-02 05:44:56 +00:00
2005-02-18 10:16:30 +00:00
# ifdef _MSC_VER
# include <float.h>
# define finite _finite
2005-10-06 11:08:26 +00:00
# elif defined(__sun) || defined(sgi)
2005-05-07 08:56:42 +00:00
# include <ieeefp.h>
2005-02-18 10:16:30 +00:00
# endif
2003-11-28 15:48:05 +00:00
2008-07-27 16:25:13 +00:00
using std : : string ;
2003-11-28 15:48:05 +00:00
# include "AIAircraft.hxx"
2007-06-28 07:47:20 +00:00
# include "performancedata.hxx"
# include "performancedb.hxx"
A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
# define TGT_VS_CUTOFF 10000
2006-10-06 17:36:31 +00:00
//#include <Airports/trafficcontroller.hxx>
2007-06-09 11:49:16 +00:00
static string tempReg ;
2011-06-25 20:44:44 +02:00
FGAIAircraft : : FGAIAircraft ( FGAISchedule * ref ) :
/* HOT must be disabled for AI Aircraft,
* otherwise traffic detection isn ' t working as expected . */
FGAIBase ( otAircraft , false )
{
2006-05-13 10:02:17 +00:00
trafficRef = ref ;
2007-07-09 05:07:56 +00:00
if ( trafficRef ) {
2006-05-13 10:02:17 +00:00
groundOffset = trafficRef - > getGroundOffset ( ) ;
2011-06-25 20:44:44 +02:00
setCallSign ( trafficRef - > getCallSign ( ) ) ;
2007-07-09 05:07:56 +00:00
}
2006-05-13 10:02:17 +00:00
else
groundOffset = 0 ;
2011-08-03 23:09:52 +02:00
fp = 0 ;
controller = 0 ;
prevController = 0 ;
towerController = 0 ;
2006-05-13 10:02:17 +00:00
dt_count = 0 ;
dt_elev_count = 0 ;
use_perf_vs = true ;
2006-10-29 19:30:21 +00:00
no_roll = false ;
tgt_speed = 0 ;
speed = 0 ;
groundTargetSpeed = 0 ;
2006-05-13 10:02:17 +00:00
// set heading and altitude locks
hdg_lock = false ;
alt_lock = false ;
roll = 0 ;
headingChangeRate = 0.0 ;
2009-09-04 17:03:50 +00:00
headingError = 0 ;
2010-08-29 19:25:34 +02:00
minBearing = 360 ;
speedFraction = 1.0 ;
2006-09-19 17:04:22 +00:00
holdPos = false ;
2010-04-25 08:32:53 +00:00
needsTaxiClearance = false ;
2011-01-10 20:53:46 +01:00
_needsGroundElevation = true ;
2007-06-28 07:47:20 +00:00
_performance = 0 ; //TODO initialize to JET_TRANSPORT from PerformanceDB
2009-09-04 17:03:50 +00:00
dt = 0 ;
2011-08-07 21:38:50 +02:00
takeOffStatus = 0 ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
FGAIAircraft : : ~ FGAIAircraft ( ) {
2006-05-13 10:02:17 +00:00
//delete fp;
2007-06-09 11:49:16 +00:00
if ( controller )
controller - > signOff ( getID ( ) ) ;
2003-11-28 15:48:05 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : readFromScenario ( SGPropertyNode * scFileNode ) {
2006-05-13 10:02:17 +00:00
if ( ! scFileNode )
return ;
2006-02-11 13:16:56 +00:00
2006-05-13 10:02:17 +00:00
FGAIBase : : readFromScenario ( scFileNode ) ;
2006-02-11 13:16:56 +00:00
2006-05-13 10:02:17 +00:00
setPerformance ( scFileNode - > getStringValue ( " class " , " jet_transport " ) ) ;
setFlightPlan ( scFileNode - > getStringValue ( " flightplan " ) ,
2007-06-10 06:06:57 +00:00
scFileNode - > getBoolValue ( " repeat " , false ) ) ;
2006-05-13 10:02:17 +00:00
setCallSign ( scFileNode - > getStringValue ( " callsign " ) ) ;
2003-11-28 15:48:05 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : bind ( ) {
2003-12-21 20:12:55 +00:00
FGAIBase : : bind ( ) ;
2004-01-22 21:13:47 +00:00
props - > tie ( " controls/gear/gear-down " ,
2007-06-10 06:06:57 +00:00
SGRawValueMethods < FGAIAircraft , bool > ( * this ,
& FGAIAircraft : : _getGearDown ) ) ;
2009-03-22 13:49:51 +00:00
props - > tie ( " transponder-id " ,
SGRawValueMethods < FGAIAircraft , const char * > ( * this ,
& FGAIAircraft : : _getTransponderCode ) ) ;
2003-12-21 20:12:55 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : unbind ( ) {
2003-12-21 20:12:55 +00:00
FGAIBase : : unbind ( ) ;
2004-01-22 21:13:47 +00:00
2004-09-08 13:21:40 +00:00
props - > untie ( " controls/gear/gear-down " ) ;
2009-03-22 13:49:51 +00:00
props - > untie ( " transponder-id " ) ;
2003-12-21 20:12:55 +00:00
}
2003-11-28 15:48:05 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : update ( double dt ) {
2006-05-13 10:02:17 +00:00
FGAIBase : : update ( dt ) ;
Run ( dt ) ;
Transform ( ) ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : setPerformance ( const std : : string & acclass ) {
2007-06-28 07:47:20 +00:00
static PerformanceDB perfdb ; //TODO make it a global service
setPerformance ( perfdb . getDataFor ( acclass ) ) ;
}
2006-02-11 13:16:56 +00:00
2006-05-13 10:02:17 +00:00
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : setPerformance ( PerformanceData * ps ) {
_performance = ps ;
}
2006-05-13 10:02:17 +00:00
2003-11-28 15:48:05 +00:00
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : Run ( double dt ) {
A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
2007-06-28 07:47:20 +00:00
FGAIAircraft : : dt = dt ;
2010-02-19 00:31:38 +00:00
bool outOfSight = false ,
flightplanActive = true ;
updatePrimaryTargetValues ( flightplanActive , outOfSight ) ; // target hdg, alt, speed
if ( outOfSight ) {
return ;
2007-06-28 07:47:20 +00:00
}
2010-02-19 00:31:38 +00:00
if ( ! flightplanActive ) {
groundTargetSpeed = 0 ;
2007-06-28 07:47:20 +00:00
}
2003-11-28 15:48:05 +00:00
2007-06-28 07:47:20 +00:00
handleATCRequests ( ) ; // ATC also has a word to say
updateSecondaryTargetValues ( ) ; // target roll, vertical speed, pitch
updateActualState ( ) ;
2011-04-29 20:44:05 +02:00
// We currently have one situation in which an AIAircraft object is used that is not attached to the
// AI manager. In this particular case, the AIAircraft is used to shadow the user's aircraft's behavior in the AI world.
// Since we perhaps don't want a radar entry of our own aircraft, the following conditional should probably be adequate
// enough
if ( manager )
UpdateRadar ( manager ) ;
2008-12-10 16:04:10 +00:00
checkVisibility ( ) ;
2007-06-28 07:47:20 +00:00
}
2006-06-16 14:22:21 +00:00
2008-12-10 16:04:10 +00:00
void FGAIAircraft : : checkVisibility ( )
{
2009-06-09 12:16:21 +00:00
double visibility_meters = fgGetDouble ( " /environment/visibility-m " ) ;
FGViewer * vw = globals - > get_current_view ( ) ;
invisible = ( SGGeodesy : : distanceM ( vw - > getPosition ( ) , pos ) > visibility_meters ) ;
2008-12-10 16:04:10 +00:00
}
2003-11-28 15:48:05 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : AccelTo ( double speed ) {
2006-05-13 10:02:17 +00:00
tgt_speed = speed ;
2011-01-10 20:53:46 +01:00
if ( ! isStationary ( ) )
_needsGroundElevation = true ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : PitchTo ( double angle ) {
2006-05-13 10:02:17 +00:00
tgt_pitch = angle ;
alt_lock = false ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : RollTo ( double angle ) {
2006-05-13 10:02:17 +00:00
tgt_roll = angle ;
hdg_lock = false ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : YawTo ( double angle ) {
2006-05-13 10:02:17 +00:00
tgt_yaw = angle ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : ClimbTo ( double alt_ft ) {
2006-06-24 00:00:27 +00:00
tgt_altitude_ft = alt_ft ;
2006-05-13 10:02:17 +00:00
alt_lock = true ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : TurnTo ( double heading ) {
2006-05-13 10:02:17 +00:00
tgt_heading = heading ;
hdg_lock = true ;
2003-11-28 15:48:05 +00:00
}
2007-06-10 06:06:57 +00:00
double FGAIAircraft : : sign ( double x ) {
2007-06-09 11:49:16 +00:00
if ( x = = 0.0 )
return x ;
2006-05-13 10:02:17 +00:00
else
2007-06-09 11:49:16 +00:00
return x / fabs ( x ) ;
2003-11-28 15:48:05 +00:00
}
2004-05-15 09:07:55 +00:00
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : setFlightPlan ( const std : : string & flightplan , bool repeat ) {
if ( ! flightplan . empty ( ) ) {
2006-05-13 10:02:17 +00:00
FGAIFlightPlan * fp = new FGAIFlightPlan ( flightplan ) ;
fp - > setRepeat ( repeat ) ;
SetFlightPlan ( fp ) ;
}
2006-02-11 13:16:56 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : SetFlightPlan ( FGAIFlightPlan * f ) {
2006-05-13 10:02:17 +00:00
delete fp ;
fp = f ;
2004-05-15 09:07:55 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : ProcessFlightPlan ( double dt , time_t now ) {
2007-06-09 11:49:16 +00:00
// the one behind you
2011-07-31 19:27:44 +02:00
FGAIWaypoint * prev = 0 ;
2007-06-09 11:49:16 +00:00
// the one ahead
2011-07-31 19:27:44 +02:00
FGAIWaypoint * curr = 0 ;
2007-06-09 11:49:16 +00:00
// the next plus 1
2011-07-31 19:27:44 +02:00
FGAIWaypoint * next = 0 ;
2006-05-13 10:02:17 +00:00
2005-02-10 09:01:51 +00:00
prev = fp - > getPreviousWaypoint ( ) ;
curr = fp - > getCurrentWaypoint ( ) ;
next = fp - > getNextWaypoint ( ) ;
2007-06-09 11:49:16 +00:00
2006-05-13 10:02:17 +00:00
dt_count + = dt ;
2006-08-26 07:22:20 +00:00
///////////////////////////////////////////////////////////////////////////
// Initialize the flightplan
//////////////////////////////////////////////////////////////////////////
2007-06-10 06:06:57 +00:00
if ( ! prev ) {
2007-06-09 11:49:16 +00:00
handleFirstWaypoint ( ) ;
return ;
} // end of initialization
2007-06-15 20:52:32 +00:00
if ( ! fpExecutable ( now ) )
return ;
2007-06-09 11:49:16 +00:00
dt_count = 0 ;
2006-05-13 10:02:17 +00:00
2010-08-29 19:25:34 +02:00
double distanceToDescent ;
if ( reachedEndOfCruise ( distanceToDescent ) ) {
if ( ! loadNextLeg ( distanceToDescent ) ) {
setDie ( true ) ;
return ;
}
prev = fp - > getPreviousWaypoint ( ) ;
curr = fp - > getCurrentWaypoint ( ) ;
next = fp - > getNextWaypoint ( ) ;
}
2007-06-10 06:06:57 +00:00
if ( ! leadPointReached ( curr ) ) {
2007-06-09 11:49:16 +00:00
controlHeading ( curr ) ;
controlSpeed ( curr , next ) ;
2011-07-24 12:48:13 +02:00
/*
2011-04-19 18:01:24 +02:00
if ( speed < 0 ) {
cerr < < getCallSign ( )
< < " : verifying lead distance to waypoint : "
< < fp - > getCurrentWaypoint ( ) - > name < < " "
< < fp - > getLeadDistance ( ) < < " . Distance to go "
< < ( fp - > getDistanceToGo ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr ) )
< < " . Target speed = "
< < tgt_speed
< < " . Current speed = "
< < speed
< < " . Minimum Bearing " < < minBearing
< < endl ;
2011-07-24 12:48:13 +02:00
} */
2007-06-10 06:06:57 +00:00
} else {
2011-07-31 19:27:44 +02:00
if ( curr - > isFinished ( ) ) //end of the flight plan
2007-06-09 11:49:16 +00:00
{
2006-05-13 10:02:17 +00:00
if ( fp - > getRepeat ( ) )
fp - > restart ( ) ;
else
setDie ( true ) ;
return ;
}
2007-06-10 06:06:57 +00:00
if ( next ) {
2007-06-09 11:49:16 +00:00
//TODO more intelligent method in AIFlightPlan, no need to send data it already has :-)
2006-05-13 10:02:17 +00:00
tgt_heading = fp - > getBearing ( curr , next ) ;
spinCounter = 0 ;
}
2007-06-09 11:49:16 +00:00
//TODO let the fp handle this (loading of next leg)
2009-06-14 15:24:30 +00:00
fp - > IncrementWaypoint ( trafficRef ! = 0 ) ;
2010-08-29 19:25:34 +02:00
if ( ( ( ! ( fp - > getNextWaypoint ( ) ) ) ) & & ( trafficRef ! = 0 ) )
2008-11-16 13:41:24 +00:00
if ( ! loadNextLeg ( ) ) {
setDie ( true ) ;
return ;
}
2006-05-13 10:02:17 +00:00
prev = fp - > getPreviousWaypoint ( ) ;
curr = fp - > getCurrentWaypoint ( ) ;
next = fp - > getNextWaypoint ( ) ;
// Now that we have incremented the waypoints, excute some traffic manager specific code
2007-06-10 06:06:57 +00:00
if ( trafficRef ) {
2007-06-09 11:49:16 +00:00
//TODO isn't this best executed right at the beginning?
2007-06-10 06:06:57 +00:00
if ( ! aiTrafficVisible ( ) ) {
2006-05-13 10:02:17 +00:00
setDie ( true ) ;
return ;
}
2007-06-10 06:06:57 +00:00
if ( ! handleAirportEndPoints ( prev , now ) ) {
2006-05-13 10:02:17 +00:00
setDie ( true ) ;
return ;
}
2007-06-09 11:49:16 +00:00
announcePositionToController ( ) ;
2006-05-13 10:02:17 +00:00
}
2007-06-10 06:06:57 +00:00
if ( next ) {
2008-04-02 19:01:48 +00:00
fp - > setLeadDistance ( tgt_speed , tgt_heading , curr , next ) ;
2006-05-13 10:02:17 +00:00
}
2011-07-31 19:27:44 +02:00
if ( ! ( prev - > getOn_ground ( ) ) ) // only update the tgt altitude from flightplan if not on the ground
2007-06-09 11:49:16 +00:00
{
2011-07-31 19:27:44 +02:00
tgt_altitude_ft = prev - > getAltitude ( ) ;
if ( curr - > getCrossat ( ) > - 1000.0 ) {
2006-05-13 10:02:17 +00:00
use_perf_vs = false ;
A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
// tgt_vs = (curr->getCrossat() - altitude_ft) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
// / 6076.0 / speed*60.0);
// if (fabs(tgt_vs) > TGT_VS_CUTOFF) { SG_LOG(SG_GENERAL, SG_ALERT, "Rediculously high vertical speed caculated at " << SG_ORIGIN << ". Corresponding to " << (tgt_vs * .005) << "degrees of pitch angle" << prev->getName()); };
// if (tgt_vs < -1500)
// tgt_vs = -1500;
// if (tgt_vs > 1500)
// tgt_vs = 1500;
// checkTcas();
2011-07-31 19:27:44 +02:00
tgt_altitude_ft = curr - > getCrossat ( ) ;
2007-06-10 06:06:57 +00:00
} else {
2006-05-13 10:02:17 +00:00
use_perf_vs = true ;
}
}
2011-07-31 19:27:44 +02:00
AccelTo ( prev - > getSpeed ( ) ) ;
2006-05-13 10:02:17 +00:00
hdg_lock = alt_lock = true ;
2011-07-31 19:27:44 +02:00
no_roll = prev - > getOn_ground ( ) ;
2004-05-15 09:07:55 +00:00
}
}
2011-01-17 23:33:54 +01:00
void FGAIAircraft : : checkTcas ( void )
{
if ( props - > getIntValue ( " tcas/threat-level " , 0 ) = = 3 )
{
int RASense = props - > getIntValue ( " tcas/ra-sense " , 0 ) ;
if ( ( RASense > 0 ) & & ( tgt_vs < 4000 ) )
// upward RA: climb!
tgt_vs = 4000 ;
else
if ( RASense < 0 )
{
// downward RA: descend!
if ( altitude_ft < 1000 )
{
// too low: level off
if ( tgt_vs > 0 )
tgt_vs = 0 ;
}
else
{
if ( tgt_vs > - 4000 )
tgt_vs = - 4000 ;
}
}
}
}
2007-06-09 11:49:16 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : initializeFlightPlan ( ) {
2006-08-26 07:22:20 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
bool FGAIAircraft : : _getGearDown ( ) const {
2007-06-28 07:47:20 +00:00
return _performance - > gearExtensible ( this ) ;
2004-09-08 13:21:40 +00:00
}
2005-02-10 09:01:51 +00:00
2009-03-22 13:49:51 +00:00
const char * FGAIAircraft : : _getTransponderCode ( ) const {
return transponderCode . c_str ( ) ;
}
2011-07-31 19:27:44 +02:00
// NOTE: Check whether the new (delayed leg increment code has any effect on this code.
// Probably not, because it should only be executed after we have already passed the leg incrementing waypoint.
2009-03-22 13:49:51 +00:00
2010-08-29 19:25:34 +02:00
bool FGAIAircraft : : loadNextLeg ( double distance ) {
2007-06-09 11:49:16 +00:00
2006-05-13 10:02:17 +00:00
int leg ;
2011-08-01 21:34:33 +02:00
if ( ( leg = fp - > getLeg ( ) ) = = 9 ) {
2008-11-16 13:41:24 +00:00
if ( ! trafficRef - > next ( ) ) {
return false ;
}
2007-07-09 05:07:56 +00:00
setCallSign ( trafficRef - > getCallSign ( ) ) ;
2011-08-01 21:34:33 +02:00
leg = 0 ;
2006-05-13 10:02:17 +00:00
fp - > setLeg ( leg ) ;
2005-02-10 09:01:51 +00:00
}
2007-06-09 11:49:16 +00:00
2006-05-13 10:02:17 +00:00
FGAirport * dep = trafficRef - > getDepartureAirport ( ) ;
FGAirport * arr = trafficRef - > getArrivalAirport ( ) ;
2007-06-10 06:06:57 +00:00
if ( ! ( dep & & arr ) ) {
2006-05-13 10:02:17 +00:00
setDie ( true ) ;
2007-06-10 06:06:57 +00:00
} else {
2006-05-13 10:02:17 +00:00
double cruiseAlt = trafficRef - > getCruiseAlt ( ) * 100 ;
2009-01-30 18:48:44 +00:00
fp - > create ( this ,
dep ,
2007-06-10 06:06:57 +00:00
arr ,
2011-07-31 19:27:44 +02:00
leg + 1 ,
2009-01-30 18:48:44 +00:00
cruiseAlt ,
2007-06-10 06:06:57 +00:00
trafficRef - > getSpeed ( ) ,
_getLatitude ( ) ,
_getLongitude ( ) ,
false ,
trafficRef - > getRadius ( ) ,
trafficRef - > getFlightType ( ) ,
acType ,
2010-08-29 19:25:34 +02:00
company ,
distance ) ;
2008-11-16 13:41:24 +00:00
//cerr << "created leg " << leg << " for " << trafficRef->getCallSign() << endl;
2005-02-10 09:01:51 +00:00
}
2008-11-16 13:41:24 +00:00
return true ;
2005-02-10 09:01:51 +00:00
}
2006-05-13 10:02:17 +00:00
// Note: This code is copied from David Luff's AILocalTraffic
2005-02-10 09:01:51 +00:00
// Warning - ground elev determination is CPU intensive
// Either this function or the logic of how often it is called
// will almost certainly change.
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : getGroundElev ( double dt ) {
2006-05-13 10:02:17 +00:00
dt_elev_count + = dt ;
2011-01-10 20:53:46 +01:00
if ( ! needGroundElevation ( ) )
return ;
2006-05-13 10:02:17 +00:00
// Update minimally every three secs, but add some randomness
2008-07-13 12:51:06 +00:00
// to prevent all AI objects doing this in synchrony
2006-05-13 10:02:17 +00:00
if ( dt_elev_count < ( 3.0 ) + ( rand ( ) % 10 ) )
return ;
2007-06-28 07:47:20 +00:00
dt_elev_count = 0 ;
2006-05-13 10:02:17 +00:00
// Only do the proper hitlist stuff if we are within visible range of the viewer.
2007-06-10 06:06:57 +00:00
if ( ! invisible ) {
2006-05-13 10:02:17 +00:00
double visibility_meters = fgGetDouble ( " /environment/visibility-m " ) ;
FGViewer * vw = globals - > get_current_view ( ) ;
2009-06-09 12:16:21 +00:00
if ( SGGeodesy : : distanceM ( vw - > getPosition ( ) , pos ) > visibility_meters ) {
2006-05-13 10:02:17 +00:00
return ;
}
double range = 500.0 ;
2010-11-19 13:59:43 +01:00
if ( globals - > get_tile_mgr ( ) - > schedule_scenery ( pos , range , 5.0 ) )
{
double alt ;
if ( getGroundElevationM ( SGGeod : : fromGeodM ( pos , 20000 ) , alt , 0 ) )
2011-01-10 20:53:46 +01:00
{
2010-11-19 13:59:43 +01:00
tgt_altitude_ft = alt * SG_METER_TO_FEET ;
2011-01-10 20:53:46 +01:00
if ( isStationary ( ) )
{
// aircraft is stationary and we obtained altitude for this spot - we're done.
_needsGroundElevation = false ;
}
}
2006-05-13 10:02:17 +00:00
}
}
2006-01-30 13:29:49 +00:00
}
2006-04-19 17:36:41 +00:00
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : doGroundAltitude ( ) {
A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
2011-01-10 20:53:46 +01:00
if ( ( fabs ( altitude_ft - ( tgt_altitude_ft + groundOffset ) ) > 1000.0 ) | |
2011-01-10 21:19:51 +01:00
( isStationary ( ) ) )
2007-06-09 11:49:16 +00:00
altitude_ft = ( tgt_altitude_ft + groundOffset ) ;
else
altitude_ft + = 0.1 * ( ( tgt_altitude_ft + groundOffset ) - altitude_ft ) ;
2010-08-29 19:25:34 +02:00
tgt_vs = 0 ;
2006-04-19 17:36:41 +00:00
}
2006-05-13 10:02:17 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : announcePositionToController ( ) {
if ( trafficRef ) {
2007-06-09 11:49:16 +00:00
int leg = fp - > getLeg ( ) ;
2006-05-13 10:02:17 +00:00
2008-07-13 12:51:06 +00:00
// Note that leg has been incremented after creating the current leg, so we should use
2007-06-09 11:49:16 +00:00
// leg numbers here that are one higher than the number that is used to create the leg
2011-07-31 19:27:44 +02:00
// NOTE: As of July, 30, 2011, the post-creation leg updating is no longer happening.
// Leg numbers are updated only once the aircraft passes the last waypoint created for that legm so I should probably just use
// the original leg numbers here!
2007-06-10 06:06:57 +00:00
switch ( leg ) {
2011-07-31 19:27:44 +02:00
case 1 : // Startup and Push back
2008-07-13 12:51:06 +00:00
if ( trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) )
controller = trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) - > getStartupController ( ) ;
break ;
2011-07-31 19:27:44 +02:00
case 2 : // Taxiing to runway
2007-06-10 06:06:57 +00:00
if ( trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) - > getGroundNetwork ( ) - > exists ( ) )
controller = trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) - > getGroundNetwork ( ) ;
break ;
2011-07-31 19:27:44 +02:00
case 3 : //Take off tower controller
2007-06-10 06:06:57 +00:00
if ( trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) ) {
controller = trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) - > getTowerController ( ) ;
} else {
cerr < < " Error: Could not find Dynamics at airport : " < < trafficRef - > getDepartureAirport ( ) - > getId ( ) < < endl ;
}
break ;
2011-07-31 19:27:44 +02:00
case 6 :
2010-08-29 19:25:34 +02:00
if ( trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) ) {
controller = trafficRef - > getArrivalAirport ( ) - > getDynamics ( ) - > getApproachController ( ) ;
}
break ;
2011-07-31 19:27:44 +02:00
case 8 : // Taxiing for parking
2007-06-10 06:06:57 +00:00
if ( trafficRef - > getArrivalAirport ( ) - > getDynamics ( ) - > getGroundNetwork ( ) - > exists ( ) )
controller = trafficRef - > getArrivalAirport ( ) - > getDynamics ( ) - > getGroundNetwork ( ) ;
break ;
default :
controller = 0 ;
break ;
2007-06-09 11:49:16 +00:00
}
2006-08-26 07:22:20 +00:00
2007-06-10 06:06:57 +00:00
if ( ( controller ! = prevController ) & & ( prevController ! = 0 ) ) {
2007-06-09 11:49:16 +00:00
prevController - > signOff ( getID ( ) ) ;
}
prevController = controller ;
2007-06-10 06:06:57 +00:00
if ( controller ) {
2011-07-31 19:27:44 +02:00
controller - > announcePosition ( getID ( ) , fp , fp - > getCurrentWaypoint ( ) - > getRouteIndex ( ) ,
2007-06-10 06:06:57 +00:00
_getLatitude ( ) , _getLongitude ( ) , hdg , speed , altitude_ft ,
2008-07-13 12:51:06 +00:00
trafficRef - > getRadius ( ) , leg , this ) ;
2007-06-09 11:49:16 +00:00
}
2006-08-26 07:22:20 +00:00
}
}
2011-08-07 21:38:50 +02:00
void FGAIAircraft : : scheduleForATCTowerDepartureControl ( int state ) {
if ( ! takeOffStatus ) {
2011-08-03 23:09:52 +02:00
int leg = fp - > getLeg ( ) ;
if ( trafficRef ) {
if ( trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) ) {
towerController = trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) - > getTowerController ( ) ;
} else {
cerr < < " Error: Could not find Dynamics at airport : " < < trafficRef - > getDepartureAirport ( ) - > getId ( ) < < endl ;
}
if ( towerController ) {
towerController - > announcePosition ( getID ( ) , fp , fp - > getCurrentWaypoint ( ) - > getRouteIndex ( ) ,
_getLatitude ( ) , _getLongitude ( ) , hdg , speed , altitude_ft ,
trafficRef - > getRadius ( ) , leg , this ) ;
2011-08-10 21:39:28 +02:00
//cerr << "Scheduling " << trafficRef->getCallSign() << " for takeoff " << endl;
2011-08-03 23:09:52 +02:00
}
}
}
2011-08-07 21:38:50 +02:00
takeOffStatus = state ;
2011-08-03 23:09:52 +02:00
}
2008-07-13 12:51:06 +00:00
// Process ATC instructions and report back
2006-08-26 07:22:20 +00:00
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : processATC ( FGATCInstruction instruction ) {
2007-06-28 07:47:20 +00:00
if ( instruction . getCheckForCircularWait ( ) ) {
// This is not exactly an elegant solution,
// but at least it gives me a chance to check
// if circular waits are resolved.
// For now, just take the offending aircraft
// out of the scene
setDie ( true ) ;
// a more proper way should be - of course - to
// let an offending aircraft take an evasive action
// for instance taxi back a little bit.
}
2007-06-09 11:49:16 +00:00
//cerr << "Processing ATC instruction (not Implimented yet)" << endl;
2007-06-10 06:06:57 +00:00
if ( instruction . getHoldPattern ( ) ) { }
2006-08-26 07:22:20 +00:00
2007-06-09 11:49:16 +00:00
// Hold Position
2007-06-10 06:06:57 +00:00
if ( instruction . getHoldPosition ( ) ) {
if ( ! holdPos ) {
2007-06-09 11:49:16 +00:00
holdPos = true ;
}
AccelTo ( 0.0 ) ;
2007-06-10 06:06:57 +00:00
} else {
if ( holdPos ) {
2007-06-09 11:49:16 +00:00
//if (trafficRef)
2008-07-13 12:51:06 +00:00
// cerr << trafficRef->getCallSign() << " Resuming Taxi." << endl;
2007-06-09 11:49:16 +00:00
holdPos = false ;
}
// Change speed Instruction. This can only be excecuted when there is no
// Hold position instruction.
2007-06-10 06:06:57 +00:00
if ( instruction . getChangeSpeed ( ) ) {
2007-06-09 11:49:16 +00:00
// if (trafficRef)
//cerr << trafficRef->getCallSign() << " Changing Speed " << endl;
AccelTo ( instruction . getSpeed ( ) ) ;
2007-06-10 06:06:57 +00:00
} else {
2011-07-31 19:27:44 +02:00
if ( fp ) AccelTo ( fp - > getPreviousWaypoint ( ) - > getSpeed ( ) ) ;
2007-06-09 11:49:16 +00:00
}
}
2007-06-10 06:06:57 +00:00
if ( instruction . getChangeHeading ( ) ) {
2007-06-09 11:49:16 +00:00
hdg_lock = false ;
TurnTo ( instruction . getHeading ( ) ) ;
2007-06-10 06:06:57 +00:00
} else {
if ( fp ) {
hdg_lock = true ;
}
2007-06-09 11:49:16 +00:00
}
2007-06-10 06:06:57 +00:00
if ( instruction . getChangeAltitude ( ) ) { }
2007-06-09 11:49:16 +00:00
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : handleFirstWaypoint ( ) {
2007-06-09 11:49:16 +00:00
bool eraseWaypoints ; //TODO YAGNI
2008-04-02 19:01:48 +00:00
headingError = 0 ;
2007-06-10 06:06:57 +00:00
if ( trafficRef ) {
2007-06-09 11:49:16 +00:00
eraseWaypoints = true ;
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
eraseWaypoints = false ;
}
2011-07-31 19:27:44 +02:00
FGAIWaypoint * prev = 0 ; // the one behind you
FGAIWaypoint * curr = 0 ; // the one ahead
FGAIWaypoint * next = 0 ; // the next plus 1
2007-06-09 11:49:16 +00:00
spinCounter = 0 ;
tempReg = " " ;
//TODO fp should handle this
fp - > IncrementWaypoint ( eraseWaypoints ) ;
if ( ! ( fp - > getNextWaypoint ( ) ) & & trafficRef )
2008-11-16 13:41:24 +00:00
if ( ! loadNextLeg ( ) ) {
setDie ( true ) ;
return ;
}
2007-06-09 11:49:16 +00:00
prev = fp - > getPreviousWaypoint ( ) ; //first waypoint
curr = fp - > getCurrentWaypoint ( ) ; //second waypoint
next = fp - > getNextWaypoint ( ) ; //third waypoint (might not exist!)
2011-07-31 19:27:44 +02:00
setLatitude ( prev - > getLatitude ( ) ) ;
setLongitude ( prev - > getLongitude ( ) ) ;
setSpeed ( prev - > getSpeed ( ) ) ;
setAltitude ( prev - > getAltitude ( ) ) ;
2007-06-09 11:49:16 +00:00
2011-07-31 19:27:44 +02:00
if ( prev - > getSpeed ( ) > 0.0 )
setHeading ( fp - > getBearing ( prev - > getLatitude ( ) , prev - > getLongitude ( ) , curr ) ) ;
2007-06-09 11:49:16 +00:00
else
2011-07-31 19:27:44 +02:00
setHeading ( fp - > getBearing ( curr - > getLatitude ( ) , curr - > getLongitude ( ) , prev ) ) ;
2007-06-09 11:49:16 +00:00
// If next doesn't exist, as in incrementally created flightplans for
// AI/Trafficmanager created plans,
// Make sure lead distance is initialized otherwise
if ( next )
fp - > setLeadDistance ( speed , hdg , curr , next ) ;
2011-07-31 19:27:44 +02:00
if ( curr - > getCrossat ( ) > - 1000.0 ) //use a calculated descent/climb rate
2007-06-09 11:49:16 +00:00
{
use_perf_vs = false ;
A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
/* tgt_vs = (curr->getCrossat() - prev->getAltitude())
2007-06-10 06:06:57 +00:00
/ ( fp - > getDistanceToGo ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr )
2011-07-31 19:27:44 +02:00
/ 6076.0 / prev - > getSpeed ( ) * 60.0 ) ;
A number of cosmetic and/or infrastructural changes.
Traffic Manager:
* Just continue routing until we run out of flights. This change removes one of the major requirements for setting the "Home port" field.
* Add a time restriction requirement for the aircraft scheduler; this became necessary after removing the limited-to-home-port routing restriction.
* Added a new field to the heuristics calculation: take into account whether an aircraft has already been used in a previous session. Rotate aircraft assignments for greater variability across sessions.
* Added a revision number to the cache files, so that old cache results, which are no longer compatible with the new file format, are discarded.
Groundnetwork and traffic control:
* Added a revision number to the cache files, so that old and incompatible results are discarded.
* The caching algorithm probably didn't store the correct data for airports that were processed while the user was quite far away. This is now corrected by checking whether the cached elevation data are equal to the generic airport elevation.
AIAircraft:
* I've been searching for the infamous aircraft bend-over-backward bug, that can occur during initialization, but to no avail yet. The only variable potentially responsible (tgt_vs) wich can explain the irregular jumping behavior, as well as the weird pitch results is initialized in AIAircraft's only constructor (through AIBase), and I can't find any situation in the ground handling code where this variable could get bizarre values. But,
* a couple of tgt_vs. calculations appear to be completely redundant. This value was calculated twice inside the ProcessFlightplan function, and subsequently again in the updateSecondaryTargetValues function. I have removed the calculations in the process flightplan function, without any apparent side effect.
2011-09-04 20:27:36 +02:00
if ( fabs ( tgt_vs ) > TGT_VS_CUTOFF ) { SG_LOG ( SG_GENERAL , SG_ALERT , " Rediculously high vertical speed caculated at " < < SG_ORIGIN ) ; } ;
checkTcas ( ) ; */
2011-07-31 19:27:44 +02:00
tgt_altitude_ft = curr - > getCrossat ( ) ;
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
use_perf_vs = true ;
2011-07-31 19:27:44 +02:00
tgt_altitude_ft = prev - > getAltitude ( ) ;
2007-06-09 11:49:16 +00:00
}
alt_lock = hdg_lock = true ;
2011-07-31 19:27:44 +02:00
no_roll = prev - > getOn_ground ( ) ;
2007-06-10 06:06:57 +00:00
if ( no_roll ) {
2007-06-09 11:49:16 +00:00
Transform ( ) ; // make sure aip is initialized.
getGroundElev ( 60.1 ) ; // make sure it's executed first time around, so force a large dt value
doGroundAltitude ( ) ;
2011-01-10 20:53:46 +01:00
_needsGroundElevation = true ; // check ground elevation again (maybe scenery wasn't available yet)
2007-06-09 11:49:16 +00:00
}
// Make sure to announce the aircraft's position
announcePositionToController ( ) ;
prevSpeed = 0 ;
}
/**
* Check Execution time ( currently once every 100 ms )
* Add a bit of randomization to prevent the execution of all flight plans
* in synchrony , which can add significant periodic framerate flutter .
*
* @ param now
* @ return
*/
2007-06-10 06:06:57 +00:00
bool FGAIAircraft : : fpExecutable ( time_t now ) {
2007-06-09 11:49:16 +00:00
double rand_exec_time = ( rand ( ) % 100 ) / 100 ;
return ( dt_count > ( 0.1 + rand_exec_time ) ) & & ( fp - > isActive ( now ) ) ;
}
/**
* Check to see if we ' ve reached the lead point for our next turn
*
* @ param curr
* @ return
*/
2011-07-31 19:27:44 +02:00
bool FGAIAircraft : : leadPointReached ( FGAIWaypoint * curr ) {
2007-06-09 11:49:16 +00:00
double dist_to_go = fp - > getDistanceToGo ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr ) ;
//cerr << "2" << endl;
double lead_dist = fp - > getLeadDistance ( ) ;
// experimental: Use fabs, because speed can be negative (I hope) during push_back.
2011-07-31 19:27:44 +02:00
if ( ( dist_to_go < fabs ( 10.0 * speed ) ) & & ( speed < 0 ) & & ( tgt_speed < 0 ) & & fp - > getCurrentWaypoint ( ) - > contains ( " PushBackPoint " ) ) {
2011-04-19 18:01:24 +02:00
tgt_speed = - ( dist_to_go / 10.0 ) ;
if ( tgt_speed > - 0.5 ) {
tgt_speed = - 0.5 ;
}
2011-07-31 19:27:44 +02:00
if ( fp - > getPreviousWaypoint ( ) - > getSpeed ( ) < tgt_speed ) {
fp - > getPreviousWaypoint ( ) - > setSpeed ( tgt_speed ) ;
2011-04-19 18:01:24 +02:00
}
}
2007-06-10 06:06:57 +00:00
if ( lead_dist < fabs ( 2 * speed ) ) {
2007-06-15 20:52:32 +00:00
//don't skip over the waypoint
lead_dist = fabs ( 2 * speed ) ;
//cerr << "Extending lead distance to " << lead_dist << endl;
2007-06-09 11:49:16 +00:00
}
//prev_dist_to_go = dist_to_go;
2008-04-02 19:01:48 +00:00
//if (dist_to_go < lead_dist)
2008-11-16 13:41:24 +00:00
// cerr << trafficRef->getCallSign() << " Distance : "
// << dist_to_go << ": Lead distance "
// << lead_dist << " " << curr->name
// << " Ground target speed " << groundTargetSpeed << endl;
2010-09-27 17:48:38 +02:00
double bearing = 0 ;
2010-08-29 19:25:34 +02:00
if ( speed > 50 ) { // don't do bearing calculations for ground traffic
bearing = getBearing ( fp - > getBearing ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr ) ) ;
if ( bearing < minBearing ) {
minBearing = bearing ;
if ( minBearing < 10 ) {
minBearing = 10 ;
}
if ( ( minBearing < 360.0 ) & & ( minBearing > 10.0 ) ) {
speedFraction = cos ( minBearing * SG_DEGREES_TO_RADIANS ) ;
} else {
speedFraction = 1.0 ;
}
}
}
if ( trafficRef ) {
//cerr << "Tracking callsign : \"" << fgGetString("/ai/track-callsign") << "\"" << endl;
2011-10-03 20:54:58 +02:00
if ( trafficRef - > getCallSign ( ) = = fgGetString ( " /ai/track-callsign " ) ) {
2010-08-29 19:25:34 +02:00
cerr < < trafficRef - > getCallSign ( ) < < " " < < tgt_altitude_ft < < " " < < _getSpeed ( ) < < " "
2011-10-03 20:54:58 +02:00
< < _getAltitude ( ) < < " " < < _getLatitude ( ) < < " " < < _getLongitude ( ) < < " " < < dist_to_go < < " " < < lead_dist < < " " < < curr - > getName ( ) < < " " < < vs < < " " < < tgt_vs < < " " < < bearing < < " " < < minBearing < < " " < < speedFraction < < " " < < invisible < < endl ;
}
2010-08-29 19:25:34 +02:00
}
if ( ( dist_to_go < lead_dist ) | | ( bearing > ( minBearing * 1.1 ) ) ) {
minBearing = 360 ;
return true ;
} else {
return false ;
}
2007-06-09 11:49:16 +00:00
}
2007-06-10 06:06:57 +00:00
bool FGAIAircraft : : aiTrafficVisible ( ) {
2009-06-09 19:39:18 +00:00
SGGeod userPos ( SGGeod : : fromDeg ( fgGetDouble ( " /position/longitude-deg " ) ,
fgGetDouble ( " /position/latitude-deg " ) ) ) ;
return ( SGGeodesy : : distanceNm ( userPos , pos ) < = TRAFFICTOAIDISTTODIE ) ;
2007-06-09 11:49:16 +00:00
}
/**
* Handle release of parking gate , once were taxiing . Also ensure service time at the gate
* in the case of an arrival .
*
* @ param prev
* @ return
*/
//TODO the trafficRef is the right place for the method
2011-07-31 19:27:44 +02:00
bool FGAIAircraft : : handleAirportEndPoints ( FGAIWaypoint * prev , time_t now ) {
2007-06-09 11:49:16 +00:00
// prepare routing from one airport to another
FGAirport * dep = trafficRef - > getDepartureAirport ( ) ;
FGAirport * arr = trafficRef - > getArrivalAirport ( ) ;
if ( ! ( dep & & arr ) )
return false ;
// This waypoint marks the fact that the aircraft has passed the initial taxi
// departure waypoint, so it can release the parking.
2008-11-16 13:41:24 +00:00
//cerr << trafficRef->getCallSign() << " has passed waypoint " << prev->name << " at speed " << speed << endl;
2011-08-07 21:38:50 +02:00
//cerr << "Passing waypoint : " << prev->getName() << endl;
2011-07-31 19:27:44 +02:00
if ( prev - > contains ( " PushBackPoint " ) ) {
2007-06-09 11:49:16 +00:00
dep - > getDynamics ( ) - > releaseParking ( fp - > getGate ( ) ) ;
2010-04-25 08:32:53 +00:00
AccelTo ( 0.0 ) ;
2011-08-07 21:38:50 +02:00
//setTaxiClearanceRequest(true);
2007-06-15 20:52:32 +00:00
}
2011-07-31 19:27:44 +02:00
if ( prev - > contains ( " legend " ) ) {
fp - > incrementLeg ( ) ;
}
2011-08-03 23:09:52 +02:00
if ( prev - > contains ( string ( " DepartureHold " ) ) ) {
2011-08-10 21:39:28 +02:00
//cerr << "Passing point DepartureHold" << endl;
2011-08-07 21:38:50 +02:00
scheduleForATCTowerDepartureControl ( 2 ) ;
2011-08-03 23:09:52 +02:00
}
2007-06-09 11:49:16 +00:00
// This is the last taxi waypoint, and marks the the end of the flight plan
// so, the schedule should update and wait for the next departure time.
2011-07-31 19:27:44 +02:00
if ( prev - > contains ( " END " ) ) {
2007-06-09 11:49:16 +00:00
time_t nextDeparture = trafficRef - > getDepartureTime ( ) ;
// make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior
2007-06-10 06:06:57 +00:00
if ( nextDeparture < ( now + 1200 ) ) {
2007-06-09 11:49:16 +00:00
nextDeparture = now + 1200 ;
}
2011-08-07 21:38:50 +02:00
fp - > setTime ( nextDeparture ) ;
2007-06-09 11:49:16 +00:00
}
return true ;
}
/**
* Check difference between target bearing and current heading and correct if necessary .
*
* @ param curr
*/
2011-07-31 19:27:44 +02:00
void FGAIAircraft : : controlHeading ( FGAIWaypoint * curr ) {
2007-06-09 11:49:16 +00:00
double calc_bearing = fp - > getBearing ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr ) ;
//cerr << "Bearing = " << calc_bearing << endl;
2007-06-10 06:06:57 +00:00
if ( speed < 0 ) {
2007-06-09 11:49:16 +00:00
calc_bearing + = 180 ;
if ( calc_bearing > 360 )
calc_bearing - = 360 ;
}
2007-06-10 06:06:57 +00:00
if ( finite ( calc_bearing ) ) {
2007-06-09 11:49:16 +00:00
double hdg_error = calc_bearing - tgt_heading ;
2007-07-10 07:01:54 +00:00
if ( fabs ( hdg_error ) > 0.01 ) {
2007-06-09 11:49:16 +00:00
TurnTo ( calc_bearing ) ;
}
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
cerr < < " calc_bearing is not a finite number : "
2007-06-10 06:06:57 +00:00
< < " Speed " < < speed
< < " pos : " < < pos . getLatitudeDeg ( ) < < " , " < < pos . getLongitudeDeg ( )
2011-07-31 19:27:44 +02:00
< < " waypoint " < < curr - > getLatitude ( ) < < " , " < < curr - > getLongitude ( ) < < endl ;
cerr < < " waypoint name " < < curr - > getName ( ) ;
2007-06-09 11:49:16 +00:00
exit ( 1 ) ; // FIXME
}
}
/**
* Update the lead distance calculation if speed has changed sufficiently
* to prevent spinning ( hopefully ) ;
*
* @ param curr
* @ param next
*/
2011-07-31 19:27:44 +02:00
void FGAIAircraft : : controlSpeed ( FGAIWaypoint * curr , FGAIWaypoint * next ) {
2007-06-09 11:49:16 +00:00
double speed_diff = speed - prevSpeed ;
2007-06-10 06:06:57 +00:00
if ( fabs ( speed_diff ) > 10 ) {
2007-06-09 11:49:16 +00:00
prevSpeed = speed ;
2007-07-10 07:01:54 +00:00
if ( next ) {
fp - > setLeadDistance ( speed , tgt_heading , curr , next ) ;
}
2007-06-09 11:49:16 +00:00
}
}
/**
* Update target values ( heading , alt , speed ) depending on flight plan or control properties
*/
2010-02-19 00:31:38 +00:00
void FGAIAircraft : : updatePrimaryTargetValues ( bool & flightplanActive , bool & aiOutOfSight ) {
2007-06-09 11:49:16 +00:00
if ( fp ) // AI object has a flightplan
{
//TODO make this a function of AIBase
time_t now = time ( NULL ) + fgGetLong ( " /sim/time/warp " ) ;
//cerr << "UpateTArgetValues() " << endl;
ProcessFlightPlan ( dt , now ) ;
2007-07-21 12:29:09 +00:00
// Do execute Ground elev for inactive aircraft, so they
// Are repositioned to the correct ground altitude when the user flies within visibility range.
// In addition, check whether we are out of user range, so this aircraft
// can be deleted.
if ( onGround ( ) ) {
2007-06-09 11:49:16 +00:00
Transform ( ) ; // make sure aip is initialized.
2007-07-21 12:29:09 +00:00
getGroundElev ( dt ) ;
doGroundAltitude ( ) ;
// Transform();
pos . setElevationFt ( altitude_ft ) ;
}
if ( trafficRef ) {
//cerr << trafficRef->getRegistration() << " Setting altitude to " << altitude_ft;
2010-02-19 00:31:38 +00:00
aiOutOfSight = ! aiTrafficVisible ( ) ;
if ( aiOutOfSight ) {
2007-07-21 12:29:09 +00:00
setDie ( true ) ;
//cerr << trafficRef->getRegistration() << " is set to die " << endl;
2010-02-19 00:31:38 +00:00
aiOutOfSight = true ;
return ;
2007-06-09 11:49:16 +00:00
}
2007-07-21 12:29:09 +00:00
}
2008-07-13 12:51:06 +00:00
timeElapsed = now - fp - > getStartTime ( ) ;
2010-02-19 00:31:38 +00:00
flightplanActive = fp - > isActive ( now ) ;
2007-07-21 12:29:09 +00:00
} else {
2007-06-09 11:49:16 +00:00
// no flight plan, update target heading, speed, and altitude
// from control properties. These default to the initial
// settings in the config file, but can be changed "on the
// fly".
string lat_mode = props - > getStringValue ( " controls/flight/lateral-mode " ) ;
2007-06-10 06:06:57 +00:00
if ( lat_mode = = " roll " ) {
2007-06-09 11:49:16 +00:00
double angle
2007-06-10 06:06:57 +00:00
= props - > getDoubleValue ( " controls/flight/target-roll " ) ;
2007-06-09 11:49:16 +00:00
RollTo ( angle ) ;
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
double angle
2007-06-10 06:06:57 +00:00
= props - > getDoubleValue ( " controls/flight/target-hdg " ) ;
2007-06-09 11:49:16 +00:00
TurnTo ( angle ) ;
}
string lon_mode
2007-06-10 06:06:57 +00:00
= props - > getStringValue ( " controls/flight/longitude-mode " ) ;
if ( lon_mode = = " alt " ) {
2007-06-09 11:49:16 +00:00
double alt = props - > getDoubleValue ( " controls/flight/target-alt " ) ;
ClimbTo ( alt ) ;
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
double angle
2007-06-10 06:06:57 +00:00
= props - > getDoubleValue ( " controls/flight/target-pitch " ) ;
2007-06-09 11:49:16 +00:00
PitchTo ( angle ) ;
}
AccelTo ( props - > getDoubleValue ( " controls/flight/target-spd " ) ) ;
}
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : updatePosition ( ) {
2007-06-09 11:49:16 +00:00
// convert speed to degrees per second
double speed_north_deg_sec = cos ( hdg * SGD_DEGREES_TO_RADIANS )
2007-06-10 06:06:57 +00:00
* speed * 1.686 / ft_per_deg_lat ;
2007-06-09 11:49:16 +00:00
double speed_east_deg_sec = sin ( hdg * SGD_DEGREES_TO_RADIANS )
2007-06-10 06:06:57 +00:00
* speed * 1.686 / ft_per_deg_lon ;
2007-06-09 11:49:16 +00:00
// set new position
pos . setLatitudeDeg ( pos . getLatitudeDeg ( ) + speed_north_deg_sec * dt ) ;
pos . setLongitudeDeg ( pos . getLongitudeDeg ( ) + speed_east_deg_sec * dt ) ;
}
2007-06-10 06:06:57 +00:00
void FGAIAircraft : : updateHeading ( ) {
2007-06-09 11:49:16 +00:00
// adjust heading based on current bank angle
if ( roll = = 0.0 )
roll = 0.01 ;
2007-06-10 06:06:57 +00:00
if ( roll ! = 0.0 ) {
2007-06-09 11:49:16 +00:00
// double turnConstant;
//if (no_roll)
// turnConstant = 0.0088362;
//else
// turnConstant = 0.088362;
// If on ground, calculate heading change directly
2007-06-28 07:47:20 +00:00
if ( onGround ( ) ) {
2007-06-09 11:49:16 +00:00
double headingDiff = fabs ( hdg - tgt_heading ) ;
2008-04-02 19:01:48 +00:00
double bank_sense = 0.0 ;
/*
double diff = fabs ( hdg - tgt_heading ) ;
if ( diff > 180 )
diff = fabs ( diff - 360 ) ;
double sum = hdg + diff ;
if ( sum > 360.0 )
sum - = 360.0 ;
if ( fabs ( sum - tgt_heading ) < 1.0 ) {
bank_sense = 1.0 ; // right turn
} else {
bank_sense = - 1.0 ; // left turn
} */
2007-06-09 11:49:16 +00:00
if ( headingDiff > 180 )
headingDiff = fabs ( headingDiff - 360 ) ;
2008-04-02 19:01:48 +00:00
double sum = hdg + headingDiff ;
if ( sum > 360.0 )
sum - = 360.0 ;
if ( fabs ( sum - tgt_heading ) > 0.0001 ) {
bank_sense = - 1.0 ;
} else {
bank_sense = 1.0 ;
}
2008-07-13 12:51:06 +00:00
//if (trafficRef)
2011-04-19 18:01:24 +02:00
// cerr << trafficRef->getCallSign() << " Heading "
// << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
2008-04-02 19:01:48 +00:00
//if (headingDiff > 60) {
groundTargetSpeed = tgt_speed ; // * cos(headingDiff * SG_DEGREES_TO_RADIANS);
//groundTargetSpeed = tgt_speed - tgt_speed * (headingDiff/180);
//} else {
// groundTargetSpeed = tgt_speed;
//}
2007-06-09 11:49:16 +00:00
if ( sign ( groundTargetSpeed ) ! = sign ( tgt_speed ) )
groundTargetSpeed = 0.21 * sign ( tgt_speed ) ; // to prevent speed getting stuck in 'negative' mode
2011-04-19 18:01:24 +02:00
// Only update the target values when we're not moving because otherwise we might introduce an enormous target change rate while waiting a the gate, or holding.
if ( speed ! = 0 ) {
if ( headingDiff > 30.0 ) {
// invert if pushed backward
headingChangeRate + = 10.0 * dt * sign ( roll ) ;
// Clamp the maximum steering rate to 30 degrees per second,
// But only do this when the heading error is decreasing.
if ( ( headingDiff < headingError ) ) {
if ( headingChangeRate > 30 )
headingChangeRate = 30 ;
else if ( headingChangeRate < - 30 )
headingChangeRate = - 30 ;
}
} else {
if ( speed ! = 0 ) {
if ( fabs ( headingChangeRate ) > headingDiff )
headingChangeRate = headingDiff * sign ( roll ) ;
else
headingChangeRate + = dt * sign ( roll ) ;
}
2008-04-02 19:01:48 +00:00
}
2007-06-09 11:49:16 +00:00
}
2011-04-19 18:01:24 +02:00
if ( trafficRef )
2011-05-07 10:03:27 +02:00
//cerr << trafficRef->getCallSign() << " Heading "
// << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << "Heading change rate : " << headingChangeRate << " bacnk sence " << bank_sense << endl;
2011-04-19 18:01:24 +02:00
hdg + = headingChangeRate * dt * sqrt ( fabs ( speed ) / 15 ) ;
2008-04-02 19:01:48 +00:00
headingError = headingDiff ;
2007-06-10 06:06:57 +00:00
} else {
if ( fabs ( speed ) > 1.0 ) {
2007-06-09 11:49:16 +00:00
turn_radius_ft = 0.088362 * speed * speed
2007-06-10 06:06:57 +00:00
/ tan ( fabs ( roll ) / SG_RADIANS_TO_DEGREES ) ;
} else {
2007-06-09 11:49:16 +00:00
// Check if turn_radius_ft == 0; this might lead to a division by 0.
turn_radius_ft = 1.0 ;
}
double turn_circum_ft = SGD_2PI * turn_radius_ft ;
double dist_covered_ft = speed * 1.686 * dt ;
double alpha = dist_covered_ft / turn_circum_ft * 360.0 ;
hdg + = alpha * sign ( roll ) ;
}
2007-06-10 06:06:57 +00:00
while ( hdg > 360.0 ) {
2007-06-09 11:49:16 +00:00
hdg - = 360.0 ;
spinCounter + + ;
}
2007-06-10 06:06:57 +00:00
while ( hdg < 0.0 ) {
2007-06-09 11:49:16 +00:00
hdg + = 360.0 ;
spinCounter - - ;
}
}
}
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : updateBankAngleTarget ( ) {
2007-06-09 11:49:16 +00:00
// adjust target bank angle if heading lock engaged
2007-06-10 06:06:57 +00:00
if ( hdg_lock ) {
2007-06-09 11:49:16 +00:00
double bank_sense = 0.0 ;
double diff = fabs ( hdg - tgt_heading ) ;
if ( diff > 180 )
diff = fabs ( diff - 360 ) ;
double sum = hdg + diff ;
if ( sum > 360.0 )
sum - = 360.0 ;
2007-06-10 06:06:57 +00:00
if ( fabs ( sum - tgt_heading ) < 1.0 ) {
2007-06-09 11:49:16 +00:00
bank_sense = 1.0 ; // right turn
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
bank_sense = - 1.0 ; // left turn
}
2007-06-28 07:47:20 +00:00
if ( diff < _performance - > maximumBankAngle ( ) ) {
2007-06-09 11:49:16 +00:00
tgt_roll = diff * bank_sense ;
2007-06-10 06:06:57 +00:00
} else {
2007-06-28 07:47:20 +00:00
tgt_roll = _performance - > maximumBankAngle ( ) * bank_sense ;
2007-06-09 11:49:16 +00:00
}
2007-06-28 07:47:20 +00:00
if ( ( fabs ( ( double ) spinCounter ) > 1 ) & & ( diff > _performance - > maximumBankAngle ( ) ) ) {
2007-06-09 11:49:16 +00:00
tgt_speed * = 0.999 ; // Ugly hack: If aircraft get stuck, they will continually spin around.
// The only way to resolve this is to make them slow down.
}
}
}
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : updateVerticalSpeedTarget ( ) {
2007-06-09 11:49:16 +00:00
// adjust target Altitude, based on ground elevation when on ground
2007-06-28 07:47:20 +00:00
if ( onGround ( ) ) {
2007-06-09 11:49:16 +00:00
getGroundElev ( dt ) ;
doGroundAltitude ( ) ;
2007-06-28 07:47:20 +00:00
} else if ( alt_lock ) {
// find target vertical speed
if ( use_perf_vs ) {
2007-06-10 06:06:57 +00:00
if ( altitude_ft < tgt_altitude_ft ) {
2007-06-09 11:49:16 +00:00
tgt_vs = tgt_altitude_ft - altitude_ft ;
2007-06-28 07:47:20 +00:00
if ( tgt_vs > _performance - > climbRate ( ) )
tgt_vs = _performance - > climbRate ( ) ;
2007-06-10 06:06:57 +00:00
} else {
2007-06-09 11:49:16 +00:00
tgt_vs = tgt_altitude_ft - altitude_ft ;
2007-06-28 07:47:20 +00:00
if ( tgt_vs < ( - _performance - > descentRate ( ) ) )
tgt_vs = - _performance - > descentRate ( ) ;
2007-06-09 11:49:16 +00:00
}
2007-06-28 07:47:20 +00:00
} else {
2007-06-09 11:49:16 +00:00
double max_vs = 4 * ( tgt_altitude_ft - altitude_ft ) ;
double min_vs = 100 ;
if ( tgt_altitude_ft < altitude_ft )
min_vs = - 100.0 ;
if ( ( fabs ( tgt_altitude_ft - altitude_ft ) < 1500.0 )
2007-06-10 06:06:57 +00:00
& & ( fabs ( max_vs ) < fabs ( tgt_vs ) ) )
2007-06-09 11:49:16 +00:00
tgt_vs = max_vs ;
if ( fabs ( tgt_vs ) < fabs ( min_vs ) )
tgt_vs = min_vs ;
}
2007-06-28 07:47:20 +00:00
} //else
// tgt_vs = 0.0;
2011-01-17 23:33:54 +01:00
checkTcas ( ) ;
2007-06-28 07:47:20 +00:00
}
void FGAIAircraft : : updatePitchAngleTarget ( ) {
// if on ground and above vRotate -> initial rotation
if ( onGround ( ) & & ( speed > _performance - > vRotate ( ) ) )
tgt_pitch = 8.0 ; // some rough B737 value
//TODO pitch angle on approach and landing
// match pitch angle to vertical speed
else if ( tgt_vs > 0 ) {
tgt_pitch = tgt_vs * 0.005 ;
} else {
tgt_pitch = tgt_vs * 0.002 ;
2007-06-09 11:49:16 +00:00
}
}
2008-07-13 12:51:06 +00:00
string FGAIAircraft : : atGate ( ) {
string tmp ( " " ) ;
if ( fp - > getLeg ( ) < 3 ) {
if ( trafficRef ) {
if ( fp - > getGate ( ) > 0 ) {
FGParking * park =
trafficRef - > getDepartureAirport ( ) - > getDynamics ( ) - > getParking ( fp - > getGate ( ) ) ;
tmp = park - > getName ( ) ;
}
}
}
return tmp ;
}
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : handleATCRequests ( ) {
//TODO implement NullController for having no ATC to save the conditionals
if ( controller ) {
2011-04-03 17:58:16 +02:00
controller - > updateAircraftInformation ( getID ( ) ,
pos . getLatitudeDeg ( ) ,
pos . getLongitudeDeg ( ) ,
hdg ,
speed ,
altitude_ft , dt ) ;
2007-06-28 07:47:20 +00:00
processATC ( controller - > getInstruction ( getID ( ) ) ) ;
}
}
2007-06-09 11:49:16 +00:00
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : updateActualState ( ) {
//update current state
//TODO have a single tgt_speed and check speed limit on ground on setting tgt_speed
updatePosition ( ) ;
2007-06-09 11:49:16 +00:00
2007-06-28 07:47:20 +00:00
if ( onGround ( ) )
speed = _performance - > actualSpeed ( this , groundTargetSpeed , dt ) ;
else
2010-08-29 19:25:34 +02:00
speed = _performance - > actualSpeed ( this , ( tgt_speed * speedFraction ) , dt ) ;
2007-06-09 11:49:16 +00:00
2007-06-28 07:47:20 +00:00
updateHeading ( ) ;
roll = _performance - > actualBankAngle ( this , tgt_roll , dt ) ;
// adjust altitude (meters) based on current vertical speed (fpm)
altitude_ft + = vs / 60.0 * dt ;
pos . setElevationFt ( altitude_ft ) ;
vs = _performance - > actualVerticalSpeed ( this , tgt_vs , dt ) ;
pitch = _performance - > actualPitch ( this , tgt_pitch , dt ) ;
2007-06-09 11:49:16 +00:00
}
2007-06-28 07:47:20 +00:00
void FGAIAircraft : : updateSecondaryTargetValues ( ) {
// derived target state values
updateBankAngleTarget ( ) ;
updateVerticalSpeedTarget ( ) ;
updatePitchAngleTarget ( ) ;
2007-06-09 11:49:16 +00:00
2007-06-28 07:47:20 +00:00
//TODO calculate wind correction angle (tgt_yaw)
2006-08-26 07:22:20 +00:00
}
2010-08-29 19:25:34 +02:00
bool FGAIAircraft : : reachedEndOfCruise ( double & distance ) {
2011-07-31 19:27:44 +02:00
FGAIWaypoint * curr = fp - > getCurrentWaypoint ( ) ;
if ( curr - > getName ( ) = = string ( " BOD " ) ) {
2010-08-29 19:25:34 +02:00
double dist = fp - > getDistanceToGo ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr ) ;
double descentSpeed = ( getPerformance ( ) - > vDescent ( ) * SG_NM_TO_METER ) / 3600.0 ; // convert from kts to meter/s
double descentRate = ( getPerformance ( ) - > descentRate ( ) * SG_FEET_TO_METER ) / 60.0 ; // convert from feet/min to meter/s
double verticalDistance = ( ( altitude_ft - 2000.0 ) - trafficRef - > getArrivalAirport ( ) - > getElevation ( ) ) * SG_FEET_TO_METER ;
double descentTimeNeeded = verticalDistance / descentRate ;
double distanceCovered = descentSpeed * descentTimeNeeded ;
//cerr << "Tracking : " << fgGetString("/ai/track-callsign");
2011-10-03 20:54:58 +02:00
// if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
// cerr << "Checking for end of cruise stage for :" << trafficRef->getCallSign() << endl;
// cerr << "Descent rate : " << descentRate << endl;
// cerr << "Descent speed : " << descentSpeed << endl;
// cerr << "VerticalDistance : " << verticalDistance << ". Altitude : " << altitude_ft << ". Elevation " << trafficRef->getArrivalAirport()->getElevation() << endl;
// cerr << "DecentTimeNeeded : " << descentTimeNeeded << endl;
// cerr << "DistanceCovered : " << distanceCovered << endl;
// }
2010-08-29 19:25:34 +02:00
//cerr << "Distance = " << distance << endl;
distance = distanceCovered ;
if ( dist < distanceCovered ) {
2011-10-03 20:54:58 +02:00
// if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
// //exit(1);
// }
2010-08-29 19:25:34 +02:00
return true ;
} else {
return false ;
}
} else {
return false ;
}
}
void FGAIAircraft : : resetPositionFromFlightPlan ( )
{
// the one behind you
2011-07-31 19:27:44 +02:00
FGAIWaypoint * prev = 0 ;
2010-08-29 19:25:34 +02:00
// the one ahead
2011-07-31 19:27:44 +02:00
FGAIWaypoint * curr = 0 ;
2010-08-29 19:25:34 +02:00
// the next plus 1
2011-07-31 19:27:44 +02:00
FGAIWaypoint * next = 0 ;
2010-08-29 19:25:34 +02:00
prev = fp - > getPreviousWaypoint ( ) ;
curr = fp - > getCurrentWaypoint ( ) ;
next = fp - > getNextWaypoint ( ) ;
2011-07-31 19:27:44 +02:00
setLatitude ( prev - > getLatitude ( ) ) ;
setLongitude ( prev - > getLongitude ( ) ) ;
2010-08-29 19:25:34 +02:00
double tgt_heading = fp - > getBearing ( curr , next ) ;
setHeading ( tgt_heading ) ;
2011-07-31 19:27:44 +02:00
setAltitude ( prev - > getAltitude ( ) ) ;
setSpeed ( prev - > getSpeed ( ) ) ;
2010-08-29 19:25:34 +02:00
}
double FGAIAircraft : : getBearing ( double crse )
{
double hdgDiff = fabs ( hdg - crse ) ;
if ( hdgDiff > 180 )
hdgDiff = fabs ( hdgDiff - 360 ) ;
return hdgDiff ;
}
time_t FGAIAircraft : : checkForArrivalTime ( string wptName ) {
2011-07-31 19:27:44 +02:00
FGAIWaypoint * curr = 0 ;
2010-08-29 19:25:34 +02:00
curr = fp - > getCurrentWaypoint ( ) ;
double tracklength = fp - > checkTrackLength ( wptName ) ;
if ( tracklength > 0.1 ) {
tracklength + = fp - > getDistanceToGo ( pos . getLatitudeDeg ( ) , pos . getLongitudeDeg ( ) , curr ) ;
} else {
return 0 ;
}
time_t now = time ( NULL ) + fgGetLong ( " /sim/time/warp " ) ;
time_t arrivalTime = fp - > getArrivalTime ( ) ;
time_t ete = tracklength / ( ( speed * SG_NM_TO_METER ) / 3600.0 ) ;
time_t secondsToGo = arrivalTime - now ;
2011-10-03 20:54:58 +02:00
// if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
// cerr << "Checking arrival time: ete " << ete << ". Time to go : " << secondsToGo << ". Track length = " << tracklength << endl;
// }
2010-08-29 19:25:34 +02:00
return ( ete - secondsToGo ) ; // Positive when we're too slow...
2011-01-17 23:33:54 +01:00
}