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

Last change on this file since 238 was 238, checked in by sc, 11 years ago

brainstorms/Puzzlebox/Brainstorms/Helicopter_Control.py:

  • more clean debugging output

brainstorms/Puzzlebox/Brainstorms/Interface.py:

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