source: trunk/Puzzlebox/Brainstorms/Interface.py @ 361

Last change on this file since 361 was 361, checked in by sc, 6 years ago
  • Added NXT-B device detection
File size: 69.2 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Interface
5#
6# Copyright Puzzlebox Productions, LLC (2010-2012)
7#
8# This code is released under the GNU Pulic License (GPL) version 2
9# For more information please refer to http://www.gnu.org/copyleft/gpl.html
10
11__changelog__ = """\
12Last Update: 2012.08.20
13
14"""
15
16__todo__ = """
17 - ERROR: could not open port /dev/ttyUSB0: [Errno 13] Permission denied: '/dev/ttyUSB0' /dev/ttyUSB0
18 - ERROR: Could not configure port: (5, 'Input/output error') /dev/ttyS0
19 - server may not correctly handle multiple clients connected
20      to an embedded Brainstorms server
21 - add setting to configuration.ini for which helicopter command gets
22      called when speed reaches threshold
23 - disable autorepeating on shortcut keys
24 - update configuration.ini file with settings entered into interface
25
26"""
27
28import os, sys, time
29import urllib
30
31if (sys.platform == 'win32'):
32        DEFAULT_IMAGE_PATH = 'images'
33        import _winreg as winreg
34        import itertools
35        import re
36        import serial
37else:
38        #import bluetooth
39        if os.path.exists('/usr/share/puzzlebox_brainstorms'):
40                os.chdir('/usr/share/puzzlebox_brainstorms')
41        if os.path.exists('/usr/share/puzzlebox_brainstorms'):
42                DEFAULT_IMAGE_PATH = '/usr/share/puzzlebox_brainstorms/images'
43        else:
44                DEFAULT_IMAGE_PATH = os.path.join( os.getcwd(), 'images')
45
46import Configuration as configuration
47
48if configuration.ENABLE_PYSIDE:
49        try:
50                import PySide as PyQt4
51                from PySide import QtCore, QtGui, QtNetwork
52        except Exception, e:
53                print "ERROR: Exception importing PySide:",
54                print e
55                configuration.ENABLE_PYSIDE = False
56        else:
57                print "INFO: [Brainstorms:Interface] Using PySide module"
58
59if not configuration.ENABLE_PYSIDE:
60        print "INFO: [Brainstorms:Interface] Using PyQt4 module"
61        from PyQt4 import QtCore, QtGui, QtNetwork
62
63from Interface_Design import Ui_Form as Design
64
65import simplejson as json
66
67import Client as brainstorms_client
68import Puzzlebox.Brainstorms.ThinkGear.Client as thinkgear_client
69import Helicopter_Control as helicopter_control
70import Wheelchair_Control as wheelchair_control
71#import puzzlebox_logger
72
73#####################################################################
74# Globals
75#####################################################################
76
77DEBUG = 1
78
79BLINK_DETECTION_ENABLED = configuration.BLINK_DETECTION_ENABLED
80BLINK_DETECTION_THRESHOLD = configuration.BLINK_DETECTION_THRESHOLD
81BLINK_DETECTION_VALID_RANGE = configuration.BLINK_DETECTION_VALID_RANGE
82
83BLINK_DETECTION_INCLUDE_FORWARD = configuration.BLINK_DETECTION_INCLUDE_FORWARD
84BLINK_DETECTION_INCLUDE_LEFT = configuration.BLINK_DETECTION_INCLUDE_LEFT
85BLINK_DETECTION_INCLUDE_RIGHT = configuration.BLINK_DETECTION_INCLUDE_RIGHT
86BLINK_DETECTION_INCLUDE_REVERSE = configuration.BLINK_DETECTION_INCLUDE_REVERSE
87
88THINKGEAR_POWER_THRESHOLDS = configuration.THINKGEAR_POWER_THRESHOLDS
89
90DEFAULT_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
91
92#NXT_BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
93
94DEFAULT_NXT_POWER_LEVEL = configuration.DEFAULT_NXT_POWER_LEVEL
95
96WHEELCHAIR_CONTROL_EEG = configuration.WHEELCHAIR_CONTROL_EEG
97
98THINKGEAR_SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
99THINKGEAR_SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
100
101BRAINSTORMS_FEEDBACK_URL = 'http://brainstorms.puzzlebox.info/contact_cgi.php'
102
103DEVICE_PATH = '/dev'
104PATH_TO_HCITOOL = '/usr/bin/hcitool'
105
106#####################################################################
107# Classes
108#####################################################################
109
110class puzzlebox_brainstorms_client_interface(QtGui.QWidget, Design):
111       
112        def __init__(self, log, server=None, DEBUG=DEBUG, parent = None):
113               
114                self.log = log
115                self.DEBUG = DEBUG
116               
117                QtGui.QWidget.__init__(self, parent)
118                self.setupUi(self)
119               
120                self.configureSettings()
121                self.connectWidgets()
122               
123                self.name = "Brainstorms Interface"
124               
125                self.robot_type = None
126               
127                self.brainstormsServer = server
128                self.brainstormsClient = None
129               
130                self.helicopter = None
131                self.wheelchair = None
132               
133                self.drive_state = 'stop_motors'
134                self.current_speed = 0
135               
136                self.current_helicopter_state = 'neutral'
137               
138                self.blinks = {}
139       
140       
141        ##################################################################
142       
143        def configureSettings(self):
144               
145                # Brainstorms Interface
146               
147                image_path = "puzzlebox.ico"
148                if not os.path.exists(image_path):
149                        image_path = os.path.join(DEFAULT_IMAGE_PATH, image_path)
150               
151                if os.path.exists(image_path):
152                        icon = QtGui.QIcon()
153                        icon.addPixmap(QtGui.QPixmap(image_path), \
154                                            QtGui.QIcon.Normal, \
155                                            QtGui.QIcon.Off)
156                        self.setWindowIcon(icon)
157               
158                image_path = "puzzlebox_logo.png"
159                if not os.path.exists(image_path):
160                        image_path = os.path.join(DEFAULT_IMAGE_PATH, image_path)
161                if os.path.exists(image_path):
162                        self.labelPuzzlebox.setPixmap(QtGui.QPixmap(image_path))
163               
164                self.pushButtonTurnLeft.setEnabled(False)
165                self.pushButtonForward.setEnabled(False)
166                self.pushButtonTurnRight.setEnabled(False)
167                self.pushButtonTurnLeftReverse.setEnabled(False)
168                self.pushButtonReverse.setEnabled(False)
169                self.pushButtonTurnRightReverse.setEnabled(False)
170               
171                self.pushButtonConcentrationEnable.setDown(True)
172                self.pushButtonRelaxationEnable.setDown(True)
173                self.pushButtonSpeedEnable.setDown(True)
174               
175               
176                # Search for available Serial and Bluetooth devices
177                self.searchForDevices()
178               
179               
180                # Robotics
181                self.textLabelRobotStatus.setText("Status: Disconnected")
182               
183                # Display communication port for LEGO Mindstorms NXT device
184                #self.lineEditNXTPort.setText(DEFAULT_DEVICE)
185                self.comboBoxRobotPortSelect.setEnabled(True)
186               
187               
188                # RC Helicopter
189                self.textLabelHelicopterStatus.setText("Status: Disconnected")
190               
191               
192                # Wheelchair
193                self.textLabelWheelchairStatus.setText("Status: Disconnected")
194               
195               
196                # Control Panel
197               
198                # Display Host for ThinkGear Connect Socket Server
199                self.lineEditThinkGearHost.setText(THINKGEAR_SERVER_HOST)
200                #self.lineEditThinkGearHost.setEnabled(False)
201               
202                # Display Port for ThinkGear Connect Socket Server
203                self.lineEditThinkGearPort.setText('%i' % THINKGEAR_SERVER_PORT)
204                #self.lineEditThinkGearPort.setEnabled(False)
205               
206               
207                self.lineEditLeftMotorPort.setText( \
208                   configuration.NXT_MOTOR_PORT_LEFT.upper() )
209                self.lineEditRightMotorPort.setText( \
210                   configuration.NXT_MOTOR_PORT_RIGHT.upper() )
211                self.checkBoxMotorSpinReversed.setChecked( \
212                   configuration.NXT_MOTORS_MOUNTED_BACKWARDS)
213               
214                self.lineEditBlinkDetectionThreshold.setText( \
215                        "%s" % configuration.BLINK_DETECTION_THRESHOLD)
216                self.checkBoxBlinkDetectionEnabled.setChecked( \
217                        configuration.BLINK_DETECTION_ENABLED)
218       
219       
220        ##################################################################
221       
222        def getMinimumThreshold(self, threshold):
223               
224                '''Return the minimum detection level which results
225                in a non-zero power setting'''
226               
227                minimum = 100
228               
229                threshold_keys = threshold.keys()
230                threshold_keys.sort()
231                threshold_keys.reverse()
232               
233                for key in threshold_keys:
234                       
235                        if ((threshold[key] < minimum) and \
236                                 (threshold[key] > 0)):
237                                minimum = key
238               
239               
240                return(minimum)
241       
242       
243        ##################################################################
244       
245        def configureNetworkBrainstorms(self):
246               
247                self.robot_type = str(self.comboBoxRobotTypeSelect.currentText())
248                if self.robot_type == 'LEGO Mindstorms':
249                        self.robot_type = 'NXT'
250               
251                device_address = str(self.comboBoxRobotPortSelect.currentText())
252               
253                self.brainstormsClient = \
254                   brainstorms_client.puzzlebox_brainstorms_network_client( \
255                           self.log, \
256                           device_address=device_address, \
257                           robot_type=self.robot_type, \
258                           parent=self)
259               
260                self.brainstormsClient.sendCommand('connect', \
261                                                   device_address=device_address)
262               
263                if self.robot_type == 'NXT':
264                        self.updateLeftMotorPort()
265                        self.updateRightMotorPort()
266                        self.updateMotorSpinReversed()
267       
268       
269        ##################################################################
270       
271        def connectToBrainstormsServer(self):
272               
273                # Prevent attempting to connect to a device which does not exist
274                device = str(self.comboBoxRobotPortSelect.currentText())
275                if device == 'N/A':
276                        self.pushButtonRobotConnect.setChecked(False)
277                        return
278                if (sys.platform != 'win32'):
279                        if ((not device.startswith(DEVICE_PATH)) or \
280                            (not os.path.exists(device))):
281                                self.searchForDevices()
282                                self.pushButtonRobotConnect.setChecked(False)
283                                return
284               
285               
286                if self.DEBUG:
287                        print "<---- [%s] Connecting to Brainstorms Server" % self.name
288               
289                self.configureNetworkBrainstorms()
290               
291                #if (self.brainstormsClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
292                        #QtGui.QMessageBox.information(self, \
293                                                                #self.brainstormsClient.socket.name, \
294                                           #"Failed to connect to Brainstorms socket server")
295               
296                #else:
297                self.disconnect(self.pushButtonRobotConnect, \
298                                                        QtCore.SIGNAL("clicked()"), \
299                                                        self.connectToBrainstormsServer)
300               
301                self.connect(self.pushButtonRobotConnect, \
302                                                        QtCore.SIGNAL("clicked()"), \
303                                                        self.disconnectFromBrainstormsServer)
304               
305                self.textLabelRobotStatus.setText("Status: Connected")
306                self.pushButtonRobotConnect.setText('Disconnect')
307               
308                self.comboBoxRobotTypeSelect.setEnabled(False)
309                self.comboBoxRobotPortSelect.setEnabled(False)
310                self.pushButtonRobotSearch.setEnabled(False)
311               
312                self.pushButtonTurnLeft.setEnabled(True)
313                self.pushButtonForward.setEnabled(True)
314                self.pushButtonTurnRight.setEnabled(True)
315                self.pushButtonTurnLeftReverse.setEnabled(True)
316                self.pushButtonReverse.setEnabled(True)
317                self.pushButtonTurnRightReverse.setEnabled(True)
318               
319                self.pushButtonTurnLeft.setFlat(True)
320                self.pushButtonForward.setFlat(False)
321                self.pushButtonTurnRight.setFlat(True)
322                self.pushButtonTurnLeftReverse.setFlat(True)
323                self.pushButtonReverse.setFlat(True)
324                self.pushButtonTurnRightReverse.setFlat(True)
325               
326               
327                self.pushButtonNXTMessageOne.setEnabled(True)
328                self.pushButtonNXTMessageTwo.setEnabled(True)
329                self.pushButtonNXTMessageThree.setEnabled(True)
330                self.pushButtonNXTMessageFour.setEnabled(True)
331                #self.pushButtonNXTMessageFive.setEnabled(True)
332                #self.pushButtonNXTMessageSix.setEnabled(True)
333               
334                self.pushButtonConcentrationEnable.setEnabled(True)
335                self.pushButtonRelaxationEnable.setEnabled(True)
336                self.pushButtonSpeedEnable.setEnabled(True)
337               
338                self.pushButtonMessageOne.setEnabled(True)
339                self.pushButtonMessageTwo.setEnabled(True)
340                self.pushButtonMessageThree.setEnabled(True)
341                self.pushButtonMessageFour.setEnabled(True)
342                #self.pushButtonMessageFive.setEnabled(True)
343                #self.pushButtonMessageSix.setEnabled(True)
344       
345       
346        ##################################################################
347       
348        def disconnectFromBrainstormsServer(self):
349               
350                if self.DEBUG:
351                        print "- - [%s] Disconnecting from Brainstorms Server" % self.name
352               
353                self.stopMotors()
354               
355                # Ensure the stopMotors command has been received by the server
356                # so the NXT robot will stop before the client disconnects
357                self.brainstormsClient.socket.flush()
358               
359                self.brainstormsClient.socket.disconnectFromHost()
360               
361                self.disconnect(self.pushButtonRobotConnect, \
362                                  QtCore.SIGNAL("clicked()"), \
363                                  self.disconnectFromBrainstormsServer)
364               
365                self.connect(self.pushButtonRobotConnect, \
366                                  QtCore.SIGNAL("clicked()"), \
367                                  self.connectToBrainstormsServer)
368               
369                self.textLabelRobotStatus.setText("Status: Disconnected")
370                self.pushButtonRobotConnect.setText('Connect')
371               
372                self.comboBoxRobotTypeSelect.setEnabled(True)
373                self.comboBoxRobotPortSelect.setEnabled(True)
374                self.pushButtonRobotSearch.setEnabled(True)
375               
376                self.pushButtonTurnLeft.setEnabled(False)
377                self.pushButtonForward.setEnabled(False)
378                self.pushButtonTurnRight.setEnabled(False)
379                self.pushButtonTurnLeftReverse.setEnabled(False)
380                self.pushButtonReverse.setEnabled(False)
381                self.pushButtonTurnRightReverse.setEnabled(False)
382               
383                self.pushButtonTurnLeft.setFlat(False)
384                self.pushButtonForward.setFlat(False)
385                self.pushButtonTurnRight.setFlat(False)
386                self.pushButtonTurnLeftReverse.setFlat(False)
387                self.pushButtonReverse.setFlat(False)
388                self.pushButtonTurnRightReverse.setFlat(False)
389               
390                self.pushButtonNXTMessageOne.setEnabled(False)
391                self.pushButtonNXTMessageTwo.setEnabled(False)
392                self.pushButtonNXTMessageThree.setEnabled(False)
393                self.pushButtonNXTMessageFour.setEnabled(False)
394                #self.pushButtonNXTMessageFive.setEnabled(False)
395                #self.pushButtonNXTMessageSix.setEnabled(False)
396               
397                self.pushButtonConcentrationEnable.setEnabled(False)
398                self.pushButtonRelaxationEnable.setEnabled(False)
399                self.pushButtonSpeedEnable.setEnabled(False)
400               
401                self.pushButtonMessageOne.setEnabled(False)
402                self.pushButtonMessageTwo.setEnabled(False)
403                self.pushButtonMessageThree.setEnabled(False)
404                self.pushButtonMessageFour.setEnabled(False)
405                #self.pushButtonMessageFive.setEnabled(False)
406                #self.pushButtonMessageSix.setEnabled(False)
407               
408                self.brainstormsClient = None
409               
410                self.searchForDevices()
411       
412       
413        ##################################################################
414       
415        def connectToThinkGearHost(self):
416               
417                if self.DEBUG:
418                        print "Connecting to ThinkGear Host"
419               
420                server_host = str(self.lineEditThinkGearHost.text())
421                server_port = int(self.lineEditThinkGearPort.text())
422               
423                self.thinkgearClient = \
424                   thinkgear_client.puzzlebox_brainstorms_network_client_thinkgear( \
425                           self.log, \
426                           server_host=server_host, \
427                           server_port=server_port, \
428                           DEBUG=0, \
429                           parent=self)
430               
431                if (self.thinkgearClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
432                        QtGui.QMessageBox.information(self, \
433                                                                self.thinkgearClient.socket.name, \
434                                           "Failed to connect to ThinkGear socket server")
435               
436                else:
437                        self.disconnect(self.pushButtonThinkGearConnect, \
438                                                         QtCore.SIGNAL("clicked()"), \
439                                                         self.connectToThinkGearHost)
440                       
441                        self.connect(self.pushButtonThinkGearConnect, \
442                                                         QtCore.SIGNAL("clicked()"), \
443                                                         self.disconnectFromThinkGearHost)
444                       
445                        self.pushButtonThinkGearConnect.setText('Disconnect')
446                       
447                        self.comboBoxEEGHeadsetModel.setEnabled(False)
448                        self.comboBoxEEGSource.setEnabled(False)
449                        self.lineEditThinkGearHost.setEnabled(False)
450                        self.lineEditThinkGearPort.setEnabled(False)
451                       
452                        self.progressBarBlinkDetection.setValue(0)
453       
454       
455        ##################################################################
456       
457        def disconnectFromThinkGearHost(self):
458               
459                if self.DEBUG:
460                        print "Disconnecting from ThinkGear Host"
461               
462                self.thinkgearClient.disconnectFromHost()
463               
464                self.disconnect(self.pushButtonThinkGearConnect, \
465                                  QtCore.SIGNAL("clicked()"), \
466                                  self.disconnectFromThinkGearHost)
467               
468                self.connect(self.pushButtonThinkGearConnect, \
469                                  QtCore.SIGNAL("clicked()"), \
470                                  self.connectToThinkGearHost)
471               
472                self.pushButtonTurnLeft.emit(QtCore.SIGNAL("released()"))
473                self.pushButtonForward.emit(QtCore.SIGNAL("released()"))
474                self.pushButtonTurnRight.emit(QtCore.SIGNAL("released()"))
475                self.pushButtonTurnLeftReverse.emit(QtCore.SIGNAL("released()"))
476                self.pushButtonReverse.emit(QtCore.SIGNAL("released()"))
477                self.pushButtonTurnRightReverse.emit(QtCore.SIGNAL("released()"))
478               
479                self.pushButtonThinkGearConnect.setText('Connect')
480               
481                self.comboBoxEEGHeadsetModel.setEnabled(True)
482                self.comboBoxEEGSource.setEnabled(True)
483                self.lineEditThinkGearHost.setEnabled(True)
484                self.lineEditThinkGearPort.setEnabled(True)
485               
486                self.progressBarConcentration.setValue(0)
487                self.progressBarRelaxation.setValue(0)
488                self.progressBarSpeed.setValue(0)
489       
490                self.progressBarHelicopterConcentration.setValue(0)
491                self.progressBarHelicopterRelaxation.setValue(0)
492                self.progressBarHelicopterSpeed.setValue(0)
493       
494                self.progressBarWheelchairConcentration.setValue(0)
495                self.progressBarWheelchairRelaxation.setValue(0)
496                self.progressBarWheelchairSpeed.setValue(0)
497       
498       
499        ##################################################################
500       
501        def connectToRCHelicopter(self):
502
503                # Prevent attempting to connect to a device which does not exist
504                device = str(self.comboBoxHelicopterPortSelect.currentText())
505                if device == 'N/A':
506                        self.pushButtonHelicopterConnect.setChecked(False)
507                        return
508                if (sys.platform != 'win32'):
509                        if ((not device.startswith(DEVICE_PATH)) or \
510                            (not os.path.exists(device))):
511                                self.searchForDevices()
512                                self.pushButtonHelicopterConnect.setChecked(False)
513                                return
514
515                self.helicopter = \
516                   helicopter_control.puzzlebox_brainstorms_helicopter_control( \
517                      device_address=device,
518                      command='neutral', \
519                      DEBUG=self.DEBUG)
520               
521                self.helicopter.start()
522               
523                self.disconnect(self.pushButtonHelicopterConnect, \
524                                  QtCore.SIGNAL("clicked()"), \
525                                  self.connectToRCHelicopter)
526               
527                self.connect(self.pushButtonHelicopterConnect, \
528                                  QtCore.SIGNAL("clicked()"), \
529                                  self.disconnectFromRCHelicopter)
530               
531                self.pushButtonHelicopterConnect.setText('Disconnect')
532               
533                self.comboBoxHelicopterTransmitter.setEnabled(False)
534                self.comboBoxHelicopterPortSelect.setEnabled(False)
535                self.pushButtonHelicopterSearch.setEnabled(False)
536               
537                self.pushButtonHelicopterHover.setEnabled(True)
538                self.pushButtonHelicopterFlyForward.setEnabled(True)
539                self.pushButtonHelicopterLand.setEnabled(True)
540                self.pushButtonHelicopterThrottle.setEnabled(True)
541                self.verticalSliderHelicopterThrottle.setEnabled(True)
542                self.pushButtonHelicopterElevatorForward.setEnabled(True)
543                self.verticalSliderHelicopterElevatorForward.setEnabled(True)
544                self.pushButtonHelicopterElevatorReverse.setEnabled(True)
545                self.verticalSliderHelicopterElevatorReverse.setEnabled(True)
546                self.pushButtonHelicopterRudderLeft.setEnabled(True)
547                self.horizontalSliderHelicopterRudderLeft.setEnabled(True)
548                self.pushButtonHelicopterRudderRight.setEnabled(True)
549                self.horizontalSliderHelicopterRudderRight.setEnabled(True)
550                self.pushButtonHelicopterAileronLeft.setEnabled(True)
551                self.horizontalSliderHelicopterAileronLeft.setEnabled(True)
552                self.pushButtonHelicopterAileronRight.setEnabled(True)
553                self.horizontalSliderHelicopterAileronRight.setEnabled(True)
554               
555                self.pushButtonHelicopterConcentrationEnable.setEnabled(True)
556                self.pushButtonHelicopterRelaxationEnable.setEnabled(True)
557                self.pushButtonHelicopterSpeedEnable.setEnabled(True)
558       
559       
560        ##################################################################
561       
562        def disconnectFromRCHelicopter(self):
563               
564                self.helicopter.neutral()
565                self.current_helicopter_state = 'neutral'
566               
567                self.helicopter.stop()
568               
569                self.disconnect(self.pushButtonHelicopterConnect, \
570                                  QtCore.SIGNAL("clicked()"), \
571                                  self.disconnectFromRCHelicopter)
572               
573                self.connect(self.pushButtonHelicopterConnect, \
574                                  QtCore.SIGNAL("clicked()"), \
575                                  self.connectToRCHelicopter)
576               
577                self.pushButtonHelicopterConnect.setText('Connect')
578               
579                self.comboBoxHelicopterTransmitter.setEnabled(True)
580                self.comboBoxHelicopterPortSelect.setEnabled(True)
581                self.pushButtonHelicopterSearch.setEnabled(True)
582               
583                self.pushButtonHelicopterHover.setEnabled(False)
584                self.pushButtonHelicopterFlyForward.setEnabled(False)
585                self.pushButtonHelicopterLand.setEnabled(False)
586                self.pushButtonHelicopterThrottle.setEnabled(False)
587                self.verticalSliderHelicopterThrottle.setEnabled(False)
588                self.pushButtonHelicopterElevatorForward.setEnabled(False)
589                self.verticalSliderHelicopterElevatorForward.setEnabled(False)
590                self.pushButtonHelicopterElevatorReverse.setEnabled(False)
591                self.verticalSliderHelicopterElevatorReverse.setEnabled(False)
592                self.pushButtonHelicopterRudderLeft.setEnabled(False)
593                self.horizontalSliderHelicopterRudderLeft.setEnabled(False)
594                self.pushButtonHelicopterRudderRight.setEnabled(False)
595                self.horizontalSliderHelicopterRudderRight.setEnabled(False)
596                self.pushButtonHelicopterAileronLeft.setEnabled(False)
597                self.horizontalSliderHelicopterAileronLeft.setEnabled(False)
598                self.pushButtonHelicopterAileronRight.setEnabled(False)
599                self.horizontalSliderHelicopterAileronRight.setEnabled(False)
600               
601                self.pushButtonHelicopterConcentrationEnable.setEnabled(False)
602                self.pushButtonHelicopterRelaxationEnable.setEnabled(False)
603                self.pushButtonHelicopterSpeedEnable.setEnabled(False)
604       
605       
606        ##################################################################
607       
608        def connectToWheelchair(self):
609               
610                # Prevent attempting to connect to a device which does not exist
611                device = str(self.comboBoxWheelchairPortSelect.currentText())
612                if device == 'N/A':
613                        self.pushButtonWheelchairConnect.setChecked(False)     
614                        return
615                if (sys.platform != 'win32'):
616                        if ((not device.startswith(DEVICE_PATH)) or \
617                            (not os.path.exists(device))):
618                                self.searchForDevices()
619                                self.pushButtonWheelchairConnect.setChecked(False)
620                                return
621               
622                self.wheelchair = \
623                   wheelchair_control.puzzlebox_brainstorms_wheelchair_control( \
624                      device_address=device,
625                      command='gui', \
626                      DEBUG=self.DEBUG)
627               
628                self.wheelchair.start()
629               
630                self.disconnect(self.pushButtonWheelchairConnect, \
631                                  QtCore.SIGNAL("clicked()"), \
632                                  self.connectToWheelchair)
633               
634                self.connect(self.pushButtonWheelchairConnect, \
635                                  QtCore.SIGNAL("clicked()"), \
636                                  self.disconnectFromWheelchair)
637               
638                self.pushButtonWheelchairConnect.setText('Disconnect')
639               
640                self.comboBoxWheelchairTransmitter.setEnabled(False)
641                self.comboBoxWheelchairPortSelect.setEnabled(False)
642                self.pushButtonWheelchairSearch.setEnabled(False)
643               
644                self.pushButtonWheelchairForward.setEnabled(True)
645                self.pushButtonWheelchairReverse.setEnabled(True)
646                self.pushButtonWheelchairLeft.setEnabled(True)
647                self.pushButtonWheelchairRight.setEnabled(True)
648                self.pushButtonWheelchairStop.setEnabled(True)
649                self.dialWheelchairSpeed.setEnabled(True)
650               
651                self.pushButtonWheelchairConcentrationEnable.setEnabled(True)
652                self.pushButtonWheelchairRelaxationEnable.setEnabled(True)
653                self.pushButtonWheelchairSpeedEnable.setEnabled(True)
654               
655                # Safety Measure: Explicitely require wheelchair speed control
656                # to be enabled each time it wheelchair is connected
657                self.pushButtonWheelchairSpeedEnable.setChecked(False)
658                self.pushButtonWheelchairSpeedEnable.setText('Disabled')
659                self.progressBarWheelchairSpeed.setValue(0)
660       
661       
662        ##################################################################
663       
664        def disconnectFromWheelchair(self):
665               
666                #self.stopWheelchair()
667               
668                self.wheelchair.stop()
669               
670                self.disconnect(self.pushButtonWheelchairConnect, \
671                                  QtCore.SIGNAL("clicked()"), \
672                                  self.disconnectFromWheelchair)
673               
674                self.connect(self.pushButtonWheelchairConnect, \
675                                  QtCore.SIGNAL("clicked()"), \
676                                  self.connectToWheelchair)
677               
678                self.pushButtonWheelchairConnect.setText('Connect')
679               
680                self.comboBoxWheelchairTransmitter.setEnabled(True)
681                self.comboBoxWheelchairPortSelect.setEnabled(True)
682                self.pushButtonWheelchairSearch.setEnabled(True)
683               
684                self.pushButtonWheelchairForward.setEnabled(False)
685                self.pushButtonWheelchairReverse.setEnabled(False)
686                self.pushButtonWheelchairLeft.setEnabled(False)
687                self.pushButtonWheelchairRight.setEnabled(False)
688                self.pushButtonWheelchairStop.setEnabled(False)
689                self.dialWheelchairSpeed.setEnabled(False)
690               
691                self.pushButtonWheelchairConcentrationEnable.setEnabled(False)
692                self.pushButtonWheelchairRelaxationEnable.setEnabled(False)
693                self.pushButtonWheelchairSpeedEnable.setEnabled(False)
694               
695                # Safety Measure: Explicitely require wheelchair speed control
696                # to be enabled each time it wheelchair is connected
697                self.pushButtonWheelchairSpeedEnable.setChecked(False)
698                self.pushButtonWheelchairSpeedEnable.setText('Disabled')
699                self.progressBarWheelchairSpeed.setValue(0)
700       
701       
702        ##################################################################
703       
704        def updateConcentrationButton(self):
705               
706                if self.pushButtonConcentrationEnable.isChecked():
707                       
708                        self.pushButtonConcentrationEnable.setText('Enabled')
709               
710                else:
711                       
712                        self.pushButtonConcentrationEnable.setText('Disabled')
713                        self.progressBarConcentration.setValue(0)
714               
715               
716                self.updateRobotSpeed()
717       
718       
719        ##################################################################
720       
721        def updateRelaxationButton(self):
722               
723                if self.pushButtonRelaxationEnable.isChecked():
724               
725                        self.pushButtonRelaxationEnable.setText('Enabled')
726               
727                else:
728                       
729                        self.pushButtonRelaxationEnable.setText('Disabled')
730                        self.progressBarRelaxation.setValue(0)
731               
732               
733                self.updateRobotSpeed()
734       
735       
736        ##################################################################
737       
738        def updateSpeedButton(self):
739               
740                if self.pushButtonSpeedEnable.isChecked():
741               
742                        self.pushButtonSpeedEnable.setText('Enabled')
743                        self.updateRobotSpeed()
744               
745                else:
746                       
747                        self.pushButtonSpeedEnable.setText('Disabled')
748                        self.progressBarSpeed.setValue(0)
749                        self.stopMotors()
750       
751       
752        ##################################################################
753       
754        def updateHelicopterConcentrationButton(self):
755               
756                if self.pushButtonHelicopterConcentrationEnable.isChecked():
757                       
758                        self.pushButtonHelicopterConcentrationEnable.setText('Enabled')
759               
760                else:
761                       
762                        self.pushButtonHelicopterConcentrationEnable.setText('Disabled')
763                        self.progressBarHelicopterConcentration.setValue(0)
764               
765               
766                self.updateHelicopterSpeed()
767       
768       
769        ##################################################################
770       
771        def updateHelicopterRelaxationButton(self):
772               
773                if self.pushButtonHelicopterRelaxationEnable.isChecked():
774               
775                        self.pushButtonHelicopterRelaxationEnable.setText('Enabled')
776               
777                else:
778                       
779                        self.pushButtonHelicopterRelaxationEnable.setText('Disabled')
780                        self.progressBarHelicopterRelaxation.setValue(0)
781               
782               
783                self.updateHelicopterSpeed()
784       
785       
786        ##################################################################
787       
788        def updateHelicopterSpeedButton(self):
789               
790                if self.pushButtonHelicopterSpeedEnable.isChecked():
791               
792                        self.pushButtonHelicopterSpeedEnable.setText('Enabled')
793                        self.updateHelicopterSpeed()
794               
795                else:
796                       
797                        self.pushButtonHelicopterSpeedEnable.setText('Disabled')
798                        self.progressBarHelicopterSpeed.setValue(0)
799                        self.landHelicopter()
800       
801       
802        ##################################################################
803       
804        def updateWheelchairConcentrationButton(self):
805               
806                if self.pushButtonWheelchairConcentrationEnable.isChecked():
807                       
808                        self.pushButtonWheelchairConcentrationEnable.setText('Enabled')
809               
810                else:
811                       
812                        self.pushButtonWheelchairConcentrationEnable.setText('Disabled')
813                        self.progressBarWheelchairConcentration.setValue(0)
814               
815               
816                self.updateWheelchairSpeed()
817       
818       
819        ##################################################################
820       
821        def updateWheelchairRelaxationButton(self):
822               
823                if self.pushButtonWheelchairRelaxationEnable.isChecked():
824               
825                        self.pushButtonWheelchairRelaxationEnable.setText('Enabled')
826               
827                else:
828                       
829                        self.pushButtonWheelchairRelaxationEnable.setText('Disabled')
830                        self.progressBarWheelchairRelaxation.setValue(0)
831               
832               
833                self.updateWheelchairSpeed()
834       
835       
836        ##################################################################
837       
838        def updateWheelchairSpeedButton(self):
839               
840                if self.pushButtonWheelchairSpeedEnable.isChecked():
841               
842                        self.pushButtonWheelchairSpeedEnable.setText('Enabled')
843                        self.updateWheelchairSpeed()
844               
845                else:
846                       
847                        self.pushButtonWheelchairSpeedEnable.setText('Disabled')
848                        self.progressBarWheelchairSpeed.setValue(0)
849                        self.stopWheelchair()
850       
851       
852        ##################################################################
853       
854        def connectWidgets(self):
855               
856                # LEGO Mindstorms Buttons
857                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("pressed()"), \
858                             self.turnLeft)
859                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("released()"), \
860                             self.stopMotors)
861               
862                self.connect(self.pushButtonForward, QtCore.SIGNAL("pressed()"), \
863                             self.driveForward)
864                self.connect(self.pushButtonForward, QtCore.SIGNAL("released()"), \
865                             self.stopMotors)
866               
867                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("pressed()"), \
868                             self.turnRight)
869                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("released()"), \
870                             self.stopMotors)
871               
872                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("pressed()"), \
873                             self.turnLeftInReverse)
874                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("released()"), \
875                             self.stopMotors)
876               
877                self.connect(self.pushButtonReverse, QtCore.SIGNAL("pressed()"), \
878                             self.driveReverse)
879                self.connect(self.pushButtonReverse, QtCore.SIGNAL("released()"), \
880                             self.stopMotors)
881               
882                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("pressed()"), \
883                             self.turnRightInReverse)
884                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("released()"), \
885                             self.stopMotors)
886               
887               
888                self.connect(self.pushButtonRobotSearch, \
889                                  QtCore.SIGNAL("clicked()"), \
890                                  self.searchForDevices)
891               
892                self.connect(self.pushButtonRobotConnect, \
893                                  QtCore.SIGNAL("clicked()"), \
894                                  self.connectToBrainstormsServer)
895               
896               
897                self.connect(self.pushButtonConcentrationEnable, \
898                                  QtCore.SIGNAL("clicked()"), \
899                                  self.updateConcentrationButton)
900               
901                self.connect(self.pushButtonRelaxationEnable, \
902                                  QtCore.SIGNAL("clicked()"), \
903                                  self.updateRelaxationButton)
904               
905                self.connect(self.pushButtonSpeedEnable, \
906                                  QtCore.SIGNAL("clicked()"), \
907                                  self.updateSpeedButton)
908               
909               
910                self.connect(self.pushButtonNXTMessageOne, QtCore.SIGNAL("pressed()"), \
911                             self.sendMessageOne)
912               
913                self.connect(self.pushButtonNXTMessageTwo, QtCore.SIGNAL("pressed()"), \
914                             self.sendMessageTwo)
915               
916                self.connect(self.pushButtonNXTMessageThree, QtCore.SIGNAL("pressed()"), \
917                             self.sendMessageThree)
918               
919                self.connect(self.pushButtonNXTMessageFour, QtCore.SIGNAL("pressed()"), \
920                             self.sendMessageFour)
921               
922                #self.connect(self.pushButtonNXTMessageFive, QtCore.SIGNAL("pressed()"), \
923                             #self.sendMessageFive)
924               
925                #self.connect(self.pushButtonNXTMessageSix, QtCore.SIGNAL("pressed()"), \
926                             #self.sendMessageSix)
927               
928               
929               
930                # RC Helicopter Buttons
931                self.connect(self.pushButtonHelicopterSearch, \
932                                  QtCore.SIGNAL("clicked()"), \
933                                  self.searchForDevices)
934               
935                self.connect(self.pushButtonHelicopterConnect, \
936                                  QtCore.SIGNAL("clicked()"), \
937                                  self.connectToRCHelicopter)
938               
939               
940                self.connect(self.pushButtonHelicopterConcentrationEnable, \
941                                  QtCore.SIGNAL("clicked()"), \
942                                  self.updateHelicopterConcentrationButton)
943               
944                self.connect(self.pushButtonHelicopterRelaxationEnable, \
945                                  QtCore.SIGNAL("clicked()"), \
946                                  self.updateHelicopterRelaxationButton)
947               
948                self.connect(self.pushButtonHelicopterSpeedEnable, \
949                                  QtCore.SIGNAL("clicked()"), \
950                                  self.updateHelicopterSpeedButton)
951               
952               
953                self.connect(self.pushButtonHelicopterHover, \
954                                  QtCore.SIGNAL("clicked()"), \
955                                  self.enableHelicopterHover)
956               
957                self.connect(self.pushButtonHelicopterFlyForward, \
958                                  QtCore.SIGNAL("clicked()"), \
959                                  self.enableHelicopterFlyForward)
960               
961                self.connect(self.pushButtonHelicopterLand, \
962                                  QtCore.SIGNAL("clicked()"), \
963                                  self.landHelicopter)
964               
965               
966               
967                # Wheelchair Buttons
968                self.connect(self.pushButtonWheelchairSearch, \
969                                  QtCore.SIGNAL("clicked()"), \
970                                  self.searchForDevices)
971               
972                self.connect(self.pushButtonWheelchairConnect, \
973                                  QtCore.SIGNAL("clicked()"), \
974                                  self.connectToWheelchair)
975               
976               
977                self.connect(self.pushButtonWheelchairConcentrationEnable, \
978                                  QtCore.SIGNAL("clicked()"), \
979                                  self.updateWheelchairConcentrationButton)
980               
981                self.connect(self.pushButtonWheelchairRelaxationEnable, \
982                                  QtCore.SIGNAL("clicked()"), \
983                                  self.updateWheelchairRelaxationButton)
984               
985                self.connect(self.pushButtonWheelchairSpeedEnable, \
986                                  QtCore.SIGNAL("clicked()"), \
987                                  self.updateWheelchairSpeedButton)
988               
989               
990                self.connect(self.pushButtonWheelchairForward, \
991                                  QtCore.SIGNAL("pressed()"), \
992                                  self.driveWheelchairForward)
993                self.connect(self.pushButtonWheelchairReverse, \
994                                  QtCore.SIGNAL("pressed()"), \
995                                  self.driveWheelchairReverse)
996                self.connect(self.pushButtonWheelchairLeft, \
997                                  QtCore.SIGNAL("pressed()"), \
998                                  self.driveWheelchairLeft)
999                self.connect(self.pushButtonWheelchairRight, \
1000                                  QtCore.SIGNAL("pressed()"), \
1001                                  self.driveWheelchairRight)
1002
1003                if not WHEELCHAIR_CONTROL_EEG:
1004                        # Manual control for Wheelchair
1005                        # Allow drive instructions to be sent once (or repeatedly)
1006                        self.connect(self.pushButtonWheelchairForward, \
1007                                     QtCore.SIGNAL("released()"), \
1008                                     self.stopWheelchair)               
1009                        self.connect(self.pushButtonWheelchairReverse, \
1010                                     QtCore.SIGNAL("released()"), \
1011                                     self.stopWheelchair)
1012                        self.connect(self.pushButtonWheelchairLeft, \
1013                                     QtCore.SIGNAL("released()"), \
1014                                     self.stopWheelchair)
1015                        self.connect(self.pushButtonWheelchairRight, \
1016                                     QtCore.SIGNAL("released()"), \
1017                                     self.stopWheelchair)
1018               
1019                self.connect(self.pushButtonWheelchairStop, \
1020                                  QtCore.SIGNAL("pressed()"), \
1021                                  self.stopWheelchair)
1022               
1023                self.connect(self.dialWheelchairSpeed, \
1024                             QtCore.SIGNAL("valueChanged(int)"), \
1025                             self.updateWheelchairSpeed)
1026               
1027               
1028               
1029                # Control Panel Buttons
1030                self.connect(self.lineEditLeftMotorPort, QtCore.SIGNAL("textEdited(const QString &)"), \
1031                             self.updateLeftMotorPort)
1032                             
1033                self.connect(self.lineEditRightMotorPort, QtCore.SIGNAL("textEdited(const QString &)"), \
1034                             self.updateRightMotorPort)
1035               
1036                self.connect(self.checkBoxMotorSpinReversed, QtCore.SIGNAL("stateChanged(int)"), \
1037                             self.updateMotorSpinReversed)
1038               
1039               
1040                self.connect(self.pushButtonMessageOne, QtCore.SIGNAL("pressed()"), \
1041                             self.sendMessageOne)
1042               
1043                self.connect(self.pushButtonMessageTwo, QtCore.SIGNAL("pressed()"), \
1044                             self.sendMessageTwo)
1045               
1046                self.connect(self.pushButtonMessageThree, QtCore.SIGNAL("pressed()"), \
1047                             self.sendMessageThree)
1048               
1049                self.connect(self.pushButtonMessageFour, QtCore.SIGNAL("pressed()"), \
1050                             self.sendMessageFour)
1051               
1052                #self.connect(self.pushButtonMessageFive, QtCore.SIGNAL("pressed()"), \
1053                             #self.sendMessageFive)
1054               
1055                #self.connect(self.pushButtonMessageSix, QtCore.SIGNAL("pressed()"), \
1056                             #self.sendMessageSix)
1057               
1058               
1059                self.connect(self.pushButtonThinkGearConnect, \
1060                                  QtCore.SIGNAL("clicked()"), \
1061                                  self.connectToThinkGearHost)
1062               
1063                self.connect(self.pushButtonSendFeedback, \
1064                                  QtCore.SIGNAL("clicked()"), \
1065                                  self.sendFeedback)
1066               
1067               
1068                #shortcut = QtGui.QShortcut(self)
1069                #shortcut.setKey(tr("Down"))
1070                #self.connect(shortcut, QtCore.SIGNAL("pressed()"), self.driveReverse)
1071               
1072               
1073                # Global Buttons
1074               
1075                action = QtGui.QAction(self)
1076                action.setShortcut(QtGui.QKeySequence("Tab"))
1077                self.connect(action, QtCore.SIGNAL("triggered()"), self.rotateControlButtons)
1078                self.addAction(action)
1079               
1080               
1081                # Robot Buttons
1082               
1083                action = QtGui.QAction(self)
1084                action.setShortcut(QtGui.QKeySequence("W"))
1085                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
1086                self.addAction(action)
1087               
1088                action = QtGui.QAction(self)
1089                action.setShortcut(QtGui.QKeySequence("Up"))
1090                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
1091                self.addAction(action)
1092               
1093               
1094                action = QtGui.QAction(self)
1095                action.setShortcut(QtGui.QKeySequence("Left"))
1096                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
1097                self.addAction(action)
1098               
1099                action = QtGui.QAction(self)
1100                action.setShortcut(QtGui.QKeySequence("A"))
1101                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
1102                self.addAction(action)
1103               
1104               
1105                action = QtGui.QAction(self)
1106                action.setShortcut(QtGui.QKeySequence("S"))
1107                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
1108                self.addAction(action)
1109               
1110                action = QtGui.QAction(self)
1111                action.setShortcut(QtGui.QKeySequence("Down"))
1112                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
1113                self.addAction(action)
1114               
1115               
1116                action = QtGui.QAction(self)
1117                action.setShortcut(QtGui.QKeySequence("D"))
1118                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
1119                self.addAction(action)
1120               
1121                action = QtGui.QAction(self)
1122                action.setShortcut(QtGui.QKeySequence("Right"))
1123                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
1124                self.addAction(action)
1125               
1126               
1127                action = QtGui.QAction(self)
1128                action.setShortcut(QtGui.QKeySequence("Z"))
1129                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeftReverse, QtCore.SLOT("animateClick()"))
1130                self.addAction(action)
1131               
1132               
1133                action = QtGui.QAction(self)
1134                action.setShortcut(QtGui.QKeySequence("C"))
1135                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRightReverse, QtCore.SLOT("animateClick()"))
1136                self.addAction(action)
1137               
1138               
1139               
1140                # RC Helicopter Buttons
1141               
1142                action = QtGui.QAction(self)
1143                action.setShortcut(QtGui.QKeySequence("Home"))
1144                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterHover, QtCore.SLOT("animateClick()"))
1145                self.addAction(action)
1146                action = QtGui.QAction(self)
1147                action.setShortcut(QtGui.QKeySequence("["))
1148                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterHover, QtCore.SLOT("animateClick()"))
1149                self.addAction(action)
1150               
1151                action = QtGui.QAction(self)
1152                action.setShortcut(QtGui.QKeySequence("PgUp"))
1153                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterFlyForward, QtCore.SLOT("animateClick()"))
1154                self.addAction(action)
1155                action = QtGui.QAction(self)
1156                action.setShortcut(QtGui.QKeySequence("]"))
1157                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterFlyForward, QtCore.SLOT("animateClick()"))
1158                self.addAction(action)
1159               
1160                action = QtGui.QAction(self)
1161                action.setShortcut(QtGui.QKeySequence("End"))
1162                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterLand, QtCore.SLOT("animateClick()"))
1163                self.addAction(action)
1164                action = QtGui.QAction(self)
1165                action.setShortcut(QtGui.QKeySequence("\\"))
1166                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterLand, QtCore.SLOT("animateClick()"))
1167                self.addAction(action)
1168               
1169               
1170               
1171                # Wheelchair Buttons
1172               
1173                action = QtGui.QAction(self)
1174                action.setShortcut(QtGui.QKeySequence("i"))
1175                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairForward, QtCore.SLOT("animateClick()"))
1176                self.addAction(action)
1177               
1178                action = QtGui.QAction(self)
1179                action.setShortcut(QtGui.QKeySequence("k"))
1180                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairReverse, QtCore.SLOT("animateClick()"))
1181                self.addAction(action)
1182                action = QtGui.QAction(self)
1183                action.setShortcut(QtGui.QKeySequence("m"))
1184                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairReverse, QtCore.SLOT("animateClick()"))
1185                self.addAction(action)
1186               
1187                action = QtGui.QAction(self)
1188                action.setShortcut(QtGui.QKeySequence("j"))
1189                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairLeft, QtCore.SLOT("animateClick()"))
1190                self.addAction(action)
1191               
1192                action = QtGui.QAction(self)
1193                action.setShortcut(QtGui.QKeySequence("l"))
1194                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairRight, QtCore.SLOT("animateClick()"))
1195                self.addAction(action)
1196               
1197                action = QtGui.QAction(self)
1198                action.setShortcut(QtGui.QKeySequence("Space"))
1199                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairStop, QtCore.SLOT("animateClick()"))
1200                self.addAction(action)
1201               
1202               
1203               
1204                # Control Panel Buttons
1205               
1206                action = QtGui.QAction(self)
1207                action.setShortcut(QtGui.QKeySequence("1"))
1208                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageOne, QtCore.SLOT("animateClick()"))
1209                self.addAction(action)
1210               
1211                action = QtGui.QAction(self)
1212                action.setShortcut(QtGui.QKeySequence("2"))
1213                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageTwo, QtCore.SLOT("animateClick()"))
1214                self.addAction(action)
1215               
1216                action = QtGui.QAction(self)
1217                action.setShortcut(QtGui.QKeySequence("3"))
1218                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageThree, QtCore.SLOT("animateClick()"))
1219                self.addAction(action)
1220               
1221                action = QtGui.QAction(self)
1222                action.setShortcut(QtGui.QKeySequence("4"))
1223                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFour, QtCore.SLOT("animateClick()"))
1224                self.addAction(action)
1225               
1226                #action = QtGui.QAction(self)
1227                #action.setShortcut(QtGui.QKeySequence("5"))
1228                #self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFive, QtCore.SLOT("animateClick()"))
1229                #self.addAction(action)
1230               
1231                #action = QtGui.QAction(self)
1232                #action.setShortcut(QtGui.QKeySequence("6"))
1233                #self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageSix, QtCore.SLOT("animateClick()"))
1234                #self.addAction(action)
1235               
1236               
1237                #self.pushButtonForward.setAutoRepeat(False)
1238                #self.pushButtonForward.setAutoRepeatDelay(0)
1239                #self.pushButtonForward.setAutoRepeatInterval(0)
1240       
1241       
1242        ##################################################################
1243       
1244        def searchForDevices(self):
1245               
1246                nxt_devices = []
1247                rc_helicopter_devices = []
1248                wheelchair_devices = []
1249               
1250                #if (sys.platform != 'win32'):
1251                if False: # temporarily disabled
1252                       
1253                        # Bluetooth module doesn't compile properly under Windows
1254                       
1255                        bluetooth_devices = []
1256                       
1257                        try:
1258                                bluetooth_devices = bluetooth.discover_devices( \
1259                                                       duration=5, \
1260                                                       flush_cache=True, \
1261                                                       lookup_names=False)
1262                        except:
1263                                #command = '%s con' % PATH_TO_HCITOOL
1264                                command = '%s scan' % PATH_TO_HCITOOL
1265                               
1266                                output = os.popen(command, 'r')
1267                               
1268                                for line in output.readlines():
1269                                        print line
1270                                        try:
1271                                                address = line.split(' ')[2]
1272                                        except:
1273                                                pass
1274                                        else:
1275                                                bluetooth_devices.append(address)
1276                       
1277                        for address in bluetooth_devices:
1278                                device_name = bluetooth.lookup_name(address)
1279                                if ((device_name == 'NXT') and \
1280                                    (address not in nxt_devices)):
1281                                        nxt_devices.append(address)
1282                       
1283                       
1284                        if self.DEBUG:
1285                                print "Bluetooth NXT devices found:",
1286                                print nxt_devices
1287               
1288               
1289                # List all serial devices
1290                serial_devices = self.enumerateSerialPorts()
1291               
1292                for serial_device in serial_devices:
1293                        #serial_device = self.fullPortName(serial_device)
1294                        nxt_devices.append(serial_device)
1295                        rc_helicopter_devices.append(serial_device)
1296                        wheelchair_devices.append(serial_device)
1297               
1298               
1299                # Configure combo boxes
1300                if nxt_devices == []:
1301                        nxt_devices.append('N/A')
1302               
1303                if rc_helicopter_devices == []:
1304                        rc_helicopter_devices.append('N/A')
1305               
1306                if wheelchair_devices == []:
1307                        wheelchair_devices.append('N/A')
1308               
1309               
1310                # Don't reset combo boxes if already connected
1311                if self.pushButtonRobotConnect.text != 'Disconnect':
1312                       
1313                        self.comboBoxRobotPortSelect.clear()
1314                       
1315                        #nxt_devices.reverse()
1316                        for nxt_device in nxt_devices:
1317                                self.comboBoxRobotPortSelect.addItem(nxt_device)
1318               
1319               
1320                if self.pushButtonHelicopterConnect.text != 'Disconnect':
1321                       
1322                        self.comboBoxHelicopterPortSelect.clear()
1323                       
1324                        #rc_helicopter_devices.reverse()
1325                        for rc_helicopter in rc_helicopter_devices:
1326                                self.comboBoxHelicopterPortSelect.addItem(rc_helicopter)
1327               
1328               
1329                if self.pushButtonWheelchairConnect.text != 'Disconnect':
1330                       
1331                        self.comboBoxWheelchairPortSelect.clear()
1332                       
1333                        #rc_helicopter_devices.reverse()
1334                        for wheelchair in wheelchair_devices:
1335                                self.comboBoxWheelchairPortSelect.addItem(wheelchair)
1336       
1337       
1338        ##################################################################
1339       
1340        def enumerateSerialPorts(self):
1341               
1342                """ Uses the Win32 registry to return an
1343                iterator of serial (COM) ports
1344                existing on this computer.
1345               
1346                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
1347                """
1348               
1349                serial_ports = []
1350               
1351                if (sys.platform == 'win32'):
1352                       
1353                        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
1354                        try:
1355                                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
1356                        except WindowsError:
1357                                #raise IterationError
1358                                return []
1359                                #pass
1360                       
1361                        for i in itertools.count():
1362                                try:
1363                                        val = winreg.EnumValue(key, i)
1364                                        #yield str(val[1])
1365                                        serial_ports.append( str(val[1]) )
1366                                except EnvironmentError:
1367                                        break
1368               
1369               
1370                else:
1371                       
1372                        if os.path.exists(DEVICE_PATH):
1373                                device_list = os.listdir(DEVICE_PATH)
1374                               
1375                                device_list.sort()
1376                       
1377                                for device in device_list:
1378                                        if device.startswith('arduino'):
1379                                                serial_ports.append( DEVICE_PATH + '/' + device )
1380                                for device in device_list:
1381                                        if device.startswith('ttyUSB'):
1382                                                serial_ports.append( DEVICE_PATH + '/' + device )
1383                                #for device in device_list:
1384                                        #if device.startswith('rfcomm'):
1385                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1386                                for device in device_list:
1387                                        if device.startswith('ttyACM'):
1388                                                serial_ports.append( DEVICE_PATH + '/' + device )
1389                                for device in device_list:
1390                                        if device.startswith('ttyS'):
1391                                                serial_ports.append( DEVICE_PATH + '/' + device )
1392                                for device in device_list:
1393                                        if device.startswith('rfcomm'):
1394                                                serial_ports.append( DEVICE_PATH + '/' + device )
1395                                #for device in device_list:
1396                                        #if device.startswith('ttys0'):
1397                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1398                                #for device in device_list:
1399                                        #if device.startswith('tty.usbserial-FTF3NM1G'):
1400                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1401                                for device in device_list:
1402                                        if device.startswith('tty.usbserial'):
1403                                                serial_ports.append( DEVICE_PATH + '/' + device )
1404                                for device in device_list:
1405                                        if device.startswith('tty.NXT-DevB'):
1406                                                serial_ports.append( DEVICE_PATH + '/' + device )
1407                                #for device in device_list:
1408                                        #if device.startswith('tty.MindWaveMobile'):
1409                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1410                                #for device in device_list:
1411                                        #if device.startswith('tty.MindWave'):
1412                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1413                                #for device in device_list:
1414                                        #if device.startswith('tty.MindSet'):
1415                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1416                                #for device in device_list:
1417                                        #if device.startswith('arduino'):
1418                                                #serial_ports.append( DEVICE_PATH + '/' + device )
1419               
1420               
1421                return(serial_ports)
1422       
1423       
1424        ##################################################################
1425       
1426        def fullPortName(self, portname):
1427               
1428                """ Given a port-name (of the form COM7,
1429                COM12, CNCA0, etc.) returns a full
1430                name suitable for opening with the
1431                Serial class.
1432                """
1433               
1434                m = re.match('^COM(\d+)$', portname)
1435                if m and int(m.group(1)) < 10:
1436                        return portname
1437               
1438                return '\\\\.\\' + portname
1439       
1440       
1441        ##################################################################
1442       
1443        # LEGO Mindstorms Controls
1444       
1445        def turnLeft(self):
1446                self.brainstormsClient.sendCommand('turn_left')
1447                self.drive_state = 'turn_left'
1448       
1449        def driveForward(self):
1450                #if self.DEBUG:
1451                        #print "driveForward"
1452                #self.pushButtonForward.setDown(True)
1453                #if (self.drive_state != 'drive_forward'):
1454                        #self.updateRobotSpeed(new_speed=DEFAULT_NXT_POWER_LEVEL)
1455                power = self.current_speed
1456                if power == 0:
1457                        power=DEFAULT_NXT_POWER_LEVEL
1458                self.brainstormsClient.sendCommand('drive_forward', power=power)
1459                self.drive_state = 'drive_forward'
1460       
1461        def turnRight(self):
1462                self.brainstormsClient.sendCommand('turn_right')
1463                self.drive_state = 'turn_right'
1464       
1465        def turnLeftInReverse(self):
1466                self.brainstormsClient.sendCommand('turn_left_in_reverse')
1467                self.drive_state = 'turn_left_in_reverse'
1468       
1469        def driveReverse(self):
1470                self.brainstormsClient.sendCommand('drive_reverse')
1471                self.drive_state = 'drive_reverse'
1472       
1473        def turnRightInReverse(self):
1474                self.brainstormsClient.sendCommand('turn_right_in_reverse')
1475                self.drive_state = 'turn_right_in_reverse'
1476       
1477        def stopMotors(self):
1478                self.pushButtonTurnLeft.setDown(False)
1479                self.pushButtonForward.setDown(False)
1480                self.pushButtonTurnRight.setDown(False)
1481                self.pushButtonTurnLeftReverse.setDown(False)
1482                self.pushButtonReverse.setDown(False)
1483                self.pushButtonTurnRightReverse.setDown(False)
1484                if (self.current_speed != 0):
1485                        self.updateRobotSpeed(new_speed=0)
1486                if self.brainstormsClient != None:
1487                        self.brainstormsClient.sendCommand('stop_motors')
1488                self.drive_state = 'stop_motors'
1489       
1490        def sendMessageOne(self):
1491                message = str(self.lineEditMessageOne.text())
1492                self.brainstormsClient.sendCommand('send_message_1')
1493       
1494        def sendMessageTwo(self):
1495                message = str(self.lineEditMessageTwo.text())
1496                self.brainstormsClient.sendCommand('send_message_2')
1497       
1498        def sendMessageThree(self):
1499                message = str(self.lineEditMessageThree.text())
1500                self.brainstormsClient.sendCommand('send_message_3')
1501       
1502        def sendMessageFour(self):
1503                message = str(self.lineEditMessageFour.text())
1504                self.brainstormsClient.sendCommand('send_message_4')
1505       
1506        #def sendMessageFive(self):
1507                #message = str(self.lineEditMessageFive.text())
1508                #self.brainstormsClient.sendCommand('send_message_5')
1509       
1510        #def sendMessageSix(self):
1511                #message = str(self.lineEditMessageSix.text())
1512                #self.brainstormsClient.sendCommand('send_message_6')
1513       
1514       
1515        ##################################################################
1516       
1517        def updateLeftMotorPort(self):
1518               
1519                motor_port = str(self.lineEditLeftMotorPort.text())
1520                motor_port = motor_port.lower()
1521               
1522                #print
1523                #print "new left motor port:",
1524                #print motor_port
1525                #print
1526               
1527                if (self.brainstormsClient != None):
1528                       
1529                        update = {'motor_port_left': motor_port}
1530                       
1531                        self.brainstormsClient.sendCommand('update', default_data=update)
1532       
1533       
1534        ##################################################################
1535       
1536        def updateRightMotorPort(self):
1537               
1538                motor_port = str(self.lineEditRightMotorPort.text())
1539                motor_port = motor_port.lower()
1540               
1541                #print
1542                #print "new right motor port:",
1543                #print motor_port
1544                #print
1545               
1546                if (self.brainstormsClient != None):
1547                       
1548                        update = {'motor_port_right': motor_port}
1549                       
1550                        self.brainstormsClient.sendCommand('update', default_data=update)
1551       
1552       
1553        ##################################################################
1554       
1555        def updateMotorSpinReversed(self):
1556               
1557                #print
1558                #print
1559                #print
1560                #print "Updating motors mounted backwards:",
1561               
1562                motors_mounted_backwards = self.checkBoxMotorSpinReversed.isChecked()
1563               
1564                #print motors_mounted_backwards
1565                #print
1566                #print
1567                #print
1568               
1569                if (self.brainstormsClient != None):
1570                       
1571                        update = {'motors_mounted_backwards': motors_mounted_backwards}
1572                       
1573                        self.brainstormsClient.sendCommand('update', default_data=update)
1574       
1575       
1576        ##################################################################
1577       
1578        def enableHelicopterHover(self):
1579               
1580                if self.pushButtonHelicopterFlyForward.isChecked():
1581                        self.pushButtonHelicopterFlyForward.setChecked(False)
1582                        self.disableHelicopterFlyForward()
1583               
1584                self.helicopter.hover(duration=None)
1585                self.current_helicopter_state = 'hover'
1586               
1587                self.disconnect(self.pushButtonHelicopterHover, \
1588                                                        QtCore.SIGNAL("clicked()"), \
1589                                                        self.enableHelicopterHover)
1590               
1591                self.connect(self.pushButtonHelicopterHover, \
1592                                  QtCore.SIGNAL("clicked()"), \
1593                                  self.disableHelicopterHover)
1594               
1595                #if self.pushButtonHelicopterFlyForward.isChecked():
1596                        #self.pushButtonHelicopterFlyForward.toggle()
1597                        ##self.disableHelicopterFlyForward()
1598       
1599       
1600        ##################################################################
1601       
1602        def disableHelicopterHover(self):
1603               
1604                self.helicopter.neutral()
1605                self.current_helicopter_state = 'neutral'
1606               
1607                self.disconnect(self.pushButtonHelicopterHover, \
1608                                                        QtCore.SIGNAL("clicked()"), \
1609                                                        self.disableHelicopterHover)
1610               
1611                self.connect(self.pushButtonHelicopterHover, \
1612                                  QtCore.SIGNAL("clicked()"), \
1613                                  self.enableHelicopterHover)
1614       
1615       
1616        ##################################################################
1617       
1618        def enableHelicopterFlyForward(self):
1619               
1620                if self.pushButtonHelicopterHover.isChecked():
1621                        self.pushButtonHelicopterHover.setChecked(False)
1622                        self.disableHelicopterHover()
1623               
1624                self.helicopter.fly_forward(duration=None)
1625                self.current_helicopter_state = 'fly_forward'
1626               
1627                self.disconnect(self.pushButtonHelicopterFlyForward, \
1628                                                        QtCore.SIGNAL("clicked()"), \
1629                                                        self.enableHelicopterFlyForward)
1630               
1631                self.connect(self.pushButtonHelicopterFlyForward, \
1632                                  QtCore.SIGNAL("clicked()"), \
1633                                  self.disableHelicopterFlyForward)
1634               
1635                #if self.pushButtonHelicopterHover.isChecked():
1636                        #self.pushButtonHelicopterHover.toggle()
1637                        ##self.disableHelicopterHover()
1638       
1639       
1640        ##################################################################
1641       
1642        def disableHelicopterFlyForward(self):
1643               
1644                self.helicopter.neutral()
1645                self.current_helicopter_state = 'neutral'
1646               
1647                self.disconnect(self.pushButtonHelicopterFlyForward, \
1648                                                        QtCore.SIGNAL("clicked()"), \
1649                                                        self.disableHelicopterFlyForward)
1650               
1651                self.connect(self.pushButtonHelicopterFlyForward, \
1652                                  QtCore.SIGNAL("clicked()"), \
1653                                  self.enableHelicopterFlyForward)
1654       
1655       
1656        ##################################################################
1657       
1658        def landHelicopter(self):
1659               
1660                self.helicopter.neutral()
1661                self.current_helicopter_state = 'neutral'
1662               
1663                if self.pushButtonHelicopterHover.isChecked():
1664                        self.pushButtonHelicopterHover.setChecked(False)
1665                        self.disableHelicopterHover()
1666                if self.pushButtonHelicopterFlyForward.isChecked():
1667                        self.pushButtonHelicopterFlyForward.setChecked(False)
1668                        self.disableHelicopterFlyForward()
1669       
1670       
1671        ##################################################################
1672       
1673        def driveWheelchairForward(self):
1674                print "WheelchairForward"
1675                speed = self.dialWheelchairSpeed.value()
1676                self.wheelchair.sendCommand(speed, 'forward')
1677       
1678        def driveWheelchairReverse(self):
1679                #print "WheelchairReverse"
1680                speed = self.dialWheelchairSpeed.value()
1681                self.wheelchair.sendCommand(speed, 'reverse')
1682       
1683        def driveWheelchairLeft(self):
1684                #print "WheelchairLeft"
1685                speed = self.dialWheelchairSpeed.value()
1686                self.wheelchair.sendCommand(speed, 'left')
1687       
1688        def driveWheelchairRight(self):
1689                #print "WheelchairRight"
1690                speed = self.dialWheelchairSpeed.value()
1691                self.wheelchair.sendCommand(speed, 'right')
1692       
1693        def stopWheelchair(self):
1694                print "stopWheelchair"
1695                speed = self.dialWheelchairSpeed.value()
1696                self.wheelchair.sendCommand(speed, 'stop')
1697       
1698       
1699        ##################################################################
1700       
1701        def updateWheelchairSpeed(self, value):
1702               
1703                if self.DEBUG:
1704                        print "DEBUG [Brainstorms:Interface]: updateWheelchairSpeed():",
1705                        print value
1706       
1707       
1708        ##################################################################
1709       
1710        def updateRobotSpeed(self, new_speed=None):
1711               
1712               
1713                #print
1714                #print "updateRobotSpeed"
1715                #print "drive_state:",
1716                #print self.drive_state
1717                #print "left.isDown:",
1718                #print self.pushButtonTurnLeft.isDown()
1719                #print "not left.isFlat:",
1720                #print not self.pushButtonTurnLeft.isFlat()
1721                #print
1722                #print "forward.isDown:",
1723                #print self.pushButtonForward.isDown()
1724                #print "not forward.isFlat:",
1725                #print not self.pushButtonForward.isFlat()
1726                #print
1727                #print "right.isDown:",
1728                #print self.pushButtonTurnRight.isDown()
1729                #print "not right.isFlat:",
1730                #print not self.pushButtonTurnRight.isFlat()
1731                #print
1732                #print "reverse.isDown:",
1733                #print self.pushButtonReverse.isDown()
1734                #print "not reverse.isFlat:",
1735                #print not self.pushButtonReverse.isFlat()
1736                #print
1737               
1738               
1739                if new_speed == None:
1740               
1741                        concentration=self.progressBarConcentration.value()
1742                        relaxation=self.progressBarRelaxation.value()
1743                       
1744                        new_speed = self.calculateSpeed(concentration, relaxation)
1745               
1746               
1747                # Update GUI
1748                if self.pushButtonSpeedEnable.isChecked():
1749                        self.progressBarSpeed.setValue(new_speed)
1750               
1751               
1752                # If there is a change between the new and current speeds
1753                # and either the robot is currently driving
1754                # or the "speed control" button is enabled,
1755                # then send the updated speed to the robot
1756                if ((self.current_speed != new_speed) and \
1757                         ((self.drive_state != 'stop_motors') or \
1758                          (self.pushButtonSpeedEnable.isChecked()))):
1759                       
1760                        if (new_speed == 0):
1761                                self.current_speed = new_speed
1762                                self.stopMotors()
1763                        else:
1764                                if ((self.brainstormsClient != None) and \
1765                                    (self.pushButtonSpeedEnable.isChecked())):
1766                                       
1767                                        if ((self.pushButtonTurnLeft.isDown()) or \
1768                                            (not self.pushButtonTurnLeft.isFlat())):
1769                                                self.pushButtonTurnLeft.setDown(True)
1770                                                self.brainstormsClient.sendCommand('turn_left', power=new_speed)
1771                                                self.drive_state = 'turn_left'
1772                                       
1773                                        if ((self.pushButtonForward.isDown()) or \
1774                                            (not self.pushButtonForward.isFlat())):
1775                                                self.pushButtonForward.setDown(True)
1776                                                self.brainstormsClient.sendCommand('drive_forward', power=new_speed)
1777                                                self.drive_state = 'drive_forward'
1778                                       
1779                                        if ((self.pushButtonReverse.isDown()) or \
1780                                            (not self.pushButtonReverse.isFlat())):
1781                                                self.pushButtonReverse.setDown(True)
1782                                                self.brainstormsClient.sendCommand('drive_reverse', power=new_speed)
1783                                                self.drive_state = 'drive_reverse'
1784                                       
1785                                        if ((self.pushButtonTurnRight.isDown()) or \
1786                                            (not self.pushButtonTurnRight.isFlat())):
1787                                                self.pushButtonTurnRight.setDown(True)
1788                                                self.brainstormsClient.sendCommand('turn_right', power=new_speed)
1789                                                self.drive_state = 'turn_right'
1790               
1791               
1792                self.current_speed = new_speed
1793       
1794       
1795        ##################################################################
1796       
1797        def updateHelicopterSpeed(self, new_speed=None):
1798               
1799                if new_speed == None:
1800               
1801                        concentration=self.progressBarHelicopterConcentration.value()
1802                        relaxation=self.progressBarHelicopterRelaxation.value()
1803                       
1804                        new_speed = self.calculateSpeed(concentration, relaxation)
1805               
1806               
1807                # Update GUI
1808                if self.pushButtonHelicopterSpeedEnable.isChecked():
1809                        self.progressBarHelicopterSpeed.setValue(new_speed)
1810                       
1811                        if ((new_speed > 0) and \
1812                            (self.current_helicopter_state == 'neutral') and \
1813                            (self.helicopter != None)):
1814                                self.enableHelicopterHover()
1815                       
1816                        elif ((new_speed == 0) and \
1817                              (self.current_helicopter_state != 'neutral') and \
1818                              (self.helicopter != None)):
1819                                self.landHelicopter()
1820               
1821               
1822                self.current_speed = new_speed
1823       
1824       
1825        ##################################################################
1826       
1827        def updateWheelchairSpeed(self, new_speed=None):
1828               
1829                if new_speed == None:
1830               
1831                        concentration=self.progressBarWheelchairConcentration.value()
1832                        relaxation=self.progressBarWheelchairRelaxation.value()
1833                       
1834                        new_speed = self.calculateSpeed(concentration, relaxation)
1835               
1836               
1837                # Update GUI
1838                if self.pushButtonWheelchairSpeedEnable.isChecked():
1839                        self.progressBarWheelchairSpeed.setValue(new_speed)
1840               
1841               
1842                self.current_speed = new_speed
1843       
1844       
1845        ##################################################################
1846       
1847        def calculateSpeed(self, concentration, relaxation):
1848               
1849                speed = 0
1850               
1851                thresholds = THINKGEAR_POWER_THRESHOLDS
1852               
1853                match = int(concentration)
1854               
1855                while ((match not in thresholds['concentration'].keys()) and \
1856                            (match >= 0)):
1857                        match -= 1
1858               
1859               
1860                if match in thresholds['concentration'].keys():
1861                        speed = thresholds['concentration'][match]
1862               
1863               
1864                match = int(relaxation)
1865               
1866                while ((match not in thresholds['relaxation'].keys()) and \
1867                            (match >= 0)):
1868                        match -= 1
1869               
1870                if match in thresholds['relaxation'].keys():
1871                        speed = speed + thresholds['relaxation'][match]
1872               
1873               
1874                # LEGO Mindstorms power settings cannot exceed 100
1875                # and don't drive well with levels less than 50
1876                if (speed > 100):
1877                        speed = 100
1878                elif (speed < 50):
1879                        speed = 0
1880               
1881               
1882                return(speed)
1883       
1884       
1885        ##################################################################
1886       
1887        def processPacketThinkGear(self, packet):
1888               
1889                if ('eSense' in packet.keys()):
1890                       
1891                        # We process eyeblinks here because we receive
1892                        # eSense packets once per second. Its a convenient
1893                        # means of processing at this frequency without
1894                        # setting an additional timer thread for the program
1895                       
1896                        self.processEyeBlinks()
1897                       
1898                        if ('attention' in packet['eSense'].keys()):
1899                                if self.pushButtonConcentrationEnable.isChecked():
1900                                        self.progressBarConcentration.setValue(packet['eSense']['attention'])
1901                                if self.pushButtonHelicopterConcentrationEnable.isChecked():
1902                                        self.progressBarHelicopterConcentration.setValue(packet['eSense']['attention'])
1903                                if self.pushButtonWheelchairConcentrationEnable.isChecked():
1904                                        self.progressBarWheelchairConcentration.setValue(packet['eSense']['attention'])
1905                       
1906                        if ('meditation' in packet['eSense'].keys()):
1907                                if self.pushButtonRelaxationEnable.isChecked():
1908                                        self.progressBarRelaxation.setValue(packet['eSense']['meditation'])
1909                                if self.pushButtonHelicopterRelaxationEnable.isChecked():
1910                                        self.progressBarHelicopterRelaxation.setValue(packet['eSense']['meditation'])
1911                                if self.pushButtonWheelchairRelaxationEnable.isChecked():
1912                                        self.progressBarWheelchairRelaxation.setValue(packet['eSense']['meditation'])
1913               
1914               
1915                # Eye Blinks
1916                if ('blinkStrength' in packet.keys()):
1917                        self.blinks[time.time()] = packet
1918               
1919               
1920                ## Emotiv Cognitiv support
1921                #if ('cognitiv' in packet.keys()):
1922                       
1923                        #if (('currentAction' in packet['cognitiv'].keys()) and \
1924                            #('currentActionPower' in packet['cognitiv'].keys()) and \
1925                            #(self.pushButtonRobotConnect.text != 'Connect')):
1926                                #if self.pushButtonConcentrationEnable.isChecked():
1927                                        #self.progressBarConcentration.setValue( int(packet['cognitiv']['currentActionPower'] * 100 )
1928                                #if self.pushButtonHelicopterConcentrationEnable.isChecked():
1929                                        #self.progressBarHelicopterConcentration.setValue( int(packet['cognitiv']['currentActionPower'] * 100 )
1930                                #if self.pushButtonWheelchairConcentrationEnable.isChecked():
1931                                        #self.progressBarWheelchairConcentration.setValue( int(packet['cognitiv']['currentActionPower'] * 100 )
1932               
1933               
1934                #if ('cognitiv' in packet.keys()):
1935                       
1936                        #if (('currentAction' in packet['cognitiv'].keys()) and \
1937                            #('currentActionPower' in packet['cognitiv'].keys()) and \
1938                            #(self.pushButtonRobotConnect.text != 'Connect')):
1939                               
1940                                # Rotate Left
1941                                #if ((int(packet['cognitiv']['currentAction']) == 128) and \
1942                                    #(packet['cognitiv']['currentActionPower'] >= 0.2)):
1943                                        #self.sendMessageOne()
1944                               
1945                                # Rotate Right
1946                                #if ((int(packet['cognitiv']['currentAction']) == 256) and \
1947                                    #(packet['cognitiv']['currentActionPower'] >= 0.2)):
1948                                        #self.sendMessageTwo()
1949                               
1950                                # Lift
1951                                #if ((int(packet['cognitiv']['currentAction']) == 8) and \
1952                                    #(packet['cognitiv']['currentActionPower'] >= 0.2)):
1953                                        #self.sendMessageThree()
1954                               
1955                                # Drop
1956                                #if ((int(packet['cognitiv']['currentAction']) == 16) and \
1957                                    #(packet['cognitiv']['currentActionPower'] >= 0.2)):
1958                                        #self.sendMessageFour()
1959               
1960               
1961                self.updateRobotSpeed()
1962                self.updateHelicopterSpeed()
1963                self.updateWheelchairSpeed()
1964       
1965       
1966        ##################################################################
1967       
1968        def processEyeBlinks(self):
1969               
1970                current_time = time.time()
1971               
1972                keys_to_delete = []
1973               
1974                for timestamp in self.blinks:
1975                        if current_time - timestamp > BLINK_DETECTION_VALID_RANGE:
1976                                keys_to_delete.append(timestamp)
1977               
1978                for timestamp in keys_to_delete:
1979                        del(self.blinks[timestamp])
1980               
1981               
1982                try:
1983                        blink_threshold = int(self.lineEditBlinkDetectionThreshold.text())
1984                except:
1985                        blink_threshold = BLINK_DETECTION_THRESHOLD
1986               
1987                self.progressBarBlinkDetection.setMaximum( blink_threshold )
1988               
1989               
1990                blinks = len(self.blinks)
1991                if blinks > blink_threshold:
1992                        blinks = blink_threshold
1993     
1994               
1995                self.progressBarBlinkDetection.setValue( blinks )
1996               
1997               
1998                if ((self.checkBoxBlinkDetectionEnabled.isChecked()) and \
1999                         (blinks >= blink_threshold)):
2000                       
2001                        self.rotateControlButtons()
2002       
2003       
2004        ##################################################################
2005       
2006        def rotateControlButtons(self):
2007               
2008                # Robotics
2009                if ((self.tabWidget.currentIndex() == \
2010                          self.tabWidget.indexOf(self.tabRobotics)) and \
2011                         (self.brainstormsClient != None)):
2012                       
2013                       
2014                        # Handle changes differntly depending if already moving
2015                        if self.drive_state == 'stop_motors':
2016                       
2017                                # Forward -> Right -> Reverse -> Left -> Forward
2018                               
2019                                if not self.pushButtonForward.isFlat():
2020                                        self.pushButtonForward.setFlat(True)
2021                                       
2022                                        if BLINK_DETECTION_INCLUDE_RIGHT:
2023                                                self.pushButtonTurnRight.setFlat(False)
2024                                        elif BLINK_DETECTION_INCLUDE_REVERSE:
2025                                                self.pushButtonReverse.setFlat(False)
2026                                        elif BLINK_DETECTION_INCLUDE_LEFT:
2027                                                self.pushButtonTurnLeft.setFlat(False)
2028                               
2029                                elif not self.pushButtonTurnRight.isFlat():
2030                                        self.pushButtonTurnRight.setFlat(True)
2031                                       
2032                                        if BLINK_DETECTION_INCLUDE_REVERSE:
2033                                                self.pushButtonReverse.setFlat(False)
2034                                        elif BLINK_DETECTION_INCLUDE_LEFT:
2035                                                self.pushButtonTurnLeft.setFlat(False)
2036                                        elif BLINK_DETECTION_INCLUDE_FORWARD:
2037                                                self.pushButtonForward.setFlat(False)
2038                               
2039                                elif not self.pushButtonReverse.isFlat():
2040                                        self.pushButtonReverse.setFlat(True)
2041                                       
2042                                        if BLINK_DETECTION_INCLUDE_LEFT:
2043                                                self.pushButtonTurnLeft.setFlat(False)
2044                                        elif BLINK_DETECTION_INCLUDE_FORWARD:
2045                                                self.pushButtonForward.setFlat(False)
2046                                        elif BLINK_DETECTION_INCLUDE_RIGHT:
2047                                                self.pushButtonTurnRight.setFlat(False)
2048                               
2049                                elif not self.pushButtonTurnLeft.isFlat():
2050                                        self.pushButtonTurnLeft.setFlat(True)
2051                                        self.pushButtonForward.setFlat(False)
2052                                       
2053                                        if BLINK_DETECTION_INCLUDE_FORWARD:
2054                                                self.pushButtonForward.setFlat(False)
2055                                        elif BLINK_DETECTION_INCLUDE_RIGHT:
2056                                                self.pushButtonTurnRight.setFlat(False)
2057                                        elif BLINK_DETECTION_INCLUDE_REVERSE:
2058                                                self.pushButtonReverse.setFlat(False)
2059                       
2060                       
2061                        else:
2062                               
2063                                # Forward -> Right -> Reverse -> Left -> Forward
2064                               
2065                                if self.pushButtonForward.isDown():
2066                                        #self.pushButtonForward.emit(QtCore.SIGNAL("released()"))
2067                                        self.pushButtonForward.setDown(False)
2068                                        self.pushButtonForward.setFlat(True)
2069                                       
2070                                        if BLINK_DETECTION_INCLUDE_RIGHT:
2071                                                self.pushButtonTurnRight.setDown(True)
2072                                                self.pushButtonTurnRight.setFlat(False)
2073                                        elif BLINK_DETECTION_INCLUDE_REVERSE:
2074                                                self.pushButtonReverse.setDown(True)
2075                                                self.pushButtonReverse.setFlat(False)
2076                                        elif BLINK_DETECTION_INCLUDE_LEFT:
2077                                                self.pushButtonTurnLeft.setDown(True)
2078                                                self.pushButtonTurnLeft.setFlat(False)
2079                               
2080                               
2081                                elif self.pushButtonTurnRight.isDown():
2082                                        #self.pushButtonTurnRight.emit(QtCore.SIGNAL("released()"))
2083                                        self.pushButtonTurnRight.setDown(False)
2084                                        self.pushButtonTurnRight.setFlat(True)
2085                                       
2086                                        if BLINK_DETECTION_INCLUDE_REVERSE:
2087                                                self.pushButtonReverse.setDown(True)
2088                                                self.pushButtonReverse.setFlat(False)
2089                                        elif BLINK_DETECTION_INCLUDE_LEFT:
2090                                                self.pushButtonTurnLeft.setDown(True)
2091                                                self.pushButtonTurnLeft.setFlat(False)
2092                                        elif BLINK_DETECTION_INCLUDE_FORWARD:
2093                                                self.pushButtonForward.setDown(True)
2094                                                self.pushButtonForward.setFlat(False)
2095                               
2096                               
2097                                elif self.pushButtonReverse.isDown():
2098                                        #self.pushButtonReverse.emit(QtCore.SIGNAL("released()"))
2099                                        self.pushButtonReverse.setDown(False)
2100                                        self.pushButtonReverse.setFlat(True)
2101                                       
2102                                        if BLINK_DETECTION_INCLUDE_LEFT:
2103                                                self.pushButtonTurnLeft.setDown(True)
2104                                                self.pushButtonTurnLeft.setFlat(False)
2105                                        elif BLINK_DETECTION_INCLUDE_FORWARD:
2106                                                self.pushButtonForward.setDown(True)
2107                                                self.pushButtonForward.setFlat(False)
2108                                        elif BLINK_DETECTION_INCLUDE_RIGHT:
2109                                                self.pushButtonTurnRight.setDown(True)
2110                                                self.pushButtonTurnRight.setFlat(False)
2111                               
2112                               
2113                                elif self.pushButtonTurnLeft.isDown():
2114                                        #self.pushButtonTurnLeft.emit(QtCore.SIGNAL("released()"))
2115                                        self.pushButtonTurnLeft.setDown(False)
2116                                        self.pushButtonTurnLeft.setFlat(True)
2117                                       
2118                                        if BLINK_DETECTION_INCLUDE_FORWARD:
2119                                                self.pushButtonForward.setDown(True)
2120                                                self.pushButtonForward.setFlat(False)
2121                                        elif BLINK_DETECTION_INCLUDE_RIGHT:
2122                                                self.pushButtonTurnRight.setDown(True)
2123                                                self.pushButtonTurnRight.setFlat(False)
2124                                        elif BLINK_DETECTION_INCLUDE_REVERSE:
2125                                                self.pushButtonReverse.setDown(True)
2126                                                self.pushButtonReverse.setFlat(False)
2127               
2128               
2129                self.blinks = {} # Reset all blinks after a rotation
2130       
2131       
2132        ##################################################################
2133       
2134        def sendFeedback(self):
2135               
2136                values = {}
2137               
2138                values['name'] = str(self.lineEditFeedbackName.text())
2139                values['email'] = str(self.lineEditFeedbackEmail.text())
2140                values['comment'] = str(self.textEditFeedback.toPlainText())
2141               
2142                values['subject'] = '[brainstorms feedback]'
2143                values['capcha_contact'] = 'brainstorms'
2144               
2145               
2146                url_data = urllib.urlencode(values)
2147               
2148                try:
2149                        page = urllib.urlopen(BRAINSTORMS_FEEDBACK_URL, url_data)
2150                       
2151                        reply = QtGui.QMessageBox.information( \
2152                              self, \
2153                              'Feedback Sent', \
2154                              'Thank you for your feedback', \
2155                              'OK')
2156                       
2157                        self.lineEditFeedbackName.setText('')
2158                        self.lineEditFeedbackEmail.setText('')
2159                        self.textEditFeedback.setText('')
2160               
2161                except:
2162                        reply = QtGui.QMessageBox.information( \
2163                              self, \
2164                              'Feedback Sent', \
2165                              'We\'re sorry but there was an error submitting your feedback.\nPlease email contact@puzzlebox.info instead.', \
2166                              'OK')
2167       
2168       
2169        ##################################################################
2170       
2171        def closeEvent(self, event):
2172               
2173                quit_message = "Are you sure you want to exit the program?"
2174               
2175                reply = QtGui.QMessageBox.question( \
2176                           self, \
2177                          'Quit Puzzlebox Brainstorms', \
2178                           quit_message, \
2179                           QtGui.QMessageBox.Yes, \
2180                           QtGui.QMessageBox.No)
2181               
2182                if reply == QtGui.QMessageBox.Yes:
2183                       
2184                        if self.brainstormsClient != None:
2185                                self.stopMotors()
2186                                self.brainstormsClient.socket.flush()
2187                               
2188                                if self.brainstormsServer != None:
2189                                       
2190                                        if self.brainstormsServer.rc == None:
2191                                               
2192                                                device_address = str(self.comboBoxRobotPortSelect.currentText())
2193                                                self.brainstormsServer.executeCommand( \
2194                                                        'stop_motors')
2195                                               
2196                                        else:
2197                                                self.brainstormsServer.rc.run('stop_motors')
2198                       
2199                       
2200                        event.accept()
2201               
2202                else:
2203                        event.ignore()
2204
2205
2206#####################################################################
2207# Functions
2208#####################################################################
2209
2210#####################################################################
2211# Main
2212#####################################################################
2213
2214if __name__ == '__main__':
2215       
2216        #log = puzzlebox_logger.puzzlebox_logger(logfile='client_interface')
2217        log = None
2218       
2219        app = QtGui.QApplication(sys.argv)
2220       
2221        window = puzzlebox_brainstorms_client_interface(log, DEBUG)
2222        window.show()
2223       
2224        sys.exit(app.exec_())
2225
Note: See TracBrowser for help on using the repository browser.