source: src/mlx/acft.py@ 359:fa4e93edd48b

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

Eliminated the parking stage (#150)

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