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

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

Documented the non-GUI modules

File size: 10.1 KB
Line 
1
2import const
3from sound import startSound
4
5import fsuipc
6import threading
7import time
8
9#-------------------------------------------------------------------------------
10
11## @package mlx.fs
12#
13# The main interface to the flight simulator.
14#
15# The \ref createSimulator function can be used to create an instance of
16# the class that can be used to access the simulator. It expects an instance of
17# the \ref ConnectionListener class, the member functions of which will be
18# called when something happens with the connection to the simulator.
19#
20# The simulator interface is most often used to retrieve the state of the
21# simulated aircraft. Instances of class \ref AircraftState are used for this
22# purpose.
23#
24# This module also contains some definitions for message sending and implements
25# the timing logic itself.
26
27#-------------------------------------------------------------------------------
28
29class ConnectionListener(object):
30 """Base class for listeners on connections to the flight simulator."""
31 def connected(self, fsType, descriptor):
32 """Called when a connection has been established to the flight
33 simulator of the given type."""
34 print "fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor
35
36 def connectionFailed(self):
37 """Called when the connection could not be established."""
38 print "fs.ConnectionListener.connectionFailed"
39
40 def disconnected(self):
41 """Called when a connection to the flight simulator has been broken."""
42 print "fs.ConnectionListener.disconnected"
43
44#-------------------------------------------------------------------------------
45
46class SimulatorException(Exception):
47 """Exception thrown by the simulator interface for communication failure."""
48
49#-------------------------------------------------------------------------------
50
51def createSimulator(type, connectionListener):
52 """Create a simulator instance for the given simulator type with the given
53 connection listener.
54
55 The returned object should provide the following members:
56 FIXME: add info
57 """
58 assert type in [const.SIM_MSFS9, const.SIM_MSFSX], \
59 "Only MS Flight Simulator 2004 and X are supported"
60 return fsuipc.Simulator(connectionListener, connectAttempts = 3)
61
62#-------------------------------------------------------------------------------
63
64class MessageThread(threading.Thread):
65 """Thread to handle messages."""
66 def __init__(self, config, simulator):
67 """Initialize the message thread with the given configuration and
68 simulator."""
69 super(MessageThread, self).__init__()
70
71 self._config = config
72 self._simulator = simulator
73
74 self._requestCondition = threading.Condition()
75 self._messages = []
76 self._nextMessageTime = None
77 self._toQuit = False
78
79 self.daemon = True
80
81 def add(self, messageType, text, duration, disconnect):
82 """Add the given message to the requested messages."""
83 with self._requestCondition:
84 self._messages.append((messageType, text, duration,
85 disconnect))
86 self._requestCondition.notify()
87
88 def quit(self):
89 """Quit the thread."""
90 with self._requestCondition:
91 self._toQuit = True
92 self._requestCondition.notifty()
93 self.join()
94
95 def run(self):
96 """Perform the thread's operation."""
97 while True:
98 (messageType, text, duration, disconnect) = (None, None, None, None)
99 with self._requestCondition:
100 now = time.time()
101 while not self._toQuit and \
102 ((self._nextMessageTime is not None and \
103 self._nextMessageTime>now) or \
104 not self._messages):
105 self._requestCondition.wait(1)
106 now = time.time()
107
108 if self._toQuit: return
109 if self._nextMessageTime is None or \
110 self._nextMessageTime<=now:
111 self._nextMessageTime = None
112
113 if self._messages:
114 (messageType, text,
115 duration, disconnect) = self._messages[0]
116 del self._messages[0]
117
118 if text is not None:
119 self._sendMessage(messageType, text, duration, disconnect)
120
121 def _sendMessage(self, messageType, text, duration, disconnect):
122 """Send the message and setup the next message time."""
123 messageLevel = self._config.getMessageTypeLevel(messageType)
124 if messageLevel==const.MESSAGELEVEL_SOUND or \
125 messageLevel==const.MESSAGELEVEL_BOTH:
126 startSound(const.SOUND_NOTIFY
127 if messageType==const.MESSAGETYPE_VISIBILITY
128 else const.SOUND_DING)
129 if (messageLevel==const.MESSAGELEVEL_FS or \
130 messageLevel==const.MESSAGELEVEL_BOTH):
131 if disconnect:
132 self._simulator.disconnect("[MLX] " + text,
133 duration = duration)
134 else:
135 self._simulator.sendMessage("[MLX] " + text,
136 duration = duration)
137 elif disconnecte:
138 self._simulator.disconnect()
139 self._nextMessageTime = time.time() + duration
140
141#-------------------------------------------------------------------------------
142
143_messageThread = None
144
145#-------------------------------------------------------------------------------
146
147def setupMessageSending(config, simulator):
148 """Setup message sending with the given config and simulator."""
149 global _messageThread
150 if _messageThread is not None:
151 _messageThread.quit()
152 _messageThread = MessageThread(config, simulator)
153 _messageThread.start()
154
155#-------------------------------------------------------------------------------
156
157def sendMessage(messageType, text, duration = 3, disconnect = False):
158 """Send the given message of the given type into the simulator and/or play
159 a corresponding sound."""
160 global _messageThread
161 if _messageThread is not None:
162 _messageThread.add(messageType, text, duration, disconnect)
163
164#-------------------------------------------------------------------------------
165
166class AircraftState(object):
167 """Base class for the aircraft state produced by the aircraft model based
168 on readings from the simulator.
169
170 The following data members should be provided at least:
171 - timestamp: the simulator time of the measurement in seconds since the
172 epoch (float)
173 - latitude (in degrees, North is positive)
174 - longitude (in degrees, East is positive)
175 - paused: a boolean indicating if the flight simulator is paused for
176 whatever reason (it could be a pause mode, or a menu, a dialog, or a
177 replay, etc.)
178 - trickMode: a boolean indicating if some "trick" mode (e.g. "SLEW" in
179 MSFS) is activated
180 - overspeed: a boolean indicating if the aircraft is in overspeed
181 - stalled: a boolean indicating if the aircraft is stalled
182 - onTheGround: a boolean indicating if the aircraft is on the ground
183 - zfw: the zero-fuel weight in kilograms (float)
184 - grossWeight: the gross weight in kilograms (float)
185 - heading: the heading of the aircraft in degrees (float)
186 - pitch: the pitch of the aircraft in degrees. Positive means pitch down,
187 negative means pitch up (float)
188 - bank: the bank of the aircraft in degrees. Positive means bank left,
189 negative means bank right (float)
190 - ias: the indicated airspeed in knots (float)
191 - smoothedIAS: the smoothed IAS in knots (float)
192 - mach: the airspeed in mach (float)
193 - groundSpeed: the ground speed (float)
194 - vs: the vertical speed in feet/minutes (float)
195 - smoothedVS: the smoothed VS in feet/minutes (float)
196 - radioAltitude: the radio altitude of the aircraft in feet (float)
197 - altitude: the altitude of the aircraft in feet (float)
198 - gLoad: G-load (float)
199 - flapsSet: the selected degrees of the flaps (float)
200 - flaps: the actual degrees of the flaps (float)
201 - fuel[]: the fuel information. It is a list of tuples with items:
202 the fuel tank identifier and the amount of fuel in that tank in
203 kgs
204 - totalFuel: the total amount of fuel in kg
205 - n1[]: the N1 values of the turbine engines (array of floats
206 of as many items as the number of engines, present only for aircraft with
207 turbines, for other aircraft it is None)
208 - rpm[]: the RPM values of the piston engines (array of floats
209 of as many items as the number of engines, present only for aircraft with
210 pistons, for other aircraft it is None)
211 - reverser[]: an array of booleans indicating if the thrust reversers are
212 activated on any of the engines. The number of items equals to the number
213 of engines with a reverser.
214 - navLightsOn: a boolean indicating if the navigation lights are on
215 - antiCollisionLightsOn: a boolean indicating if the anti-collision lights are on
216 - strobeLightsOn: a boolean indicating if the strobe lights are on
217 - landingLightsOn: a boolean indicating if the landing lights are on
218 - pitotHeatOn: a boolean indicating if the pitot heat is on
219 - parking: a boolean indicating if the parking brake is set
220 - gearControlDown: a boolean indicating if the gear control is set to down
221 - gearsDown: a boolean indicating if the gears are down
222 - spoilersArmed: a boolean indicating if the spoilers have been armed for
223 automatic deployment
224 - spoilersExtension: the percentage of how much the spoiler is extended
225 (float)
226 - altimeter: the altimeter setting in hPa (float)
227 - nav1: the frequency of the NAV1 radio in MHz (string)
228 - nav2: the frequency of the NAV1 radio in MHz (string)
229 - squawk: the transponder code (string)
230 - windSpeed: the speed of the wind at the aircraft in knots (float)
231 - windDirection: the direction of the wind at the aircraft in degrees (float)
232 - visibility: the visibility in metres (float)
233 - cog: the centre of gravity
234
235 FIXME: needed when taxiing only:
236 - payload weight
237
238 FIXME: needed rarely:
239 - latitude, longitude
240 - transporter
241 - visibility
242 """
243
Note: See TracBrowser for help on using the repository browser.