source: src/mlx/acft.py@ 360:b83988619f8b

Last change on this file since 360:b83988619f8b was 360:b83988619f8b, checked in by István Váradi <ivaradi@…>, 11 years ago

Added aircraft-specific minimal speed for the reversers (#152)

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