Changeset 89:ef4711a984fe
- Timestamp:
- 04/17/12 18:00:09 (13 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
src/mlx/acft.py
r86 r89 5 5 import const 6 6 import checks 7 import util 7 8 8 9 import time … … 112 113 checker.check(self._flight, self, self._flight.logger, 113 114 self._aircraftState, aircraftState) 115 116 self._flight.handleState(self._aircraftState, aircraftState) 114 117 115 118 self._maxVS = max(self._maxVS, aircraftState.vs) … … 155 158 elif newStage==const.STAGE_PARKING: 156 159 self.logger.message(aircraftState.timestamp, "Block time end") 160 elif newStage==const.STAGE_END: 161 flightLength = self._flight.flightTimeEnd - self._flight.flightTimeStart 162 self.logger.message(aircraftState.timestamp, 163 "Flight time: " + 164 util.getTimeIntervalString(flightLength)) 165 self.logger.message(aircraftState.timestamp, 166 "Flown distance: %.2f NM" % \ 167 (self._flight.flownDistance,)) 168 blockLength = self._flight.blockTimeEnd - self._flight.blockTimeStart 169 self.logger.message(aircraftState.timestamp, 170 "Block time: " + 171 util.getTimeIntervalString(blockLength)) 157 172 158 173 def prepareFlare(self): -
src/mlx/flight.py
r86 r89 4 4 5 5 import const 6 import util 6 7 7 8 import threading … … 39 40 self.aircraft = None 40 41 self.simulator = None 42 43 self.blockTimeStart = None 44 self.flightTimeStart = None 45 self.flightTimeEnd = None 46 self.blockTimeEnd = None 47 48 self._lastDistanceTime = None 49 self._previousLatitude = None 50 self._previousLongitude = None 51 self.flownDistance = 0.0 52 53 self.startFuel = None 54 self.endFuel = None 41 55 42 56 self._endCondition = threading.Condition() … … 80 94 return self._gui.vref 81 95 96 def handleState(self, oldState, currentState): 97 """Handle a new state information.""" 98 self._updateFlownDistance(currentState) 99 100 self.endFuel = sum(currentState.fuel) 101 if self.startFuel is None: 102 self.startFuel = self.endFuel 103 82 104 def setStage(self, timestamp, stage): 83 105 """Set the flight stage. … … 88 110 self._gui.setStage(stage) 89 111 self.logger.stage(timestamp, stage) 90 if stage==const.STAGE_END: 112 if stage==const.STAGE_PUSHANDTAXI: 113 self.blockTimeStart = timestamp 114 elif stage==const.STAGE_TAKEOFF: 115 self.flightTimeStart = timestamp 116 elif stage==const.STAGE_TAXIAFTERLAND: 117 self.flightTimeEnd = timestamp 118 elif stage==const.STAGE_PARKING: 119 self.blockTimeEnd = timestamp 120 elif stage==const.STAGE_END: 91 121 with self._endCondition: 92 122 self._endCondition.notify() … … 133 163 self._endCondition.wait(1) 134 164 165 def _updateFlownDistance(self, currentState): 166 """Update the flown distance.""" 167 if not currentState.onTheGround: 168 updateData = False 169 if self._lastDistanceTime is None or \ 170 self._previousLatitude is None or \ 171 self._previousLongitude is None: 172 updateData = True 173 elif currentState.timestamp >= (self._lastDistanceTime + 30.0): 174 updateData = True 175 self.flownDistance += self._getDistance(currentState) 176 177 if updateData: 178 self._previousLatitude = currentState.latitude 179 self._previousLongitude = currentState.longitude 180 self._lastDistanceTime = currentState.timestamp 181 else: 182 if self._lastDistanceTime is not None and \ 183 self._previousLatitude is not None and \ 184 self._previousLongitude is not None: 185 self.flownDistance += self._getDistance(currentState) 186 187 self._lastDistanceTime = None 188 189 def _getDistance(self, currentState): 190 """Get the distance between the previous and the current state.""" 191 return util.getDistCourse(self._previousLatitude, self._previousLongitude, 192 currentState.latitude, currentState.longitude)[0] 193 135 194 #--------------------------------------------------------------------------------------- -
src/mlx/fs.py
r59 r89 51 51 - timestamp: the simulator time of the measurement in seconds since the 52 52 epoch (float) 53 - latitude (in degrees, North is positive) 54 - longitude (in degrees, East is positive) 53 55 - paused: a boolean indicating if the flight simulator is paused for 54 56 whatever reason (it could be a pause mode, or a menu, a dialog, or a … … 58 60 - overspeed: a boolean indicating if the aircraft is in overspeed 59 61 - stalled: a boolean indicating if the aircraft is stalled 60 - onTheGround: a boolean indicating if the aircraft is on the ground 62 - onTheGround: a boolean indicating if the aircraft is on the ground 61 63 - zfw: the zero-fuel weight in kilograms (float) 62 64 - grossWeight: the gross weight in kilograms (float) -
src/mlx/fsuipc.py
r61 r89 746 746 object describing the aircraft's state.""" 747 747 monitoringData = [("paused", 0x0264, "H"), 748 ("latitude", 0x0560, "l"), 749 ("longitude", 0x0568, "l"), 748 750 ("frozen", 0x3364, "H"), 749 751 ("replay", 0x0628, "d"), … … 872 874 873 875 state.timestamp = timestamp 876 877 state.latitude = data[self._monidx_latitude] * \ 878 90.0 / 10001750.0 / 65536.0 / 65536.0 879 880 state.longitude = data[self._monidx_longitude] * \ 881 360.0 / 65536.0 / 65536.0 / 65536.0 / 65536.0 882 if state.longitude>180.0: state.longitude = 360.0 - state.longitude 874 883 875 884 state.paused = data[self._monidx_paused]!=0 or \ -
src/mlx/gui/flight.py
r88 r89 6 6 import mlx.fs as fs 7 7 from mlx.checks import PayloadChecker 8 import mlx.util as util 8 9 9 10 import datetime … … 1477 1478 def activate(self): 1478 1479 """Called when the page is activated.""" 1479 self._flightEnded = False1480 1481 1480 self._starButton.set_sensitive(True) 1482 1481 self._starButton.set_active(False) … … 1516 1515 1517 1516 self._vref.set_sensitive(False) 1517 # FIXME: Perhaps a separate initialize() call which would set up 1518 # defaults? 1519 self._flightEnded = False 1518 1520 1519 1521 def _starButtonClicked(self, button): … … 1557 1559 def _forwardClicked(self, button): 1558 1560 """Called when the forward button is clicked.""" 1559 #self._wizard.nextPage() 1560 self.finalize() 1561 self._wizard.nextPage() 1562 1563 #----------------------------------------------------------------------------- 1564 1565 class FinishPage(Page): 1566 """Flight finish page.""" 1567 def __init__(self, wizard): 1568 """Construct the finish page.""" 1569 help = "There are some statistics about your flight below.\n\n" \ 1570 "Review the data, also on earlier pages, and if you are\n" \ 1571 "satisfied, you can save or send your PIREP." 1572 1573 super(FinishPage, self).__init__(wizard, "Finish", help) 1574 1575 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5, 1576 xscale = 0.0, yscale = 0.0) 1577 1578 table = gtk.Table(5, 2) 1579 table.set_row_spacings(4) 1580 table.set_col_spacings(16) 1581 table.set_homogeneous(True) 1582 alignment.add(table) 1583 self.setMainWidget(alignment) 1584 1585 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 1586 label = gtk.Label("Flight rating:") 1587 labelAlignment.add(label) 1588 table.attach(labelAlignment, 0, 1, 0, 1) 1589 1590 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 1591 self._flightRating = gtk.Label() 1592 self._flightRating.set_width_chars(7) 1593 self._flightRating.set_alignment(0.0, 0.5) 1594 self._flightRating.set_use_markup(True) 1595 labelAlignment.add(self._flightRating) 1596 table.attach(labelAlignment, 1, 2, 0, 1) 1597 1598 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 1599 label = gtk.Label("Flight time:") 1600 labelAlignment.add(label) 1601 table.attach(labelAlignment, 0, 1, 1, 2) 1602 1603 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 1604 self._flightTime = gtk.Label() 1605 self._flightTime.set_width_chars(10) 1606 self._flightTime.set_alignment(0.0, 0.5) 1607 self._flightTime.set_use_markup(True) 1608 labelAlignment.add(self._flightTime) 1609 table.attach(labelAlignment, 1, 2, 1, 2) 1610 1611 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 1612 label = gtk.Label("Block time:") 1613 labelAlignment.add(label) 1614 table.attach(labelAlignment, 0, 1, 2, 3) 1615 1616 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 1617 self._blockTime = gtk.Label() 1618 self._blockTime.set_width_chars(10) 1619 self._blockTime.set_alignment(0.0, 0.5) 1620 self._blockTime.set_use_markup(True) 1621 labelAlignment.add(self._blockTime) 1622 table.attach(labelAlignment, 1, 2, 2, 3) 1623 1624 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 1625 label = gtk.Label("Distance flown:") 1626 labelAlignment.add(label) 1627 table.attach(labelAlignment, 0, 1, 3, 4) 1628 1629 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 1630 self._distanceFlown = gtk.Label() 1631 self._distanceFlown.set_width_chars(10) 1632 self._distanceFlown.set_alignment(0.0, 0.5) 1633 self._distanceFlown.set_use_markup(True) 1634 labelAlignment.add(self._distanceFlown) 1635 table.attach(labelAlignment, 1, 2, 3, 4) 1636 1637 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 1638 label = gtk.Label("Fuel used:") 1639 labelAlignment.add(label) 1640 table.attach(labelAlignment, 0, 1, 4, 5) 1641 1642 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 1643 self._fuelUsed = gtk.Label() 1644 self._fuelUsed.set_width_chars(10) 1645 self._fuelUsed.set_alignment(0.0, 0.5) 1646 self._fuelUsed.set_use_markup(True) 1647 labelAlignment.add(self._fuelUsed) 1648 table.attach(labelAlignment, 1, 2, 4, 5) 1649 1650 self._saveButton = self.addButton("S_ave PIREP...") 1651 self._saveButton.set_use_underline(True) 1652 #self._saveButton.connect("clicked", self._saveClicked) 1653 1654 self._sendButton = self.addButton("_Send PIREP...", True) 1655 self._sendButton.set_use_underline(True) 1656 #self._sendButton.connect("clicked", self._sendClicked) 1657 1658 def activate(self): 1659 """Activate the page.""" 1660 flight = self._wizard.gui._flight 1661 rating = flight.logger.getRating() 1662 if rating<0: 1663 self._flightRating.set_markup('<b><span foreground="red">NO GO</span></b>') 1664 else: 1665 self._flightRating.set_markup("<b>%.1f %%</b>" % (rating,)) 1666 1667 flightLength = flight.flightTimeEnd - flight.flightTimeStart 1668 self._flightTime.set_markup("<b>%s</b>" % \ 1669 (util.getTimeIntervalString(flightLength),)) 1670 1671 blockLength = flight.blockTimeEnd - flight.blockTimeStart 1672 self._blockTime.set_markup("<b>%s</b>" % \ 1673 (util.getTimeIntervalString(blockLength),)) 1674 1675 self._distanceFlown.set_markup("<b>%.2f NM</b>" % \ 1676 (flight.flownDistance,)) 1677 1678 self._fuelUsed.set_markup("<b>%.0f kg</b>" % \ 1679 (flight.endFuel - flight.startFuel,)) 1561 1680 1562 1681 #----------------------------------------------------------------------------- … … 1588 1707 self._landingPage = LandingPage(self) 1589 1708 self._pages.append(self._landingPage) 1709 self._pages.append(FinishPage(self)) 1590 1710 1591 1711 maxWidth = 0 -
src/mlx/gui/monitor.py
r77 r89 4 4 5 5 import mlx.const as const 6 import mlx.util as util 6 7 7 8 import time … … 170 171 table.attach(label, 4, 5, 6, 7) 171 172 table.attach(self._windDirection, 5, 6, 6, 7) 173 174 (label, self._position) = self._createLabeledEntry("Position:", 25) 175 table.attach(label, 6, 7, 6, 7) 176 table.attach(self._position, 7, 10, 6, 7) 172 177 173 178 alignment.add(table) … … 240 245 self._windSpeed.set_text("-") 241 246 self._windDirection.set_text("-") 247 self._position.set_text("-") 242 248 else: 243 249 self._timestamp.set_text(time.strftime("%H:%M:%S", … … 304 310 self._windSpeed.set_text("%.0f" % (aircraftState.windSpeed,)) 305 311 self._windDirection.set_text("%03.0f" % (aircraftState.windDirection,)) 312 self._position.set_text(util.getCoordinateString((aircraftState.latitude, 313 aircraftState.longitude))) 306 314 307 315 #------------------------------------------------------------------------------ -
src/mlx/pyuipc_sim.py
r88 r89 184 184 self.flapsNotches = [0, 1, 2, 5, 10, 15, 25, 30, 40] 185 185 self.fuelCapacities = [10000.0, 5000.0, 5000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 186 187 self.latitude = 47.5 188 self.longitude = 19.05 186 189 187 190 self.paused = False … … 291 294 elif offset==0x036d: # Overspeed 292 295 return 1 if self.overspeed else 0 296 elif offset==0x0560: # Latitude 297 return long(self.latitude * 10001750.0 * 65536.0 * 65536.0 / 90.0) 298 elif offset==0x0568: # Longitude 299 return long(self.longitude * 65536.0 * 65536.0 * 65536.0 * 65536.0 / 360.0) 293 300 elif offset==0x0570: # Altitude 294 301 return long(self.altitude * const.FEETTOMETRES * 65536.0 * 65536.0) … … 472 479 elif offset==0x036d: # Overspeed 473 480 self.overspeed = value!=0 481 elif offset==0x0560: # Latitude 482 self.latitude = value * 90.0 / 10001750.0 / 65536.0 / 65536.0 483 elif offset==0x0568: # Longitude 484 self.longitude = value * 360.0 / 65536.0 / 65536.0 / 65536.0 / 65536.0 474 485 elif offset==0x0570: # Altitude 475 486 self.altitude = value / const.FEETTOMETRES / 65536.0 / 65536.0 … … 908 919 self._valueHandlers["airPath"] = (0x3c00, -256, lambda value: value, 909 920 lambda word: word) 921 self._valueHandlers["latitude"] = (0x0560, "l", 922 lambda value: value * 90.0 / 923 10001750.0 / 65536.0 / 65536.0, 924 lambda word: long(float(word) * 925 10001750.0 * 926 65536.0 * 65536.0 / 90.0)) 927 self._valueHandlers["longitude"] = (0x0568, "l", 928 lambda value: value * 360.0 / 929 65536.0 / 65536.0 / 65536.0 / 65536.0, 930 lambda word: long(float(word) * 931 65536.0 * 65536.0 * 932 65536.0 * 65536.0 / 933 360.0)) 910 934 self._valueHandlers["paused"] = (0x0264, "H", CLI.bool2str, CLI.str2bool) 911 935 self._valueHandlers["frozen"] = (0x3364, "H", CLI.bool2str, CLI.str2bool) -
src/mlx/util.py
r27 r89 1 1 # Various utilities 2 2 3 import math 4 5 #------------------------------------------------------------------------------ 6 7 # The average of the radius at the poles and a the equator, in metres 8 #EARTH_RADIUS=6367467.4 9 EARTH_RADIUS=6371000 10 #EARTH_RADIUS=6378137 11 12 #------------------------------------------------------------------------------ 13 14 def getDegMinSec(degrees): 15 """Break up the given floating point degrees value into a tuple. 16 17 The tuple contains 4 items: 18 - the degrees as an integer 19 - the minutes as an integer 20 - the seconds as an integer 21 - 1.0 if the value was non-negative, -1.0 if it was negative.""" 22 23 if degrees<0: 24 degrees = -degrees 25 mul = -1.0 26 else: 27 mul = 1.0 28 29 deg = int(degrees) 30 min = int((degrees*60.0)%60.0) 31 sec = int((degrees*3600.0)%60.0) 32 33 return (deg, min, sec, mul) 34 35 #------------------------------------------------------------------------------ 36 37 def getCoordinateString((latitude, longitude)): 38 """Get the string representation of the given coordinate pair.""" 39 40 latitude_str = getLatitudeString(latitude) 41 longitude_str = getLongitudeString(longitude) 42 43 return latitude_str + " " + longitude_str 44 45 #------------------------------------------------------------------------------ 46 47 def getLatitudeString(latitude): 48 """Get a string representation of the given latitude.""" 49 return getDegreeString(latitude, ["N", "S"]) 50 51 #------------------------------------------------------------------------------ 52 53 def getLongitudeString(longitude): 54 """Get a string representation of the given longitude.""" 55 56 return getDegreeString(longitude, ["E", "W"]) 57 58 #------------------------------------------------------------------------------ 59 60 def getDegreeString(degree, prefixes): 61 """Get a string representation of the given degree. 62 63 If the sign is positive, prefixes[0], otherwise prefixes[1] will be 64 prepended to the string.""" 65 66 if degree<0: 67 prefix = prefixes[1] 68 else: 69 prefix = prefixes[0] 70 71 (deg, min, sec, _sign) = getDegMinSec(degree) 72 73 return u"%s%d\u00b0%02d\u2032%02d\u2033" % (prefix, deg, min, sec) 74 75 #------------------------------------------------------------------------------ 76 77 def getTimeIntervalString(seconds): 78 """Get a more human-friendly representation of the given time interval 79 expressed in seconds.""" 80 hours = int(seconds / 3600) 81 minutes = int((seconds / 60) % 60) 82 seconds = int(seconds % 60) 83 return "%d:%02d:%02d" % (hours, minutes, seconds) 84 85 #------------------------------------------------------------------------------ 86 87 def km2nm(km): 88 """Convert the given kilometres into nautical miles.""" 89 return km/1.852 90 91 #------------------------------------------------------------------------------ 92 93 def nm2km(nm): 94 """Convert the given nautical miles into kilometres.""" 95 return nm*1.852 96 97 #------------------------------------------------------------------------------ 98 99 def radians2km(radians): 100 """Convert the given radians into kilometres""" 101 return radians * EARTH_RADIUS / 1000.0 102 103 #------------------------------------------------------------------------------ 104 105 def radians2nm(radians): 106 """Convert the given radians into nautical miles.""" 107 return km2nm(radians2km(radians)) 108 109 #------------------------------------------------------------------------------ 110 111 def getDistCourse(latitude1, longitude1, latitude2, longitude2): 112 """Get the distance and course between the two geographical coordinates. 113 114 This function calculates the rhumb distance.""" 115 116 latitude1 = math.radians(latitude1) 117 longitude1 = math.radians(longitude1) 118 119 latitude2 = math.radians(latitude2) 120 longitude2 = math.radians(longitude2) 121 122 dlon_W = (longitude1 - longitude2) % (math.pi*2) 123 dlon_E = (longitude2 - longitude1) % (math.pi*2) 124 125 dphi = math.log(math.tan(latitude2/2 + math.pi/4)/ 126 math.tan(latitude1/2 + math.pi/4)) 127 128 if abs(latitude1-latitude2) < math.sqrt(1e-15): 129 q = math.cos(latitude1) 130 else: 131 q = (latitude1-latitude2)/dphi 132 133 if dlon_W < dlon_E: 134 tc = math.atan2(-dlon_W, dphi) % (math.pi*2) 135 d = math.sqrt(math.pow(q*dlon_W, 2) + 136 math.pow(latitude1-latitude2, 2)) 137 else: 138 tc = math.atan2(dlon_E, dphi) % (math.pi*2) 139 d = math.sqrt(math.pow(q*dlon_E, 2) + 140 math.pow(latitude1-latitude2, 2)) 141 142 return (radians2nm(d), math.degrees(tc)) 143
Note:
See TracChangeset
for help on using the changeset viewer.