2012-10-05 17:12:46 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "performancedb.hxx"
|
|
|
|
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
2009-05-05 10:36:38 +00:00
|
|
|
#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>
|
|
|
|
|
2012-10-05 17:12:46 +00:00
|
|
|
#include "performancedata.hxx"
|
2007-06-28 07:47:20 +00:00
|
|
|
|
2009-05-05 10:36:38 +00:00
|
|
|
using std::string;
|
|
|
|
using std::cerr;
|
|
|
|
|
2007-06-28 07:47:20 +00:00
|
|
|
PerformanceDB::PerformanceDB()
|
|
|
|
{
|
2009-05-05 10:36:38 +00:00
|
|
|
SGPath dbpath( globals->get_fg_root() );
|
|
|
|
|
2007-06-28 07:47:20 +00:00
|
|
|
|
2009-05-05 10:36:38 +00:00
|
|
|
dbpath.append( "/AI/Aircraft/" );
|
|
|
|
dbpath.append( "performancedb.xml");
|
|
|
|
load(dbpath);
|
2007-06-28 07:47:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PerformanceDB::~PerformanceDB()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void PerformanceDB::registerPerformanceData(const std::string& id, PerformanceData* data) {
|
|
|
|
//TODO if key exists already replace data "inplace", i.e. copy to existing PerfData instance
|
|
|
|
// this updates all aircraft currently using the PerfData instance.
|
|
|
|
_db[id] = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerformanceDB::registerPerformanceData(const std::string& id, const std::string& filename) {
|
|
|
|
registerPerformanceData(id, new PerformanceData(filename));
|
|
|
|
}
|
|
|
|
|
2012-10-05 17:12:46 +00:00
|
|
|
PerformanceData* PerformanceDB::getDataFor(const string& acType, const string& acClass)
|
|
|
|
{
|
|
|
|
// first, try with the specific aircraft type, such as 738 or A322
|
|
|
|
if (_db.find(acType) != _db.end()) {
|
|
|
|
return _db[acType];
|
|
|
|
}
|
|
|
|
|
|
|
|
string alias = findAlias(acType);
|
|
|
|
if (_db.find(alias) != _db.end()) {
|
|
|
|
return _db[alias];
|
|
|
|
}
|
|
|
|
|
|
|
|
SG_LOG(SG_AI, SG_INFO, "no performance data for " << acType);
|
|
|
|
|
|
|
|
if (_db.find(acClass) == _db.end()) {
|
2007-06-28 07:47:20 +00:00
|
|
|
return _db["jet_transport"];
|
2012-10-05 17:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return _db[acClass];
|
2007-06-28 07:47:20 +00:00
|
|
|
}
|
2009-05-05 10:36:38 +00:00
|
|
|
|
2012-10-05 17:12:46 +00:00
|
|
|
void PerformanceDB::load(const SGPath& filename) {
|
2009-05-05 10:36:38 +00:00
|
|
|
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);
|
2009-06-27 08:09:10 +00:00
|
|
|
} catch (const sg_exception &) {
|
2011-12-11 12:55:56 +00:00
|
|
|
SG_LOG(SG_AI, SG_ALERT,
|
2009-05-05 10:36:38 +00:00
|
|
|
"Error reading AI aircraft performance database: " << filename.str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPropertyNode * node = root.getNode("performancedb");
|
2012-10-05 17:12:46 +00:00
|
|
|
for (int i = 0; i < node->nChildren(); i++) {
|
2009-05-05 10:36:38 +00:00
|
|
|
SGPropertyNode * db_node = node->getChild(i);
|
2012-10-05 17:12:46 +00:00
|
|
|
if (!strcmp(db_node->getName(), "aircraft")) {
|
2009-05-05 10:36:38 +00:00
|
|
|
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));
|
2012-10-05 17:12:46 +00:00
|
|
|
} else if (!strcmp(db_node->getName(), "alias")) {
|
|
|
|
string alias(db_node->getStringValue("alias"));
|
|
|
|
if (alias.empty()) {
|
|
|
|
SG_LOG(SG_AI, SG_ALERT, "performance DB alias entry with no <alias> definition");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_FOREACH(SGPropertyNode* matchNode, db_node->getChildren("match")) {
|
|
|
|
string match(matchNode->getStringValue());
|
|
|
|
_aliases.push_back(StringPair(match, alias));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_AI, SG_ALERT, "unrecognized performance DB entry:" << db_node->getName());
|
|
|
|
}
|
|
|
|
} // of nodes iteration
|
2009-05-05 10:36:38 +00:00
|
|
|
}
|
|
|
|
|
2012-10-05 17:12:46 +00:00
|
|
|
string PerformanceDB::findAlias(const string& acType) const
|
|
|
|
{
|
|
|
|
BOOST_FOREACH(const StringPair& alias, _aliases) {
|
|
|
|
if (acType.find(alias.first) == 0) { // matched!
|
|
|
|
return alias.second;
|
|
|
|
}
|
|
|
|
} // of alias iteration
|
|
|
|
|
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
|
|
|
|