source: src/mlx/acft.py@ 263:7ee78a903649

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

RPM is handled properly and the fuel tanks of Li-2 match the simulator

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