source: src/mlx/acft.py@ 379:476e04537509

Last change on this file since 379:476e04537509 was 369:dcc9f8bd75dd, checked in by István Váradi <ivaradi@…>, 12 years ago

The aircraft's name and model are logged first when we enter the boarding stage

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