+void FGAIBallistic::setFuseRange(double f) {
+ _fuse_range = f;
+}
+
+void FGAIBallistic::setSubID(int i) {
+ _subID = i;
+}
+
+void FGAIBallistic::setSubmodel(const string& s) {
+ _submodel = s;
+}
+
+void FGAIBallistic::setGroundOffset(double g) {
+ _ground_offset = g;
+}
+
+void FGAIBallistic::setLoadOffset(double l) {
+ _load_offset = l;
+}
+
+double FGAIBallistic::getLoadOffset() const {
+ return _load_offset;
+}
+
+void FGAIBallistic::setSlaved(bool s) {
+ _slave_to_ac = s;
+}
+
+void FGAIBallistic::setContentsPath(const string& path) {
+
+ _contents_path = path;
+
+ if (!path.empty()) {
+ _contents_node = fgGetNode(path.c_str(), true);
+ }
+}
+
+void FGAIBallistic::setContentsNode(SGPropertyNode_ptr node) {
+
+ if (node != 0) {
+ _contents_node = node;
+ _contents_path = _contents_node->getDisplayName();
+ }
+}
+
+void FGAIBallistic::setParentNodes(SGPropertyNode_ptr node) {
+
+ if (node != 0) {
+ _pnode = node;
+ _p_pos_node = _pnode->getChild("position", 0, true);
+ _p_lat_node = _p_pos_node->getChild("latitude-deg", 0, true);
+ _p_lon_node = _p_pos_node->getChild("longitude-deg", 0, true);
+ _p_alt_node = _p_pos_node->getChild("altitude-ft", 0, true);
+ _p_agl_node = _p_pos_node->getChild("altitude-agl-ft", 0, true);
+
+
+ _p_ori_node = _pnode->getChild("orientation", 0, true);
+ _p_pch_node = _p_ori_node->getChild("pitch-deg", 0, true);
+ _p_rll_node = _p_ori_node->getChild("roll-deg", 0, true);
+ _p_hdg_node = _p_ori_node->getChild("true-heading-deg",0, true);
+
+ _p_vel_node = _pnode->getChild("velocities", 0, true);
+ _p_spd_node = _p_vel_node->getChild("true-airspeed-kt", 0, true);
+ }
+
+}
+
+void FGAIBallistic::setParentPos() {
+
+ if (_pnode != 0) {
+ //cout << "set parent pos" << endl;
+
+ double lat = _p_lat_node->getDoubleValue();
+ double lon = _p_lon_node->getDoubleValue();
+ double alt = _p_alt_node->getDoubleValue();
+
+ _parentpos.setLongitudeDeg(lon);
+ _parentpos.setLatitudeDeg(lat);
+ _parentpos.setElevationFt(alt);
+
+ }
+
+}
+
+bool FGAIBallistic::getSlaved() const {
+ return _slave_to_ac;
+}
+
+double FGAIBallistic::getMass() const {
+ return _mass;
+}
+
+double FGAIBallistic::getContents() {
+ if(_contents_node){
+ _contents_lb = _contents_node->getChild("level-lbs",0,1)->getDoubleValue();
+ }
+ return _contents_lb;
+}
+
+void FGAIBallistic::setContents(double c) {
+ if(_contents_node)
+ _contents_lb = _contents_node->getChild("level-gal_us",0,1)->setDoubleValue(c);
+}
+
+void FGAIBallistic::setSlavedLoad(bool l) {
+ _slave_load_to_ac = l;
+}
+
+bool FGAIBallistic::getSlavedLoad() const {
+ return _slave_load_to_ac;
+}
+
+void FGAIBallistic::setForcePath(const string& p) {
+ _force_path = p;
+ if (!_force_path.empty()) {
+ SGPropertyNode *fnode = fgGetNode(_force_path.c_str(), 0, true );
+ _force_node = fnode->getChild("force-lb", 0, true);
+ _force_azimuth_node = fnode->getChild("force-azimuth-deg", 0, true);
+ _force_elevation_node = fnode->getChild("force-elevation-deg", 0, true);
+ }
+}
+
+bool FGAIBallistic::getHtAGL(double start){
+
+ if (getGroundElevationM(SGGeod::fromGeodM(pos, start),
+ _elevation_m, &_material)) {
+ _ht_agl_ft = pos.getElevationFt() - _elevation_m * SG_METER_TO_FEET;
+
+ if (_material) {
+ const vector<string>& names = _material->get_names();
+ _solid = _material->get_solid();
+ _load_resistance = _material->get_load_resistance();
+ _frictionFactor =_material->get_friction_factor();
+
+ if (!names.empty())
+ props->setStringValue("material/name", names[0].c_str());
+ else
+ props->setStringValue("material/name", "");
+
+ _mat_name = names[0];
+
+ //cout << "material " << _mat_name
+ //<< " solid " << _solid
+ //<< " load " << _load_resistance
+ //<< " frictionFactor " << _frictionFactor
+ //<< endl;
+
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+
+}
+
+double FGAIBallistic::getRecip(double az){
+ // calculate the reciprocal of the input azimuth
+ if(az - 180 < 0){
+ return az + 180;
+ } else {
+ return az - 180;
+ }
+}
+
+void FGAIBallistic::setPch(double e, double dt, double coeff){
+ double c = dt / (coeff + dt);
+ pitch = (e * c) + (pitch * (1 - c));
+}
+
+void FGAIBallistic::setBnk(double r, double dt, double coeff){
+ double c = dt / (coeff + dt);
+ roll = (r * c) + (roll * (1 - c));
+}
+
+void FGAIBallistic::setSpd(double s, double dt, double coeff){
+ double c = dt / (coeff + dt);
+ _speed = (s * c) + (_speed * (1 - c));
+}
+
+void FGAIBallistic::setHt(double h, double dt, double coeff){
+ double c = dt / (coeff + dt);
+ _height = (h * c) + (_height * (1 - c));
+}
+
+int FGAIBallistic::setHdg(double tgt_hdg, double dt, double coeff){
+ double recip = getRecip(hdg);
+ double c = dt / (coeff + dt);
+ //we need to ensure that we turn the short way to the new hdg
+ if (tgt_hdg < recip && tgt_hdg < hdg && hdg > 180) {
+ hdg = ((tgt_hdg + 360) * c) + (hdg * (1 - c));
+// cout << "case 1: right turn" << endl;
+ } else if (tgt_hdg > recip && tgt_hdg > hdg && hdg <= 180){
+ hdg = ((tgt_hdg - 360) * c) + (hdg * (1 - c));
+// cout << "case 2: left turn" << endl;
+ } else {
+ hdg = (tgt_hdg * c) + (hdg * (1 - c));
+// cout << "case 4: left turn" << endl;
+ }
+ return -1;
+}
+
+double FGAIBallistic::getTgtXOffset() const {
+ return _tgt_x_offset;
+}
+
+double FGAIBallistic::getTgtYOffset() const {
+ return _tgt_y_offset;
+}
+
+double FGAIBallistic::getTgtZOffset() const {
+ return _tgt_z_offset;
+}
+
+void FGAIBallistic::setTgtXOffset(double x){
+ _tgt_x_offset = x;
+}
+
+void FGAIBallistic::setTgtYOffset(double y){
+ _tgt_y_offset = y;
+}
+
+void FGAIBallistic::setTgtZOffset(double z){
+ _tgt_z_offset = z;
+}
+
+void FGAIBallistic::slaveToAC(double dt){
+
+ double hdg, pch, rll, agl = 0;
+
+ if (_pnode != 0) {
+ setParentPos();
+ hdg = _p_hdg_node->getDoubleValue();
+ pch = _p_pch_node->getDoubleValue();
+ rll = _p_rll_node->getDoubleValue();
+ agl = _p_agl_node->getDoubleValue();
+ setOffsetPos(_parentpos, hdg, pch, rll);
+ setSpeed(_p_spd_node->getDoubleValue());
+ }else {
+ hdg = manager->get_user_heading();
+ pch = manager->get_user_pitch();
+ rll = manager->get_user_roll();
+ agl = manager->get_user_agl();
+ setOffsetPos(userpos, hdg, pch, rll);
+ setSpeed(manager->get_user_speed());
+ }
+
+ pos.setLatitudeDeg(_offsetpos.getLatitudeDeg());
+ pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
+ pos.setElevationFt(_offsetpos.getElevationFt());
+ setHeading(hdg);
+ setPitch(pch + _pitch_offset);
+ setBank(rll + _roll_offset);
+ setOffsetVelocity(dt, pos);
+
+ //update the mass (slugs)
+ _mass = (_weight_lb + getContents()) / slugs_to_lbs;
+
+ _impact_reported = false;
+
+ //cout << _name << " _mass "<<_mass <<" " << getContents()
+ //<< " " << getContents() / slugs_to_lbs << " weight " << _weight_lb << endl;
+ // cout << _name << " update hs " << hs << " vs " << vs << endl;