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

Source Code for Module aerocalc.airspeed

   1  #!/usr/bin/python 
   2  # -*- coding: 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.27, 16 May 2007 
  31  # 
  32  # Version History: 
  33  # vers     date      Notes 
  34  # 0.21   10 June 06  Started to add interactive mode 
  35  # 0.22   10 July 06  Error correction in some default units 
  36  # 0.23   07 Jan 07   Added several more interactive functions 
  37  # 0.24   05 May 07   Reworked to use default units from default_units module. 
  38  # 0.25   06 May 07   Added several more interactive functions 
  39  # 0.26   12 May 07   Reworked the interactive mode to move common idioms to 
  40  #                    functions 
  41  # 0.27   16 May 07   Reworked to respect default units, to stay open after 
  42  #                    running, and to save results between functions. 
  43  # ############################################################################# 
  44  # 
  45  # To Do:  1. Add functions: 
  46  # 
  47  #         2. Extend the following functions to work at M > 1 and CAS > 661.48: 
  48  #             dp_over_p2mach 
  49  #             dp2eas 
  50  #             dp2tas 
  51  #             eas2dp 
  52  #             tas2dp 
  53  # 
  54  #         3. Test the following functions: 
  55  #             cas2eas 
  56  #             eas2cas 
  57  #             cas_mach2alt 
  58  #             cas_alt2mach 
  59  #             mach_alt2cas 
  60  #             mach2tas # errors? 
  61  #             tas2mach # errors? 
  62  # 
  63  #         4. Add examples to all functions. 
  64  # 
  65  #         5. Add tests for all functions. 
  66  # 
  67  #         6. Check superconic versions of cas to mach and mach to cas equations 
  68  #            from TPS notes 
  69  # 
  70  #         7. Done. 
  71  # 
  72  #         8. Done. 
  73  # 
  74  # 
  75  # Done    7. Rework the interactive functions to respect the default units. 
  76  # 
  77  #         8. Rework interactive functions to share data between runs. 
  78   
  79  # ############################################################################# 
  80  # % coverage.py -r -m ../airspeed.py 
  81  # Name          Stmts   Exec  Cover   Missing 
  82  # ------------------------------------------- 
  83  # ../airspeed     422     52    12%   98-109, 112, 115-117, 122-127, 156-198, 207, 217, 221, 223, 226, 231-278, 310, 315-316, 346-365, 370-404, 435-436, 440-444, 479-521, 530-600, 603-634, 660-664, 674-704, 707-722, 750-889, 891-892, 903-904, 931, 945-989, 998-1050, 1053-1209, 1231-1299, 1360-1362, 1368-1389, 1395, 1398, 1400-1401, 1411-1503, 1513-1530, 1562-1604 
  84  """ 
  85  Perform various air speed conversions. 
  86   
  87  Convert between Indicated Air Speed (IAS), Calibrated Air Speed (CAS),  
  88  Equivalent Air Speed (EAS), True Air Speed (TAS) and mach number. 
  89   
  90  Convert between pitot static system pressures and air speed. 
  91   
  92  Provide interactive airspeed conversions when script is run directly, e.g.  
  93  'python airspeed.py'. 
  94   
  95  """ 
  96   
  97  import math as M 
  98  import std_atm as SA 
  99   
 100  try: 
 101      from default_units import * 
 102  except ImportError: 
 103      default_area_units = 'ft**2' 
 104      default_power_units = 'hp' 
 105      default_speed_units = 'kt' 
 106      default_temp_units = 'C' 
 107      default_weight_units = 'lb' 
 108      default_press_units = 'in HG' 
 109      default_density_units = 'lb/ft**3' 
 110      default_length_units = 'ft' 
 111      default_alt_units = default_length_units 
 112      default_avgas_units = 'lb' 
 113   
 114  import unit_conversion as U 
 115  import val_input as VI 
 116   
 117  Rho0 = SA.Rho0  # Density at sea level, kg/m**3 
 118  P0 = 101325.0  # Pressure at sea level, pa 
 119   
 120  # speed of sound from http://www.edwards.af.mil/sharing/tech_pubs/Handbook-10%20March02.pdf 
 121   
 122  A0 = 340.2941  # speed of sound at sea level, std day, m/s 
 123   
 124  # F calculated by manipulating NASA RP 1046 pg 17 
 125  # F is used in some of the supersonic solution equations. 
 126   
 127  F = (1.25 ** 2.5 * (2.4 ** 2.) ** 2.5) * 1.2 
 128   
 129  # ############################################################################# 
 130  # 
 131  # delta pressure to speed 
 132  # 
 133  #    delta pressure to CAS 
 134  # 
 135  #    delta pressure and altitude to EAS 
 136  # 
 137  #    delta pressure, altitude and temperature to TAS 
 138  # 
 139  # ############################################################################# 
 140   
 141   
142 -def _dp2speed( 143 dp, 144 Pref, 145 Rhoref, 146 press_units=default_press_units, 147 speed_units=default_speed_units, 148 ):
149 150 dp = U.press_conv(dp, from_units=press_units, to_units='pa') 151 speed = M.sqrt(((7. * Pref) * (1. / Rhoref)) * ((dp / Pref + 1.) 152 ** (2. / 7.) - 1.)) 153 154 # check to confirm the speed is less than 661.48 kt 155 156 speed_kt = U.speed_conv(speed, from_units='m/s', to_units='kt') 157 if speed_kt > 661.48: 158 raise ValueError, \ 159 'The function _dp2speed only works if the speed is less than or equal to 661.48 kt' 160 speed = U.speed_conv(speed, from_units='m/s', to_units=speed_units) 161 162 return speed
163 164
165 -def dp2cas(dp, press_units=default_press_units, 166 speed_units=default_speed_units):
167 """ 168 Return the CAS for a given differential pressure (the difference 169 between the pitot and static pressures). 170 171 The pressure units may be in inches of HG, mm of HG, psi, lb/ft^2, 172 hpa and mb. The units are specified as: 'in HG', 'mm HG', 'psi', 173 'lb/in**2', 'psf', 'lb/ft**2 'hpa', 'mb' or 'pa'. 174 175 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 176 177 If the units are not specified, the units in default_units.py are used. 178 179 Examples: 180 181 Determine the CAS in kt that is equivalent to a differential pressure 182 of 15 in HG: 183 >>> dp2cas(15) 184 518.96637566127652 185 186 Determine the CAS in mph that is equivalent to a differential pressure 187 of 0.2 psi: 188 >>> dp2cas(.2, press_units = 'psi', speed_units = 'mph') 189 105.88275188221526 190 """ 191 192 try: 193 194 # subsonic case 195 196 cas = _dp2speed(dp, P0, Rho0, press_units, speed_units) 197 return cas 198 except ValueError: 199 200 # supersonic case - need to iterate a solution. Set upper and lower 201 # guesses, and iterate until we zero in on a cas that produces the 202 # desired differential pressure. 203 204 dp_seek = U.press_conv(dp, from_units=press_units, to_units='pa' 205 ) 206 207 low = 340 # initial lower guess, m/s 208 209 # This function works up to approximately 6,600 kt CAS. The upper 210 # limit can be extended by increasing the value of the initial upper 211 # guess ("high"). 212 213 high = 3400 # initial upper guess, m/s 214 215 # confirm initial low and high are OK: 216 217 dp_low = _super_cas2dp(low) 218 if dp_low > dp_seek: 219 raise ValueError, 'Initial lower cas guess is too high.' 220 221 dp_high = _super_cas2dp(high) 222 if dp_high < dp_seek: 223 raise ValueError, 'Initial upper cas guess is too low.' 224 225 guess = (low + high) / 2. 226 dp_guess = _super_cas2dp(guess) 227 228 # keep iterating until dp is within 0.001% of desired value 229 230 while M.fabs(dp_guess - dp_seek) / dp_seek > 1e-5: 231 if dp_guess > dp_seek: 232 high = guess 233 else: 234 low = guess 235 236 guess = (low + high) / 2. 237 dp_guess = _super_cas2dp(guess) 238 239 # the supersonic solution is in m/s, so we need to convert to the 240 # desired units. 241 242 cas = U.speed_conv(guess, from_units='m/s', to_units=speed_units) 243 244 # Supersonic case. The subsonic case is returned way up at the top, 245 # inside the try statement. 246 247 return cas
248 249
250 -def dp2eas( 251 dp, 252 altitude, 253 press_units=default_press_units, 254 speed_units=default_speed_units, 255 alt_units=default_alt_units, 256 ):
257 """ 258 Return the EAS for a given differential pressure (the difference 259 between the pitot and static pressures) and altitude. 260 261 The pressure units may be in inches of HG, mm of HG, psi, lb/ft^2, 262 hpa and mb. The units are specified as: 'in HG', 'mm HG', 'psi', 263 'lb/in**2', 'psf', 'lb/ft**2 'hpa', 'mb' or 'pa'. 264 265 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 266 267 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 268 statute miles, ('sm') or nautical miles ('nm'). 269 270 If the units are not specified, the units in default_units.py are used. 271 272 This first version only works for EAS < 661.48 kt. 273 """ 274 275 P = SA.alt2press(altitude, alt_units, press_units='pa') 276 277 eas = _dp2speed(dp, P, Rho0, press_units, speed_units) 278 return eas
279 280
281 -def dp2tas( 282 dp, 283 altitude, 284 temp, 285 press_units=default_press_units, 286 speed_units=default_speed_units, 287 alt_units=default_alt_units, 288 temp_units=default_temp_units, 289 ):
290 """ 291 Return the TAS for a given differential pressure (the difference 292 between the pitot and static pressures) and altitude. 293 294 The pressure units may be in inches of HG, mm of HG, psi, lb/ft^2, 295 hpa and mb. The units are specified as: 'in HG', 'mm HG', 'psi', 296 'lb/in**2', 'psf', 'lb/ft**2 'hpa', 'mb' or 'pa'. 297 298 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 299 300 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 301 statute miles, ('sm') or nautical miles ('nm'). 302 303 The temperature may be in deg C, F, K or R. 304 305 If the units are not specified, the units in default_units.py are used. 306 307 This first version only works for TAS < 661.48 kt. 308 """ 309 310 P = SA.alt2press(altitude, alt_units, press_units='pa') 311 312 press_ratio = SA.alt2press_ratio(altitude, alt_units) 313 temp_ratio = U.temp_conv(temp, from_units=temp_units, to_units='K')\ 314 / 288.15 315 density_ratio = press_ratio / temp_ratio 316 Rho = Rho0 * density_ratio 317 318 tas = _dp2speed(dp, P, Rho, press_units, speed_units) 319 return tas
320 321 322 # ############################################################################# 323 # 324 # speed to delta pressure 325 # 326 # CAS to delta pressure 327 # 328 # EAS and altitude to delta pressure 329 # 330 # TAS, altitude and temperature to delta pressure 331 # 332 # ############################################################################# 333 334
335 -def _speed2dp( 336 speed, 337 Pref, 338 Rhoref, 339 press_units=default_press_units, 340 speed_units=default_speed_units, 341 ):
342 """ Return a delta pressure (the difference between the pitot and 343 static pressures) for a given speed. Subsonic equation. 344 """ 345 346 speed = U.speed_conv(speed, from_units=speed_units, to_units='m/s') 347 dp = Pref * (((Rhoref * speed ** 2.) / (7. * Pref) + 1.) ** 3.5 348 - 1.) 349 dp = U.press_conv(dp, from_units='pa', to_units=press_units) 350 351 return dp
352 353
354 -def _super_cas2dp(mcas):
355 """Return the differential pressure (difference between pitot and static 356 pressures) for a given CAS. 357 358 This function only works for speed in m/s, and pressure in pa. 359 360 This function is only intended for CAS > 661.48 kt. 361 """ 362 363 dp_over_P0 = (F * (mcas / A0) ** 7.) / (7. * (mcas / A0) ** 2. - 1.)\ 364 ** 2.5 - 1. 365 dp = dp_over_P0 * P0 366 367 return dp
368 369
370 -def cas2dp(cas, speed_units=default_speed_units, 371 press_units=default_press_units):
372 """ 373 Return the differential pressure (difference between pitot and static 374 pressures) for a given CAS. 375 376 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 377 378 The pressure units may be in inches of HG, mm of HG, psi, lb/ft^2, 379 hpa and mb. The units are specified as: 'in HG', 'mm HG', 'psi', 380 'lb/in**2', 'psf', 'lb/ft**2 'hpa', 'mb' or 'pa'. 381 382 If the units are not specified, the units in default_units.py are used. 383 """ 384 385 # check to confirm the speed is less than 661.48 kt 386 # kcas = U.speed_conv(cas, from_units = speed_units, to_units = 'kt') 387 388 mcas = U.speed_conv(cas, from_units=speed_units, to_units='m/s') 389 390 # if kcas > 661.48: 391 392 if mcas > A0: 393 394 # supersonic case 395 396 dp = _super_cas2dp(mcas) 397 dp = U.press_conv(dp, from_units='pa', to_units=press_units) 398 else: 399 400 # subsonic case 401 402 dp = _speed2dp(cas, P0, Rho0, press_units=press_units, 403 speed_units=speed_units) 404 return dp
405 406
407 -def eas2dp( 408 eas, 409 altitude, 410 speed_units=default_speed_units, 411 alt_units=default_alt_units, 412 press_units=default_press_units, 413 ):
414 """ 415 Return the differential pressure (difference between pitot and static 416 pressures) for a given EAS. 417 418 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 419 420 The pressure units may be in inches of HG, mm of HG, psi, lb/ft^2, 421 hpa and mb. The units are specified as: 'in HG', 'mm HG', 'psi', 422 'lb/in**2', 'psf', 'lb/ft**2 'hpa', 'mb' or 'pa'. 423 424 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 425 statute miles, ('sm') or nautical miles ('nm'). 426 427 If the units are not specified, the units in default_units.py are used. 428 429 This first version only works for CAS < 661.48 kt. 430 431 """ 432 433 # check to confirm the speed is less than 661.48 kt 434 435 keas = U.speed_conv(eas, from_units=speed_units, to_units='kt') 436 if keas > 661.48: 437 raise ValueError, \ 438 'The function eas2dp only works if the eas is less than or equal to 661.48 kt' 439 440 P = SA.alt2press(altitude, alt_units=alt_units, press_units='pa') 441 dp = _speed2dp(eas, P, Rho0, press_units=press_units, 442 speed_units=speed_units) 443 444 return dp
445 446
447 -def tas2dp( 448 tas, 449 altitude, 450 temp, 451 speed_units=default_speed_units, 452 alt_units=default_alt_units, 453 temp_units=default_temp_units, 454 press_units=default_press_units, 455 ):
456 """ 457 Return the differential pressure (difference between pitot and static 458 pressures) for a given TAS. 459 460 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 461 462 The pressure units may be in inches of HG, mm of HG, psi, lb/ft^2, 463 hpa and mb. The units are specified as: 'in HG', 'mm HG', 'psi', 464 'lb/in**2', 'psf', 'lb/ft**2 'hpa', 'mb' or 'pa'. 465 466 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 467 statute miles, ('sm') or nautical miles ('nm'). 468 469 The temperature may be in deg C, F, K or R. 470 471 If the units are not specified, the units in default_units.py are used. 472 473 This first version only works for CAS < 661.48 kt. 474 475 """ 476 477 # check to confirm the speed is less than 661.48 kt 478 479 ktas = U.speed_conv(tas, from_units=speed_units, to_units='kt') 480 if ktas > 661.48: 481 raise ValueError, \ 482 'The function tas2dp only works if the tas is less than or equal to 661.48 kt' 483 484 P = SA.alt2press(altitude, alt_units=alt_units, press_units='pa') 485 486 press_ratio = SA.alt2press_ratio(altitude, alt_units) 487 temp_ratio = U.temp_conv(temp, from_units=temp_units, to_units='K')\ 488 / 288.15 489 density_ratio = press_ratio / temp_ratio 490 Rho = Rho0 * density_ratio 491 dp = _speed2dp(tas, P, Rho, press_units=press_units, 492 speed_units=speed_units) 493 494 return dp
495 496
497 -def cas2eas( 498 cas, 499 altitude, 500 speed_units=default_speed_units, 501 alt_units=default_alt_units, 502 ):
503 """ 504 Return the EAS for a given CAS, pressure altitude and temperature. 505 506 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 507 508 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 509 statute miles, ('sm') or nautical miles ('nm'). 510 511 If the units are not specified, the units in default_units.py are used. 512 """ 513 514 dp = cas2dp(cas, speed_units) 515 eas = dp2eas(dp, altitude, alt_units=alt_units, 516 speed_units=speed_units) 517 518 return eas
519 520
521 -def i_cas2eas(data_items):
522 """ 523 Return the EAS for a given CAS, pressure altitude and temp, with 524 interactive input from the user. 525 """ 526 527 # version that goes interactive, if required 528 529 data_items['cas'] = _get_CAS(data_items) 530 cas = data_items['cas'] 531 532 data_items['speed_units'] = _get_speed_units(data_items) 533 speed_units = data_items['speed_units'] 534 535 data_items['altitude'] = _get_alt(data_items) 536 altitude = data_items['altitude'] 537 538 data_items['alt_units'] = _get_alt_units(data_items) 539 alt_units = data_items['alt_units'] 540 541 print 542 print 'CAS = ', cas, speed_units 543 print 'Altitude = ', altitude, alt_units 544 print 545 546 eas = cas2eas(cas, altitude, speed_units, alt_units) 547 data_items['eas'] = eas 548 return_string = 'EAS = ' + str(eas) + ' ' + speed_units 549 print return_string
550 551
552 -def cas2tas( 553 cas, 554 altitude, 555 temp='std', 556 speed_units=default_speed_units, 557 alt_units=default_alt_units, 558 temp_units=default_temp_units, 559 ):
560 """ 561 Return the TAS for a given CAS, pressure altitude and temperature. 562 563 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 564 565 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 566 statute miles, ('sm') or nautical miles ('nm'). 567 568 The temperature may be in deg C, F, K or R. The temperature defaults to std 569 temperature if it is not input. 570 571 If the units are not specified, the units in default_units.py are used. 572 573 """ 574 575 if temp == 'std': 576 temp = SA.alt2temp(altitude, temp_units=temp_units, 577 alt_units=alt_units) 578 579 dp = cas2dp(cas, speed_units) 580 tas = dp2tas( 581 dp, 582 altitude, 583 temp, 584 speed_units=speed_units, 585 alt_units=alt_units, 586 temp_units=temp_units, 587 ) 588 589 return tas
590 591
592 -def i_cas2tas(data_items):
593 """ 594 Return the TAS for a given CAS, pressure altitude and temp, with 595 interactive input from the user. 596 """ 597 598 # version that goes interactive, if required 599 600 data_items['cas'] = _get_CAS(data_items) 601 cas = data_items['cas'] 602 603 data_items['speed_units'] = _get_speed_units(data_items) 604 speed_units = data_items['speed_units'] 605 606 data_items['altitude'] = _get_alt(data_items) 607 altitude = data_items['altitude'] 608 609 data_items['alt_units'] = _get_alt_units(data_items) 610 alt_units = data_items['alt_units'] 611 612 data_items['temp_units'] = _get_temp_units(data_items) 613 temp_units = data_items['temp_units'] 614 615 data_items['temp'] = _get_temp(data_items) 616 temp = data_items['temp'] 617 618 print 619 print 'CAS = ', cas, speed_units 620 print 'Altitude = ', altitude, alt_units 621 print 'Temperature = ', temp, 'deg', temp_units 622 print 623 624 tas = cas2tas( 625 cas, 626 altitude, 627 temp, 628 speed_units, 629 alt_units, 630 temp_units, 631 ) 632 data_items['tas'] = tas 633 return_string = 'TAS = ' + str(tas) + ' ' + speed_units 634 print return_string
635 636
637 -def eas2tas( 638 eas, 639 altitude, 640 temp='std', 641 speed_units=default_speed_units, 642 alt_units=default_alt_units, 643 temp_units=default_temp_units, 644 ):
645 """ 646 Return the TAS for a given EAS, pressure altitude and temperature. 647 648 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 649 650 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 651 statute miles, ('sm') or nautical miles ('nm'). 652 653 The temperature may be in deg C, F, K or R. The temperature defaults to std 654 temperature if it is not input. 655 656 If the units are not specified, the units in default_units.py are used. 657 658 """ 659 660 if temp == 'std': 661 temp = SA.alt2temp(altitude, temp_units=temp_units, 662 alt_units=alt_units) 663 664 dp = eas2dp(eas, altitude, speed_units, alt_units) 665 tas = dp2tas( 666 dp, 667 altitude, 668 temp, 669 speed_units=speed_units, 670 alt_units=alt_units, 671 temp_units=temp_units, 672 ) 673 674 return tas
675 676
677 -def i_eas2tas(data_items):
678 """ 679 Return the TAS for a given EAS, pressure altitude and temp, with 680 interactive input from the user. 681 """ 682 683 # version that goes interactive, if required 684 685 data_items['eas'] = _get_EAS(data_items) 686 eas = data_items['eas'] 687 688 data_items['speed_units'] = _get_speed_units(data_items) 689 speed_units = data_items['speed_units'] 690 691 data_items['altitude'] = _get_alt(data_items) 692 altitude = data_items['altitude'] 693 694 data_items['alt_units'] = _get_alt_units(data_items) 695 alt_units = data_items['alt_units'] 696 697 data_items['temp_units'] = _get_temp_units(data_items) 698 temp_units = data_items['temp_units'] 699 700 data_items['temp'] = _get_temp(data_items) 701 temp = data_items['temp'] 702 703 print 704 print 'EAS = ', eas, speed_units 705 print 'Altitude = ', altitude, alt_units 706 print 'Temperature = ', temp, 'deg', temp_units 707 print 708 709 tas = eas2tas( 710 eas, 711 altitude, 712 temp, 713 speed_units, 714 alt_units, 715 temp_units, 716 ) 717 data_items['tas'] = tas 718 return_string = 'TAS = ' + str(tas) + ' ' + speed_units 719 print return_string
720 721
722 -def eas2cas( 723 eas, 724 altitude, 725 speed_units=default_speed_units, 726 alt_units=default_alt_units, 727 ):
728 """ 729 Return the CAS for a given EAS, pressure altitude and temperature. 730 731 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 732 733 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 734 statute miles, ('sm') or nautical miles ('nm'). 735 736 If the units are not specified, the default units in default_units.py are used. 737 738 Examples: 739 740 Determine equivalent Air Speed for 250 kt CAS at 10,000 ft: 741 >>> cas2eas(250, 10000) 742 248.09577137102258 743 744 Determine equivalent Air Speed for 250 mph CAS at 10,000 ft: 745 >>> cas2eas(250, 10000, speed_units = 'mph') 746 248.54048288757579 747 """ 748 749 dp = eas2dp(eas, altitude, speed_units, alt_units) 750 cas = dp2cas(dp, speed_units=speed_units) 751 752 return cas
753 754
755 -def i_eas2cas(data_items):
756 """ 757 Return the CAS for a given EAS, pressure altitude, with 758 interactive input from the user. 759 760 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 761 762 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 763 statute miles, ('sm') or nautical miles ('nm'). 764 765 If the units are not specified, the units in default_units.py are used. 766 767 """ 768 769 data_items['eas'] = _get_EAS(data_items) 770 eas = data_items['eas'] 771 772 data_items['speed_units'] = _get_speed_units(data_items) 773 speed_units = data_items['speed_units'] 774 775 data_items['altitude'] = _get_alt(data_items) 776 altitude = data_items['altitude'] 777 778 data_items['alt_units'] = _get_alt_units(data_items) 779 alt_units = data_items['alt_units'] 780 781 print 782 print 'EAS = ', eas, speed_units 783 print 'Altitude = ', altitude, alt_units 784 print 785 786 cas = eas2cas(eas, altitude, speed_units, alt_units) 787 data_items['cas'] = cas 788 return_string = 'CAS = ' + str(cas) + ' ' + speed_units 789 print return_string
790 791
792 -def tas2cas( 793 tas, 794 altitude, 795 temp='std', 796 speed_units=default_speed_units, 797 alt_units=default_alt_units, 798 temp_units=default_temp_units, 799 ):
800 """ 801 Return the CAS for a given TAS, pressure altitude and temperature. 802 803 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 804 805 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 806 statute miles, ('sm') or nautical miles ('nm'). 807 808 The temperature may be in deg C, F, K or R. The temperature defaults to std 809 temperature if it is not input. 810 811 If the units are not specified, the units in default_units.py are used. 812 813 Examples: 814 815 Determine the true Air Speed for 250 kt CAS at 10,000 ft with standard 816 temperature: 817 >>> cas2tas(250, 10000) 818 288.70227231079861 819 820 Determine the true Air Speed for 250 mph CAS at 10,000 ft with standard 821 temperature: 822 >>> cas2tas(250, 10000, speed_units = 'mph') 823 289.21977095514148 824 825 Determine the true Air Speed for 250 mph CAS at 10,000 ft with 826 temperature of 0 deg C: 827 >>> cas2tas(250, 10000, 0, speed_units = 'mph') 828 291.80148048806217 829 830 Determine the true Air Speed for 250 mph CAS at 10,000 ft with 831 temperature of 0 deg F: 832 >>> cas2tas(250, 10000, 0, speed_units = 'mph', temp_units = 'F') 833 282.14588227473797 834 """ 835 836 if temp == 'std': 837 temp = SA.alt2temp(altitude, temp_units=temp_units, 838 alt_units=alt_units) 839 840 dp = tas2dp( 841 tas, 842 altitude, 843 temp, 844 speed_units, 845 alt_units=alt_units, 846 temp_units=temp_units, 847 ) 848 cas = dp2cas(dp, speed_units=speed_units) 849 850 return cas
851 852
853 -def i_tas2cas(data_items):
854 """ 855 Return the CAS for a given TAS, pressure altitude and temp, with 856 interactive input from the user. 857 858 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 859 860 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 861 statute miles, ('sm') or nautical miles ('nm'). 862 863 The temperature may be in deg C, F, K or R. The temperature defaults to std 864 temperature if it is not input. 865 866 If the units are not specified, the units in default_units.py are used. 867 868 """ 869 870 data_items['tas'] = _get_TAS(data_items) 871 tas = data_items['tas'] 872 873 data_items['speed_units'] = _get_speed_units(data_items) 874 speed_units = data_items['speed_units'] 875 876 data_items['altitude'] = _get_alt(data_items) 877 altitude = data_items['altitude'] 878 879 data_items['alt_units'] = _get_alt_units(data_items) 880 alt_units = data_items['alt_units'] 881 882 data_items['temp_units'] = _get_temp_units(data_items) 883 temp_units = data_items['temp_units'] 884 885 data_items['temp'] = _get_temp(data_items) 886 temp = data_items['temp'] 887 888 print 889 print 'TAS = ', tas, speed_units 890 print 'Altitude = ', altitude, alt_units 891 print 'Temperature = ', temp, 'deg', temp_units 892 print 893 894 cas = tas2cas( 895 tas, 896 altitude, 897 temp, 898 speed_units, 899 alt_units, 900 temp_units, 901 ) 902 data_items['cas'] = cas 903 return_string = 'CAS = ' + str(cas) + ' ' + speed_units 904 print return_string
905 906
907 -def tas2eas( 908 tas, 909 altitude, 910 temp='std', 911 speed_units=default_speed_units, 912 alt_units=default_alt_units, 913 temp_units=default_temp_units, 914 ):
915 """ 916 Return the EAS for a given TAS, pressure altitude and temperature. 917 918 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 919 920 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 921 statute miles, ('sm') or nautical miles ('nm'). 922 923 The temperature may be in deg C, F, K or R. The temperature defaults to std 924 temperature if it is not input. 925 926 If the units are not specified, the units in default_units.py are used. 927 928 """ 929 930 if temp == 'std': 931 temp = SA.alt2temp(altitude, temp_units=temp_units, 932 alt_units=alt_units) 933 934 dp = tas2dp( 935 tas, 936 altitude, 937 temp, 938 speed_units, 939 alt_units=alt_units, 940 temp_units=temp_units, 941 ) 942 eas = dp2eas(dp, altitude, alt_units=alt_units, 943 speed_units=speed_units) 944 945 return eas
946 947
948 -def i_tas2eas(data_items):
949 """ 950 Return the EAS for a given TAS, pressure altitude and temp, with 951 interactive input from the user. 952 953 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 954 955 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 956 statute miles, ('sm') or nautical miles ('nm'). 957 958 The temperature may be in deg C, F, K or R. The temperature defaults to std 959 temperature if it is not input. 960 961 If the units are not specified, the units in default_units.py are used. 962 963 """ 964 965 data_items['tas'] = _get_TAS(data_items) 966 tas = data_items['tas'] 967 968 data_items['speed_units'] = _get_speed_units(data_items) 969 speed_units = data_items['speed_units'] 970 971 data_items['altitude'] = _get_alt(data_items) 972 altitude = data_items['altitude'] 973 974 data_items['alt_units'] = _get_alt_units(data_items) 975 alt_units = data_items['alt_units'] 976 977 data_items['temp_units'] = _get_temp_units(data_items) 978 temp_units = data_items['temp_units'] 979 980 data_items['temp'] = _get_temp(data_items) 981 temp = data_items['temp'] 982 983 print 984 print 'TAS = ', tas, speed_units 985 print 'Altitude = ', altitude, alt_units 986 print 'Temperature = ', temp, 'deg', temp_units 987 print 988 989 eas = tas2eas( 990 tas, 991 altitude, 992 temp, 993 speed_units, 994 alt_units, 995 temp_units, 996 ) 997 data_items['eas'] = eas 998 return_string = 'EAS = ' + str(eas) + ' ' + speed_units 999 print return_string
1000 1001 1002 # ############################################################################# 1003 # 1004 # delta p over p to Mach 1005 # 1006 # and 1007 # 1008 # Mach to delta p over p 1009 # 1010 # ############################################################################# 1011 1012
1013 -def dp_over_p2mach(dp_over_p):
1014 """ 1015 Return the mach number for a given delta p over p. 1016 1017 Mach must be less than or equal to 10. 1018 """ 1019 1020 # mach = (5*( (dp_over_p + 1)**(2/7.) -1) )**0.5 1021 1022 mach = M.sqrt(5. * ((dp_over_p + 1.) ** (2. / 7.) - 1.)) 1023 1024 if mach <= 1.: 1025 return mach 1026 else: 1027 1028 # supersonic case - need to iterate a solution. Set upper and lower 1029 # guesses, and iterate until we zero in on a mach that produces the 1030 # desired result. 1031 1032 dp_over_p_seek = dp_over_p 1033 1034 low = 1. # initial lower guess for mach 1035 1036 # This function works up to Mach 10 The upper limit can be 1037 # extended by increasing the value of the initial upper guess 1038 # ("high"). 1039 1040 high = 10 # initial upper guess for mach 1041 1042 # confirm initial low and high are OK: 1043 1044 dp_over_p_low = mach2dp_over_p(low) 1045 if dp_over_p_low > dp_over_p_seek: 1046 raise ValueError, 'Initial lower mach guess is too high.' 1047 1048 dp_over_p_high = mach2dp_over_p(high) 1049 if dp_over_p_high < dp_over_p_seek: 1050 raise ValueError, 'Initial upper mach guess is too low.' 1051 1052 guess = (low + high) / 2. 1053 dp_over_p_guess = mach2dp_over_p(guess) 1054 1055 # keep iterating until dp is within 0.001% of desired value 1056 1057 while M.fabs(dp_over_p_guess - dp_over_p_seek) / dp_over_p_seek\ 1058 > 1e-5: 1059 if dp_over_p_guess > dp_over_p_seek: 1060 high = guess 1061 else: 1062 low = guess 1063 1064 guess = (low + high) / 2. 1065 dp_over_p_guess = mach2dp_over_p(guess) 1066 1067 return guess
1068 1069
1070 -def mach2dp_over_p(M):
1071 """ 1072 Return the delta p over p for a given mach number. 1073 The result is equal to: 1074 (pitot pressure - static pressure) / static pressure 1075 1076 Example - determine the delta p over p at mach 0.4: 1077 1078 >>> mach2dp_over_p(.4) 1079 0.11655196580975336 1080 """ 1081 1082 if M <= 1.: 1083 dp_over_p = (M ** 2. / 5. + 1.) ** 3.5 - 1. 1084 else: 1085 dp_over_p = (F * M ** 7.) / (7. * M ** 2. - 1.) ** 2.5 - 1. 1086 1087 return dp_over_p
1088 1089 1090 # ############################################################################# 1091 # 1092 # conversions between cas, mach and altitude 1093 # 1094 # pick any two values, and find the third 1095 # 1096 # ############################################################################# 1097 1098
1099 -def cas_mach2alt( 1100 cas, 1101 mach, 1102 speed_units=default_speed_units, 1103 alt_units=default_alt_units, 1104 ):
1105 """ 1106 Return the altitude that corresponds to a given CAS and mach. 1107 1108 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1109 1110 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 1111 statute miles, ('sm') or nautical miles ('nm'). 1112 1113 If the units are not specified, the units in default_units.py are used. 1114 1115 """ 1116 1117 dp = cas2dp(cas, speed_units=speed_units, press_units='pa') 1118 dp_over_p = mach2dp_over_p(mach) 1119 p = dp / dp_over_p 1120 altitude = SA.press2alt(p, press_units='pa', alt_units=alt_units) 1121 1122 return altitude
1123 1124
1125 -def i_cas_mach2alt(data_items):
1126 """ 1127 Return the altitude that corresponds to a given CAS and mach, with an 1128 interactive interface. 1129 """ 1130 1131 data_items['cas'] = _get_CAS(data_items) 1132 cas = data_items['cas'] 1133 1134 data_items['speed_units'] = _get_speed_units(data_items) 1135 speed_units = data_items['speed_units'] 1136 1137 data_items['mach'] = _get_mach(data_items) 1138 mach = data_items['mach'] 1139 1140 data_items['alt_units'] = _get_alt_units(data_items) 1141 alt_units = data_items['alt_units'] 1142 1143 print 1144 print 'CAS = ', cas, speed_units 1145 print 'Mach = ', mach 1146 1147 # print 'Desired altitude units are: ', alt_units 1148 1149 print 1150 1151 alt = cas_mach2alt(cas, mach, speed_units, alt_units) 1152 data_items['altitude'] = alt 1153 1154 return_string = 'Altitude = ' + str(alt) + ' ' + alt_units 1155 print return_string
1156 1157
1158 -def cas_alt2mach( 1159 cas, 1160 altitude, 1161 speed_units=default_speed_units, 1162 alt_units=default_alt_units, 1163 ):
1164 """ 1165 Return the mach that corresponds to a given CAS and altitude. 1166 1167 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1168 1169 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 1170 statute miles, ('sm') or nautical miles ('nm'). 1171 1172 If the units are not specified, the units in default_units.py are used. 1173 1174 """ 1175 1176 dp = cas2dp(cas, speed_units=speed_units, press_units='pa') 1177 p = SA.alt2press(altitude, alt_units=alt_units, press_units='pa') 1178 dp_over_p = dp / p 1179 mach = dp_over_p2mach(dp_over_p) 1180 1181 return mach
1182 1183
1184 -def i_cas_alt2mach(data_items):
1185 """ 1186 Return the mach that corresponds to a given CAS and altitude, using an 1187 interactive interface. 1188 """ 1189 1190 data_items['cas'] = _get_CAS(data_items) 1191 cas = data_items['cas'] 1192 1193 data_items['speed_units'] = _get_speed_units(data_items) 1194 speed_units = data_items['speed_units'] 1195 1196 data_items['altitude'] = _get_alt(data_items) 1197 altitude = data_items['altitude'] 1198 1199 data_items['alt_units'] = _get_alt_units(data_items) 1200 alt_units = data_items['alt_units'] 1201 1202 print 1203 print 'CAS = ', cas, speed_units 1204 print 'Altitude = ', altitude, alt_units 1205 print 1206 1207 mach = cas_alt2mach(cas, altitude, speed_units, alt_units) 1208 data_items['mach'] = mach 1209 print 'Mach = ', mach
1210 1211
1212 -def _cas_alt2mach2( 1213 cas, 1214 altitude, 1215 speed_units=default_speed_units, 1216 alt_units=default_alt_units, 1217 ):
1218 """ 1219 Alternative, trial variant of cas_alt2mach, using the equations from 1220 USAF TPS notes. 1221 1222 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1223 1224 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 1225 statute miles, ('sm') or nautical miles ('nm'). 1226 1227 If the units are not specified, the units in default_units.py are used. 1228 1229 """ 1230 1231 PR = SA.alt2press_ratio(altitude, alt_units) 1232 cas = U.speed_conv(cas, from_units=speed_units, to_units='m/s') 1233 1234 if cas <= A0: 1235 1236 # <= 661.48 kt 1237 1238 mach = M.sqrt(5. * (((1. / PR) * ((1. + 0.2 * (cas / A0) ** 2.) 1239 ** 3.5 - 1.) + 1.) ** (2. / 7.) - 1.)) 1240 else: 1241 raise ValueError, 'CAS too high.' 1242 1243 return mach
1244 1245
1246 -def mach_alt2cas( 1247 mach, 1248 altitude, 1249 alt_units=default_alt_units, 1250 speed_units=default_speed_units, 1251 ):
1252 """ 1253 Return the calibrated Air Speed that corresponds to a given mach and 1254 altitude. 1255 1256 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1257 1258 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 1259 statute miles, ('sm') or nautical miles ('nm'). 1260 1261 If the units are not specified, the units in default_units.py are used. 1262 1263 """ 1264 1265 p = SA.alt2press(altitude, alt_units=alt_units, press_units='pa') 1266 dp_over_p = mach2dp_over_p(mach) 1267 dp = dp_over_p * p 1268 cas = dp2cas(dp, press_units='pa', speed_units=speed_units) 1269 1270 return cas
1271 1272
1273 -def i_mach_alt2cas(data_items):
1274 """ 1275 Return the calibrated Air Speed that corresponds to a given mach and 1276 altitude, using an interactive interface. 1277 """ 1278 1279 data_items['mach'] = _get_mach(data_items) 1280 mach = data_items['mach'] 1281 1282 data_items['altitude'] = _get_alt(data_items) 1283 altitude = data_items['altitude'] 1284 1285 data_items['alt_units'] = _get_alt_units(data_items) 1286 alt_units = data_items['alt_units'] 1287 1288 data_items['speed_units'] = _get_speed_units(data_items) 1289 speed_units = data_items['speed_units'] 1290 1291 print 1292 print 'Altitude = ', altitude, alt_units 1293 print 'Mach = ', mach 1294 print 1295 1296 cas = mach_alt2cas(mach, altitude, alt_units, speed_units) 1297 data_items['cas'] = cas 1298 return_string = 'CAS = ' + str(cas) + ' ' + speed_units 1299 print return_string
1300 1301 1302 # ############################################################################# 1303 # 1304 # Mach and temperature to TAS 1305 # 1306 # and 1307 # 1308 # TAS and temperature to Mach 1309 # 1310 # ############################################################################# 1311 1312
1313 -def mach2tas( 1314 mach, 1315 temp='std', 1316 altitude='blank', 1317 temp_units=default_temp_units, 1318 alt_units=default_alt_units, 1319 speed_units=default_speed_units, 1320 ):
1321 """ 1322 Return the TAS for a given mach number. The temperature or altitude 1323 must also be specified. If the altitude is specified, the temperature 1324 is assumed to be standard. If both the altitude and temperature are 1325 specified, the altitude input is ignored. 1326 1327 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1328 1329 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 1330 statute miles, ('sm') or nautical miles ('nm'). 1331 1332 The temperature may be in deg C, F, K or R. The temperature defaults to std 1333 temperature if it is not input. 1334 1335 If the units are not specified, the units in default_units.py are used. 1336 1337 Examples: 1338 1339 Determine the TAS in kt at 0.8 mach at a temperature of 1340 -15 deg C: 1341 >>> mach2tas(0.8, -15) 1342 500.87884108468597 1343 1344 Determine the TAS in kt at 0.8 mach at 30,000 ft, assuming 1345 standard temperature: 1346 >>> mach2tas(0.8, altitude = 30000) 1347 471.45798523415107 1348 1349 Determine the TAS in mph at 0.8 mach at 5000 m, assuming 1350 standard temperature: 1351 >>> mach2tas(0.8, altitude = 5000, alt_units = 'm', speed_units = 'mph') 1352 573.60326790383715 1353 1354 Determine the TAS in km/h at 0.4 mach at a temperature of 1355 300 deg K: 1356 >>> mach2tas(0.4, 300, temp_units = 'K', speed_units = 'km/h') 1357 499.99796329569176 1358 """ 1359 1360 if temp == 'std': 1361 if altitude != 'blank': 1362 temp = SA.alt2temp(altitude, temp_units=temp_units, 1363 alt_units=alt_units) 1364 else: 1365 raise ValueError, \ 1366 'At least one of the temperature or altitude must be specified.' 1367 1368 tas = mach * SA.temp2speed_of_sound(temp, temp_units, speed_units) 1369 1370 return tas
1371 1372
1373 -def i_mach2tas(data_items):
1374 """ 1375 Return the TAS that corresponds to a given Mach, altitude, and temperature 1376 using an interactive interface. 1377 """ 1378 1379 data_items['mach'] = _get_mach(data_items) 1380 mach = data_items['mach'] 1381 1382 data_items['altitude'] = _get_alt(data_items) 1383 altitude = data_items['altitude'] 1384 1385 data_items['alt_units'] = _get_alt_units(data_items) 1386 alt_units = data_items['alt_units'] 1387 1388 data_items['temp_units'] = _get_temp_units(data_items) 1389 temp_units = data_items['temp_units'] 1390 1391 data_items['temp'] = _get_temp(data_items) 1392 temp = data_items['temp'] 1393 1394 data_items['speed_units'] = _get_speed_units(data_items) 1395 speed_units = data_items['speed_units'] 1396 1397 print 1398 print 'Mach = ', mach 1399 print 'Altitude = ', altitude, alt_units 1400 print 'Temperature =', temp, temp_units 1401 print 1402 1403 tas = mach2tas( 1404 mach, 1405 temp, 1406 altitude, 1407 temp_units, 1408 alt_units, 1409 speed_units, 1410 ) 1411 data_items['tas'] = tas 1412 print 'TAS = ', tas, speed_units
1413 1414
1415 -def tas2mach( 1416 tas, 1417 temp='std', 1418 altitude='blank', 1419 temp_units=default_temp_units, 1420 alt_units=default_alt_units, 1421 speed_units=default_speed_units, 1422 ):
1423 """ 1424 Return the mach number for a given TAS. The temperature or altitude 1425 must also be specified. If the altitude is specified, the temperature 1426 is assumed to be standard. If both the altitude and temperature are 1427 specified, the altitude input is ignored. 1428 1429 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1430 1431 The altitude may be in feet ('ft'), metres ('m'), kilometres ('km'), 1432 statute miles, ('sm') or nautical miles ('nm'). 1433 1434 The temperature may be in deg C, F, K or R. The temperature defaults to std 1435 temperature if it is not input. 1436 1437 If the units are not specified, the units in default_units.py are used. 1438 1439 Examples: 1440 1441 Determine the mach number for a TAS of 500 kt at a temperature of 1442 -15 deg C: 1443 >>> tas2mach(500, -15) 1444 0.79859632148519943 1445 1446 Determine the mach number for a TAS of 500 kt at a temperature of 1447 0 deg F: 1448 >>> tas2mach(500, 0, temp_units = 'F') 1449 0.80292788758764277 1450 1451 Determine the mach number for a TAS of 500 kt at an altitude of 1452 10,000 ft, assuming standard temperature: 1453 >>> tas2mach(500, altitude = 10000) 1454 0.78328945665870209 1455 1456 Determine the mach number for a TAS of 400 mph at an altitude of 1457 5000 m, assuming standard temperature: 1458 >>> tas2mach(400, altitude = 5000, speed_units = 'mph', alt_units = 'm') 1459 0.55787687746166581 1460 """ 1461 1462 if temp == 'std': 1463 if altitude != 'blank': 1464 temp = SA.alt2temp(altitude, temp_units=temp_units, 1465 alt_units=alt_units) 1466 else: 1467 raise ValueError, \ 1468 'At least one of the temperature or altitude must be specified.' 1469 1470 mach = tas / SA.temp2speed_of_sound(temp, temp_units, speed_units) 1471 1472 return mach
1473 1474
1475 -def i_tas2mach(data_items):
1476 """ 1477 Return the mach that corresponds to a given TAS, altitude, and temperature 1478 using an interactive interface. 1479 """ 1480 1481 data_items['tas'] = _get_TAS(data_items) 1482 tas = data_items['tas'] 1483 1484 data_items['speed_units'] = _get_speed_units(data_items) 1485 speed_units = data_items['speed_units'] 1486 1487 data_items['altitude'] = _get_alt(data_items) 1488 altitude = data_items['altitude'] 1489 1490 data_items['alt_units'] = _get_alt_units(data_items) 1491 alt_units = data_items['alt_units'] 1492 1493 data_items['temp_units'] = _get_temp_units(data_items) 1494 temp_units = data_items['temp_units'] 1495 1496 data_items['temp'] = _get_temp(data_items) 1497 temp = data_items['temp'] 1498 1499 print 1500 print 'TAS = ', tas, speed_units 1501 print 'Altitude = ', altitude, alt_units 1502 print 'Temperature =', temp, temp_units 1503 print 1504 1505 mach = tas2mach( 1506 tas, 1507 temp, 1508 altitude, 1509 temp_units, 1510 alt_units, 1511 speed_units, 1512 ) 1513 data_items['mach'] = mach 1514 print 'Mach = ', mach
1515 1516 1517 # ############################################################################# 1518 # 1519 # Ram temperature rise calculations 1520 # 1521 # Mach and indicated temperature to ambient temperature 1522 # 1523 # and 1524 # 1525 # TAS and indicated temperature to ambient temperature 1526 # 1527 # ############################################################################# 1528 1529
1530 -def mach2temp( 1531 mach, 1532 indicated_temp, 1533 recovery_factor, 1534 temp_units=default_temp_units, 1535 ):
1536 """ 1537 Return the ambient temp, given the mach number, indicated 1538 temperature and the temperature probe's recovery factor. 1539 1540 The temperature may be in deg C, F, K or R. 1541 1542 If the units are not specified, the units in default_units.py are used. 1543 1544 1545 Examples: 1546 1547 Determine the ambient temperature with an indicated temperature of 1548 -20 deg C at mach 0.6 with a probe recovery factor of 0.8: 1549 1550 >>> mach2temp(0.6, -20, 0.8) 1551 -33.787291981845698 1552 1553 Determine the ambient temperature with an indicated temperature of 1554 75 deg F at mach 0.3 with a probe recovery factor of 0.9: 1555 1556 >>> mach2temp(0.3, 75, 0.9, temp_units = 'F') 1557 66.476427868529839 1558 """ 1559 1560 indicated_temp = U.temp_conv(indicated_temp, from_units=temp_units, 1561 to_units='K') 1562 ambient_temp = indicated_temp / (1. + (0.2 * recovery_factor) * mach 1563 ** 2.) 1564 1565 ambient_temp = U.temp_conv(ambient_temp, from_units='K', 1566 to_units=temp_units) 1567 1568 return ambient_temp
1569 1570
1571 -def tas2temp( 1572 tas, 1573 indicated_temp, 1574 recovery_factor, 1575 speed_units=default_speed_units, 1576 temp_units=default_temp_units, 1577 ):
1578 """ 1579 Return the ambient temp, given the TAS, indicated temperature 1580 and the temperature probe's recovery factor. 1581 1582 The speed units may be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'. 1583 1584 The temperature may be in deg C, F, K or R. The temperature defaults to std 1585 temperature if it is not input. 1586 1587 If the units are not specified, the units in default_units.py are used. 1588 1589 """ 1590 1591 indicated_temp = U.temp_conv(indicated_temp, from_units=temp_units, 1592 to_units='K') 1593 tas = U.speed_conv(tas, from_units=speed_units, to_units='kt') 1594 1595 # value 7592.4732909142658 was adjusted to make the result equal that 1596 # obtained using mach2temp 1597 1598 ambient_temp = indicated_temp - (recovery_factor * tas ** 2.)\ 1599 / 7592.4732909142658 1600 1601 ambient_temp = U.temp_conv(ambient_temp, from_units='K', 1602 to_units=temp_units) 1603 1604 return ambient_temp
1605 1606 1607 # ############################################################################# 1608 # 1609 # Interactive mode 1610 # 1611 # Private functions for interactive user interface 1612 # 1613 # ############################################################################# 1614 1615
1616 -def _get_alt(data_items): #pragma: no cover
1617 try: 1618 prompt = 'Altitude = [' + str(data_items['altitude']) + '] ' 1619 value = VI.get_input2(prompt, 1620 conditions_any=['ERROR - Altitude must be a number. Commas are not allowed.' 1621 , 'type(float(X)) == float', 'X == ""']) 1622 if value != '': 1623 data_items['altitude'] = float(value) 1624 except KeyError: 1625 1626 prompt = 'Altitude = ' 1627 data_items['altitude'] = float(VI.get_input2('Altitude = ', 1628 conditions_any=['ERROR - Altitude must be a number. Commas are not allowed.' 1629 , 'type(float(X)) == float', 'X == ""'])) 1630 return data_items['altitude'] 1631 1632
1633 -def _get_alt_units(data_items): #pragma: no cover
1634 1635 if data_items['alt_units'] == 'ft': 1636 prompt = 'altitude units = [ft], m, km, sm, nm: ' 1637 elif data_items['alt_units'] == 'm': 1638 prompt = 'altitude units = [m], ft, km, sm, nm: ' 1639 elif data_items['alt_units'] == 'km': 1640 prompt = 'altitude units = [km], ft, m, sm, nm: ' 1641 elif data_items['alt_units'] == 'sm': 1642 prompt = 'altitude units = [sm], ft, m, km, nm: ' 1643 elif data_items['alt_units'] == 'nm': 1644 prompt = 'altitude units = [nm], ft, m, km, sm: ' 1645 1646 alt_units = VI.get_input2(prompt, conditions_any=[ 1647 'ERROR - altitude units must be one of "ft", "m", "km", "sm" or "nm".' 1648 , 1649 'X == "ft"', 1650 'X =="m"', 1651 'X == "km"', 1652 'X == "sm"', 1653 'X == "nm"', 1654 'X == ""', 1655 ]) 1656 if alt_units != '': 1657 print 'Alt units not blank' 1658 data_items['alt_units'] = alt_units 1659 return data_items['alt_units'] 1660 1661
1662 -def _get_CAS(data_items): #pragma: no cover
1663 try: 1664 prompt = 'CAS = [' + str(data_items['cas']) + '] ' 1665 value = VI.get_input2(prompt, 1666 conditions_any=['ERROR - CAS must be a positive number.' 1667 , 'float(X) >= 0', 'X == ""']) 1668 if value != '': 1669 data_items['cas'] = float(value) 1670 except KeyError: 1671 prompt = 'CAS = ' 1672 data_items['cas'] = float(VI.get_input2(prompt, 1673 conditions_any=['ERROR - CAS must be a positive number.' 1674 , 'float(X) >= 0'])) 1675 1676 return data_items['cas'] 1677 1678
1679 -def _get_EAS(data_items): #pragma: no cover
1680 try: 1681 prompt = 'EAS = [' + str(data_items['eas']) + '] ' 1682 value = VI.get_input2(prompt, 1683 conditions_any=['ERROR - EAS must be a positive number.' 1684 , 'float(X) >= 0', 'X == ""']) 1685 if value != '': 1686 data_items['eas'] = float(value) 1687 except KeyError: 1688 prompt = 'EAS = ' 1689 data_items['eas'] = float(VI.get_input2(prompt, 1690 conditions_any=['ERROR - EAS must be a positive number.' 1691 , 'float(X) >= 0'])) 1692 1693 return data_items['eas'] 1694 1695
1696 -def _get_TAS(data_items): #pragma: no cover
1697 try: 1698 prompt = 'TAS = [' + str(data_items['tas']) + '] ' 1699 value = VI.get_input2(prompt, 1700 conditions_any=['ERROR - TAS must be a positive number.' 1701 , 'float(X) >= 0', 'X == ""']) 1702 if value != '': 1703 data_items['tas'] = float(value) 1704 except KeyError: 1705 prompt = 'TAS = ' 1706 data_items['tas'] = float(VI.get_input2(prompt, 1707 conditions_any=['ERROR - TAS must be a positive number.' 1708 , 'float(X) >= 0'])) 1709 1710 return data_items['tas'] 1711 1712
1713 -def _get_speed_units(data_items): #pragma: no cover
1714 if data_items['speed_units'] == 'kt': 1715 prompt = 'speed units = [kt], mph, km/h, m/s, ft/s: ' 1716 elif data_items['speed_units'] == 'mph': 1717 prompt = 'speed units = [mph], kt, km/h, m/s, ft/s: ' 1718 elif data_items['speed_units'] == 'km/h': 1719 prompt = 'speed units = [km/h], kt, mph, m/s, ft/s: ' 1720 elif data_items['speed_units'] == 'm/s': 1721 prompt = 'speed units = [m/s], kt, mph, km/h, ft/s: ' 1722 elif data_items['speed_units'] == 'mph': 1723 prompt = 'speed units = [ft/s], kt, mph, km/h, m/s: ' 1724 1725 spd_units = VI.get_input2(prompt, conditions_any=[ 1726 'ERROR - speed units must be one of "kt", "mph", "km/h", "m/s" or "ft/s".' 1727 , 1728 'X == "kt"', 1729 'X =="mph"', 1730 'X == "km/h"', 1731 'X == "m/s"', 1732 'X == "ft/s"', 1733 'X == ""', 1734 ]) 1735 if spd_units != '': 1736 data_items['speed_units'] = spd_units 1737 return data_items['speed_units'] 1738 1739
1740 -def _get_mach(data_items): #pragma: no cover
1741 try: 1742 prompt = 'Mach = [' + str(data_items['mach']) + '] ' 1743 value = VI.get_input2(prompt, 1744 conditions_any=['ERROR - Mach must be a positive number.' 1745 , 'float(X) >= 0', 'X == ""']) 1746 if value != '': 1747 data_items['mach'] = float(value) 1748 except KeyError: 1749 prompt = 'Mach = ' 1750 data_items['mach'] = float(VI.get_input2(prompt, 1751 conditions_any=['ERROR - Mach must be a positive number.' 1752 , 'float(X) >= 0'])) 1753 1754 return data_items['mach'] 1755 1756
1757 -def _get_temp(data_items): #pragma: no cover
1758 try: 1759 prompt = 'Temperature = [' + str(data_items['temp']) + '] ' 1760 value = VI.get_input2(prompt, 1761 conditions_any=['ERROR - Temperature must be a number, or S for std temperature.' 1762 , 'X =="S"', 'X == "s"', 'X == ""', 1763 'type(float(X)) == float']) 1764 if value.upper() == 'S': 1765 data_items['temp'] = SA.alt2temp(data_items['altitude'], 1766 alt_units=data_items['alt_units'], 1767 temp_units=data_items['temp_units']) 1768 elif value != '': 1769 data_items['temp'] = value 1770 except KeyError: 1771 prompt = 'Temperature = [std] ' 1772 value = VI.get_input2(prompt, 1773 conditions_any=['ERROR - Temperature must be a number, or S for std temperature.' 1774 , 'X =="S"', 'X == "s"', 'X == ""', 1775 'type(float(X)) == float']) 1776 if value == 'S' or value == 's' or value == '': 1777 data_items['temp'] = SA.alt2temp(data_items['altitude'], 1778 alt_units=data_items['alt_units'], 1779 temp_units=data_items['temp_units']) 1780 else: 1781 data_items['temp'] = value 1782 1783 return float(data_items['temp']) 1784 1785
1786 -def _get_temp_units(data_items): #pragma: no cover
1787 if data_items['temp_units'] == 'C': 1788 prompt = 'Temperature units = [C], F, K, R: ' 1789 elif data_items['temp_units'] == 'F': 1790 prompt = 'Temperature units = [F], C, K, R: ' 1791 elif data_items['temp_units'] == 'K': 1792 prompt = 'Temperature units = [K], C, F, R: ' 1793 elif data_items['temp_units'] == 'R': 1794 prompt = 'Temperature units = [R], C, F, K: ' 1795 1796 temp_units = VI.get_input2(prompt, conditions_any=[ 1797 'ERROR - temperature units must be one of "C", "F", "K", or "R".' 1798 , 1799 'X.upper() == "C"', 1800 'X.upper() == "F"', 1801 'X.upper() == "K"', 1802 'X.upper() == "R"', 1803 'X == ""', 1804 ]).upper() 1805 if temp_units != '': 1806 data_items['temp_units'] = temp_units 1807 return data_items['temp_units'] 1808 1809
1810 -def _interactive_mode(): #pragma: no cover
1811 """ 1812 Provide interactive interface for selected functions. 1813 """ 1814 1815 data_items = {} 1816 data_items['speed_units'] = default_speed_units 1817 data_items['alt_units'] = default_alt_units 1818 data_items['temp_units'] = default_temp_units 1819 1820 _interactive_interface(data_items) 1821 1822
1823 -def _interactive_interface(data_items): #pragma: no cover
1824 """Provide interactive interface to screen. 1825 """ 1826 1827 func_list = [ 1828 ['i_cas2eas(data_items)', 'CAS to EAS'], 1829 ['i_cas2tas(data_items)', 'CAS to TAS'], 1830 ['i_eas2cas(data_items)', 'EAS to CAS'], 1831 ['i_eas2tas(data_items)', 'EAS to TAS'], 1832 ['i_tas2cas(data_items)', 'TAS to CAS'], 1833 ['i_tas2eas(data_items)', 'TAS to EAS'], 1834 ['i_cas_alt2mach(data_items)', 'CAS and Altitude to Mach'], 1835 ['i_cas_mach2alt(data_items)', 'CAS and Mach to Altitude'], 1836 ['i_mach_alt2cas(data_items)', 'Mach and Altitude to CAS'], 1837 ['i_tas2mach(data_items)', 1838 'TAS, Altitude and Temperature to Mach'], 1839 ['i_mach2tas(data_items)', 1840 'Mach, Altitude and Temperature to TAS'], 1841 ] 1842 1843 count = 1 1844 print 'The following functions are available:' 1845 for func in func_list: 1846 if count < 10: 1847 print ' ', count, '-', func[1] 1848 else: 1849 print '', count, '-', func[1] 1850 count += 1 1851 print ' Q - Quit' 1852 1853 1854 item = VI.get_input2('Select a function to run by number: ', 1855 conditions_any=['You must enter an integer between 1 and ' 1856 + str(len(func_list)) + ', or "Q"', 1857 '0 < int(X) <= ' + str(len(func_list)), 1858 'X == "Q"', 'X == "q"']) 1859 if item.upper() == 'Q': 1860 return 1861 else: 1862 item = int(item) 1863 print 1864 func_list_num = item - 1 1865 eval(func_list[func_list_num][0]) 1866 prompt = '\nDo another calculation [Y/n]' 1867 input_data = raw_input(prompt) 1868 if input_data == '' or input_data == 'Y' or input_data == 'y': 1869 print '\n' 1870 _interactive_interface(data_items) 1871 else: 1872 sys.exit() 1873 1874 1875 if __name__ == '__main__': #pragma: no cover 1876 1877 # run doctest to check the validity of the examples in the doc strings. 1878 1879 import doctest 1880 import sys 1881 doctest.testmod(sys.modules[__name__]) 1882 1883 # run the interactive interface 1884 1885 _interactive_mode() 1886