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

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

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

  • function name capitalization consistency fix

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

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