diff --git a/src/AIModel/AICarrier.cxx b/src/AIModel/AICarrier.cxx index 79653fc86..e52201939 100644 --- a/src/AIModel/AICarrier.cxx +++ b/src/AIModel/AICarrier.cxx @@ -194,6 +194,7 @@ void FGAICarrier::readFromScenario(SGPropertyNode* scFileNode) { setMinLat(scFileNode->getDoubleValue("min-lat", 0)); setMaxLong(scFileNode->getDoubleValue("max-long", 0)); setMinLong(scFileNode->getDoubleValue("min-long", 0)); + setMPControl(scFileNode->getBoolValue("mp-control", false)); SGPropertyNode* flols = scFileNode->getChild("flols-pos"); if (flols) { @@ -268,18 +269,32 @@ void FGAICarrier::setTACANChannelID(const string& id) { TACAN_channel_id = id; } +void FGAICarrier::setMPControl(bool c) { + MPControl = c; +} + void FGAICarrier::update(double dt) { // Now update the position and heading. This will compute new hdg and // roll values required for the rotation speed computation. FGAIShip::update(dt); //automatic turn into wind with a target wind of 25 kts otd - if(turn_to_launch_hdg){ - TurnToLaunch(); - } else if(OutsideBox() || returning) {// check that the carrier is inside the operating box - ReturnToBox(); + //SG_LOG(SG_GENERAL, SG_ALERT, "AICarrier: MPControl " << MPControl ); + if (!MPControl){ + + if(turn_to_launch_hdg){ + TurnToLaunch(); + } else if(turn_to_recovery_hdg ){ + TurnToRecover(); + } else if(OutsideBox() || returning ) {// check that the carrier is inside + ReturnToBox(); // the operating box, + } else { + TurnToBase(); + } + } else { - TurnToBase(); + FGAIShip::TurnTo(tgt_heading); + FGAIShip::AccelTo(tgt_speed); } UpdateWind(dt); @@ -352,7 +367,10 @@ bool FGAICarrier::init(bool search_in_AI_path) { turn_to_launch_hdg = false; + turn_to_recovery_hdg = false; + turn_to_base_course = true; returning = false; + in_to_wind = false; mOpBoxPos = pos; base_course = hdg; @@ -402,6 +420,8 @@ void FGAICarrier::bind() { SGRawValueMethods(pos, &SGGeod::getLatitudeDeg)); props->tie("controls/start-pos-long-deg", SGRawValueMethods(pos, &SGGeod::getLongitudeDeg)); + props->tie("controls/mp-control", + SGRawValuePointer(&MPControl)); props->tie("velocities/speed-kts", SGRawValuePointer(&speed)); props->tie("environment/surface-wind-speed-true-kts", @@ -414,24 +434,31 @@ void FGAICarrier::bind() { SGRawValuePointer(&rel_wind)); props->tie("environment/rel-wind-speed-kts", SGRawValuePointer(&rel_wind_speed_kts)); + props->tie("environment/in-to-wind", + SGRawValuePointer(&in_to_wind)); props->tie("controls/flols/wave-off-lights", SGRawValuePointer(&wave_off_lights)); props->tie("controls/elevators", SGRawValuePointer(&elevators)); props->tie("surface-positions/elevators-pos-norm", SGRawValuePointer(&pos_norm)); - props->tie("controls/elevators-trans-time-s", + props->tie("controls/constants/elevators/trans-time-s", SGRawValuePointer(&transition_time)); - props->tie("controls/elevators-time-constant", + props->tie("controls/constants/elevators/time-constant", SGRawValuePointer(&time_constant)); props->tie("controls/jbd", SGRawValuePointer(&jbd)); props->tie("surface-positions/jbd-pos-norm", SGRawValuePointer(&jbd_pos_norm)); - props->tie("controls/jbd-trans-time-s", + props->tie("controls/constants/jbd/trans-time-s", SGRawValuePointer(&jbd_transition_time)); - props->tie("controls/jbd-time-constant", + props->tie("controls/constants/jbd/time-constant", SGRawValuePointer(&jbd_time_constant)); + props->tie("controls/turn-to-recovery-hdg", + SGRawValuePointer(&turn_to_recovery_hdg)); + props->tie("controls/turn-to-base-course", + SGRawValuePointer(&turn_to_base_course)); + props->setBoolValue("controls/flols/cut-lights", false); props->setBoolValue("controls/flols/wave-off-lights", false); @@ -457,16 +484,19 @@ void FGAICarrier::unbind() { props->untie("environment/wind-from-true-degs"); props->untie("environment/rel-wind-from-degs"); props->untie("environment/rel-wind-speed-kts"); + props->untie("environment/in-to-wind"); props->untie("controls/flols/wave-off-lights"); props->untie("controls/elevators"); props->untie("surface-positions/elevators-pos-norm"); - props->untie("controls/elevators-trans-time-secs"); - props->untie("controls/elevators-time-constant"); + props->untie("controls/constants/elevators/trans-time-secs"); + props->untie("controls/constants/elevators/time-constant"); props->untie("controls/jbd"); - props->untie("surface-positions/jbd-pos-norm"); - props->untie("controls/jbd-trans-time-s"); + props->untie("surface-positions/jbd/pos-norm"); + props->untie("controls/constants/jbd/trans-time-s"); props->untie("controls/jbd-time-constant"); - + props->untie("controls/mp-control"); + props->untie("controls/turn-to-recovery-hdg"); + props->untie("controls/turn-to-base-course"); } @@ -539,18 +569,52 @@ void FGAICarrier::UpdateWind( double dt) { void FGAICarrier::TurnToLaunch(){ + // calculate tgt heading + if (wind_speed_kts < 3){ + tgt_heading = base_course; + } else { + tgt_heading = wind_from_deg; + } + //calculate tgt speed double tgt_speed = 25 - wind_speed_kts; if (tgt_speed < 10) tgt_speed = 10; //turn the carrier - FGAIShip::TurnTo(wind_from_deg); + FGAIShip::TurnTo(tgt_heading); FGAIShip::AccelTo(tgt_speed); } +void FGAICarrier::TurnToRecover(){ + //these are the rules for adjusting heading to provide a relative wind + //down the angled flightdeck + + if (wind_speed_kts < 3){ + tgt_heading = base_course + 60; + } else if (rel_wind < -9 && rel_wind >= -180){ + tgt_heading = wind_from_deg; + } else if (rel_wind > -7 && rel_wind < 45){ + tgt_heading = wind_from_deg + 60; + } else if (rel_wind >=45 && rel_wind < 180){ + tgt_heading = wind_from_deg + 45; + } else + tgt_heading = hdg; + + SG_NORMALIZE_RANGE(tgt_heading, 0.0, 360.0); + + //calculate tgt speed + double tgt_speed = 26 - wind_speed_kts; + if (tgt_speed < 10) + tgt_speed = 10; + + //turn the carrier + FGAIShip::TurnTo(tgt_heading); + FGAIShip::AccelTo(tgt_speed); + +} void FGAICarrier::TurnToBase(){ //turn the carrier @@ -625,9 +689,12 @@ bool FGAICarrier::OutsideBox() { //returns true if the carrier is outside operat bool FGAICarrier::InToWind() { - if ( fabs(rel_wind) < 5 ) - return true; + in_to_wind = false; + if ( fabs(rel_wind) < 10 ){ + in_to_wind = true; + return true; + } return false; } diff --git a/src/AIModel/AICarrier.hxx b/src/AIModel/AICarrier.hxx index 082e11153..bd7bc405d 100644 --- a/src/AIModel/AICarrier.hxx +++ b/src/AIModel/AICarrier.hxx @@ -60,7 +60,9 @@ public: void setMinLat( double deg ); void setMaxLong( double deg ); void setMinLong( double deg ); + void setMPControl( bool c ); void TurnToLaunch(); + void TurnToRecover(); void TurnToBase(); void ReturnToBox(); bool OutsideBox(); @@ -96,6 +98,7 @@ private: double rel_wind_from_deg; + list wire_objects; // List of wire object names list catapult_objects; // List of catapult object names list ppositions; // List of positions where an aircraft can start. @@ -108,6 +111,7 @@ private: double angle; int source; // the flols light which is visible at the moment bool wave_off_lights; + bool in_to_wind; // these are for maneuvering the carrier SGGeod mOpBoxPos; @@ -121,8 +125,11 @@ private: double base_course, base_speed; bool turn_to_launch_hdg; + bool turn_to_recovery_hdg; + bool turn_to_base_course; bool returning; // set if the carrier is returning to an operating box bool InToWind(); // set if the carrier is in to wind + bool MPControl; SGPropertyNode_ptr _longitude_node; diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx index c152ce36a..5111d9981 100644 --- a/src/AIModel/AIShip.cxx +++ b/src/AIModel/AIShip.cxx @@ -29,6 +29,8 @@ #endif #include + +#include #include #include #include @@ -162,6 +164,8 @@ void FGAIShip::bind() { SGRawValuePointer(&_waiting)); props->tie("submodels/serviceable", SGRawValuePointer(&_serviceable)); + props->tie("controls/turn-radius-ft", + SGRawValuePointer(&turn_radius_ft)); } void FGAIShip::unbind() { @@ -184,6 +188,7 @@ void FGAIShip::unbind() { props->untie("position/waypoint-wait-count"); props->untie("position/waypoint-waiting"); props->untie("submodels/serviceable"); + props->untie("controls/turn-radius-ft"); } void FGAIShip::update(double dt) { @@ -269,9 +274,6 @@ void FGAIShip::Run(double dt) { pos.setLongitudeDeg(pos.getLongitudeDeg() + speed_east_deg_sec * dt); // adjust heading based on current _rudder angle - - //cout << "turn_radius_ft " << turn_radius_ft ; - if (turn_radius_ft <= 0) turn_radius_ft = 0; // don't allow nonsense values @@ -289,8 +291,6 @@ void FGAIShip::Run(double dt) { // we need to allow for negative speeds _sp_turn_radius_ft = 10 * pow ((fabs(speed) - 15), 2) + turn_radius_ft; - //cout << " speed turn radius " << _sp_turn_radius_ft ; - if (_rudder <= -0.25 || _rudder >= 0.25) { // adjust turn radius for _rudder angle. The equation is even more approximate. float a = 19; @@ -299,19 +299,13 @@ void FGAIShip::Run(double dt) { _rd_turn_radius_ft = (a * exp(b * fabs(_rudder)) + c) * _sp_turn_radius_ft; - //cout <<" _rudder turn radius " << _rd_turn_radius_ft << endl; - // calculate the angle, alpha, subtended by the arc traversed in time dt alpha = ((speed * 1.686 * dt) / _rd_turn_radius_ft) * SG_RADIANS_TO_DEGREES; // make sure that alpha is applied in the right direction hdg += alpha * sign(_rudder); - if (hdg > 360.0) - hdg -= 360.0; - - if (hdg < 0.0) - hdg += 360.0; + SG_NORMALIZE_RANGE(hdg, 0.0, 360.0); //adjust roll for rudder angle and speed. Another bit of voodoo raw_roll = _roll_factor * speed * _rudder;