X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FAIModel%2FAIShip.cxx;h=9b6a0470524e8fc2b017bc4fd3a412875a91abe0;hb=38226af24ec01e8f0a20d7fd73ef838a69f6ef25;hp=f484b6ac7f7f9a1c43094b7fdf8d3cba13502ab5;hpb=acbcf94bde0ea73132a1dfadc0ebfd161d25f96d;p=flightgear.git diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx index f484b6ac7..9b6a04705 100644 --- a/src/AIModel/AIShip.cxx +++ b/src/AIModel/AIShip.cxx @@ -42,17 +42,38 @@ 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), + + +_waiting(false), +_new_waypoint(true), +_tunnel(false), +_initial_tunnel(false), +_restart(false), +_hdg_constant(0.01), +_limit(100), +_elevation_m(0), +_elevation_ft(0), +_tow_angle(0), +_missed_count(0), +_wp_range(0), +_dt_count(0), +_next_run(0), +_roll_constant(0.001), +_roll_factor(-0.0083335), +_old_range(0), +_range_rate(0), +_missed_time_sec(30), +_day(86400), +_lead_angle(0), +_xtrack_error(0), +_curr_alt(0), +_prev_alt(0), +_until_time(""), +_fp_init(false), +_missed(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)); @@ -77,9 +99,10 @@ void FGAIShip::readFromScenario(SGPropertyNode* scFileNode) { setRudderConstant(scFileNode->getDoubleValue("rudder-constant", 0.5)); setFixedTurnRadius(scFileNode->getDoubleValue("fixed-turn-radius-ft", 500)); setSpeedConstant(scFileNode->getDoubleValue("speed-constant", 0.5)); + setSMPath(scFileNode->getStringValue("submodel-path", "")); 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 +115,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 +127,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 +180,12 @@ void FGAIShip::bind() { SGRawValuePointer(&_waiting)); props->tie("waypoint/lead-angle-deg", SGRawValuePointer(&_lead_angle)); + props->tie("waypoint/tunnel", + SGRawValuePointer(&_tunnel)); + props->tie("waypoint/alt-curr-m", + SGRawValuePointer(&_curr_alt)); + props->tie("waypoint/alt-prev-m", + SGRawValuePointer(&_prev_alt)); props->tie("submodels/serviceable", SGRawValuePointer(&_serviceable)); props->tie("controls/turn-radius-ft", @@ -192,6 +200,10 @@ void FGAIShip::bind() { SGRawValuePointer(&_proportion)); props->tie("controls/fixed-turn-radius-ft", SGRawValuePointer(&_fixed_turn_radius)); + props->tie("controls/restart", + SGRawValuePointer(&_restart)); + props->tie("velocities/speed-kts", + SGRawValuePointer(&speed)); } void FGAIShip::unbind() { @@ -216,6 +228,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 +239,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) { @@ -234,12 +251,12 @@ void FGAIShip::update(double dt) { // Update the velocity information stored in those nodes. // Transform that one to the horizontal local coordinate system. SGQuatd ec2hl = SGQuatd::fromLonLat(pos); - // The orientation of the carrier wrt the horizontal local frame + // The orientation of the ship wrt the horizontal local frame SGQuatd hl2body = SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll); // and postrotate the orientation of the AIModel wrt the horizontal // local frame SGQuatd ec2body = ec2hl*hl2body; - // The cartesian position of the carrier in the wgs84 world + // The cartesian position of the ship in the wgs84 world SGVec3d cartPos = SGVec3d::fromGeod(pos); // The simulation time this transform is meant for @@ -257,7 +274,7 @@ void FGAIShip::update(double dt) { // Only change these values if we are able to compute them safely if (SGLimits::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 +285,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 +314,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 +341,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 +422,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 +474,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; @@ -472,10 +490,6 @@ void FGAIShip::setFlightPlan(FGAIFlightPlan* f) { fp = f; } -void FGAIShip::setName(const string& n) { - _name = n; -} - void FGAIShip::setStartTime(const string& st) { _start_time = st; } @@ -504,6 +518,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 +559,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 +576,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" ); @@ -593,10 +620,12 @@ double FGAIShip::getCourse(double lat, double lon, double lat2, double lon2) con void FGAIShip::ProcessFlightPlan(double dt) { + if ( dt < 0.00001 ) { + return; + } + double time_sec = getDaySeconds(); - double until_time_sec = 0; - _missed = false; _dt_count += dt; /////////////////////////////////////////////////////////////////////////// @@ -609,7 +638,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 +678,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_DEBUG, "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_INFO, "AIShip: "<< _name << " Flightplan repeating "); fp->restart(); prev = curr; curr = fp->getCurrentWaypoint(); @@ -662,6 +711,10 @@ void FGAIShip::ProcessFlightPlan(double dt) { _missed_count = 0; _lead_angle = 0; AccelTo(prev->speed); + } else if (_restart){ + SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " Flightplan restarting "); + _missed_count = 0; + initFlightPlan(); } else { SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " Flightplan dying "); setDie(true); @@ -688,7 +741,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 +756,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_INFO, "AIShip: " << _name << " " << curr->name << " waiting until: " << _until_time << " " << until_time_sec << " now " << time_sec ); setSpeed(0); @@ -711,7 +764,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { _waiting = true; return; } else { - SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " + SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " wait until done: getting new waypoints "); setUntilTime(""); fp->IncrementWaypoint(false); @@ -748,7 +801,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 +821,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 +829,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 +844,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 +873,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 +888,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 +966,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 +1017,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 +1061,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 +1097,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); }