]> git.mxchange.org Git - flightgear.git/commitdiff
Add "expiry" parameter and other changes to implement persistent contrails using...
authorVivian Meazza <vivian.meazza@lineone.net>
Wed, 28 Jul 2010 21:20:50 +0000 (22:20 +0100)
committerVivian Meazza <vivian.meazza@lineone.net>
Wed, 28 Jul 2010 21:20:50 +0000 (22:20 +0100)
Signed-off-by: Vivian Meazza <vivian.meazza@lineone.net>
src/AIModel/AIBallistic.cxx
src/AIModel/AIBallistic.hxx
src/AIModel/AIBase.cxx
src/AIModel/submodel.cxx
src/AIModel/submodel.hxx

index 68a388e750b561aef5137643ba755349c6179ef6..63409b81aa511f588b31f027dfef6d7c4755ef7a 100644 (file)
@@ -65,7 +65,8 @@ FGAIBallistic::FGAIBallistic(object_type ot) :
     _report_impact(false),
     _external_force(false),
     _impact_report_node(fgGetNode("/ai/models/model-impact", true)),
-    _old_height(0)
+    _old_height(0),
+       _elapsed_time(0)
 
 {
     no_roll = false;
@@ -81,7 +82,8 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
 
     FGAIBase::readFromScenario(scFileNode);
 
-    //setPath(scFileNode->getStringValue("model", "Models/Geometry/rocket.ac"));
+    //setPath(scFileNode->getStringValue("model", "Models/Geometry/rocket.ac")); 
+       setRandom(scFileNode->getBoolValue("random", false));
     setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0));
     setElevation(scFileNode->getDoubleValue("elevation", 0));
     setDragArea(scFileNode->getDoubleValue("eda", 0.007));
@@ -94,10 +96,11 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
     setCd(scFileNode->getDoubleValue("cd", 0.029));
     //setMass(scFileNode->getDoubleValue("mass", 0.007));
     setWeight(scFileNode->getDoubleValue("weight", 0.25));
-    setStabilisation(scFileNode->getBoolValue("aero-stabilized", false));
+    setStabilisation(scFileNode->getBoolValue("aero-stabilised", false));
     setNoRoll(scFileNode->getBoolValue("no-roll", false));
-    setRandom(scFileNode->getBoolValue("random", false));
     setImpact(scFileNode->getBoolValue("impact", false));
+       setExpiry(scFileNode->getBoolValue("expiry", false));
+       setCollision(scFileNode->getBoolValue("collision", false));
     setImpactReportNode(scFileNode->getStringValue("impact-reports"));
     setName(scFileNode->getStringValue("name", "Rocket"));
     setFuseRange(scFileNode->getDoubleValue("fuse-range", 0.0));
@@ -105,7 +108,7 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
     setSubID(scFileNode->getIntValue("SubID", 0));
     setExternalForce(scFileNode->getBoolValue("external-force", false));
     setForcePath(scFileNode->getStringValue("force-path", ""));
-    setForceStabilisation(scFileNode->getBoolValue("force-stabilized", false));
+    setForceStabilisation(scFileNode->getBoolValue("force-stabilised", false));
     setXoffset(scFileNode->getDoubleValue("x-offset", 0.0));
     setYoffset(scFileNode->getDoubleValue("y-offset", 0.0));
     setZoffset(scFileNode->getDoubleValue("z-offset", 0.0));
@@ -117,7 +120,6 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
     setSlaved(scFileNode->getBoolValue("slaved", false));
     setSlavedLoad(scFileNode->getBoolValue("slaved-load", false));
     setContentsNode(scFileNode->getStringValue("contents"));
-    setRandom(scFileNode->getBoolValue("random", false));
 }
 
 bool FGAIBallistic::init(bool search_in_AI_path) {
@@ -125,6 +127,16 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
 
     _impact_reported = false;
     _collision_reported = false;
+       _expiry_reported = false;
+
+       _impact_lat = 0;
+    _impact_lon = 0;
+    _impact_elev = 0;
+    _impact_hdg = 0;
+    _impact_pitch = 0;
+    _impact_roll = 0;
+    _impact_speed = 0;
+
     invisible = false;
 
     _elapsed_time += (sg_random() * 100);
@@ -132,6 +144,8 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
     props->setStringValue("material/name", "");
     props->setStringValue("name", _name.c_str());
     props->setStringValue("submodels/path", _submodel.c_str());
+       props->setStringValue("force/path", _force_path.c_str());
+       //props->setStringValue("vector/path", _vector_path.c_str());
 
     // start with high value so that animations don't trigger yet
     _ht_agl_ft = 1e10;
@@ -264,7 +278,14 @@ void FGAIBallistic::update(double dt) {
 }
 
 void FGAIBallistic::setAzimuth(double az) {
-    hdg = _azimuth = az;
+    
+               
+       if (_random)
+               hdg = _azimuth = (az - 5 ) + (10 * sg_random());
+       else 
+               hdg = _azimuth = az;
+
+       //cout << _name << " init hdg " << hdg << " random " << _random << endl;
 }
 
 void FGAIBallistic::setElevation(double el) {
@@ -292,7 +313,12 @@ void FGAIBallistic::setDragArea(double a) {
 }
 
 void FGAIBallistic::setLife(double seconds) {
-    life = seconds;
+
+       if (_random){
+               life = seconds * _randomness + (seconds * (1 -_randomness) * sg_random());
+               //cout << "life " << life << endl;
+       } else
+               life = seconds;
 }
 
 void FGAIBallistic::setBuoyancy(double fpss) {
@@ -323,6 +349,10 @@ void FGAIBallistic::setWeight(double w) {
     _weight_lb = w;
 }
 
+void FGAIBallistic::setRandomness(double r) {
+    _randomness = r;
+}
+
 void FGAIBallistic::setRandom(bool r) {
     _random = r;
 }
@@ -335,9 +365,9 @@ void FGAIBallistic::setCollision(bool c) {
     _report_collision = c;
 }
 
-void FGAIBallistic::setExpiry(bool e) {\r
-    _report_expiry = e;\r
-//     cout <<  "_report_expiry " << _report_expiry << endl;\r
+void FGAIBallistic::setExpiry(bool e) {
+    _report_expiry = e;
+       //cout <<  "_report_expiry " << _report_expiry << endl;
 }
 
 void FGAIBallistic::setExternalForce(bool f) {
@@ -486,17 +516,17 @@ void FGAIBallistic::setHt(double h, double dt, double coeff){
 }
 
 void FGAIBallistic::setHdg(double az, 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 (az < recip && az < hdg && hdg > 180) {
-        hdg = ((az + 360) * c) + (hdg * (1 - c));
-    } else if (az > recip && az > hdg && hdg <= 180){
-        hdg = ((az - 360) * c) + (hdg * (1 - c));
-    } else {
-        hdg = (az * c) + (hdg * (1 - c));
-    }
-    }
+       double recip = getRecip(hdg);
+       double c = dt / (coeff + dt);
+       //we need to ensure that we turn the short way to the new hdg
+       if (az < recip && az < hdg && hdg > 180) {
+               hdg = ((az + 360) * c) + (hdg * (1 - c));
+       } else if (az > recip && az > hdg && hdg <= 180){
+               hdg = ((az - 360) * c) + (hdg * (1 - c));
+       } else {
+               hdg = (az * c) + (hdg * (1 - c));
+       }
+}
 
 double  FGAIBallistic::getTgtXOffset() const {
     return _tgt_x_offset;
@@ -543,21 +573,22 @@ void FGAIBallistic::Run(double dt) {
     _life_timer += dt;
 
     // if life = -1 the object does not die
-       if (_life_timer > life && life != -1){\r
-\r
-               if (_report_expiry && !_expiry_reported){\r
-                       handle_expiry();\r
-               } else\r
-                       setDie(true);\r
-\r
+       if (_life_timer > life && life != -1){
+
+               if (_report_expiry && !_expiry_reported){
+                       //cout<<"AIBallistic: expiry"<< endl;
+                       handle_expiry();
+               } else
+                       setDie(true);
+
        }
 
     //set the contents in the appropriate tank or other property in the parent to zero
     setContents(0);
 
-    //randomise Cd by +- 5%
+    //randomise Cd by +- 10%
     if (_random)
-        _Cd = _Cd * 0.95 + (0.05 * sg_random());
+        _Cd = _Cd * 0.90 + (0.10 * sg_random());
 
     // Adjust Cd by Mach number. The equations are based on curves
     // for a conventional shell/bullet (no boat-tail).
@@ -630,12 +661,13 @@ void FGAIBallistic::Run(double dt) {
     double friction_force_speed_east_deg_sec = 0;
     double force_elevation_deg = 0;
 
-    if (_external_force) {
+       if (_external_force) {
+
         SGPropertyNode *n = fgGetNode(_force_path.c_str(), true);
         double force_lbs            = n->getChild("force-lb", 0, true)->getDoubleValue();
         force_elevation_deg         = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
         double force_azimuth_deg    = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue();
-
+               
         //resolve force into vertical and horizontal components:
         double v_force_lbs = force_lbs * sin( force_elevation_deg * SG_DEGREES_TO_RADIANS );
         h_force_lbs = force_lbs * cos( force_elevation_deg * SG_DEGREES_TO_RADIANS );
@@ -764,14 +796,19 @@ void FGAIBallistic::Run(double dt) {
     if (_azimuth < 0)
         _azimuth += 360;
 
+       //cout << "_azimuth " << _azimuth << " hdg "<<  hdg << endl;
+
     if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter
+               cout<< "_aero_stabilised "<< endl;
         const double coeff = 0.9;
 
         // we assume a symetrical MI about the pitch and yaw axis
         setPch(_elevation, dt, coeff);
         setHdg(_azimuth, dt, coeff);
     } else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter
-        const double coeff = 0.9;
+        //cout<< "_force_stabilised "<< endl;
+               
+               const double coeff = 0.9;
         double ratio = h_force_lbs/(_mass * slugs_to_lbs);
 
         if (ratio >  1) ratio =  1;
@@ -822,17 +859,18 @@ void FGAIBallistic::handle_impact() {
     }
 }
 
-void FGAIBallistic::handle_expiry() {\r
-\r
-        report_impact(pos.getElevationM());\r
-        _expiry_reported = true;\r
-\r
-               SG_LOG(SG_GENERAL, SG_ALERT, "AIBallistic: expiry");\r
-        //if (life == -1){\r
-        //    invisible = true;\r
-        //} else if (_subID == 0)  // kill the AIObject if there is no subsubmodel\r
-        //    setDie(true);\r
-   \r
+void FGAIBallistic::handle_expiry() {
+       
+               SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
+
+        report_impact(pos.getElevationM());
+        _expiry_reported = true;
+
+        //if (life == -1){
+        //    invisible = true;
+        //} else if (_subID == 0)  // kill the AIObject if there is no subsubmodel
+        //    setDie(true);
+   
 }
 
 void FGAIBallistic::handle_collision()
@@ -883,7 +921,7 @@ SGVec3d FGAIBallistic::getCartHitchPos() const{
 
     // convert geodetic positions to geocentered
     SGVec3d cartuserPos = getCartUserPos();
-    SGVec3d cartPos = getCartPos();
+    //SGVec3d cartPos = getCartPos();
 
     // Transform to the right coordinate frame, configuration is done in
     // the x-forward, y-right, z-up coordinates (feet), computation
index 29b51fffdc521af1314de942dc574023be83165d..84fcc8ee76fdfacf2156747e64356e04152bf34b 100644 (file)
@@ -68,6 +68,7 @@ public:
     void setWeight( double w );
     void setNoRoll( bool nr );
     void setRandom( bool r );
+       void setRandomness( double r );
     void setName(const string&);
     void setCollision(bool c);
        void setExpiry(bool e);
@@ -151,7 +152,8 @@ private:
     bool   _wind;            // if true, local wind will be applied to object
     double _Cd;              // drag coefficient
     double _mass;            // slugs
-    bool   _random;          // modifier for Cd
+    bool   _random;          // modifier for Cd, life, az
+       double _randomness;              // dimension for _random
     double _load_resistance; // ground load resistanc N/m^2
     double _frictionFactor;  // dimensionless modifier for Coefficient of Friction
     bool   _solid;           // if true ground is solid for FDMs
@@ -195,13 +197,13 @@ private:
     double getDistanceLoadToHitch() const;
     double getElevLoadToHitch() const;
     double getBearingLoadToHitch() const;
+
     double getRecip(double az);
     double getMass() const;
 
     double hs;
     double _ground_offset;
     double _load_offset;
-    double _force;
     double _old_height;
 
     SGVec3d _oldcarthitchPos;
index f4d002563b2bd6de0a53aa5db68747d2e42e665f..d143296a18f04b8f931701721924fb4bf5634fd8 100644 (file)
@@ -81,6 +81,8 @@ FGAIBase::FGAIBase(object_type ot) :
     delete_me = false;
     _impact_reported = false;
     _collision_reported = false;
+       _expiry_reported = false;
+
     _subID = 0;
 
     _x_offset = 0;
index c810c5ccf027962a30933e7e42ff80b477d53e86..f5cc1f8167c76b649896d1f57afdfd99d17f5a0c 100644 (file)
@@ -127,7 +127,8 @@ void FGSubmodelMgr::update(double dt)
             continue;           // so we can continue
 
         if (_impact || _hit || _expiry) {
-            //SG_LOG(SG_GENERAL, SG_DEBUG, "Submodel: Impact " << _impact << " hit! " << _hit );
+    //        SG_LOG(SG_GENERAL, SG_ALERT, "Submodel: Impact " << _impact << " hit! " << _hit 
+                               //<< " exipiry :-( " << _expiry );
 
             submodel_iterator = submodels.begin();
 
@@ -144,9 +145,11 @@ void FGSubmodelMgr::update(double dt)
                     _parent_roll = (*sm_list_itr)->_getImpactRoll();
                     _parent_speed = (*sm_list_itr)->_getImpactSpeed();
                     (*submodel_iterator)->first_time = true;
+                                       //cout << "Impact: parent SubID = child_ID elev " << _parent_elev << endl;
 
-                    if (release(*submodel_iterator, dt))
+                                       if (release(*submodel_iterator, dt))
                         (*sm_list_itr)->setDie(true);
+
                 }
 
                 ++submodel_iterator;
@@ -174,7 +177,7 @@ void FGSubmodelMgr::update(double dt)
         if ((*submodel_iterator)->trigger_node != 0) {
             _trigger_node = (*submodel_iterator)->trigger_node;
             trigger = _trigger_node->getBoolValue();
-            //cout << "trigger node found " <<  trigger << endl;
+            //cout << (*submodel_iterator)->name << "trigger node found " <<  trigger << endl;
         } else {
             trigger = true;
             //cout << (*submodel_iterator)->name << "trigger node not found " << trigger << endl;
@@ -182,8 +185,8 @@ void FGSubmodelMgr::update(double dt)
 
                if (trigger && (*submodel_iterator)->count != 0) {
 
-                       //int id = (*submodel_iterator)->id;
-                       //string name = (*submodel_iterator)->name;
+                       int id = (*submodel_iterator)->id;
+                       string name = (*submodel_iterator)->name;
                        /*SG_LOG(SG_GENERAL, SG_DEBUG,
                        "Submodels end:  " << (*submodel_iterator)->id
                        << " name " << (*submodel_iterator)->name
@@ -213,9 +216,11 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
     sm->timer += dt;
 
     if (sm->timer < sm->delay) {
-        //cout << "not yet: timer" << sm->timer << " delay " << sm->delay<< endl;
+        //cout << "not yet: timer " << sm->timer << " delay " << sm->delay << endl;
         return false;
     }
+       
+       //cout << "released timer: " << sm->timer << " delay " << sm->delay << endl;
 
     sm->timer = 0.0;
 
@@ -228,9 +233,12 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
 
     FGAIBallistic* ballist = new FGAIBallistic;
     ballist->setPath(sm->model.c_str());
-    ballist->setLatitude(IC.lat);
-    ballist->setLongitude(IC.lon);
-    ballist->setAltitude(IC.alt);
+    ballist->setName(sm->name);
+       ballist->setRandom(sm->random);
+       ballist->setRandomness(sm->randomness);
+       ballist->setLatitude(offsetpos.getLatitudeDeg());
+       ballist->setLongitude(offsetpos.getLongitudeDeg());
+       ballist->setAltitude(offsetpos.getElevationFt());
     ballist->setAzimuth(IC.azimuth);
     ballist->setElevation(IC.elevation);
     ballist->setRoll(IC.roll);
@@ -245,7 +253,6 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
     ballist->setCd(sm->cd);
     ballist->setStabilisation(sm->aero_stabilised);
     ballist->setNoRoll(sm->no_roll);
-    ballist->setName(sm->name);
     ballist->setCollision(sm->collision);
        ballist->setExpiry(sm->expiry);
     ballist->setImpact(sm->impact);
@@ -260,7 +267,6 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
 
     if (sm->count > 0)
         sm->count--;
-
     return true;
 }
 
@@ -305,7 +311,9 @@ void FGSubmodelMgr::transform(submodel *sm)
 
     //cout << " name " << name << " id " << id << " sub id" << sub_id << endl;
 
-    if (_impact || _hit) {
+       // set the Initial Conditions for the types of submodel parent 
+
+    if (_impact || _hit || _expiry) {
         // set the data for a submodel tied to a submodel
         _count++;
         //cout << "Submodels: release sub sub " << _count<< endl;
@@ -380,12 +388,22 @@ void FGSubmodelMgr::transform(submodel *sm)
     cout << "speed north " << IC.speed_north_fps << endl ;
     cout << "parent speed fps in" << IC.speed << "sm speed in " << sm->speed << 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();
 
-    in[0] = sm->x_offset;
-    in[1] = sm->y_offset;
-    in[2] = sm->z_offset;
+       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;
+
+       setOffsetPos();
+
+       //IC.elevation += sm->pitch_offset;
+       //IC.azimuth   += sm->yaw_offset ;
 
     // pre-process the trig functions
     cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS);
@@ -395,35 +413,35 @@ void FGSubmodelMgr::transform(submodel *sm)
     cosRz = cos(IC.azimuth * SG_DEGREES_TO_RADIANS);
     sinRz = sin(IC.azimuth * SG_DEGREES_TO_RADIANS);
 
-    // set up the transform matrix
-    trans[0][0] =  cosRy * cosRz;
-    trans[0][1] =  -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
-    trans[0][2] =  sinRx * sinRz + cosRx * sinRy * cosRz;
+    //// set up the transform matrix
+    //trans[0][0] =  cosRy * cosRz;
+    //trans[0][1] =  -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
+    //trans[0][2] =  sinRx * sinRz + cosRx * sinRy * cosRz;
 
-    trans[1][0] =  cosRy * sinRz;
-    trans[1][1] =  cosRx * cosRz + sinRx * sinRy * sinRz;
-    trans[1][2] =  -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
+    //trans[1][0] =  cosRy * sinRz;
+    //trans[1][1] =  cosRx * cosRz + sinRx * sinRy * sinRz;
+    //trans[1][2] =  -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
 
-    trans[2][0] =  -1 * sinRy;
-    trans[2][1] =  sinRx * cosRy;
-    trans[2][2] =  cosRx * cosRy;
+    //trans[2][0] =  -1 * sinRy;
+    //trans[2][1] =  sinRx * cosRy;
+    //trans[2][2] =  cosRx * cosRy;
 
 
-    // multiply the input and transform matrices
-    out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
-    out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
-    out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
+    //// multiply the input and transform matrices
+    //out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
+    //out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
+    //out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
 
-    // convert ft to degrees of latitude
-    out[0] = out[0] / (366468.96 - 3717.12 * cos(IC.lat * SG_DEGREES_TO_RADIANS));
+    //// convert ft to degrees of latitude
+    //out[0] = out[0] / (366468.96 - 3717.12 * cos(IC.lat * SG_DEGREES_TO_RADIANS));
 
-    // convert ft to degrees of longitude
-    out[1] = out[1] / (365228.16 * cos(IC.lat * SG_DEGREES_TO_RADIANS));
+    //// convert ft to degrees of longitude
+    //out[1] = out[1] / (365228.16 * cos(IC.lat * SG_DEGREES_TO_RADIANS));
 
-    // set submodel initial position
-    IC.lat += out[0];
-    IC.lon += out[1];
-    IC.alt += out[2];
+    //// set submodel initial position
+    //IC.lat += out[0];
+    //IC.lon += out[1];
+    //IC.alt += out[2];
 
     // get aircraft velocity vector angles in XZ and XY planes
     //double alpha = _user_alpha_node->getDoubleValue();
@@ -431,7 +449,7 @@ void FGSubmodelMgr::transform(submodel *sm)
     //double velXY = IC.azimuth - (IC.elevation - alpha * sinRx);
 
     // Get submodel initial velocity vector angles in XZ and XY planes.
-    // This needs to be fixed. This vector should be added to aircraft's vector.
+    // This vector should be added to aircraft's vector.
     IC.elevation += (sm->yaw_offset * sinRx) + (sm->pitch_offset * cosRx);
     IC.azimuth   += (sm->yaw_offset * cosRx) - (sm->pitch_offset * sinRx);
 
@@ -454,7 +472,7 @@ void FGSubmodelMgr::transform(submodel *sm)
 
     // 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;
+        //IC.azimuth = atan2(IC.total_speed_east, IC.total_speed_north) * SG_RADIANS_TO_DEGREES;
         //        cout << "azimuth1 " << IC.azimuth<<endl;
 
         // rationalise the output
@@ -506,15 +524,6 @@ void FGSubmodelMgr::loadAI()
 }
 
 
-double FGSubmodelMgr::getRange(double lat, double lon, double lat2, double lon2) const
-{
-    double course, distance, az2;
-
-    //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_NM;
-    return distance;
-}
 
 void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
 {
@@ -572,6 +581,10 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
         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);
+
+
         //cout <<  "sm->contents_node " << sm->contents_node << endl;
         if (sm->contents_node != 0)
             sm->contents = sm->contents_node->getDoubleValue();
@@ -594,11 +607,13 @@ void FGSubmodelMgr::setData(int id, string& path, bool 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)));
         string name = sm->name;
         sm->prop->setStringValue("name", name.c_str());
 
@@ -608,7 +623,7 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
 
         string force_path = sm->force_path;
         sm->prop->setStringValue("force_path", force_path.c_str());
-        //cout << "set force_path " << force_path << endl;
+        //cout << "set force_path Sub " << force_path << endl;
 
         if (sm->contents_node != 0)
             sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents)));
@@ -673,8 +688,11 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
         sm->contents_node   = fgGetNode(entry_node->getStringValue("contents", "none"), false);
         sm->speed_node      = fgGetNode(entry_node->getStringValue("speed-node", "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);
 
         //cout <<  "sm->contents_node " << sm->contents_node << endl;
         if (sm->contents_node != 0)
@@ -703,16 +721,17 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
         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)));
         string name = sm->name;
         sm->prop->setStringValue("name", name.c_str());
 
         string submodel = sm->submodel;
         sm->prop->setStringValue("submodel", submodel.c_str());
-        // cout << " set submodel path " << submodel<< endl;
+        // 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 " << force_path << endl;
+        cout << "set force_path  AI" << force_path << endl;
 
         if (sm->contents_node != 0)
             sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents)));
@@ -772,4 +791,44 @@ void FGSubmodelMgr::loadSubmodels()
     //}
 }
 
+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);
+}
 // end of submodel.cxx
index bcf7363e8ee63554c04292a4aa7316b12d77bb10..cd645f64e66d4e9333b4518123b06f821eefea24 100644 (file)
@@ -53,6 +53,7 @@ public:
         double             drag_area;
         double             life;
         double             buoyancy;
+               double                     randomness;
         bool               wind;
         bool               first_time;
         double             cd;
@@ -62,6 +63,7 @@ public:
         int                id;
         bool               no_roll;
         bool               serviceable;
+               bool               random;
         bool               collision;
                bool                       expiry;
         bool               impact;
@@ -142,6 +144,10 @@ private:
     double _parent_pitch;
     double _parent_roll;
     double _parent_speed;
+       double _x_offset;
+    double _y_offset;
+    double _z_offset;
+
 
     static const double lbs_to_slugs; //conversion factor
 
@@ -193,9 +199,13 @@ private:
 
     bool release(submodel *, double dt);
 
-    double getRange(double lat, double lon, double lat2, double lon2) const;
 
     int _count;
+       
+       SGGeod userpos;
+       SGGeod offsetpos;
+       SGVec3d getCartOffsetPos() const;
+       void setOffsetPos();
 
 };