double airportElev = aAirport->getElevation();
waypoint* wpt;
- wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, 15);
+ wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
- wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, 15);
+ wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
}
char buffer[10];
snprintf (buffer, 10, "%d", node);
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
- waypoint* wpt = createOnGround(ac, buffer, tn->geod(), apt->getElevation(), 15);
+ waypoint* wpt = createOnGround(ac, buffer, tn->geod(), apt->getElevation(), ac->getPerformance()->vTaxi());
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
double airportElev = aAirport->getElevation();
waypoint* wpt;
- wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, 15);
+ wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
- wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, 15);
+ wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
double heading, lat, lon;
aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading);
- wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev, 15);
+ wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev, ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
}
char buffer[10];
snprintf (buffer, 10, "%d", node);
FGTaxiNode *tn = gn->findNode(node);
- waypoint* wpt = createOnGround(ac, buffer, tn->geod(), apt->getElevation(), 15);
+ waypoint* wpt = createOnGround(ac, buffer, tn->geod(), apt->getElevation(), ac->getPerformance()->vTaxi());
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
******************************************************************/
void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, const string &fltType)
{
- double accel = ac->getPerformance()->acceleration();
- double vRotate = ac->getPerformance()->vRotate();
+ double accel = ac->getPerformance()->acceleration();
+ double vTaxi = ac->getPerformance()->vTaxi();
+ double vRotate = ac->getPerformance()->vRotate();
+ double vTakeoff = ac->getPerformance()->vTakeoff();
+ double vClimb = ac->getPerformance()->vClimb();
// Acceleration = dV / dT
// Acceleration X dT = dV
// dT = dT / Acceleration
//d = (Vf^2 - Vo^2) / (2*a)
- double accelTime = (vRotate - 15) / accel;
+ double accelTime = (vRotate - vTaxi) / accel;
//cerr << "Using " << accelTime << " as total acceleration time" << endl;
- double accelDistance = (vRotate*vRotate - 15*15) / (2*accel);
+ double accelDistance = (vRotate*vRotate - vTaxi*vTaxi) / (2*accel);
//cerr << "Using " << accelDistance << " " << accel << " " << vRotate << endl;
waypoint *wpt;
// Get the current active runway, based on code from David Luff
double airportElev = apt->getElevation();
// Acceleration point, 105 meters into the runway,
SGGeod accelPoint = rwy->pointOnCenterline(105.0);
- wpt = createOnGround(ac, "accel", accelPoint, airportElev, speed);
- waypoints.push_back(wpt);
-
+ wpt = createOnGround(ac, "accel", accelPoint, airportElev, vClimb);
+ waypoints.push_back(wpt);
+
//Start Climbing to 3000 ft. Let's do this
// at the center of the runway for now:
SGGeod rotate = rwy->pointOnCenterline(105.0+accelDistance);
waypoint *wpt;
bool planLoaded = false;
string fPLName;
+ double vClimb = ac->getPerformance()->vClimb();
if (firstFlight) {
string rwyClass = getRunwayClassFromTrafficType(fltType);
}
} else {
SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER);
- wpt = createInAir(ac, "10000ft climb", climb1, speed, 10000);
+ wpt = createInAir(ac, "10000ft climb", climb1, vClimb, 10000);
wpt->gear_down = true;
wpt->flaps_down= true;
waypoints.push_back(wpt);
{
// Ten thousand ft. Slowing down to 240 kts
waypoint *wpt;
+double vDecent = ac->getPerformance()->vDescent();
+ double vApproach = ac->getPerformance()->vApproach();
//Beginning of Decent
//string name;
rwy = apt->getRunwayByIdent(activeRunway);
SGGeod descent1 = rwy->pointOnCenterline(-100000); // 100km out
- wpt = createInAir(ac, "Dec 10000ft", descent1, apt->getElevation(), 240);
+ wpt = createInAir(ac, "Dec 10000ft", descent1, apt->getElevation(), vDecent);
wpt->crossat = 10000;
waypoints.push_back(wpt);
// Three thousand ft. Slowing down to 160 kts
SGGeod descent2 = rwy->pointOnCenterline(-8*SG_NM_TO_METER); // 8nm out
- wpt = createInAir(ac, "DEC 3000ft", descent2, apt->getElevation(), 160);
+ wpt = createInAir(ac, "DEC 3000ft", descent2, apt->getElevation(), vApproach);
wpt->crossat = 3000;
wpt->gear_down = true;
wpt->flaps_down= true;
******************************************************************/
void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt)
{
- // Ten thousand ft. Slowing down to 150 kts
+ double vTouchdown = ac->getPerformance()->vTouchdown();
+ double vTaxi = ac->getPerformance()->vTaxi();
+
waypoint *wpt;
double aptElev = apt->getElevation();
//Runway Threshold
- wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, 150);
+ wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, vTouchdown);
wpt->crossat = apt->getElevation();
waypoints.push_back(wpt);
// Roll-out
- wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, 30);
+ wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, vTaxi*2);
waypoints.push_back(wpt);
SGGeod rollOut = rwy->pointOnCenterline(rwy->lengthM() * 0.9);
- wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, 15);
+ wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, vTaxi);
wpt->crossat = apt->getElevation();
waypoints.push_back(wpt);
}
double lon, lon2;
double az2;
double heading;
+
+ double vTaxi = ac->getPerformance()->vTaxi();
+ double vTaxiReduced = vTaxi * (2.0/3.0);
apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
heading += 180.0;
if (heading > 360)
geo_direct_wgs_84 ( 0, lat, lon, heading,
2.2*radius,
&lat2, &lon2, &az2 );
- wpt = createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2), aptElev, 10);
+ wpt = createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2), aptElev, vTaxiReduced);
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
0.1 *radius,
&lat2, &lon2, &az2 );
- wpt = createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2), aptElev, 10);
+ wpt = createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2), aptElev, vTaxiReduced);
waypoints.push_back(wpt);
- wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, 10);
+ wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, vTaxiReduced);
waypoints.push_back(wpt);
}
#include <fstream>
#include <iostream>
-#include "AIFlightPlan.hxx"
-#include "AIAircraft.hxx"
#include <simgear/route/waypoint.hxx>
#include <Navaids/awynet.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
+#include "AIFlightPlan.hxx"
+#include "AIAircraft.hxx"
+#include "performancedata.hxx"
+
+
using std::iostream;
void FGAIFlightPlan::evaluateRoutePart(double deplat,
double longitude, double speed,
double alt, const string& fltType)
{
+ double vCruise = ac->getPerformance()->vCruise();
waypoint *wpt;
- wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, speed);
+ wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, vCruise);
waypoints.push_back(wpt);
string rwyClass = getRunwayClassFromTrafficType(fltType);
// begin descent 110km out
SGGeod beginDescentPoint = rwy->pointOnCenterline(-110000);
- wpt = createInAir(ac, "BOD", beginDescentPoint, alt, speed);
+ wpt = createInAir(ac, "BOD", beginDescentPoint, alt, vCruise);
waypoints.push_back(wpt);
}
# include <config.h>
#endif
-#include "AIFlightPlan.hxx"
#include <simgear/math/sg_geodesy.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
+#include "AIFlightPlan.hxx"
+#include "AIAircraft.hxx"
+#include "performancedata.hxx"
+
+// TODO: Use James Turner's createOnGround functions.
void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
bool firstFlight, FGAirport *dep,
double latitude,
const string& airline)
{
double lat, lon, heading;
+ double vTaxi = ac->getPerformance()->vTaxi();
+ double vTaxiBackward = vTaxi * (-2.0/3.0);
+ double vTaxiReduced = vTaxi * (2.0/3.0);
FGTaxiRoute *pushBackRoute;
// Active runway can be conditionally set by ATC, so at the start of a new flight, this
// must be reset.
// Elevation is currently disregarded when on_ground is true
// because the AIModel obtains a periodic ground elevation estimate.
wpt->altitude = dep->getElevation();
- wpt->speed = -10;
+ wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
// Elevation is currently disregarded when on_ground is true
// because the AIModel obtains a periodic ground elevation estimate.
wpt->altitude = dep->getElevation();
- wpt->speed = -10;
+ wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
}
// some special considerations for the last point:
wpt->name = string("PushBackPoint");
- wpt->speed = 15;
+ wpt->speed = vTaxi;
//for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end(); i++) {
// cerr << "Waypoint Name: " << (*i)->name << endl;
//}
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
- wpt->speed = 10;
+ wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
- wpt->speed = 10;
+ wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->latitude = tn->getLatitude();
wpt->longitude = tn->getLongitude();
wpt->altitude = dep->getElevation();
- wpt->speed = 10;
+ wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
double lon2;
double az2;
+ double vTaxi = ac->getPerformance()->vTaxi();
+ double vTaxiBackward = vTaxi * (-2.0/3.0);
+ double vTaxiReduced = vTaxi * (2.0/3.0);
+
dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
wpt->latitude = lat;
wpt->longitude = lon;
wpt->altitude = dep->getElevation();
- wpt->speed = -10;
+ wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
- wpt->speed = -10;
+ wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
- wpt->speed = 10;
+ wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
#include "AIAircraft.hxx"
PerformanceData::PerformanceData(double acceleration,
- double deceleration,
- double climbRate,
- double descentRate,
- double vRotate,
- double vTakeOff,
- double vClimb,
- double vCruise,
- double vDescent,
- double vApproach,
- double vTouchdown,
- double vTaxi) :
+ double deceleration,
+ double climbRate,
+ double descentRate,
+ double vRotate,
+ double vTakeOff,
+ double vClimb,
+ double vCruise,
+ double vDescent,
+ double vApproach,
+ double vTouchdown,
+ double vTaxi) :
_acceleration(acceleration),
_deceleration(deceleration),
_climbRate(climbRate),
// if (tgt_speed > _vTaxi & ac->onGround()) // maximum taxi speed on ground
// tgt_speed = _vTaxi;
// bad idea for a take off roll :-)
-
+
double speed = ac->getSpeed();
double speed_diff = tgt_speed - speed;
// check maximum bank angle
if (fabs(tgt_roll) > _maxbank)
tgt_roll = _maxbank * tgt_roll/fabs(tgt_roll);
-
+
double roll = ac->getRoll();
double bank_diff = tgt_roll - roll;
-
+
if (fabs(bank_diff) > 0.2) {
if (bank_diff > 0.0) {
roll += _rollrate * dt;
if (pitch > tgt_pitch)
pitch = tgt_pitch;
-
} else if (pdiff < 0.0) { // nose down
pitch -= 0.002*_descentRate * dt / 3.0;
double PerformanceData::actualVerticalSpeed(FGAIAircraft* ac, double tgt_vs, double dt) {
double vs = ac->getVerticalSpeed();
double vs_diff = tgt_vs - vs;
-
+
if (fabs(vs_diff) > 10.0) {
if (vs_diff > 0.0) {
vs += _climbRate * dt / 3.0; //TODO avoid hardcoded 3 secs to attain climb rate from level flight
if (vs > tgt_vs)
vs = tgt_vs;
-
} else if (vs_diff < 0.0) {
vs -= _descentRate * dt / 3.0;
inline double vRotate () { return _vRotate; };
inline double maximumBankAngle () { return _maxbank; };
inline double acceleration () { return _acceleration; };
+ inline double vTaxi () { return _vTaxi; };
+ inline double vTakeoff () { return _vTakeOff; };
+ inline double vClimb () { return _vClimb; };
+ inline double vDescent () { return _vDescent; };
+ inline double vApproach () { return _vApproach; };
+ inline double vTouchdown () { return _vTouchdown; };
+ inline double vCruise () { return _vCruise; };
private:
double _acceleration;
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
+#include <simgear/xml/easyxml.hxx>
+
+#include <Main/globals.hxx>
+#include <iostream>
+#include <fstream>
+
#include "performancedb.hxx"
+using std::string;
+using std::cerr;
+
PerformanceDB::PerformanceDB()
{
- // these are the 6 classes originally defined in the PERFSTRUCT
- // Plus a few more for testing
- registerPerformanceData("heavy_jet", new PerformanceData(
- 4.0, 2.0, 3000.0, 1500.0, 150.0, 160.0, 300.0, 430.0, 300.0, 170.0, 150.0, 15.0));
- registerPerformanceData("light", new PerformanceData(
- 2.0, 2.0, 450.0, 1000.0, 70.0, 70.0, 80.0, 100.0, 80.0, 70.0, 60.0, 15.0));
- registerPerformanceData("ww2_fighter", new PerformanceData(
- 4.0, 2.0, 3000.0, 1500.0, 110.0, 110.0, 180.0, 250.0, 200.0, 130.0, 100.0, 15.0));
- registerPerformanceData("jet_fighter", new PerformanceData(
- 7.0, 3.0, 4000.0, 2000.0, 120.0, 150.0, 350.0, 500.0, 350.0, 170.0, 150.0, 15.0));
- registerPerformanceData("jet_transport", new PerformanceData(
- 5.0, 2.0, 3000.0, 1500.0, 100.0, 140.0, 300.0, 430.0, 300.0, 170.0, 130.0, 15.0));
- registerPerformanceData("tanker", new PerformanceData(
- 5.0, 2.0, 3000.0, 1500.0, 100.0, 140.0, 300.0, 430.0, 300.0, 170.0, 130.0, 15.0));
- registerPerformanceData("ufo", new PerformanceData(
- 30.0, 30.0, 6000.0, 6000.0, 150.0, 150.0, 300.0, 430.0, 300.0, 170.0, 130.0, 15.0));
+ SGPath dbpath( globals->get_fg_root() );
+
+ dbpath.append( "/AI/Aircraft/" );
+ dbpath.append( "performancedb.xml");
+ load(dbpath);
}
return _db[id];
}
+
+void PerformanceDB::load(SGPath filename) {
+ string name;
+ double acceleration;
+ double deceleration;
+ double climbRate;
+ double descentRate;
+ double vRotate;
+ double vTakeOff;
+ double vClimb;
+ double vCruise;
+ double vDescent;
+ double vApproach;
+ double vTouchdown;
+ double vTaxi;
+ SGPropertyNode root;
+ try {
+ readProperties(filename.str(), &root);
+ } catch (const sg_exception &e) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Error reading AI aircraft performance database: " << filename.str());
+ return;
+ }
+
+ SGPropertyNode * node = root.getNode("performancedb");
+ for (int i = 0; i < node->nChildren(); i++) {
+ SGPropertyNode * db_node = node->getChild(i);
+ name = db_node->getStringValue("type", "heavy_jet");
+ acceleration = db_node->getDoubleValue("acceleration-kts-hour", 4.0);
+ deceleration = db_node->getDoubleValue("deceleration-kts-hour", 2.0);
+ climbRate = db_node->getDoubleValue("climbrate-fpm", 3000.0);
+ descentRate = db_node->getDoubleValue("decentrate-fpm", 1500.0);
+ vRotate = db_node->getDoubleValue("rotate-speed-kts", 150.0);
+ vTakeOff = db_node->getDoubleValue("takeoff-speed-kts", 160.0);
+ vClimb = db_node->getDoubleValue("climb-speed-kts", 300.0);
+ vCruise = db_node->getDoubleValue("cruise-speed-kts", 430.0);
+ vDescent = db_node->getDoubleValue("decent-speed-kts", 300.0);
+ vApproach = db_node->getDoubleValue("approach-speed-kts", 170.0);
+ vTouchdown = db_node->getDoubleValue("touchdown-speed-kts", 150.0);
+ vTaxi = db_node->getDoubleValue("taxi-speed-kts", 15.0);
+
+ registerPerformanceData(name, new PerformanceData(
+ acceleration, deceleration, climbRate, descentRate, vRotate, vTakeOff, vClimb, vCruise, vDescent, vApproach, vTouchdown, vTaxi));
+ }
+}
+
#define PERFORMANCEDB_HXX
#include <string>
+#include <vector>
#include <map>
#include "performancedata.hxx"
* Allows to store performance data for later reuse/retrieval. Just
* a simple map for now.
*
- * @author Thomas Förster <t.foerster@biologie.hu-berlin.de>
+ * @author Thomas F�rster <t.foerster@biologie.hu-berlin.de>
*/
//TODO provide std::map interface?
class PerformanceDB
void registerPerformanceData(const std::string& id, const std::string& filename);
PerformanceData* getDataFor(const std::string& id);
+ void load(SGPath path);
private:
std::map<std::string, PerformanceData*> _db;