FlightGear next
performancedb.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2 #include "config.h"
3#endif
4
5#include "performancedb.hxx"
6
7#include <simgear/sg_inlines.h>
8#include <simgear/misc/sg_path.hxx>
9#include <simgear/props/props.hxx>
10#include <simgear/props/props_io.hxx>
11#include <simgear/structure/exception.hxx>
12
13#include <Main/globals.hxx>
14#include <cstring>
15#include <iostream>
16
17#include "performancedata.hxx"
18
19using std::string;
20
22{
23 SGPath dbpath( globals->get_fg_root() );
24 dbpath.append( "/AI/Aircraft/" );
25 dbpath.append( "performancedb.xml");
26 load(dbpath);
27
28 if (getDefaultPerformance() == 0) {
29 SG_LOG(SG_AI, SG_WARN, "PerformanceDB: no default performance data found/loaded");
30 }
31}
32
34{
35 PerformanceDataDict::iterator it;
36 for (it = _db.begin(); it != _db.end(); ++it) {
37 delete it->second;
38 }
39
40 _db.clear();
41 _aliases.clear();
42}
43
44void PerformanceDB::update(double dt)
45{
46 SG_UNUSED(dt);
47 suspend();
48}
49
50void PerformanceDB::registerPerformanceData(const std::string& id, PerformanceData* data) {
51 // TODO: if key exists already replace data "inplace", i.e. copy to existing PerfData instance
52 // this updates all aircraft currently using the PerfData instance.
53 _db[id] = data;
54}
55
56PerformanceData* PerformanceDB::getDataFor(const string& acType, const string& acClass) const
57{
58 // first, try with the specific aircraft type, such as 738 or A322
59 PerformanceDataDict::const_iterator it;
60 it = _db.find(acType);
61 if (it != _db.end()) {
62 return it->second;
63 }
64
65 const string& alias = findAlias(acType);
66 it = _db.find(alias);
67 if (it != _db.end()) {
68 return it->second;
69 }
70
71 it = _db.find(acClass);
72 if (it == _db.end()) {
73 return getDefaultPerformance();
74 }
75
76 return it->second;
77}
78
80{
81 PerformanceDataDict::const_iterator it = _db.find("jet_transport");
82 if (it == _db.end())
83 return NULL;
84
85 return it->second;
86}
87
88bool PerformanceDB::havePerformanceDataForAircraftType(const std::string& acType) const
89{
90 PerformanceDataDict::const_iterator it = _db.find(acType);
91 if (it != _db.end())
92 return true;
93
94 const std::string alias(findAlias(acType));
95 return (_db.find(alias) != _db.end());
96}
97
98void PerformanceDB::load(const SGPath& filename)
99{
100 SGPropertyNode root;
101 try {
102 readProperties(filename, &root);
103 } catch (const sg_exception &) {
104 SG_LOG(SG_AI, SG_ALERT,
105 "Error reading AI aircraft performance database: " << filename);
106 return;
107 }
108
109 SGPropertyNode * node = root.getNode("performancedb");
110 for (int i = 0; i < node->nChildren(); i++) {
111 SGPropertyNode * db_node = node->getChild(i);
112 if (db_node->getNameString() == "aircraft") {
113 PerformanceData* data = NULL;
114 if (db_node->hasChild("base")) {
115 std::string baseName = db_node->getStringValue("base");
116 PerformanceData* baseData = _db[baseName];
117 if (!baseData) {
118 SG_LOG(SG_AI, SG_ALERT,
119 "Error reading AI aircraft performance database: unknown base type " << baseName);
120 return;
121 }
122
123 // clone base data to 'inherit' from it
124 data = new PerformanceData(baseData);
125 } else {
126 data = new PerformanceData;
127 }
128
129 data->initFromProps(db_node);
130 std::string name = db_node->getStringValue("type", "heavy_jet");
131 registerPerformanceData(name, data);
132 } else if (db_node->getNameString() == "alias") {
133 std::string alias = db_node->getStringValue("alias");
134 if (alias.empty()) {
135 SG_LOG(SG_AI, SG_ALERT, "performance DB alias entry with no <alias> definition");
136 continue;
137 }
138
139 for (auto matchNode : db_node->getChildren("match")) {
140 std::string match = matchNode->getStringValue();
141 _aliases.push_back(StringPair(match, alias));
142 }
143 } else {
144 SG_LOG(SG_AI, SG_ALERT, "unrecognized performance DB entry:" << db_node->getNameString());
145 }
146 } // of nodes iteration
147}
148
149const string& PerformanceDB::findAlias(const string& acType) const
150{
151 for (const auto& alias : _aliases) {
152 if (acType.find(alias.first) == 0) { // matched!
153 return alias.second;
154 }
155 } // of alias iteration
156
157 static const string empty;
158 return empty;
159}
160
161
162// Register the subsystem.
163SGSubsystemMgr::Registrant<PerformanceDB> registrantPerformanceDB(
164 SGSubsystemMgr::POST_FDM);
bool suspend
Definition JSBSim.cpp:93
#define i(x)
bool havePerformanceDataForAircraftType(const std::string &acType) const
PerformanceData * getDefaultPerformance() const
void init() override
void update(double dt) override
PerformanceData * getDataFor(const std::string &acType, const std::string &acClass) const
get performance data for an aircraft type / class.
void shutdown() override
Data storage for aircraft performance data.
void initFromProps(SGPropertyNode *props)
const char * name
FGGlobals * globals
Definition globals.cxx:142
SGSubsystemMgr::Registrant< PerformanceDB > registrantPerformanceDB(SGSubsystemMgr::POST_FDM)