// << lead_dist << " " << curr->name
// << " Ground target speed " << groundTargetSpeed << endl;
double bearing = 0;
- if (speed > 50) { // don't do bearing calculations for ground traffic
+ // don't do bearing calculations for ground traffic
bearing = getBearing(fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr));
if (bearing < minBearing) {
minBearing = bearing;
} else {
speedFraction = 1.0;
}
- }
- }
+ }
if (trafficRef) {
//cerr << "Tracking callsign : \"" << fgGetString("/ai/track-callsign") << "\"" << endl;
/* if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
<< _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << " " << curr->name << " " << vs << " " << tgt_vs << " " << bearing << " " << minBearing << " " << speedFraction << endl;
}*/
}
- if ((dist_to_go < lead_dist) || (bearing > (minBearing * 1.1))) {
+ if ((dist_to_go < lead_dist) ||
+ ((dist_to_go > prev_dist_to_go) && (bearing > (minBearing * 1.1))) ) {
minBearing = 360;
speedFraction = 1.0;
+ prev_dist_to_go = HUGE_VAL;
return true;
} else {
+ prev_dist_to_go = dist_to_go;
return false;
}
}
if (prev->contains(string("Accel"))) {
takeOffStatus = 3;
}
+ //if (prev->contains(string("landing"))) {
+ // if (speed < _performance->vTaxi() * 2) {
+ // fp->shortenToFirst(2, "legend");
+ // }
+ //}
/*if (prev->contains(string("final"))) {
cerr << getCallSign() << " "
// << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << "Heading change rate : " << headingChangeRate << " bacnk sence " << bank_sense << endl;
hdg += headingChangeRate * dt * sqrt(fabs(speed) / 15);
headingError = headingDiff;
+ if (fabs(headingError) < 1.0) {
+ hdg = tgt_heading;
+ }
} else {
if (fabs(speed) > 1.0) {
turn_radius_ft = 0.088362 * speed * speed
}
else
wpt_iterator--;
+}
+void FGAIFlightPlan::eraseLastWaypoint()
+{
+ delete (waypoints.back());
+ waypoints.pop_back();;
+ wpt_iterator = waypoints.begin();
+ wpt_iterator++;
}
+
+
// gives distance in feet from a position to a waypoint
double FGAIFlightPlan::getDistanceToGo(double lat, double lon, FGAIWaypoint* wp) const{
return SGGeodesy::distanceM(SGGeod::fromDeg(lon, lat),
trackDistance = 0; // name not found
}
return trackDistance;
-}
\ No newline at end of file
+}
+
+void FGAIFlightPlan::shortenToFirst(unsigned int number, string name)
+{
+ while (waypoints.size() > number + 3) {
+ eraseLastWaypoint();
+ }
+ (waypoints.back())->setName((waypoints.back())->getName() + name);
+}
FGAIFlightPlan* getSID() { return sid; };
FGAIWaypoint *getWayPoint(int i) { return waypoints[i]; };
FGAIWaypoint *getLastWaypoint() { return waypoints.back(); };
+
+ void shortenToFirst(unsigned int number, std::string name);
private:
FGAIFlightPlan *sid;
bool createParking(FGAIAircraft *, FGAirport *, double radius);
void deleteWaypoints();
void resetWaypoints();
+ void eraseLastWaypoint();
bool createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
+#include <FDM/LaRCsim/basic_aero.h>
/* FGAIFlightPlan::create()
}
intVec ids;
- int runwayId = gn->findNearestNode(runwayTakeoff);
+ int runwayId = 0;
+ if (gn->getVersion() > 0) {
+ runwayId = gn->findNearestNodeOnRunway(runwayTakeoff);
+ } else {
+ runwayId = gn->findNearestNode(runwayTakeoff);
+ }
// A negative gateId indicates an overflow parking, use a
// fallback mechanism for this.
}
intVec ids;
- int runwayId = gn->findNearestNode(lastWptPos);
+ int runwayId = 0;
+ if (gn->getVersion() == 1) {
+ runwayId = gn->findNearestNodeOnRunway(lastWptPos);
+ } else {
+ runwayId = gn->findNearestNode(lastWptPos);
+ }
+ //cerr << "Using network node " << runwayId << endl;
// A negative gateId indicates an overflow parking, use a
// fallback mechanism for this.
// Starting from gate 0 is a bit of a hack...
const string & fltType)
{
double vTouchdown = ac->getPerformance()->vTouchdown();
- //double vTaxi = ac->getPerformance()->vTaxi();
+ double vTaxi = ac->getPerformance()->vTaxi();
+ double decel = ac->getPerformance()->deceleration() * 1.5;
+
+ 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();
coord = rwy->pointOnCenterline((currentDist * (i / nPoints)));
wpt = createInAir(ac, buffer, coord, currentAltitude, (vTouchdown));
}*/
-
- for (int i = 1; i < 10; i++) {
- snprintf(buffer, 12, "wpt%d", i);
+ double rolloutDistance =
+ (vTouchdownMetric * vTouchdownMetric - vTaxiMetric * vTaxiMetric) / (2 * decelMetric);
+ //cerr << " touchdown speed = " << vTouchdown << ". Rollout distance " << rolloutDistance << endl;
+ int nPoints = 50;
+ for (int i = 1; i < nPoints; i++) {
+ snprintf(buffer, 12, "landing03%d", i);
- coord = rwy->pointOnCenterline((rwy->lengthM() * 0.9) * (i / 10.0));
- wpt = createOnGround(ac, buffer, coord, currElev, (vTouchdown / i));
- wpt->setCrossat(apt->getElevation());
+ coord = rwy->pointOnCenterline((rolloutDistance * ((double) i / (double) nPoints)));
+ wpt = createOnGround(ac, buffer, coord, currElev, vTaxi);
+ wpt->setCrossat(currElev);
waypoints.push_back(wpt);
}
+ double mindist = 1.1 * rolloutDistance;
+ double maxdist = rwy->lengthM();
+ //cerr << "Finding nearest exit" << endl;
+ 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);
+ else {
+ break;
+ }
+
+ double dist = SGGeodesy::distanceM(coord, tn->getGeod());
+ if (dist < (min + 0.75)) {
+ break;
+ }
+ min = dist;
+ }
+ if (tn) {
+ wpt = createOnGround(ac, buffer, tn->getGeod(), currElev, vTaxi);
+ waypoints.push_back(wpt);
+ }
+ }
+ cerr << "Done. " << endl;
/*
//Runway Threshold
inline double vRotate () { return _vRotate; };
inline double maximumBankAngle () { return _maxbank; };
inline double acceleration () { return _acceleration; };
+ inline double deceleration () { return _deceleration; };
inline double vTaxi () { return _vTaxi; };
inline double vTakeoff () { return _vTakeOff; };
inline double vClimb () { return _vClimb; };
void FGAirportDynamicsXMLLoader::endElement (const char * name) {
//cout << "End element " << name << endl;
+ if (name == string("version")) {
+ _dynamics->getGroundNetwork()->addVersion(atoi(value.c_str()));
+ //std::cerr << "version" << value<< std::endl;
+ }
if (name == string("AWOS")) {
_dynamics->addAwosFreq(atoi(value.c_str()));
//cerr << "Adding AWOS" << value<< endl;
count = 0;
currTraffic = activeTraffic.begin();
group = 0;
+ version = 0;
networkInitialized = false;
}
return index;
}
+int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod)
+{
+ double minDist = HUGE_VAL;
+ int index = -1;
+
+ for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
+ itr++) {
+ if (!((*itr)->getIsOnRunway())) {
+ continue;
+ }
+ double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
+ if (d < minDist) {
+ minDist = d;
+ index = (*itr)->getIndex();
+ //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+ }
+ }
+
+ return index;
+}
+
+
int FGGroundNetwork::findNearestNode(double lat, double lon)
{
return findNearestNode(SGGeod::fromDeg(lon, lat));
time_t nextSave;
//int maxDepth;
int count;
+ int version;
FGTaxiNodeVector nodes;
FGTaxiNodeVector pushBackNodes;
FGTaxiSegmentVector segments;
void addNode (const FGTaxiNode& node);
void addNodes (FGParkingVec *parkings);
void addSegment(const FGTaxiSegment& seg);
+ void setVersion (int v) { version = v;};
+
+ int getVersion() { return version; };
void init();
bool exists() {
int findNearestNode(double lat, double lon);
int findNearestNode(const SGGeod& aGeod);
+ int findNearestNodeOnRunway(const SGGeod& aGeod);
FGTaxiNode *findNode(unsigned idx);
FGTaxiSegment *findSegment(unsigned idx);
virtual void update(double dt);
void saveElevationCache();
+ void addVersion(int v) {version = v; };
};
<< " " << arrT << ":");
flights.push_back(flight);
- } while (1); //(currentDestination != startingPort);
+ } while (currentDestination != startingPort);
SG_LOG(SG_GENERAL, SG_BULK, " Done ");
}
}
if (flights.size()) {
time_t arrival = flights.back()->getArrivalTime();
- if ((*i)->getDepartureTime() < (arrival+(20*60)))
+ int groundTime = groundTimeFromRadius();
+ if ((*i)->getDepartureTime() < (arrival+(groundTime)))
continue;
}
if (min != 0) {
return NULL;
}
+int FGAISchedule::groundTimeFromRadius()
+{
+ if (radius < 10)
+ return 15 * 60;
+ else if (radius < 15)
+ return 20 * 60;
+ else if (radius < 20)
+ return 30 * 60;
+ else if (radius < 25)
+ return 50 * 60;
+ else if (radius < 30)
+ return 90 * 60;
+ else
+ return 120 * 60;
+}
+
+
double FGAISchedule::getSpeed()
{
FGScheduledFlightVecIterator i = flights.begin();
bool valid;
void scheduleFlights(time_t now);
+ int groundTimeFromRadius();
/**
* Transition this schedule from distant mode to AI mode;