source: src/mlx/fs.py@ 353:f3c95dc2eaea

version_0.11
Last change on this file since 353:f3c95dc2eaea was 341:c18840deae77, checked in by István Váradi <ivaradi@…>, 12 years ago

#114: the NAV lights are not considered for the DA F70

File size: 11.8 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 disconnect:
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. If
215 the detection of the state of the landing lights is unreliable, and should
216 not be considered, this is set to None.
217 - antiCollisionLightsOn: a boolean indicating if the anti-collision lights are on
218 - strobeLightsOn: a boolean indicating if the strobe lights are on
219 - landingLightsOn: a boolean indicating if the landing lights are on. If
220 the detection of the state of the landing lights is unreliable, and should
221 not be considered, this is set to None.
222 - pitotHeatOn: a boolean indicating if the pitot heat is on
223 - parking: a boolean indicating if the parking brake is set
224 - gearControlDown: a boolean indicating if the gear control is set to down
225 - gearsDown: a boolean indicating if the gears are down
226 - spoilersArmed: a boolean indicating if the spoilers have been armed for
227 automatic deployment
228 - spoilersExtension: the percentage of how much the spoiler is extended
229 (float)
230 - altimeter: the altimeter setting in hPa (float)
231 - nav1: the frequency of the NAV1 radio in MHz (string). Can be None, if
232 the frequency is unreliable or meaningless.
233 - nav1_obs: the OBS setting of the NAV1 radio in degrees (int). Can be None, if
234 the value is unreliable or meaningless.
235 - nav1_manual: a boolean indicating if the NAV1 radio is on manual control
236 - nav2: the frequency of the NAV1 radio in MHz (string). Can be None, if
237 the frequency is unreliable or meaningless.
238 - nav2_obs: the OBS setting of the NAV2 radio in degrees (int). Can be None, if
239 the value is unreliable or meaningless.
240 - nav2_manual: a boolean indicating if the NAV2 radio is on manual control
241 - adf1: the frequency of the ADF1 radio in kHz (string). Can be None, if
242 the frequency is unreliable or meaningless.
243 - adf2: the frequency of the ADF2 radio in kHz (string). Can be None, if
244 the frequency is unreliable or meaningless.
245 - squawk: the transponder code (string)
246 - windSpeed: the speed of the wind at the aircraft in knots (float)
247 - windDirection: the direction of the wind at the aircraft in degrees (float)
248 - visibility: the visibility in metres (float)
249 - cog: the centre of gravity
250 - xpdrC: a boolean indicating whether the transponder is in C mode, or
251 None, if the state cannot be read properly
252 - apMaster: a boolean indicating whether the autopilot is switched on, or
253 None, if the state cannot be read properly
254 - apHeadingHold: a boolean indicating whether the autopilot's heading hold
255 mode is switched on, or None, if the state cannot be read properly
256 - apHeading: the autopilot heading value in degrees (float),
257 or None, if the state cannot be read properly
258 - apAltitudeHold: a boolean indicating whether the autopilot's altitude hold
259 mode is switched on, or None, if the state cannot be read properly
260 - apAltitude: the autopilot altitude value in feet (float),
261 or None, if the state cannot be read properly
262 - elevatorTrim: a float value indicating the deflection of the elevator
263 trim in degrees
264 """
Note: See TracBrowser for help on using the repository browser.