source: src/mlx/acft.py@ 311:d044f00da30c

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

In case of Tu-154 the anti-collision lights are handled normally

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