Changeset 141:3172532920ad


Ignore:
Timestamp:
05/01/12 12:57:18 (13 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

Fuel loading works

Location:
src/mlx
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/mlx/acft.py

    r140 r141  
    735735#---------------------------------------------------------------------------------------
    736736
     737MostFuelTankAircraft = T134
     738
     739#---------------------------------------------------------------------------------------
     740
    737741_classes = { const.AIRCRAFT_B736 : B736,
    738742             const.AIRCRAFT_B737 : B737,
  • src/mlx/const.py

    r140 r141  
    329329#-------------------------------------------------------------------------------
    330330
     331fuelTanks = [ FUELTANK_CENTRE,
     332              FUELTANK_LEFT,
     333              FUELTANK_RIGHT,
     334              FUELTANK_LEFT_AUX,
     335              FUELTANK_RIGHT_AUX,
     336              FUELTANK_LEFT_TIP,
     337              FUELTANK_RIGHT_TIP,
     338              FUELTANK_EXTERNAL1,
     339              FUELTANK_EXTERNAL2,
     340              FUELTANK_CENTRE2 ]
     341
     342#-------------------------------------------------------------------------------
     343
     344_fuelTankStrings = { FUELTANK_CENTRE : "centre",
     345                     FUELTANK_LEFT : "left",
     346                     FUELTANK_RIGHT : "right",
     347                     FUELTANK_LEFT_AUX : "left_aux",
     348                     FUELTANK_RIGHT_AUX : "right_aux",
     349                     FUELTANK_LEFT_TIP : "left_tip",
     350                     FUELTANK_RIGHT_TIP : "right_tip",
     351                     FUELTANK_EXTERNAL1 : "external1",
     352                     FUELTANK_EXTERNAL2 : "external2",
     353                     FUELTANK_CENTRE2 : "centre2" }
     354
     355def fuelTank2string(fuelTank):
     356    """Get the string equivalent of the given fuelTank."""
     357    return _fuelTankStrings[fuelTank] \
     358           if fuelTank in _fuelTankStrings else None   
     359
     360#-------------------------------------------------------------------------------
     361
    331362# The available gates at LHBP
    332363lhbpGateNumbers = []
  • src/mlx/fsuipc.py

    r140 r141  
    528528   
    529529        self._latin1decoder = codecs.getdecoder("iso-8859-1")
    530    
     530
    531531    def connect(self, aircraft):
    532532        """Initiate a connection to the simulator."""
     
    608608
    609609        self._handler.requestWrite(data, self._handleMessageSent)
     610
     611    def getFuel(self, tanks, callback):
     612        """Get the fuel from the given tanks.
     613
     614        The callback will be called with a list of two-tuples, where the tuples
     615        have the following items:
     616        - the current weight of the fuel in the tank (in kgs)
     617        - the current total capacity of the tank (in kgs)."""
     618        data = [(0x0af4, "H")]     # Fuel weight
     619        for tank in tanks:
     620            offset = _tank2offset[tank]
     621            data.append( (offset, "u") )     # tank level
     622            data.append( (offset+4, "u") )   # tank capacity
     623
     624        self._handler.requestRead(data, self._handleFuelRetrieved,
     625                                  extra = callback)
     626
     627    def setFuelLevel(self, levels):
     628        """Set the fuel level to the given ones.
     629
     630        levels is an array of two-tuples, where each tuple consists of the
     631        following:
     632        - the const.FUELTANK_XXX constant denoting the tank that must be set,
     633        - the requested level of the fuel as a floating-point value between 0.0
     634        and 1.0."""
     635        data = []
     636        for (tank, level) in levels:
     637            offset = _tank2offset[tank]
     638            data.append( (offset, "u", long(level * 128.8 * 65536.0)) )
     639        self._handler.requestWrite(data, self._handleFuelWritten)
    610640           
    611641    def disconnect(self):
     
    801831    def _handleMessageSent(self, success, extra):
    802832        """Callback for a message sending request."""
     833        pass
     834
     835    def _handleFuelRetrieved(self, data, callback):
     836        """Callback for a fuel retrieval request."""
     837        fuelWeight = data[0] / 256.0
     838        result = []
     839        for i in range(1, len(data), 2):
     840            capacity = data[i+1] * fuelWeight * const.LBSTOKG
     841            amount = data[i] * capacity / 128.0 / 65536.0
     842            result.append( (amount, capacity) )
     843
     844        callback(result)
     845                                                 
     846    def _handleFuelWritten(self, success, extra):
     847        """Callback for a fuel setting request."""
    803848        pass
    804849                                                 
  • src/mlx/gui/flight.py

    r139 r141  
    55import mlx.const as const
    66import mlx.fs as fs
     7import mlx.acft as acft
    78from mlx.checks import PayloadChecker
    89import mlx.util as util
     
    967968    def _forwardClicked(self, button):
    968969        """Called when the forward button is clicked."""
     970        if not self._completed:
     971            gui = self._wizard.gui
     972            gui.beginBusy(xstr("fuel_get_busy"))
     973           
     974            gui.simulator.getFuel(gui.flight.aircraft.fuelTanks,
     975                                  self._handleFuel)
     976        else:
     977            self._wizard.nextPage()
     978
     979    def _handleFuel(self, fuelData):
     980        """Callback for the fuel query operation."""
     981        gobject.idle_add(self._processFuel, fuelData)
     982
     983    def _processFuel(self, fuelData):
     984        """Process the given fuel data."""
     985        self._wizard.gui.endBusy()
     986        self._wizard._fuelData = fuelData
    969987        self._wizard.nextPage()
     988       
     989#-----------------------------------------------------------------------------
     990
     991class FuelTank(gtk.VBox):
     992    """Widget for the fuel tank."""
     993    def __init__(self, fuelTank, name, capacity, currentWeight):
     994        """Construct the widget for the tank with the given name."""
     995        super(FuelTank, self).__init__()
     996
     997        self.fuelTank = fuelTank
     998        self.capacity = capacity
     999        self.currentWeight = currentWeight
     1000        self.expectedWeight = currentWeight
     1001
     1002        label = gtk.Label("<b>" + name + "</b>")
     1003        label.set_use_markup(True)
     1004        label.set_justify(JUSTIFY_CENTER)
     1005        label.set_alignment(0.5, 1.0)
     1006        self.pack_start(label, False, False, 4)
     1007
     1008        self._tankFigure = gtk.DrawingArea()
     1009        self._tankFigure.set_size_request(38, -1)
     1010
     1011        if pygobject:
     1012            self._tankFigure.connect("draw", self._drawTankFigure)
     1013        else:
     1014            self._tankFigure.connect("expose_event", self._drawTankFigure)
     1015
     1016        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
     1017                                  xscale = 0.0, yscale = 1.0)
     1018        alignment.add(self._tankFigure)
     1019
     1020        self.pack_start(alignment, True, True, 4)
     1021
     1022        self._expectedButton = gtk.SpinButton()
     1023        self._expectedButton.set_numeric(True)
     1024        self._expectedButton.set_range(0, self.capacity)
     1025        self._expectedButton.set_increments(10, 100)
     1026        self._expectedButton.set_value(currentWeight)
     1027        self._expectedButton.set_alignment(1.0)
     1028        self._expectedButton.set_width_chars(5)
     1029        self._expectedButton.connect("value-changed", self._expectedChanged)
     1030
     1031        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
     1032                                  xscale = 0.0, yscale = 1.0)
     1033        alignment.add(self._expectedButton)
     1034        self.pack_start(alignment, False, False, 4)
     1035
     1036    def setCurrent(self, currentWeight):
     1037        """Set the current weight."""
     1038        self.currentWeight = currentWeight
     1039        self._redraw()
     1040
     1041    def isCorrect(self):
     1042        """Determine if the contents of the fuel tank are as expected"""
     1043        return abs(self.expectedWeight - self.currentWeight)<=1
     1044
     1045    def disable(self):
     1046        """Disable the fuel tank."""
     1047        self._expectedButton.set_sensitive(False)
     1048
     1049    def _redraw(self):
     1050        """Redraw the tank figure."""
     1051        self._tankFigure.queue_draw()
     1052
     1053    def _drawTankFigure(self, connStateArea, eventOrContext):
     1054        """Draw the tank figure."""
     1055        triangleSize = 5
     1056       
     1057        context = eventOrContext if pygobject else connStateArea.window.cairo_create()
     1058
     1059        width = connStateArea.get_allocated_width() if pygobject \
     1060                else connStateArea.allocation.width
     1061        height = connStateArea.get_allocated_height() if pygobject \
     1062                 else connStateArea.allocation.height
     1063
     1064        rectangleX0 = triangleSize
     1065        rectangleY0 = triangleSize
     1066        rectangleX1 = width - 1 - triangleSize
     1067        rectangleY1 = height - 1 - triangleSize
     1068        rectangleLineWidth = 2.0
     1069
     1070        context.set_source_rgb(0.0, 0.0, 0.0)
     1071        context.set_line_width(rectangleLineWidth)
     1072        context.rectangle(rectangleX0 + rectangleLineWidth/2,
     1073                          rectangleY0 + rectangleLineWidth/2,
     1074                          rectangleX1 - rectangleX0 - rectangleLineWidth,
     1075                          rectangleY1 - rectangleY0 - rectangleLineWidth)
     1076        context.stroke()
     1077
     1078        rectangleInnerLeft   = rectangleX0 + rectangleLineWidth
     1079        rectangleInnerRight  = rectangleX1 - rectangleLineWidth
     1080        rectangleInnerTop    = rectangleY0 + rectangleLineWidth
     1081        rectangleInnerBottom = rectangleY1 - rectangleLineWidth
     1082
     1083        rectangleInnerWidth = rectangleInnerRight - rectangleInnerLeft
     1084        rectangleInnerHeight = rectangleInnerBottom - rectangleInnerTop
     1085
     1086        context.set_source_rgb(1.0, 0.9, 0.6)
     1087        currentHeight = self.currentWeight * rectangleInnerHeight / self.capacity
     1088        currentX = rectangleInnerTop + rectangleInnerHeight - currentHeight
     1089        context.rectangle(rectangleInnerLeft,
     1090                          rectangleInnerTop + rectangleInnerHeight - currentHeight,
     1091                          rectangleInnerWidth, currentHeight)
     1092        context.fill()
     1093
     1094        expectedHeight = self.expectedWeight * rectangleInnerHeight / self.capacity
     1095        expectedY = rectangleInnerTop + rectangleInnerHeight - expectedHeight
     1096
     1097        context.set_line_width(1.5)
     1098        context.set_source_rgb(0.0, 0.85, 0.85)
     1099        context.move_to(rectangleX0, expectedY)
     1100        context.line_to(rectangleX1, expectedY)
     1101        context.stroke()
     1102
     1103        context.set_line_width(0.0)
     1104        context.move_to(0, expectedY - triangleSize)
     1105        context.line_to(0, expectedY + triangleSize)
     1106        context.line_to(rectangleX0 + 1, expectedY)
     1107        context.line_to(0, expectedY - triangleSize)
     1108        context.fill()
     1109
     1110        context.set_line_width(0.0)
     1111        context.move_to(width, expectedY - triangleSize)
     1112        context.line_to(width, expectedY + triangleSize)
     1113        context.line_to(rectangleX1 - 1, expectedY)
     1114        context.line_to(width, expectedY - triangleSize)
     1115        context.fill()
     1116
     1117    def _expectedChanged(self, spinButton):
     1118        """Called when the expected value has changed."""
     1119        self.expectedWeight = spinButton.get_value_as_int()
     1120        self._redraw()       
     1121
     1122#-----------------------------------------------------------------------------
     1123
     1124class FuelPage(Page):
     1125    """The page containing the fuel tank filling."""
     1126    _pumpStep = 0.02
     1127   
     1128    def __init__(self, wizard):
     1129        """Construct the page."""
     1130        super(FuelPage, self).__init__(wizard, xstr("fuel_title"),
     1131                                       xstr("fuel_help"),
     1132                                       completedHelp = xstr("fuel_chelp"))
     1133
     1134        self._fuelTanks = []
     1135        self._fuelTable = None
     1136        self._fuelAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
     1137                                            xscale = 0.0, yscale = 1.0)
     1138        self.setMainWidget(self._fuelAlignment)
     1139
     1140        tanks = acft.MostFuelTankAircraft.fuelTanks
     1141        tankData = ((2500, 3900),) * len(tanks)
     1142        self._setupTanks(tanks, tankData)
     1143
     1144        self._backButton = self.addPreviousButton(clicked = self._backClicked)
     1145        self._button = self.addNextButton(clicked = self._forwardClicked)
     1146
     1147        self._pumpIndex = 0
     1148
     1149    def activate(self):
     1150        """Activate the page."""
     1151        gui = self._wizard.gui
     1152
     1153        self._setupTanks(gui.flight.aircraft.fuelTanks,
     1154                         self._wizard._fuelData)
     1155
     1156    def finalize(self):
     1157        """Finalize the page."""
     1158        for fuelTank in self._fuelTanks:
     1159            fuelTank.disable()
     1160
     1161    def _backClicked(self, button):
     1162        """Called when the Back button is pressed."""
     1163        self.goBack()
     1164       
     1165    def _forwardClicked(self, button):
     1166        """Called when the forward button is clicked."""
     1167        if not self._completed:
     1168            self._pumpIndex = 0
     1169            self._wizard.gui.beginBusy(xstr("fuel_pump_busy"))
     1170            self._pump()
     1171        else:
     1172            self._wizard.nextPage()       
     1173
     1174    def _setupTanks(self, tanks, tankData):
     1175        """Setup the tanks for the given data."""
     1176        numTanks = len(tanks)
     1177        if self._fuelTable is not None:
     1178            self._fuelAlignment.remove(self._fuelTable)
     1179
     1180        self._fuelTanks = []
     1181        self._fuelTable = gtk.Table(numTanks, 1)
     1182        self._fuelTable.set_col_spacings(16)
     1183        for i in range(0, numTanks):
     1184            tank = tanks[i]
     1185            (current, capacity) = tankData[i]
     1186
     1187            fuelTank = FuelTank(tank,
     1188                                xstr("fuel_tank_" +
     1189                                     const.fuelTank2string(tank)),
     1190                                capacity, current)
     1191            self._fuelTable.attach(fuelTank, i, i+1, 0, 1)
     1192            self._fuelTanks.append(fuelTank)
     1193           
     1194        self._fuelAlignment.add(self._fuelTable)
     1195        self.show_all()
     1196
     1197    def _pump(self):
     1198        """Perform one step of pumping.
     1199
     1200        It is checked, if the current tank's contents are of the right
     1201        quantity. If not, it is filled one step further to the desired
     1202        contents. Otherwise the next tank is started. If all tanks are are
     1203        filled, the next page is selected."""
     1204        numTanks = len(self._fuelTanks)
     1205
     1206        fuelTank = None
     1207        while self._pumpIndex < numTanks:
     1208            fuelTank = self._fuelTanks[self._pumpIndex]
     1209            if fuelTank.isCorrect():
     1210                self._pumpIndex += 1
     1211                fuelTank = None
     1212            else:
     1213                break
     1214
     1215        if fuelTank is None:
     1216            self._wizard.gui.endBusy()
     1217            self._wizard.nextPage()
     1218        else:
     1219            currentLevel = fuelTank.currentWeight / fuelTank.capacity
     1220            expectedLevel = fuelTank.expectedWeight / fuelTank.capacity
     1221            if currentLevel<expectedLevel:
     1222                currentLevel += FuelPage._pumpStep
     1223                if currentLevel>expectedLevel: currentLevel = expectedLevel
     1224            else:
     1225                currentLevel -= FuelPage._pumpStep
     1226                if currentLevel<expectedLevel: currentLevel = expectedLevel
     1227            fuelTank.setCurrent(currentLevel * fuelTank.capacity)
     1228            self._wizard.gui.simulator.setFuelLevel([(fuelTank.fuelTank,
     1229                                                      currentLevel)])
     1230            gobject.timeout_add(50, self._pump)
    9701231       
    9711232#-----------------------------------------------------------------------------
     
    9741235    """The page containing the route and the flight level."""
    9751236    def __init__(self, wizard):
     1237        """Construct the page."""
    9761238        super(RoutePage, self).__init__(wizard, xstr("route_title"),
    9771239                                        xstr("route_help"),
     
    20452307        self._payloadIndex = len(self._pages)
    20462308        self._pages.append(TimePage(self))
     2309        self._pages.append(FuelPage(self))
    20472310        self._routePage = RoutePage(self)
    20482311        self._pages.append(self._routePage)
     
    22422505        self._bookedFlight = None
    22432506        self._departureGate = "-"
     2507        self._fuelData = None
    22442508        self._departureNOTAMs = None
    22452509        self._departureMETAR = None
  • src/mlx/i18n.py

    r139 r141  
    284284                 "Click here to query the current UTC time from the simulator.")
    285285        self.add("time_busy", "Querying time...")
     286
     287        self.add("fuel_title", "Fuel")
     288        self.add("fuel_help",
     289                 "Enter the amount of fuel in kilograms that need to be "
     290                 "present in each tank below.\n\n"
     291                 "When you press <b>Next</b>, the necessary amount of fuel\n"
     292                 "will be pumped into or out of the tanks.")
     293        self.add("fuel_chelp",
     294                 "The amount of fuel tanked into your aircraft at the\n"
     295                 "beginning of the flight can be seen below.")
     296        self.add("fuel_tank_centre", "Centre\n")
     297        self.add("fuel_tank_left", "Left\n")
     298        self.add("fuel_tank_right", "Right\n")
     299        self.add("fuel_tank_left_aux", "Left\nAux")
     300        self.add("fuel_tank_right_aux", "Right\nAux")
     301        self.add("fuel_tank_left_tip", "Left\nTip")
     302        self.add("fuel_tank_right_tip", "Right\nTip")
     303        self.add("fuel_tank_external1", "External\n1")
     304        self.add("fuel_tank_external2", "External\n2")
     305        self.add("fuel_tank_centre2", "Centre\n2")
     306        self.add("fuel_get_busy", "Querying fuel information...")
     307        self.add("fuel_pump_busy", "Pumping fuel...")
    286308
    287309        self.add("route_title", "Route")
Note: See TracChangeset for help on using the changeset viewer.