def calcElevEffectiveness(inputFile): ''' DESCRIPTION: This function calculates the elevator effectiveness (Cmdelta), which is a constant value found from the measurements when changing xcg. ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n ... SI [Condition]: By default set to SI=True\n OUTPUT:\n ... Cmdelta [float]: Elevator effectiveness ''' # Import data param = imPar.parametersStatic() static2b = imStat.staticMeas(inputFile, 'static2b', SI=True) aeroCoeff = calcAeroCoeff(inputFile, 'static2b') static2bWeight = imWeight.calcWeightCG(inputFile, 'static2b') # Obtain values from data cbar = param.c delta = static2b['delta'].to_numpy() delta1 = delta[0] delta2 = delta[1] Cn = aeroCoeff['Cl'].to_numpy() CnAvg = np.average( Cn ) xcg = static2bWeight['Xcg'].to_numpy() xcg1 = xcg[0] xcg2 = xcg[1] # Calculation Cmdelta = -1 * ( CnAvg * (xcg2 - xcg1) / cbar ) / ( delta2 - delta1 ) return Cmdelta
def calcElevContrForce(inputFile): ''' DESCRIPTION: This function calculates the reduced elevator control force for each meassurement taken during the second stationary measurement series. ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n ... SI [Condition]: By default set to SI=True\n OUTPUT:\n ... FeRed [Arary]: Numpy array containing the reduced elevator control force ''' # Import data param = imPar.parametersStatic() static2a = imStat.staticMeas(inputFile, 'static2a', SI=True) static2aWeight = imWeight.calcWeightCG(inputFile, 'static2a') # Obtain values from data Ws = param.Ws Fe = static2a['Fe'].to_numpy() W = static2aWeight['Weight'].to_numpy() # Calculation FeRed = Fe * Ws / W return FeRed
def calcAeroCoeff(inputFile, dataSet): ''' DESCRIPTION: This function calculates the lift coefficient for the static measurements. (CL \approx CN) ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n ... dataSet [String]: Name of data set; choose between 'static1', 'static2a' or 'static2b'\n ... SI [Condition]: By default set to SI=True\n OUTPUT:\n ... aeroCoeff [Dataframe]: Pandas dataframe containing Cl, Cd, e, Cla, Cd0, aoa0 ''' # Import data param = imPar.parametersStatic() static = imStat.staticMeas(inputFile, dataSet) staticNotSI = imStat.staticMeas(inputFile, dataSet, SI=False) staticFlightCond = imStat.staticFlightCondition(inputFile, dataSet) staticTp = imStat.staticThrust(inputFile, dataSet) staticWeight = imWeight.calcWeightCG(inputFile, dataSet) # Obtain vales from data S = param.S A = param.A aoa_rad = static['aoa'].to_numpy() aoa_deg = staticNotSI['aoa'].to_numpy() rho = staticFlightCond['rho'].to_numpy() Vt = staticFlightCond['Vt'].to_numpy() W = staticWeight['Weight'].to_numpy() Tp = staticTp['Tp'].to_numpy() # Calculations Cl = W / (0.5 * rho * Vt**2 * S) Cd = Tp / (0.5 * rho * Vt**2 * S) aeroCoeff = {} if dataSet == 'static1': Cl_aoa = stats.linregress(aoa_deg,Cl) Cd_Cl2 = stats.linregress(Cl**2,Cd) Cla = Cl_aoa.slope aoa0 = -Cl_aoa.intercept / Cla e = 1/(np.pi*A*Cd_Cl2.slope) Cd0 = Cd_Cl2.intercept dataNames = ['Cl','Cd','e','Cla','Cd0','aoa0'] for name in dataNames: aeroCoeff[name] = locals()[name] else: dataNames = ['Cl','Cd'] for name in dataNames: aeroCoeff[name] = locals()[name] aeroCoeff = pd.DataFrame(data=aeroCoeff) return aeroCoeff
def calcAeroCoeff(inputFile): ''' DESCRIPTION: This function calculates the aerodynamic coefficient for the first static measurement. (CL \approx CN) ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n OUTPUT:\n ... CLa [float]: Lift curve slope ... aoa0 [float]: Zero lift angle of attack ... e [float]: Oswald efficiency factor ... CD0 [float]: Zero lift drag ... aeroCoeff [Dataframe]: Pandas dataframe containing CL, CD ''' # Import data param = imPar.parametersStatic() static = imStat.staticMeas(inputFile, 'static1') staticNotSI = imStat.staticMeas(inputFile, 'static1', SI=False) staticFlightCond = imStat.staticFlightCondition(inputFile, 'static1') staticTp = imStat.staticThrust(inputFile, 'static1') staticWeight = imWeight.calcWeightCG(inputFile, 'static1') # Obtain vales from data S = param.S A = param.A aoa_rad = static['aoa'].to_numpy() aoa_deg = staticNotSI['aoa'].to_numpy() rho = staticFlightCond['rho'].to_numpy() Vt = staticFlightCond['Vt'].to_numpy() W = staticWeight['Weight'].to_numpy() Tp = staticTp['Tp'].to_numpy() # Calculations CL = W / (0.5 * rho * Vt**2 * S) CD = Tp / (0.5 * rho * Vt**2 * S) CL_aoa = stat.linregress(aoa_rad, CL) CD_CL2 = stat.linregress(CL**2, CD) CLa = CL_aoa.slope aoa0 = -CL_aoa.intercept / CLa e = 1 / (np.pi * A * CD_CL2.slope) CD0 = CD_CL2.intercept aeroCoeff = {} dataNames = ['CL', 'CD'] for name in dataNames: aeroCoeff[name] = locals()[name] aeroCoeff = pd.DataFrame(data=aeroCoeff) return CLa, aoa0, e, CD0, aeroCoeff
def plotElevTrimCurve(inputFile): ''' DESCRIPTION: Function description ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n OUTPUT:\n ... None, but running this function creates a figure which can be displayed by calling plt.plot() ''' # Import data static2a_nonSI = imStat.staticMeas(inputFile,'static2a',SI=False) Weight2a = imWeight.calcWeightCG(inputFile, 'static2a') # Obtain values from data aoa_deg = static2a_nonSI['aoa'].to_numpy() delta_deg = static2a_nonSI['delta'].to_numpy() Xcg = np.average(Weight2a['Xcg'].to_numpy()) Weight = np.average(Weight2a['Weight'].to_numpy()) # Calculations linregress = stats.linregress(aoa_deg, delta_deg) # Start plotting plt.figure('Elevator trim curve',[10,7]) plt.title("Elevator Trim Curve",fontsize=22) plt.scatter(aoa_deg,delta_deg) plt.plot(np.sort(aoa_deg),np.sort(aoa_deg)*linregress.slope + linregress.intercept, 'k--') plt.ylim(1.2*max(delta_deg),1.2*min(delta_deg)) plt.grid() plt.xlim(0.9*np.sort(aoa_deg)[0],1.1*np.sort(aoa_deg)[-1]) plt.xlabel(r'$\alpha$ [$\degree$]',fontsize=16) plt.ylabel(r'$\delta_{e}$ [$\degree$]',fontsize=16) plt.axhline(0,color='k') props = dict(boxstyle='round', facecolor='white', alpha=0.5) # plt.text(1.03*np.sort(aoa_deg)[1],1.05*delta_deg[1],'$x_{cg}$ = 7.15 m\nW = 59875 kg',bbox=props,fontsize=16) plt.text(1.03*np.sort(aoa_deg)[1],1.05*delta_deg[1],'$x_{cg}$ = '+str(round(Xcg,2))+' m\nW = '+str(int(round(Weight,0)))+' kg',bbox=props,fontsize=16) props = dict(boxstyle='round', facecolor='white', alpha=0.5) plt.show() return
def plotRedElevContrForceCurve(inputFile): ''' DESCRIPTION: Function description ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n OUTPUT:\n ... None, but running this function creates a figure which can be displayed by calling plt.plot() ''' # Import data static2a = imStat.staticMeas(inputFile,'static2a') flightCond2a = imStat.staticFlightCondition(inputFile,'static2a') Weight2a = imWeight.calcWeightCG(inputFile, 'static2a') # Obtain values from data VeRed = np.sort( flightCond2a['VeRed'].to_numpy() ) Xcg = np.average(Weight2a['Xcg'].to_numpy()) deltaTr = np.rad2deg(np.average(static2a['deltaTr'])) # Calculation FeRed = np.sort(calcElevContrForce(inputFile)) # Start plotting plt.figure('Elevator Force Control Curve',[10,7]) plt.title("Reduced Elevator Control Force Curve",fontsize=22) plt.plot(VeRed,FeRed,marker='o') plt.xlim(0.9*VeRed[0],1.1*VeRed[-1]) plt.xlabel(r'$V_{e}^{*}$ [$\dfrac{m}{s}$]',fontsize=16) plt.ylim(1.2*FeRed[-1],1.2*FeRed[0]) plt.ylabel(r'$F_{e}^{*}$ [N]',fontsize=16) plt.axhline(0,color='k') props = dict(boxstyle='round', facecolor='white', alpha=0.5) plt.text(1.03*VeRed[2],1.05*FeRed[2],'$x_{cg}$ = '+str(round(Xcg,2))+' m\n$\delta_{t_{e}}$ = '+str(round(deltaTr,3))+'$\degree$',bbox=props,fontsize=16) plt.grid() return
def staticFlightCondition(inputFile, dataSet): ''' DESCRIPTION: This function calculates flight conditions using the measurement data. ======== INPUT:\n ... inputFile [String]: Name of excel file; choose between 'reference' or 'actual'\n ... dataSet [String]: Name of data set; choose between 'static1', 'static2a' or 'static2b'\n ... SI [Condition]: By default set to SI=True\n OUTPUT:\n ... staticFlightCond [Dataframe]: Pandas dataframe containing flight condition values that are not measured. ''' # Import data meas = staticMeas(inputFile, dataSet, SI=True) param = imPar.parametersStatic() staticWeight = imWeight.calcWeightCG(inputFile, dataSet) # Constant values pres0 = param.pres0 rho0 = param.rho0 Temp0 = param.Temp0 g0 = param.g Ws = param.Ws gamma = param.gamma lamb = param.lamb R = param.R Vi = meas['Vi'].to_numpy() Vc = Vi - 2 * 0.514444444 TempMeas = meas['TAT'].to_numpy() hp = meas['hp'].to_numpy() W = staticWeight['Weight'].to_numpy() # Calculation pres = pres0 * (1 + lamb * hp / Temp0)**(-g0 / (lamb * R)) Mach = np.sqrt( 2 / (gamma - 1) * ((1 + pres0 / pres * ((1 + (gamma - 1) / (2 * gamma) * rho0 / pres0 * Vc**2)**(gamma / (gamma - 1)) - 1))**( (gamma - 1) / gamma) - 1)) Temp = TempMeas / (1 + (gamma - 1) / 2 * Mach**2) a = np.sqrt(gamma * R * Temp) Vt = Mach * a rho = pres / (R * Temp) Ve = Vt * np.sqrt(rho / rho0) VeRed = Ve * np.sqrt(Ws / W) Tisa = Temp0 + lamb * meas['hp'].to_numpy() DeltaTisa = Temp - Tisa staticFlightCond = {} dataNames = [ 'pres', 'Mach', 'Temp', 'a', 'Vt', 'rho', 'Ve', 'VeRed', 'DeltaTisa' ] for name in dataNames: staticFlightCond[name] = locals()[name] staticFlightCond = pd.DataFrame(data=staticFlightCond) return staticFlightCond