source: src/mlx/acft.py@ 305:ddc2dfec2080

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

Cruise level changes are logged

File size: 31.6 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._checkers.append(checks.ThrustChecker())
721 self.dow = 53259
722 self.mtow = 98000
723 self.mlw = 78000
724 self.mzfw = 72000
725 self.gearSpeedLimit = 216
726 self.flapSpeedLimits = { 15 : 227,
727 28 : 194,
728 45 : 162 }
729
730 @property
731 def speedInKnots(self):
732 """Indicate if the speed is in knots."""
733 return False
734
735 def _appendLightsLoggers(self):
736 """Append the loggers needed for the lights."""
737 self._checkers.append(checks.AnticollisionLightsLogger())
738 self._checkers.append(checks.LandingLightsLogger())
739 self._checkers.append(checks.NavLightsLogger())
740
741 def _appendLightsCheckers(self):
742 """Append the checkers needed for the lights."""
743 self._checkers.append(checks.TupolevAntiCollisionLightsChecker())
744 self._checkers.append(checks.LandingLightsChecker())
745 self._checkers.append(checks.NavLightsChecker())
746
747#---------------------------------------------------------------------------------------
748
749
750class YK40(Aircraft):
751 """Yakovlev Yak-40 aircraft.
752
753 The aircraft type-specific values in the aircraft state have the following
754 structure:
755 - fuel: left, right
756 - n1: left, right
757 - reverser: left, right"""
758 def __init__(self, flight):
759 super(YK40, self).__init__(flight)
760 self._checkers.append(checks.ThrustChecker())
761 self.dow = 9400
762 self.mtow = 17200
763 self.mlw = 16800
764 self.mzfw = 12100
765 self.gearSpeedLimit = 165
766 self.flapSpeedLimits = { 20 : 165,
767 35 : 135 }
768
769 @property
770 def speedInKnots(self):
771 """Indicate if the speed is in knots."""
772 return False
773
774 def _appendLightsLoggers(self):
775 """Append the loggers needed for the lights."""
776 self._checkers.append(checks.AnticollisionLightsLogger())
777 self._checkers.append(checks.LandingLightsLogger())
778 self._checkers.append(checks.NavLightsLogger())
779
780 def _appendLightsCheckers(self):
781 """Append the checkers needed for the lights."""
782 self._checkers.append(checks.AntiCollisionLightsChecker())
783 self._checkers.append(checks.LandingLightsChecker())
784 self._checkers.append(checks.NavLightsChecker())
785
786#---------------------------------------------------------------------------------------
787
788mostFuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_EXTERNAL1,
789 const.FUELTANK_LEFT_AUX,
790 const.FUELTANK_CENTRE,
791 const.FUELTANK_RIGHT_AUX,
792 const.FUELTANK_EXTERNAL2, const.FUELTANK_RIGHT_TIP]
793
794#---------------------------------------------------------------------------------------
795
796_classes = { const.AIRCRAFT_B736 : B736,
797 const.AIRCRAFT_B737 : B737,
798 const.AIRCRAFT_B738 : B738,
799 const.AIRCRAFT_B738C : B738Charter,
800 const.AIRCRAFT_B733 : B733,
801 const.AIRCRAFT_B734 : B734,
802 const.AIRCRAFT_B735 : B735,
803 const.AIRCRAFT_DH8D : DH8D,
804 const.AIRCRAFT_B762 : B762,
805 const.AIRCRAFT_B763 : B763,
806 const.AIRCRAFT_CRJ2 : CRJ2,
807 const.AIRCRAFT_F70 : F70,
808 const.AIRCRAFT_DC3 : DC3,
809 const.AIRCRAFT_T134 : T134,
810 const.AIRCRAFT_T154 : T154,
811 const.AIRCRAFT_YK40 : YK40 }
812
813#---------------------------------------------------------------------------------------
814
815if __name__ == "__main__":
816 value = SmoothedValue()
817
818 print "Adding 1, 12.0"
819 value.add(1, 12.0)
820 print value.get()
821
822 print "Adding 1, 15.0"
823 value.add(1, 15.0)
824 print value.get()
825
826 print "Adding 2, 18.0"
827 value.add(2, 18.0)
828 print value.get()
829
830 print "Adding 2, 20.0"
831 value.add(2, 20.0)
832 print value.get()
833
834 print "Adding 5, 22.0"
835 value.add(5, 22.0)
836 print value.get()
837
838 print "Adding 5, 25.0"
839 value.add(5, 25.0)
840 print value.get()
841
842 print "Adding 5, 29.0"
843 value.add(5, 29.0)
844 print value.get()
845
846 print "Adding 5, 21.0"
847 value.add(5, 21.0)
848 print value.get()
849
850 print "Adding 5, 26.0"
851 value.add(5, 26.0)
852 print value.get()
853
854 print "Adding 2, 30.0"
855 value.add(2, 30.0)
856 print value.get()
857
858 print "Adding 2, 55.0"
859 value.add(2, 55.0)
860 print value.get()
861
862#---------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.