Package aerocalc :: Module ssec
[frames] | no frames]

Source Code for Module aerocalc.ssec

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  3   
  4  # ############################################################################# 
  5  # Copyright (c) 2008, Kevin Horton 
  6  # All rights reserved. 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are met: 
  9  # * 
 10  #     * Redistributions of source code must retain the above copyright 
 11  #       notice, this list of conditions and the following disclaimer. 
 12  #     * Redistributions in binary form must reproduce the above copyright 
 13  #       notice, this list of conditions and the following disclaimer in the 
 14  #       documentation and/or other materials provided with the distribution. 
 15  #     * The name of Kevin Horton may not be used to endorse or promote products 
 16  #       derived from this software without specific prior written permission. 
 17  # * 
 18  # THIS SOFTWARE IS PROVIDED BY KEVIN HORTON ``AS IS'' AND ANY EXPRESS OR 
 19  # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 20  # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 
 21  # EVENT SHALL KEVIN HORTON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 22  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 23  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 24  # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 25  # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 26  # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 27  # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 28  # ############################################################################# 
 29  # 
 30  # version 0.10, 25 Apr 2008 
 31  # 
 32  # Version History: 
 33  # vers     date     Notes 
 34  # 0.10   25 Apr 08  First public release.  
 35  # ############################################################################# 
 36   
 37  """ 
 38  Various functions related to static source error correction. 
 39  """ 
 40   
 41  import airspeed as A 
 42  import math as M 
 43  import std_atm as SA 
 44  import unit_conversion as U 
 45   
 46  ############################################################################## 
 47  # 
 48  # TAS from GPS data. 
 49  # 
 50  ############################################################################## 
51 -def gps2tas(GS, TK, verbose = 0):
52 """ 53 Returns true airspeed, given GPS groundspeed and track on at least 54 three legs (four legs preferred). Uses the method developed by Doug 55 Gray - http://www.kilohotel.com/rv8/rvlinks/doug_gray/TAS_FNL4.pdf 56 57 GS and TK are lists of ground speed and track data. 58 59 Three legs: 60 If verbose = 0, then only TAS is returned. 61 If verbose = 1, then TAS, wind speed and direction are returned. 62 If verbose = 2, then TAS, wind speed and direction and the heading 63 for each leg are returned. The wind speed and direction is 64 returned as a tuple, and the headings are returned as a tuple 65 66 67 Four legs: 68 Data from only three legs is sufficient to calculate TAS. If data 69 four legs is entered, four different calculations are conducted, 70 using a different mix of three data points for each calculation. 71 If the data quality is high, the TAS and wind for all four 72 calculations will be similar. The standard deviation on the TAS is 73 calculated - good quality data will have a standard deviation of 74 less than 1 kt. 75 76 If verbose = 0, then only TAS is returned. 77 If verbose = 1, then TAS and its standard deviation are returned. 78 If verbose = 2, then TAS, its standard deviation and the four wind 79 speeds and directions are returned (the winds are returned as a list 80 of four tuples) 81 82 Validated against sample data in four leg tab of NTPS GPS PEC spreadsheet: 83 http://www.ntps.edu/Files/GPS%20PEC.XLS 84 85 Examples: 86 87 Data for all examples: 88 >>> gs = [178, 185, 188, 184] 89 >>> tk = [178, 82, 355, 265] 90 91 Determine the TAS, given the above data from four runs: 92 >>> gps2tas(gs, tk) 93 183.72669557114619 94 95 Determine the TAS and standard deviation from the four calculations: 96 >>> gps2tas(gs, tk, verbose = 1) 97 (183.72669557114619, 0.82709634705928436) 98 99 Determine the TAS, standard deviation, and wind speed and direction 100 for each calculation: 101 >>> gps2tas(gs, tk, verbose = 2) 102 (183.72669557114619, 0.82709634705928436, ((5.2608369270843056, 194.51673740323213), (3.5823966532035927, 181.52174627838372), (5.1495218164839995, 162.69803415599802), (6.4436728241320145, 177.94783081049718))) 103 104 """ 105 # confirm GS and TK are valid lengths: 106 if 2 < len(GS) < 5: 107 pass 108 else: 109 raise ValueError, 'GS must be a list of three or four items' 110 111 if 2 < len(TK) < 5: 112 pass 113 else: 114 raise ValueError, 'TK must be a list of three or four items' 115 116 if len(GS) != len(TK): 117 raise ValueError, 'The ground speed and track arrays must have the same number of elements.' 118 119 if len(GS) == 3: 120 result = gps2tas3(GS, TK, verbose) 121 return result 122 else: 123 gs_data_sets, tk_data_sets, results = [], [], [] 124 125 gs_data_sets.append([GS[0], GS[1], GS[2]]) 126 gs_data_sets.append([GS[1], GS[2], GS[3]]) 127 gs_data_sets.append([GS[2], GS[3], GS[0]]) 128 gs_data_sets.append([GS[3], GS[0], GS[1]]) 129 130 tk_data_sets.append([TK[0], TK[1], TK[2]]) 131 tk_data_sets.append([TK[1], TK[2], TK[3]]) 132 tk_data_sets.append([TK[2], TK[3], TK[0]]) 133 tk_data_sets.append([TK[3], TK[0], TK[1]]) 134 135 for (gs, tk) in zip (gs_data_sets, tk_data_sets): 136 results.append(gps2tas3(gs, tk, 2)) 137 138 ave_TAS = 0 139 ave_wind_x = 0 140 ave_wind_y = 0 141 sum2_TAS = 0 142 143 for item in results: 144 ave_TAS +=item[0] 145 sum2_TAS += item[0] ** 2 146 ave_wind_x += item[1][0] * M.sin(M.pi * item[1][1] / 180.) 147 ave_wind_y += item[1][0] * M.cos(M.pi * item[1][1] / 180.) 148 149 ave_TAS /= 4. 150 std_dev_TAS = M.sqrt((sum2_TAS - 4 * ave_TAS ** 2) / 3) 151 ave_wind_x /= 4 152 ave_wind_y /= 4. 153 ave_wind_speed = M.sqrt(ave_wind_x ** 2 + ave_wind_y ** 2) 154 ave_wind_dir = (720. - (180. / M.pi * M.atan2(ave_wind_x, ave_wind_y))) % 360 155 # return results 156 157 if verbose == 0: 158 return ave_TAS 159 elif verbose == 1: 160 return ave_TAS, std_dev_TAS 161 elif verbose == 2: 162 return ave_TAS, std_dev_TAS, ((results[0][1][0], results[0][1][1]),(results[1][1][0], results[1][1][1]),(results[2][1][0], results[2][1][1]),(results[3][1][0], results[3][1][1])) 163 else: 164 raise ValueError, 'The value of verbose must be equal to 0, 1 or 2'
165 166
167 -def gps2tas3(GS, TK, verbose=0):
168 """ 169 Returns true airspeed, given GPS groundspeed and track on three legs. 170 Uses the method developed by Doug Gray: 171 http://www.kilohotel.com/rv8/rvlinks/doug_gray/TAS_FNL4.pdf 172 173 GS and TK are arrays of ground speed and track data. 174 175 If verbose = 0, then only TAS is returned. 176 If verbose = 1, then TAS, wind speed and wind direction are returned. 177 If verbose = 2, then TAS, wind speed and direction and the heading for 178 each leg are returned. The wind speed and direction is returned as a 179 tuple, and the headings are returned as a tuple 180 181 Validated against sample in Doug Gray's paper. 182 183 Examples: 184 185 """ 186 x, y, b, m, hdg = [], [], [], [], [] 187 188 for (gs, tk) in zip(GS, TK): 189 x.append(gs * M.sin(M.pi * (360. - tk) / 180.)) 190 y.append(gs * M.cos(M.pi * (360. - tk) / 180.)) 191 192 m.append(-1 * (x[1] - x[0]) / (y[1] - y[0])) 193 m.append(-1 * (x[2] - x[0]) / (y[2] - y[0])) 194 195 b.append((y[0] + y[1]) / 2 - m[0] * (x[0] + x[1]) / 2) 196 b.append((y[0] + y[2]) / 2 - m[1] * (x[0] + x[2]) / 2) 197 198 wind_x = (b[0] - b[1]) / (m[1] - m[0]) 199 wind_y = m[0] * wind_x + b[0] 200 201 wind_speed = M.sqrt(wind_x ** 2 + wind_y ** 2) 202 wind_dir = (540. - (180. / M.pi * M.atan2(wind_x, wind_y))) % 360. 203 204 TAS = M.sqrt((x[0] - wind_x) ** 2 + (y[0] - wind_y) ** 2) 205 206 if verbose >= 2: 207 hdg.append((540. - (180. / M.pi * M.atan2(wind_x - x[0], wind_y - y[0]))) % 360.) 208 hdg.append((540. - (180. / M.pi * M.atan2(wind_x - x[1], wind_y - y[1]))) % 360.) 209 hdg.append((540. - (180. / M.pi * M.atan2(wind_x - x[2], wind_y - y[2]))) % 360.) 210 211 return TAS, (wind_speed, wind_dir), (hdg[0], hdg[1], hdg[2]) 212 213 elif verbose == 1: 214 return TAS, (wind_speed, wind_dir) 215 elif verbose == 0: 216 return TAS 217 else: 218 raise ValueError, 'The value of verbose must be equal to 0, 1 or 2'
219 220
221 -def main():
222 pass
223 224 225 if __name__ == '__main__': 226 main() 227