def main(args): trAng5 = rad(5.0) trAng6 = rad(6.0) c_f_water = 1481.0 c_air = 343 c1 = c_f_water c2 = c_air ang5 = np.arcsin((c1 / c2) * trAng5) ang6 = np.arcsin((c1 / c2) * trAng6) print deg(ang5) print deg(ang6) d = 1.0/(tan(ang6)-tan(ang5)) print d R = d*tan(ang5) print R return 0
def get_poa(self, dates, ghi, dhi, dni, sun_zenith, sun_azimuth, dni_extra=None, airmass=None, model="haydavies"): if self.method == "pvlib": sun_zenith = deg(sun_zenith) sun_azimuth = deg(sun_azimuth) if dni_extra is None: dni_extra = irradiance.extraradiation(DatetimeIndex(dates)) if airmass is None: airmass = atmosphere.relativeairmass(sun_zenith) poa = irradiance.total_irrad(self.tilt, self.azimuth, sun_zenith, sun_azimuth, dni, ghi, dhi, dni_extra=dni_extra, airmass=airmass, model=model, albedo=self.albedo) self.poa = poa['poa_global']
def xcp(self, alpha): '''wing center of pressure measured vs leading edge''' alphaMin = -2 # deg alphaMax = 9.5 # deg if alpha < rad(alphaMin): alpha = rad(alphaMin) elif alpha > rad(alphaMax): alpha = rad(alphaMax) return self.xCP[0] + self.xCP[1] * deg(alpha) + self.xCP[2] * deg(alpha) ** 2 + self.xCP[3] * deg(alpha) ** 3
def draw_arc_arrow(ax, angle_, theta2_, center=(0., 0.), text="", text_offset=(0., 0.), radius=1., color='white', is_rad=True, flip=False): if(is_rad): angle_ = deg(angle_) theta2_ = deg(theta2_) #========Line if(flip): head_angle = 180+angle_ direction = 1. arc = Arc([center[0],center[1]],radius*2.,radius*2.,angle=angle_, theta1=0., theta2=theta2_-angle_, capstyle='round', linestyle='-', lw=1, color=color) else: head_angle = angle_ direction = -1. arc = Arc([center[0],center[1]],radius*2.,radius*2.,angle=theta2_, theta1=0., theta2=angle_-theta2_, capstyle='round', linestyle='-', lw=1, color=color) ax.add_patch(arc) #========Create the arrow head arrow_scale = radius/30. delta_angle = arrow_scale/(radius) endX=center[0]+(radius)*(np.cos(rad(angle_) + direction*delta_angle) ) #Do trig to determine end position endY=center[1]+(radius)*(np.sin(rad(angle_) + direction*delta_angle) ) ax.add_patch( #Create triangle as arrow head RegularPolygon( (endX, endY), # (x,y) 3, # number of vertices arrow_scale, # radius rad(head_angle), # orientation color=color ) ) #========text middle_angle = theta2_ - (theta2_ - angle_)/2. endX=center[0]+(radius*1.05)*(np.cos(rad(middle_angle)) ) endY=center[1]+(radius*1.05)*(np.sin(rad(middle_angle)) ) ax.text(endX+text_offset[0], endY+text_offset[1], text, size=20) return
def inverse(t,tol=0.1): target = vector(t) if((t - joint_positions['shoulder']).length > 57.1): print('Out of range') return out_of_range_condition(target) elif((t - joint_positions['wrist']).length < tol): print('Iterations = 0') try: return(deg([theta_shoulder, theta_arm_ud, theta_arm_oc, theta_uturn, theta_elbow])) except NameError: return([0,0,0,0,0]) else: return iteration(target,tol)
def serialize(angle, hour=False): if not angle: return "Nedefinisan" angle = deg(angle) if hour: angle /= 15 degrees = int(angle) minutes = (angle - degrees) * 60 seconds = (minutes - int(minutes)) * 60 minutes = int(minutes) if hour: return f"{degrees}h {minutes}m {seconds:.3f}s" return f"{degrees}° {minutes}' {seconds:.3f}\""
def launch(args): # logging.basicConfig() #Edit params.yml here only; it is copied (read only) to results folder # print('Backend {}, interactive {}'.format(matplotlib.get_backend(), matplotlib.is_interactive())) ####################################################################### # path = '/media/sf_results/2021-11-15' # path = '/media/sf_results/2021-11-24 v control' ####################################################################### [path,ks,replacedParams] = args os.chdir('/home/bret/winchrep/pythonModeling/launch') # sys.stdout = Tee(sys.stdout, open(os.path.join(path,'log.txt'), "w")) runsDir = path.replace(path.split('/')[-1],'') if not os.path.exists(runsDir): os.mkdir(runsDir) print ('\n',ks) print ('**** Number of run folders: ',len( os.listdir(runsDir))) if not os.path.exists(path): os.mkdir(path) overwriteCopyParams(replacedParams,path) pr = loadParams(path) # parameters if not pr['overwriteResults'] and os.path.exists(os.path.join(path, 'results.txt')): print('Run complete: results.txt exists') return g = 9.8 saveStateFile = os.path.join(path, 'savedState') writeStatesFile = os.path.join(path, 'manyStates') writeStateDersFile = os.path.join(path, 'manyStDers') save = [saveStateFile,writeStatesFile, writeStateDersFile] if os.path.exists(writeStatesFile): os.remove(writeStatesFile) if os.path.exists(writeStateDersFile): os.remove(writeStateDersFile) #--- time tStart = pr['tStart'] tEnd = pr['tEnd'] print ('tEnd',tEnd) dt0 = pr['dt0'] tfactor = pr['tfactor'] if pr['useTables']: tfactor = max(30,tfactor) dt = dt0/float(tfactor) # nominal time step, sec ntime = int((tEnd - tStart)/dt) + 1 # number of time steps to allow for data points saved # # Loop over parameters for study, optimization # if loop: # loopParams = linspace(0,8,50) #Alpha\ # else: # loopParams = [setpoint[0]] # # # loopData = zeros(len(loopParams),dtype = [('alphaLoop', float),('xRoll', float),('tRoll', float),('yfinal', float),('vmax', float),('vDmax', float),('Sthmax',float),\ # ('alphaMax', float),('gammaMax', float),('thetaDmax', float),('Tmax', float),('Tavg', float),('yDfinal', float),('Lmax', float),\ # ('smRopeMin', float),('smStallMin', float),('smStructMin', float),('smRecovMin', float)]) # yminLoop = 20 #if yfinal is less than this height, the run failed, so ignore this time point # for iloop,param in enumerate(loopParams): # alphaLoop = param # if len(loopParams) > 1: # if loopWhich == 0: # path = os.path.join(path,'loop0--{:3.1f},3'.format(param)) # setpoint = [param,3,30] # deg,speed, deg last one is climb angle to transition to final control # elif loopWhich == 1: # path = os.path.join(path,'loop1--3,{:3.1f}'.format(param)) # setpoint = [3,param,30] # deg,speed, deg last one is climb angle to transition to final control # elif loopWhich == 'both': # path = os.path.join(path,'loop01--{:3.1f},{:3.1f}'.format(param,param)) # setpoint = [param,param,30] # deg,speed, deg last one is climb angle to transition to final control # if not os.path.exists(path): os.mkdir(path) # else: # path = path control = pr['control'] setpoint = pr['setpoint'] print('\nInitial pilot control: ({},{:4.1f})'.format(control[0],setpoint[0]) ) t = linspace(tStart,tEnd,num=ntime) # create the objects we need from classes ti = timeinfo(tStart,tEnd,ntime) gl = glider(pr,ntime) ai = air(pr,gl,ntime) rp = rope(pr,tEnd,ntime) dr = drum(pr,ntime) tc = torqconv(pr,ntime) en = engine(pr,dr,ntime) op = operator(pr,ntime) pl = pilot(pr,control,setpoint,ntime) ##### Advanced block for air start # loadState = True loadState = pr['loadState'] if loadState: # print('loading state from {}'.format(saveStateFile) ) time,gl,rp,dr,tc,en,op,pl = readState(saveStateFile,gl,rp,dr,tc,en,op,pl) print('loaded state for time {}', time) #Change some of the initial conditions rp.T = op.targetT * gl.W # v = 43 # gl.xD = v * cos(gl.theta); gl.yD = v* sin(gl.theta) # gl.y = 1 ##### End advanced block for air start #initialize state vector to zero S0 = zeros(9) #integrate the ODEs S0 = stateJoin(S0,gl,rp,dr,tc,en,op,pl) S = odeint(stateDer,S0,t,mxstep=500, args =(pr,gl,ai,rp,dr,tc,en,op,pl,ti,save)) #Split S (now a matrix with state variables in columns and times in rows) gl,rp,dr,tc,en,op,pl = stateSplitMat(S,gl,rp,dr,tc,en,op,pl) #gl.x, etc are now 1-D arrays # Integrater always goes to tEnd. # ti.i and all data arrays stoppped being updated after release # ti is passed to prepData and arrays are stopped after tRelease # So tRelease = ti.data[ti.i]['t'] preppedData = prepData(pr,t,ti,gl,ai,rp,dr,tc,en,op,pl) [t, x, y, xD, yD, v, vD, alpha, theta, thetaD, gamma, elev, Sth, omegd, omege, L, D, T, Tg, vgw, \ torqWing,torqStab, Me, Few, engP, omegrel, rdrum, tctorqueDrum, winP, ropP, gliP, gndTorq, ropeTheta, ropeTorq, \ smRope, smStall, smStruct, smRecov, vGust, gData, dData, oData, pData, eData, rData, aData, tData] = preppedData #ground roll if max(y) > gl.deltar: iEndRoll = where(y > gl.deltar)[0][0] # where it's left the ground xRoll = x[iEndRoll] tRoll = t[iEndRoll] iEndRollData = where(t>tRoll)[0][0] else: xRoll = 0 #didn't get off ground tRoll = 0 iEndRollData = 1 #misc results Tavg = mean(T[where(T>10)[0]])/gl.W # final values yfinal = y[-1] yDfinal = yD[-1] # if yDfinal < 0.5: yDfinal = 0 # max values ymax = max(y) thetaDmax = max(thetaD) vmax = max(v) vDmax = max(vD) #max acceleration Sthmax = max(Sth) Tmax = max(T)/gl.W alphaMax = max(alpha[iEndRollData:]) Lmax = max(L)/gl.W gammaMax = max(gamma) # safety margin minimum values taken when glider is 1m or more above the ground minHeight = 1 #m to be airborne if y[-1] > minHeight: iminHeight = where(y > minHeight)[0][0] tminHeight = t[iminHeight] iminHeightData = where(t>tminHeight)[0][0] smRopeMin = min(smRope[iminHeightData:]) smStallMin = min(smStall[iminHeightData:]) smStructMin = min(smStruct[iminHeightData:]) smRecovMin = min(smRecov[iminHeightData:]) else: iminHeight = 0 tminHeight = 0 iminHeightData = t smRopeMin = min(smRope) smStallMin = min(smStall) smStructMin = min(smStruct) smRecovMin = min(smRecov) # Comments to user print('Controls', control ) print('Throttle ramp up time (after slack is out)', op.tRampUp) print('Final time: {:5.1f}s'.format(t[-1])) print('Final vy: {:5.1f} m/s'.format(yDfinal)) if yDfinal > 0: ymax += 0.5* yDfinal**2/g stalledList = where(gl.data['alpha'] > gl.alphaStall)[0] if len(stalledList) > 0: tstalled = t[stalledList[0]] print ('Glider stalled at {:5.1f}s'.format(tstalled)) print('Final height reached: {:5.0f} m, {:5.0f} ft. Fraction of rope length: {:4.1f}%'.format(yfinal,yfinal/0.305,100*yfinal/float(rp.lo))) print('Maximum speed: {:3.0f} m/s, maximum rotation rate: {:3.1f} deg/s'.format(vmax,deg(thetaDmax))) print('Maximum tension factor: {:3.1f}'.format(Tmax)) print('Average tension factor: {:3.1f}'.format(Tavg)) print('Maximum angle of attack: {:3.1f} deg'.format(deg(alphaMax))) print('Ground roll: {:5.0f} m, {:5.1f} sec'.format(xRoll,tRoll)) # # check whether to keep this run as loop data # if yfinal < yminLoop and iloop >0: # print('Bad run, not saving data') # loopData[iloop] = loopData[iloop-1] #write over this data point with the last one. # else: # # Store loop results # loopData[iloop]['alphaLoop'] = alphaLoop # loopData[iloop]['xRoll'] = xRoll # loopData[iloop]['tRoll'] = tRoll # loopData[iloop]['yfinal'] = yfinal # loopData[iloop]['yDfinal'] = yDfinal # loopData[iloop]['vmax'] = vmax # loopData[iloop]['vDmax'] = vDmax # loopData[iloop]['Lmax'] = Lmax # loopData[iloop]['Tmax'] = Tmax # loopData[iloop]['Tavg'] = Tavg # loopData[iloop]['Sthmax'] = Sthmax # loopData[iloop]['alphaMax'] = deg(alphaMax) # loopData[iloop]['gammaMax'] = deg(gammaMax) # loopData[iloop]['thetaDmax'] = deg(thetaDmax) # loopData[iloop]['smRopeMin'] = smRopeMin # loopData[iloop]['smStallMin'] = smStallMin # loopData[iloop]['smStructMin'] = smStructMin # loopData[iloop]['smRecovMin'] = smRecovMin # Need to fix this to plot for each part of loop # plot results for each one close('all') if pr['SIPlotsShow'] or pr['SIPlotsSave']: figures = plotsSI(path,preppedData,pr,gl,ai,rp,dr,tc,en,op,pl) if pr['impPlotsShow'] or pr['impPlotsSave']: figures = plotsImp(figures,path,preppedData,pr,gl,ai,rp,dr,tc,en,op,pl) # show() writeRunResults(ks,setpoint,elev,t,v,gl,op,rp,pl,T,Sth,yfinal,stalledList,path) return
def writeRunResults(ks, setpoint, elev, t, v, gl, op, rp, pl, T, Sth, yfinal, stalledList, path): print(ks) vSet = setpoint[0] # placesTest = where(v > vSet)[0] # placesTest = where(t > 1)[0] if pl.tPrepRelease: placesTest = where((t > op.tRampUp + 1) & (t < pl.tPrepRelease))[ 0] #Don't include ramp period in tests. else: placesTest = where(t > op.tRampUp + 1)[0] if len(placesTest) > 0: timesTest = t[placesTest] testStart = timesTest[0] flightDur = timesTest[-1] - testStart vTest = v[placesTest] elevTest = deg(elev[placesTest]) verr = vTest - vSet meanv = mean(vTest) meanvErr = mean(verr) stdvErr = std(verr) meanElev = mean(elevTest) stdElev = std(elevTest) Ttest = T[placesTest] / gl.W * 100 Terr = Ttest - op.targetT * 100 meanT = mean(Ttest) meanTErr = mean(Terr) stdTErr = std(Terr) SthTest = Sth[placesTest] # sampleElev the elevator and throttle every 0.5 sec for extreme swings dt = 0.1 # sec sampleElev = [] lasttime = timesTest[0] crossElev = 0 # how many times does the elevator setting change sign? for i, elevator in enumerate(elevTest[:-1]): if timesTest[i] - lasttime > dt: sampleElev.append(elevator) for i in range(len(sampleElev) - 1): if sign(sampleElev[i]) != sign(sampleElev[i + 1]): crossElev += 1 sampleSth = [] fullThr = 0 # how many times does the throttle hit 100 and drop away for i, setting in enumerate(SthTest[:-1]): if timesTest[i] - lasttime > dt: sampleSth.append(setting) for i in range(len(sampleSth) - 1): if sampleSth[i] < 1.0 and abs(sampleSth[i + 1] - 1.0) < 1e-6: fullThr += 1 fracHeight = 100 * yfinal / float(rp.lo) if len(stalledList) > 0: stalled = 1.0 else: stalled = 0 output = [ flightDur, testStart, meanv, meanvErr, stdvErr, meanElev, stdElev, crossElev, meanT, meanTErr, stdTErr, fullThr, fracHeight, stalled ] labels = [ 'flightDur', 'testStart', 'meanv ', 'meanvErr', 'stdvErr ', 'meanElev', 'stdElev', 'crossElev', 'meanTx100', 'meanTErr', 'stdTErr', 'fullThr', 'fracHeight', 'stalled' ] resultsLines = [] for i, label in enumerate(labels): resultsLine = '{} \t{:4.1f}'.format(label, output[i]) print(resultsLine) resultsLines.append(resultsLine + '\n') writefile(resultsLines, os.path.join(path, 'results.txt'))
def plotsImp(figures, path, preppedData, pr, gl, ai, rp, dr, tc, en, op, pl): close('all') showPlot = pr['impPlotsShow'] save = pr['impPlotsSave'] path = os.path.join(path, 'imperial') if not os.path.exists(path): os.mkdir(path) lbsPernewt = 1 / 4.44822 hpPerW = 1.34102 / 1000.0 ftlbPerNm = 0.738 ktPerms = 1.94384 ftPerm = 3.28084 rpmPerRadPs = 60 / 2 / pi g = 9.8 [t, x, y, xD, yD, v, vD, alpha, theta, thetaD, gamma, elev, Sth, omegd, omege, L, D, T, Tg, vgw, \ torqWing,torqStab, Me, Few, engP, omegrel, rdrum, tctorqueDrum, winP, ropP, gliP, gndTorq, ropeTheta, ropeTorq, \ smRope, smStall, smStruct, smRecov, vGust, gData, dData, oData, pData, eData, rData, aData, tData] = preppedData iColor = 0 # counter for plots, so each variable has a different color # plot engine power and torque curves from model parameters if pr['plotPowerTorque']: omegeng = linspace(0, 1.1 * en.omegapeakP, 100) powr = linspace(0, 1.1 * en.omegapeakP, 100) torq = linspace(0, 1.1 * en.omegapeakP, 100) rpm = omegeng * 60 / 2.0 / pi for i, omegr in enumerate(omegeng): powr[i] = hpPerW * en.Pavail(omegr) torq[i] = ftlbPerNm * en.torqAvail(omegr) figures.append( xy(False, showPlot, save, path, iColor, [rpm], [powr, torq], 'Engine speed (rpm)', 'Power (HP), Torque(Ftlbs)', ['Pistons power', 'Pistons torque'], 'Engine curves')) if pr['plotLift']: ##plot lift curve vs alpha at v_best alphaList = linspace(-20, 80, 100) lift = array([gl.Lnl(gl.vb, rad(alph)) for alph in alphaList]) figures.append(xy(False, showPlot, save, path, iColor, [alphaList], [lift/gl.W], \ 'Angle of attack (deg)', 'Lift/Weight', [''], 'Lift vs angle of attack')) alphaList = linspace(-4, pr['alphaStallVsWing'], 100) drag = array([gl.coeffDrag(rad(alph)) for alph in alphaList]) figures.append(xy(False, showPlot, save, path, iColor, [alphaList], [drag], \ 'Angle of attack (deg)', 'Drag coefficient', [''], 'Drag vs angle of attack')) if pr['plotTorqCov']: vrelList = linspace(0, 1.5, 100) tcGearingList = array([tc.torqMult(vrel) for vrel in vrelList]) # tcEfficiencyList = array([vrel * tc.torqMult(vrel) for vrel in vrelList]) tcInvKform = array([tc.invKform(vrel) for vrel in vrelList]) figures.append(xy(False, showPlot, save, path, iColor, [vrelList], \ [tcGearingList, tcInvKform], 'vDrum/vEngine', '' ,['torque factor','inverse capacity form'], 'Torque converter')) # def xy(holdOpen, showPlot, save, path, iColor, xs, ys, xlbl, ylbl, legendLabels, titlestr, xmin=None, xmax=None): #presentation figures #height, T, L, y vs x figures.append( xy(False, showPlot, save, path, iColor, [ftPerm * x], [ftPerm * y, Tg / gl.W * 1000, L / gl.W * 1000], 'x (ft)', 'y (ft), forces', ['height', 'tension/Weight x 1000', 'lift/Weight x 1000'], 'Height and forces vs x')) # glider v, climb, alpha, elevator vs x figures.append(xy(False, showPlot, save, path, iColor, [ftPerm * x], [ktPerms*v, deg(alpha),deg(gamma), deg(elev)], \ 'x (ft)', 'velocity (kts), angles (deg)', ['v', 'angle of attack', 'climb', 'elevator'], 'Glider speed and angles vs x')) # engine rpm, vrel, thr vs x figures.append(xy(False, showPlot, save, path, iColor, [ftPerm*x], [omege * 60 / 2 / pi/10, hpPerW*engP, 10 * 100 * omegrel, 10 * 100 * Sth], \ 'x (ft)', 'Speeds (rpm,kts), %', ['eng rpm/10', 'engine HP', \ 'TC speed vs engine % x10', 'throttle % x10'], 'Engine vs x')) #height, T, L, y vs t figures.append( xy(False, showPlot, save, path, iColor, [t], [ftPerm * y, Tg / gl.W * 1000, L / gl.W * 1000], 't (sec)', 'y (ft), forces', ['height', 'tension/Weight x 1000', 'lift/Weight x 1000'], 'Height and forces vs t')) # glider v, climb, alpha, elevator vs t figures.append(xy(False, showPlot, save, path, iColor, [t], [ktPerms*v, deg(alpha),deg(gamma), deg(elev)], \ 't (sec)', 'velocity (kts), angles (deg)', ['v', 'angle of attack', 'climb', 'elevator'], 'Glider speed and angles vs t')) # engine rpm, vrel, thr vs t figures.append(xy(False, showPlot, save, path, iColor, [t], [omege * 60 / 2 / pi/10, hpPerW*engP, 10 * 100 * omegrel, 10 * 100 * Sth], \ 't (sec)', 'Speeds (rpm,kts), %', ['eng rpm/10', 'engine HP', \ 'TC speed vs engine % x10', 'throttle % x10'], 'Engine vs t')) # glider position vs time figures.append( xy(False, showPlot, save, path, iColor, [t], [ftPerm * x, ftPerm * y], 'time (sec)', 'position (ft)', ['x', 'y'], 'Glider position vs time')) figures.append( xy(False, showPlot, save, path, iColor, [ftPerm * x], [ftPerm * y], 'x (ft)', 'y (ft)', [''], 'Glider y vs x')) # glider speed and angles figures.append(xy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t], [ktPerms*xD, ktPerms*yD, ktPerms*v, deg(alpha), deg(theta), deg(gamma), deg(elev), deg(thetaD)], \ 'time (sec)', 'Velocity (kts), Angles (deg)', ['vx', 'vy', 'v', 'angle of attack', 'pitch', 'climb', 'elevator', 'pitch rate (deg/sec)'], 'Glider velocities and angles')) # iColor = 0 #restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t, t], [ktPerms*v, ktPerms * dr.rdrum * omegd, y/rp.lo, Tg/gl.W, L/gl.W, divide(L, D), deg(alpha), deg(gamma), deg(thetaD)], \ [0, 0, 1, 1, 1, 0, 0, 0, 0], 'time (sec)', ['Velocity (kt), Angles (deg), L/D', 'Relative forces and height'], ['v (glider)', r'$v_r$ (rope)', \ 'height/' + r'$\l_o $', 'T/W at glider', 'L/W', 'L/D', 'angle of attack', 'climb angle', 'rot. rate (deg/sec)'], 'Glider and rope')) # Forces figures.append(xy(False, showPlot, save, path, iColor, [t, t, t, t, t], [L/gl.W, D/gl.W, T/gl.W, Tg/gl.W, Few/gl.W], \ 'time (sec)', 'Forces/Weight', ['lift', 'drag', 'tension at drum', 'tension at glider', 'tc-drum'], 'Forces')) # torques figures.append( xy(False, showPlot, save, path, iColor, [t], [ ftlbPerNm * ropeTorq, ftlbPerNm * (torqWing + torqStab), ftlbPerNm * Me, ftlbPerNm * gndTorq ], 'time (sec)', 'Torque (ft-lbs)', ['rope', 'stabilizer+wing', 'elevator', 'ground'], 'Torques on glider')) figures.append( xy(False, showPlot, save, path, iColor, [t], [ftlbPerNm * torqWing, ftlbPerNm * torqStab], 'time (sec)', 'Torque (ft-lbs)', ['wing', 'stabilizer'], 'Torques wing and stabilzer')) # Engine, rope and drum figures.append(xy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t], [ktPerms*multiply(omege,rdrum)/dr.gear/dr.diff, ktPerms*multiply(omegd,rdrum), \ ktPerms*vgw, deg(ropeTheta), ftlbPerNm * tctorqueDrum/10, -ftlbPerNm * multiply(T,rdrum)/10, 100 * Sth], 'time (sec)', 'Speeds (effective: kt), Torque/10 (Ft-lbs) Angle (deg), Throttle %', ['engine speed', 'rope speed', 'glider radial speed', 'rope angle', 'TC torque on drum', 'Rope torque on drum','throttle'], 'Engine, drum and rope')) # Engine figures.append(xy(False, showPlot, save, path, iColor, [t], [omege * 60 / 2 / pi/10, hpPerW*engP, ftlbPerNm*engP/(omege + 1e-6), ftlbPerNm*tctorqueDrum/dr.gear/ dr.diff, 10 * 100 * omegrel, 10 * 100 * Sth], \ 'time (sec)', 'Speeds (rpm,kts), Torque (ft-lbs), %', ['eng rpm/10', 'engine HP', 'engine torque', 'TC torque out',\ 'TC speed vs engine % x10', 'throttle % x10'], 'Engine')) figures.append( xy(False, showPlot, save, path, iColor, [t], [ eData['Edeliv'] / 1e6, dData['Edeliv'] / 1e6, rData['Edeliv'] / 1e6, gData['Edeliv'] / 1e6, gData['Emech'] / 1e6 ], 'time (sec)', 'Energy (MJ)', ['to engine', 'to drum', 'to rope', 'to glider', 'in glider'], 'Energy delivered and kept')) figures.append( xy(False, showPlot, save, path, iColor, [t], [engP / en.Pmax, winP / en.Pmax, ropP / en.Pmax, gliP / en.Pmax], 'time (sec)', 'Power/Pmax', ['to engine', 'to drum', 'to rope', 'to glider'], 'Power delivered')) zoom = pr['zoom'] if zoom: # if not ai.startGust is None and 's' in ai.startGust: # t1 = float(ai.startGust.split()[0])-0.5 # t2 = t1 + 2*ai.widthGust/2.05.0 + 2.0 -1.5 [t1, t2] = zoom if ai.vGustPeak > 0 and not ai.startGust is None: # without safety margins iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, T/gl.W, vGust], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W', 'vel gust'], 'Winch launch')) if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, T/gl.W, vGust], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W', 'vel gust'], 'Winch launch expanded', t1, t2)) # with safety margins (T/W is redundant) iColor = 0 # restart color cycle figures.append(xyy(False and not zoom, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, smStruct, smStall, smRope, smRecov, vGust], \ [0, 0, 0, 1, 1, 1, 1, 0, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin', 'vel gust'], 'Winch launch and safety margins')) if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, smStruct, smStall, smRope, smRecov, vGust], \ [0, 0, 0, 1, 1, 1, 1, 0, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin', 'vel gust'], 'Winch launch and safety margins expanded', t1, t2)) else: # without gusts # without safety margins if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, T/gl.W], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W'], 'Winch launch expanded', t1, t2)) iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, T/gl.W], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W'], 'Winch launch')) # with safety margins if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, smStruct, smStall, smRope, smRecov], \ [0, 0, 0, 1, 1, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Winch launch and safety margins expanded', t1, t2)) iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t], [ktPerms*v,ftPerm/10.0*y, deg(gamma), L/gl.W, smStruct, smStall, smRope, smRecov], \ [0, 0, 0, 1, 1, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Winch launch and safety margins')) # safety margins alone if zoom: iColor = 6 # choose color cycle start figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t], [smStruct, smStall, smRope, smRecov], \ [1, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Safety margins expanded', t1, t2)) iColor = 6 # choose color cycle start figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t], [smStruct, smStall, smRope, smRecov], \ [1, 1, 1, 0], 'time (sec)', ['Velocity (kt), Height/10 (ft), Angle (deg)', "Relative forces"], \ ['struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Safety margins')) ############# '''Looping over parameters is now done with multiprocessor pool. Below are plots from old looping''' # plot loop results (saved in last parameter's folder # if loop: # heightDiff = loopData['yfinal'] - min(loopData['yfinal']) # vs minimum in loop # iColor = 0 # restart color cycle # figures.append(xyy(False, showPlot, save, path, iColor, [loopData['alphaLoop']] * 12, # [loopData['xRoll'], 10 * loopData['tRoll'], loopData['yfinal']/rp.lo * 100, heightDiff, loopData['vmax'], # loopData['vDmax']/g, loopData['Sthmax'], loopData['Tmax'], loopData['Lmax'], loopData['alphaMax'], # loopData['gammaMax'], # loopData['thetaDmax']], \ # [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0], 'Angle of attack setting (deg)', # ['Velocity (kt), Angles (deg), m, sec, %', "Relative forces,g's"], \ # ['x gnd roll', 't gnd roll x 10', 'height/rope %', 'height diff', r'$v_{max}$', "max g's", 'max throttle', # r'$T_{max}/W$', r'$L_{max}/W$', r'$\alpha_{max}$', r'$\gamma_{max}$', 'rot. max (deg/sec)'], # 'Flight (all) vs target angle of attack')) # # fewer results, for presentation # iColor = 0 # restart color cycle # figures.append(xyy(False, showPlot, save, path, iColor, [loopData['alphaLoop']] * 4, # [loopData['vmax'], heightDiff, loopData['gammaMax'], loopData['Lmax']], \ # [0, 0, 0, 1], 'Angle of attack target (deg)', # ['Velocity (kt), Angle (deg), Height/10 (ft), %', "Relative forces"], \ # [r'$v_{max}$', 'height diff', 'climb angle max', r'$L_{max}/W$'], 'Flight vs target angle of attack')) # # With safety margins for presentation # iColor = 4 # match colors in previous plot # figures.append(xyy(False, [loopData['alphaLoop']] * 4, # [loopData['smStructMin'], loopData['smStallMin'], loopData['smRopeMin'], loopData['smRecovMin']], \ # [1, 1, 1, 0], 'Target angle of attack (deg)', ['Recovery height margin (ft)', "Safety margin (g's)"], \ # ['struct margin', 'stall margin', 'rope margin', 'recovery margin'], # 'Safety margins vs target angle of attack')) # print('Stop program to close plots!') return figures
def get_aoi(self, sun_zenith, sun_azimuth): if self.method == "pvlib": self.aoi = rad(self.syst.get_aoi(deg(sun_zenith), deg(sun_azimuth)))
def stateDer(S, t, pr, gl, ai, rp, dr, tc, en, op, pl, ti, save): '''First derivative of the state vector''' g = 9.8 [saveStateFile, writeStatesFile, writeStateDersFile] = save saveStateTime = pr['saveStateTime'] writeStatesTimes = pr['writeStatesTimes'] if rp.data[ti.i][ 'theta'] > rp.thetaMax: # glider released but the integrator must finish to specified tEnd return zeros(len(S)) else: gl, rp, dr, tc, en, op, pl = stateSplitVec(S, gl, rp, dr, tc, en, op, pl) # if gl.xD < 1e-6: # gl.xD = 1e-6 # to handle v = 0 initial if en.omeg < 1e-6: en.omeg = 1e-6 # to handle v = 0 initial # ----algebraic and logic functions----# # gear dr.checkGear(t) # rope and crash gl.max = max(gl.y, gl.ymax) thetarope = arctan(gl.y / float(rp.lo - gl.x)) if gl.y < 0 and gl.ymax > 1: print('Glider crashed at {:4.1f} s.'.format(t)) else: if thetarope < -1e-6: thetarope += pi # to handle overflight of winch if not rp.broken: # break rope if chosen for simulation: if not rp.breakAngle is None and (thetarope > rp.breakAngle or t > rp.breakTime): rp.broken = True rp.tRelease = t print('Rope broke at rope angle {:4.1f} deg, {:4.1f} s.'. format(deg(thetarope), t)) print('Horizontal velocity {:4.1f} m/s.'.format(gl.xD)) else: rp.T = 0.0 lenrope = sqrt((rp.lo - gl.x)**2 + gl.y**2) # steady wind vwx = ai.vhead if gl.y > ai.heightupdraft: vwy = ai.vupdraft else: vwy = 0.0 # glider v = sqrt(gl.xD**2 + gl.yD**2) # speed vecAir = array( [gl.xD + vwx, gl.yD - vwy] ) # note minus sign for y, similar to above for vwy. Vy reduces glider speed vs air vAir = norm(vecAir) # speed vs air vgw = (gl.xD * (rp.lo - gl.x) - gl.yD * gl.y) / float( lenrope) # velocity of glider toward winch vtrans = sqrt( v**2 - vgw**2 + 1e-6) # velocity of glider perpendicular to straight line rope rp.thetaRG = rp.thetaRopeGlider( t, ti, thetarope, vtrans, lenrope, pr) # rope angle at glider corrected for rope weight and drag Tg = rp.Tglider(thetarope, lenrope) # tension at glider corrected for rope weight if gl.freeFlight: Tg = 0 if gl.xD > 1: # avoid initial zeros problem gamma = arctan(gl.yD / gl.xD) # climb angle. gammaAir = arctan( (gl.yD - vwy) / (gl.xD + vwx)) # climb angle vs air else: gamma = 0 gammaAir = 0 # gusts -- only one 1-cos gust per simulation vgx, vgy, d, vgxStab, vgyStab = ai.gustDynamic(t, gammaAir, gl.x, gl.y) vecGustWing = array( [vgx, -vgy]) # note minus sign for y, similar to above for vwy gammaAirWing = gammaAir vAirWing = vAir if norm(vecGustWing) > 0: vecAirWing = vecAir + vecGustWing vAirWing = norm(vecAirWing) # speed vs air gammaAirWing = arctan( vecAirWing[1] / vecAirWing[0]) # climb angle vs air with gust alpha = gl.theta - gammaAirWing # angle of attack for wing vecGustStab = array( [vgxStab, -vgyStab]) # note minus sign for y, similar to above for vwy gammaAirStab = gammaAir vAirStab = vAir if norm(vecGustStab) > 0: vecAirStab = vecAir + vecGustStab vAirStab = norm(vecAirStab) gammaAirStab = arctan(vecAirStab[1] / vecAirStab[0]) alphaStab = gl.theta - gammaAirStab # angle of attack for elevator # forces on glider Lwing = gl.Lnl(vAirWing, alpha) # lift Lstab = gl.W * (gl.rsw0 + gl.ralphas * alphaStab) * (vAirStab / gl.vb)**2 L = Lwing + Lstab D = gl.W * gl.coeffDrag(alpha) / gl.Co * (vAirWing / gl.vb) ** 2 \ + 0.5 * 1.22 * (gl.Agear * vAirWing ** 2 + rp.Apara * vgw ** 2) torqWing = Lwing * (gl.xCG - gl.xcp(alpha)) torqStab = -gl.ls * Lstab [Fmain, Ftail, Ffric] = gl.gndForces(ti, rp) gndTorq = Fmain * gl.d_m - Ftail * gl.d_t M = torqWing + torqStab + pl.Me + gndTorq # torque of air and ground on glider ropetorq = Tg * sqrt(rp.a**2 + rp.b**2) * sin( arctan(rp.b / float(rp.a)) - gl.theta - rp.thetaRG) # torque of rope on glider # Torques on drum and engine dr.rdrum = dr.newRadius(rp, lenrope) #increasing drum radius with time # if t>14.95: # print(t) # dummy = True omegrel = dr.gear * dr.diff * dr.omeg / en.omeg # dr.gear can vary with time if abs(en.dotomeg) > 1e-6: omegrelD = dr.gear * dr.diff * dr.dotomeg / en.dotomeg else: omegrelD = 0 powerPistons = op.Sth * en.Pavail(en.omeg) torqPistons = powerPistons / float(en.omeg) # if op.Sth>0: # Then it's in gear...but we start with idle at beginning to take up slack slipTorq = tc.invK( omegrel)**2 * en.omeg**2 #- tc.tcdamp * omegrel * omegrelD # torqtcd = tc.torqMult(omegrel) * dr.gear * dr.diff * slipTorq torqtcd = tc.torqMult(omegrel) * dr.gear * dr.diff * slipTorq * ( 1 - pr['winchLossFactor']) torqtce = slipTorq #testing: # if t>3.7: # print('test',t,torqtcd) # dummy=1 # if t>7.3: # print('test', t, 'dr.dotomeg', dr.dotomeg,'en.dotomeg', en.dotomeg, 'omegrelD', omegrelD, 'TM', tc.torqMult(omegrel), 'ik', # tc.invK(omegrel)) # if t>7.5: # sys.exit('stop') # if t> 0 and abs(ti.temp - torqtcd)/abs(torqtcd) > 0.4: # dummy = 1 ti.temp = torqtcd # print (t,'throttle',op.Sth, 'omegrel',omegrel,'torqtcd',torqtcd) # # print('{:10.8f} rpm {:8.0f} omegrel {:8.5f} veng {:8.5f} Sth {:8.5f} P>drum {:8.5f} P<eng {:8.5f} P<pistons {:8.5f}'\ # .format(t,en.omeg*60/2/pi, omegrel,en.omeg*dr.omeTov(),op.Sth, \ # dr.omeg*torqtcd/en.Pmax, en.omeg*torqtce/en.Pmax, # en.omeg*torqPistons/en.Pmax)) powerToEngine = powerPistons powerToDrum = dr.omeg * torqtcd if t > 0.4: dummy = True # ----derivatives of state variables----# dotx = gl.xD dotxD = 1 / float(gl.m) * (Tg * cos(rp.thetaRG) - D * cos(gamma) - L * sin(gamma) - Ffric) # x acceleration doty = gl.yD dotyD = 1 / float( gl.m) * (L * cos(gamma) - Tg * sin(rp.thetaRG) - D * sin(gamma) - gl.W + Fmain + Ftail) # y acceleration dottheta = gl.thetaD dotthetaD = 1 / float(gl.I) * ( ropetorq + M - sign(dottheta) * gl.dampThetaDot * dottheta**2) dotT = rp.chgT(dr.omeg * dr.rdrum, vgw, lenrope) if dotT < 0 and rp.T < 0.01: #don't allow tension to be negative dotT = 0 if gl.freeFlight: dotT = 0 dotomege = 1 / float( en.Iengine) * (torqPistons - torqtce - en.damp * en.omeg) #rpm limiter if en.omeg > en.omegaLimit and dotomege > 0: dotomege = 0.0 dotomegd = 1 / float( dr.Idrum) * (torqtcd - dr.rdrum * rp.T - dr.damp * dr.omeg) # dotomegd = 1 / float(dr.Idrum) * (torqtcd) # print ('turned off rope tension') if t > 7.2: dummy = True # The ode solver enters this routine usually two or more times per time step. # We advance the time step counter only if the time has changed by close to a nominal time step if t - ti.oldt > 1.0 * ti.dt: ti.i += 1 if t > pr['timeForceFullElev']: pl.elev = gl.elevLimits[1] print('FORCING ELEVATOR TO FULL!!') if saveStateTime is not None: if t > saveStateTime: saveState(t, gl, rp, dr, tc, en, op, pl, saveStateFile) if writeStatesTimes is not None: if writeStatesTimes[0] < t < writeStatesTimes[1]: writeStates(t, gl, rp, dr, tc, en, op, pl, writeStatesFile) writeStateDers(t, gl, dotx, dotxD, doty, dotyD, dottheta, dotthetaD, dotT, dotomegd, dotomege, writeStateDersFile) ti.data[ti.i]['t'] = t gl.data[ti.i]['x'] = gl.x gl.data[ti.i]['xD'] = gl.xD gl.data[ti.i]['y'] = gl.y gl.data[ti.i]['yD'] = gl.yD gl.data[ti.i]['v'] = v gl.data[ti.i]['vD'] = sqrt(dotxD**2 + dotyD**2) gl.data[ti.i]['yDD'] = dotyD gl.data[ti.i]['theta'] = gl.theta gl.data[ti.i]['thetaD'] = gl.thetaD gl.data[ti.i]['gamma'] = gamma gl.data[ti.i]['alpha'] = alpha gl.data[ti.i][ 'alphaStall'] = gl.alphaStall # constant stall angle include just for comparison if gl.y > 0.01: sm, Vball, gammaBall, ygainDelay, type = gl.smRecov( v, L, alpha, gamma, pl) # print('t:{:8.3f} type:{:8s} x:{:8.3f} y:{:8.3f} ygnDelay:{:8.3f} sm:{:8.3f} v:{:8.3f} vball:{:8.3f} gam:{:8.3f} gamball:{:8.3f} '.format(t,type,gl.x,gl.y,ygainDelay,sm,v,Vball,deg(gamma),deg(gammaBall))) if gl.y > 0.3 or sm > 0: gl.data[ ti.i]['smRecov'] = sm # gl.smRecov(v,L,alpha,gamma,pl) ngust = ai.gustLoad(gl, v) if Lwing > 0: gl.data[ti.i]['smStall'] = ( vAirWing / gl.vStall )**2 - Lwing / gl.W - ngust # safety margin vs stall (g's) gl.data[ti.i]['smStruct'] = gl.n1 * sqrt( (1 - gl.mw * gl.yG / gl.m / gl.yL * (1 - 1 / gl.n1)) ) - Lwing / gl.W - ngust # safety margin vs structural damage (g's) else: gl.data[ti.i]['smStall'] = ( vAirWing / gl.vStall )**2 - ngust # safety margin vs stall (g's). No negative lift is considered. gl.data[ti.i]['smStruct'] = gl.n4 * sqrt( (1 - gl.mw * gl.yG / gl.m / gl.yL * (1 - 1 / gl.n1)) ) - abs( Lwing ) / gl.W - ngust # safety margin vs structural damage (g's) # gl.data[ti.i]['smStruct'] = gl.n1*(1-0) - Lglider/gl.W - ngust #safety margin vs structural damage (g's) gl.data[ti.i]['vgw'] = vgw gl.data[ti.i]['L'] = L gl.data[ti.i]['D'] = D gl.data[ti.i]['gndTorq'] = gndTorq gl.data[ti.i]['torqWing'] = torqWing gl.data[ti.i]['torqStab'] = torqStab gl.data[ti.i]['Emech'] = 0.5 * ( gl.m * v**2 + gl.I * gl.thetaD**2) + gl.m * g * gl.y # only glider energy here gl.data[ti.i]['Pdeliv'] = Tg * v * cos(rp.thetaRG + gl.theta) gl.data[ti.i]['Edeliv'] = gl.data[ti.i - 1]['Edeliv'] + gl.data[ ti.i]['Pdeliv'] * (t - ti.oldt) # integrate ai.data[ti.i]['vGust'] = norm(vecGustWing) op.data[ti.i]['Sth'] = op.Sth rp.data[ti.i]['Pdeliv'] = rp.T * dr.omeg * dr.rdrum rp.data[ti.i]['Edeliv'] = rp.data[ti.i - 1]['Edeliv'] + rp.data[ ti.i]['Pdeliv'] * (t - ti.oldt) # integrate rp.data[ti.i]['T'] = rp.T rp.data[ti.i]['Tglider'] = Tg rp.data[ti.i][ 'torq'] = ropetorq #torque of rope on glider (on rp. for labeling simplicty rp.data[ti.i]['theta'] = thetarope rp.data[ti.i]['sm'] = (rp.Twl - Tg) / gl.W if rp.T > 0: rp.data[ti.i]['stretch'] = rp.data[ti.i - 1]['stretch'] + ( dr.omeg * dr.rdrum - vgw) * (t - ti.oldt) dr.data[ti.i]['v'] = dr.omeg * dr.rdrum dr.data[ti.i]['omegrel'] = omegrel dr.data[ti.i]['rdrum'] = dr.rdrum dr.data[ti.i]['Pdeliv'] = powerToDrum dr.data[ti.i]['Edeliv'] = dr.data[ti.i - 1]['Edeliv'] + dr.data[ ti.i]['Pdeliv'] * (t - ti.oldt) # integrate dr.data[ti.i]['torq'] = torqtcd en.data[ti.i]['torqTC'] = torqtce en.data[ti.i]['Pdeliv'] = powerToEngine # en.data[ti.i]['torq'] = # doesn't have much meaning on engine since we don't have a defined radius en.data[ti.i]['Edeliv'] = en.data[ti.i - 1]['Edeliv'] + en.data[ ti.i]['Pdeliv'] * (t - ti.oldt) # integrate dr.dotomeg = dotomegd en.dotomeg = dotomege # op.data[ti.i]['Sth'] = op.Sth ti.oldt = t # ---update things that don't affect stateDer gl.findState(t, ti, rp, pl) # Update controls pl.control(pr, t, ti, gl) op.control(pr, t, ti, gl, rp, dr, en) #don't print state variables or derivatives, use writeStatesFile, writeStateDersFile return [ dotx, dotxD, doty, dotyD, dottheta, dotthetaD, dotT, dotomegd, dotomege ]
def out_of_range_condition(t): b = (t - joint_positions['shoulder']).length c = (31/b)*(t - joint_positions['shoulder']) + joint_positions['shoulder'] # new_elbow joint_positions['elbow'] = c theta_shoulder = arcsin(joint_positions['shoulder'][1]/13.7) # theta_shoulder = 0 # new_elbow judgement theta3, theta_arm_oc = get_oc_angle() theta_arm_ud = get_ud_angle(theta3) if((deg(theta_arm_ud) > 32) or (deg(theta_arm_ud) < 0) or (deg(theta_arm_oc) > 30) or (deg(theta_arm_oc) < 0)): if(deg(theta_arm_ud) > 32): theta_arm_ud = rad(32) elif(deg(theta_arm_ud < 0)): theta_arm_ud = 0 if(deg(theta_arm_oc) > 30): theta_arm_oc = rad(30) elif(deg(theta_arm_oc) < 0): theta_arm_oc = 0 arr = get_elbow_position([theta_shoulder, theta_arm_ud, theta_arm_oc]) joint_positions['elbow']= vector(arr) c = joint_positions['elbow'] e = (t - c).length f = (26.1/e)*(t - c) + c # new_wrist joint_positions['wrist'] = f # new_wrist judgement theta_elbow = get_elbow_angle() theta_uturn = get_uturn_angle(theta_shoulder, theta_arm_ud, theta_arm_oc, theta_elbow) if ((deg(theta_uturn) > 90) or (deg(theta_uturn < 0))): if(deg(theta_uturn) > 90): theta_uturn = rad(90) else: theta_uturn = 0 arr = get_wrist_position([theta_shoulder, theta_arm_ud, theta_arm_oc, theta_uturn, theta_elbow]) f = vector(arr) joint_positions['wrist'] = f return(deg([theta_shoulder, theta_arm_ud, theta_arm_oc, theta_uturn, theta_elbow]))
def iteration(t,tolerance): iterations = 0 need_test = False if ((t - joint_positions['elbow']).length < 0.001): arr = get_elbow_position([0, 0.1, 0.1]) joint_positions['elbow'] = vector(arr) arr = get_wrist_position([0, 0.1, 0.1, 0.1, 1]) joint_positions['wrist'] = vector(arr) while((need_test) or ((joint_positions['wrist'] - t).length > tolerance)): # _______________________________________________________________________________________________ #________________________ Forward reaching, from target to reference_____________________________ # _______________________________________________________________________________________________ joint_positions['wrist'] = t len_share = 26.1 / (joint_positions['wrist'] - joint_positions['elbow']).length joint_positions['elbow'] = (1-len_share)*joint_positions['wrist'] + len_share*joint_positions['elbow'] len_share = 31 / (joint_positions['elbow'] - joint_positions['shoulder']).length joint_positions['shoulder'] = (1-len_share)*joint_positions['elbow'] + len_share*joint_positions['shoulder'] # ________________________________________________________________________________________________ # ____________________________Forward reaching ends here__________________________________________ # ________________________________________________________________________________________________ # ------------------------------------------------------------------------------------------------------------------------------- #_________________________________________________________________________________________________ #_________________________Backward reaching, from reference to target_____________________________ # ________________________________________________________________________________________________ len_share = 13.7 / (joint_positions['origin'] - joint_positions['shoulder']).length joint_positions['shoulder'] = (1-len_share)*joint_positions['origin'] + len_share*joint_positions['shoulder'] # ____________________________________________________________________________________________ # __________________test if shoulder is away from x-y plane___________________________________ # ____________________________________________________________________________________________ if(joint_positions['shoulder'][2] != 0): # rotate shoulder about y-axis, so that it stays in x-y plane rotation = np.arctan(joint_positions['shoulder'][2]/joint_positions['shoulder'][0]) x = joint_positions['shoulder'][0]*cos(rotation) + joint_positions['shoulder'][2]*sin(rotation) z = joint_positions['shoulder'][2]*cos(rotation) - joint_positions['shoulder'][0]*sin(rotation) y = joint_positions['shoulder'][1] joint_positions['shoulder'] = vector(x,y,z) theta_shoulder = arcsin(joint_positions['shoulder'][1]/13.7) # ____________________________________________________________________________________________ # __________________test if shoulder is out of the boundary___________________________________ # ____________________________________________________________________________________________ if((deg(theta_shoulder) > 9) or (deg(theta_shoulder) < 0)): if(deg(theta_shoulder) > 9): theta_shoulder = rad(9) elif(deg(theta_shoulder) < 0): theta_shoulder = rad(0) # rotate about z-axis, so that it stays within hardware limit x = 13.7*cos(theta_shoulder) y = 13.7*sin(theta_shoulder) joint_positions['shoulder'] = vector(x,y,0) # _______________________________________________________________________________________________ # ____________________________________Adjustment of shoulder ends here___________________________ # _______________________________________________________________________________________________ # -------------------------------------------------------------------------------------------------------------------------------- # _______________________________________________________________________________________________ # ____________________________________Starts adjustment of elbow_________________________________ # _______________________________________________________________________________________________ len_share = 31 / (joint_positions['shoulder'] - joint_positions['elbow']).length joint_positions['elbow'] = (1-len_share)*joint_positions['shoulder'] + len_share*joint_positions['elbow'] theta3, theta_arm_oc = get_oc_angle() theta_arm_ud = get_ud_angle(theta3) # _______________________________________________________________________________________________ # _________________________________Test if position of elbow is out of boundary__________________ # _______________________________________________________________________________________________ if((deg(theta_arm_ud) > 32) or (deg(theta_arm_ud) < 0) or (deg(theta_arm_oc) > 30) or (deg(theta_arm_oc) < 0)): if(deg(theta_arm_ud) > 32): theta_arm_ud = rad(32) elif(deg(theta_arm_ud < 0)): theta_arm_ud = 0 if(deg(theta_arm_oc) > 30): theta_arm_oc = rad(30) elif(deg(theta_arm_oc) < 0): theta_arm_oc = 0 arr = get_elbow_position([theta_shoulder, theta_arm_ud, theta_arm_oc]) joint_positions['elbow'] = vector(arr) # _______________________________________________________________________________________________ # _________________________________Adjustment of elbow ends here_________________________________ # _______________________________________________________________________________________________ # _________________________________Starts adjustment of wrist____________________________________ # _______________________________________________________________________________________________ len_share = 26.1 / (joint_positions['elbow'] - joint_positions['wrist']).length joint_positions['wrist'] = (1-len_share)*joint_positions['elbow'] + len_share*joint_positions['wrist'] theta_elbow = get_elbow_angle() theta_uturn = get_uturn_angle(theta_shoulder, theta_arm_ud, theta_arm_oc, theta_elbow) need_test = False # _______________________________________________________________________________________________ # ________________________________Test if wrist is out of boundary_______________________________ # _______________________________________________________________________________________________ if(deg(theta_uturn)<0 and abs(deg(theta_uturn))>0.00001): V = joint_positions['elbow'] - joint_positions['wrist'] k = joint_positions['shoulder'] - joint_positions['elbow'] k = k/(k.length) Vrot = V*cos(-theta_uturn) + (k.cross(V))*sin(-theta_uturn) + k*(k.dot(V))*(1-cos(-theta_uturn)) joint_positions['elbow'] = joint_positions['wrist'] + Vrot need_test = True if(deg(theta_uturn)>90): theta_uturn = np.pi/2 theta_arm_ud = theta_arm_ud - rad(1) iterations += 1 if(iterations > 100): print('Target is unreachable (iterations > 100)') return(deg([theta_shoulder, theta_arm_ud, theta_arm_oc, theta_uturn, theta_elbow])) print('Iterations = ',iterations) return(deg([theta_shoulder, theta_arm_ud, theta_arm_oc, theta_uturn, theta_elbow]))
def plotsSI(path, preppedData, pr, gl, ai, rp, dr, tc, en, op, pl): showPlot = pr['SIPlotsShow'] save = pr['SIPlotsSave'] figures = [] g = 9.8 [t, x, y, xD, yD, v, vD, alpha, theta, thetaD, gamma, elev, Sth, omegd, omege, L, D, T, Tg, vgw, \ torqWing,torqStab, Me, Few, engP, omegrel, rdrum, tctorqueDrum, winP, ropP, gliP, gndTorq, ropeTheta, ropeTorq, \ smRope, smStall, smStruct, smRecov, vGust, gData, dData, oData, pData, eData, rData, aData, tData] = preppedData iColor = 0 # counter for plots, so each variable has a different color # plot engine power and torque curves from model parameters figures.append( xy(False, showPlot, save, path, iColor, [t], [oData['err'], oData['derr'], oData['interr']], 't (sec)', 'error quantities', ['err', 'derr', 'interr'], 'Errors operator')) figures.append( xy(False, showPlot, save, path, iColor, [t], [pData['err'], pData['derr'], pData['interr']], 't (sec)', 'error quantities', ['err', 'derr', 'interr'], 'Errors pilot')) if pr['plotPowerTorque']: omegeng = linspace(0, 1.1 * en.omegapeakP, 100) powr = linspace(0, 1.1 * en.omegapeakP, 100) torq = linspace(0, 1.1 * en.omegapeakP, 100) rpm = omegeng * 60 / 2.0 / pi for i, omegar in enumerate(omegeng): powr[i] = en.Pavail(omegar) / 1000 torq[i] = en.torqAvail(omegar) figures.append( xy(False, showPlot, save, path, iColor, [rpm], [powr, torq], 'Engine speed (rpm)', 'Power (kW), Torque(Nm)', ['Pistons power', 'Pistons torque'], 'Engine curves')) if pr['plotLift']: ##plot lift curve vs alpha at v_best alphaList = linspace(-20, 80, 100) lift = array([gl.Lnl(gl.vb, rad(alph)) for alph in alphaList]) figures.append(xy(False, showPlot, save, path, iColor, [alphaList], [lift / gl.W], \ 'Angle of attack (deg)', 'Lift/Weight', [''], 'Lift vs angle of attack')) alphaList = linspace(-4, pr['alphaStallVsWing'], 100) drag = array([gl.coeffDrag(rad(alph)) for alph in alphaList]) figures.append(xy(False, showPlot, save, path, iColor, [alphaList], [drag], \ 'Angle of attack (deg)', 'Drag coefficient', [''], 'Drag vs angle of attack')) if pr['plotTorqCov']: vrelList = linspace(0, 1.5, 100) tcGearingList = array([tc.torqMult(vrel) for vrel in vrelList]) # tcEfficiencyList = array([vrel * tc.torqMult(vrel) for vrel in vrelList]) tcInvKform = array([tc.invKform(vrel) for vrel in vrelList]) figures.append(xy(False, showPlot, save, path, iColor, [vrelList], \ [tcGearingList, tcInvKform], 'vDrum/vEngine', '' ,['torque factor','inverse capacity form'], 'Torque converter')) # glider position vs time figures.append( xy(False, showPlot, save, path, iColor, [t], [x, y], 'time (sec)', 'position (m)', ['x', 'y'], 'Glider position vs time')) figures.append( xy(False, showPlot, save, path, iColor, [x], [y], 'x (m)', 'y (m)', [''], 'Glider y vs x')) # glider speed and angles figures.append(xy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t], [xD, yD, v, deg(alpha), deg(theta), deg(gamma), deg(elev), deg(thetaD)], \ 'time (sec)', 'Velocity (m/s), Angles (deg)', ['vx', 'vy', 'v', 'angle of attack', 'pitch', 'climb', 'elevator', 'pitch rate (deg/sec)'], 'Glider velocities and angles')) # iColor = 0 #restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t, t, t], [v, rData['stretch'], dr.rdrum * omegd, y / rp.lo, Tg / gl.W, L / gl.W, divide(L, D), deg(alpha), deg(gamma), deg(thetaD)], \ [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 'time (sec)', ['Velocity (m/s), stretch (m), Angles (deg), L/D', 'Relative forces and height'], ['v (glider)', 'stretch', r'$v_r$ (rope)', \ 'height/' + r'$\l_o $', 'T/W at glider', 'L/W', 'L/D', 'angle of attack', 'climb angle', 'rot. rate (deg/sec)'], 'Glider and rope')) # Forces figures.append(xy(False, showPlot, save, path, iColor, [t, t, t, t, t], [L / gl.W, D / gl.W, T / gl.W, Tg / gl.W, Few / gl.W], \ 'time (sec)', 'Forces/Weight', ['lift', 'drag', 'tension at drum', 'tension at glider', 'tc-drum'], 'Forces')) # torques figures.append( xy(False, showPlot, save, path, iColor, [t], [ropeTorq, torqWing + torqStab, Me, gndTorq], 'time (sec)', 'Torque (Nm)', ['rope', 'stabilizer+wing', 'elevator', 'ground'], 'Torques on glider')) figures.append( xy(False, showPlot, save, path, iColor, [t], [torqWing, torqStab], 'time (sec)', 'Torque (Nm)', ['wing', 'stabilizer'], 'Torques wing and stabilizer')) # Engine, rope and drum figures.append(xy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t], [multiply(omege,rdrum)/dr.gear/dr.diff, multiply(omegd,rdrum), \ vgw, deg(ropeTheta), tctorqueDrum/10, -multiply(T,rdrum)/10, 100 * Sth], 'time (sec)', 'Speeds (effective: m/s), Torque/100 (Nm) Angle (deg), Throttle %', ['engine speed', 'rope speed', 'glider radial speed', 'rope angle', 'TC torque on drum', 'Rope torque on drum','throttle'], 'Engine, drum and rope')) figures.append(xy(False, showPlot, save, path, iColor, [t], [omege * 60 / 2 / pi/10, engP/1000, engP/(omege + 1e-6), tctorqueDrum / dr.gear / dr.diff, 10 * 100 * omegrel, \ 10 * 100 * Sth], \ 'time (sec)', 'Speeds (rpm,m/s), Power (KW)Torque (Nm), Throttlex10 %', ['eng rpm/10', 'engine power', 'engine torque','TC torque out', 'TC speed vs engine % x10', 'throttle % x10'], 'Engine')) figures.append( xy(False, showPlot, save, path, iColor, [t], [ eData['Edeliv'] / 1e6, dData['Edeliv'] / 1e6, rData['Edeliv'] / 1e6, gData['Edeliv'] / 1e6, gData['Emech'] / 1e6 ], 'time (sec)', 'Energy (MJ)', ['to engine', 'to drum', 'to rope', 'to glider', 'in glider'], 'Energy delivered and kept')) figures.append( xy(False, showPlot, save, path, iColor, [t], [engP / en.Pmax, winP / en.Pmax, ropP / en.Pmax, gliP / en.Pmax], 'time (sec)', 'Power/Pmax', ['to engine', 'to drum', 'to rope', 'to glider'], 'Power delivered')) # zoom in on a time range same plot as above # Specialty plots for presentations # zoom = True # if zoom: # t1 = 6 ; t2 = 17 # figures.append(xyy(False, showPlot, save, path, iColor,[t,t,t,t,t,t,t,t,t,t,t],[1.94*v,1.94*omegd,y/0.305/10,Tg/gl.W,L/gl.W,10*deg(alpha),10*deg(gData['alphaStall']),deg(gamma),10*deg(elev),Sth,omege/dr.rdrum*60/2/pi*dr.diff*dr.gear/100],\ # [0,0,0,1,1,0,0,0,0,1,0],'time (sec)',['Velocity (kts), Height/10 (ft), Angle (deg)','Relative forces'],\ # ['v (glider)',r'$v_r$ (rope)','height/10','T/W', 'L/W', 'angle of attack','stall angle','climb angle','elev deflection','throttle','rpm/100'],'Glider and engine expanded',t1,t2) # iColor = 0 #restart color cycle # figures.append(xyy(False, showPlot, save, path, iColor,[t,t,t,t,t,t,t,t],[1.94*v,y/0.305,deg(gamma),L/gl.W,smStruct,smStall,smRope,smRecov/0.305],\ # [0,0,0,1,1,1,1,0],'time (sec)',['Velocity (kts), Height (ft), Angle (deg)',"Relative forces"],\ # ['v','height','Climb angle','L/W','Struct margin','Stall margin','Rope margin','Recovery margin'],'Glider and safety margins',t1,t2) # iColor = 0 #restart color cycle # figures.append(xyy(False, showPlot, save, path, iColor,[t,t,t,t,t,t,t,t,t,t,t],[1.94*v,1.94*omegd,y/0.305/10,Tg/gl.W,L/gl.W,10*deg(alpha),10*deg(gData['alphaStall']),deg(gamma),10*deg(elev),Sth,omege/dr.rdrum*60/2/pi*dr.diff*dr.gear/100],\ # [0,0,0,1,1,0,0,0,0,1,0],'time (sec)',['Velocity (kts), Height/10 (ft), Angle (deg)','Relative forces'],\ # ['v (glider)',r'$v_r$ (rope)','height/10','T/W', 'L/W', 'angle of attack','stall angle','climb angle','elev deflection','throttle','rpm/100'],'Glider and engine') # iColor = 0 #restart color cycle # figures.append(xyy(True,[t,t,t,t,t,t,t,t],[1.94*v,y/0.305/10,deg(gamma),L/gl.W,smStruct,smStall,smRope,smRecov/0.305/10],\ # [0,0,0,1,1,1,1,0],'time (sec)',['Velocity (kts), Height (ft), Angle (deg)',"Relative forces"],\ # ['v','height/10','climb angle','L/W','Struct margin','Stall margin','Rope margin','Recovery margin'],'Glider and safety margins') # Imperial units: # if vGustPeak > 0 and ymax > hGust: # figures.append(xyy(False, showPlot, save, path, iColor,[t,t,t,t,t,t,t,t,t],[1.94*v,y/0.305,deg(gamma),L/gl.W,smStruct,smStall,smRope,smRecov/0.305, 1.94*vGust*10],\ # [0,0,0,1,1,1,1,0,0],'time (sec)',['Velocity (kts), Height (ft), Angle (deg)',"Relative forces"],\ # ['velocity','height','climb angle','L/W','struct margin','stall margin','rope margin','recovery margin','vel gust'],'Glider and safety margins') # else: # figures.append(xyy(False, showPlot, save, path, iColor,[t,t,t,t,t,t,t,t],[1.94*v,y/0.305,deg(gamma),L/gl.W,smStruct,smStall,smRope,smRecov/0.305],\ # [0,0,0,1,1,1,1,0],'time (sec)',['Velocity (kts), Height (ft), Angle (deg)',"Relative forces"],\ # ['velocity','height','climb angle','L/W','struct margin','stall margin','rope margin','recovery margin'],'Glider and safety margins') zoom = pr['zoom'] if zoom: # if not ai.startGust is None and 's' in ai.startGust: # t1 = float(ai.startGust.split()[0])-0.5 # t2 = t1 + 2*ai.widthGust/25.0 + 2.0 -1.5 [t1, t2] = zoom if ai.vGustPeak > 0 and not ai.startGust is None: # without safety margins iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, T / gl.W, vGust], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W', 'vel gust'], 'Winch launch')) if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, T / gl.W, vGust], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W', 'vel gust'], 'Winch launch expanded', t1, t2)) # with safety margins (T/W is redundant) iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, smStruct, smStall, smRope, smRecov, vGust], \ [0, 0, 0, 1, 1, 1, 1, 0, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin', 'vel gust'], 'Winch launch and safety margins')) if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, smStruct, smStall, smRope, smRecov, vGust], \ [0, 0, 0, 1, 1, 1, 1, 0, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin', 'vel gust'], 'Winch launch and safety margins expanded', t1, t2)) else: # without gusts # without safety margins if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, T / gl.W], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W'], 'Winch launch expanded', t1, t2)) iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, T / gl.W], \ [0, 0, 0, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'T/W'], 'Winch launch')) # with safety margins if zoom: iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, smStruct, smStall, smRope, smRecov], \ [0, 0, 0, 1, 1, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Winch launch and safety margins expanded', t1, t2)) iColor = 0 # restart color cycle figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t, t, t, t, t], [v, y/10.0, deg(gamma), L / gl.W, smStruct, smStall, smRope, smRecov], \ [0, 0, 0, 1, 1, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height/10 (m), Angle (deg)', "Relative forces"], \ ['velocity', 'height', 'climb angle', 'L/W', 'struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Winch launch and safety margins')) # safety margins alone if zoom: iColor = 6 # choose color cycle start figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t], [smStruct, smStall, smRope, smRecov], \ [1, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height (m), Angle (deg)', "Relative forces"], \ ['struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Safety margins expanded', t1, t2)) iColor = 6 # choose color cycle start figures.append(xyy(False, showPlot, save, path, iColor, [t, t, t, t], [smStruct, smStall, smRope, smRecov], \ [1, 1, 1, 0], 'time (sec)', ['Velocity (m/s), Height (m), Angle (deg)', "Relative forces"], \ ['struct margin', 'stall margin', 'rope margin', 'recovery margin'], 'Safety margins')) return figures
def coeffDrag(self,alpha): return self.CD[0] + self.CD[1] * deg(alpha) + self.CD[2] * deg(alpha) ** 2 + self.CD[3] * deg(alpha) ** 3
def wobj_error_x(self): if (self.parser.yaml_wobj is None): return numpy.NaN acos_val = acos( normalize(self.wobj_ori_x).dot(self.parser.yaml_wobj_ori_x)) return deg(acos_val)