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

Last change on this file since 259 was 259, checked in by sc, 10 years ago

trunk/synapse/Puzzlebox/Synapse/Interface.py:

  • Now supports configurable interface tab positioning

trunk/synapse/Puzzlebox/Synapse/Configuration.py:

  • Now supports configurable interface tab positioning

trunk/synapse/puzzlebox_synapse_configuration.ini:

  • Now supports configurable interface tab positioning

trunk/brainstorms/Puzzlebox/Brainstorms/Interface.py:

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