diff --git a/mission_analysis/src/standard_mission/flight_segments/flight_segments.cpp b/mission_analysis/src/standard_mission/flight_segments/flight_segments.cpp index 322a3e1f75ba659c5e22d5969995ed60aa540c80..127520fe95aae142746c64a07d2f3f9a3ff0bc67 100644 --- a/mission_analysis/src/standard_mission/flight_segments/flight_segments.cpp +++ b/mission_analysis/src/standard_mission/flight_segments/flight_segments.cpp @@ -164,17 +164,25 @@ void StandardMission::takeoff_calculation(OperatingConditions* oc, FlightConditi */ const double vS1g(sqrt(2. * fc->aircraft_mass * G_FORCE / (this->wing_surface_area * this->aero.CLmaxTakeoff * this->atm.getDensity(fc->altitude)))); - const double vLOF(1.128 * vS1g); // CS25.107-B: v2 >= 1.2 * v_Stall = 1.2 * 0.94 * v_Stall_1g = 1.128 * v_Stall_1g - fc->end_TAS = vLOF; + this->takeoff_stall_speed.set_value(0.94 * vS1g); // CS25.107-B: v_Stall = 0.94 * v_Stall_1g + this->lift_off_speed.set_value(1.2 * this->takeoff_stall_speed.value()); // CS25.107-B: v2 >= 1.2 * v_Stall + fc->end_TAS = this->lift_off_speed.value(); fc->delta_h = 0.; this->calculate_ground_run(oc, fc, a_mission_step); // Calculation of first part of takeoff distance: ground run + uint16_t lift_off_index(this->mission_profile.size()); // this->mission_profile.size() = index + 1 = wheels off the ground index; wait for first climb step before using + /* Output of the take off parameters */ - myRuntimeInfo->out << "Lift-off speed: " << this->mission_profile.back().end_TAS << " m/s." << std::endl; - myRuntimeInfo->out << "Lift-off thrust: " << convertUnit(NOPREFIX, NEWTON, KILO, NEWTON, this->mission_profile.back().end_thrust) << " kN." << std::endl; + myRuntimeInfo->out << "Lift-off speed: " << this->lift_off_speed.value() << " m/s." << std::endl; + myRuntimeInfo->out << "Lift-off thrust: " << convertUnit(NOPREFIX, NEWTON, KILO, NEWTON, this->mission_profile.back().end_thrust) << " kN." << std::endl; myRuntimeInfo->out << "Lift-off distance: " << this->mission_profile.back().end_range << " m." << std::endl; + this->set_segment_initial_conditions(fc, true, this->aero.CLgroundRoll); this->change_altitude_at_constant_speed(oc, fc, a_mission_step); // Takeoff distance calculation part 2: Climb to screen height (35 ft) + this->takeoff_distance = this->mission_profile.back().end_range; + this->lift_off_angle_of_attack.set_value(convertUnit(DEGREE, RADIAN, this->mission_profile.at(lift_off_index).end_angle_of_attack)); + this->lift_off_lift_coefficient.set_value(this->mission_profile.at(lift_off_index).end_CL); + this->takeoff_climb_angle.set_value(this->mission_profile.back().end_glide_path_angle); myRuntimeInfo->out << "Takeoff distance total: " << this->takeoff_distance.value() << " m." << std::endl; } @@ -699,7 +707,12 @@ double StandardMission::glide_slope_interception(OperatingConditions* oc, Flight double StandardMission::landing(OperatingConditions* oc, FlightConditions* fc, const uint16_t& a_mission_step, const bool& simulation_mode) { /**< \todo [T148] (https://unicado.ilr.rwth-aachen.de/T148): Consider using this method - http://walter.bislins.ch/aviatik/index.asp?page=Bremsweg+eines+Verkehrsflugzeugs */ - if (!simulation_mode) myRuntimeInfo->out << "Landing ... " << std::endl; + uint16_t index_50_ft; + if (!simulation_mode) { + myRuntimeInfo->out << "Landing ... " << std::endl; + index_50_ft = this->mission_profile.size(); // save current index (marker for first step under 50 ft above ground) + this->maximum_landing_angle_off_attack = this->mission_profile.at(index_50_ft - 1).end_angle_of_attack; // - 1 for the start value at 50 ft + } double descent_to_touchdown_range(0.); oc->set_segment_operating_conditions(a_mission_step); /* Set the initial conditions for the segment */ @@ -709,7 +722,16 @@ double StandardMission::landing(OperatingConditions* oc, FlightConditions* fc, c //Approach to touch down // [2] p.313-324 descent_to_touchdown_range = this->change_altitude_at_constant_speed(oc, fc, a_mission_step, simulation_mode); + if (!simulation_mode) { + /* Get the maximum lift coefficient between 50 ft and touchdown */ + for (uint16_t i(index_50_ft); i < this->mission_profile.size(); i++) { + if (abs(this->maximum_landing_angle_off_attack.value()) < abs(this->mission_profile.at(i).end_angle_of_attack)) { + this->maximum_landing_angle_off_attack.set_value(abs(this->mission_profile.at(i).end_angle_of_attack)); + } + } + this->maximum_landing_angle_off_attack.set_value( // Convert to rad + convertUnit(DEGREE, RADIAN, this->maximum_landing_angle_off_attack.value())); myRuntimeInfo->out << "Touchdown after " << convertUnit(METER, NAUTICALMILE, this->mission_profile.back().end_range) << " NM" << std::endl; //Ground run myRuntimeInfo->out << "Rolling on the runway during the reaction time ..." << std::endl; diff --git a/mission_analysis/src/standard_mission/standard_mission/standard_mission.cpp b/mission_analysis/src/standard_mission/standard_mission/standard_mission.cpp index 97cee49ebf973ee9d7b6536c357c3f2de3ccc277..cac51a24d31a71f09c2a64b9c118c32ae864abd2 100644 --- a/mission_analysis/src/standard_mission/standard_mission/standard_mission.cpp +++ b/mission_analysis/src/standard_mission/standard_mission/standard_mission.cpp @@ -131,6 +131,13 @@ StandardMission::StandardMission(const std::shared_ptr<RuntimeIO>& rtIO) : : EndnodeReadOnly<double>("requirements_and_specifications/requirements/top_level_aircraft_requirements/" + std::string("design_mission/descent_speed_schedule/descent_speed_above_FL100")).read(rtIO->acxml).value()), + lift_off_speed(Endnode<double>("lift_off_speed", "Speed at lift-off", 0, "m/s", 0, 350)), + lift_off_lift_coefficient(Endnode<double>("lift_off_coefficient", "Lift coefficient at lift-off", 0, "1", 0, 100)), + lift_off_angle_of_attack(Endnode<double>("lift_off_angle_of_attack", "Angle of attack at lift-off", 0, "rad", 0, Rounding(PI/2., 2))), + takeoff_climb_angle(Endnode<double>("takeoff_climb_angle", "Climb angle towards screen height (35 ft)", 0, "rad", 0, Rounding(PI/2., 2))), + takeoff_stall_speed(Endnode<double>("takeoff_stall_speed", "Stall speed until screen height (35 ft)", 0, "m/s", 0, 350)), + maximum_landing_angle_off_attack(Endnode<double>("maximum_landing_angle_of_attack", "Maximum angle of attack while landing (between 50 ft and touchdown) ", + 0, "rad", 0, Rounding(PI/2., 2))), /* Propulsion */ engine(rtIO), /* Aerodynamic - Polar calculation */ @@ -479,6 +486,7 @@ void StandardMission::update() { check_and_add_nodes(subpath, "Mission data", -1, 0); subpath += "/" + this->mission_type; check_and_add_nodes(subpath, "Data of " + replaceAll(this->mission_type, "_", " ")); + std::string subpath_backup(subpath); /* Non-global endnode initialization */ EndnodeReadOnly<double> energy_carrier_tmp(EndnodeReadOnly<double>("consumed_energy")); @@ -547,8 +555,22 @@ void StandardMission::update() { flight_time.update(rtIO->acxml.at(subpath)); takeoff_engine_derate.update(rtIO->acxml.at(subpath)); + /* Takeoff and landing performance*/ + subpath += "/takeoff_performance_parameters"; + this->check_and_add_nodes(subpath, "Performance parameters for takeoff steps from 0 ft to screen height (35 ft)."); + this->lift_off_speed.update(rtIO->acxml.at(subpath)); + this->takeoff_stall_speed.update(rtIO->acxml.at(subpath)); + this->lift_off_lift_coefficient.update(rtIO->acxml.at(subpath)); + this->lift_off_angle_of_attack.update(rtIO->acxml.at(subpath)); + this->takeoff_climb_angle.update(rtIO->acxml.at(subpath)); + + subpath = subpath_backup + "/landing_performance_parameters"; + this->check_and_add_nodes(subpath, "Performance parameters for landing steps from 50 ft to touchdown."); + myRuntimeInfo->out << this->maximum_landing_angle_off_attack.value() << std::endl; + this->maximum_landing_angle_off_attack.update(rtIO->acxml.at(subpath)); + /* Cruise lift coefficients */ - subpath += "/cruise"; + subpath = subpath_backup + "/cruise"; this->check_and_add_nodes(subpath, "Characteristics of the cruise segment"); this->CL_cruise_average.update(rtIO->acxml.at(subpath)); this->CL_cruise_min.update(rtIO->acxml.at(subpath)); @@ -570,7 +592,8 @@ void StandardMission::update() { relative_cruise_step_end.update(rtIO->acxml.at(subpath + "/cruise_step@" + num2Str(i))); altitude.update(rtIO->acxml.at(subpath + "/cruise_step@" + num2Str(i))); } - /* Takeoff and landing */ + + /* Runway length */ if (this->estimate_MTOM) { // estimate_MTOM = true -> design mission -> set runway lengths and approach speed // Set nodes if not existing subpath = "aircraft_exchange_file/assessment"; diff --git a/mission_analysis/src/standard_mission/standard_mission/standard_mission.h b/mission_analysis/src/standard_mission/standard_mission/standard_mission.h index ecd51f955594ac85279c3575e9f6b1d8128ba174..b2d4d19a6e4d06fde6fbb82de803510dcc4185b9 100644 --- a/mission_analysis/src/standard_mission/standard_mission/standard_mission.h +++ b/mission_analysis/src/standard_mission/standard_mission/standard_mission.h @@ -120,11 +120,17 @@ class StandardMission : public Strategy { double max_altitude_one_engine_inoperative; /**< Maximum altitude (100 ft/min climbing criterion) with one engine inoperative and at MTOM [m] */ Endnode<double> approach_speed; /**< Maximum approach speed needed for the mission [m] */ double approach_speed_required; /**< Maximum approach speed that shall not be exceeded [m/s] */ - double climb_speed_below_FL100; /**< Climb calibrated airspeed below flight level 100 [KCAS] */ - double climb_speed_above_FL100; /**< Climb calibrated airspeed above flight level 100 [KCAS] */ + double climb_speed_below_FL100; /**< Climb calibrated airspeed below flight level 100 [m/s] */ + double climb_speed_above_FL100; /**< Climb calibrated airspeed above flight level 100 [m/s] */ double delta_mach_above_crossover; /**< Delta to desired cruise Mach number above crossover [-] */ - double descent_speed_below_FL100; /**< Descent calibrated airspeed below flight level 100 [KCAS] */ - double descent_speed_above_FL100; /**< Descent calibrated airspeed above flight level 100 [KCAS] */ + double descent_speed_below_FL100; /**< Descent calibrated airspeed below flight level 100 [m/s] */ + double descent_speed_above_FL100; /**< Descent calibrated airspeed above flight level 100 [m/s] */ + Endnode<double> lift_off_speed; /**< Speed at lift-off [m/s] */ + Endnode<double> lift_off_lift_coefficient; /**< Lift coefficient at lift-off [-] */ + Endnode<double> lift_off_angle_of_attack; /**< Angle of attack at lift-off [rad] */ + Endnode<double> takeoff_climb_angle; /**< Climb angle towards screen height (35 ft) [rad] */ + Endnode<double> takeoff_stall_speed; /**< Stall speed until screen height (35 ft) [m/s] */ + Endnode<double> maximum_landing_angle_off_attack; /**< Maximum angle of attack while landing (between 50 ft and touchdown) [rad] */ /* Propulsion */ @@ -212,7 +218,7 @@ class StandardMission : public Strategy { double end_L_over_D; /**< Lift over drag coefficient at the end of the segment [-] */ double end_specific_air_range; /**< Specific air range at the end of the segment [m/kg] */ std::string end_aero_config; /**< Aerodynamic configuration at the end of the segment */ - double end_glide_path_angle; /**< Path angle at the end of the segment [deg] */ + double end_glide_path_angle; /**< Path angle at the end of the segment [rad] */ double end_TAS; /**< True airspeed at the end of the segment [m/s] */ double end_mach; /**< Mach number at the end of the segment [-] */ double end_CAS; /**< Calibrated airspeed at the end of the segment [m/s] */