+
+
+void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
+{
+ SGPropertyNode root;
+
+ SGPath config = globals->resolve_aircraft_path(path);
+ try {
+ SG_LOG(SG_GENERAL, SG_DEBUG,
+ "Submodels: Trying to read AI submodels file: " << config.str());
+ readProperties(config.str(), &root);
+ } catch (const sg_exception &) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Submodels: Unable to read AI submodels file: " << config.str());
+ return;
+ }
+
+ vector<SGPropertyNode_ptr> children = root.getChildren("submodel");
+ vector<SGPropertyNode_ptr>::iterator it = children.begin();
+ vector<SGPropertyNode_ptr>::iterator end = children.end();
+
+ for (int i = 0; it != end; ++it, i++) {
+ //cout << "Reading AI submodel " << (*it)->getPath() << endl;
+ submodel* sm = new submodel;
+ SGPropertyNode * entry_node = *it;
+ sm->name = entry_node->getStringValue("name", "none_defined");
+ sm->model = entry_node->getStringValue("model", "Models/Geometry/rocket.ac");
+ sm->speed = entry_node->getDoubleValue("speed", 2329.4);
+ sm->repeat = entry_node->getBoolValue("repeat", false);
+ sm->delay = entry_node->getDoubleValue("delay", 0.25);
+ sm->count = entry_node->getIntValue("count", 1);
+ sm->slaved = entry_node->getBoolValue("slaved", false);
+ sm->x_offset = entry_node->getDoubleValue("x-offset", 0.0);
+ sm->y_offset = entry_node->getDoubleValue("y-offset", 0.0);
+ sm->z_offset = entry_node->getDoubleValue("z-offset", 0.0);
+ sm->yaw_offset = entry_node->getDoubleValue("yaw-offset", 0.0);
+ sm->pitch_offset = entry_node->getDoubleValue("pitch-offset", 0.0);
+ sm->drag_area = entry_node->getDoubleValue("eda", 0.034);
+ sm->life = entry_node->getDoubleValue("life", 900.0);
+ sm->buoyancy = entry_node->getDoubleValue("buoyancy", 0);
+ sm->wind = entry_node->getBoolValue("wind", false);
+ sm->cd = entry_node->getDoubleValue("cd", 0.193);
+ sm->weight = entry_node->getDoubleValue("weight", 0.25);
+ sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true);
+ sm->no_roll = entry_node->getBoolValue("no-roll", false);
+ sm->collision = entry_node->getBoolValue("collision", false);
+ sm->expiry = entry_node->getBoolValue("expiry", false);
+ sm->impact = entry_node->getBoolValue("impact", false);
+ sm->impact_report = entry_node->getStringValue("impact-reports");
+ sm->fuse_range = entry_node->getDoubleValue("fuse-range", 0.0);
+ sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false);
+ sm->speed_node = fgGetNode(entry_node->getStringValue("speed-prop", "none"), false);
+ sm->submodel = entry_node->getStringValue("submodel-path", "");
+ sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false);
+ sm->ext_force = entry_node->getBoolValue("external-force", false);
+ sm->force_path = entry_node->getStringValue("force-path", "");
+ sm->random = entry_node->getBoolValue("random", false);
+ sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
+
+ if (sm->contents_node != 0)
+ sm->contents = sm->contents_node->getDoubleValue();
+
+ const char *trigger_path = entry_node->getStringValue("trigger", 0);
+ if (trigger_path) {
+ sm->trigger_node = fgGetNode(trigger_path, true);
+ sm->trigger_node->setBoolValue(sm->trigger_node->getBoolValue());
+ } else {
+ sm->trigger_node = 0;
+ }
+
+ if (sm->speed_node != 0)
+ sm->speed = sm->speed_node->getDoubleValue();
+
+ sm->timer = sm->delay;
+ sm->id = id;
+ sm->first_time = false;
+ sm->serviceable = serviceable;
+ sm->sub_id = 0;
+
+ sm->prop = fgGetNode("/ai/submodels/submodel", index, true);
+ sm->prop->tie("delay", SGRawValuePointer<double>(&(sm->delay)));
+ sm->prop->tie("count", SGRawValuePointer<int>(&(sm->count)));
+ sm->prop->tie("repeat", SGRawValuePointer<bool>(&(sm->repeat)));
+ sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id)));
+ sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id)));
+ sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable)));
+ sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random)));
+ sm->prop->tie("slaved", SGRawValuePointer<bool>(&(sm->slaved)));
+ string name = sm->name;
+ sm->prop->setStringValue("name", name.c_str());
+
+ string submodel = sm->submodel;
+ sm->prop->setStringValue("submodel", submodel.c_str());
+
+ string force_path = sm->force_path;
+ sm->prop->setStringValue("force_path", force_path.c_str());
+ //cout << "set force_path Sub " << force_path << endl;
+
+ if (sm->contents_node != 0)
+ sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents)));
+
+ index++;
+ submodels.push_back(sm);
+ }
+}
+
+void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
+{
+ SGPropertyNode root;
+ SGPath config = globals->resolve_aircraft_path(path);
+
+ try {
+ SG_LOG(SG_GENERAL, SG_DEBUG,
+ "Submodels: Trying to read AI submodels file: " << config.str());
+ readProperties(config.str(), &root);
+
+ } catch (const sg_exception &) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Submodels: Unable to read AI submodels file: " << config.str());
+ return;
+ }
+
+ vector<SGPropertyNode_ptr> children = root.getChildren("submodel");
+ vector<SGPropertyNode_ptr>::iterator it = children.begin();
+ vector<SGPropertyNode_ptr>::iterator end = children.end();
+
+ for (int i = 0; it != end; ++it, i++) {
+ //cout << "Reading AI submodel " << (*it)->getPath() << endl;
+ submodel* sm = new submodel;
+ SGPropertyNode * entry_node = *it;
+ sm->name = entry_node->getStringValue("name", "none_defined");
+ sm->model = entry_node->getStringValue("model", "Models/Geometry/rocket.ac");
+ sm->speed = entry_node->getDoubleValue("speed", 2329.4);
+ sm->repeat = entry_node->getBoolValue("repeat", false);
+ sm->delay = entry_node->getDoubleValue("delay", 0.25);
+ sm->count = entry_node->getIntValue("count", 1);
+ sm->slaved = entry_node->getBoolValue("slaved", false);
+ sm->x_offset = entry_node->getDoubleValue("x-offset", 0.0);
+ sm->y_offset = entry_node->getDoubleValue("y-offset", 0.0);
+ sm->z_offset = entry_node->getDoubleValue("z-offset", 0.0);
+ sm->yaw_offset = entry_node->getDoubleValue("yaw-offset", 0.0);
+ sm->pitch_offset = entry_node->getDoubleValue("pitch-offset", 0.0);
+ sm->drag_area = entry_node->getDoubleValue("eda", 0.034);
+ sm->life = entry_node->getDoubleValue("life", 900.0);
+ sm->buoyancy = entry_node->getDoubleValue("buoyancy", 0);
+ sm->wind = entry_node->getBoolValue("wind", false);
+ sm->cd = entry_node->getDoubleValue("cd", 0.193);
+ sm->weight = entry_node->getDoubleValue("weight", 0.25);
+ sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true);
+ sm->no_roll = entry_node->getBoolValue("no-roll", false);
+ sm->collision = entry_node->getBoolValue("collision", false);
+ sm->expiry = entry_node->getBoolValue("expiry", false);
+ sm->impact = entry_node->getBoolValue("impact", false);
+ sm->impact_report = entry_node->getStringValue("impact-reports");
+ sm->fuse_range = entry_node->getDoubleValue("fuse-range", 0.0);
+ sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false);
+ sm->speed_node = fgGetNode(entry_node->getStringValue("speed-prop", "none"), false);
+ sm->submodel = entry_node->getStringValue("submodel-path", "");
+ sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false);
+ sm->ext_force = entry_node->getBoolValue("external-force", false);
+ sm->force_path = entry_node->getStringValue("force-path", "");
+ sm->random = entry_node->getBoolValue("random", false);
+ sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
+
+ if (sm->contents_node != 0)
+ sm->contents = sm->contents_node->getDoubleValue();
+
+ const char *trigger_path = entry_node->getStringValue("trigger", 0);
+ if (trigger_path) {
+ sm->trigger_node = fgGetNode(trigger_path, true);
+ sm->trigger_node->setBoolValue(sm->trigger_node->getBoolValue());
+ } else {
+ sm->trigger_node = 0;
+ }
+
+ if (sm->speed_node != 0)
+ sm->speed = sm->speed_node->getDoubleValue();
+
+ sm->timer = sm->delay;
+ sm->id = index;
+ sm->first_time = false;
+ sm->serviceable = serviceable;
+ sm->sub_id = 0;
+
+ sm->prop = fgGetNode("/ai/submodels/subsubmodel", index, true);
+ sm->prop->tie("count", SGRawValuePointer<int>(&(sm->count)));
+ sm->prop->tie("repeat", SGRawValuePointer<bool>(&(sm->repeat)));
+ sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id)));
+ sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id)));
+ sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable)));
+ sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random)));
+ sm->prop->tie("slaved", SGRawValuePointer<bool>(&(sm->slaved)));
+
+ string name = sm->name;
+ sm->prop->setStringValue("name", name.c_str());
+
+ string submodel = sm->submodel;
+ sm->prop->setStringValue("submodel-path", submodel.c_str());
+ // cout << " set submodel path AI" << submodel<< endl;
+
+ string force_path = sm->force_path;
+ sm->prop->setStringValue("force_path", force_path.c_str());
+ //cout << "set force_path AI" << force_path << endl;
+
+ if (sm->contents_node != 0)
+ sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents)));
+
+ index++;
+ subsubmodels.push_back(sm);
+ }
+}
+
+void FGSubmodelMgr::loadSubmodels()
+{
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Submodels: Loading sub submodels");
+
+ _found_sub = false;
+
+ submodel_iterator = submodels.begin();
+
+ while (submodel_iterator != submodels.end()) {
+ string submodel = (*submodel_iterator)->submodel;
+ if (!submodel.empty()) {
+ //int id = (*submodel_iterator)->id;
+ bool serviceable = true;
+ SG_LOG(SG_GENERAL, SG_DEBUG, "found path sub sub "
+ << submodel
+ << " index " << index
+ << " name " << (*submodel_iterator)->name);
+
+ if ((*submodel_iterator)->sub_id == 0){
+ (*submodel_iterator)->sub_id = index;
+ _found_sub = true;
+ setSubData(index, submodel, serviceable);
+ }
+ }
+
+ ++submodel_iterator;
+ } // end while
+
+ subsubmodel_iterator = subsubmodels.begin();
+
+ while (subsubmodel_iterator != subsubmodels.end()) {
+
+ submodels.push_back(*subsubmodel_iterator);
+ ++subsubmodel_iterator;
+ } // end while
+
+ subsubmodels.clear();
+
+ //submodel_iterator = submodels.begin();
+
+ //int subcount = 0;
+
+ //while (submodel_iterator != submodels.end()) {
+ // int id = (*submodel_iterator)->id;
+ // subcount++;
+
+ // SG_LOG(SG_GENERAL, SG_ALERT,"after pushback "
+ // << " parent id " << id
+ // << " name " << (*submodel_iterator)->name
+ // << " sub id " << (*submodel_iterator)->sub_id
+ // << " subcount "<< subcount);
+
+ // ++submodel_iterator;
+ //}
+}
+
+SGVec3d FGSubmodelMgr::getCartOffsetPos() const{
+
+ // convert geodetic positions to geocentered
+ SGVec3d cartuserPos = SGVec3d::fromGeod(userpos);
+ // Transform to the right coordinate frame, configuration is done in
+ // the x-forward, y-right, z-up coordinates (feet), computation
+ // in the simulation usual body x-forward, y-right, z-down coordinates
+ // (meters) )
+
+ SGVec3d _off(_x_offset * SG_FEET_TO_METER,
+ _y_offset * SG_FEET_TO_METER,
+ -_z_offset * SG_FEET_TO_METER);
+
+ // Transform the user position to the horizontal local coordinate system.
+ SGQuatd hlTrans = SGQuatd::fromLonLat(userpos);
+
+ // and postrotate the orientation of the user model wrt the horizontal
+ // local frame
+ hlTrans *= SGQuatd::fromYawPitchRollDeg(
+ IC.azimuth,
+ IC.elevation,
+ IC.roll);
+
+ // The offset converted to the usual body fixed coordinate system
+ // rotated to the earth-fixed coordinates axis
+ SGVec3d off = hlTrans.backTransform(_off);
+
+ // Add the position offset of the user model to get the geocentered position
+ SGVec3d offsetPos = cartuserPos + off;
+ return offsetPos;
+}
+
+void FGSubmodelMgr::setOffsetPos(){
+ // convert the offset geocentered position to geodetic
+ SGVec3d cartoffsetPos = getCartOffsetPos();
+
+ SGGeodesy::SGCartToGeod(cartoffsetPos, offsetpos);
+
+ //cout << "OFFSET POS" << offsetpos.getElevationFt();
+
+}
+
+void FGSubmodelMgr::valueChanged(SGPropertyNode *prop)
+{
+ return; // this isn't working atm
+
+ const char* _model_added = _model_added_node->getStringValue();
+
+ basic_string <char>::size_type indexCh2b;
+
+ string str2 = _model_added;
+ const char *cstr2b = "multiplayer";
+ indexCh2b = str2.find( cstr2b, 0 );
+
+ if (indexCh2b != string::npos ){ // we will ignore Ballistic Objects - there are potentially too many
+
+ //cout << "Submodels: model added - " << str2 <<" read path "<< endl;
+ //return;
+ SGPropertyNode *a_node = fgGetNode(_model_added, true);
+ SGPropertyNode *sub_node = a_node->getChild("sim", 0, true);
+ SGPropertyNode_ptr path_node = sub_node->getChild("path", 0, true);
+ SGPropertyNode_ptr callsign_node = a_node->getChild("callsign", 0, true);
+
+ string callsign = callsign_node->getStringValue();
+
+ //cout << "Submodels: model added - " << callsign <<" read callsign "<< endl;
+ return;
+
+ } else {
+ cout << "model added - " << str2 <<" returning "<< endl;
+ return;
+ }
+
+}
+
+void FGSubmodelMgr::setParentNode(int id) {
+
+ const SGPropertyNode_ptr ai = fgGetNode("/ai/models", true);
+
+ for (int i = ai->nChildren() - 1; i >= -1; i--) {
+ SGPropertyNode_ptr model;
+
+ if (i < 0) { // last iteration: selected model
+ model = _selected_ac;
+ } else {
+ model = ai->getChild(i);
+ string path = ai->getPath();
+ const string name = model->getStringValue("name");
+ int parent_id = model->getIntValue("id");
+ if (!model->nChildren()){
+ continue;
+ }
+ if (parent_id == id) {
+ _selected_ac = model; // save selected model for last iteration
+ break;
+ }
+
+ }
+ if (!model)
+ continue;
+
+ }// end for loop
+
+ if (_selected_ac != 0){
+
+ //cout << " parent node found"<< endl;
+
+ const string name = _selected_ac->getStringValue("name");
+ IC.lat = _selected_ac->getDoubleValue("position/latitude-deg");
+ IC.lon = _selected_ac->getDoubleValue("position/longitude-deg");
+ IC.alt = _selected_ac->getDoubleValue("position/altitude-ft");
+ IC.roll = _selected_ac->getDoubleValue("orientation/roll-deg");
+ IC.elevation = _selected_ac->getDoubleValue("orientation/pitch-deg");
+ IC.azimuth = _selected_ac->getDoubleValue("orientation/true-heading-deg");
+ IC.speed = _selected_ac->getDoubleValue("velocities/true-airspeed-kt") * SG_KT_TO_FPS;
+ IC.speed_down_fps = -_selected_ac->getDoubleValue("velocities/vertical-speed-fps");
+ IC.speed_east_fps = _selected_ac->getDoubleValue("velocities/speed-east-fps");
+ IC.speed_north_fps = _selected_ac->getDoubleValue("velocities/speed-north-fps");
+
+ //cout << name << " IC.speed " << IC.speed << endl;
+
+ } else {
+ SG_LOG(SG_GENERAL, SG_ALERT, "AISubmodel: parent node not found ");
+ }
+
+}
+// end of submodel.cxx