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

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

Brainstorms/Helicopter_Control.py:

  • sync_to_helicopter control added

Brainstorms/Interface?.py:

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