source: orbit/python/Puzzlebox/Orbit/Plugin_Orbit.py @ cb467b5

Last change on this file since cb467b5 was cb467b5, checked in by Steve Castellotti <sc@…>, 7 years ago
  • continued merge of Orbit from Jigsaw
  • Property mode set to 100644
File size: 36.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Jigsaw - Plug-in - Orbit
5#
6# Copyright Puzzlebox Productions, LLC (2013-2014)
7
8__changelog__ = """\
9Last Update: 2014.02.23
10"""
11
12__todo__ = """
13- Add warning message when trying to use audio IR transmitter
14- Quit message still says "Puzzlebox Jigsaw" (Interface.closeEvent)
15- Select default ThinkGear device from configuration file (debug default to emulator)
16"""
17
18import os, string, sys, time
19
20import Puzzlebox.Orbit.Configuration as configuration
21
22if configuration.ENABLE_PYSIDE:
23        try:
24                from PySide import QtCore, QtGui, QtNetwork
25                if configuration.DEFAULT_ORBIT_AUDIO_FRAMEWORK == 'Phonon':
26                        try:
27                                from PySide.phonon import Phonon
28                        except Exception, e:
29                                print "ERROR: [Plugin:Orbit] Exception importing Phonon:",
30                                print e
31                                configuration.DEFAULT_ORBIT_AUDIO_FRAMEWORK = 'QSound'
32        except Exception, e:
33                print "ERROR: [Plugin:Orbit] Exception importing PySide:",
34                print e
35                configuration.ENABLE_PYSIDE = False
36        else:
37                print "INFO: [Plugin:Orbit] Using PySide module"
38
39if not configuration.ENABLE_PYSIDE:
40        print "INFO: [Plugin:Orbit] Using PyQt4 module"
41        from PyQt4 import QtCore, QtGui, QtNetwork
42        if configuration.DEFAULT_ORBIT_AUDIO_FRAMEWORK == 'Phonon':
43                        try:
44                                from PyQt4.phonon import Phonon
45                        except Exception, e:
46                                print "ERROR: [Plugin:Orbit] Exception importing Phonon:",
47                                print e
48                                configuration.DEFAULT_ORBIT_AUDIO_FRAMEWORK = 'QSound'
49
50
51try:
52        from Puzzlebox.Jigsaw.Interface_Plot import *
53        MATPLOTLIB_AVAILABLE = True
54except Exception, e:
55        print "ERROR: Exception importing Puzzlebox.Jigsaw.Interface_Plot:",
56        print e
57        MATPLOTLIB_AVAILABLE = False
58
59#MATPLOTLIB_AVAILABLE = False
60
61if (sys.platform == 'win32'):
62        DEFAULT_IMAGE_PATH = 'images'
63elif (sys.platform == 'darwin'):
64        DEFAULT_IMAGE_PATH = 'images'
65else:
66        DEFAULT_IMAGE_PATH = '/usr/share/puzzlebox_orbit/images'
67
68
69try:
70        _fromUtf8 = QtCore.QString.fromUtf8
71except AttributeError:
72        _fromUtf8 = lambda s: s
73
74
75from Puzzlebox.Orbit.Design_Plugin_Orbit import Ui_Form as Design
76
77import Puzzlebox.Orbit.Protocol_Orbit as protocol_orbit
78#import puzzlebox_logger
79
80
81#####################################################################
82# Globals
83#####################################################################
84
85DEBUG = 1
86
87THINKGEAR_POWER_THRESHOLDS = { \
88       
89        'concentration': { \
90                0: 0, \
91                10: 0, \
92                20: 0, \
93                30: 0, \
94                40: 0, \
95                50: 0, \
96                60: 0, \
97                70: 0, \
98                71: 0, \
99                72: 60, \
100                73: 62, \
101                74: 64, \
102                75: 66, \
103                76: 68, \
104                77: 70, \
105                78: 72, \
106                79: 74, \
107                80: 76, \
108                81: 78, \
109                82: 80, \
110                83: 82, \
111                84: 84, \
112                85: 86, \
113                86: 88, \
114                87: 90, \
115                88: 90, \
116                89: 90, \
117                90: 100, \
118                100: 100, \
119                }, \
120       
121        'relaxation': { \
122                0: 0, \
123                10: 0, \
124                20: 0, \
125                30: 0, \
126                40: 0, \
127                50: 0, \
128                60: 0, \
129                70: 0, \
130                80: 0, \
131                90: 0, \
132                100: 0, \
133                }, \
134       
135} # THINKGEAR_POWER_THRESHOLDS
136
137ORBIT_LABEL_TITLE = '''
138<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
139<html><head><meta name="qrichtext" content="1" /><style type="text/css">
140p, li { white-space: pre-wrap; }
141</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
142<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://orbit.puzzlebox.info"><span style=" font-size:11pt; font-weight:600; text-decoration: none; color:#000000;">Puzzlebox<br />Orbit</span></a></p></body></html>
143'''
144
145ORBIT_LABEL_HELP_WEB_ADDRESS = '''
146<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
147<html><head><meta name="qrichtext" content="1" /><style type="text/css">
148p, li { white-space: pre-wrap; }
149</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
150<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://orbit.puzzlebox.info"><span style="text-decoration: none; color:#000000;; color:#0000ff;">http://orbit.puzzlebox.info</span></a></p></body></html>
151'''
152
153#####################################################################
154# Classes
155#####################################################################
156
157class puzzlebox_jigsaw_plugin_orbit(QtGui.QWidget, Design):
158       
159        def __init__(self, log, tabIndex=None, DEBUG=DEBUG, parent=None):
160               
161                self.log = log
162                self.DEBUG = DEBUG
163                self.parent = parent
164                self.tabIndex = tabIndex
165               
166                QtGui.QWidget.__init__(self, parent)
167                self.setupUi(self)
168               
169                self.configuration = configuration
170                self.thresholds = THINKGEAR_POWER_THRESHOLDS
171               
172                self.configureSettings()
173                self.connectWidgets()
174               
175                self.mediaState = None
176               
177                if self.configuration.DEFAULT_ORBIT_AUDIO_FRAMEWORK == 'Phonon':
178                        self.initializeAudioPhonon()
179                else:
180                        self.initializeAudio()
181               
182                self.name = "Jigsaw-Plugin-Orbit"
183                self.baseWidget = self.horizontalLayoutWidget
184                self.tabTitle = _fromUtf8("Orbit")
185               
186                if self.tabIndex == None:
187                        self.parent.tabWidget.addTab(self.baseWidget, self.tabTitle)
188                else:
189                        self.parent.tabWidget.insertTab(self.tabIndex, self.baseWidget, self.tabTitle)
190               
191                self.customDataHeaders = []
192                self.protocolSupport = ['EEG']
193               
194                self.current_power = 0
195               
196                self.pitch = 0
197                self.throttle = 0
198                self.yaw = 0
199                self.updateFlightCharateristics()
200               
201                self.protocol = None
202       
203       
204        ##################################################################
205       
206        def configureSettings(self):
207               
208                self.parent.setProgressBarColor( \
209                        self.progressBarOrbitConcentration, 'FF0000') # Red
210                self.parent.setProgressBarColor( \
211                        self.progressBarOrbitRelaxation, '0000FF') # Blue
212                self.parent.setProgressBarColor( \
213                        self.progressBarOrbitConnectionLevel, '00FF00') # Green
214                self.parent.setProgressBarColor( \
215                        self.progressBarOrbitPower, 'FCFF00') # Yellow
216               
217               
218                self.progressBarOrbitConcentration.setValue(0)
219                self.progressBarOrbitRelaxation.setValue(0)
220                self.progressBarOrbitConnectionLevel.setValue(0)
221                self.progressBarOrbitPower.setValue(0)
222                #self.dialOrbitPower.setValue(0)
223               
224                #self.pushButtonOrbitOn.setChecked(False)
225                #self.pushButtonOrbitOff.setChecked(True)
226               
227                # Tweak UI Elements
228                #self.pushButtonOrbitOn.setVisible(False)
229                #self.pushButtonOrbitOff.setVisible(False)
230                # Following command removed due to causing a segfault
231                #self.verticalLayout_5.removeItem(self.horizontalLayout_3)
232               
233               
234                #self.dialOrbitPower.setEnabled(False)
235               
236               
237                self.pushButtonOrbitConcentrationEnable.setVisible(False)
238                self.pushButtonOrbitRelaxationEnable.setVisible(False)
239               
240                self.comboBoxInfraredPortSelect.setVisible(False)
241                #self.pushButtonInfraredSearch.setEnabled(False)
242               
243                self.pushButtonInfraredConnect.setVisible(False)
244                self.pushButtonInfraredSearch.setVisible(False)
245               
246                #self.textLabelInfraredStatus.setText('Status: Unknown')
247                self.textLabelInfraredStatus.setVisible(False)
248               
249               
250                #self.searchInfraredDevices()
251                self.updateOrbitDeviceList()
252               
253                #index = string.uppercase.index(configuration.DEFAULT_ORBIT_HOUSE_CODE)
254                #self.comboBoxInfraredHouseCode.setCurrentIndex(index)
255                #self.comboBoxInfraredDeviceNumber.setCurrentIndex(configuration.DEFAULT_ORBIT_DEVICE - 1)
256               
257               
258                if MATPLOTLIB_AVAILABLE:
259                       
260                        windowBackgroundRGB =  (self.palette().window().color().red() / 255.0, \
261                                                self.palette().window().color().green() / 255.0, \
262                                                self.palette().window().color().blue() / 255.0)
263                       
264                        self.rawEEGMatplot = rawEEGMatplotlibCanvas( \
265                                                parent=self.widgetPlotRawEEG, \
266                                                width=self.widgetPlotRawEEG.width(), \
267                                                height=self.widgetPlotRawEEG.height(), \
268                                                title=None, \
269                                                axes_top_text='1.0s', \
270                                                axes_bottom_text='0.5s', \
271                                                facecolor=windowBackgroundRGB)
272                       
273                       
274                        self.historyEEGMatplot = historyEEGMatplotlibCanvas( \
275                                                    parent=self.widgetPlotHistory, \
276                                                    width=self.widgetPlotHistory.width(), \
277                                                    height=self.widgetPlotHistory.height(), \
278                                                    title=None, \
279                                                    axes_right_text='percent', \
280                                                    facecolor=windowBackgroundRGB)
281       
282       
283        ##################################################################
284
285        def connectWidgets(self):
286               
287                self.connect(self.comboBoxInfraredModelName, \
288                             QtCore.SIGNAL("activated(int)"), \
289                             self.updateOrbitDeviceList)
290               
291                self.connect(self.pushButtonInfraredSearch, \
292                             QtCore.SIGNAL("clicked()"), \
293                             self.searchInfraredDevices)
294               
295                self.connect(self.pushButtonInfraredConnect, \
296                             QtCore.SIGNAL("clicked()"), \
297                             self.connectInfraredDevice)
298               
299                self.connect(self.horizontalSliderOrbitConcentration, \
300                             QtCore.SIGNAL("valueChanged(int)"), \
301                             self.updateSliderConcentration)
302               
303                self.connect(self.horizontalSliderOrbitRelaxation, \
304                             QtCore.SIGNAL("valueChanged(int)"), \
305                             self.updateSliderRelaxation)
306               
307               
308                self.connect(self.pushButtonHelicopterHover, \
309                             QtCore.SIGNAL("clicked()"), \
310                             self.enableHelicopterHover)
311               
312                self.connect(self.pushButtonHelicopterForward, \
313                             QtCore.SIGNAL("clicked()"), \
314                             self.enableHelicopterForward)
315               
316                self.connect(self.pushButtonHelicopterSpinLeft, \
317                             QtCore.SIGNAL("clicked()"), \
318                             self.enableHelicopterSpinLeft)
319               
320                self.connect(self.pushButtonHelicopterSpinRight, \
321                             QtCore.SIGNAL("clicked()"), \
322                             self.enableHelicopterSpinRight)
323               
324                self.connect(self.pushButtonHelicopterTestFly, \
325                             QtCore.SIGNAL("clicked()"), \
326                             self.helicopterTestFly)
327               
328                self.connect(self.pushButtonHelicopterLand, \
329                             QtCore.SIGNAL("clicked()"), \
330                             self.helicopterLand)
331               
332               
333                self.connect(self.horizontalSliderOrbitPitch, \
334                             QtCore.SIGNAL("valueChanged(int)"), \
335                             self.updateSliderPitch)
336               
337                self.connect(self.horizontalSliderOrbitThrottle, \
338                             QtCore.SIGNAL("valueChanged(int)"), \
339                             self.updateSliderThrottle)
340               
341                self.connect(self.horizontalSliderOrbitYaw, \
342                             QtCore.SIGNAL("valueChanged(int)"), \
343                             self.updateSliderYaw)
344       
345       
346        ##################################################################
347       
348        def updateOrbitInterface(self):
349               
350                # Interface
351                self.parent.setWindowTitle("Puzzlebox Orbit")
352                self.parent.tabWidget.setTabText(0, "Puzzlebox")
353               
354                # Session
355                self.parent.plugin_session.textLabelTitlePuzzleboxJigsaw.setText(ORBIT_LABEL_TITLE)
356               
357                self.parent.plugin_session.labelSessionPluginAPI.hide()
358                self.parent.plugin_session.checkBoxServiceEnableJSON.setCheckable(False)
359                self.parent.plugin_session.checkBoxServiceEnableJSON.hide()
360                self.parent.plugin_session.lineSessionPluginAPI.hide()
361               
362                sessionGraphicFile = os.path.join( \
363                        os.getcwd(), \
364                        'images', \
365                        self.configuration.DEFAULT_ORBIT_SESSION_GRAPHIC)
366               
367                try:
368                        self.parent.plugin_session.labelSessionGraphic.setPixmap(QtGui.QPixmap(sessionGraphicFile))
369                except Exception, e:
370                        if self.DEBUG:
371                                print "ERROR [Plugin:Orbit] Exception:",
372                                print e
373               
374                # Help
375                self.parent.plugin_help.textLabelTitlePuzzleboxJigsaw.setText(ORBIT_LABEL_TITLE)
376                self.parent.plugin_help.labelWebsiteAddress.setText(ORBIT_LABEL_HELP_WEB_ADDRESS)
377                self.parent.plugin_help.loadWebURL(self.configuration.DEFAULT_ORBIT_HELP_URL)
378       
379       
380        ##################################################################
381       
382        def connectInfraredDevice(self):
383               
384                self.comboBoxInfraredModelName.setEnabled(False)
385                self.comboBoxInfraredPortSelect.setEnabled(False)
386                self.pushButtonInfraredSearch.setEnabled(False)
387               
388                self.disconnect(self.pushButtonInfraredConnect, \
389                                QtCore.SIGNAL("clicked()"), \
390                                self.connectInfraredDevice)
391               
392                self.connect(self.pushButtonInfraredConnect, \
393                             QtCore.SIGNAL("clicked()"), \
394                             self.disconnectInfraredDevice)
395               
396                self.pushButtonInfraredConnect.setText('Disconnect')
397               
398                infraredDevice = str(self.comboBoxInfraredModelName.currentText())
399                serial_device = str(self.comboBoxInfraredPortSelect.currentText())
400               
401                if infraredDevice == 'Puzzlebox Pyramid':
402                        mode = 'pyramid'
403                elif infraredDevice == 'Arduino Infrared Circuit':
404                        mode = 'arduino'
405               
406                self.protocol = protocol_orbit.puzzlebox_jigsaw_protocol_orbit( \
407                                   log=self.log, \
408                                   serial_port=serial_device, \
409                                   mode=mode, \
410                                   command='land', \
411                                   DEBUG=self.DEBUG, \
412                                   parent=self)
413               
414                self.protocol.start()
415       
416       
417        ##################################################################
418       
419        def disconnectInfraredDevice(self):
420               
421                self.comboBoxInfraredModelName.setEnabled(True)
422                self.comboBoxInfraredPortSelect.setEnabled(True)
423                self.pushButtonInfraredSearch.setEnabled(True)
424               
425                self.disconnect(self.pushButtonInfraredConnect, \
426                                QtCore.SIGNAL("clicked()"), \
427                                self.disconnectInfraredDevice)
428               
429                self.connect(self.pushButtonInfraredConnect, \
430                             QtCore.SIGNAL("clicked()"), \
431                             self.connectInfraredDevice)
432               
433                self.pushButtonInfraredConnect.setText('Connect')
434               
435               
436                if self.protocol != None:
437                        self.protocol.stop()
438               
439                self.protocol = None
440       
441       
442        ##################################################################
443       
444        def updateOrbitDeviceList(self, index=None):
445               
446                selection = str(self.comboBoxInfraredModelName.currentText())
447               
448                if selection == 'Puzzlebox Pyramid':
449                       
450                        self.comboBoxInfraredPortSelect.setVisible(True)
451                        self.pushButtonInfraredConnect.setVisible(True)
452                        #self.pushButtonInfraredSearch.setEnabled(True)
453                        self.pushButtonInfraredSearch.setVisible(True)
454               
455               
456                elif selection == 'Audio Infrared Dongle':
457                       
458                        self.comboBoxInfraredPortSelect.setVisible(False)
459                        self.pushButtonInfraredConnect.setVisible(False)
460                        #self.pushButtonInfraredSearch.setEnabled(False)
461                        self.pushButtonInfraredSearch.setVisible(False)
462               
463               
464                elif selection == 'Arduino Infrared Circuit':
465                       
466                        self.comboBoxInfraredPortSelect.setVisible(True)
467                        self.pushButtonInfraredConnect.setVisible(True)
468                        #self.pushButtonInfraredSearch.setEnabled(True)
469                        self.pushButtonInfraredSearch.setVisible(True)
470               
471               
472                self.searchInfraredDevices()
473       
474       
475        ##################################################################
476       
477        def searchInfraredDevices(self):
478               
479                self.comboBoxInfraredPortSelect.clear() # doesn't seem to work under OS X
480               
481                devices = self.searchForSerialDevices()
482               
483                if devices == []:
484                        devices = ['No Devices Found']
485                        self.comboBoxInfraredPortSelect.setEnabled(False)
486                        self.pushButtonInfraredConnect.setEnabled(False)
487                else:
488                        self.comboBoxInfraredPortSelect.setEnabled(True)
489                        self.pushButtonInfraredConnect.setEnabled(True)
490               
491                for device in devices:
492                        self.comboBoxInfraredPortSelect.addItem(device)
493       
494       
495        ##################################################################
496       
497        def searchForSerialDevices(self, devices=[]):
498               
499                if (sys.platform == 'win32'):
500                       
501                        for portname in self.parent.plugin_eeg.enumerateSerialPorts():
502                               
503                                if portname not in devices:
504                                        #portname = self.fullPortName(portname)
505                                        devices.append(portname)
506               
507                else:
508                       
509                        if os.path.exists('/dev/ttyUSB0'):
510                                devices.append('/dev/ttyUSB0')
511                        if os.path.exists('/dev/ttyUSB1'):
512                                devices.append('/dev/ttyUSB1')
513                        if os.path.exists('/dev/ttyUSB2'):
514                                devices.append('/dev/ttyUSB2')
515                        if os.path.exists('/dev/ttyUSB3'):
516                                devices.append('/dev/ttyUSB3')
517                        if os.path.exists('/dev/ttyUSB4'):
518                                devices.append('/dev/ttyUSB4')
519                        if os.path.exists('/dev/ttyUSB5'):
520                                devices.append('/dev/ttyUSB5')
521                        if os.path.exists('/dev/ttyUSB6'):
522                                devices.append('/dev/ttyUSB6')
523                        if os.path.exists('/dev/ttyUSB7'):
524                                devices.append('/dev/ttyUSB7')
525                        if os.path.exists('/dev/ttyUSB8'):
526                                devices.append('/dev/ttyUSB8')
527                        if os.path.exists('/dev/ttyUSB9'):
528                                devices.append('/dev/ttyUSB9')
529                       
530                        if os.path.exists('/dev/ttyACM0'):
531                                devices.append('/dev/ttyACM0')
532                        if os.path.exists('/dev/ttyACM1'):
533                                devices.append('/dev/ttyACM1')
534                        if os.path.exists('/dev/ttyACM2'):
535                                devices.append('/dev/ttyACM2')
536                        if os.path.exists('/dev/ttyACM3'):
537                                devices.append('/dev/ttyACM3')
538                        if os.path.exists('/dev/ttyACM4'):
539                                devices.append('/dev/ttyACM4')
540                       
541                        if os.path.exists('/dev/tty.usbmodemfd1221'):
542                                devices.append('/dev/tty.usbmodemfd1221')
543                        if os.path.exists('/dev/tty.usbmodemfd1222'):
544                                devices.append('/dev/tty.usbmodemfd1222')
545                       
546                        #if os.path.exists('/dev/tty.usbserial-A602050J'):
547                                #devices.append('/dev/tty.usbserial-A602050J')
548                        #if os.path.exists('/dev/tty.usbserial-A100MZB6'):
549                                #devices.append('/dev/tty.usbserial-A100MZB6')
550               
551               
552                if (sys.platform == 'darwin'):
553                        for device in os.listdir('/dev'):
554                                if device.startswith('tty.usbserial'):
555                                        devices.append(device)
556               
557               
558                return(devices)
559       
560       
561        ##################################################################
562       
563        def updateSliderConcentration(self):
564               
565                self.updatePowerThresholds()
566       
567       
568        ##################################################################
569       
570        def updateSliderRelaxation(self):
571               
572                self.updatePowerThresholds()
573       
574       
575        ##################################################################
576       
577        def updatePowerThresholds(self):
578               
579                minimum_power = self.configuration.DEFAULT_ORBIT_POWER_MINIMUM
580                maximum_power = self.configuration.DEFAULT_ORBIT_POWER_MAXIMUM
581               
582                # Reset all values to zero
583                for index in range(101):
584                        self.thresholds['concentration'][index] = 0
585                        self.thresholds['relaxation'][index] = 0
586               
587               
588                concentration_value = self.horizontalSliderOrbitConcentration.value()
589               
590                if concentration_value != 0:
591                       
592                        concentration_range = 101 - concentration_value
593                       
594                        for x in range(concentration_range):
595                               
596                                current_index = x + concentration_value
597                                if (concentration_value == 100):
598                                        percent_of_max_power = x # don't divide by zero
599                                else:
600                                        percent_of_max_power = x / (100.0 - concentration_value)
601                                new_power = minimum_power + ((maximum_power - minimum_power) * percent_of_max_power)
602                                self.thresholds['concentration'][current_index] = int(new_power)
603               
604               
605                relaxation_value = self.horizontalSliderOrbitRelaxation.value()
606               
607                if relaxation_value != 0:
608                        relaxation_range = 101 - relaxation_value
609                       
610                        for x in range(relaxation_range):
611                               
612                                current_index = x + relaxation_value
613                                if (relaxation_value == 100):
614                                        percent_of_max_power = x # don't divide by zero
615                                else:
616                                        percent_of_max_power = x / (100.0 - relaxation_value)
617                                new_power = minimum_power + ((maximum_power - minimum_power) * percent_of_max_power)
618                                self.thresholds['relaxation'][current_index] = int(new_power)
619               
620               
621                #if self.DEBUG > 2:
622                        #concentration_keys = self.thresholds['concentration'].keys()
623                        #concentration_keys.sort()
624                        #for key in concentration_keys:
625                                #print "%i: %i" % (key, self.thresholds['concentration'][key])
626                       
627                        #print
628                        #print
629                       
630                        #concentration_keys = self.thresholds['relaxation'].keys()
631                        #concentration_keys.sort()
632                        #for key in concentration_keys:
633                                #print "%i: %i" % (key, self.thresholds['relaxation'][key])
634       
635       
636        ##################################################################
637       
638        def processCustomData(self, packet):
639               
640                return(packet)
641       
642       
643        ##################################################################
644       
645        #def connectToThinkGearHost(self):
646               
647                #pass
648       
649       
650        ##################################################################
651       
652        #def disconnectFromThinkGearHost(self):
653               
654                #self.progressBarOrbitConcentration.setValue(0)
655                #self.progressBarOrbitRelaxation.setValue(0)
656                #self.progressBarOrbitConnectionLevel.setValue(0)
657       
658       
659        ##################################################################
660       
661        def updateEEGProcessingGUI(self):
662               
663                self.progressBarOrbitConcentration.setValue(0)
664                self.progressBarOrbitRelaxation.setValue(0)
665                self.progressBarOrbitConnectionLevel.setValue(0)
666               
667                self.stopControl()
668       
669       
670        ##################################################################
671       
672        def processPacketEEG(self, packet):
673               
674                self.processPacketThinkGear(packet)
675                #self.processPacketEmotiv(packet)
676       
677       
678        ##################################################################
679       
680        def processPacketThinkGear(self, packet):
681               
682                if (self.parent.tabWidget.currentIndex() == \
683                    self.tabIndex):
684                    #self.parent.tabWidget.indexOf(self.parent.tabOrbit))
685                       
686                        #if ('rawEeg' in packet.keys()):
687                                ##self.parent.packets['rawEeg'].append(packet['rawEeg'])
688                                ##value = packet['rawEeg']
689                                ##if MATPLOTLIB_AVAILABLE and \
690                                ##(self.parent.tabWidget.currentIndex() == self.tabIndex):
691                                        ##self.rawEEGMatplot.update_figure(value)
692                                #return
693                       
694                       
695                        if ('rawEeg' in packet.keys()):
696                                self.rawEEGMatplot.updateValues(packet['rawEeg'])
697                                return
698                       
699                       
700                        if ('eSense' in packet.keys()):
701                               
702                                #self.processEyeBlinks()
703                               
704                                if ('attention' in packet['eSense'].keys()):
705                                        if self.pushButtonOrbitConcentrationEnable.isChecked():
706                                                self.progressBarOrbitConcentration.setValue(packet['eSense']['attention'])
707                                               
708                                                # Perform custom function for packet data
709                                                #packet = self.processCustomData(packet)
710                               
711                               
712                                if ('meditation' in packet['eSense'].keys()):
713                                        if self.pushButtonOrbitRelaxationEnable.isChecked():
714                                                self.progressBarOrbitRelaxation.setValue(packet['eSense']['meditation'])
715                               
716                               
717                                self.updateOrbitPower()
718                                #self.updateProgressBarColors()
719                               
720                                if MATPLOTLIB_AVAILABLE:
721                                        self.historyEEGMatplot.updateValues('eSense', packet['eSense'])
722                                        if (self.parent.tabWidget.currentIndex() == self.tabIndex):
723                                                self.historyEEGMatplot.updateFigure('eSense', packet['eSense'])
724                       
725                       
726                        if ('poorSignalLevel' in packet.keys()):
727                               
728                                if packet['poorSignalLevel'] == 200:
729                                        value = 0
730                                        self.textLabelOrbitConnectionLevel.setText('No Contact')
731                                elif packet['poorSignalLevel'] == 0:
732                                        value = 100
733                                        self.textLabelOrbitConnectionLevel.setText('Connected')
734                                else:
735                                        value = int(100 - ((packet['poorSignalLevel'] / 200.0) * 100))
736                                self.textLabelOrbitConnectionLevel.setText('Connection Level')
737                                self.progressBarOrbitConnectionLevel.setValue(value)
738       
739       
740        ##################################################################
741       
742        #def processPacketEmotiv(self, packet):
743               
744                #pass
745       
746       
747        ##################################################################
748       
749        def updateOrbitPower(self, new_speed=None):
750               
751                if new_speed == None:
752                       
753                        concentration=self.progressBarOrbitConcentration.value()
754                        relaxation=self.progressBarOrbitRelaxation.value()
755                       
756                        new_speed = self.calculateSpeed(concentration, relaxation)
757               
758               
759                self.current_power = new_speed
760               
761                # Update GUI
762                #if self.pushButtonControlPowerEnable.isChecked():
763                        #self.progressBarControlPower.setValue(new_speed)
764               
765                self.progressBarOrbitPower.setValue(new_speed)
766                #self.dialOrbitPower.setValue(new_speed)
767               
768               
769                self.triggerActions(power=self.current_power)
770               
771               
772        ##################################################################
773       
774        def triggerActions(self, power):
775               
776                infraredDevice = str(self.comboBoxInfraredModelName.currentText())
777               
778                if power == 0:
779                       
780                        #self.pushButtonOrbitOn.setChecked(False)
781                        #self.pushButtonOrbitOff.setChecked(True)
782                       
783                        if infraredDevice == 'Puzzlebox Pyramid':
784                               
785                                if self.protocol != None:
786                                        #self.protocol.sendCommand('land')
787                                        self.protocol.land()
788                                        self.protocol.setColorWheel(255, 255, 0) # yellow
789                       
790                        elif infraredDevice == 'Audio Infrared Dongle':
791                                self.stopControl()
792                       
793                        elif infraredDevice == 'Arduino Infrared Circuit':
794                               
795                                if self.protocol != None:
796                                        #self.protocol.sendCommand('land')
797                                        self.protocol.land()
798               
799               
800                else:
801                       
802                        #self.pushButtonOrbitOn.setChecked(True)
803                        #self.pushButtonOrbitOff.setChecked(False)
804                       
805                        if infraredDevice == 'Puzzlebox Pyramid':
806                               
807                                if self.protocol != None:
808                                       
809                                        #self.protocol.sendCommand('hover')
810                                       
811                                        self.protocol.setThrottle(self.throttle)
812                                        self.protocol.setYaw(self.yaw)
813                                        self.protocol.setPitch(self.pitch)
814                                        self.protocol.setColorWheel(255, 255, 255) # yellow
815                       
816                        elif infraredDevice == 'Audio Infrared Dongle':
817                                self.playControl()
818                       
819                        elif infraredDevice == 'Arduino Infrared Circuit':
820                               
821                                if self.protocol != None:
822                                       
823                                        #self.protocol.sendCommand('hover')
824                                       
825                                        self.protocol.setThrottle(self.throttle)
826                                        self.protocol.setYaw(self.yaw)
827                                        self.protocol.setPitch(self.pitch)
828       
829       
830        ##################################################################
831       
832        def calculateSpeed(self, concentration, relaxation):
833               
834                speed = 0
835               
836                #thresholds = self.configuration.THINKGEAR_POWER_THRESHOLDS
837                #thresholds = THINKGEAR_POWER_THRESHOLDS
838               
839                match = int(concentration)
840               
841                while ((match not in self.thresholds['concentration'].keys()) and \
842                            (match >= 0)):
843                        match -= 1
844               
845               
846                if match in self.thresholds['concentration'].keys():
847                        speed = self.thresholds['concentration'][match]
848               
849               
850                match = int(relaxation)
851               
852                while ((match not in self.thresholds['relaxation'].keys()) and \
853                            (match >= 0)):
854                        match -= 1
855               
856                if match in self.thresholds['relaxation'].keys():
857                        speed = speed + self.thresholds['relaxation'][match]
858               
859               
860                # Power settings cannot exceed 100
861                # and must be higher than 50
862                if (speed > 100):
863                        speed = 100
864                elif (speed < 50):
865                        speed = 0
866               
867               
868                return(speed)
869       
870       
871        ##################################################################
872       
873        def initializeAudioFilePath(self):
874               
875                self.audio_file = os.path.join( \
876                        os.getcwd(), \
877                        'audio', \
878                        self.configuration.DEFAULT_ORBIT_AUDIO_FILE)
879       
880       
881        ##################################################################
882       
883        def initializeAudio(self):
884               
885                if self.DEBUG:
886                        print "INFO: [Plugin:Orbit] Using QSound Audio Framework"
887               
888                self.initializeAudioFilePath()
889               
890                self.media = QtGui.QSound(self.audio_file)
891               
892                self.media.setLoops(-1) # loop indefinitely
893               
894                #print dir(self.media)
895               
896                #self.media.play()
897       
898       
899        ##################################################################
900       
901        def initializeAudioPhonon(self):
902               
903                if self.DEBUG:
904                        print "INFO: [Plugin:Orbit] Using Phonon Audio Framework"
905               
906                self.initializeAudioFilePath()
907               
908                self.media = Phonon.MediaObject()
909               
910                #print dir(self.media)
911               
912                audio = Phonon.AudioOutput(Phonon.MusicCategory)
913                Phonon.createPath(self.media, audio)
914                f = QtCore.QFile(self.audio_file)
915                if f.exists():
916                        source = Phonon.MediaSource(self.audio_file)
917                        if source.type() != -1:                 # -1 stands for invalid file
918                                self.media.setCurrentSource(source)
919                               
920                                self.media.play()
921                               
922                        else:
923                                if self.DEBUG:
924                                        print "ERROR: [Plugin:Orbit] Audio control file invalid:",
925                                        print self.audio_file
926                else:
927                        if self.DEBUG:
928                                print "ERROR: [Plugin:Orbit] Audio control file does not exist:,"
929                                print self.audio_file
930       
931       
932        ##################################################################
933       
934        def audioFilePlaying(self):
935               
936                if (self.configuration.DEFAULT_ORBIT_AUDIO_FRAMEWORK == 'Phonon'):
937                       
938                        if (self.media.state() == Phonon.State.PlayingState):
939                               
940                                return True
941                       
942                        else:
943                               
944                                return False
945                               
946               
947                else:
948                       
949                        if self.mediaState == 'Playing':
950                               
951                                return True
952                               
953                        else:
954                               
955                                return False
956       
957       
958        ##################################################################
959       
960        def playControl(self):
961               
962                if (not self.audioFilePlaying()):
963                       
964                        if self.DEBUG:
965                                print "INFO: [Plugin:Orbit] Playing:",
966                                print self.audio_file
967                       
968                        self.media.play()
969                        self.mediaState = 'Playing'
970       
971       
972        ##################################################################
973       
974        def stopControl(self):
975               
976                if (self.audioFilePlaying()):
977                       
978                        if self.DEBUG:
979                                print "INFO: [Plugin:Orbit] Stopping:",
980                                print self.audio_file
981                       
982                        self.media.stop()
983                        self.mediaState = 'Stopped'
984       
985       
986        ##################################################################
987       
988        def updateSliderPitch(self):
989               
990                self.updateFlightCharateristics()
991       
992       
993        ##################################################################
994       
995        def updateSliderThrottle(self):
996               
997                self.updateFlightCharateristics()
998       
999       
1000        ##################################################################
1001       
1002        def updateSliderYaw(self):
1003               
1004                self.updateFlightCharateristics()
1005       
1006       
1007        ##################################################################
1008       
1009        def updateFlightCharateristics(self):
1010               
1011                self.pitch = self.horizontalSliderOrbitPitch.value()
1012                self.throttle = self.horizontalSliderOrbitThrottle.value()
1013                self.yaw = self.horizontalSliderOrbitYaw.value()
1014               
1015                matchFound = False
1016               
1017                for mode in self.configuration.ORBIT_CONTROL_SETTINGS.keys():
1018                       
1019                        settings = self.configuration.ORBIT_CONTROL_SETTINGS[mode]
1020                       
1021                        if ((self.throttle == settings['throttle']) and \
1022                            (self.yaw == settings['yaw']) and \
1023                            (self.pitch == settings['pitch'])):
1024                               
1025                                matchFound = True
1026                               
1027                                if mode == 'hover':
1028                                        if not self.pushButtonHelicopterHover.isChecked():
1029                                                self.enableHelicopterHover()
1030                               
1031                                elif mode == 'forward':
1032                                        if not self.pushButtonHelicopterForward.isChecked():
1033                                                self.enableHelicopterForward()
1034                               
1035                                elif mode == 'spinleft':
1036                                        if not self.pushButtonHelicopterSpinLeft.isChecked():
1037                                                self.enableHelicopterSpinLeft()
1038                               
1039                                elif mode == 'spinright':
1040                                        if not self.pushButtonHelicopterSpinRight.isChecked():
1041                                                self.enableHelicopterSpinRight()
1042               
1043               
1044                if not matchFound:
1045                        if self.pushButtonHelicopterHover.isChecked():
1046                                self.disableHelicopterHover()
1047                        elif self.pushButtonHelicopterForward.isChecked():
1048                                self.disableHelicopterForward()
1049                        elif self.pushButtonHelicopterSpinLeft.isChecked():
1050                                self.disableHelicopterSpinLeft()
1051                        elif self.pushButtonHelicopterSpinRight.isChecked():
1052                                self.disableHelicopterSpinRight()
1053       
1054       
1055        ##################################################################
1056       
1057        def setFlightPlan(self, mode):
1058               
1059                if mode in self.configuration.ORBIT_CONTROL_SETTINGS.keys():
1060                       
1061                        settings = self.configuration.ORBIT_CONTROL_SETTINGS[mode]
1062                       
1063                        self.horizontalSliderOrbitThrottle.setSliderPosition(settings['throttle'])
1064                        self.horizontalSliderOrbitYaw.setSliderPosition(settings['yaw'])
1065                        self.horizontalSliderOrbitPitch.setSliderPosition(settings['pitch'])
1066       
1067       
1068        ##################################################################
1069       
1070        def enableHelicopterHover(self):
1071               
1072                if not self.pushButtonHelicopterHover.isChecked():
1073                        self.pushButtonHelicopterHover.setChecked(True)
1074               
1075                if self.pushButtonHelicopterForward.isChecked():
1076                        self.pushButtonHelicopterForward.setChecked(False)
1077                        self.disableHelicopterForward()
1078               
1079                if self.pushButtonHelicopterSpinLeft.isChecked():
1080                        self.pushButtonHelicopterSpinLeft.setChecked(False)
1081                        self.disableHelicopterSpinLeft()
1082                       
1083                if self.pushButtonHelicopterSpinRight.isChecked():
1084                        self.pushButtonHelicopterSpinRight.setChecked(False)
1085                        self.disableHelicopterSpinRight()
1086               
1087               
1088                self.setFlightPlan('hover')
1089               
1090               
1091                self.disconnect(self.pushButtonHelicopterHover, \
1092                                QtCore.SIGNAL("clicked()"), \
1093                                self.enableHelicopterHover)
1094               
1095                self.connect(self.pushButtonHelicopterHover, \
1096                             QtCore.SIGNAL("clicked()"), \
1097                             self.disableHelicopterHover)
1098       
1099       
1100        ##################################################################
1101       
1102        def disableHelicopterHover(self):
1103               
1104                if self.pushButtonHelicopterHover.isChecked():
1105                        self.pushButtonHelicopterHover.setChecked(False)
1106               
1107                self.disconnect(self.pushButtonHelicopterHover, \
1108                                QtCore.SIGNAL("clicked()"), \
1109                                self.disableHelicopterHover)
1110               
1111                self.connect(self.pushButtonHelicopterHover, \
1112                             QtCore.SIGNAL("clicked()"), \
1113                             self.enableHelicopterHover)
1114       
1115       
1116        ##################################################################
1117       
1118        def enableHelicopterForward(self):
1119               
1120                if not self.pushButtonHelicopterForward.isChecked():
1121                        self.pushButtonHelicopterForward.setChecked(True)
1122               
1123                if self.pushButtonHelicopterHover.isChecked():
1124                        self.pushButtonHelicopterHover.setChecked(False)
1125                        self.disableHelicopterHover()
1126               
1127                if self.pushButtonHelicopterSpinLeft.isChecked():
1128                        self.pushButtonHelicopterSpinLeft.setChecked(False)
1129                        self.disableHelicopterSpinLeft()
1130                       
1131                if self.pushButtonHelicopterSpinRight.isChecked():
1132                        self.pushButtonHelicopterSpinRight.setChecked(False)
1133                        self.disableHelicopterSpinRight()
1134               
1135               
1136                self.setFlightPlan('forward')
1137               
1138               
1139                self.disconnect(self.pushButtonHelicopterForward, \
1140                                QtCore.SIGNAL("clicked()"), \
1141                                self.enableHelicopterForward)
1142               
1143                self.connect(self.pushButtonHelicopterForward, \
1144                             QtCore.SIGNAL("clicked()"), \
1145                             self.disableHelicopterForward)
1146       
1147       
1148        ##################################################################
1149       
1150        def disableHelicopterForward(self):
1151               
1152                if self.pushButtonHelicopterForward.isChecked():
1153                        self.pushButtonHelicopterForward.setChecked(False)
1154               
1155                self.disconnect(self.pushButtonHelicopterForward, \
1156                                QtCore.SIGNAL("clicked()"), \
1157                                self.disableHelicopterForward)
1158               
1159                self.connect(self.pushButtonHelicopterForward, \
1160                             QtCore.SIGNAL("clicked()"), \
1161                             self.enableHelicopterForward)
1162       
1163       
1164        ##################################################################
1165       
1166        def enableHelicopterSpinLeft(self):
1167               
1168                if not self.pushButtonHelicopterSpinLeft.isChecked():
1169                        self.pushButtonHelicopterSpinLeft.setChecked(True)
1170               
1171                if self.pushButtonHelicopterHover.isChecked():
1172                        self.pushButtonHelicopterHover.setChecked(False)
1173                        self.disableHelicopterHover()
1174               
1175                if self.pushButtonHelicopterForward.isChecked():
1176                        self.pushButtonHelicopterForward.setChecked(False)
1177                        self.disableHelicopterForward()
1178                       
1179                if self.pushButtonHelicopterSpinRight.isChecked():
1180                        self.pushButtonHelicopterSpinRight.setChecked(False)
1181                        self.disableHelicopterSpinRight()
1182               
1183               
1184                self.setFlightPlan('spinleft')
1185               
1186               
1187                self.disconnect(self.pushButtonHelicopterSpinLeft, \
1188                                QtCore.SIGNAL("clicked()"), \
1189                                self.enableHelicopterSpinLeft)
1190               
1191                self.connect(self.pushButtonHelicopterSpinLeft, \
1192                             QtCore.SIGNAL("clicked()"), \
1193                             self.disableHelicopterSpinLeft)
1194       
1195       
1196        ##################################################################
1197       
1198        def disableHelicopterSpinLeft(self):
1199               
1200                if self.pushButtonHelicopterSpinLeft.isChecked():
1201                        self.pushButtonHelicopterSpinLeft.setChecked(False)
1202               
1203                self.disconnect(self.pushButtonHelicopterSpinLeft, \
1204                                QtCore.SIGNAL("clicked()"), \
1205                                self.disableHelicopterSpinLeft)
1206               
1207                self.connect(self.pushButtonHelicopterSpinLeft, \
1208                             QtCore.SIGNAL("clicked()"), \
1209                             self.enableHelicopterSpinLeft)
1210       
1211       
1212        ##################################################################
1213       
1214        def enableHelicopterSpinRight(self):
1215               
1216                if not self.pushButtonHelicopterSpinRight.isChecked():
1217                        self.pushButtonHelicopterSpinRight.setChecked(True)
1218               
1219                if self.pushButtonHelicopterHover.isChecked():
1220                        self.pushButtonHelicopterHover.setChecked(False)
1221                        self.disableHelicopterHover()
1222               
1223                if self.pushButtonHelicopterForward.isChecked():
1224                        self.pushButtonHelicopterForward.setChecked(False)
1225                        self.disableHelicopterForward()
1226                       
1227                if self.pushButtonHelicopterSpinLeft.isChecked():
1228                        self.pushButtonHelicopterSpinLeft.setChecked(False)
1229                        self.disableHelicopterSpinLeft()
1230               
1231               
1232                self.setFlightPlan('spinright')
1233               
1234               
1235                self.disconnect(self.pushButtonHelicopterSpinRight, \
1236                                QtCore.SIGNAL("clicked()"), \
1237                                self.enableHelicopterSpinRight)
1238               
1239                self.connect(self.pushButtonHelicopterSpinRight, \
1240                             QtCore.SIGNAL("clicked()"), \
1241                             self.disableHelicopterSpinRight)
1242       
1243       
1244        ##################################################################
1245       
1246        def disableHelicopterSpinRight(self):
1247               
1248                if self.pushButtonHelicopterSpinRight.isChecked():
1249                        self.pushButtonHelicopterSpinRight.setChecked(False)
1250               
1251                self.disconnect(self.pushButtonHelicopterSpinRight, \
1252                                QtCore.SIGNAL("clicked()"), \
1253                                self.disableHelicopterSpinRight)
1254               
1255                self.connect(self.pushButtonHelicopterSpinRight, \
1256                             QtCore.SIGNAL("clicked()"), \
1257                             self.enableHelicopterSpinRight)
1258       
1259       
1260        ##################################################################
1261       
1262        def helicopterLand(self):
1263               
1264                self.horizontalSliderOrbitConcentration.setSliderPosition(0)
1265                self.updateSliderConcentration()
1266                self.triggerActions(power=0)
1267       
1268       
1269        ##################################################################
1270       
1271        def helicopterTestFly(self):
1272               
1273                self.triggerActions(power=100)
1274       
1275       
1276        ##################################################################
1277       
1278        def stop(self):
1279               
1280                self.triggerActions(power=0)
1281               
1282                self.disconnectInfraredDevice()
1283
1284
1285#####################################################################
1286# Functions
1287#####################################################################
1288
1289#####################################################################
1290# Main
1291#####################################################################
1292
1293#if __name__ == '__main__':
1294       
1295        #pass
Note: See TracBrowser for help on using the repository browser.