source: trunk/brainstorms/Puzzlebox/Brainstorms/Interface.py @ 247

Last change on this file since 247 was 247, checked in by sc, 12 years ago

Interface.py:

  • Fixed bugs with device port connections

Wheelchair_Control.py:

  • Turning speeds reduced

setup.py:

  • whitespace cleanup
File size: 53.8 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Client Interface - Qt
5#
6# Copyright Puzzlebox Productions, LLC (2010)
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: 2010.12.04
13
14"""
15
16__todo__ = """
17 - server may not correctly handle multiple clients connected
18      to an embedded Brainstorms server
19 - disable autorepeating on shortcut keys
20 - update configuration.ini file with settings entered into interface
21
22"""
23
24import os, sys
25import urllib
26
27if (sys.platform == 'win32'):
28        DEFAULT_IMAGE_PATH = 'images'
29        import _winreg as winreg
30        import itertools
31        import re
32        import serial
33else:
34        DEFAULT_IMAGE_PATH = '/usr/share/puzzlebox_brainstorms/images'
35        import bluetooth
36        os.chdir('/usr/share/puzzlebox_brainstorms')
37
38try:
39        import PySide as PyQt4
40        from PySide import QtCore, QtGui, QtNetwork
41except:
42        print "Using PyQt4 module"
43        from PyQt4 import QtCore, QtGui, QtNetwork
44else:
45        print "Using PySide module"
46
47#from PyQt4 import QtCore, QtGui, QtNetwork
48#from PySide import QtCore, QtGui, QtNetwork
49
50from Interface_Design import Ui_Form as Design
51
52import simplejson as json
53
54import Configuration as configuration
55import Client as brainstorms_client
56import Puzzlebox.Brainstorms.ThinkGear.Client as thinkgear_client
57import Helicopter_Control as helicopter_control
58import Wheelchair_Control as wheelchair_control
59#import puzzlebox_logger
60
61#####################################################################
62# Globals
63#####################################################################
64
65DEBUG = 1
66
67THINKGEAR_POWER_THRESHOLDS = configuration.THINKGEAR_POWER_THRESHOLDS
68
69BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
70
71NXT_BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
72
73DEFAULT_NXT_POWER_LEVEL = configuration.DEFAULT_NXT_POWER_LEVEL
74
75THINKGEAR_SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
76THINKGEAR_SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
77
78BRAINSTORMS_FEEDBACK_URL = 'http://brainstorms.puzzlebox.info/contact_cgi.php'
79
80DEVICE_PATH = '/dev'
81PATH_TO_HCITOOL = '/usr/bin/hcitool'
82
83#####################################################################
84# Classes
85#####################################################################
86
87class puzzlebox_brainstorms_client_interface(QtGui.QWidget, Design):
88       
89        def __init__(self, log, server=None, DEBUG=DEBUG, parent = None):
90               
91                self.log = log
92                self.DEBUG = DEBUG
93               
94                QtGui.QWidget.__init__(self, parent)
95                self.setupUi(self)
96               
97                self.configureSettings()
98                self.connectWidgets()
99               
100                self.name = "Brainstorms Interface"
101               
102                self.brainstormsServer = server
103                self.brainstormsClient = None
104               
105                self.helicopter = None
106                self.wheelchair = None
107               
108                self.drive_state = 'stop_motors'
109                self.current_speed = 0
110               
111                self.current_helicopter_state = 'neutral'
112       
113       
114        ##################################################################
115       
116        def configureSettings(self):
117               
118                # Brainstorms Interface
119               
120                image_path = "puzzlebox.ico"
121                if not os.path.exists(image_path):
122                        image_path = os.path.join(DEFAULT_IMAGE_PATH, image_path)
123               
124                if os.path.exists(image_path):
125                        icon = QtGui.QIcon()
126                        icon.addPixmap(QtGui.QPixmap(image_path), \
127                                            QtGui.QIcon.Normal, \
128                                            QtGui.QIcon.Off)
129                        self.setWindowIcon(icon)
130               
131                image_path = "puzzlebox_logo.png"
132                if not os.path.exists(image_path):
133                        image_path = os.path.join(DEFAULT_IMAGE_PATH, image_path)
134                if os.path.exists(image_path):
135                        self.labelPuzzlebox.setPixmap(QtGui.QPixmap(image_path))
136               
137                self.pushButtonTurnLeft.setEnabled(False)
138                self.pushButtonForward.setEnabled(False)
139                self.pushButtonTurnRight.setEnabled(False)
140                self.pushButtonTurnLeftReverse.setEnabled(False)
141                self.pushButtonReverse.setEnabled(False)
142                self.pushButtonTurnRightReverse.setEnabled(False)
143               
144                self.pushButtonConcentrationEnable.setDown(True)
145                self.pushButtonRelaxationEnable.setDown(True)
146                self.pushButtonSpeedEnable.setDown(True)
147               
148               
149                # Search for available Serial and Bluetooth devices
150                self.searchForDevices()
151               
152               
153                # LEGO Mindstorms
154                self.textLabelNXTStatus.setText("Status: Disconnected")
155               
156                # Display communication port for LEGO Mindstorms NXT device
157                #self.lineEditNXTPort.setText(NXT_BLUETOOTH_DEVICE)
158                self.comboBoxNXTPortSelect.setEnabled(True)
159               
160               
161                # RC Helicopter
162                self.textLabelHelicopterStatus.setText("Status: Disconnected")
163               
164               
165                # Wheelchair
166                self.textLabelWheelchairStatus.setText("Status: Disconnected")
167               
168               
169                # Control Panel
170               
171                # Display Host for ThinkGear Connect Socket Server
172                self.lineEditThinkGearHost.setText(THINKGEAR_SERVER_HOST)
173                #self.lineEditThinkGearHost.setEnabled(False)
174               
175                # Display Port for ThinkGear Connect Socket Server
176                self.lineEditThinkGearPort.setText('%i' % THINKGEAR_SERVER_PORT)
177                #self.lineEditThinkGearPort.setEnabled(False)
178               
179               
180                self.lineEditLeftMotorPort.setText( \
181                   configuration.NXT_MOTOR_PORT_LEFT.upper() )
182                self.lineEditRightMotorPort.setText(   \
183                   configuration.NXT_MOTOR_PORT_RIGHT.upper() )
184                self.checkBoxMotorSpinReversed.setChecked( \
185                   configuration.NXT_MOTORS_MOUNTED_BACKWARDS)
186       
187       
188        ##################################################################
189       
190        def getMinimumThreshold(self, threshold):
191               
192                '''Return the minimum detection level which results
193                in a non-zero power setting'''
194               
195                minimum = 100
196               
197                threshold_keys = threshold.keys()
198                threshold_keys.sort()
199                threshold_keys.reverse()
200               
201                for key in threshold_keys:
202                       
203                        if ((threshold[key] < minimum) and \
204                                 (threshold[key] > 0)):
205                                minimum = key
206               
207               
208                return(minimum)
209       
210       
211        ##################################################################
212       
213        def configureNetworkBrainstorms(self):
214               
215                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
216               
217                self.brainstormsClient = \
218                   brainstorms_client.puzzlebox_brainstorms_network_client( \
219                           self.log, \
220                           bluetooth_device=bluetooth_device, \
221                           parent=self)
222               
223                self.brainstormsClient.sendCommand('connect', \
224                                                   bluetooth_device=bluetooth_device)
225       
226       
227        ##################################################################
228       
229        def connectToBrainstormsServer(self):
230               
231                # Prevent attempting to connect to a device which does not exist
232                device = str(self.comboBoxNXTPortSelect.currentText())
233                if device == 'N/A':
234                        self.pushButtonNXTConnect.setChecked(False)
235                        return
236                if (sys.platform != 'win32'):
237                        if ((not device.startswith(DEVICE_PATH)) or \
238                            (not os.path.exists(device))):
239                                self.searchForDevices()
240                                self.pushButtonNXTConnect.setChecked(False)
241                                return
242               
243               
244                if self.DEBUG:
245                        print "<---- [%s] Connecting to Brainstorms Server" % self.name
246               
247                self.configureNetworkBrainstorms()
248               
249                #if (self.brainstormsClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
250                        #QtGui.QMessageBox.information(self, \
251                                                                #self.brainstormsClient.socket.name, \
252                                           #"Failed to connect to Brainstorms socket server")
253               
254                #else:
255                self.disconnect(self.pushButtonNXTConnect, \
256                                                        QtCore.SIGNAL("clicked()"), \
257                                                        self.connectToBrainstormsServer)
258               
259                self.connect(self.pushButtonNXTConnect, \
260                                                        QtCore.SIGNAL("clicked()"), \
261                                                        self.disconnectFromBrainstormsServer)
262               
263                self.textLabelNXTStatus.setText("Status: Connected")
264                self.pushButtonNXTConnect.setText('Disconnect')
265               
266                self.comboBoxNXTPortSelect.setEnabled(False)
267                self.pushButtonNXTSearch.setEnabled(False)
268               
269                self.pushButtonTurnLeft.setEnabled(True)
270                self.pushButtonForward.setEnabled(True)
271                self.pushButtonTurnRight.setEnabled(True)
272                self.pushButtonTurnLeftReverse.setEnabled(True)
273                self.pushButtonReverse.setEnabled(True)
274                self.pushButtonTurnRightReverse.setEnabled(True)
275               
276                self.pushButtonNXTMessageOne.setEnabled(True)
277                self.pushButtonNXTMessageTwo.setEnabled(True)
278                self.pushButtonNXTMessageThree.setEnabled(True)
279                self.pushButtonNXTMessageFour.setEnabled(True)
280                self.pushButtonNXTMessageFive.setEnabled(True)
281                self.pushButtonNXTMessageSix.setEnabled(True)
282               
283                self.pushButtonConcentrationEnable.setEnabled(True)
284                self.pushButtonRelaxationEnable.setEnabled(True)
285                self.pushButtonSpeedEnable.setEnabled(True)
286               
287                self.pushButtonMessageOne.setEnabled(True)
288                self.pushButtonMessageTwo.setEnabled(True)
289                self.pushButtonMessageThree.setEnabled(True)
290                self.pushButtonMessageFour.setEnabled(True)
291                self.pushButtonMessageFive.setEnabled(True)
292                self.pushButtonMessageSix.setEnabled(True)
293       
294       
295        ##################################################################
296       
297        def disconnectFromBrainstormsServer(self):
298               
299                if self.DEBUG:
300                        print "- - [%s] Disconnecting from Brainstorms Server" % self.name
301               
302                self.stopMotors()
303               
304                # Ensure the stopMotors command has been received by the server
305                # so the NXT robot will stop before the client disconnects
306                self.brainstormsClient.socket.flush()
307               
308                self.brainstormsClient.socket.disconnectFromHost()
309               
310                self.disconnect(self.pushButtonNXTConnect, \
311                                  QtCore.SIGNAL("clicked()"), \
312                                  self.disconnectFromBrainstormsServer)
313               
314                self.connect(self.pushButtonNXTConnect, \
315                                  QtCore.SIGNAL("clicked()"), \
316                                  self.connectToBrainstormsServer)
317               
318                self.textLabelNXTStatus.setText("Status: Disconnected")
319                self.pushButtonNXTConnect.setText('Connect')
320               
321                self.comboBoxNXTPortSelect.setEnabled(True)
322                self.pushButtonNXTSearch.setEnabled(True)
323               
324                self.pushButtonTurnLeft.setEnabled(False)
325                self.pushButtonForward.setEnabled(False)
326                self.pushButtonTurnRight.setEnabled(False)
327                self.pushButtonTurnLeftReverse.setEnabled(False)
328                self.pushButtonReverse.setEnabled(False)
329                self.pushButtonTurnRightReverse.setEnabled(False)
330               
331                self.pushButtonNXTMessageOne.setEnabled(False)
332                self.pushButtonNXTMessageTwo.setEnabled(False)
333                self.pushButtonNXTMessageThree.setEnabled(False)
334                self.pushButtonNXTMessageFour.setEnabled(False)
335                self.pushButtonNXTMessageFive.setEnabled(False)
336                self.pushButtonNXTMessageSix.setEnabled(False)
337               
338                self.pushButtonConcentrationEnable.setEnabled(False)
339                self.pushButtonRelaxationEnable.setEnabled(False)
340                self.pushButtonSpeedEnable.setEnabled(False)
341               
342                self.pushButtonMessageOne.setEnabled(False)
343                self.pushButtonMessageTwo.setEnabled(False)
344                self.pushButtonMessageThree.setEnabled(False)
345                self.pushButtonMessageFour.setEnabled(False)
346                self.pushButtonMessageFive.setEnabled(False)
347                self.pushButtonMessageSix.setEnabled(False)
348               
349                self.brainstormsClient = None
350               
351                self.searchForDevices()
352       
353       
354        ##################################################################
355       
356        def connectToThinkGearHost(self):
357               
358                if self.DEBUG:
359                        print "Connecting to ThinkGear Host"
360               
361                server_host = str(self.lineEditThinkGearHost.text())
362                server_port = int(self.lineEditThinkGearPort.text())
363               
364                self.thinkgearClient = \
365                   thinkgear_client.puzzlebox_brainstorms_network_client_thinkgear( \
366                           self.log, \
367                           server_host=server_host, \
368                           server_port=server_port, \
369                           DEBUG=0, \
370                           parent=self)
371               
372                if (self.thinkgearClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
373                        QtGui.QMessageBox.information(self, \
374                                                                self.thinkgearClient.socket.name, \
375                                           "Failed to connect to ThinkGear socket server")
376               
377                else:
378                        self.disconnect(self.pushButtonThinkGearConnect, \
379                                                         QtCore.SIGNAL("clicked()"), \
380                                                         self.connectToThinkGearHost)
381                       
382                        self.connect(self.pushButtonThinkGearConnect, \
383                                                         QtCore.SIGNAL("clicked()"), \
384                                                         self.disconnectFromThinkGearHost)
385                       
386                        self.pushButtonThinkGearConnect.setText('Disconnect')
387                       
388                        self.comboBoxEEGHeadsetModel.setEnabled(False)
389                        self.comboBoxEEGSource.setEnabled(False)
390                        self.lineEditThinkGearHost.setEnabled(False)
391                        self.lineEditThinkGearPort.setEnabled(False)
392       
393       
394        ##################################################################
395       
396        def disconnectFromThinkGearHost(self):
397               
398                if self.DEBUG:
399                        print "Disconnecting from ThinkGear Host"
400               
401                self.thinkgearClient.disconnectFromHost()
402               
403                self.disconnect(self.pushButtonThinkGearConnect, \
404                                  QtCore.SIGNAL("clicked()"), \
405                                  self.disconnectFromThinkGearHost)
406               
407                self.connect(self.pushButtonThinkGearConnect, \
408                                  QtCore.SIGNAL("clicked()"), \
409                                  self.connectToThinkGearHost)
410               
411                self.pushButtonForward.emit(QtCore.SIGNAL("released()"))
412               
413                self.pushButtonThinkGearConnect.setText('Connect')
414               
415                self.comboBoxEEGHeadsetModel.setEnabled(True)
416                self.comboBoxEEGSource.setEnabled(True)
417                self.lineEditThinkGearHost.setEnabled(True)
418                self.lineEditThinkGearPort.setEnabled(True)
419               
420                self.progressBarConcentration.setValue(0)
421                self.progressBarRelaxation.setValue(0)
422                self.progressBarSpeed.setValue(0)
423       
424                self.progressBarHelicopterConcentration.setValue(0)
425                self.progressBarHelicopterRelaxation.setValue(0)
426                self.progressBarHelicopterSpeed.setValue(0)
427       
428                self.progressBarWheelchairConcentration.setValue(0)
429                self.progressBarWheelchairRelaxation.setValue(0)
430                self.progressBarWheelchairSpeed.setValue(0)
431       
432       
433        ##################################################################
434       
435        def connectToRCHelicopter(self):
436
437                # Prevent attempting to connect to a device which does not exist
438                device = str(self.comboBoxHelicopterPortSelect.currentText())
439                if device == 'N/A':
440                        self.pushButtonHelicopterConnect.setChecked(False)
441                        return
442                if (sys.platform != 'win32'):
443                        if ((not device.startswith(DEVICE_PATH)) or \
444                            (not os.path.exists(device))):
445                                self.searchForDevices()
446                                self.pushButtonHelicopterConnect.setChecked(False)
447                                return
448
449                self.helicopter = \
450                   helicopter_control.puzzlebox_brainstorms_helicopter_control( \
451                      device_address=device,
452                      command='neutral', \
453                      DEBUG=self.DEBUG)
454               
455                self.helicopter.start()
456               
457                self.disconnect(self.pushButtonHelicopterConnect, \
458                                  QtCore.SIGNAL("clicked()"), \
459                                  self.connectToRCHelicopter)
460               
461                self.connect(self.pushButtonHelicopterConnect, \
462                                  QtCore.SIGNAL("clicked()"), \
463                                  self.disconnectFromRCHelicopter)
464               
465                self.pushButtonHelicopterConnect.setText('Disconnect')
466               
467                self.comboBoxHelicopterTransmitter.setEnabled(False)
468                self.comboBoxHelicopterPortSelect.setEnabled(False)
469                self.pushButtonHelicopterSearch.setEnabled(False)
470               
471                self.pushButtonHelicopterHover.setEnabled(True)
472                self.pushButtonHelicopterFlyForward.setEnabled(True)
473                self.pushButtonHelicopterLand.setEnabled(True)
474                self.pushButtonHelicopterThrottle.setEnabled(True)
475                self.verticalSliderHelicopterThrottle.setEnabled(True)
476                self.pushButtonHelicopterElevatorForward.setEnabled(True)
477                self.verticalSliderHelicopterElevatorForward.setEnabled(True)
478                self.pushButtonHelicopterElevatorReverse.setEnabled(True)
479                self.verticalSliderHelicopterElevatorReverse.setEnabled(True)
480                self.pushButtonHelicopterRudderLeft.setEnabled(True)
481                self.horizontalSliderHelicopterRudderLeft.setEnabled(True)
482                self.pushButtonHelicopterRudderRight.setEnabled(True)
483                self.horizontalSliderHelicopterRudderRight.setEnabled(True)
484                self.pushButtonHelicopterAileronLeft.setEnabled(True)
485                self.horizontalSliderHelicopterAileronLeft.setEnabled(True)
486                self.pushButtonHelicopterAileronRight.setEnabled(True)
487                self.horizontalSliderHelicopterAileronRight.setEnabled(True)
488               
489                self.pushButtonHelicopterConcentrationEnable.setEnabled(True)
490                self.pushButtonHelicopterRelaxationEnable.setEnabled(True)
491                self.pushButtonHelicopterSpeedEnable.setEnabled(True)
492       
493       
494        ##################################################################
495       
496        def disconnectFromRCHelicopter(self):
497               
498                self.helicopter.neutral()
499                self.current_helicopter_state = 'neutral'
500               
501                self.helicopter.stop()
502               
503                self.disconnect(self.pushButtonHelicopterConnect, \
504                                  QtCore.SIGNAL("clicked()"), \
505                                  self.disconnectFromRCHelicopter)
506               
507                self.connect(self.pushButtonHelicopterConnect, \
508                                  QtCore.SIGNAL("clicked()"), \
509                                  self.connectToRCHelicopter)
510               
511                self.pushButtonHelicopterConnect.setText('Connect')
512               
513                self.comboBoxHelicopterTransmitter.setEnabled(True)
514                self.comboBoxHelicopterPortSelect.setEnabled(True)
515                self.pushButtonHelicopterSearch.setEnabled(True)
516               
517                self.pushButtonHelicopterHover.setEnabled(False)
518                self.pushButtonHelicopterFlyForward.setEnabled(False)
519                self.pushButtonHelicopterLand.setEnabled(False)
520                self.pushButtonHelicopterThrottle.setEnabled(False)
521                self.verticalSliderHelicopterThrottle.setEnabled(False)
522                self.pushButtonHelicopterElevatorForward.setEnabled(False)
523                self.verticalSliderHelicopterElevatorForward.setEnabled(False)
524                self.pushButtonHelicopterElevatorReverse.setEnabled(False)
525                self.verticalSliderHelicopterElevatorReverse.setEnabled(False)
526                self.pushButtonHelicopterRudderLeft.setEnabled(False)
527                self.horizontalSliderHelicopterRudderLeft.setEnabled(False)
528                self.pushButtonHelicopterRudderRight.setEnabled(False)
529                self.horizontalSliderHelicopterRudderRight.setEnabled(False)
530                self.pushButtonHelicopterAileronLeft.setEnabled(False)
531                self.horizontalSliderHelicopterAileronLeft.setEnabled(False)
532                self.pushButtonHelicopterAileronRight.setEnabled(False)
533                self.horizontalSliderHelicopterAileronRight.setEnabled(False)
534               
535                self.pushButtonHelicopterConcentrationEnable.setEnabled(False)
536                self.pushButtonHelicopterRelaxationEnable.setEnabled(False)
537                self.pushButtonHelicopterSpeedEnable.setEnabled(False)
538       
539       
540        ##################################################################
541       
542        def connectToWheelchair(self):
543               
544                # Prevent attempting to connect to a device which does not exist
545                device = str(self.comboBoxWheelchairPortSelect.currentText())
546                if device == 'N/A':
547                        self.pushButtonWheelchairConnect.setChecked(False)     
548                        return
549                if (sys.platform != 'win32'):
550                        if ((not device.startswith(DEVICE_PATH)) or \
551                            (not os.path.exists(device))):
552                                self.searchForDevices()
553                                self.pushButtonWheelchairConnect.setChecked(False)
554                                return
555               
556                self.wheelchair = \
557                   wheelchair_control.puzzlebox_brainstorms_wheelchair_control( \
558                      device_address=device,
559                      command=None, \
560                      DEBUG=self.DEBUG)
561               
562                #self.wheelchair.start()
563               
564                self.disconnect(self.pushButtonWheelchairConnect, \
565                                  QtCore.SIGNAL("clicked()"), \
566                                  self.connectToWheelchair)
567               
568                self.connect(self.pushButtonWheelchairConnect, \
569                                  QtCore.SIGNAL("clicked()"), \
570                                  self.disconnectFromWheelchair)
571               
572                self.pushButtonWheelchairConnect.setText('Disconnect')
573               
574                self.comboBoxWheelchairTransmitter.setEnabled(False)
575                self.comboBoxWheelchairPortSelect.setEnabled(False)
576                self.pushButtonWheelchairSearch.setEnabled(False)
577               
578                self.pushButtonWheelchairForward.setEnabled(True)
579                self.pushButtonWheelchairReverse.setEnabled(True)
580                self.pushButtonWheelchairLeft.setEnabled(True)
581                self.pushButtonWheelchairRight.setEnabled(True)
582                self.pushButtonWheelchairStop.setEnabled(True)
583                self.dialWheelchairSpeed.setEnabled(True)
584               
585                self.pushButtonWheelchairConcentrationEnable.setEnabled(True)
586                self.pushButtonWheelchairRelaxationEnable.setEnabled(True)
587                self.pushButtonWheelchairSpeedEnable.setEnabled(True)
588               
589                # Safety Measure: Explicitely require wheelchair speed control
590                # to be enabled each time it wheelchair is connected
591                self.pushButtonWheelchairSpeedEnable.setChecked(False)
592                self.pushButtonWheelchairSpeedEnable.setText('Disabled')
593                self.progressBarWheelchairSpeed.setValue(0)
594       
595       
596        ##################################################################
597       
598        def disconnectFromWheelchair(self):
599               
600                self.stopWheelchair()
601               
602                #self.wheelchair.stop()
603               
604                self.disconnect(self.pushButtonWheelchairConnect, \
605                                  QtCore.SIGNAL("clicked()"), \
606                                  self.disconnectFromWheelchair)
607               
608                self.connect(self.pushButtonWheelchairConnect, \
609                                  QtCore.SIGNAL("clicked()"), \
610                                  self.connectToWheelchair)
611               
612                self.pushButtonWheelchairConnect.setText('Connect')
613               
614                self.comboBoxWheelchairTransmitter.setEnabled(True)
615                self.comboBoxWheelchairPortSelect.setEnabled(True)
616                self.pushButtonWheelchairSearch.setEnabled(True)
617               
618                self.pushButtonWheelchairForward.setEnabled(False)
619                self.pushButtonWheelchairReverse.setEnabled(False)
620                self.pushButtonWheelchairLeft.setEnabled(False)
621                self.pushButtonWheelchairRight.setEnabled(False)
622                self.pushButtonWheelchairStop.setEnabled(False)
623                self.dialWheelchairSpeed.setEnabled(False)
624               
625                self.pushButtonWheelchairConcentrationEnable.setEnabled(False)
626                self.pushButtonWheelchairRelaxationEnable.setEnabled(False)
627                self.pushButtonWheelchairSpeedEnable.setEnabled(False)
628               
629                # Safety Measure: Explicitely require wheelchair speed control
630                # to be enabled each time it wheelchair is connected
631                self.pushButtonWheelchairSpeedEnable.setChecked(False)
632                self.pushButtonWheelchairSpeedEnable.setText('Disabled')
633                self.progressBarWheelchairSpeed.setValue(0)
634       
635       
636        ##################################################################
637       
638        def updateConcentrationButton(self):
639               
640                if self.pushButtonConcentrationEnable.isChecked():
641                       
642                        self.pushButtonConcentrationEnable.setText('Enabled')
643               
644                else:
645                       
646                        self.pushButtonConcentrationEnable.setText('Disabled')
647                        self.progressBarConcentration.setValue(0)
648               
649               
650                self.updateSpeed()
651       
652       
653        ##################################################################
654       
655        def updateRelaxationButton(self):
656               
657                if self.pushButtonRelaxationEnable.isChecked():
658               
659                        self.pushButtonRelaxationEnable.setText('Enabled')
660               
661                else:
662                       
663                        self.pushButtonRelaxationEnable.setText('Disabled')
664                        self.progressBarRelaxation.setValue(0)
665               
666               
667                self.updateNXTSpeed()
668       
669       
670        ##################################################################
671       
672        def updateSpeedButton(self):
673               
674                if self.pushButtonSpeedEnable.isChecked():
675               
676                        self.pushButtonSpeedEnable.setText('Enabled')
677                        self.updateSpeed()
678               
679                else:
680                       
681                        self.pushButtonSpeedEnable.setText('Disabled')
682                        self.progressBarSpeed.setValue(0)
683                        self.stopMotors()
684       
685       
686        ##################################################################
687       
688        def updateHelicopterConcentrationButton(self):
689               
690                if self.pushButtonHelicopterConcentrationEnable.isChecked():
691                       
692                        self.pushButtonHelicopterConcentrationEnable.setText('Enabled')
693               
694                else:
695                       
696                        self.pushButtonHelicopterConcentrationEnable.setText('Disabled')
697                        self.progressBarHelicopterConcentration.setValue(0)
698               
699               
700                self.updateHelicopterSpeed()
701       
702       
703        ##################################################################
704       
705        def updateHelicopterRelaxationButton(self):
706               
707                if self.pushButtonHelicopterRelaxationEnable.isChecked():
708               
709                        self.pushButtonHelicopterRelaxationEnable.setText('Enabled')
710               
711                else:
712                       
713                        self.pushButtonHelicopterRelaxationEnable.setText('Disabled')
714                        self.progressBarHelicopterRelaxation.setValue(0)
715               
716               
717                self.updateHelicopterSpeed()
718       
719       
720        ##################################################################
721       
722        def updateHelicopterSpeedButton(self):
723               
724                if self.pushButtonHelicopterSpeedEnable.isChecked():
725               
726                        self.pushButtonHelicopterSpeedEnable.setText('Enabled')
727                        self.updateHelicopterSpeed()
728               
729                else:
730                       
731                        self.pushButtonHelicopterSpeedEnable.setText('Disabled')
732                        self.progressBarHelicopterSpeed.setValue(0)
733                        self.landHelicopter()
734       
735       
736        ##################################################################
737       
738        def updateWheelchairConcentrationButton(self):
739               
740                if self.pushButtonWheelchairConcentrationEnable.isChecked():
741                       
742                        self.pushButtonWheelchairConcentrationEnable.setText('Enabled')
743               
744                else:
745                       
746                        self.pushButtonWheelchairConcentrationEnable.setText('Disabled')
747                        self.progressBarWheelchairConcentration.setValue(0)
748               
749               
750                self.updateWheelchairSpeed()
751       
752       
753        ##################################################################
754       
755        def updateWheelchairRelaxationButton(self):
756               
757                if self.pushButtonWheelchairRelaxationEnable.isChecked():
758               
759                        self.pushButtonWheelchairRelaxationEnable.setText('Enabled')
760               
761                else:
762                       
763                        self.pushButtonWheelchairRelaxationEnable.setText('Disabled')
764                        self.progressBarWheelchairRelaxation.setValue(0)
765               
766               
767                self.updateWheelchairSpeed()
768       
769       
770        ##################################################################
771       
772        def updateWheelchairSpeedButton(self):
773               
774                if self.pushButtonWheelchairSpeedEnable.isChecked():
775               
776                        self.pushButtonWheelchairSpeedEnable.setText('Enabled')
777                        self.updateWheelchairSpeed()
778               
779                else:
780                       
781                        self.pushButtonWheelchairSpeedEnable.setText('Disabled')
782                        self.progressBarWheelchairSpeed.setValue(0)
783                        self.stopWheelchair()
784       
785       
786        ##################################################################
787       
788        def connectWidgets(self):
789               
790                # LEGO Mindstorms Buttons
791                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("pressed()"), \
792                             self.turnLeft)
793                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("released()"), \
794                             self.stopMotors)
795               
796                self.connect(self.pushButtonForward, QtCore.SIGNAL("pressed()"), \
797                             self.driveForward)
798                self.connect(self.pushButtonForward, QtCore.SIGNAL("released()"), \
799                             self.stopMotors)
800               
801                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("pressed()"), \
802                             self.turnRight)
803                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("released()"), \
804                             self.stopMotors)
805               
806                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("pressed()"), \
807                             self.turnLeftInReverse)
808                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("released()"), \
809                             self.stopMotors)
810               
811                self.connect(self.pushButtonReverse, QtCore.SIGNAL("pressed()"), \
812                             self.driveReverse)
813                self.connect(self.pushButtonReverse, QtCore.SIGNAL("released()"), \
814                             self.stopMotors)
815               
816                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("pressed()"), \
817                             self.turnRightInReverse)
818                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("released()"), \
819                             self.stopMotors)
820               
821               
822                self.connect(self.pushButtonNXTSearch, \
823                                  QtCore.SIGNAL("clicked()"), \
824                                  self.searchForDevices)
825               
826                self.connect(self.pushButtonNXTConnect, \
827                                  QtCore.SIGNAL("clicked()"), \
828                                  self.connectToBrainstormsServer)
829               
830               
831                self.connect(self.pushButtonConcentrationEnable, \
832                                  QtCore.SIGNAL("clicked()"), \
833                                  self.updateConcentrationButton)
834               
835                self.connect(self.pushButtonRelaxationEnable, \
836                                  QtCore.SIGNAL("clicked()"), \
837                                  self.updateRelaxationButton)
838               
839                self.connect(self.pushButtonSpeedEnable, \
840                                  QtCore.SIGNAL("clicked()"), \
841                                  self.updateSpeedButton)
842               
843               
844                self.connect(self.pushButtonNXTMessageOne, QtCore.SIGNAL("pressed()"), \
845                             self.sendMessageOne)
846               
847                self.connect(self.pushButtonNXTMessageTwo, QtCore.SIGNAL("pressed()"), \
848                             self.sendMessageTwo)
849               
850                self.connect(self.pushButtonNXTMessageThree, QtCore.SIGNAL("pressed()"), \
851                             self.sendMessageThree)
852               
853                self.connect(self.pushButtonNXTMessageFour, QtCore.SIGNAL("pressed()"), \
854                             self.sendMessageFour)
855               
856                self.connect(self.pushButtonNXTMessageFive, QtCore.SIGNAL("pressed()"), \
857                             self.sendMessageFive)
858               
859                self.connect(self.pushButtonNXTMessageSix, QtCore.SIGNAL("pressed()"), \
860                             self.sendMessageSix)
861               
862               
863               
864                # RC Helicopter Buttons
865                self.connect(self.pushButtonHelicopterSearch, \
866                                  QtCore.SIGNAL("clicked()"), \
867                                  self.searchForDevices)
868               
869                self.connect(self.pushButtonHelicopterConnect, \
870                                  QtCore.SIGNAL("clicked()"), \
871                                  self.connectToRCHelicopter)
872               
873               
874                self.connect(self.pushButtonHelicopterConcentrationEnable, \
875                                  QtCore.SIGNAL("clicked()"), \
876                                  self.updateHelicopterConcentrationButton)
877               
878                self.connect(self.pushButtonHelicopterRelaxationEnable, \
879                                  QtCore.SIGNAL("clicked()"), \
880                                  self.updateHelicopterRelaxationButton)
881               
882                self.connect(self.pushButtonHelicopterSpeedEnable, \
883                                  QtCore.SIGNAL("clicked()"), \
884                                  self.updateHelicopterSpeedButton)
885               
886               
887                self.connect(self.pushButtonHelicopterHover, \
888                                  QtCore.SIGNAL("clicked()"), \
889                                  self.enableHelicopterHover)
890               
891                self.connect(self.pushButtonHelicopterFlyForward, \
892                                  QtCore.SIGNAL("clicked()"), \
893                                  self.enableHelicopterFlyForward)
894               
895                self.connect(self.pushButtonHelicopterLand, \
896                                  QtCore.SIGNAL("clicked()"), \
897                                  self.landHelicopter)
898               
899               
900               
901                # Wheelchair Buttons
902                self.connect(self.pushButtonWheelchairSearch, \
903                                  QtCore.SIGNAL("clicked()"), \
904                                  self.searchForDevices)
905               
906                self.connect(self.pushButtonWheelchairConnect, \
907                                  QtCore.SIGNAL("clicked()"), \
908                                  self.connectToWheelchair)
909               
910               
911                self.connect(self.pushButtonWheelchairConcentrationEnable, \
912                                  QtCore.SIGNAL("clicked()"), \
913                                  self.updateWheelchairConcentrationButton)
914               
915                self.connect(self.pushButtonWheelchairRelaxationEnable, \
916                                  QtCore.SIGNAL("clicked()"), \
917                                  self.updateWheelchairRelaxationButton)
918               
919                self.connect(self.pushButtonWheelchairSpeedEnable, \
920                                  QtCore.SIGNAL("clicked()"), \
921                                  self.updateWheelchairSpeedButton)
922               
923               
924                self.connect(self.pushButtonWheelchairForward, \
925                                  QtCore.SIGNAL("pressed()"), \
926                                  self.driveWheelchairForward)
927                self.connect(self.pushButtonWheelchairForward, \
928                             QtCore.SIGNAL("released()"), \
929                             self.stopWheelchair)
930               
931                self.connect(self.pushButtonWheelchairReverse, \
932                                  QtCore.SIGNAL("pressed()"), \
933                                  self.driveWheelchairReverse)
934                self.connect(self.pushButtonWheelchairReverse, \
935                             QtCore.SIGNAL("released()"), \
936                             self.stopWheelchair)
937               
938                self.connect(self.pushButtonWheelchairLeft, \
939                                  QtCore.SIGNAL("pressed()"), \
940                                  self.driveWheelchairLeft)
941                self.connect(self.pushButtonWheelchairLeft, \
942                             QtCore.SIGNAL("released()"), \
943                             self.stopWheelchair)
944               
945                self.connect(self.pushButtonWheelchairRight, \
946                                  QtCore.SIGNAL("pressed()"), \
947                                  self.driveWheelchairRight)
948                self.connect(self.pushButtonWheelchairRight, \
949                             QtCore.SIGNAL("released()"), \
950                             self.stopWheelchair)
951               
952                self.connect(self.pushButtonWheelchairStop, \
953                                  QtCore.SIGNAL("pressed()"), \
954                                  self.stopWheelchair)
955               
956               
957               
958                # Control Panel Buttons
959                self.connect(self.pushButtonMessageOne, QtCore.SIGNAL("pressed()"), \
960                             self.sendMessageOne)
961               
962                self.connect(self.pushButtonMessageTwo, QtCore.SIGNAL("pressed()"), \
963                             self.sendMessageTwo)
964               
965                self.connect(self.pushButtonMessageThree, QtCore.SIGNAL("pressed()"), \
966                             self.sendMessageThree)
967               
968                self.connect(self.pushButtonMessageFour, QtCore.SIGNAL("pressed()"), \
969                             self.sendMessageFour)
970               
971                self.connect(self.pushButtonMessageFive, QtCore.SIGNAL("pressed()"), \
972                             self.sendMessageFive)
973               
974                self.connect(self.pushButtonMessageSix, QtCore.SIGNAL("pressed()"), \
975                             self.sendMessageSix)
976               
977               
978                self.connect(self.pushButtonThinkGearConnect, \
979                                  QtCore.SIGNAL("clicked()"), \
980                                  self.connectToThinkGearHost)
981               
982                self.connect(self.pushButtonSendFeedback, \
983                                  QtCore.SIGNAL("clicked()"), \
984                                  self.sendFeedback)
985               
986               
987                #shortcut = QtGui.QShortcut(self)
988                #shortcut.setKey(tr("Down"))
989                #self.connect(shortcut, QtCore.SIGNAL("pressed()"), self.driveReverse)
990               
991               
992                action = QtGui.QAction(self)
993                action.setShortcut(QtGui.QKeySequence("W"))
994                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
995                self.addAction(action)
996               
997                action = QtGui.QAction(self)
998                action.setShortcut(QtGui.QKeySequence("Up"))
999                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
1000                self.addAction(action)
1001               
1002               
1003                action = QtGui.QAction(self)
1004                action.setShortcut(QtGui.QKeySequence("Left"))
1005                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
1006                self.addAction(action)
1007               
1008                action = QtGui.QAction(self)
1009                action.setShortcut(QtGui.QKeySequence("A"))
1010                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
1011                self.addAction(action)
1012               
1013               
1014                action = QtGui.QAction(self)
1015                action.setShortcut(QtGui.QKeySequence("S"))
1016                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
1017                self.addAction(action)
1018               
1019                action = QtGui.QAction(self)
1020                action.setShortcut(QtGui.QKeySequence("Down"))
1021                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
1022                self.addAction(action)
1023               
1024               
1025                action = QtGui.QAction(self)
1026                action.setShortcut(QtGui.QKeySequence("D"))
1027                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
1028                self.addAction(action)
1029               
1030                action = QtGui.QAction(self)
1031                action.setShortcut(QtGui.QKeySequence("Right"))
1032                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
1033                self.addAction(action)
1034               
1035               
1036                action = QtGui.QAction(self)
1037                action.setShortcut(QtGui.QKeySequence("Z"))
1038                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeftReverse, QtCore.SLOT("animateClick()"))
1039                self.addAction(action)
1040               
1041               
1042                action = QtGui.QAction(self)
1043                action.setShortcut(QtGui.QKeySequence("C"))
1044                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRightReverse, QtCore.SLOT("animateClick()"))
1045                self.addAction(action)
1046               
1047               
1048               
1049                # RC Helicopter Buttons
1050               
1051                action = QtGui.QAction(self)
1052                action.setShortcut(QtGui.QKeySequence("Home"))
1053                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterHover, QtCore.SLOT("animateClick()"))
1054                self.addAction(action)
1055                action = QtGui.QAction(self)
1056                action.setShortcut(QtGui.QKeySequence("["))
1057                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterHover, QtCore.SLOT("animateClick()"))
1058                self.addAction(action)
1059               
1060                action = QtGui.QAction(self)
1061                action.setShortcut(QtGui.QKeySequence("PgUp"))
1062                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterFlyForward, QtCore.SLOT("animateClick()"))
1063                self.addAction(action)
1064                action = QtGui.QAction(self)
1065                action.setShortcut(QtGui.QKeySequence("]"))
1066                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterFlyForward, QtCore.SLOT("animateClick()"))
1067                self.addAction(action)
1068               
1069                action = QtGui.QAction(self)
1070                action.setShortcut(QtGui.QKeySequence("End"))
1071                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterLand, QtCore.SLOT("animateClick()"))
1072                self.addAction(action)
1073                action = QtGui.QAction(self)
1074                action.setShortcut(QtGui.QKeySequence("\\"))
1075                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterLand, QtCore.SLOT("animateClick()"))
1076                self.addAction(action)
1077               
1078               
1079               
1080                # Wheelchair Buttons
1081               
1082                action = QtGui.QAction(self)
1083                action.setShortcut(QtGui.QKeySequence("i"))
1084                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairForward, QtCore.SLOT("animateClick()"))
1085                self.addAction(action)
1086               
1087                action = QtGui.QAction(self)
1088                action.setShortcut(QtGui.QKeySequence("k"))
1089                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairReverse, QtCore.SLOT("animateClick()"))
1090                self.addAction(action)
1091                action = QtGui.QAction(self)
1092                action.setShortcut(QtGui.QKeySequence("m"))
1093                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairReverse, QtCore.SLOT("animateClick()"))
1094                self.addAction(action)
1095               
1096                action = QtGui.QAction(self)
1097                action.setShortcut(QtGui.QKeySequence("j"))
1098                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairLeft, QtCore.SLOT("animateClick()"))
1099                self.addAction(action)
1100               
1101                action = QtGui.QAction(self)
1102                action.setShortcut(QtGui.QKeySequence("l"))
1103                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairRight, QtCore.SLOT("animateClick()"))
1104                self.addAction(action)
1105               
1106                action = QtGui.QAction(self)
1107                action.setShortcut(QtGui.QKeySequence("Space"))
1108                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairStop, QtCore.SLOT("animateClick()"))
1109                self.addAction(action)
1110               
1111               
1112               
1113                # Control Panel Buttons
1114               
1115                action = QtGui.QAction(self)
1116                action.setShortcut(QtGui.QKeySequence("1"))
1117                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageOne, QtCore.SLOT("animateClick()"))
1118                self.addAction(action)
1119               
1120                action = QtGui.QAction(self)
1121                action.setShortcut(QtGui.QKeySequence("2"))
1122                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageTwo, QtCore.SLOT("animateClick()"))
1123                self.addAction(action)
1124               
1125                action = QtGui.QAction(self)
1126                action.setShortcut(QtGui.QKeySequence("3"))
1127                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageThree, QtCore.SLOT("animateClick()"))
1128                self.addAction(action)
1129               
1130                action = QtGui.QAction(self)
1131                action.setShortcut(QtGui.QKeySequence("4"))
1132                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFour, QtCore.SLOT("animateClick()"))
1133                self.addAction(action)
1134               
1135                action = QtGui.QAction(self)
1136                action.setShortcut(QtGui.QKeySequence("5"))
1137                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFive, QtCore.SLOT("animateClick()"))
1138                self.addAction(action)
1139               
1140                action = QtGui.QAction(self)
1141                action.setShortcut(QtGui.QKeySequence("6"))
1142                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageSix, QtCore.SLOT("animateClick()"))
1143                self.addAction(action)
1144               
1145               
1146                #self.pushButtonForward.setAutoRepeat(False)
1147                #self.pushButtonForward.setAutoRepeatDelay(0)
1148                #self.pushButtonForward.setAutoRepeatInterval(0)
1149       
1150       
1151        ##################################################################
1152       
1153        def searchForDevices(self):
1154               
1155                nxt_devices = []
1156                rc_helicopter_devices = []
1157                wheelchair_devices = []
1158               
1159                #if (sys.platform != 'win32'):
1160                if False: # temporarily disabled
1161                       
1162                        # Bluetooth module doesn't compile properly under Windows
1163                       
1164                        bluetooth_devices = []
1165                       
1166                        try:
1167                                bluetooth_devices = bluetooth.discover_devices( \
1168                                                       duration=5, \
1169                                                       flush_cache=True, \
1170                                                       lookup_names=False)
1171                        except:
1172                                #command = '%s con' % PATH_TO_HCITOOL
1173                                command = '%s scan' % PATH_TO_HCITOOL
1174                               
1175                                output = os.popen(command, 'r')
1176                               
1177                                for line in output.readlines():
1178                                        print line
1179                                        try:
1180                                                address = line.split(' ')[2]
1181                                        except:
1182                                                pass
1183                                        else:
1184                                                bluetooth_devices.append(address)
1185                       
1186                        for address in bluetooth_devices:
1187                                device_name = bluetooth.lookup_name(address)
1188                                if ((device_name == 'NXT') and \
1189                                    (address not in nxt_devices)):
1190                                        nxt_devices.append(address)
1191                       
1192                       
1193                        if self.DEBUG:
1194                                print "Bluetooth NXT devices found:",
1195                                print nxt_devices
1196               
1197               
1198                # List all serial devices
1199                serial_devices = self.enumerateSerialPorts()
1200               
1201                for serial_device in serial_devices:
1202                        #serial_device = self.fullPortName(serial_device)
1203                        nxt_devices.append(serial_device)
1204                        rc_helicopter_devices.append(serial_device)
1205                        wheelchair_devices.append(serial_device)
1206               
1207               
1208                # Configure combo boxes
1209                if nxt_devices == []:
1210                        nxt_devices.append('N/A')
1211               
1212                if rc_helicopter_devices == []:
1213                        rc_helicopter_devices.append('N/A')
1214               
1215                if wheelchair_devices == []:
1216                        wheelchair_devices.append('N/A')
1217               
1218               
1219                # Don't reset combo boxes if already connected
1220                if self.pushButtonNXTConnect.text != 'Disconnect':
1221                       
1222                        self.comboBoxNXTPortSelect.clear()
1223                       
1224                        #nxt_devices.reverse()
1225                        for nxt_device in nxt_devices:
1226                                self.comboBoxNXTPortSelect.addItem(nxt_device)
1227               
1228               
1229                if self.pushButtonHelicopterConnect.text != 'Disconnect':
1230                       
1231                        self.comboBoxHelicopterPortSelect.clear()
1232                       
1233                        #rc_helicopter_devices.reverse()
1234                        for rc_helicopter in rc_helicopter_devices:
1235                                self.comboBoxHelicopterPortSelect.addItem(rc_helicopter)
1236       
1237       
1238                if self.pushButtonWheelchairConnect.text != 'Disconnect':
1239                       
1240                        self.comboBoxWheelchairPortSelect.clear()
1241                       
1242                        #rc_helicopter_devices.reverse()
1243                        for wheelchair in wheelchair_devices:
1244                                self.comboBoxWheelchairPortSelect.addItem(wheelchair)
1245       
1246       
1247        ##################################################################
1248       
1249        def enumerateSerialPorts(self):
1250               
1251                """ Uses the Win32 registry to return an
1252                iterator of serial (COM) ports
1253                existing on this computer.
1254               
1255                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
1256                """
1257               
1258                serial_ports = []
1259               
1260                if (sys.platform == 'win32'):
1261                       
1262                        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
1263                        try:
1264                                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
1265                        except WindowsError:
1266                                #raise IterationError
1267                                return []
1268                                #pass
1269                       
1270                        for i in itertools.count():
1271                                try:
1272                                        val = winreg.EnumValue(key, i)
1273                                        #yield str(val[1])
1274                                        serial_ports.append( str(val[1]) )
1275                                except EnvironmentError:
1276                                        break
1277               
1278               
1279                else:
1280                       
1281                        if os.path.exists(DEVICE_PATH):
1282                                device_list = os.listdir(DEVICE_PATH)
1283                               
1284                                device_list.sort()
1285                       
1286                                for device in device_list:
1287                                        if device.startswith('ttyUSB'):
1288                                                serial_ports.append( DEVICE_PATH + '/' + device )
1289                                for device in device_list:
1290                                        if device.startswith('rfcomm'):
1291                                                serial_ports.append( DEVICE_PATH + '/' + device )
1292                                for device in device_list:
1293                                        if device.startswith('ttyACM'):
1294                                                serial_ports.append( DEVICE_PATH + '/' + device )
1295                                for device in device_list:
1296                                        if device.startswith('ttyS'):
1297                                                serial_ports.append( DEVICE_PATH + '/' + device )
1298               
1299               
1300                return(serial_ports)
1301       
1302       
1303        ##################################################################
1304       
1305        def fullPortName(self, portname):
1306               
1307                """ Given a port-name (of the form COM7,
1308                COM12, CNCA0, etc.) returns a full
1309                name suitable for opening with the
1310                Serial class.
1311                """
1312               
1313                m = re.match('^COM(\d+)$', portname)
1314                if m and int(m.group(1)) < 10:
1315                        return portname
1316               
1317                return '\\\\.\\' + portname
1318       
1319       
1320        ##################################################################
1321       
1322        # LEGO Mindstorms Controls
1323       
1324        def turnLeft(self):
1325                self.brainstormsClient.sendCommand('turn_left')
1326                self.drive_state = 'turn_left'
1327       
1328        def driveForward(self):
1329                #if self.DEBUG:
1330                        #print "driveForward"
1331                self.pushButtonForward.setDown(True)
1332                if (self.drive_state != 'drive_forward'):
1333                        self.updateNXTSpeed(new_speed=DEFAULT_NXT_POWER_LEVEL)
1334                self.brainstormsClient.sendCommand('drive_forward', power=self.current_speed)
1335                self.drive_state = 'drive_forward'
1336       
1337        def turnRight(self):
1338                self.brainstormsClient.sendCommand('turn_right')
1339                self.drive_state = 'turn_right'
1340       
1341        def turnLeftInReverse(self):
1342                self.brainstormsClient.sendCommand('turn_left_in_reverse')
1343                self.drive_state = 'turn_left_in_reverse'
1344       
1345        def driveReverse(self):
1346                self.brainstormsClient.sendCommand('drive_reverse')
1347                self.drive_state = 'drive_reverse'
1348       
1349        def turnRightInReverse(self):
1350                self.brainstormsClient.sendCommand('turn_right_in_reverse')
1351                self.drive_state = 'turn_right_in_reverse'
1352       
1353        def stopMotors(self):
1354                self.pushButtonForward.setDown(False)
1355                if (self.current_speed != 0):
1356                        self.updateNXTSpeed(new_speed=0)
1357                if self.brainstormsClient != None:
1358                        self.brainstormsClient.sendCommand('stop_motors')
1359                self.drive_state = 'stop_motors'
1360       
1361        def sendMessageOne(self):
1362                message = str(self.lineEditMessageOne.text())
1363                self.brainstormsClient.sendCommand('send_message_1')
1364       
1365        def sendMessageTwo(self):
1366                message = str(self.lineEditMessageTwo.text())
1367                self.brainstormsClient.sendCommand('send_message_2')
1368       
1369        def sendMessageThree(self):
1370                message = str(self.lineEditMessageThree.text())
1371                self.brainstormsClient.sendCommand('send_message_3')
1372       
1373        def sendMessageFour(self):
1374                message = str(self.lineEditMessageFour.text())
1375                self.brainstormsClient.sendCommand('send_message_4')
1376       
1377        def sendMessageFive(self):
1378                message = str(self.lineEditMessageFive.text())
1379                self.brainstormsClient.sendCommand('send_message_5')
1380       
1381        def sendMessageSix(self):
1382                message = str(self.lineEditMessageSix.text())
1383                self.brainstormsClient.sendCommand('send_message_6')
1384       
1385       
1386        ##################################################################
1387       
1388        def enableHelicopterHover(self):
1389               
1390                if self.pushButtonHelicopterFlyForward.isChecked():
1391                        self.pushButtonHelicopterFlyForward.setChecked(False)
1392                        self.disableHelicopterFlyForward()
1393               
1394                self.helicopter.hover(duration=None)
1395                self.current_helicopter_state = 'hover'
1396               
1397                self.disconnect(self.pushButtonHelicopterHover, \
1398                                                        QtCore.SIGNAL("clicked()"), \
1399                                                        self.enableHelicopterHover)
1400               
1401                self.connect(self.pushButtonHelicopterHover, \
1402                                  QtCore.SIGNAL("clicked()"), \
1403                                  self.disableHelicopterHover)
1404               
1405                #if self.pushButtonHelicopterFlyForward.isChecked():
1406                        #self.pushButtonHelicopterFlyForward.toggle()
1407                        ##self.disableHelicopterFlyForward()
1408       
1409       
1410        ##################################################################
1411       
1412        def disableHelicopterHover(self):
1413               
1414                self.helicopter.neutral()
1415                self.current_helicopter_state = 'neutral'
1416               
1417                self.disconnect(self.pushButtonHelicopterHover, \
1418                                                        QtCore.SIGNAL("clicked()"), \
1419                                                        self.disableHelicopterHover)
1420               
1421                self.connect(self.pushButtonHelicopterHover, \
1422                                  QtCore.SIGNAL("clicked()"), \
1423                                  self.enableHelicopterHover)
1424       
1425       
1426        ##################################################################
1427       
1428        def enableHelicopterFlyForward(self):
1429               
1430                if self.pushButtonHelicopterHover.isChecked():
1431                        self.pushButtonHelicopterHover.setChecked(False)
1432                        self.disableHelicopterHover()
1433               
1434                self.helicopter.fly_forward(duration=None)
1435                self.current_helicopter_state = 'fly_forward'
1436               
1437                self.disconnect(self.pushButtonHelicopterFlyForward, \
1438                                                        QtCore.SIGNAL("clicked()"), \
1439                                                        self.enableHelicopterFlyForward)
1440               
1441                self.connect(self.pushButtonHelicopterFlyForward, \
1442                                  QtCore.SIGNAL("clicked()"), \
1443                                  self.disableHelicopterFlyForward)
1444               
1445                #if self.pushButtonHelicopterHover.isChecked():
1446                        #self.pushButtonHelicopterHover.toggle()
1447                        ##self.disableHelicopterHover()
1448       
1449       
1450        ##################################################################
1451       
1452        def disableHelicopterFlyForward(self):
1453               
1454                self.helicopter.neutral()
1455                self.current_helicopter_state = 'neutral'
1456               
1457                self.disconnect(self.pushButtonHelicopterFlyForward, \
1458                                                        QtCore.SIGNAL("clicked()"), \
1459                                                        self.disableHelicopterFlyForward)
1460               
1461                self.connect(self.pushButtonHelicopterFlyForward, \
1462                                  QtCore.SIGNAL("clicked()"), \
1463                                  self.enableHelicopterFlyForward)
1464       
1465       
1466        ##################################################################
1467       
1468        def landHelicopter(self):
1469               
1470                self.helicopter.neutral()
1471                self.current_helicopter_state = 'neutral'
1472               
1473                if self.pushButtonHelicopterHover.isChecked():
1474                        self.pushButtonHelicopterHover.setChecked(False)
1475                        self.disableHelicopterHover()
1476                if self.pushButtonHelicopterFlyForward.isChecked():
1477                        self.pushButtonHelicopterFlyForward.setChecked(False)
1478                        self.disableHelicopterFlyForward()
1479       
1480       
1481        ##################################################################
1482       
1483        def driveWheelchairForward(self):
1484                #print "WheelchairForward"
1485                speed = self.dialWheelchairSpeed.value()
1486                self.wheelchair.sendCommand(speed, 'forward')
1487       
1488        def driveWheelchairReverse(self):
1489                print "WheelchairReverse"
1490                speed = self.dialWheelchairSpeed.value()
1491                self.wheelchair.sendCommand(speed, 'reverse')
1492       
1493        def driveWheelchairLeft(self):
1494                print "WheelchairLeft"
1495                speed = self.dialWheelchairSpeed.value()
1496                self.wheelchair.sendCommand(speed, 'left')
1497       
1498        def driveWheelchairRight(self):
1499                print "WheelchairRight"
1500                speed = self.dialWheelchairSpeed.value()
1501                self.wheelchair.sendCommand(speed, 'right')
1502       
1503        def stopWheelchair(self):
1504                print "stopWheelchair"
1505                speed = self.dialWheelchairSpeed.value()
1506                self.wheelchair.sendCommand(speed, 'stop')
1507       
1508       
1509        ##################################################################
1510       
1511        def updateNXTSpeed(self, new_speed=None):
1512               
1513                if new_speed == None:
1514               
1515                        concentration=self.progressBarConcentration.value()
1516                        relaxation=self.progressBarRelaxation.value()
1517                       
1518                        new_speed = self.calculateSpeed(concentration, relaxation)
1519               
1520               
1521                # Update GUI
1522                if self.pushButtonSpeedEnable.isChecked():
1523                        self.progressBarSpeed.setValue(new_speed)
1524               
1525               
1526                # If there is a change between the new and current speeds
1527                # and either the robot is currently driving forward
1528                # or the "speed control" button is enabled,
1529                # then send the updated speed to the robot
1530                if ((self.current_speed != new_speed) and \
1531                         ((self.drive_state == 'drive_forward') or \
1532                          (self.pushButtonSpeedEnable.isChecked()))):
1533                       
1534                        if (new_speed == 0):
1535                                self.current_speed = new_speed
1536                                self.stopMotors()
1537                        else:
1538                                if ((self.brainstormsClient != None) and \
1539                                    (self.pushButtonSpeedEnable.isChecked())):
1540                                        self.pushButtonForward.setDown(True)
1541                                        self.brainstormsClient.sendCommand('drive_forward', power=new_speed)
1542               
1543               
1544                self.current_speed = new_speed
1545       
1546       
1547        ##################################################################
1548       
1549        def updateHelicopterSpeed(self, new_speed=None):
1550               
1551                if new_speed == None:
1552               
1553                        concentration=self.progressBarHelicopterConcentration.value()
1554                        relaxation=self.progressBarHelicopterRelaxation.value()
1555                       
1556                        new_speed = self.calculateSpeed(concentration, relaxation)
1557               
1558               
1559                # Update GUI
1560                if self.pushButtonHelicopterSpeedEnable.isChecked():
1561                        self.progressBarHelicopterSpeed.setValue(new_speed)
1562                       
1563                        if ((new_speed > 0) and \
1564                            (self.current_helicopter_state == 'neutral') and \
1565                            (self.helicopter != None)):
1566                                self.enableHelicopterHover()
1567                       
1568                        elif ((new_speed == 0) and \
1569                              (self.current_helicopter_state != 'neutral') and \
1570                              (self.helicopter != None)):
1571                                self.landHelicopter()
1572               
1573               
1574                self.current_speed = new_speed
1575       
1576       
1577        ##################################################################
1578       
1579        def updateWheelchairSpeed(self, new_speed=None):
1580               
1581                if new_speed == None:
1582               
1583                        concentration=self.progressBarWheelchairConcentration.value()
1584                        relaxation=self.progressBarWheelchairRelaxation.value()
1585                       
1586                        new_speed = self.calculateSpeed(concentration, relaxation)
1587               
1588               
1589                # Update GUI
1590                if self.pushButtonWheelchairSpeedEnable.isChecked():
1591                        self.progressBarWheelchairSpeed.setValue(new_speed)
1592               
1593               
1594                self.current_speed = new_speed
1595       
1596       
1597        ##################################################################
1598       
1599        def calculateSpeed(self, concentration, relaxation):
1600               
1601                speed = 0
1602               
1603                thresholds = THINKGEAR_POWER_THRESHOLDS
1604               
1605                match = int(concentration)
1606               
1607                while ((match not in thresholds['concentration'].keys()) and \
1608                            (match >= 0)):
1609                        match -= 1
1610               
1611               
1612                if match in thresholds['concentration'].keys():
1613                        speed = thresholds['concentration'][match]
1614               
1615               
1616                match = int(relaxation)
1617               
1618                while ((match not in thresholds['relaxation'].keys()) and \
1619                            (match >= 0)):
1620                        match -= 1
1621               
1622                if match in thresholds['relaxation'].keys():
1623                        speed = speed + thresholds['relaxation'][match]
1624               
1625               
1626                # LEGO Mindstorms power settings cannot exceed 100
1627                # and don't drive well with levels less than 50
1628                if (speed > 100):
1629                        speed = 100
1630                elif (speed < 50):
1631                        speed = 0
1632               
1633               
1634                return(speed)
1635       
1636       
1637        ##################################################################
1638       
1639        def processPacketThinkGear(self, packet):
1640               
1641                if ('eSense' in packet.keys()):
1642                       
1643                        if ('attention' in packet['eSense'].keys()):
1644                                if self.pushButtonConcentrationEnable.isChecked():
1645                                        self.progressBarConcentration.setValue(packet['eSense']['attention'])
1646                                if self.pushButtonHelicopterConcentrationEnable.isChecked():
1647                                        self.progressBarHelicopterConcentration.setValue(packet['eSense']['attention'])
1648                                if self.pushButtonWheelchairConcentrationEnable.isChecked():
1649                                        self.progressBarWheelchairConcentration.setValue(packet['eSense']['attention'])
1650                       
1651                        if ('meditation' in packet['eSense'].keys()):
1652                                if self.pushButtonRelaxationEnable.isChecked():
1653                                        self.progressBarRelaxation.setValue(packet['eSense']['meditation'])
1654                                if self.pushButtonHelicopterRelaxationEnable.isChecked():
1655                                        self.progressBarHelicopterRelaxation.setValue(packet['eSense']['meditation'])
1656                                if self.pushButtonWheelchairRelaxationEnable.isChecked():
1657                                        self.progressBarWheelchairRelaxation.setValue(packet['eSense']['meditation'])
1658               
1659               
1660                self.updateNXTSpeed()
1661                self.updateHelicopterSpeed()
1662                self.updateWheelchairSpeed()
1663       
1664       
1665        ##################################################################
1666
1667        def sendFeedback(self):
1668               
1669                values = {}
1670
1671                values['name'] = str(self.lineEditFeedbackName.text())
1672                values['email'] = str(self.lineEditFeedbackEmail.text())
1673                values['comment'] = str(self.textEditFeedback.toPlainText())
1674               
1675                values['subject'] = '[brainstorms feedback]'
1676                values['capcha_contact'] = 'brainstorms'
1677               
1678               
1679                url_data = urllib.urlencode(values)
1680               
1681                try:
1682                        page = urllib.urlopen(BRAINSTORMS_FEEDBACK_URL, url_data)
1683                       
1684                        reply = QtGui.QMessageBox.information( \
1685                              self, \
1686                              'Feedback Sent', \
1687                              'Thank you for your feedback', \
1688                              'OK')
1689                       
1690                        self.lineEditFeedbackName.setText('')
1691                        self.lineEditFeedbackEmail.setText('')
1692                        self.textEditFeedback.setText('')
1693               
1694                except:
1695                        reply = QtGui.QMessageBox.information( \
1696                              self, \
1697                              'Feedback Sent', \
1698                              'We\'re sorry but there was an error submitting your feedback.\nPlease email contact@puzzlebox.info instead.', \
1699                              'OK')
1700       
1701       
1702        ##################################################################
1703       
1704        def closeEvent(self, event):
1705               
1706                quit_message = "Are you sure you want to exit the program?"
1707               
1708                reply = QtGui.QMessageBox.question( \
1709                           self, \
1710                          'Quit Puzzlebox Brainstorms', \
1711                           quit_message, \
1712                           QtGui.QMessageBox.Yes, \
1713                           QtGui.QMessageBox.No)
1714               
1715                if reply == QtGui.QMessageBox.Yes:
1716                       
1717                        if self.brainstormsClient != None:
1718                                self.stopMotors()
1719                                self.brainstormsClient.socket.flush()
1720                               
1721                                if self.brainstormsServer != None:
1722                                       
1723                                        if self.brainstormsServer.rc == None:
1724                                               
1725                                                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
1726                                                self.brainstormsServer.executeCommand( \
1727                                                        'stop_motors', \
1728                                                        bluetooth_device=bluetooth_device)
1729                                               
1730                                        else:
1731                                                self.brainstormsServer.rc.run('stop_motors')
1732                       
1733                       
1734                        event.accept()
1735               
1736                else:
1737                        event.ignore()
1738
1739
1740#####################################################################
1741# Functions
1742#####################################################################
1743
1744#####################################################################
1745# Main
1746#####################################################################
1747
1748if __name__ == '__main__':
1749       
1750        #log = puzzlebox_logger.puzzlebox_logger(logfile='client_interface')
1751        log = None
1752       
1753        app = QtGui.QApplication(sys.argv)
1754       
1755        window = puzzlebox_brainstorms_client_interface(log, DEBUG)
1756        window.show()
1757       
1758        sys.exit(app.exec_())
1759
Note: See TracBrowser for help on using the repository browser.