source: src/mlx/acft.py@ 919:2ce8ca39525b

python3
Last change on this file since 919:2ce8ca39525b was 919:2ce8ca39525b, checked in by István Váradi <ivaradi@…>, 5 years ago

Ran 2to3

File size: 48.6 KB
RevLine 
[298]1
[919]2from . import const
3from . import gates
4from . import checks
5from . import fs
6from .i18n import xstr
7from . import util
[298]8
9import sys
10import time
11import traceback
12
13from collections import deque
14
15#---------------------------------------------------------------------------------------
16
[297]17## @package mlx.acft
18#
19# The simulator-independent aircraft classes.
20#
21# This module contains the aircraft classes that contain some general data
22# about each aircraft type in the MAVA Fleet. The base class, \ref Aircraft
23# also implements some parts of the logging and traces some data. The classes
24# are also responsible for creating the \ref mlx.checks "checkers". Most of
25# them are created by the \ref Aircraft class' constructor, but there can be
26# type-specific differences. For example the lights are different for different
27# types, so there is a \ref Aircraft._appendLightsLoggers "function" which can
28# be reimplemented in child classes, if needed. This class maintains also the
29# \ref SmoothedValue "smoothed values" of the IAS and the VS and set these
30# values in the \ref mlx.fs.AircraftState "aircraft state" when it is received
31# from the simulator.
[4]32
33#---------------------------------------------------------------------------------------
34
[512]35# Derate type: no derate possible
36DERATE_NONE = 0
37
38# Derate type: Boeing, i.e. a percentage value.
39# For logging, the percentage value is expected as a string (i.e. whatever the
40# pilot enters into the text field).
41DERATE_BOEING = 1
42
43# Derate type: EPR, i.e. an EPR value.
44# For logging, the EPR value is expected as a string (i.e. whatever the pilot
45# enters into the text field).
46DERATE_EPR = 2
47
48# Derate type: Tupolev, i.e. nominal or takeoff
49# For logging, one of the DERATE_TUPOLEV_xxx values are expected.
50DERATE_TUPOLEV = 3
51
52# Tupolev derate value: nominal
53DERATE_TUPOLEV_NOMINAL = 1
54
55# Tupolev derate value: takeoff
56DERATE_TUPOLEV_TAKEOFF = 2
57
58# Derate type: BAe-146, i.e. enabled or not
59# For logging, a boolean is expected.
60DERATE_B462 = 4
61
62#---------------------------------------------------------------------------------------
63
[197]64class SmoothedValue(object):
65 """A smoothed value."""
66 def __init__(self):
67 """Construct the value."""
68 self._deque = deque()
69 self._sum = 0
70
71 def add(self, length, value):
72 """Add the given value and smooth with the given length."""
73 dequeLength = len(self._deque)
74 while dequeLength>=length:
75 self._sum -= self._deque.popleft()
76 dequeLength -= 1
77
78 self._sum += value
79 self._deque.append(value)
80
81 def get(self):
82 """Get the average."""
83 return self._sum / len(self._deque)
[331]84
[4]85#---------------------------------------------------------------------------------------
86
[709]87class SimBriefData(object):
88 """Data to be used when creating SimBrief briefings."""
89 def __init__(self, climbProfiles, cruiseProfiles, descentProfiles):
90 """Construct the SimBrief data with the given profiles."""
91 self.climbProfiles = climbProfiles
92 self.cruiseProfiles = cruiseProfiles
93 self.descentProfiles = descentProfiles
94
95#---------------------------------------------------------------------------------------
96
[4]97class Aircraft(object):
98 """Base class for aircraft."""
[8]99 @staticmethod
[798]100 def create(flight, bookedFlight):
[8]101 """Create an aircraft instance for the type in the given flight."""
[798]102 acft = _classes[flight.aircraftType](flight)
103 acft.setBookedFlight(bookedFlight)
104 return acft
[8]105
[592]106 def __init__(self, flight, minLandingFuel = None,
107 recommendedLandingFuel = None):
[4]108 """Construct the aircraft for the given type."""
[8]109 self._flight = flight
[591]110 self._minLandingFuel = minLandingFuel
[592]111 self._recommendedLandingFuel = recommendedLandingFuel
[369]112
113 self._name = None
114 self._modelName = None
115
[4]116 self._aircraftState = None
[331]117
[9]118 self._maxVS = -10000.0
119 self._minVS = 10000.0
[4]120
[101]121 self._v1r2LineIndex = None
[384]122 self._derateLineID = None
[391]123 self._takeoffAntiIceLineID = None
[96]124 self._vrefLineIndex = None
[391]125 self._landingAntiIceLineID = None
[96]126
[117]127 self.humanWeight = 82.0
128
[598]129 self.initialClimbSpeedAltitude = 1500
130 self.reverseMinSpeed = 50
[360]131
[644]132 self.hasStrobeLight = True
133
[611]134 self.maxTakeOffPitch = 15.0
135 self.maxTouchDownPitch = 15.0
[624]136 self.brakeCoolTime = 10.0
[611]137
[709]138 self.simBriefData = None
139
[8]140 self._checkers = []
141
[197]142 config = flight.config
[11]143 # Loggers
144
[8]145 self._checkers.append(checks.StageChecker())
[9]146 self._checkers.append(checks.TakeOffLogger())
[8]147
148 self._checkers.append(checks.AltimeterLogger())
[321]149
[366]150 self._ilsLogger = checks.ILSLogger()
151 self._checkers.append(self._ilsLogger)
[321]152 self._nav1Logger = checks.NAV1Logger()
153 self._checkers.append(self._nav1Logger)
154 self._nav2Logger = checks.NAV2Logger()
155 self._checkers.append(self._nav2Logger)
156
157 self._adf1Logger = checks.ADF1Logger()
158 self._checkers.append(self._adf1Logger)
159 self._adf2Logger = checks.ADF2Logger()
160 self._checkers.append(self._adf2Logger)
[331]161
[8]162 self._checkers.append(checks.SquawkLogger())
163
[211]164 self._appendLightsLoggers()
[8]165
166 self._checkers.append(checks.FlapsLogger())
167
168 self._checkers.append(checks.GearsLogger())
[601]169 self._checkers.append(checks.InitialClimbSpeedLogger())
[9]170 self._checkers.append(checks.CruiseSpeedLogger())
[10]171 self._checkers.append(checks.SpoilerLogger())
[338]172 self._checkers.append(checks.APLogger())
[9]173
[197]174 if config.isMessageTypeFS(const.MESSAGETYPE_VISIBILITY):
[134]175 self._checkers.append(checks.VisibilityChecker())
176
[139]177 # FIXME: we should have a central data model object, and not collect
178 # the data from the GUI. However, some pieces of data (e.g. V-speeds,
179 # etc. that is entered into the GUI) *should* be a part of the GUI and
180 # queried from it, so the model should have a reference to the GUI as
181 # well and access such data via the GUI!
[215]182 if config.onlineACARS and flight.loggedIn and not flight.entranceExam:
[139]183 self._checkers.append(checks.ACARSSender(flight._gui))
184
[11]185 # Fault checkers
[211]186
187 self._appendLightsCheckers()
[11]188
[335]189 self._checkers.append(checks.TransponderChecker())
190
[11]191 self._checkers.append(checks.BankChecker())
192
193 self._checkers.append(checks.FlapsRetractChecker())
194 self._checkers.append(checks.FlapsSpeedLimitChecker())
195
196 self._checkers.append(checks.GearsDownChecker())
197 self._checkers.append(checks.GearSpeedLimitChecker())
198
199 self._checkers.append(checks.GLoadChecker())
200
201 self._checkers.append(checks.MLWChecker())
202 self._checkers.append(checks.MTOWChecker())
203 self._checkers.append(checks.MZFWChecker())
204 self._checkers.append(checks.PayloadChecker())
205
[539]206 self._checkers.append(checks.SpeedChecker())
[11]207 self._checkers.append(checks.VSChecker())
[197]208
[447]209 timeout = 30.0 + config.realIASSmoothingLength - 1
[622]210 self._checkers.append(checks.OverspeedChecker(faultTimeout = timeout))
[331]211
[11]212 self._checkers.append(checks.StallChecker())
213
214 self._checkers.append(checks.PitotChecker())
[331]215
[598]216 self._checkers.append(checks.ReverserLogger())
[11]217 self._checkers.append(checks.ReverserChecker())
218
[273]219 if flight.aircraftType is not None and config.enableApproachCallouts:
220 approachCallouts = flight.config.getApproachCallouts(flight.aircraftType)
221 if approachCallouts:
222 self._checkers.append(checks.ApproachCalloutsPlayer(approachCallouts))
223
[197]224 self._smoothedIAS = SmoothedValue()
225 self._smoothedVS = SmoothedValue()
226
[4]227 @property
228 def type(self):
229 """Get the type of the aircraft."""
[8]230 return self._flight.aircraftType
231
232 @property
233 def flight(self):
234 """Get the flight the aircraft belongs to."""
235 return self._flight
[4]236
[8]237 @property
[592]238 def minLandingFuel(self):
239 """Get the minimum acceptable amount of the landing fuel."""
240 return self._minLandingFuel
241
242 @property
243 def recommendedLandingFuel(self):
244 """Get the recommended amount of the landing fuel."""
245 return self._recommendedLandingFuel
246
247 @property
[8]248 def logger(self):
249 """Get the logger to use for the aircraft."""
250 return self._flight.logger
251
[139]252 @property
253 def state(self):
254 """Get the current aircraft state."""
255 return self._aircraftState
[241]256
257 @property
258 def speedInKnots(self):
259 """Indicate if the speed is in knots.
260
261 This default implementation returns True."""
262 return True
[304]263
264 @property
[635]265 def aglInFeet(self):
266 """Indicate if AGL altitudes are to be logged in feet.
267
268 This default implementation returns True."""
269 return True
270
271 @property
[304]272 def timestamp(self):
273 """Get the timestamp of the current state."""
274 return None if self._aircraftState is None \
275 else self._aircraftState.timestamp
[331]276
[384]277 @property
[512]278 def derateType(self):
279 """Get the derate type for this aircraft.
280
281 This default implementation returns DERATE_NONE."""
282 return DERATE_NONE
[384]283
[798]284 def setBookedFlight(self, bookedFlight):
285 """Update the aircraft based on the booked flight data (e.g. tail number).
286
287 This default implementation does nothing."""
288
[512]289 def getDerateLine(self, value):
290 """Get the log line for the given derate value.
291
292 It uses the the derate type and produces the standard message for
293 each. This children need not override it, although they can."""
294 dt = self.derateType
[384]295
[512]296 if dt==DERATE_BOEING:
297 return "Derate calculated by the pilot: %s %%" % \
298 ("-" if value is None else value,)
299 elif dt==DERATE_EPR:
300 return "EPR calculated by the pilot: %s" % \
301 ("-" if value is None else value,)
302 elif dt==DERATE_TUPOLEV:
303 return "Thrust setting calculated by the pilot: %s" % \
304 ("-" if value is None else
305 "nominal" if value==DERATE_TUPOLEV_NOMINAL else "takeoff",)
306 elif dt==DERATE_B462:
307 return "Derate setting: %s" % \
308 ("-" if value is None else "enabled" if value else "disabled",)
309 elif dt!=DERATE_NONE:
[919]310 print("mlx.acft.getDerateLine: invalid derate type: " + dt)
[384]311
312 return None
313
[11]314 def getFlapsSpeedLimit(self, flaps):
315 """Get the speed limit for the given flaps setting."""
316 return self.flapSpeedLimits[flaps] if flaps in self.flapSpeedLimits \
317 else None
318
[8]319 def modelChanged(self, timestamp, aircraftName, modelName):
[4]320 """Called when the simulator's aircraft changes."""
[369]321 self._name = aircraftName
322 self._modelName = modelName
323 if self._flight.stage is not None:
324 self._logNameAndModel(timestamp)
[4]325
326 def handleState(self, aircraftState):
[197]327 """Called when the state of the aircraft changes.
328
329 This is the function that the simulator calls directly with the new
330 state."""
[274]331 try:
332 config = self._flight.config
[197]333
[274]334 self._smoothedIAS.add(config.realIASSmoothingLength, aircraftState.ias)
335 aircraftState.smoothedIAS = self._smoothedIAS.get()
336
337 self._smoothedVS.add(config.realVSSmoothingLength, aircraftState.vs)
338 aircraftState.smoothedVS = self._smoothedVS.get()
[197]339
[274]340 for checker in self._checkers:
341 try:
342 checker.check(self._flight, self, self._flight.logger,
343 self._aircraftState, aircraftState)
344 except:
[919]345 print("Checker", checker, "failed", file=sys.stderr)
[274]346 traceback.print_exc()
[7]347
[274]348 self._flight.handleState(self._aircraftState, aircraftState)
[89]349
[274]350 self._maxVS = max(self._maxVS, aircraftState.vs)
351 self._minVS = min(self._minVS, aircraftState.vs)
352 except:
[919]353 print("Failed to handle the state", file=sys.stderr)
[274]354 traceback.print_exc()
355 finally:
356 self._aircraftState = aircraftState
[331]357
[8]358 def setStage(self, aircraftState, newStage):
359 """Set the given stage as the new one and do whatever should be
360 done."""
[369]361 if newStage==const.STAGE_BOARDING:
362 self._logNameAndModel(aircraftState.timestamp)
363
[624]364 oldStage = self._flight.stage
365
[9]366 if self._flight.setStage(aircraftState.timestamp, newStage):
367 if newStage==const.STAGE_PUSHANDTAXI:
368 self.logger.message(aircraftState.timestamp, "Block time start")
[274]369 self._flight.logFuel(aircraftState)
[331]370 self.logger.message(aircraftState.timestamp,
[313]371 "ZFW: %.2f kg" % (aircraftState.zfw))
[134]372 flight = self._flight
373 if flight.v1 is None or flight.vr is None or flight.v2 is None:
374 fs.sendMessage(const.MESSAGETYPE_HELP,
375 "Don't forget to set the takeoff V-speeds!",
376 5)
[9]377 elif newStage==const.STAGE_TAKEOFF:
[624]378 if oldStage == const.STAGE_RTO and self._flight.hasRTO:
379 rtoState = self._flight.rtoState
380 if (aircraftState.timestamp - rtoState.timestamp) < \
381 (self.brakeCoolTime * 60.0):
382 self.logger.fault("brakeCoolTime",
383 aircraftState.timestamp,
384 "Did not cool the brakes for at least %.f minutes after the RTO" % (self.brakeCoolTime,),
385 15.0)
[241]386 self.logger.message(aircraftState.timestamp,
387 "Flight time start")
[331]388 self.logger.message(aircraftState.timestamp,
[9]389 "Takeoff weight: %.0f kg, MTOW: %.0f kg" % \
390 (aircraftState.grossWeight, self.mtow))
[409]391 self._logQNH(aircraftState)
[9]392 self.logger.message(aircraftState.timestamp,
[333]393 "Wind %03.0f/%.0f" % \
[331]394 (aircraftState.windDirection,
[9]395 aircraftState.windSpeed))
[321]396 self._logRadios(aircraftState)
[345]397 self._logV1R2(aircraftState)
[384]398 self._logDerate(aircraftState)
[391]399 self._logTakeoffAntiIce(aircraftState)
[321]400 elif newStage==const.STAGE_DESCENT or newStage==const.STAGE_LANDING:
401 self._logRadios(aircraftState)
[409]402 if newStage==const.STAGE_LANDING:
403 self._logQNH(aircraftState)
[634]404 elif newStage==const.STAGE_GOAROUND:
[919]405 from .logger import Logger
[634]406 self._flight.handleFault("goaround",
407 aircraftState.timestamp,
408 "Go-around detected, please, explain!",
409 Logger.NO_SCORE)
[9]410 elif newStage==const.STAGE_TAXIAFTERLAND:
[184]411 flight = self._flight
412 bookedFlight = flight.bookedFlight
413 config = flight.config
[136]414 if config.onlineGateSystem and \
[215]415 flight.loggedIn and \
[184]416 not flight.entranceExam and \
[136]417 bookedFlight.arrivalICAO=="LHBP" and \
418 config.isMessageTypeFS(const.MESSAGETYPE_GATE_SYSTEM):
[134]419 self._flight.getFleet(callback = self._fleetRetrieved,
420 force = True)
[9]421 self.logger.message(aircraftState.timestamp, "Flight time end")
[274]422 self._flight.logFuel(aircraftState)
[591]423 if self._minLandingFuel is not None and \
424 aircraftState.totalFuel<self._minLandingFuel:
[597]425 self._flight.handleFault(self.__class__,
426 aircraftState.timestamp,
427 "The amount of the landing fuel is less than the minimum for this type: %ukgs (possible NO GO!)" %
428 (self._minLandingFuel,), 0)
[9]429 self.logger.message(aircraftState.timestamp,
430 "Landing weight: %.0f kg, MLW: %.0f" % \
431 (aircraftState.grossWeight, self.mlw))
432 self.logger.message(aircraftState.timestamp,
433 "Vertical speed range: %.0f..%.0f feet/min" % \
[12]434 (self._minVS, self._maxVS))
[359]435 # elif newStage==const.STAGE_PARKING:
436 # self.logger.message(aircraftState.timestamp, "Block time end")
[89]437 elif newStage==const.STAGE_END:
438 flightLength = self._flight.flightTimeEnd - self._flight.flightTimeStart
[359]439 self.logger.message(aircraftState.timestamp, "Block time end")
[89]440 self.logger.message(aircraftState.timestamp,
441 "Flight time: " +
442 util.getTimeIntervalString(flightLength))
443 self.logger.message(aircraftState.timestamp,
444 "Flown distance: %.2f NM" % \
[331]445 (self._flight.flownDistance,))
[89]446 blockLength = self._flight.blockTimeEnd - self._flight.blockTimeStart
447 self.logger.message(aircraftState.timestamp,
448 "Block time: " +
449 util.getTimeIntervalString(blockLength))
[8]450
[9]451 def prepareFlare(self):
452 """Called when it is detected that we will soon flare.
[8]453
454 On the first call, it should start monitoring some parameters more
455 closely to determine flare time."""
[9]456 self.flight.simulator.startFlare()
457
[331]458 def flareStarted(self, windSpeed, windDirection, visibility,
[9]459 flareStart, flareStartFS):
460 """Called when the flare has started."""
461 self.logger.message(self._aircraftState.timestamp, "The flare has begun")
462 self.logger.message(self._aircraftState.timestamp,
[333]463 "Wind %03.0f/%.0f" % \
[9]464 (windDirection, windSpeed))
465 self.logger.message(self._aircraftState.timestamp,
466 "Visibility: %.0f metres" % (visibility,))
[409]467 self._logQNH(self._aircraftState)
[101]468 self._logVRef()
[391]469 self._logLandingAntiIce(self._aircraftState)
[9]470 self.flight.flareStarted(flareStart, flareStartFS)
[134]471 fs.sendMessage(const.MESSAGETYPE_INFORMATION, "Flare-time", 3)
[331]472
[9]473 def flareFinished(self, flareEnd, flareEndFS, tdRate, tdRateCalculatedByFS,
474 ias, pitch, bank, heading):
475 """Called when the flare has finished."""
476 (flareTimeFromFS, flareTime) = self.flight.flareFinished(flareEnd,
[170]477 flareEndFS,
478 tdRate)
[9]479 self.logger.message(self._aircraftState.timestamp,
[153]480 "Flaretime: %.3f (from %s)" % \
[331]481 (flareTime,
[9]482 "the simulator" if flareTimeFromFS else "real time",))
483 self.logger.message(self._aircraftState.timestamp,
484 "Touchdown rate: %.0f feet/min" % (tdRate,))
485 self.logger.message(self._aircraftState.timestamp,
486 "Touchdown rate was calculated by the %s" % \
487 ("simulator" if tdRateCalculatedByFS else "logger",))
[241]488 flight = self._flight
[9]489 self.logger.message(self._aircraftState.timestamp,
[241]490 "Touchdown speed: %.0f %s" % \
491 (flight.speedFromKnots(ias),
492 flight.getEnglishSpeedUnit()))
[9]493 self.logger.message(self._aircraftState.timestamp,
494 "Touchdown pitch: %.1f degrees" % (pitch,))
495 self.logger.message(self._aircraftState.timestamp,
496 "Touchdown bank: %.1f degrees" % (bank,))
497 self.logger.message(self._aircraftState.timestamp,
498 "Touchdown heading: %03.0f degrees" % (heading,))
[331]499 self.logger.message(self._aircraftState.timestamp,
[340]500 "CG: %.1f%%" % \
[271]501 (self._aircraftState.cog*100.0,))
[8]502
[611]503 if abs(pitch)>self.maxTouchDownPitch:
504 self._flight.handleNoGo("TDPitch", self._aircraftState.timestamp,
505 "Touchdown pitch higher than aircraft maximum (%.2f)" % \
506 (self.maxTouchDownPitch,),
507 "TD TAILSTRIKE NO GO")
508
[8]509 def cancelFlare(self):
510 """Cancel flare, if it has started."""
[9]511 self.flight.simulator.cancelFlare()
[8]512
513 def checkFlightEnd(self, aircraftState):
514 """Check if the end of the flight has arrived.
515
516 This default implementation checks the N1 values, but for
517 piston-powered aircraft you need to check the RPMs."""
518 for n1 in aircraftState.n1:
519 if n1>=0.5: return False
520 return True
521
[101]522 def updateV1R2(self):
523 """Update the V1, Vr and V2 values from the flight, if the these values
524 have already been logged."""
525 if self._v1r2LineIndex is not None:
526 self._logV1R2()
527
[384]528 def updateDerate(self):
529 """Update the derate value from the flight, if the these values
530 have already been logged."""
531 if self._derateLineID is not None:
532 self._logDerate()
533
[391]534 def updateTakeoffAntiIce(self):
535 """Update the take-off anti-ice setting."""
536 if self._takeoffAntiIceLineID is not None:
537 self._logTakeoffAntiIce()
538
[211]539 def _appendLightsLoggers(self):
540 """Append the loggers needed for the lights.
541
542 This default implementation adds the loggers for the anti-collision
543 lights, the landing lights, the strobe lights and the NAV lights."""
544 self._checkers.append(checks.AnticollisionLightsLogger())
545 self._checkers.append(checks.LandingLightsLogger())
546 self._checkers.append(checks.StrobeLightsLogger())
547 self._checkers.append(checks.NavLightsLogger())
548
549 def _appendLightsCheckers(self):
550 """Append the checkers needed for the lights.
551
552 This default implementation adds the checkers for the anti-collision
553 lights, the landing lights, the strobe lights and the NAV lights."""
554 self._checkers.append(checks.AntiCollisionLightsChecker())
555 self._checkers.append(checks.LandingLightsChecker())
556 self._checkers.append(checks.NavLightsChecker())
557 self._checkers.append(checks.StrobeLightsChecker())
558
[241]559 def _speedToLog(self, speed):
560 """Convert the given speed (being either None or expressed in the
561 flight's speed unit into a string."""
562 if speed is None:
563 return "-"
564 else:
565 return str(speed) + " " + self._flight.getEnglishSpeedUnit()
566
[345]567 def _logV1R2(self, state = None):
[101]568 """Log the V1, Vr and V2 value either newly, or by updating the
569 corresponding line."""
[526]570 message = "Calc. TO speeds: V1: %s, VR: %s, V2: %s" % \
[241]571 (self._speedToLog(self._flight.v1),
572 self._speedToLog(self._flight.vr),
573 self._speedToLog(self._flight.v2))
[101]574
575 if self._v1r2LineIndex is None:
[345]576 if state is None:
577 state = self._aircraftState
[101]578 self._v1r2LineIndex = \
[345]579 self.logger.message(state.timestamp, message)
[101]580 else:
581 self.logger.updateLine(self._v1r2LineIndex, message)
582
[384]583 def _logDerate(self, state = None):
584 """Log the derate values either newly or by updating the corresponding
585 line."""
[512]586 dt = self.derateType
587 if dt==DERATE_NONE:
[384]588 return
589
[512]590 message = self.getDerateLine(self._flight.derate)
591 if message is not None:
592 if self._derateLineID is None:
593 if state is None:
594 state = self._aircraftState
595 self._derateLineID = \
596 self.logger.message(state.timestamp, message)
597 else:
598 self.logger.updateLine(self._derateLineID, message)
[384]599
[391]600 def _logTakeoffAntiIce(self, state = None):
601 """Log the take-off anti-ice setting either newly or by updating the
602 corresponding line."""
603 antiIceOn = self._flight.takeoffAntiIceOn
604 if state is not None:
605 antiIceOn = antiIceOn or state.antiIceOn is True
606 self._flight.takeoffAntiIceOn = antiIceOn
607
608 message = "Anti-ice was turned %s" % \
609 ("ON" if antiIceOn else "OFF")
610
611 if self._takeoffAntiIceLineID is None:
612 if state is None:
613 state = self._aircraftState
614 self._takeoffAntiIceLineID = \
615 self.logger.message(state.timestamp, message)
616 else:
617 self.logger.updateLine(self._takeoffAntiIceLineID, message)
618
[96]619 def updateVRef(self):
620 """Update the Vref value from the flight, if the Vref value has already
621 been logged."""
622 if self._vrefLineIndex is not None:
623 self._logVRef()
624
625 def _logVRef(self):
626 """Log the Vref value either newly, or by updating the corresponding
627 line."""
628 message = "VRef speed calculated by the pilot: %s" % \
[241]629 (self._speedToLog(self._flight.vref),)
[96]630 if self._vrefLineIndex is None:
631 self._vrefLineIndex = \
632 self.logger.message(self._aircraftState.timestamp, message)
633 else:
634 self.logger.updateLine(self._vrefLineIndex, message)
635
[391]636 def updateLandingAntiIce(self):
637 """Update the landing anti-ice setting."""
638 if self._landingAntiIceLineID is not None:
639 self._logLandingAntiIce()
640
641 def _logLandingAntiIce(self, state = None):
642 """Log the landing anti-ice setting either newly or by updating the
643 corresponding line."""
644 antiIceOn = self._flight.landingAntiIceOn
645 if state is not None:
646 antiIceOn = antiIceOn or state.antiIceOn is True
647 self._flight.landingAntiIceOn = antiIceOn
648
649 message = "Anti-ice was turned %s" % \
650 ("ON" if antiIceOn else "OFF")
651
652 if self._landingAntiIceLineID is None:
653 if state is None:
654 state = self._aircraftState
655 self._landingAntiIceLineID = \
656 self.logger.message(state.timestamp, message)
657 else:
658 self.logger.updateLine(self._landingAntiIceLineID, message)
659
[134]660 def _fleetRetrieved(self, fleet):
661 """Callback for the fleet retrieval result."""
662 if fleet is not None:
663 gateList = ""
664 occupiedGateNumbers = fleet.getOccupiedGateNumbers()
[619]665 for gate in gates.lhbpGates.gates:
666 if gate.isAvailable(gates.lhbpGates, occupiedGateNumbers):
[134]667 if gateList: gateList += ", "
[619]668 gateList += gate.number
[134]669 fs.sendMessage(const.MESSAGETYPE_GATE_SYSTEM,
670 "Free gates: " + gateList, 20)
[331]671
[134]672
[321]673 def _logRadios(self, aircraftState):
674 """Log the radios from the given aircraft state."""
675 flight = self._flight
676 logger = flight.logger
677
[366]678 self._ilsLogger.forceLog(flight, logger, aircraftState)
[321]679 self._nav1Logger.forceLog(flight, logger, aircraftState)
680 self._nav2Logger.forceLog(flight, logger, aircraftState)
[329]681 self._adf1Logger.forceLog(flight, logger, aircraftState)
682 self._adf2Logger.forceLog(flight, logger, aircraftState)
[321]683
[409]684 def _logQNH(self, aircraftState):
685 """Log the current QNH along with the altimeter setting."""
686 self.logger.message(aircraftState.timestamp,
687 "QNH: %.2f hPa, altimeter: %.2f hPa" % \
688 (aircraftState.qnh, aircraftState.altimeter))
689
[369]690 def _logNameAndModel(self, timestamp):
691 """Log the aircraft's name and model with taking the timestamp from the
692 given state."""
693 self._flight.logger.message(timestamp,
694 "Aircraft: name='%s', model='%s'" % \
695 (self._name, self._modelName))
696
[4]697#---------------------------------------------------------------------------------------
[7]698
699class Boeing737(Aircraft):
700 """Base class for the various aircraft in the Boeing 737 family.
701
702 The aircraft type-specific values in the aircraft state have the following
703 structure:
[140]704 - fuel: left, centre, right
[7]705 - n1: left, right
[331]706 - reverser: left, right"""
[592]707 def __init__(self, flight, minLandingFuel = 2500,
708 recommendedLandingFuel = 3500):
709 super(Boeing737, self).__init__(flight,
710 minLandingFuel = minLandingFuel,
711 recommendedLandingFuel =
712 recommendedLandingFuel)
[95]713
[9]714 self.gearSpeedLimit = 270
715 self.flapSpeedLimits = { 1 : 260,
716 2 : 260,
717 5 : 250,
718 10 : 210,
719 15 : 200,
720 25 : 190,
721 30 : 175,
722 40 : 162 }
[7]723
[384]724 @property
[512]725 def derateType(self):
726 """Get the derate type for this type."""
727 return DERATE_BOEING
[384]728
[7]729#---------------------------------------------------------------------------------------
730
731class B736(Boeing737):
732 """Boeing 737-600 aircraft."""
[861]733 dow = 38307
734
[8]735 def __init__(self, flight):
736 super(B736, self).__init__(flight)
[9]737 self.mtow = 58328
738 self.mlw = 54657
739 self.mzfw = 51482
[611]740 self.maxTakeOffPitch = 16.2
741 self.maxTouchDownPitch = 14.7
[709]742 self.simBriefData = SimBriefData(["250/280/78"],
743 ["CI", "M75", "M78", "M79", "M80", "LRC"],
744 ["78/280/250"])
[7]745
746#---------------------------------------------------------------------------------------
747
748class B737(Boeing737):
749 """Boeing 737-700 aircraft."""
[861]750 dow = 39250
751
[8]752 def __init__(self, flight):
753 super(B737, self).__init__(flight)
[9]754 self.mtow = 61410
755 self.mlw = 58059
756 self.mzfw = 54657
[611]757 self.maxTakeOffPitch = 14.7
758 self.maxTouchDownPitch = 13.2
[709]759 self.simBriefData = SimBriefData(["250/280/78"],
760 ["CI", "M75", "M78", "M79", "M80", "LRC"],
761 ["78/280/250", "78/250/250"])
[7]762
763#---------------------------------------------------------------------------------------
764
765class B738(Boeing737):
766 """Boeing 737-800 aircraft."""
[861]767 dow = 42690
768
[8]769 def __init__(self, flight):
770 super(B738, self).__init__(flight)
[797]771 self.mtow = 71791
[9]772 self.mlw = 65317
773 self.mzfw = 61688
[611]774 self.maxTakeOffPitch = 11
775 self.maxTouchDownPitch = 9.5
[709]776 self.simBriefData = SimBriefData(["250/280/78"],
777 ["CI", "M76", "M78", "M79", "M80", "LRC"],
778 ["78/280/250", "78/250/250"])
[9]779
780#---------------------------------------------------------------------------------------
781
782class B738Charter(B738):
783 """Boeing 737-800 aircraft used for charters."""
784 def __init__(self, flight):
785 super(B738Charter, self).__init__(flight)
786 self.mtow = 77791
[709]787 self.simBriefData = SimBriefData(["AUTO"],
788 ["280/M74"],
789 ["AUTO"])
[7]790
791#---------------------------------------------------------------------------------------
792
[591]793class Boeing737CL(Boeing737):
794 """Base class for the various aircraft in the Boeing 737 Classic family."""
795 def __init__(self, flight):
[592]796 super(Boeing737CL, self).__init__(flight, minLandingFuel = 3500,
797 recommendedLandingFuel = None)
[591]798
799#---------------------------------------------------------------------------------------
800
[790]801class B732(Boeing737CL):
802 """Boeing 737-200 aircraft."""
[861]803 dow = 27646
804
[790]805 def __init__(self, flight):
806 super(B732, self).__init__(flight)
[796]807 self.mtow = 52390
808 self.mlw = 46720
809 self.mzfw = 43091
810 self.maxTakeOffPitch = 15.5
811 self.maxTouchDownPitch = 15.5
[790]812
813#---------------------------------------------------------------------------------------
814
[591]815class B733(Boeing737CL):
[7]816 """Boeing 737-300 aircraft."""
[861]817 dow = 32900
818
[8]819 def __init__(self, flight):
820 super(B733, self).__init__(flight)
[797]821 self.mtow = 56472
822 self.mlw = 51710
823 self.mzfw = 47625
[611]824 self.maxTakeOffPitch = 13.4
825 self.maxTouchDownPitch = 12.0
[7]826
827#---------------------------------------------------------------------------------------
828
[591]829class B734(Boeing737CL):
[7]830 """Boeing 737-400 aircraft."""
[8]831 def __init__(self, flight):
832 super(B734, self).__init__(flight)
[797]833 self.dow = 35100
834 self.mtow = 62822
835 self.mlw = 54885
836 self.mzfw = 51256
[611]837 self.maxTakeOffPitch = 11.4
838 self.maxTouchDownPitch = 10
[7]839
840#---------------------------------------------------------------------------------------
841
[591]842class B735(Boeing737CL):
[7]843 """Boeing 737-500 aircraft."""
[861]844 dow = 31900
845
[8]846 def __init__(self, flight):
847 super(B735, self).__init__(flight)
[797]848 self.mtow = 62823
849 self.mlw = 49895
850 self.mzfw = 46720
[611]851 self.maxTakeOffPitch = 14.7
852 self.maxTouchDownPitch = 13.2
[7]853
854#---------------------------------------------------------------------------------------
855
856class DH8D(Aircraft):
857 """Bombardier Dash-8 Q400 aircraft.
858
859 The aircraft type-specific values in the aircraft state have the following
860 structure:
[140]861 - fuel: left, right
[7]862 - n1: left, right
863 - reverser: left, right."""
[861]864 dow = 18508
[140]865
[8]866 def __init__(self, flight):
[591]867 super(DH8D, self).__init__(flight, minLandingFuel = 2000)
[797]868 self.mtow = 29574
869 self.mlw = 28123
870 self.mzfw = 26308
[9]871 self.gearSpeedLimit = 215
872 self.flapSpeedLimits = { 5 : 200,
873 10 : 181,
874 15 : 172,
875 35 : 158 }
[611]876 self.maxTakeOffPitch = 8.0
877 self.maxTouchDownPitch = 7.0
[709]878 self.simBriefData = SimBriefData(["I-900", "II-900", "III-900",
879 "I-850", "II-850", "III-850"],
880 ["MCR", "ISC", "LRC", "HSC"],
881 ["I-850", "II-850", "III-850"])
[9]882
[7]883#---------------------------------------------------------------------------------------
884
885class Boeing767(Aircraft):
886 """Base class for the various aircraft in the Boeing 767 family.
887
888 The aircraft type-specific values in the aircraft state have the following
889 structure:
[140]890 - fuel: left, centre, right
[7]891 - n1: left, right
892 - reverser: left, right"""
[140]893
[612]894 def __init__(self, flight, minLandingFuel = 7000):
[591]895 super(Boeing767, self).__init__(flight, minLandingFuel = minLandingFuel)
[9]896 self.gearSpeedLimit = 270
897 self.flapSpeedLimits = { 1 : 255,
898 5 : 235,
899 10 : 215,
900 20 : 215,
901 25 : 185,
902 30 : 175 }
[7]903
[384]904 @property
[512]905 def derateType(self):
906 """Get the derate type for this type."""
907 return DERATE_BOEING
[384]908
[7]909#---------------------------------------------------------------------------------------
910
911class B762(Boeing767):
912 """Boeing 767-200 aircraft."""
[861]913 dow = 84507
914
[8]915 def __init__(self, flight):
916 super(B762, self).__init__(flight)
[797]917 self.mtow = 159210
[9]918 self.mlw = 126098
919 self.mzfw = 114758
[611]920 self.maxTakeOffPitch = 13.1
921 self.maxTouchDownPitch = 11.6
[7]922
923#---------------------------------------------------------------------------------------
924
925class B763(Boeing767):
926 """Boeing 767-300 aircraft."""
[861]927 dow = 91311
928
[8]929 def __init__(self, flight):
[331]930 super(B763, self).__init__(flight)
[9]931 self.mtow = 181436
932 self.mlw = 137892
[797]933 self.mzfw = 114758
[611]934 self.maxTakeOffPitch = 9.6
935 self.maxTouchDownPitch = 8.1
[709]936 self.simBriefData = SimBriefData(["250/290/78"],
937 ["CI", "M76", "M78", "M80", "M82", "M84", "LRC"],
938 ["78/290/250"])
[7]939
[799]940 def setBookedFlight(self, bookedFlight):
941 """Update the aircraft based on the booked flight data (e.g. tail number)."""
942 if bookedFlight.tailNumber=="HA-LHD":
943 self.mtow = 159210
944 self.mlw = 126098
945
[7]946#---------------------------------------------------------------------------------------
947
948class CRJ2(Aircraft):
949 """Bombardier CRJ-200 aircraft.
950
951 The aircraft type-specific values in the aircraft state have the following
952 structure:
[140]953 - fuel: left, centre, right
[7]954 - n1: left, right
955 - reverser: left, right."""
[861]956 dow = 14549
957
[8]958 def __init__(self, flight):
[591]959 super(CRJ2, self).__init__(flight, minLandingFuel = 1000)
[9]960 self.mtow = 22995
961 self.mlw = 21319
962 self.mzfw = 19958
963 self.gearSpeedLimit = 240
964 self.flapSpeedLimits = { 8 : 260,
965 20 : 220,
966 30 : 190,
967 45 : 175 }
[611]968 self.maxTakeOffPitch = 18.0
969 self.maxTouchDownPitch = 18.0
[709]970 self.simBriefData = SimBriefData(["250/70", "290/74"],
971 ["CI", "LRC", "M70", "M72", "M74", "M77", "M80"],
972 ["74/290/250", "77/320/250"])
[7]973
974#---------------------------------------------------------------------------------------
975
976class F70(Aircraft):
977 """Fokker 70 aircraft.
978
979 The aircraft type-specific values in the aircraft state have the following
980 structure:
[140]981 - fuel: left, centre, right
[7]982 - n1: left, right
983 - reverser: left, right."""
[861]984 dow = 24283
985
[8]986 def __init__(self, flight):
[591]987 super(F70, self).__init__(flight, minLandingFuel = 1900)
[9]988 self.mtow = 38100 # FIXME: differentiate by registration number,
989 # MTOW of HA-LMF: 41955
990 self.mlw = 36740
991 self.mzfw = 32655
992 self.gearSpeedLimit = 200
993 self.flapSpeedLimits = { 8 : 250,
994 15 : 220,
995 25 : 220,
996 42 : 180 }
[360]997 self.reverseMinSpeed = 50
[611]998 self.maxTakeOffPitch = 16.0
999 self.maxTouchDownPitch = 16.0
[7]1000
[384]1001 @property
[512]1002 def derateType(self):
1003 """Get the derate type for this type."""
1004 return DERATE_EPR
[384]1005
[7]1006#---------------------------------------------------------------------------------------
1007
1008class DC3(Aircraft):
1009 """Lisunov Li-2 (DC-3) aircraft.
1010
1011 The aircraft type-specific values in the aircraft state have the following
1012 structure:
[140]1013 - fuel: left aux, left, right, right aux
[7]1014 - rpm: left, right
1015 - reverser: left, right."""
[861]1016 dow = 8627
1017
[8]1018 def __init__(self, flight):
1019 super(DC3, self).__init__(flight)
[9]1020 self.mtow = 11884
1021 self.mlw = 11793
1022 self.mzfw = 11780
1023 self.gearSpeedLimit = 148
1024 self.flapSpeedLimits = { 15 : 135,
1025 30 : 99,
1026 45 : 97 }
[8]1027
1028 def _checkFlightEnd(self, aircraftState):
1029 """Check if the end of the flight has arrived.
1030
1031 This implementation checks the RPM values to be 0."""
1032 for rpm in aircraftState.rpm:
[29]1033 if rpm>0: return False
1034 return True
[7]1035
1036#---------------------------------------------------------------------------------------
1037
1038class T134(Aircraft):
1039 """Tupolev Tu-134 aircraft.
1040
1041 The aircraft type-specific values in the aircraft state have the following
1042 structure:
[140]1043 - fuel: left tip, left aux, centre, right aux, right tip, external 1,
[7]1044 external 2
1045 - n1: left, right
1046 - reverser: left, right."""
[861]1047 dow = 29500
1048
[8]1049 def __init__(self, flight):
[591]1050 super(T134, self).__init__(flight, minLandingFuel = 3000)
[210]1051 self.mtow = 49000
[9]1052 self.mlw = 43000
1053 self.mzfw = 38500
1054 self.gearSpeedLimit = 216
[210]1055 self.flapSpeedLimits = { 10 : 450,
1056 20 : 400,
1057 30 : 300 }
[360]1058 self.reverseMinSpeed = 50
[7]1059
[644]1060 self.hasStrobeLight = False
1061
[611]1062 self.maxTakeOffPitch = 16.0
1063 self.maxTouchDownPitch = 16.0
1064
[241]1065 @property
[512]1066 def derateType(self):
1067 """Get the derate type for this type."""
1068 return DERATE_TUPOLEV
[384]1069
1070 @property
[241]1071 def speedInKnots(self):
1072 """Indicate if the speed is in knots."""
1073 return False
[331]1074
[635]1075 @property
1076 def aglInFeet(self):
1077 """Indicate if AGL altituedes are in feet."""
1078 return False
1079
[211]1080 def _appendLightsLoggers(self):
1081 """Append the loggers needed for the lights."""
1082 self._checkers.append(checks.AnticollisionLightsLogger())
1083 self._checkers.append(checks.LandingLightsLogger())
1084 self._checkers.append(checks.NavLightsLogger())
1085
1086 def _appendLightsCheckers(self):
1087 """Append the checkers needed for the lights."""
1088 self._checkers.append(checks.TupolevAntiCollisionLightsChecker())
[631]1089 self._checkers.append(checks.TupolevLandingLightsChecker())
[211]1090 self._checkers.append(checks.LandingLightsChecker())
1091 self._checkers.append(checks.NavLightsChecker())
1092
[7]1093#---------------------------------------------------------------------------------------
1094
1095class T154(Aircraft):
1096 """Tupolev Tu-154 aircraft.
1097
1098 The aircraft type-specific values in the aircraft state have the following
1099 structure:
[140]1100 - fuel: left aux, left, centre, centre 2, right, right aux
[7]1101 - n1: left, centre, right
1102 - reverser: left, right"""
[888]1103 dow = 53259
[861]1104
[8]1105 def __init__(self, flight):
[591]1106 super(T154, self).__init__(flight, minLandingFuel = 5000)
[9]1107 self.mtow = 98000
1108 self.mlw = 78000
1109 self.mzfw = 72000
1110 self.gearSpeedLimit = 216
1111 self.flapSpeedLimits = { 15 : 227,
1112 28 : 194,
1113 45 : 162 }
[360]1114 self.reverseMinSpeed = 50
[9]1115
[644]1116 self.hasStrobeLight = False
1117
[611]1118 self.maxTakeOffPitch = 16.0
1119 self.maxTouchDownPitch = 16.0
[709]1120 self.simBriefData = SimBriefData(["AUTO"],
1121 ["300/M80"],
1122 ["AUTO"])
[611]1123
[241]1124 @property
1125 def speedInKnots(self):
1126 """Indicate if the speed is in knots."""
1127 return False
[331]1128
[384]1129 @property
[635]1130 def aglInFeet(self):
1131 """Indicate if AGL altituedes are in feet."""
1132 return False
1133
1134 @property
[512]1135 def derateType(self):
1136 """Get the derate type for this type."""
1137 return DERATE_TUPOLEV
[384]1138
[799]1139 def setBookedFlight(self, bookedFlight):
1140 """Update the aircraft based on the booked flight data (e.g. tail number)."""
1141 if bookedFlight.tailNumber in ["HA-LCM", "HA-LCN", "HA-LCO", "HA-LCP",
1142 "HA-LCR", "HA-LCU", "HA-LCV"]:
1143 self.mtow = 100000
1144 self.mlw = 80000
[904]1145 elif bookedFlight.tailNumber=="HA-LCX":
1146 self.mtow = 100000
1147 self.mlw = 80000
1148 self.mzfw = 74000
1149
1150 self.flapSpeedLimits = { 15 : 227,
1151 28 : 194,
[905]1152 36 : 178,
[904]1153 45 : 162 }
[799]1154
[211]1155 def _appendLightsLoggers(self):
1156 """Append the loggers needed for the lights."""
1157 self._checkers.append(checks.AnticollisionLightsLogger())
1158 self._checkers.append(checks.LandingLightsLogger())
1159 self._checkers.append(checks.NavLightsLogger())
1160
1161 def _appendLightsCheckers(self):
1162 """Append the checkers needed for the lights."""
1163 self._checkers.append(checks.AntiCollisionLightsChecker())
[631]1164 self._checkers.append(checks.TupolevLandingLightsChecker())
[211]1165 self._checkers.append(checks.LandingLightsChecker())
1166 self._checkers.append(checks.NavLightsChecker())
1167
[539]1168#---------------------------------------------------------------------------------------
1169
1170class YK40(Aircraft):
1171 """Yakovlev Yak-40 aircraft.
1172
1173 The aircraft type-specific values in the aircraft state have the following
1174 structure:
1175 - fuel: left, right
1176 - n1: left, right
1177 - reverser: left, right"""
[861]1178 dow = 9400
1179
[539]1180 def __init__(self, flight):
1181 super(YK40, self).__init__(flight)
1182 self.mtow = 17200
1183 self.mlw = 16800
1184 self.mzfw = 12100
1185 self.gearSpeedLimit = 165
1186 self.flapSpeedLimits = { 20 : 165,
1187 35 : 135 }
1188
[644]1189 self.hasStrobeLight = False
1190
[539]1191 @property
1192 def speedInKnots(self):
1193 """Indicate if the speed is in knots."""
1194 return False
1195
1196 @property
[635]1197 def aglInFeet(self):
1198 """Indicate if AGL altituedes are in feet."""
1199 return False
1200
1201 @property
[539]1202 def derateType(self):
1203 """Get the derate type for this type."""
1204 return DERATE_TUPOLEV
1205
1206 def _appendLightsLoggers(self):
1207 """Append the loggers needed for the lights."""
1208 self._checkers.append(checks.AnticollisionLightsLogger())
1209 self._checkers.append(checks.LandingLightsLogger())
1210 self._checkers.append(checks.NavLightsLogger())
1211
1212 def _appendLightsCheckers(self):
1213 """Append the checkers needed for the lights."""
1214 self._checkers.append(checks.AntiCollisionLightsChecker())
1215 self._checkers.append(checks.LandingLightsChecker())
1216 self._checkers.append(checks.NavLightsChecker())
[403]1217
[7]1218#---------------------------------------------------------------------------------------
1219
[443]1220class B462(Aircraft):
1221 """British Aerospace BAe-146 aircraft.
1222
1223 The aircraft type-specific values in the aircraft state have the following
1224 structure:
1225 - fuel: left, centre, right
1226 - n1: left outer, left inner, right inner, right outer
1227 - reverser: empty (the plane has no reversers)"""
[861]1228 dow = 25706
1229
[443]1230 def __init__(self, flight):
1231 super(B462, self).__init__(flight)
1232 self.mtow = 43998
1233 self.mlw = 38599
1234 self.mzfw = 33792
1235 self.gearSpeedLimit = 210
1236 self.flapSpeedLimits = { 18 : 217,
1237 24 : 180,
1238 30 : 170,
1239 33 : 150 }
1240
[445]1241 @property
[512]1242 def derateType(self):
1243 """Get the derate type for this type."""
1244 return DERATE_B462
[445]1245
[443]1246#---------------------------------------------------------------------------------------
1247
[274]1248mostFuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_EXTERNAL1,
1249 const.FUELTANK_LEFT_AUX,
1250 const.FUELTANK_CENTRE,
1251 const.FUELTANK_RIGHT_AUX,
1252 const.FUELTANK_EXTERNAL2, const.FUELTANK_RIGHT_TIP]
[141]1253
1254#---------------------------------------------------------------------------------------
1255
[191]1256_classes = { const.AIRCRAFT_B736 : B736,
1257 const.AIRCRAFT_B737 : B737,
1258 const.AIRCRAFT_B738 : B738,
1259 const.AIRCRAFT_B738C : B738Charter,
[790]1260 const.AIRCRAFT_B732 : B732,
[191]1261 const.AIRCRAFT_B733 : B733,
1262 const.AIRCRAFT_B734 : B734,
1263 const.AIRCRAFT_B735 : B735,
1264 const.AIRCRAFT_DH8D : DH8D,
1265 const.AIRCRAFT_B762 : B762,
1266 const.AIRCRAFT_B763 : B763,
1267 const.AIRCRAFT_CRJ2 : CRJ2,
1268 const.AIRCRAFT_F70 : F70,
1269 const.AIRCRAFT_DC3 : DC3,
1270 const.AIRCRAFT_T134 : T134,
1271 const.AIRCRAFT_T154 : T154,
[443]1272 const.AIRCRAFT_YK40 : YK40,
1273 const.AIRCRAFT_B462 : B462 }
[8]1274
1275#---------------------------------------------------------------------------------------
[197]1276
[862]1277def getClass(aircraftType):
1278 """Get the class representing the given aircraft types"""
1279 return _classes[aircraftType]
1280
1281#---------------------------------------------------------------------------------------
1282
[197]1283if __name__ == "__main__":
1284 value = SmoothedValue()
1285
[919]1286 print("Adding 1, 12.0")
[197]1287 value.add(1, 12.0)
[919]1288 print(value.get())
[197]1289
[919]1290 print("Adding 1, 15.0")
[197]1291 value.add(1, 15.0)
[919]1292 print(value.get())
[197]1293
[919]1294 print("Adding 2, 18.0")
[197]1295 value.add(2, 18.0)
[919]1296 print(value.get())
[197]1297
[919]1298 print("Adding 2, 20.0")
[197]1299 value.add(2, 20.0)
[919]1300 print(value.get())
[197]1301
[919]1302 print("Adding 5, 22.0")
[197]1303 value.add(5, 22.0)
[919]1304 print(value.get())
[197]1305
[919]1306 print("Adding 5, 25.0")
[197]1307 value.add(5, 25.0)
[919]1308 print(value.get())
[197]1309
[919]1310 print("Adding 5, 29.0")
[197]1311 value.add(5, 29.0)
[919]1312 print(value.get())
[197]1313
[919]1314 print("Adding 5, 21.0")
[197]1315 value.add(5, 21.0)
[919]1316 print(value.get())
[197]1317
[919]1318 print("Adding 5, 26.0")
[197]1319 value.add(5, 26.0)
[919]1320 print(value.get())
[197]1321
[919]1322 print("Adding 2, 30.0")
[197]1323 value.add(2, 30.0)
[919]1324 print(value.get())
[197]1325
[919]1326 print("Adding 2, 55.0")
[197]1327 value.add(2, 55.0)
[919]1328 print(value.get())
[197]1329
1330#---------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.