source: src/mlx/acft.py@ 367:ecebdd53757b

Last change on this file since 367:ecebdd53757b was 366:21db3f9653ce, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support for the ILS frequency, and made use of it in case of the DA F70 model (#115)

File size: 33.3 KB
Line 
1
2import const
3import checks
4import fs
5import util
6
7import sys
8import time
9import traceback
10
11from collections import deque
12
13#---------------------------------------------------------------------------------------
14
15## @package mlx.acft
16#
17# The simulator-independent aircraft classes.
18#
19# This module contains the aircraft classes that contain some general data
20# about each aircraft type in the MAVA Fleet. The base class, \ref Aircraft
21# also implements some parts of the logging and traces some data. The classes
22# are also responsible for creating the \ref mlx.checks "checkers". Most of
23# them are created by the \ref Aircraft class' constructor, but there can be
24# type-specific differences. For example the lights are different for different
25# types, so there is a \ref Aircraft._appendLightsLoggers "function" which can
26# be reimplemented in child classes, if needed. This class maintains also the
27# \ref SmoothedValue "smoothed values" of the IAS and the VS and set these
28# values in the \ref mlx.fs.AircraftState "aircraft state" when it is received
29# from the simulator.
30
31#---------------------------------------------------------------------------------------
32
33class SmoothedValue(object):
34 """A smoothed value."""
35 def __init__(self):
36 """Construct the value."""
37 self._deque = deque()
38 self._sum = 0
39
40 def add(self, length, value):
41 """Add the given value and smooth with the given length."""
42 dequeLength = len(self._deque)
43 while dequeLength>=length:
44 self._sum -= self._deque.popleft()
45 dequeLength -= 1
46
47 self._sum += value
48 self._deque.append(value)
49
50 def get(self):
51 """Get the average."""
52 return self._sum / len(self._deque)
53
54#---------------------------------------------------------------------------------------
55
56class Aircraft(object):
57 """Base class for aircraft."""
58 @staticmethod
59 def create(flight):
60 """Create an aircraft instance for the type in the given flight."""
61 return _classes[flight.aircraftType](flight)
62
63 def __init__(self, flight):
64 """Construct the aircraft for the given type."""
65 self._flight = flight
66 self._aircraftState = None
67
68 self._maxVS = -10000.0
69 self._minVS = 10000.0
70
71 self._v1r2LineIndex = None
72 self._vrefLineIndex = None
73
74 self.humanWeight = 82.0
75
76 self.reverseMinSpeed = 60
77
78 self._checkers = []
79
80 config = flight.config
81 # Loggers
82
83 self._checkers.append(checks.StageChecker())
84 self._checkers.append(checks.TakeOffLogger())
85
86 self._checkers.append(checks.AltimeterLogger())
87
88 self._ilsLogger = checks.ILSLogger()
89 self._checkers.append(self._ilsLogger)
90 self._nav1Logger = checks.NAV1Logger()
91 self._checkers.append(self._nav1Logger)
92 self._nav2Logger = checks.NAV2Logger()
93 self._checkers.append(self._nav2Logger)
94
95 self._adf1Logger = checks.ADF1Logger()
96 self._checkers.append(self._adf1Logger)
97 self._adf2Logger = checks.ADF2Logger()
98 self._checkers.append(self._adf2Logger)
99
100 self._checkers.append(checks.SquawkLogger())
101
102 self._appendLightsLoggers()
103
104 self._checkers.append(checks.FlapsLogger())
105
106 self._checkers.append(checks.GearsLogger())
107 self._checkers.append(checks.CruiseSpeedLogger())
108 self._checkers.append(checks.SpoilerLogger())
109 self._checkers.append(checks.APLogger())
110
111 if config.isMessageTypeFS(const.MESSAGETYPE_VISIBILITY):
112 self._checkers.append(checks.VisibilityChecker())
113
114 # FIXME: we should have a central data model object, and not collect
115 # the data from the GUI. However, some pieces of data (e.g. V-speeds,
116 # etc. that is entered into the GUI) *should* be a part of the GUI and
117 # queried from it, so the model should have a reference to the GUI as
118 # well and access such data via the GUI!
119 if config.onlineACARS and flight.loggedIn and not flight.entranceExam:
120 self._checkers.append(checks.ACARSSender(flight._gui))
121
122 # Fault checkers
123
124 self._appendLightsCheckers()
125
126 self._checkers.append(checks.TransponderChecker())
127
128 self._checkers.append(checks.BankChecker())
129
130 self._checkers.append(checks.FlapsRetractChecker())
131 self._checkers.append(checks.FlapsSpeedLimitChecker())
132
133 self._checkers.append(checks.GearsDownChecker())
134 self._checkers.append(checks.GearSpeedLimitChecker())
135
136 self._checkers.append(checks.GLoadChecker())
137
138 self._checkers.append(checks.MLWChecker())
139 self._checkers.append(checks.MTOWChecker())
140 self._checkers.append(checks.MZFWChecker())
141 self._checkers.append(checks.PayloadChecker())
142
143 self._appendSpeedChecker()
144 self._checkers.append(checks.VSChecker())
145
146 timeout = 5.0 + config.realIASSmoothingLength - 1
147 self._checkers.append(checks.OverspeedChecker(timeout = timeout))
148
149 self._checkers.append(checks.StallChecker())
150
151 self._checkers.append(checks.PitotChecker())
152
153 self._checkers.append(checks.ReverserChecker())
154
155 if flight.aircraftType is not None and config.enableApproachCallouts:
156 approachCallouts = flight.config.getApproachCallouts(flight.aircraftType)
157 if approachCallouts:
158 self._checkers.append(checks.ApproachCalloutsPlayer(approachCallouts))
159
160 self._smoothedIAS = SmoothedValue()
161 self._smoothedVS = SmoothedValue()
162
163 @property
164 def type(self):
165 """Get the type of the aircraft."""
166 return self._flight.aircraftType
167
168 @property
169 def flight(self):
170 """Get the flight the aircraft belongs to."""
171 return self._flight
172
173 @property
174 def logger(self):
175 """Get the logger to use for the aircraft."""
176 return self._flight.logger
177
178 @property
179 def state(self):
180 """Get the current aircraft state."""
181 return self._aircraftState
182
183 @property
184 def speedInKnots(self):
185 """Indicate if the speed is in knots.
186
187 This default implementation returns True."""
188 return True
189
190 @property
191 def timestamp(self):
192 """Get the timestamp of the current state."""
193 return None if self._aircraftState is None \
194 else self._aircraftState.timestamp
195
196 def getFlapsSpeedLimit(self, flaps):
197 """Get the speed limit for the given flaps setting."""
198 return self.flapSpeedLimits[flaps] if flaps in self.flapSpeedLimits \
199 else None
200
201 def modelChanged(self, timestamp, aircraftName, modelName):
202 """Called when the simulator's aircraft changes."""
203 self._flight.logger.message(timestamp,
204 "Aircraft: name='%s', model='%s'" % \
205 (aircraftName, modelName))
206
207 def handleState(self, aircraftState):
208 """Called when the state of the aircraft changes.
209
210 This is the function that the simulator calls directly with the new
211 state."""
212 try:
213 config = self._flight.config
214
215 self._smoothedIAS.add(config.realIASSmoothingLength, aircraftState.ias)
216 aircraftState.smoothedIAS = self._smoothedIAS.get()
217
218 self._smoothedVS.add(config.realVSSmoothingLength, aircraftState.vs)
219 aircraftState.smoothedVS = self._smoothedVS.get()
220
221 for checker in self._checkers:
222 try:
223 checker.check(self._flight, self, self._flight.logger,
224 self._aircraftState, aircraftState)
225 except:
226 print >> sys.stderr, "Checker", checker, "failed"
227 traceback.print_exc()
228
229 self._flight.handleState(self._aircraftState, aircraftState)
230
231 self._maxVS = max(self._maxVS, aircraftState.vs)
232 self._minVS = min(self._minVS, aircraftState.vs)
233 except:
234 print >> sys.stderr, "Failed to handle the state"
235 traceback.print_exc()
236 finally:
237 self._aircraftState = aircraftState
238
239 def setStage(self, aircraftState, newStage):
240 """Set the given stage as the new one and do whatever should be
241 done."""
242 if self._flight.setStage(aircraftState.timestamp, newStage):
243 if newStage==const.STAGE_PUSHANDTAXI:
244 self.logger.message(aircraftState.timestamp, "Block time start")
245 self._flight.logFuel(aircraftState)
246 self.logger.message(aircraftState.timestamp,
247 "ZFW: %.2f kg" % (aircraftState.zfw))
248 flight = self._flight
249 if flight.v1 is None or flight.vr is None or flight.v2 is None:
250 fs.sendMessage(const.MESSAGETYPE_HELP,
251 "Don't forget to set the takeoff V-speeds!",
252 5)
253 elif newStage==const.STAGE_TAKEOFF:
254 self.logger.message(aircraftState.timestamp,
255 "Flight time start")
256 self.logger.message(aircraftState.timestamp,
257 "Takeoff weight: %.0f kg, MTOW: %.0f kg" % \
258 (aircraftState.grossWeight, self.mtow))
259 self.logger.message(aircraftState.timestamp,
260 "Wind %03.0f/%.0f" % \
261 (aircraftState.windDirection,
262 aircraftState.windSpeed))
263 self._logRadios(aircraftState)
264 self._logV1R2(aircraftState)
265 elif newStage==const.STAGE_DESCENT or newStage==const.STAGE_LANDING:
266 self._logRadios(aircraftState)
267 elif newStage==const.STAGE_TAXIAFTERLAND:
268 flight = self._flight
269 bookedFlight = flight.bookedFlight
270 config = flight.config
271 if config.onlineGateSystem and \
272 flight.loggedIn and \
273 not flight.entranceExam and \
274 bookedFlight.arrivalICAO=="LHBP" and \
275 config.isMessageTypeFS(const.MESSAGETYPE_GATE_SYSTEM):
276 self._flight.getFleet(callback = self._fleetRetrieved,
277 force = True)
278 self.logger.message(aircraftState.timestamp, "Flight time end")
279 self._flight.logFuel(aircraftState)
280 self.logger.message(aircraftState.timestamp,
281 "Landing weight: %.0f kg, MLW: %.0f" % \
282 (aircraftState.grossWeight, self.mlw))
283 self.logger.message(aircraftState.timestamp,
284 "Vertical speed range: %.0f..%.0f feet/min" % \
285 (self._minVS, self._maxVS))
286 # elif newStage==const.STAGE_PARKING:
287 # self.logger.message(aircraftState.timestamp, "Block time end")
288 elif newStage==const.STAGE_END:
289 flightLength = self._flight.flightTimeEnd - self._flight.flightTimeStart
290 self.logger.message(aircraftState.timestamp, "Block time end")
291 self.logger.message(aircraftState.timestamp,
292 "Flight time: " +
293 util.getTimeIntervalString(flightLength))
294 self.logger.message(aircraftState.timestamp,
295 "Flown distance: %.2f NM" % \
296 (self._flight.flownDistance,))
297 blockLength = self._flight.blockTimeEnd - self._flight.blockTimeStart
298 self.logger.message(aircraftState.timestamp,
299 "Block time: " +
300 util.getTimeIntervalString(blockLength))
301
302 def prepareFlare(self):
303 """Called when it is detected that we will soon flare.
304
305 On the first call, it should start monitoring some parameters more
306 closely to determine flare time."""
307 self.flight.simulator.startFlare()
308
309 def flareStarted(self, windSpeed, windDirection, visibility,
310 flareStart, flareStartFS):
311 """Called when the flare has started."""
312 self.logger.message(self._aircraftState.timestamp, "The flare has begun")
313 self.logger.message(self._aircraftState.timestamp,
314 "Wind %03.0f/%.0f" % \
315 (windDirection, windSpeed))
316 self.logger.message(self._aircraftState.timestamp,
317 "Visibility: %.0f metres" % (visibility,))
318 self.logger.message(self._aircraftState.timestamp,
319 "Altimeter setting: %.0f hPa" % \
320 (self._aircraftState.altimeter,))
321 self._logVRef()
322 self.flight.flareStarted(flareStart, flareStartFS)
323 fs.sendMessage(const.MESSAGETYPE_INFORMATION, "Flare-time", 3)
324
325 def flareFinished(self, flareEnd, flareEndFS, tdRate, tdRateCalculatedByFS,
326 ias, pitch, bank, heading):
327 """Called when the flare has finished."""
328 (flareTimeFromFS, flareTime) = self.flight.flareFinished(flareEnd,
329 flareEndFS,
330 tdRate)
331 self.logger.message(self._aircraftState.timestamp,
332 "Flaretime: %.3f (from %s)" % \
333 (flareTime,
334 "the simulator" if flareTimeFromFS else "real time",))
335 self.logger.message(self._aircraftState.timestamp,
336 "Touchdown rate: %.0f feet/min" % (tdRate,))
337 self.logger.message(self._aircraftState.timestamp,
338 "Touchdown rate was calculated by the %s" % \
339 ("simulator" if tdRateCalculatedByFS else "logger",))
340 flight = self._flight
341 self.logger.message(self._aircraftState.timestamp,
342 "Touchdown speed: %.0f %s" % \
343 (flight.speedFromKnots(ias),
344 flight.getEnglishSpeedUnit()))
345 self.logger.message(self._aircraftState.timestamp,
346 "Touchdown pitch: %.1f degrees" % (pitch,))
347 self.logger.message(self._aircraftState.timestamp,
348 "Touchdown bank: %.1f degrees" % (bank,))
349 self.logger.message(self._aircraftState.timestamp,
350 "Touchdown heading: %03.0f degrees" % (heading,))
351 self.logger.message(self._aircraftState.timestamp,
352 "CG: %.1f%%" % \
353 (self._aircraftState.cog*100.0,))
354
355 def cancelFlare(self):
356 """Cancel flare, if it has started."""
357 self.flight.simulator.cancelFlare()
358
359 def checkFlightEnd(self, aircraftState):
360 """Check if the end of the flight has arrived.
361
362 This default implementation checks the N1 values, but for
363 piston-powered aircraft you need to check the RPMs."""
364 for n1 in aircraftState.n1:
365 if n1>=0.5: return False
366 return True
367
368 def updateV1R2(self):
369 """Update the V1, Vr and V2 values from the flight, if the these values
370 have already been logged."""
371 if self._v1r2LineIndex is not None:
372 self._logV1R2()
373
374 def _appendLightsLoggers(self):
375 """Append the loggers needed for the lights.
376
377 This default implementation adds the loggers for the anti-collision
378 lights, the landing lights, the strobe lights and the NAV lights."""
379 self._checkers.append(checks.AnticollisionLightsLogger())
380 self._checkers.append(checks.LandingLightsLogger())
381 self._checkers.append(checks.StrobeLightsLogger())
382 self._checkers.append(checks.NavLightsLogger())
383
384 def _appendLightsCheckers(self):
385 """Append the checkers needed for the lights.
386
387 This default implementation adds the checkers for the anti-collision
388 lights, the landing lights, the strobe lights and the NAV lights."""
389 self._checkers.append(checks.AntiCollisionLightsChecker())
390 self._checkers.append(checks.LandingLightsChecker())
391 self._checkers.append(checks.NavLightsChecker())
392 self._checkers.append(checks.StrobeLightsChecker())
393
394 def _appendSpeedChecker(self):
395 """Append the speed checker.
396
397 This default implementation used the SpeedChecker."""
398 self._checkers.append(checks.SpeedChecker())
399
400 def _speedToLog(self, speed):
401 """Convert the given speed (being either None or expressed in the
402 flight's speed unit into a string."""
403 if speed is None:
404 return "-"
405 else:
406 return str(speed) + " " + self._flight.getEnglishSpeedUnit()
407
408 def _logV1R2(self, state = None):
409 """Log the V1, Vr and V2 value either newly, or by updating the
410 corresponding line."""
411 message = "Speeds calculated by the pilot: V1: %s, VR: %s, V2: %s" % \
412 (self._speedToLog(self._flight.v1),
413 self._speedToLog(self._flight.vr),
414 self._speedToLog(self._flight.v2))
415
416 if self._v1r2LineIndex is None:
417 if state is None:
418 state = self._aircraftState
419 self._v1r2LineIndex = \
420 self.logger.message(state.timestamp, message)
421 else:
422 self.logger.updateLine(self._v1r2LineIndex, message)
423
424 def updateVRef(self):
425 """Update the Vref value from the flight, if the Vref value has already
426 been logged."""
427 if self._vrefLineIndex is not None:
428 self._logVRef()
429
430 def _logVRef(self):
431 """Log the Vref value either newly, or by updating the corresponding
432 line."""
433 message = "VRef speed calculated by the pilot: %s" % \
434 (self._speedToLog(self._flight.vref),)
435 if self._vrefLineIndex is None:
436 self._vrefLineIndex = \
437 self.logger.message(self._aircraftState.timestamp, message)
438 else:
439 self.logger.updateLine(self._vrefLineIndex, message)
440
441 def _fleetRetrieved(self, fleet):
442 """Callback for the fleet retrieval result."""
443 if fleet is not None:
444 gateList = ""
445 occupiedGateNumbers = fleet.getOccupiedGateNumbers()
446 for gateNumber in const.lhbpGateNumbers:
447 if gateNumber not in occupiedGateNumbers:
448 if gateList: gateList += ", "
449 gateList += gateNumber
450 fs.sendMessage(const.MESSAGETYPE_GATE_SYSTEM,
451 "Free gates: " + gateList, 20)
452
453
454 def _logRadios(self, aircraftState):
455 """Log the radios from the given aircraft state."""
456 flight = self._flight
457 logger = flight.logger
458
459 self._ilsLogger.forceLog(flight, logger, aircraftState)
460 self._nav1Logger.forceLog(flight, logger, aircraftState)
461 self._nav2Logger.forceLog(flight, logger, aircraftState)
462 self._adf1Logger.forceLog(flight, logger, aircraftState)
463 self._adf2Logger.forceLog(flight, logger, aircraftState)
464
465#---------------------------------------------------------------------------------------
466
467class Boeing737(Aircraft):
468 """Base class for the various aircraft in the Boeing 737 family.
469
470 The aircraft type-specific values in the aircraft state have the following
471 structure:
472 - fuel: left, centre, right
473 - n1: left, right
474 - reverser: left, right"""
475 def __init__(self, flight):
476 super(Boeing737, self).__init__(flight)
477 self._checkers.append(checks.ThrustChecker())
478
479 self.gearSpeedLimit = 270
480 self.flapSpeedLimits = { 1 : 260,
481 2 : 260,
482 5 : 250,
483 10 : 210,
484 15 : 200,
485 25 : 190,
486 30 : 175,
487 40 : 162 }
488
489 # def _appendSpeedChecker(self):
490 # """Append the NoStrobeSpeedChecker to the checkers.
491
492 # FOR TESTING ONLY, THIS FUNCTION SHOULD NORMALLY BE COMMENTED OUT!!!"""
493 # self._checkers.append(checks.NoStrobeSpeedChecker())
494
495#---------------------------------------------------------------------------------------
496
497class B736(Boeing737):
498 """Boeing 737-600 aircraft."""
499 def __init__(self, flight):
500 super(B736, self).__init__(flight)
501 self.dow = 38307
502 self.mtow = 58328
503 self.mlw = 54657
504 self.mzfw = 51482
505
506#---------------------------------------------------------------------------------------
507
508class B737(Boeing737):
509 """Boeing 737-700 aircraft."""
510 def __init__(self, flight):
511 super(B737, self).__init__(flight)
512 self.dow = 39250
513 self.mtow = 61410
514 self.mlw = 58059
515 self.mzfw = 54657
516
517#---------------------------------------------------------------------------------------
518
519class B738(Boeing737):
520 """Boeing 737-800 aircraft."""
521 def __init__(self, flight):
522 super(B738, self).__init__(flight)
523 self.dow = 42690
524 self.mtow = 71709
525 self.mlw = 65317
526 self.mzfw = 61688
527
528#---------------------------------------------------------------------------------------
529
530class B738Charter(B738):
531 """Boeing 737-800 aircraft used for charters."""
532 def __init__(self, flight):
533 super(B738Charter, self).__init__(flight)
534 self.mtow = 77791
535
536#---------------------------------------------------------------------------------------
537
538class B733(Boeing737):
539 """Boeing 737-300 aircraft."""
540 def __init__(self, flight):
541 super(B733, self).__init__(flight)
542 self.dow = 32700
543 self.mtow = 62820
544 self.mlw = 51700
545 self.mzfw = 48410
546
547#---------------------------------------------------------------------------------------
548
549class B734(Boeing737):
550 """Boeing 737-400 aircraft."""
551 def __init__(self, flight):
552 super(B734, self).__init__(flight)
553 self.dow = 33200
554 self.mtow = 68050
555 self.mlw = 56200
556 self.mzfw = 53100
557
558#---------------------------------------------------------------------------------------
559
560class B735(Boeing737):
561 """Boeing 737-500 aircraft."""
562 def __init__(self, flight):
563 super(B735, self).__init__(flight)
564 self.dow = 31300
565 self.mtow = 60550
566 self.mlw = 50000
567 self.mzfw = 46700
568
569#---------------------------------------------------------------------------------------
570
571class DH8D(Aircraft):
572 """Bombardier Dash-8 Q400 aircraft.
573
574 The aircraft type-specific values in the aircraft state have the following
575 structure:
576 - fuel: left, right
577 - n1: left, right
578 - reverser: left, right."""
579
580 def __init__(self, flight):
581 super(DH8D, self).__init__(flight)
582 self.dow = 17185
583 self.mtow = 29257
584 self.mlw = 28009
585 self.mzfw = 25855
586 self.gearSpeedLimit = 215
587 self.flapSpeedLimits = { 5 : 200,
588 10 : 181,
589 15 : 172,
590 35 : 158 }
591
592#---------------------------------------------------------------------------------------
593
594class Boeing767(Aircraft):
595 """Base class for the various aircraft in the Boeing 767 family.
596
597 The aircraft type-specific values in the aircraft state have the following
598 structure:
599 - fuel: left, centre, right
600 - n1: left, right
601 - reverser: left, right"""
602
603 def __init__(self, flight):
604 super(Boeing767, self).__init__(flight)
605 self._checkers.append(checks.ThrustChecker())
606 self.gearSpeedLimit = 270
607 self.flapSpeedLimits = { 1 : 255,
608 5 : 235,
609 10 : 215,
610 20 : 215,
611 25 : 185,
612 30 : 175 }
613
614#---------------------------------------------------------------------------------------
615
616class B762(Boeing767):
617 """Boeing 767-200 aircraft."""
618 def __init__(self, flight):
619 super(B762, self).__init__(flight)
620 self.dow = 84507
621 self.mtow = 175540
622 self.mlw = 126098
623 self.mzfw = 114758
624
625#---------------------------------------------------------------------------------------
626
627class B763(Boeing767):
628 """Boeing 767-300 aircraft."""
629 def __init__(self, flight):
630 super(B763, self).__init__(flight)
631 self.dow = 91311
632 self.mtow = 181436
633 self.mlw = 137892
634 self.mzfw = 130635
635
636#---------------------------------------------------------------------------------------
637
638class CRJ2(Aircraft):
639 """Bombardier CRJ-200 aircraft.
640
641 The aircraft type-specific values in the aircraft state have the following
642 structure:
643 - fuel: left, centre, right
644 - n1: left, right
645 - reverser: left, right."""
646 def __init__(self, flight):
647 super(CRJ2, self).__init__(flight)
648 self._checkers.append(checks.ThrustChecker())
649 self.dow = 14549
650 self.mtow = 22995
651 self.mlw = 21319
652 self.mzfw = 19958
653 self.gearSpeedLimit = 240
654 self.flapSpeedLimits = { 8 : 260,
655 20 : 220,
656 30 : 190,
657 45 : 175 }
658
659#---------------------------------------------------------------------------------------
660
661class F70(Aircraft):
662 """Fokker 70 aircraft.
663
664 The aircraft type-specific values in the aircraft state have the following
665 structure:
666 - fuel: left, centre, right
667 - n1: left, right
668 - reverser: left, right."""
669 def __init__(self, flight):
670 super(F70, self).__init__(flight)
671 self._checkers.append(checks.ThrustChecker())
672 self.dow = 24283
673 self.mtow = 38100 # FIXME: differentiate by registration number,
674 # MTOW of HA-LMF: 41955
675 self.mlw = 36740
676 self.mzfw = 32655
677 self.gearSpeedLimit = 200
678 self.flapSpeedLimits = { 8 : 250,
679 15 : 220,
680 25 : 220,
681 42 : 180 }
682 self.reverseMinSpeed = 50
683
684#---------------------------------------------------------------------------------------
685
686class DC3(Aircraft):
687 """Lisunov Li-2 (DC-3) aircraft.
688
689 The aircraft type-specific values in the aircraft state have the following
690 structure:
691 - fuel: left aux, left, right, right aux
692 - rpm: left, right
693 - reverser: left, right."""
694 def __init__(self, flight):
695 super(DC3, self).__init__(flight)
696 self.dow = 8627
697 self.mtow = 11884
698 self.mlw = 11793
699 self.mzfw = 11780
700 self.gearSpeedLimit = 148
701 self.flapSpeedLimits = { 15 : 135,
702 30 : 99,
703 45 : 97 }
704
705 def _checkFlightEnd(self, aircraftState):
706 """Check if the end of the flight has arrived.
707
708 This implementation checks the RPM values to be 0."""
709 for rpm in aircraftState.rpm:
710 if rpm>0: return False
711 return True
712
713#---------------------------------------------------------------------------------------
714
715class T134(Aircraft):
716 """Tupolev Tu-134 aircraft.
717
718 The aircraft type-specific values in the aircraft state have the following
719 structure:
720 - fuel: left tip, left aux, centre, right aux, right tip, external 1,
721 external 2
722 - n1: left, right
723 - reverser: left, right."""
724 def __init__(self, flight):
725 super(T134, self).__init__(flight)
726 self._checkers.append(checks.ThrustChecker())
727 self.dow = 29500
728 self.mtow = 49000
729 self.mlw = 43000
730 self.mzfw = 38500
731 self.gearSpeedLimit = 216
732 self.flapSpeedLimits = { 10 : 450,
733 20 : 400,
734 30 : 300 }
735 self.reverseMinSpeed = 50
736
737 @property
738 def speedInKnots(self):
739 """Indicate if the speed is in knots."""
740 return False
741
742 def _appendLightsLoggers(self):
743 """Append the loggers needed for the lights."""
744 self._checkers.append(checks.AnticollisionLightsLogger())
745 self._checkers.append(checks.LandingLightsLogger())
746 self._checkers.append(checks.NavLightsLogger())
747
748 def _appendLightsCheckers(self):
749 """Append the checkers needed for the lights."""
750 self._checkers.append(checks.TupolevAntiCollisionLightsChecker())
751 self._checkers.append(checks.LandingLightsChecker())
752 self._checkers.append(checks.NavLightsChecker())
753
754 def _appendSpeedChecker(self):
755 """Append the NoStrobeSpeedChecker to the checkers."""
756 self._checkers.append(checks.NoStrobeSpeedChecker())
757
758#---------------------------------------------------------------------------------------
759
760class T154(Aircraft):
761 """Tupolev Tu-154 aircraft.
762
763 The aircraft type-specific values in the aircraft state have the following
764 structure:
765 - fuel: left aux, left, centre, centre 2, right, right aux
766 - n1: left, centre, right
767 - reverser: left, right"""
768 def __init__(self, flight):
769 super(T154, self).__init__(flight)
770 self.dow = 53259
771 self.mtow = 98000
772 self.mlw = 78000
773 self.mzfw = 72000
774 self.gearSpeedLimit = 216
775 self.flapSpeedLimits = { 15 : 227,
776 28 : 194,
777 45 : 162 }
778 self.reverseMinSpeed = 50
779
780 @property
781 def speedInKnots(self):
782 """Indicate if the speed is in knots."""
783 return False
784
785 def _appendLightsLoggers(self):
786 """Append the loggers needed for the lights."""
787 self._checkers.append(checks.AnticollisionLightsLogger())
788 self._checkers.append(checks.LandingLightsLogger())
789 self._checkers.append(checks.NavLightsLogger())
790
791 def _appendLightsCheckers(self):
792 """Append the checkers needed for the lights."""
793 self._checkers.append(checks.AntiCollisionLightsChecker())
794 self._checkers.append(checks.LandingLightsChecker())
795 self._checkers.append(checks.NavLightsChecker())
796
797#---------------------------------------------------------------------------------------
798
799
800class YK40(Aircraft):
801 """Yakovlev Yak-40 aircraft.
802
803 The aircraft type-specific values in the aircraft state have the following
804 structure:
805 - fuel: left, right
806 - n1: left, right
807 - reverser: left, right"""
808 def __init__(self, flight):
809 super(YK40, self).__init__(flight)
810 self._checkers.append(checks.ThrustChecker())
811 self.dow = 9400
812 self.mtow = 17200
813 self.mlw = 16800
814 self.mzfw = 12100
815 self.gearSpeedLimit = 165
816 self.flapSpeedLimits = { 20 : 165,
817 35 : 135 }
818
819 @property
820 def speedInKnots(self):
821 """Indicate if the speed is in knots."""
822 return False
823
824 def _appendLightsLoggers(self):
825 """Append the loggers needed for the lights."""
826 self._checkers.append(checks.AnticollisionLightsLogger())
827 self._checkers.append(checks.LandingLightsLogger())
828 self._checkers.append(checks.NavLightsLogger())
829
830 def _appendLightsCheckers(self):
831 """Append the checkers needed for the lights."""
832 self._checkers.append(checks.AntiCollisionLightsChecker())
833 self._checkers.append(checks.LandingLightsChecker())
834 self._checkers.append(checks.NavLightsChecker())
835
836#---------------------------------------------------------------------------------------
837
838mostFuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_EXTERNAL1,
839 const.FUELTANK_LEFT_AUX,
840 const.FUELTANK_CENTRE,
841 const.FUELTANK_RIGHT_AUX,
842 const.FUELTANK_EXTERNAL2, const.FUELTANK_RIGHT_TIP]
843
844#---------------------------------------------------------------------------------------
845
846_classes = { const.AIRCRAFT_B736 : B736,
847 const.AIRCRAFT_B737 : B737,
848 const.AIRCRAFT_B738 : B738,
849 const.AIRCRAFT_B738C : B738Charter,
850 const.AIRCRAFT_B733 : B733,
851 const.AIRCRAFT_B734 : B734,
852 const.AIRCRAFT_B735 : B735,
853 const.AIRCRAFT_DH8D : DH8D,
854 const.AIRCRAFT_B762 : B762,
855 const.AIRCRAFT_B763 : B763,
856 const.AIRCRAFT_CRJ2 : CRJ2,
857 const.AIRCRAFT_F70 : F70,
858 const.AIRCRAFT_DC3 : DC3,
859 const.AIRCRAFT_T134 : T134,
860 const.AIRCRAFT_T154 : T154,
861 const.AIRCRAFT_YK40 : YK40 }
862
863#---------------------------------------------------------------------------------------
864
865if __name__ == "__main__":
866 value = SmoothedValue()
867
868 print "Adding 1, 12.0"
869 value.add(1, 12.0)
870 print value.get()
871
872 print "Adding 1, 15.0"
873 value.add(1, 15.0)
874 print value.get()
875
876 print "Adding 2, 18.0"
877 value.add(2, 18.0)
878 print value.get()
879
880 print "Adding 2, 20.0"
881 value.add(2, 20.0)
882 print value.get()
883
884 print "Adding 5, 22.0"
885 value.add(5, 22.0)
886 print value.get()
887
888 print "Adding 5, 25.0"
889 value.add(5, 25.0)
890 print value.get()
891
892 print "Adding 5, 29.0"
893 value.add(5, 29.0)
894 print value.get()
895
896 print "Adding 5, 21.0"
897 value.add(5, 21.0)
898 print value.get()
899
900 print "Adding 5, 26.0"
901 value.add(5, 26.0)
902 print value.get()
903
904 print "Adding 2, 30.0"
905 value.add(2, 30.0)
906 print value.get()
907
908 print "Adding 2, 55.0"
909 value.add(2, 55.0)
910 print value.get()
911
912#---------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.