source: src/mlx/acft.py@ 297:9d1f71a9de51

Last change on this file since 297:9d1f71a9de51 was 297:9d1f71a9de51, checked in by István Váradi <ivaradi@…>, 12 years ago

Added some further documentation

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