Traffic improvements.
Make landings and takeoffs look more correct; tweak climb-out and touchdown phases in particular, so the turn to destination heading occurs earlier on climb out, and touchdown occurs close the GS transmitter / some distance down the runway from the beginning.
This commit is contained in:
parent
4e75587332
commit
c79e2465df
12 changed files with 324 additions and 312 deletions
|
@ -709,9 +709,9 @@ void FGAIAircraft::handleFirstWaypoint() {
|
|||
setAltitude(prev->getAltitude());
|
||||
|
||||
if (prev->getSpeed() > 0.0)
|
||||
setHeading(fp->getBearing(prev->getLatitude(), prev->getLongitude(), curr));
|
||||
setHeading(fp->getBearing(prev, curr));
|
||||
else
|
||||
setHeading(fp->getBearing(curr->getLatitude(), curr->getLongitude(), prev));
|
||||
setHeading(fp->getBearing(curr, prev));
|
||||
|
||||
// If next doesn't exist, as in incrementally created flightplans for
|
||||
// AI/Trafficmanager created plans,
|
||||
|
@ -799,7 +799,7 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
|
|||
// << " Ground target speed " << groundTargetSpeed << endl;
|
||||
double bearing = 0;
|
||||
// don't do bearing calculations for ground traffic
|
||||
bearing = getBearing(fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr));
|
||||
bearing = getBearing(fp->getBearing(pos, curr));
|
||||
if (bearing < minBearing) {
|
||||
minBearing = bearing;
|
||||
if (minBearing < 10) {
|
||||
|
@ -913,12 +913,11 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
|
|||
* @param curr
|
||||
*/
|
||||
void FGAIAircraft::controlHeading(FGAIWaypoint* curr) {
|
||||
double calc_bearing = fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
|
||||
double calc_bearing = fp->getBearing(pos, curr);
|
||||
//cerr << "Bearing = " << calc_bearing << endl;
|
||||
if (speed < 0) {
|
||||
calc_bearing +=180;
|
||||
if (calc_bearing > 360)
|
||||
calc_bearing -= 360;
|
||||
SG_NORMALIZE_RANGE(calc_bearing, 0.0, 360.0);
|
||||
}
|
||||
|
||||
if (finite(calc_bearing)) {
|
||||
|
@ -1023,19 +1022,6 @@ void FGAIAircraft::updatePrimaryTargetValues(bool& flightplanActive, bool& aiOut
|
|||
}
|
||||
}
|
||||
|
||||
void FGAIAircraft::updatePosition() {
|
||||
// convert speed to degrees per second
|
||||
double speed_north_deg_sec = cos( hdg * SGD_DEGREES_TO_RADIANS )
|
||||
* speed * 1.686 / ft_per_deg_lat;
|
||||
double speed_east_deg_sec = sin( hdg * SGD_DEGREES_TO_RADIANS )
|
||||
* speed * 1.686 / ft_per_deg_lon;
|
||||
|
||||
// set new position
|
||||
pos.setLatitudeDeg( pos.getLatitudeDeg() + speed_north_deg_sec * dt);
|
||||
pos.setLongitudeDeg( pos.getLongitudeDeg() + speed_east_deg_sec * dt);
|
||||
}
|
||||
|
||||
|
||||
void FGAIAircraft::updateHeading() {
|
||||
// adjust heading based on current bank angle
|
||||
if (roll == 0.0)
|
||||
|
@ -1181,13 +1167,9 @@ void FGAIAircraft::updateVerticalSpeedTarget() {
|
|||
// find target vertical speed
|
||||
if (use_perf_vs) {
|
||||
if (altitude_ft < tgt_altitude_ft) {
|
||||
tgt_vs = tgt_altitude_ft - altitude_ft;
|
||||
if (tgt_vs > _performance->climbRate())
|
||||
tgt_vs = _performance->climbRate();
|
||||
tgt_vs = std::min(tgt_altitude_ft - altitude_ft, _performance->climbRate());
|
||||
} else {
|
||||
tgt_vs = tgt_altitude_ft - altitude_ft;
|
||||
if (tgt_vs < (-_performance->descentRate()))
|
||||
tgt_vs = -_performance->descentRate();
|
||||
tgt_vs = std::max(tgt_altitude_ft - altitude_ft, -_performance->descentRate());
|
||||
}
|
||||
} else {
|
||||
double vert_dist_ft = fp->getCurrentWaypoint()->getCrossat() - altitude_ft;
|
||||
|
@ -1265,7 +1247,9 @@ void FGAIAircraft::handleATCRequests() {
|
|||
void FGAIAircraft::updateActualState() {
|
||||
//update current state
|
||||
//TODO have a single tgt_speed and check speed limit on ground on setting tgt_speed
|
||||
updatePosition();
|
||||
double distance = speed * SG_KT_TO_MPS * dt;
|
||||
pos = SGGeodesy::direct(pos, hdg, distance);
|
||||
|
||||
|
||||
if (onGround())
|
||||
speed = _performance->actualSpeed(this, groundTargetSpeed, dt, holdPos);
|
||||
|
|
|
@ -148,7 +148,6 @@ private:
|
|||
void updatePrimaryTargetValues(bool& flightplanActive, bool& aiOutOfSight);
|
||||
|
||||
void updateSecondaryTargetValues();
|
||||
void updatePosition();
|
||||
void updateHeading();
|
||||
void updateBankAngleTarget();
|
||||
void updateVerticalSpeedTarget();
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <Main/fg_init.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
|
||||
|
@ -124,45 +125,8 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename)
|
|||
lastNodeVisited = 0;
|
||||
taxiRoute = 0;
|
||||
|
||||
SGPath path( globals->get_fg_root() );
|
||||
path.append( ("/AI/FlightPlans/" + filename).c_str() );
|
||||
SGPropertyNode root;
|
||||
|
||||
try {
|
||||
readProperties(path.str(), &root);
|
||||
} catch (const sg_exception &) {
|
||||
SG_LOG(SG_AI, SG_ALERT,
|
||||
"Error reading AI flight plan: " << path.str());
|
||||
// cout << path.str() << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode * node = root.getNode("flightplan");
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
//cout << "Reading waypoint " << i << endl;
|
||||
FGAIWaypoint* wpt = new FGAIWaypoint;
|
||||
SGPropertyNode * wpt_node = node->getChild(i);
|
||||
wpt->setName (wpt_node->getStringValue("name", "END" ));
|
||||
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
|
||||
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
|
||||
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
|
||||
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
|
||||
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
|
||||
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
|
||||
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
|
||||
wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false ));
|
||||
wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0 ));
|
||||
wpt->setTime (wpt_node->getStringValue("time", "" ));
|
||||
|
||||
if (wpt->getName() == "END") wpt->setFinished(true);
|
||||
else wpt->setFinished(false);
|
||||
|
||||
pushBackWaypoint( wpt );
|
||||
}
|
||||
|
||||
wpt_iterator = waypoints.begin();
|
||||
isValid = true;
|
||||
//cout << waypoints.size() << " waypoints read." << endl;
|
||||
isValid = parseProperties(filename);
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,7 +150,9 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
|
|||
double speed,
|
||||
const string& fltType,
|
||||
const string& acType,
|
||||
const string& airline)
|
||||
const string& airline) :
|
||||
departure(dep),
|
||||
arrival(arr)
|
||||
{
|
||||
sid = 0;
|
||||
repeat = false;
|
||||
|
@ -199,99 +165,110 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
|
|||
lastNodeVisited = 0;
|
||||
taxiRoute = 0;
|
||||
|
||||
SGPath path( globals->get_fg_root() );
|
||||
path.append( "/AI/FlightPlans" );
|
||||
path.append( p );
|
||||
|
||||
SGPropertyNode root;
|
||||
isValid = true;
|
||||
|
||||
// This is a bit of a hack:
|
||||
// Normally the value of course will be used to evaluate whether
|
||||
// or not a waypoint will be used for midair initialization of
|
||||
// an AI aircraft. However, if a course value of 999 will be passed
|
||||
// when an update request is received, which will by definition always be
|
||||
// on the ground and should include all waypoints.
|
||||
// bool useInitialWayPoint = true;
|
||||
// bool useCurrentWayPoint = false;
|
||||
// if (course == 999)
|
||||
// {
|
||||
// useInitialWayPoint = false;
|
||||
// useCurrentWayPoint = true;
|
||||
// }
|
||||
|
||||
if (path.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
readProperties(path.str(), &root);
|
||||
|
||||
SGPropertyNode * node = root.getNode("flightplan");
|
||||
|
||||
//pushBackWaypoint( init_waypoint );
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
//cout << "Reading waypoint " << i << endl;
|
||||
FGAIWaypoint* wpt = new FGAIWaypoint;
|
||||
SGPropertyNode * wpt_node = node->getChild(i);
|
||||
wpt->setName (wpt_node->getStringValue("name", "END" ));
|
||||
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
|
||||
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
|
||||
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
|
||||
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
|
||||
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
|
||||
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
|
||||
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
|
||||
|
||||
if (wpt->getName() == "END") wpt->setFinished(true);
|
||||
else wpt->setFinished(false);
|
||||
pushBackWaypoint(wpt);
|
||||
} // of node loop
|
||||
wpt_iterator = waypoints.begin();
|
||||
} catch (const sg_exception &e) {
|
||||
SG_LOG(SG_AI, SG_WARN, "Error reading AI flight plan: " <<
|
||||
e.getMessage() << " from " << e.getOrigin());
|
||||
}
|
||||
if (parseProperties(p)) {
|
||||
isValid = true;
|
||||
} else {
|
||||
// cout << path.str() << endl;
|
||||
// cout << "Trying to create this plan dynamically" << endl;
|
||||
// cout << "Route from " << dep->id << " to " << arr->id << endl;
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
time_t timeDiff = now-start;
|
||||
leg = 1;
|
||||
|
||||
if ((timeDiff > 60) && (timeDiff < 1500))
|
||||
leg = 2;
|
||||
//else if ((timeDiff >= 1200) && (timeDiff < 1500)) {
|
||||
//leg = 3;
|
||||
//ac->setTakeOffStatus(2);
|
||||
//}
|
||||
else if ((timeDiff >= 1500) && (timeDiff < 2000))
|
||||
leg = 4;
|
||||
else if (timeDiff >= 2000)
|
||||
leg = 5;
|
||||
/*
|
||||
if (timeDiff >= 2000)
|
||||
leg = 5;
|
||||
*/
|
||||
SG_LOG(SG_AI, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
|
||||
wpt_iterator = waypoints.begin();
|
||||
bool dist = 0;
|
||||
isValid = create(ac, dep,arr, leg, alt, speed, lat, lon,
|
||||
firstLeg, radius, fltType, acType, airline, dist);
|
||||
wpt_iterator = waypoints.begin();
|
||||
}
|
||||
|
||||
createWaypoints(ac, course, start, dep, arr, firstLeg, radius,
|
||||
alt, lat, lon, speed, fltType, acType, airline);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FGAIFlightPlan::~FGAIFlightPlan()
|
||||
{
|
||||
deleteWaypoints();
|
||||
delete taxiRoute;
|
||||
|
||||
// if we're parked at a gate, release it
|
||||
if (gateId >= 0) {
|
||||
FGAirport* apt = (leg >= 7) ? arrival : departure;
|
||||
if (apt) {
|
||||
SG_LOG(SG_AI, SG_INFO, "releasing parking gate " << gateId << " at " << apt->ident());
|
||||
apt->getDynamics()->releaseParking(gateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FGAIFlightPlan::createWaypoints(FGAIAircraft *ac,
|
||||
double course,
|
||||
time_t start,
|
||||
FGAirport *dep,
|
||||
FGAirport *arr,
|
||||
bool firstLeg,
|
||||
double radius,
|
||||
double alt,
|
||||
double lat,
|
||||
double lon,
|
||||
double speed,
|
||||
const string& fltType,
|
||||
const string& acType,
|
||||
const string& airline)
|
||||
{
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
time_t timeDiff = now-start;
|
||||
leg = 1;
|
||||
|
||||
if ((timeDiff > 60) && (timeDiff < 1500))
|
||||
leg = 2;
|
||||
//else if ((timeDiff >= 1200) && (timeDiff < 1500)) {
|
||||
//leg = 3;
|
||||
//ac->setTakeOffStatus(2);
|
||||
//}
|
||||
else if ((timeDiff >= 1500) && (timeDiff < 2000))
|
||||
leg = 4;
|
||||
else if (timeDiff >= 2000)
|
||||
leg = 5;
|
||||
/*
|
||||
if (timeDiff >= 2000)
|
||||
leg = 5;
|
||||
*/
|
||||
SG_LOG(SG_AI, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
|
||||
wpt_iterator = waypoints.begin();
|
||||
bool dist = 0;
|
||||
isValid = create(ac, dep, arr, leg, alt, speed, lat, lon,
|
||||
firstLeg, radius, fltType, acType, airline, dist);
|
||||
wpt_iterator = waypoints.begin();
|
||||
|
||||
}
|
||||
|
||||
bool FGAIFlightPlan::parseProperties(const std::string& filename)
|
||||
{
|
||||
SGPath path( globals->get_fg_root() );
|
||||
path.append( "/AI/FlightPlans/" + filename );
|
||||
if (!path.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SGPropertyNode root;
|
||||
try {
|
||||
readProperties(path.str(), &root);
|
||||
} catch (const sg_exception &e) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "Error reading AI flight plan: " << path.str()
|
||||
<< "message:" << e.getFormattedMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
SGPropertyNode * node = root.getNode("flightplan");
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
FGAIWaypoint* wpt = new FGAIWaypoint;
|
||||
SGPropertyNode * wpt_node = node->getChild(i);
|
||||
wpt->setName (wpt_node->getStringValue("name", "END" ));
|
||||
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
|
||||
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
|
||||
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
|
||||
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
|
||||
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
|
||||
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
|
||||
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
|
||||
wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false ));
|
||||
wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0 ));
|
||||
wpt->setTime (wpt_node->getStringValue("time", "" ));
|
||||
wpt->setFinished ((wpt->getName() == "END"));
|
||||
pushBackWaypoint( wpt );
|
||||
}
|
||||
|
||||
wpt_iterator = waypoints.begin();
|
||||
return true;
|
||||
}
|
||||
|
||||
FGAIWaypoint* const FGAIFlightPlan::getPreviousWaypoint( void ) const
|
||||
{
|
||||
|
@ -425,10 +402,9 @@ double FGAIFlightPlan::getBearing(FGAIWaypoint* first, FGAIWaypoint* second) con
|
|||
return SGGeodesy::courseDeg(first->getPos(), second->getPos());
|
||||
}
|
||||
|
||||
|
||||
double FGAIFlightPlan::getBearing(double lat, double lon, FGAIWaypoint* wp) const
|
||||
double FGAIFlightPlan::getBearing(const SGGeod& aPos, FGAIWaypoint* wp) const
|
||||
{
|
||||
return SGGeodesy::courseDeg(SGGeod::fromDeg(lon, lat), wp->getPos());
|
||||
return SGGeodesy::courseDeg(aPos, wp->getPos());
|
||||
}
|
||||
|
||||
void FGAIFlightPlan::deleteWaypoints()
|
||||
|
|
|
@ -19,16 +19,21 @@
|
|||
#ifndef _FG_AIFLIGHTPLAN_HXX
|
||||
#define _FG_AIFLIGHTPLAN_HXX
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
// forward decls
|
||||
class FGTaxiRoute;
|
||||
class FGRunway;
|
||||
class FGAIAircraft;
|
||||
class FGAirport;
|
||||
|
||||
typedef SGSharedPtr<FGAirport> FGAirportRef;
|
||||
|
||||
class FGAIWaypoint {
|
||||
private:
|
||||
std::string name;
|
||||
|
@ -121,7 +126,8 @@ public:
|
|||
void setLeadDistance(double distance_ft);
|
||||
double getLeadDistance( void ) const {return lead_distance;}
|
||||
double getBearing(FGAIWaypoint* previous, FGAIWaypoint* next) const;
|
||||
double getBearing(double lat, double lon, FGAIWaypoint* next) const;
|
||||
double getBearing(const SGGeod& aPos, FGAIWaypoint* next) const;
|
||||
|
||||
double checkTrackLength(std::string wptName);
|
||||
time_t getStartTime() const { return start_time; }
|
||||
time_t getArrivalTime() const { return arrivalTime; }
|
||||
|
@ -187,9 +193,10 @@ private:
|
|||
FGTaxiRoute *taxiRoute;
|
||||
std::string name;
|
||||
bool isValid;
|
||||
|
||||
FGAirportRef departure, arrival;
|
||||
|
||||
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double radius, const std::string&, const std::string&, const std::string&);
|
||||
bool createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
|
||||
bool createClimb(FGAIAircraft *, bool, FGAirport *, FGAirport* arrival, double, double, const std::string&);
|
||||
bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
|
||||
bool createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
|
||||
bool createLanding(FGAIAircraft *, FGAirport *, const std::string&);
|
||||
|
@ -214,6 +221,28 @@ private:
|
|||
|
||||
//void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);
|
||||
void evaluateRoutePart(double deplat, double deplon, double arrlat, double arrlon);
|
||||
|
||||
/**
|
||||
* look for and parse an PropertyList flight-plan file - essentially
|
||||
* a flat list waypoint objects, encoded to properties
|
||||
*/
|
||||
bool parseProperties(const std::string& filename);
|
||||
|
||||
void createWaypoints(FGAIAircraft *ac,
|
||||
double course,
|
||||
time_t start,
|
||||
FGAirport *dep,
|
||||
FGAirport *arr,
|
||||
bool firstLeg,
|
||||
double radius,
|
||||
double alt,
|
||||
double lat,
|
||||
double lon,
|
||||
double speed,
|
||||
const std::string& fltType,
|
||||
const std::string& acType,
|
||||
const std::string& airline);
|
||||
|
||||
public:
|
||||
wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
|
||||
wpt_vector_iterator getLastWayPoint() { return waypoints.end(); };
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Environment/environment.hxx>
|
||||
#include <FDM/LaRCsim/basic_aero.h>
|
||||
#include <Navaids/navrecord.hxx>
|
||||
|
||||
|
||||
/* FGAIFlightPlan::create()
|
||||
|
@ -78,7 +79,7 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
|
|||
retVal = createTakeOff(ac, firstFlight, dep, speed, fltType);
|
||||
break;
|
||||
case 4:
|
||||
retVal = createClimb(ac, firstFlight, dep, speed, alt, fltType);
|
||||
retVal = createClimb(ac, firstFlight, dep, arr, speed, alt, fltType);
|
||||
break;
|
||||
case 5:
|
||||
retVal = createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
|
||||
|
@ -460,20 +461,18 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
|
|||
const string & fltType)
|
||||
{
|
||||
const double ACCEL_POINT = 105.0;
|
||||
const double KNOTS_HOUR_TO_MSEC = SG_NM_TO_METER / 3600.0;
|
||||
// climb-out angle in degrees. could move this to the perf-db but this
|
||||
// value is pretty sane
|
||||
const double INITIAL_PITCH_ANGLE = 12.5;
|
||||
const double INITIAL_PITCH_ANGLE = 10.0;
|
||||
|
||||
double accel = ac->getPerformance()->acceleration();
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double vRotate = ac->getPerformance()->vRotate();
|
||||
double vTakeoff = ac->getPerformance()->vTakeoff();
|
||||
|
||||
double accelMetric = accel * KNOTS_HOUR_TO_MSEC;
|
||||
double vTaxiMetric = vTaxi * KNOTS_HOUR_TO_MSEC;
|
||||
double vRotateMetric = vRotate * KNOTS_HOUR_TO_MSEC;
|
||||
double vTakeoffMetric = vTakeoff * KNOTS_HOUR_TO_MSEC;
|
||||
double accelMetric = accel * SG_KT_TO_MPS;
|
||||
double vTaxiMetric = vTaxi * SG_KT_TO_MPS;
|
||||
double vRotateMetric = vRotate * SG_KT_TO_MPS;
|
||||
|
||||
FGAIWaypoint *wpt;
|
||||
// Get the current active runway, based on code from David Luff
|
||||
|
@ -498,7 +497,8 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
|
|||
wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
double vRef = vTakeoffMetric + 20; // climb-out at v2 + 20kts
|
||||
double vRef = vTakeoff + 20; // climb-out at v2 + 20kts
|
||||
|
||||
double gearUpDist = d + pitchDistance(INITIAL_PITCH_ANGLE, 400 * SG_FEET_TO_METER);
|
||||
accelPoint = rwy->pointOnCenterline(gearUpDist);
|
||||
|
||||
|
@ -509,14 +509,22 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
|
|||
wpt->setGear_down(false);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
// limit climbout speed to 240kts below 10000'
|
||||
double vClimbBelow10000 = std::min(240.0, ac->getPerformance()->vClimb());
|
||||
|
||||
// create two climb-out points. This is important becuase the first climb point will
|
||||
// be a (sometimes large) turn towards the destination, and we don't want to
|
||||
// commence that turn below 2000'
|
||||
double climbOut = d + pitchDistance(INITIAL_PITCH_ANGLE, 2000 * SG_FEET_TO_METER);
|
||||
accelPoint = rwy->pointOnCenterline(climbOut);
|
||||
wpt = createInAir(ac, "2000'", accelPoint, airportElev + 2000, vRef);
|
||||
wpt = createInAir(ac, "2000'", accelPoint, airportElev + 2000, vClimbBelow10000);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
climbOut = d + pitchDistance(INITIAL_PITCH_ANGLE, 2500 * SG_FEET_TO_METER);
|
||||
accelPoint = rwy->pointOnCenterline(climbOut);
|
||||
wpt = createInAir(ac, "2500'", accelPoint, airportElev + 2500, vClimbBelow10000);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
// as soon as we pass 2000', hand off to departure so the next acft can line up
|
||||
// ideally the next aircraft would be able to line-up + hold but that's tricky
|
||||
// with the current design.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -525,14 +533,14 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
|
|||
* initialize the Aircraft at the parking location
|
||||
******************************************************************/
|
||||
bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
|
||||
FGAirport * apt, double speed, double alt,
|
||||
FGAirport * apt, FGAirport* arrival,
|
||||
double speed, double alt,
|
||||
const string & fltType)
|
||||
{
|
||||
FGAIWaypoint *wpt;
|
||||
// bool planLoaded = false;
|
||||
string fPLName;
|
||||
// string fPLName;
|
||||
double vClimb = ac->getPerformance()->vClimb();
|
||||
|
||||
|
||||
if (firstFlight) {
|
||||
string rwyClass = getRunwayClassFromTrafficType(fltType);
|
||||
double heading = ac->getTrafficRef()->getCourse();
|
||||
|
@ -546,18 +554,23 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
|
|||
//cerr << " Cloning waypoint " << endl;
|
||||
}
|
||||
} else {
|
||||
FGRunway * rwy = apt->getRunwayByIdent(activeRunway);
|
||||
assert( rwy != NULL );
|
||||
|
||||
SGGeod climb1 = rwy->pointOnCenterline(10 * SG_NM_TO_METER);
|
||||
FGRunway* runway = apt->getRunwayByIdent(activeRunway);
|
||||
SGGeod cur = runway->end();
|
||||
if (!waypoints.empty()) {
|
||||
cur = waypoints.back()->getPos();
|
||||
}
|
||||
|
||||
// compute course towards destination
|
||||
double course = SGGeodesy::courseDeg(cur, arrival->geod());
|
||||
|
||||
SGGeod climb1 = SGGeodesy::direct(cur, course, 10 * SG_NM_TO_METER);
|
||||
wpt = createInAir(ac, "10000ft climb", climb1, 10000, vClimb);
|
||||
wpt->setGear_down(true);
|
||||
wpt->setFlaps_down(true);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
SGGeod climb2 = rwy->pointOnCenterline(20 * SG_NM_TO_METER);
|
||||
wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2);
|
||||
wpt->setAltitude(18000);
|
||||
SGGeod climb2 = SGGeodesy::direct(cur, course, 20 * SG_NM_TO_METER);
|
||||
wpt = createInAir(ac, "18000ft climb", climb2, 18000, vClimb);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
return true;
|
||||
|
@ -580,8 +593,6 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
|||
FGAIWaypoint *wpt;
|
||||
double vDescent = ac->getPerformance()->vDescent();
|
||||
double vApproach = ac->getPerformance()->vApproach();
|
||||
double vTouchdown = ac->getPerformance()->vTouchdown();
|
||||
|
||||
|
||||
//Beginning of Descent
|
||||
string rwyClass = getRunwayClassFromTrafficType(fltType);
|
||||
|
@ -827,34 +838,7 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
|||
|
||||
// The approach leg should bring the aircraft to approximately 4-6 nm out, after which the landing phase should take over.
|
||||
//cerr << "Phase 3: Approach" << endl;
|
||||
double tgt_speed = vApproach;
|
||||
distanceOut -= distanceCovered;
|
||||
double touchDownPoint = 0; //(rwy->lengthM() * 0.1);
|
||||
for (int i = 1; i < nPoints; i++) {
|
||||
SGGeod result;
|
||||
double currentDist = i * (distanceOut / nPoints);
|
||||
//double currentAltitude =
|
||||
// apt->getElevation() + 2000 - (i * 2000 / (nPoints-1));
|
||||
double alt = currentAltitude - (i * 2000 / (nPoints - 1));
|
||||
snprintf(buffer, 16, "final%03d", i);
|
||||
result = rwy->pointOnCenterline((-distanceOut) + currentDist + touchDownPoint);
|
||||
if (i == nPoints - 30) {
|
||||
tgt_speed = vTouchdown;
|
||||
}
|
||||
wpt = createInAir(ac, buffer, result, alt, tgt_speed);
|
||||
wpt->setCrossat(alt);
|
||||
wpt->setTrackLength((distanceOut / nPoints));
|
||||
// account for the extra distance due to an extended downwind leg
|
||||
if (i == 1) {
|
||||
wpt->setTrackLength(wpt->getTrackLength() + distanceCovered);
|
||||
}
|
||||
//cerr << "Track Length : " << wpt->trackLength;
|
||||
pushBackWaypoint(wpt);
|
||||
//if (apt->ident() == fgGetString("/sim/presets/airport-id")) {
|
||||
// cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << " " << apt->getElevation() << " " << distanceOut << endl;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
//cerr << "Done" << endl;
|
||||
|
||||
// Erase the two bogus BOD points: Note check for conflicts with scripted AI flightPlans
|
||||
|
@ -885,10 +869,31 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
|||
ac->resetPositionFromFlightPlan();
|
||||
}
|
||||
waypoints[1]->setName( (waypoints[1]->getName() + string("legend")));
|
||||
waypoints.back()->setName(waypoints.back()->getName() + "LandingThreshold");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* compute the distance along the centerline, to the ILS glideslope
|
||||
* transmitter. Return -1 if there's no GS for the runway
|
||||
*/
|
||||
static double runwayGlideslopeTouchdownDistance(FGRunway* rwy)
|
||||
{
|
||||
FGNavRecord* gs = rwy->glideslope();
|
||||
if (!gs) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SGVec3d runwayPosCart = SGVec3d::fromGeod(rwy->pointOnCenterline(0.0));
|
||||
// compute a unit vector in ECF cartesian space, from the runway beginning to the end
|
||||
SGVec3d runwayDirectionVec = normalize(SGVec3d::fromGeod(rwy->end()) - runwayPosCart);
|
||||
SGVec3d gsTransmitterVec = gs->cart() - runwayPosCart;
|
||||
|
||||
// project the gsTransmitterVec along the runwayDirctionVec to get out
|
||||
// final value (in metres)
|
||||
double dist = dot(runwayDirectionVec, gsTransmitterVec);
|
||||
return dist;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* CreateLanding
|
||||
* Create a flight path from the "permision to land" point (currently
|
||||
|
@ -902,108 +907,81 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
|
|||
double vTouchdown = ac->getPerformance()->vTouchdown();
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double decel = ac->getPerformance()->deceleration() * 1.4;
|
||||
|
||||
double vApproach = ac->getPerformance()->vApproach();
|
||||
|
||||
double vTouchdownMetric = (vTouchdown * SG_NM_TO_METER) / 3600;
|
||||
double vTaxiMetric = (vTaxi * SG_NM_TO_METER) / 3600;
|
||||
double decelMetric = (decel * SG_NM_TO_METER) / 3600;
|
||||
|
||||
//string rwyClass = getRunwayClassFromTrafficType(fltType);
|
||||
//double heading = ac->getTrafficRef()->getCourse();
|
||||
//apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
|
||||
//rwy = apt->getRunwayByIdent(activeRunway);
|
||||
|
||||
|
||||
FGAIWaypoint *wpt;
|
||||
//double aptElev = apt->getElevation();
|
||||
double currElev = 0;
|
||||
char buffer[12];
|
||||
FGRunway * rwy = apt->getRunwayByIdent(activeRunway);
|
||||
assert( rwy != NULL );
|
||||
SGGeod refPoint = rwy->pointOnCenterline(0);
|
||||
FGTaxiNode *tn = 0;
|
||||
if (apt->getDynamics()->getGroundNetwork()) {
|
||||
int node = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint);
|
||||
tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
SGGeod threshold = rwy->threshold();
|
||||
double currElev = threshold.getElevationFt();
|
||||
|
||||
double touchdownDistance = runwayGlideslopeTouchdownDistance(rwy);
|
||||
if (touchdownDistance < 0.0) {
|
||||
double landingLength = rwy->lengthM() - (rwy->displacedThresholdM());
|
||||
// touchdown 25% of the way along the landing area
|
||||
touchdownDistance = rwy->displacedThresholdM() + (landingLength * 0.25);
|
||||
}
|
||||
if (tn) {
|
||||
currElev = tn->getElevationFt(apt->getElevation());
|
||||
} else {
|
||||
currElev = apt->getElevation();
|
||||
}
|
||||
|
||||
|
||||
|
||||
SGGeod coord;
|
||||
|
||||
|
||||
/*double distanceOut = rwy->lengthM() * .1;
|
||||
double nPoints = 20;
|
||||
for (int i = 1; i < nPoints; i++) {
|
||||
snprintf(buffer, 12, "flare%d", i);
|
||||
double currentDist = i * (distanceOut / nPoints);
|
||||
double currentAltitude = apt->getElevation() + 20 - (i * 20 / nPoints);
|
||||
coord = rwy->pointOnCenterline((currentDist * (i / nPoints)));
|
||||
wpt = createInAir(ac, buffer, coord, currentAltitude, (vTouchdown));
|
||||
}*/
|
||||
double rolloutDistance =
|
||||
(vTouchdownMetric * vTouchdownMetric - vTaxiMetric * vTaxiMetric) / (2 * decelMetric);
|
||||
//cerr << " touchdown speed = " << vTouchdown << ". Rollout distance " << rolloutDistance << endl;
|
||||
// find glideslope entry point, 2000' above touchdown elevation
|
||||
double glideslopeEntry = -((2000 * SG_FEET_TO_METER) / tan(3.0)) + touchdownDistance;
|
||||
FGAIWaypoint *wpt = createInAir(ac, "Glideslope begin", rwy->pointOnCenterline(glideslopeEntry),
|
||||
currElev + 2000, vApproach);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
// deceleration point, 500' above touchdown elevation - slow from approach speed
|
||||
// to touchdown speed
|
||||
double decelPoint = -((500 * SG_FEET_TO_METER) / tan(3.0)) + touchdownDistance;
|
||||
wpt = createInAir(ac, "500' decel", rwy->pointOnCenterline(decelPoint),
|
||||
currElev + 2000, vTouchdown);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
// compute elevation above the runway start, based on a 3-degree glideslope
|
||||
double heightAboveRunwayStart = touchdownDistance *
|
||||
tan(3.0 * SG_DEGREES_TO_RADIANS) * SG_METER_TO_FEET;
|
||||
wpt = createInAir(ac, "CrossThreshold", rwy->begin(),
|
||||
heightAboveRunwayStart + currElev, vTouchdown);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
double rolloutDistance = accelDistance(vTouchdownMetric, vTaxiMetric, decelMetric);
|
||||
|
||||
int nPoints = 50;
|
||||
for (int i = 1; i < nPoints; i++) {
|
||||
snprintf(buffer, 12, "landing03%d", i);
|
||||
|
||||
coord = rwy->pointOnCenterline((rolloutDistance * ((double) i / (double) nPoints)));
|
||||
wpt = createOnGround(ac, buffer, coord, currElev, 2*vTaxi);
|
||||
double t = ((double) i) / nPoints;
|
||||
coord = rwy->pointOnCenterline(touchdownDistance + (rolloutDistance * t));
|
||||
double vel = (vTouchdownMetric * (1.0 - t)) + (vTaxiMetric * t);
|
||||
wpt = createOnGround(ac, buffer, coord, currElev, vel);
|
||||
wpt->setCrossat(currElev);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
|
||||
wpt->setSpeed(vTaxi);
|
||||
double mindist = 1.1 * rolloutDistance;
|
||||
double maxdist = rwy->lengthM();
|
||||
//cerr << "Finding nearest exit" << endl;
|
||||
double mindist = (1.1 * rolloutDistance) + touchdownDistance;
|
||||
|
||||
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
|
||||
if (gn) {
|
||||
double min = 0;
|
||||
for (int i = ceil(mindist); i < floor(maxdist); i++) {
|
||||
coord = rwy->pointOnCenterline(mindist);
|
||||
int nodeId = 0;
|
||||
if (gn->getVersion() > 0) {
|
||||
nodeId = gn->findNearestNodeOnRunway(coord);
|
||||
} else {
|
||||
nodeId = gn->findNearestNode(coord);
|
||||
}
|
||||
if (tn)
|
||||
tn = gn->findNode(nodeId);
|
||||
if (!tn)
|
||||
break;
|
||||
|
||||
double dist = SGGeodesy::distanceM(coord, tn->geod());
|
||||
if (dist < (min + 0.75)) {
|
||||
break;
|
||||
}
|
||||
min = dist;
|
||||
}
|
||||
if (tn) {
|
||||
wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
if (!gn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
coord = rwy->pointOnCenterline(mindist);
|
||||
int nodeId = 0;
|
||||
if (gn->getVersion() > 0) {
|
||||
nodeId = gn->findNearestNodeOnRunway(coord, rwy);
|
||||
} else {
|
||||
nodeId = gn->findNearestNode(coord);
|
||||
}
|
||||
|
||||
FGTaxiNode* tn = gn->findNode(nodeId);
|
||||
if (tn) {
|
||||
wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
//cerr << "Done. " << endl;
|
||||
|
||||
/*
|
||||
//Runway Threshold
|
||||
wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, vTouchdown);
|
||||
wpt->crossat = apt->getElevation();
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
// Roll-out
|
||||
wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, vTaxi*2);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
SGGeod rollOut = rwy->pointOnCenterline(rwy->lengthM() * 0.9);
|
||||
wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, vTaxi);
|
||||
wpt->crossat = apt->getElevation();
|
||||
pushBackWaypoint(wpt);
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
#include <AIModel/AIAircraft.hxx>
|
||||
#include <AIModel/performancedata.hxx>
|
||||
|
@ -455,7 +456,7 @@ int FGGroundNetwork::findNearestNode(const SGGeod & aGeod)
|
|||
return index;
|
||||
}
|
||||
|
||||
int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod)
|
||||
int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod, FGRunway* aRunway)
|
||||
{
|
||||
double minDist = HUGE_VAL;
|
||||
int index = -1;
|
||||
|
@ -465,6 +466,16 @@ int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod)
|
|||
if (!i->second->getIsOnRunway()) {
|
||||
continue;
|
||||
}
|
||||
// check point lies on the runway - i.e that course from aGeod to the
|
||||
// runway end, matches the runway heading
|
||||
if (aRunway) {
|
||||
double course = SGGeodesy::courseDeg(i->second->geod(), aRunway->end());
|
||||
double headingDiff = course - aRunway->headingDeg();
|
||||
SG_NORMALIZE_RANGE(headingDiff, -180.0, 180.0);
|
||||
if (fabs(headingDiff) > 3.0) { // 3 degrees tolerance
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
double d = SGGeodesy::distanceM(aGeod, i->second->geod());
|
||||
if (d < minDist) {
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
#include <list>
|
||||
#include <map>
|
||||
|
||||
class Block;
|
||||
|
||||
#include "gnnode.hxx"
|
||||
#include "parking.hxx"
|
||||
#include <ATC/trafficcontrol.hxx>
|
||||
|
||||
|
||||
class Block;
|
||||
class FGRunway;
|
||||
class FGTaxiSegment; // forward reference
|
||||
class FGAIFlightPlan; // forward reference
|
||||
class FGAirport; // forward reference
|
||||
|
@ -275,7 +275,7 @@ public:
|
|||
};
|
||||
|
||||
int findNearestNode(const SGGeod& aGeod);
|
||||
int findNearestNodeOnRunway(const SGGeod& aGeod);
|
||||
int findNearestNodeOnRunway(const SGGeod& aGeod, FGRunway* aRunway = NULL);
|
||||
|
||||
FGTaxiNode *findNode(unsigned idx);
|
||||
FGTaxiSegment *findSegment(unsigned idx);
|
||||
|
|
|
@ -149,6 +149,17 @@ FGNavRecord* FGRunway::ILS() const
|
|||
return (FGNavRecord*) flightgear::NavDataCache::instance()->loadById(_ils);
|
||||
}
|
||||
|
||||
FGNavRecord* FGRunway::glideslope() const
|
||||
{
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
||||
PositionedID gsId = cache->findNavaidForRunway(guid(), FGPositioned::GS);
|
||||
if (gsId == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (FGNavRecord*) cache->loadById(gsId);
|
||||
}
|
||||
|
||||
std::vector<flightgear::SID*> FGRunway::getSIDs() const
|
||||
{
|
||||
FGAirport* apt = airport();
|
||||
|
|
|
@ -108,6 +108,11 @@ public:
|
|||
|
||||
FGNavRecord* ILS() const;
|
||||
|
||||
/**
|
||||
* retrieve the associated glideslope transmitter, if one is defined.
|
||||
*/
|
||||
FGNavRecord* glideslope() const;
|
||||
|
||||
void setILS(PositionedID nav) { _ils = nav; }
|
||||
|
||||
FGRunway* reciprocalRunway() const;
|
||||
|
|
|
@ -528,6 +528,9 @@ public:
|
|||
findNavsByFreqNoPos = prepare("SELECT positioned.rowid FROM positioned, navaid WHERE "
|
||||
"positioned.rowid=navaid.rowid AND freq=?1 " AND_TYPED);
|
||||
|
||||
findNavaidForRunway = prepare("SELECT positioned.rowid FROM positioned, navaid WHERE "
|
||||
"positioned.rowid=navaid.rowid AND runway=?1 AND type=?2");
|
||||
|
||||
// for an octree branch, return the child octree nodes which exist,
|
||||
// described as a bit-mask
|
||||
getOctreeChildren = prepare("SELECT children FROM octree WHERE rowid=?1");
|
||||
|
@ -808,7 +811,7 @@ public:
|
|||
|
||||
sqlite3_stmt_ptr searchAirports;
|
||||
sqlite3_stmt_ptr findCommByFreq, findNavsByFreq,
|
||||
findNavsByFreqNoPos;
|
||||
findNavsByFreqNoPos, findNavaidForRunway;
|
||||
sqlite3_stmt_ptr getAirportItems, getAirportItemByIdent;
|
||||
sqlite3_stmt_ptr findAirportRunway,
|
||||
findILS;
|
||||
|
@ -1707,6 +1710,18 @@ AirwayEdgeVec NavDataCache::airwayEdgesFrom(int network, PositionedID pos)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PositionedID NavDataCache::findNavaidForRunway(PositionedID runway, FGPositioned::Type ty)
|
||||
{
|
||||
d->reset(d->findNavaidForRunway);
|
||||
sqlite3_bind_int64(d->findNavaidForRunway, 1, runway);
|
||||
sqlite3_bind_int(d->findNavaidForRunway, 2, ty);
|
||||
if (!d->execSelect(d->findNavaidForRunway)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sqlite3_column_int64(d->findNavaidForRunway, 0);
|
||||
}
|
||||
|
||||
} // of namespace flightgear
|
||||
|
||||
|
|
|
@ -140,6 +140,11 @@ public:
|
|||
/// returning results. Only used by TACAN carrier search
|
||||
PositionedIDVec findNavaidsByFreq(int freqKhz, FGPositioned::Filter* filt);
|
||||
|
||||
/**
|
||||
* Given a runway and type, find the corresponding navaid (ILS / GS / OM)
|
||||
*/
|
||||
PositionedID findNavaidForRunway(PositionedID runway, FGPositioned::Type ty);
|
||||
|
||||
/**
|
||||
* given a navaid name (or similar) from apt.dat / nav.dat, find the
|
||||
* corresponding airport and runway IDs.
|
||||
|
|
|
@ -200,15 +200,15 @@ void FGTrafficManager::shutdown()
|
|||
cachefile << "[TrafficManagerCachedata:ref:2011:09:04]" << endl;
|
||||
}
|
||||
}
|
||||
for (ScheduleVectorIterator sched = scheduledAircraft.begin();
|
||||
sched != scheduledAircraft.end(); sched++) {
|
||||
|
||||
BOOST_FOREACH(FGAISchedule* acft, scheduledAircraft) {
|
||||
if (saveData) {
|
||||
cachefile << (*sched)->getRegistration() << " "
|
||||
<< (*sched)->getRunCount() << " "
|
||||
<< (*sched)->getHits() << " "
|
||||
<< (*sched)->getLastUsed() << endl;
|
||||
cachefile << acft->getRegistration() << " "
|
||||
<< acft->getRunCount() << " "
|
||||
<< acft->getHits() << " "
|
||||
<< acft->getLastUsed() << endl;
|
||||
}
|
||||
delete(*sched);
|
||||
delete acft;
|
||||
}
|
||||
if (saveData) {
|
||||
cachefile.close();
|
||||
|
@ -271,10 +271,9 @@ void FGTrafficManager::finishInit()
|
|||
SG_LOG(SG_AI, SG_INFO, "finishing AI-Traffic init");
|
||||
loadHeuristics();
|
||||
|
||||
// Do sorting and scoring separately, to take advantage of the "homeport| variable
|
||||
for (currAircraft = scheduledAircraft.begin();
|
||||
currAircraft != scheduledAircraft.end(); currAircraft++) {
|
||||
(*currAircraft)->setScore();
|
||||
// Do sorting and scoring separately, to take advantage of the "homeport" variable
|
||||
BOOST_FOREACH(FGAISchedule* schedule, scheduledAircraft) {
|
||||
schedule->setScore();
|
||||
}
|
||||
|
||||
sort(scheduledAircraft.begin(), scheduledAircraft.end(),
|
||||
|
@ -372,7 +371,7 @@ void FGTrafficManager::update(double /*dt */ )
|
|||
}
|
||||
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
if (scheduledAircraft.size() == 0) {
|
||||
if (scheduledAircraft.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue