+SGPropertyNode_ptr
+FGAIManager::loadScenarioFile(const std::string& filename)
+{
+ SGPath path(globals->get_fg_root());
+ path.append("AI/" + filename + ".xml");
+ try {
+ SGPropertyNode_ptr root = new SGPropertyNode;
+ readProperties(path.str(), root);
+ return root;
+ } catch (const sg_exception &) {
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Incorrect path specified for AI "
+ "scenario: \"" << path.str() << "\"");
+ return 0;
+ }
+}
+
+bool
+FGAIManager::getStartPosition(const string& id, const string& pid,
+ SGGeod& geodPos, double& hdng, SGVec3d& uvw)
+{
+ bool found = false;
+ SGPropertyNode* root = fgGetNode("sim/ai", true);
+ if (!root->getNode("enabled", true)->getBoolValue())
+ return found;
+
+ for (int i = 0 ; (!found) && i < root->nChildren() ; i++) {
+ SGPropertyNode *aiEntry = root->getChild( i );
+ if ( !strcmp( aiEntry->getName(), "scenario" ) ) {
+ string filename = aiEntry->getStringValue();
+ SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
+ if (scenarioTop) {
+ SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
+ if (scenarios) {
+ for (int i = 0; i < scenarios->nChildren(); i++) {
+ SGPropertyNode* scEntry = scenarios->getChild(i);
+ std::string type = scEntry->getStringValue("type");
+ std::string pnumber = scEntry->getStringValue("pennant-number");
+ std::string name = scEntry->getStringValue("name");
+ if (type == "carrier" && (pnumber == id || name == id)) {
+ osg::ref_ptr<FGAICarrier> carrier = new FGAICarrier;
+ carrier->readFromScenario(scEntry);
+
+ if (carrier->getParkPosition(pid, geodPos, hdng, uvw)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return found;
+}
+
+const FGAIBase *
+FGAIManager::calcCollision(double alt, double lat, double lon, double fuse_range)
+{
+ // we specify tgt extent (ft) according to the AIObject type
+ double tgt_ht[] = {0, 50 ,100, 250, 0, 100, 0, 0, 50, 50, 50};
+ double tgt_length[] = {0, 100, 200, 750, 0, 50, 0, 0, 200, 100, 100};
+ ai_list_iterator ai_list_itr = ai_list.begin();
+ ai_list_iterator end = ai_list.end();
+
+ while (ai_list_itr != end) {
+ double tgt_alt = (*ai_list_itr)->_getAltitude();
+ int type = (*ai_list_itr)->getType();
+ tgt_ht[type] += fuse_range;
+
+ if (fabs(tgt_alt - alt) > tgt_ht[type] || type == FGAIBase::otBallistic
+ || type == FGAIBase::otStorm || type == FGAIBase::otThermal ) {
+ SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: skipping "
+ << fabs(tgt_alt - alt)
+ << " "
+ << type
+ );
+ ++ai_list_itr;
+ continue;
+ }
+
+ double tgt_lat = (*ai_list_itr)->_getLatitude();
+ double tgt_lon = (*ai_list_itr)->_getLongitude();
+ int id = (*ai_list_itr)->getID();
+
+ double range = calcRange(lat, lon, tgt_lat, tgt_lon);
+
+ SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: AI list size "
+ << ai_list.size()
+ << " type " << type
+ << " ID " << id
+ << " range " << range
+ //<< " bearing " << bearing
+ << " alt " << tgt_alt
+ );
+
+ tgt_length[type] += fuse_range;
+
+ if (range < tgt_length[type]){
+ SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: HIT! "
+ << " type " << type
+ << " ID " << id
+ << " range " << range
+ << " alt " << tgt_alt
+ );
+ return (*ai_list_itr).get();
+ }
+ ++ai_list_itr;
+ }
+ return 0;
+}
+
+double
+FGAIManager::calcRange(double lat, double lon, double lat2, double lon2) const
+{
+ double course, az2, distance;
+
+ //calculate the bearing and range of the second pos from the first
+ geo_inverse_wgs_84(lat, lon, lat2, lon2, &course, &az2, &distance);
+ distance *= SG_METER_TO_FEET;
+ return distance;