]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/AIShip.cxx
Fix crashes (activating the route-manager) with a default GPS.
[flightgear.git] / src / AIModel / AIShip.cxx
index f484b6ac7f7f9a1c43094b7fdf8d3cba13502ab5..41f09550e010caa143ee71695889c81e17ace689 100644 (file)
 
 
 FGAIShip::FGAIShip(object_type ot) :
-    FGAIBase(ot),
-    _limit(40),
-    _elevation_m(0),
-    _elevation_ft(0),
-    _tow_angle(0),
-    _dt_count(0),
-    _next_run(0),
-    _lead_angle(0),
-    _xtrack_error(0)
+FGAIBase(ot),
+_limit(100),
+_elevation_m(0),
+_elevation_ft(0),
+_tow_angle(0),
+_dt_count(0),
+_next_run(0),
+_lead_angle(0),
+_xtrack_error(0),
+_tunnel(false),
+_initial_tunnel(false),
+_curr_alt(0),
+_prev_alt(0),
+_until_time(""),
+_fp_init(false),
+_missed(false),
+_waiting(false),
+_new_waypoint(true),
+_missed_count(0),
+_wait_count(0),
+_missed_time_sec(30),
+_day(86400),
+_wp_range(0),
+_old_range(0),
+_range_rate(0),
+_roll_constant(0.001),
+_hdg_constant(0.01),
+_roll_factor(-0.0083335),
+_restart(false)
 
 {
+        invisible = false;
 }
 
 FGAIShip::~FGAIShip() {
@@ -70,6 +91,7 @@ void FGAIShip::readFromScenario(SGPropertyNode* scFileNode) {
     setRadius(scFileNode->getDoubleValue("turn-radius-ft", 2000));
     std::string flightplan = scFileNode->getStringValue("flightplan");
     setRepeat(scFileNode->getBoolValue("repeat", false));
+    setRestart(scFileNode->getBoolValue("restart", false));
     setStartTime(scFileNode->getStringValue("time", ""));
     setLeadAngleGain(scFileNode->getDoubleValue("lead-angle-gain", 1.5));
     setLeadAngleLimit(scFileNode->getDoubleValue("lead-angle-limit-deg", 15));
@@ -79,7 +101,7 @@ void FGAIShip::readFromScenario(SGPropertyNode* scFileNode) {
     setSpeedConstant(scFileNode->getDoubleValue("speed-constant", 0.5));
 
     if (!flightplan.empty()) {
-            SG_LOG(SG_GENERAL, SG_ALERT, "getting flightplan: " << _name );
+        SG_LOG(SG_GENERAL, SG_ALERT, "getting flightplan: " << _name );
 
         FGAIFlightPlan* fp = new FGAIFlightPlan(flightplan);
         setFlightPlan(fp);
@@ -92,8 +114,6 @@ bool FGAIShip::init(bool search_in_AI_path) {
     curr = 0; // the one ahead
     next = 0; // the next plus 1
 
-    _until_time = "";
-
     props->setStringValue("name", _name.c_str());
     props->setStringValue("waypoint/name-prev", _prev_name.c_str());
     props->setStringValue("waypoint/name-curr", _curr_name.c_str());
@@ -106,27 +126,8 @@ bool FGAIShip::init(bool search_in_AI_path) {
     _rudder = 0.0;
     no_roll = false;
 
-    _roll_constant = 0.001;
-    _hdg_constant = 0.01;
-    _roll_factor = -0.0083335;
-
     _rd_turn_radius_ft = _sp_turn_radius_ft = turn_radius_ft;
 
-    _fp_init = false;
-    _missed = false;
-    _waiting = false;
-    _new_waypoint = true;
-
-    _missed_count = 0;
-    _wait_count = 0;
-    _missed_time_sec = 30;
-
-    _day = 86400;
-
-
-    _wp_range = _old_range = 0;
-    _range_rate = 0;
-
     if (fp)
         _fp_init = initFlightPlan();
 
@@ -178,6 +179,12 @@ void FGAIShip::bind() {
         SGRawValuePointer<bool>(&_waiting));
     props->tie("waypoint/lead-angle-deg",
         SGRawValuePointer<double>(&_lead_angle));
+    props->tie("waypoint/tunnel",
+        SGRawValuePointer<bool>(&_tunnel));
+    props->tie("waypoint/alt-curr-m",
+        SGRawValuePointer<double>(&_curr_alt));
+    props->tie("waypoint/alt-prev-m",
+        SGRawValuePointer<double>(&_prev_alt));
     props->tie("submodels/serviceable",
         SGRawValuePointer<bool>(&_serviceable));
     props->tie("controls/turn-radius-ft",
@@ -192,6 +199,10 @@ void FGAIShip::bind() {
         SGRawValuePointer<double>(&_proportion));
     props->tie("controls/fixed-turn-radius-ft",
         SGRawValuePointer<double>(&_fixed_turn_radius));
+    props->tie("controls/restart",
+        SGRawValuePointer<bool>(&_restart));
+    props->tie("velocities/speed-kts",
+                SGRawValuePointer<double>(&speed));
 }
 
 void FGAIShip::unbind() {
@@ -216,6 +227,9 @@ void FGAIShip::unbind() {
     props->untie("waypoint/lead-angle-deg");
     props->untie("waypoint/xtrack-error-ft");
     props->untie("waypoint/waiting");
+    props->untie("waypoint/tunnel");
+    props->untie("waypoint/alt-curr-m");
+    props->untie("waypoint/alt-prev-m");
     props->untie("submodels/serviceable");
     props->untie("controls/turn-radius-ft");
     props->untie("controls/turn-radius-corrected-ft");
@@ -224,6 +238,8 @@ void FGAIShip::unbind() {
     props->untie("controls/constants/lead-angle/proportion");
     props->untie("controls/fixed-turn-radius-ft");
     props->untie("controls/constants/speed");
+    props->untie("controls/restart");
+    props->untie("velocities/speed-kts");
 
 }
 void FGAIShip::update(double dt) {
@@ -257,7 +273,7 @@ void FGAIShip::update(double dt) {
     // Only change these values if we are able to compute them safely
     if (SGLimits<double>::min() < dt) {
         // Now here is the finite difference ...
-        
+
         // Transform that one to the horizontal local coordinate system.
         SGQuatd ec2hlNew = SGQuatd::fromLonLat(pos);
         // compute the new orientation
@@ -268,7 +284,7 @@ void FGAIShip::update(double dt) {
         dOr.getAngleAxis(dOrAngleAxis);
         // divided by the time difference provides a rotation speed vector
         dOrAngleAxis /= dt;
-        
+
         aip.setBodyAngularVelocity(dOrAngleAxis);
     }
 }
@@ -297,8 +313,7 @@ void FGAIShip::Run(double dt) {
     }
 
     // do not allow unreasonable speeds
-    if (speed > _limit)
-        speed = _limit;
+    SG_CLAMP_RANGE(speed, -_limit * 0.75, _limit);
 
     // convert speed to degrees per second
     speed_north_deg_sec = cos(hdg / SGD_RADIANS_TO_DEGREES)
@@ -325,17 +340,26 @@ void FGAIShip::Run(double dt) {
 
 
     //we assume that at slow speed ships will manoeuvre using engines/bow thruster
-    if (fabs(speed)<=5)
-        _sp_turn_radius_ft = _fixed_turn_radius;
-    else {
-        // adjust turn radius for speed. The equation is very approximate.
-        // we need to allow for negative speeds
-        if (type == "ship")
-        _sp_turn_radius_ft = 10 * pow ((fabs(speed) - 15), 2) + turn_radius_ft;
-        else
-            _sp_turn_radius_ft = turn_radius_ft;
+       if(type == "ship" || type == "carrier" || type == "escort"){
+
+               if (fabs(speed)<=5)
+                       _sp_turn_radius_ft = _fixed_turn_radius;
+               else {
+                       // adjust turn radius for speed. The equation is very approximate.
+                       // we need to allow for negative speeds
+                       _sp_turn_radius_ft = 10 * pow ((fabs(speed) - 15), 2) + turn_radius_ft;
+               }
+
+       } else {
+               
+               if (fabs(speed) <= 40)
+           _sp_turn_radius_ft = _fixed_turn_radius;
+               else {
+                       // adjust turn radius for speed. 
+                       _sp_turn_radius_ft = turn_radius_ft;
+               }
+       }
 
-    }
 
     if (_rudder <= -0.25 || _rudder >= 0.25) {
         // adjust turn radius for _rudder angle. The equation is even more approximate.
@@ -397,12 +421,12 @@ void FGAIShip::Run(double dt) {
     }
 
     // set the _rudder limit by speed
-    if (type == "ship"){
+    if (type == "ship" || type == "carrier" || type == "escort"){
 
-    if (speed <= 40)
-        rudder_limit = (-0.825 * speed) + 35;
-    else
-        rudder_limit = 2;
+        if (speed <= 40)
+            rudder_limit = (-0.825 * speed) + 35;
+        else
+            rudder_limit = 2;
 
     } else
         rudder_limit = 20;
@@ -449,13 +473,6 @@ void FGAIShip::ClimbTo(double altitude) {
 }
 
 void FGAIShip::TurnTo(double heading) {
-    //double relbrg_corr = _relbrg;
-
-    //if ( relbrg_corr > 5)
-    //    relbrg_corr = 5;
-    //else if( relbrg_corr < -5)
-    //    relbrg_corr = -5;
-
     tgt_heading = heading - _lead_angle + _tow_angle;
     SG_NORMALIZE_RANGE(tgt_heading, 0.0, 360.0);
     _hdg_lock = true;
@@ -504,6 +521,10 @@ void FGAIShip::setRepeat(bool r) {
     _repeat = r;
 }
 
+void FGAIShip::setRestart(bool r) {
+    _restart = r;
+}
+
 void FGAIShip::setMissed(bool m) {
     _missed = m;
     props->setBoolValue("waypoint/missed", _missed);
@@ -541,6 +562,15 @@ void FGAIShip::setFixedTurnRadius(double ftr) {
     _fixed_turn_radius = ftr;
 }
 
+void FGAIShip::setInitialTunnel(bool t) {
+    _initial_tunnel = t;
+    setTunnel(_initial_tunnel);
+}
+
+void FGAIShip::setTunnel(bool t) {
+    _tunnel = t;
+}
+
 void FGAIShip::setWPNames() {
 
     if (prev != 0)
@@ -549,7 +579,7 @@ void FGAIShip::setWPNames() {
         setPrevName("");
 
     if (curr != 0)
-    setCurrName(curr->name);
+        setCurrName(curr->name);
     else{
         setCurrName("");
         SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" );
@@ -594,9 +624,7 @@ double FGAIShip::getCourse(double lat, double lon, double lat2, double lon2) con
 void FGAIShip::ProcessFlightPlan(double dt) {
 
     double time_sec = getDaySeconds();
-    double until_time_sec = 0;
 
-    _missed = false;
     _dt_count += dt;
 
     ///////////////////////////////////////////////////////////////////////////
@@ -609,7 +637,10 @@ void FGAIShip::ProcessFlightPlan(double dt) {
     if (_dt_count < _next_run && _start_sec < time_sec)
         return;
 
-    _next_run = 1.0 + (0.5 * sg_random());
+    _next_run = 0.05 + (0.025 * sg_random());
+
+    double until_time_sec = 0;
+    _missed = false;
 
     // check to see if we've reached the point for our next turn
     // if the range to the waypoint is less than the calculated turn
@@ -646,10 +677,27 @@ void FGAIShip::ProcessFlightPlan(double dt) {
 
     if ((_wp_range < (sp_turn_radius_nm * 1.25)) || _missed || (_waiting && !_new_waypoint)) {
 
-        if (_next_name == "END" || fp->getNextWaypoint() == 0) {
+        if (_next_name == "TUNNEL"){
+            _tunnel = !_tunnel;
+
+            SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " " << sp_turn_radius_nm );
+
+            fp->IncrementWaypoint(false);
+            next = fp->getNextWaypoint();
+
+            if (next->name == "WAITUNTIL" || next->name == "WAIT"
+                || next->name == "END" || next->name == "TUNNEL")
+                return;
+
+            prev = curr;
+            fp->IncrementWaypoint(false);
+            curr = fp->getCurrentWaypoint();
+            next = fp->getNextWaypoint();
+
+        }else if(_next_name == "END" || fp->getNextWaypoint() == 0) {
 
             if (_repeat) {
-                SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << "Flightplan restarting ");
+                SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << " Flightplan repeating ");
                 fp->restart();
                 prev = curr;
                 curr = fp->getCurrentWaypoint();
@@ -662,6 +710,10 @@ void FGAIShip::ProcessFlightPlan(double dt) {
                 _missed_count = 0;
                 _lead_angle = 0;
                 AccelTo(prev->speed);
+            } else if (_restart){
+                SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " Flightplan restarting ");
+                _missed_count = 0;
+                initFlightPlan();
             } else {
                 SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " Flightplan dying ");
                 setDie(true);
@@ -688,7 +740,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
                 next = fp->getNextWaypoint();
 
                 if (next->name == "WAITUNTIL" || next->name == "WAIT"
-                        || next->name == "END")
+                    || next->name == "END" || next->name == "TUNNEL")
                     return;
 
                 prev = curr;
@@ -703,7 +755,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
             _until_time = next->time;
             setUntilTime(next->time);
             if (until_time_sec > time_sec) {
-                SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " "
+                SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " "
                     << curr->name << " waiting until: "
                     << _until_time << " " << until_time_sec << " now " << time_sec );
                 setSpeed(0);
@@ -748,7 +800,13 @@ void FGAIShip::ProcessFlightPlan(double dt) {
         _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
         _old_range = _wp_range;
         setWPPos();
-        AccelTo(prev->speed);
+        object_type type = getType();
+
+        if (type != 10)
+            AccelTo(prev->speed);
+
+        _curr_alt = curr->altitude;
+        _prev_alt = prev->altitude;
 
     } else {
         _new_waypoint = false;
@@ -762,7 +820,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
     else
         SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: Bearing or Range is not a finite number");
 
-     _dt_count = 0;
+    _dt_count = 0;
 } // end Processing FlightPlan
 
 bool FGAIShip::initFlightPlan() {
@@ -770,8 +828,8 @@ bool FGAIShip::initFlightPlan() {
     SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " initializing waypoints ");
 
     bool init = false;
-
     _start_sec = 0;
+    _tunnel = _initial_tunnel;
 
     fp->restart();
     fp->IncrementWaypoint(false);
@@ -785,7 +843,7 @@ bool FGAIShip::initFlightPlan() {
         fp->IncrementWaypoint(false);
         curr = fp->getCurrentWaypoint();
         next = fp->getNextWaypoint();
-    }
+    } // end while loop
 
     if (!_start_time.empty()){
         _start_sec = processTimeString(_start_time);
@@ -814,9 +872,9 @@ bool FGAIShip::initFlightPlan() {
         }
 
     } else {
-    setLatitude(prev->latitude);
-    setLongitude(prev->longitude);
-    setSpeed(prev->speed);
+        setLatitude(prev->latitude);
+        setLongitude(prev->longitude);
+        setSpeed(prev->speed);
     }
 
     setWPNames();
@@ -829,7 +887,7 @@ bool FGAIShip::initFlightPlan() {
     _missed_count = 0;
     _new_waypoint = true;
 
-    SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " done initialising waypoints ");
+    SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " done initialising waypoints " << _tunnel);
     if (prev)
         init = true;
 
@@ -907,11 +965,11 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
             next = fp->getNextWaypoint();
 
             if (next->name != "WAITUNTIL" && next->name != "WAIT"
-                    && next->name != "END") {
-                prev = curr;
-                fp->IncrementWaypoint(false);
-                curr = fp->getCurrentWaypoint();
-                next = fp->getNextWaypoint();
+                && next->name != "END") {
+                    prev = curr;
+                    fp->IncrementWaypoint(false);
+                    curr = fp->getCurrentWaypoint();
+                    next = fp->getNextWaypoint();
             }
 
         } else if (next->name == "WAITUNTIL") {
@@ -958,8 +1016,8 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
     // so we will calculate the distance back up the track from the current waypoint
     // then calculate the lat and lon.
 
-    /*cout << "advancing flight plan done elapsed_sec: " << elapsed_sec
-        << " " << day_sec << endl;*/
+    //cout << "advancing flight plan done elapsed_sec: " << elapsed_sec
+    //    << " " << day_sec << endl;
 
     double time_diff = elapsed_sec - day_sec;
     double lat, lon, recip;
@@ -1002,27 +1060,33 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
 
 void FGAIShip::setWPPos() {
 
-    if (curr->name == "END" || curr->name == "WAIT" || curr->name == "WAITUNTIL"){
-        cout<< curr->name << endl;
-        return;
+    if (curr->name == "END" || curr->name == "WAIT"
+        || curr->name == "WAITUNTIL" || curr->name == "TUNNEL"){
+            //cout << curr->name << " returning" << endl;
+            return;
     }
 
     double elevation_m = 0;
     wppos.setLatitudeDeg(curr->latitude);
     wppos.setLongitudeDeg(curr->longitude);
-    wppos.setElevationFt(0);
+    wppos.setElevationM(0);
 
     if (curr->on_ground){
 
-        if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(wppos, 10000),
-            elevation_m, &_material)){
+        if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(wppos, 3000),
+            elevation_m, &_material, 0)){
                 wppos.setElevationM(elevation_m);
         }
 
+        //cout << curr->name << " setting measured  elev " << elevation_m << endl;
+
     } else {
-        wppos.setElevationFt(curr->altitude);
+        wppos.setElevationM(curr->altitude);
+        //cout << curr->name << " setting FP elev " << elevation_m << endl;
     }
 
+    curr->altitude = wppos.getElevationM();
+
 }
 
 void FGAIShip::setXTrackError() {
@@ -1032,19 +1096,17 @@ void FGAIShip::setXTrackError() {
     double brg = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(),
         curr->latitude, curr->longitude);
     double xtrack_error_nm = sin((course - brg)* SG_DEGREES_TO_RADIANS) * _wp_range;
+    double factor = -0.0045 * speed + 1;
+    double limit = _lead_angle_limit * factor;
 
-    //if (_wp_range > _sp_turn_radius_ft / (2 * 6076.1155)){
     if (_wp_range > 0){
         _lead_angle = atan2(xtrack_error_nm,(_wp_range * _proportion)) * SG_RADIANS_TO_DEGREES;
     } else
         _lead_angle = 0;
 
-    _lead_angle *= _lead_angle_gain;
+    _lead_angle *= _lead_angle_gain * factor;
     _xtrack_error = xtrack_error_nm * 6076.1155;
 
-    if (_lead_angle<= -_lead_angle_limit)
-        _lead_angle = -_lead_angle_limit;
-    else if (_lead_angle >= _lead_angle_limit)
-        _lead_angle = _lead_angle_limit;
+    SG_CLAMP_RANGE(_lead_angle, -limit, limit);
 
 }