]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/submodel.cxx
Interim windows build fix
[flightgear.git] / src / AIModel / submodel.cxx
index acec600c6d0537000250d585aa01a4dc12eed9cd..b3000f9a39ec6770a5e4776e7e724e6ff5b542bc 100644 (file)
@@ -259,11 +259,13 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
     ballist->setName(sm->name);
     ballist->setSlaved(sm->slaved);
     ballist->setRandom(sm->random);
-    ballist->setRandomness(sm->randomness);
+    ballist->setLifeRandomness(sm->life_randomness->get_value());
     ballist->setLatitude(offsetpos.getLatitudeDeg());
     ballist->setLongitude(offsetpos.getLongitudeDeg());
     ballist->setAltitude(offsetpos.getElevationFt());
+    ballist->setAzimuthRandomError(sm->azimuth_error->get_value());
     ballist->setAzimuth(IC.azimuth);
+    ballist->setElevationRandomError(sm->elevation_error->get_value());
     ballist->setElevation(IC.elevation);
     ballist->setRoll(IC.roll);
     ballist->setSpeed(IC.speed / SG_KT_TO_FPS);
@@ -274,6 +276,7 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
     ballist->setLife(sm->life);
     ballist->setBuoyancy(sm->buoyancy);
     ballist->setWind(sm->wind);
+    ballist->setCdRandomness(sm->cd_randomness->get_value());
     ballist->setCd(sm->cd);
     ballist->setStabilisation(sm->aero_stabilised);
     ballist->setNoRoll(sm->no_roll);
@@ -287,9 +290,9 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
     ballist->setForceStabilisation(sm->force_stabilised);
     ballist->setExternalForce(sm->ext_force);
     ballist->setForcePath(sm->force_path.c_str());
-    ballist->setXoffset(sm->x_offset);
-    ballist->setYoffset(sm->y_offset);
-    ballist->setZoffset(sm->z_offset);
+    ballist->setXoffset(_x_offset);
+    ballist->setYoffset(_y_offset);
+    ballist->setZoffset(_z_offset);
     ballist->setPitchoffset(sm->pitch_offset->get_value());
     ballist->setYawoffset(sm->yaw_offset->get_value());
     ballist->setParentNodes(_selected_ac);
@@ -342,11 +345,6 @@ void FGSubmodelMgr::transform(submodel *sm)
     if (sm->speed_node != 0)
         sm->speed = sm->speed_node->getDoubleValue();
 
-    double yaw_offset = sm->yaw_offset->get_value();
-    double pitch_offset = sm->pitch_offset->get_value();
-
-    //cout << " name " << name << " id " << id << " sub id" << sub_id << endl;
-
     // set the Initial Conditions for the types of submodel parent 
 
     if (_impact || _hit || _expiry) {
@@ -382,79 +380,62 @@ void FGSubmodelMgr::transform(submodel *sm)
         setParentNode(id);
     }
 
-    //cout << "Submodel: setting IC "<< name << endl;
-    //cout << "heading " << IC.azimuth << endl ;
-    //cout << "speed down " << IC.speed_down_fps << endl ;
-    //cout << "speed east " << IC.speed_east_fps << endl ;
-    //cout << "speed north " << IC.speed_north_fps << endl ;
-    //cout << "parent speed fps in " << IC.speed << "sm speed in " << sm->speed << endl ;
-    //cout << "lat " << IC.lat;
-    //cout << "alt " << IC.alt <<  endl ;
-
     // Set the Initial Conditions that are common to all types of parent
     IC.wind_from_east =  _user_wind_from_east_node->getDoubleValue();
     IC.wind_from_north = _user_wind_from_north_node->getDoubleValue();
 
-    //cout << "wind e " << IC.wind_from_east << " n " << IC.wind_from_north << endl;
-
     userpos.setLatitudeDeg(IC.lat);
     userpos.setLongitudeDeg(IC.lon);
     userpos.setElevationFt(IC.alt);
 
-    _x_offset = sm->x_offset;
-    _y_offset = sm->y_offset;
-    _z_offset = sm->z_offset;
+    if (sm->offsets_in_meter) {
+        _x_offset = -sm->x_offset->get_value() * SG_METER_TO_FEET;
+        _y_offset =  sm->y_offset->get_value() * SG_METER_TO_FEET;
+        _z_offset =  sm->z_offset->get_value() * SG_METER_TO_FEET;
+    }
+    else {
+        _x_offset = sm->x_offset->get_value();
+        _y_offset = sm->y_offset->get_value();
+        _z_offset = sm->z_offset->get_value();
+    }
 
     setOffsetPos();
 
-    // Pre-process the trig functions
-    cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS);
-    sinRx = sin(-IC.roll * SG_DEGREES_TO_RADIANS);
-    cosRy = cos(-IC.elevation * SG_DEGREES_TO_RADIANS);
-    sinRy = sin(-IC.elevation * SG_DEGREES_TO_RADIANS);
-    cosRz = cos(IC.azimuth * SG_DEGREES_TO_RADIANS);
-    sinRz = sin(IC.azimuth * SG_DEGREES_TO_RADIANS);
-
-
-    // Get submodel initial velocity vector angles in XZ and XY planes.
-    // This vector should be added to aircraft's vector.
-    IC.elevation += (yaw_offset * sinRx) + (pitch_offset * cosRx);
-    IC.azimuth   += (yaw_offset * cosRx) - (pitch_offset * sinRx);
+    // Compute initial orientation using yaw and pitch offsets and parent's orientation
+    const double yaw_offset = sm->yaw_offset->get_value();
+    const double pitch_offset = sm->pitch_offset->get_value();
 
-    // Calculate the total speed north
-    IC.total_speed_north = sm->speed * cos(IC.elevation * SG_DEGREES_TO_RADIANS)
-            * cos(IC.azimuth * SG_DEGREES_TO_RADIANS) + IC.speed_north_fps;
+    SGQuatd ic_quat = SGQuatd::fromYawPitchRollDeg(IC.azimuth, IC.elevation, IC.roll);
+    ic_quat *= SGQuatd::fromYawPitchRollDeg(yaw_offset, pitch_offset, 0.0);
 
-    // Calculate the total speed east
-    IC.total_speed_east = sm->speed * cos(IC.elevation * SG_DEGREES_TO_RADIANS)
-            * sin(IC.azimuth * SG_DEGREES_TO_RADIANS) + IC.speed_east_fps;
+    // Calculate total speed using speeds of submodel and parent
+    SGVec3d total_speed = SGVec3d(IC.speed_north_fps, IC.speed_east_fps, IC.speed_down_fps);
+    total_speed += ic_quat.rotate(SGVec3d(sm->speed, 0, 0));
 
-    // Calculate the total speed down
-    IC.total_speed_down = sm->speed * -sin(IC.elevation * SG_DEGREES_TO_RADIANS)
-            + IC.speed_down_fps;
-
-    // Re-calculate speed, elevation and azimuth
-    IC.speed = sqrt(IC.total_speed_north * IC.total_speed_north
-            + IC.total_speed_east * IC.total_speed_east
-            + IC.total_speed_down * IC.total_speed_down);
+    IC.speed = length(total_speed);
 
     // If speeds are low this calculation can become unreliable
     if (IC.speed > 1) {
-        IC.azimuth = atan2(IC.total_speed_east, IC.total_speed_north) * SG_RADIANS_TO_DEGREES;
-        //        cout << "azimuth1 " << IC.azimuth<<endl;
+        const double total_speed_north = total_speed.x();
+        const double total_speed_east  = total_speed.y();
+        const double total_speed_down  = total_speed.z();
+
+        IC.azimuth = atan2(total_speed_east, total_speed_north) * SG_RADIANS_TO_DEGREES;
 
         // Rationalize the output
         if (IC.azimuth < 0)
             IC.azimuth += 360;
         else if (IC.azimuth >= 360)
             IC.azimuth -= 360;
-        // cout << "azimuth2 " << IC.azimuth<<endl;
 
-        IC.elevation = -atan(IC.total_speed_down / sqrt(IC.total_speed_north
-            * IC.total_speed_north + IC.total_speed_east * IC.total_speed_east))
+        IC.elevation = -atan(total_speed_down / sqrt(total_speed_north
+            * total_speed_north + total_speed_east * total_speed_east))
             * SG_RADIANS_TO_DEGREES;
     }
-    //cout << "IC.speed " << IC.speed / SG_KT_TO_FPS << endl;
+    else {
+        double ic_roll;
+        ic_quat.getEulerDeg(IC.azimuth, IC.elevation, ic_roll);
+    }
 }
 
 void FGSubmodelMgr::updatelat(double lat)
@@ -527,9 +508,6 @@ void FGSubmodelMgr::setData(int id, const string& path, bool serviceable, const
         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->drag_area        = entry_node->getDoubleValue("eda", 0.034);
         sm->life             = entry_node->getDoubleValue("life", 900.0);
         sm->buoyancy         = entry_node->getDoubleValue("buoyancy", 0);
@@ -550,16 +528,87 @@ void FGSubmodelMgr::setData(int id, const string& path, bool serviceable, const
         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);
 
         SGPropertyNode_ptr prop_root = fgGetNode("/", true);
         SGPropertyNode n;
+        SGPropertyNode_ptr a, b;
+
+        // Offsets
+        a = entry_node->getNode("offsets", false);
+        sm->offsets_in_meter = (a != 0);
 
-        SGPropertyNode_ptr a = entry_node->getNode("yaw-offset");
-        sm->yaw_offset   = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n );
+        if (a) {
+            b = a->getNode("x-m");
+            sm->x_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
 
-        a = entry_node->getNode("pitch-offset");
-        sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n );
+            b = a->getNode("y-m");
+            sm->y_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+
+            b = a->getNode("z-m");
+            sm->z_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+
+            b = a->getNode("heading-deg");
+            sm->yaw_offset   = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+
+            b = a->getNode("pitch-deg");
+            sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+        }
+        else {
+            bool old = false;
+
+            b = entry_node->getNode("x-offset");
+            sm->x_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+            if (b) old = true;
+
+            b = entry_node->getNode("y-offset");
+            sm->y_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+            if (b) old = true;
+
+            b = entry_node->getNode("z-offset");
+            sm->z_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+            if (b) old = true;
+
+            b = entry_node->getNode("yaw-offset");
+            sm->yaw_offset   = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+            if (b) old = true;
+
+            b = entry_node->getNode("pitch-offset");
+            sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+            if (b) old = true;
+
+#if defined(ENABLE_DEV_WARNINGS)
+            if (old) {
+                SG_LOG(SG_AI, SG_WARN, "Submodels: <*-offset> is deprecated. Use <offsets> instead");
+            }
+#endif
+        }
+
+        // Randomness
+        a = entry_node->getNode("randomness", true);
+
+        // Maximum azimuth randomness error in degrees
+        b = a->getNode("azimuth");
+        sm->azimuth_error   = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+
+        // Maximum elevation randomness error in degrees
+        b = a->getNode("elevation");
+        sm->elevation_error = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n);
+
+        // Randomness of Cd (plus or minus)
+        b = a->getNode("cd");
+        if (!b) {
+            b = a->getNode("cd", true);
+            b->setDoubleValue(0.1);
+        }
+        sm->cd_randomness   = new FGXMLAutopilot::InputValue(*prop_root, *b);
+
+        // Randomness of life (plus or minus)
+        b = a->getNode("life");
+        if (!b) {
+            b = a->getNode("life", true);
+            b->setDoubleValue(0.5);
+        }
+        sm->life_randomness = new FGXMLAutopilot::InputValue(*prop_root, *b);
 
         if (sm->contents_node != 0)
             sm->contents = sm->contents_node->getDoubleValue();