source: src/mlx/fs.py@ 233:c0ab38ca1546

Last change on this file since 233:c0ab38ca1546 was 209:3172e5cab96e, checked in by István Váradi <ivaradi@…>, 12 years ago

The position of the gear control lever is logged

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