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

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

trunk/brainstorms/interface/puzzlebox_brainstorms_interface_design.ui:
trunk/brainstorms/Puzzlebox/Brainstorms/Interface_Design.py:

  • SVG image paths fixed

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

  • rc helicopters progress bars working
  • rc helicopter progress bars enable/disable working
  • control panel configuration settings working

trunk/brainstorms/Puzzlebox/Brainstorms/Configuration.py:
trunk/brainstorms/puzzlebox_brainstorms_configuration.ini:

  • motor port display order swapped
File size: 32.5 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.28
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
25
26if (sys.platform == 'win32'):
27        import _winreg as winreg
28        import itertools
29        import re
30        import serial
31else:
32        import bluetooth
33
34try:
35        import PySide as PyQt4
36        from PySide import QtCore, QtGui, QtNetwork
37except:
38        print "Using PyQt4 module"
39        from PyQt4 import QtCore, QtGui, QtNetwork
40else:
41        print "Using PySide module"
42
43#from PyQt4 import QtCore, QtGui, QtNetwork
44#from PySide import QtCore, QtGui, QtNetwork
45
46from Interface_Design import Ui_Form as Design
47
48import simplejson as json
49
50import Configuration as configuration
51import Client as brainstorms_client
52import Puzzlebox.Brainstorms.ThinkGear.Client as thinkgear_client
53#import puzzlebox_logger
54
55#####################################################################
56# Globals
57#####################################################################
58
59DEBUG = 1
60
61THINKGEAR_POWER_THRESHOLDS = configuration.THINKGEAR_POWER_THRESHOLDS
62
63BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
64
65NXT_BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
66
67DEFAULT_NXT_POWER_LEVEL = configuration.DEFAULT_NXT_POWER_LEVEL
68
69THINKGEAR_SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
70THINKGEAR_SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
71
72DEVICE_PATH = '/dev'
73PATH_TO_HCITOOL = '/usr/bin/hcitool'
74
75#####################################################################
76# Classes
77#####################################################################
78
79class puzzlebox_brainstorms_client_interface(QtGui.QWidget, Design):
80       
81        def __init__(self, log, server=None, DEBUG=DEBUG, parent = None):
82               
83                self.log = log
84                self.DEBUG = DEBUG
85               
86                QtGui.QWidget.__init__(self, parent)
87                self.setupUi(self)
88               
89                self.configureSettings()
90                self.connectWidgets()
91               
92                self.name = "Brainstorms Interface"
93               
94                self.brainstormsServer = server
95                self.brainstormsClient = None
96               
97                self.drive_state = 'stop_motors'
98                self.current_speed = 0
99       
100       
101        ##################################################################
102       
103        def configureSettings(self):
104               
105                # Brainstorms Interface
106               
107                icon = QtGui.QIcon()
108                icon.addPixmap(QtGui.QPixmap("images/puzzlebox.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
109                self.setWindowIcon(icon)
110               
111                self.pushButtonTurnLeft.setEnabled(False)
112                self.pushButtonForward.setEnabled(False)
113                self.pushButtonTurnRight.setEnabled(False)
114                self.pushButtonTurnLeftReverse.setEnabled(False)
115                self.pushButtonReverse.setEnabled(False)
116                self.pushButtonTurnRightReverse.setEnabled(False)
117               
118                self.pushButtonConcentrationEnable.setDown(True)
119                self.pushButtonRelaxationEnable.setDown(True)
120                self.pushButtonSpeedEnable.setDown(True)
121               
122               
123                # Search for available Serial and Bluetooth devices
124                self.searchForDevices()
125               
126               
127                # LEGO Mindstorms
128                self.textLabelNXTStatus.setText("Status: Disconnected")
129               
130                # Display communication port for LEGO Mindstorms NXT device
131                #self.lineEditNXTPort.setText(NXT_BLUETOOTH_DEVICE)
132                self.comboBoxNXTPortSelect.setEnabled(True)
133               
134               
135                # RC Helicopter
136                self.textLabelHelicopterStatus.setText("Status: Disconnected")
137               
138               
139                # EEG Headset
140               
141                # Display Host for ThinkGear Connect Socket Server
142                self.lineEditThinkGearHost.setText(THINKGEAR_SERVER_HOST)
143                #self.lineEditThinkGearHost.setEnabled(False)
144               
145                # Display Port for ThinkGear Connect Socket Server
146                self.lineEditThinkGearPort.setText('%i' % THINKGEAR_SERVER_PORT)
147                #self.lineEditThinkGearPort.setEnabled(False)
148               
149               
150                # Control Panel
151                self.lineEditLeftMotorPort.setText( \
152                   configuration.NXT_MOTOR_PORT_LEFT.upper() )
153                self.lineEditRightMotorPort.setText(   \
154                   configuration.NXT_MOTOR_PORT_RIGHT.upper() )
155                self.checkBoxMotorSpinReversed.setChecked( \
156                   configuration.NXT_MOTORS_MOUNTED_BACKWARDS)
157       
158       
159        ##################################################################
160       
161        def getMinimumThreshold(self, threshold):
162               
163                '''Return the minimum detection level which results
164                in a non-zero power setting'''
165               
166                minimum = 100
167               
168                threshold_keys = threshold.keys()
169                threshold_keys.sort()
170                threshold_keys.reverse()
171               
172                for key in threshold_keys:
173                       
174                        if ((threshold[key] < minimum) and \
175                                 (threshold[key] > 0)):
176                                minimum = key
177               
178               
179                return(minimum)
180       
181       
182        ##################################################################
183       
184        def configureNetworkBrainstorms(self):
185               
186                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
187               
188                self.brainstormsClient = \
189                   brainstorms_client.puzzlebox_brainstorms_network_client( \
190                           self.log, \
191                           bluetooth_device=bluetooth_device, \
192                           parent=self)
193               
194                self.brainstormsClient.sendCommand('connect', \
195                                                   bluetooth_device=bluetooth_device)
196       
197       
198        ##################################################################
199       
200        def connectToBrainstormsServer(self):
201               
202                # Prevent attempting to connect to a device which no longer exists
203                if (sys.platform != 'win32'):
204                        device = str(self.comboBoxNXTPortSelect.currentText())
205                        if ((not device.startswith(DEVICE_PATH)) or \
206                            (not os.path.exists(device))):
207                                self.searchForDevices()
208                                return
209               
210               
211                if self.DEBUG:
212                        print "<---- [%s] Connecting to Brainstorms Server" % self.name
213               
214                self.configureNetworkBrainstorms()
215               
216                #if (self.brainstormsClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
217                        #QtGui.QMessageBox.information(self, \
218                                                                #self.brainstormsClient.socket.name, \
219                                           #"Failed to connect to Brainstorms socket server")
220               
221                #else:
222                self.disconnect(self.pushButtonNXTConnect, \
223                                                        QtCore.SIGNAL("clicked()"), \
224                                                        self.connectToBrainstormsServer)
225               
226                self.connect(self.pushButtonNXTConnect, \
227                                                        QtCore.SIGNAL("clicked()"), \
228                                                        self.disconnectFromBrainstormsServer)
229               
230                self.textLabelNXTStatus.setText("Status: Connected")
231                self.pushButtonNXTConnect.setText('Disconnect')
232               
233                self.comboBoxNXTPortSelect.setEnabled(False)
234                self.pushButtonNXTSearch.setEnabled(False)
235               
236                self.pushButtonTurnLeft.setEnabled(True)
237                self.pushButtonForward.setEnabled(True)
238                self.pushButtonTurnRight.setEnabled(True)
239                self.pushButtonTurnLeftReverse.setEnabled(True)
240                self.pushButtonReverse.setEnabled(True)
241                self.pushButtonTurnRightReverse.setEnabled(True)
242               
243                self.pushButtonNXTMessageOne.setEnabled(True)
244                self.pushButtonNXTMessageTwo.setEnabled(True)
245                self.pushButtonNXTMessageThree.setEnabled(True)
246                self.pushButtonNXTMessageFour.setEnabled(True)
247                self.pushButtonNXTMessageFive.setEnabled(True)
248                self.pushButtonNXTMessageSix.setEnabled(True)
249               
250                self.pushButtonConcentrationEnable.setEnabled(True)
251                self.pushButtonRelaxationEnable.setEnabled(True)
252                self.pushButtonSpeedEnable.setEnabled(True)
253               
254                self.pushButtonMessageOne.setEnabled(True)
255                self.pushButtonMessageTwo.setEnabled(True)
256                self.pushButtonMessageThree.setEnabled(True)
257                self.pushButtonMessageFour.setEnabled(True)
258                self.pushButtonMessageFive.setEnabled(True)
259                self.pushButtonMessageSix.setEnabled(True)
260               
261                self.pushButtonHelicopterConcentrationEnable.setEnabled(True)
262                self.pushButtonHelicopterRelaxationEnable.setEnabled(True)
263                self.pushButtonHelicopterSpeedEnable.setEnabled(True)
264       
265       
266        ##################################################################
267       
268        def disconnectFromBrainstormsServer(self):
269               
270                if self.DEBUG:
271                        print "- - [%s] Disconnecting from Brainstorms Server" % self.name
272               
273                self.stopMotors()
274               
275                # Ensure the stopMotors command has been received by the server
276                # so the NXT robot will stop before the client disconnects
277                self.brainstormsClient.socket.flush()
278               
279                self.brainstormsClient.socket.disconnectFromHost()
280               
281                self.disconnect(self.pushButtonNXTConnect, \
282                                  QtCore.SIGNAL("clicked()"), \
283                                  self.disconnectFromBrainstormsServer)
284               
285                self.connect(self.pushButtonNXTConnect, \
286                                  QtCore.SIGNAL("clicked()"), \
287                                  self.connectToBrainstormsServer)
288               
289                self.textLabelNXTStatus.setText("Status: Disconnected")
290                self.pushButtonNXTConnect.setText('Connect')
291               
292                self.comboBoxNXTPortSelect.setEnabled(True)
293                self.pushButtonNXTSearch.setEnabled(True)
294               
295                self.pushButtonTurnLeft.setEnabled(False)
296                self.pushButtonForward.setEnabled(False)
297                self.pushButtonTurnRight.setEnabled(False)
298                self.pushButtonTurnLeftReverse.setEnabled(False)
299                self.pushButtonReverse.setEnabled(False)
300                self.pushButtonTurnRightReverse.setEnabled(False)
301               
302                self.pushButtonNXTMessageOne.setEnabled(False)
303                self.pushButtonNXTMessageTwo.setEnabled(False)
304                self.pushButtonNXTMessageThree.setEnabled(False)
305                self.pushButtonNXTMessageFour.setEnabled(False)
306                self.pushButtonNXTMessageFive.setEnabled(False)
307                self.pushButtonNXTMessageSix.setEnabled(False)
308               
309                self.pushButtonConcentrationEnable.setEnabled(False)
310                self.pushButtonRelaxationEnable.setEnabled(False)
311                self.pushButtonSpeedEnable.setEnabled(False)
312               
313                self.pushButtonMessageOne.setEnabled(False)
314                self.pushButtonMessageTwo.setEnabled(False)
315                self.pushButtonMessageThree.setEnabled(False)
316                self.pushButtonMessageFour.setEnabled(False)
317                self.pushButtonMessageFive.setEnabled(False)
318                self.pushButtonMessageSix.setEnabled(False)
319               
320                self.brainstormsClient = None
321               
322                self.searchForDevices()
323       
324       
325        ##################################################################
326       
327        def connectToThinkGearHost(self):
328               
329                if self.DEBUG:
330                        print "Connecting to ThinkGear Host"
331               
332                server_host = str(self.lineEditThinkGearHost.text())
333                server_port = int(self.lineEditThinkGearPort.text())
334               
335                self.thinkgearClient = \
336                   thinkgear_client.puzzlebox_brainstorms_network_client_thinkgear( \
337                           self.log, \
338                           server_host=server_host, \
339                           server_port=server_port, \
340                           DEBUG=0, \
341                           parent=self)
342               
343                if (self.thinkgearClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
344                        QtGui.QMessageBox.information(self, \
345                                                                self.thinkgearClient.socket.name, \
346                                           "Failed to connect to ThinkGear socket server")
347               
348                else:
349                        self.disconnect(self.pushButtonThinkGearConnect, \
350                                                         QtCore.SIGNAL("clicked()"), \
351                                                         self.connectToThinkGearHost)
352                       
353                        self.connect(self.pushButtonThinkGearConnect, \
354                                                         QtCore.SIGNAL("clicked()"), \
355                                                         self.disconnectFromThinkGearHost)
356                       
357                        self.pushButtonThinkGearConnect.setText('Disconnect')
358                       
359                        self.comboBoxEEGHeadsetModel.setEnabled(False)
360                        self.comboBoxEEGSource.setEnabled(False)
361                        self.lineEditThinkGearHost.setEnabled(False)
362                        self.lineEditThinkGearPort.setEnabled(False)
363       
364       
365        ##################################################################
366       
367        def disconnectFromThinkGearHost(self):
368               
369                if self.DEBUG:
370                        print "Disconnecting from ThinkGear Host"
371               
372                self.thinkgearClient.disconnectFromHost()
373               
374                self.disconnect(self.pushButtonThinkGearConnect, \
375                                  QtCore.SIGNAL("clicked()"), \
376                                  self.disconnectFromThinkGearHost)
377               
378                self.connect(self.pushButtonThinkGearConnect, \
379                                  QtCore.SIGNAL("clicked()"), \
380                                  self.connectToThinkGearHost)
381               
382                self.pushButtonForward.emit(QtCore.SIGNAL("released()"))
383               
384                self.pushButtonThinkGearConnect.setText('Connect')
385               
386                self.comboBoxEEGHeadsetModel.setEnabled(True)
387                self.comboBoxEEGSource.setEnabled(True)
388                self.lineEditThinkGearHost.setEnabled(True)
389                self.lineEditThinkGearPort.setEnabled(True)
390               
391                self.progressBarConcentration.setValue(0)
392                self.progressBarRelaxation.setValue(0)
393                self.progressBarSpeed.setValue(0)
394       
395                self.progressBarHelicopterConcentration.setValue(0)
396                self.progressBarHelicopterRelaxation.setValue(0)
397                self.progressBarHelicopterSpeed.setValue(0)
398       
399       
400        ##################################################################
401       
402        def updateConcentrationButton(self):
403               
404                if self.pushButtonConcentrationEnable.isChecked():
405                       
406                        self.pushButtonConcentrationEnable.setText('Enabled')
407               
408                else:
409                       
410                        self.pushButtonConcentrationEnable.setText('Disabled')
411                        self.progressBarConcentration.setValue(0)
412               
413               
414                self.updateSpeed()
415       
416       
417        ##################################################################
418       
419        def updateRelaxationButton(self):
420               
421                if self.pushButtonRelaxationEnable.isChecked():
422               
423                        self.pushButtonRelaxationEnable.setText('Enabled')
424               
425                else:
426                       
427                        self.pushButtonRelaxationEnable.setText('Disabled')
428                        self.progressBarRelaxation.setValue(0)
429               
430               
431                self.updateNXTSpeed()
432       
433       
434        ##################################################################
435       
436        def updateSpeedButton(self):
437               
438                if self.pushButtonSpeedEnable.isChecked():
439               
440                        self.pushButtonSpeedEnable.setText('Enabled')
441                        self.updateSpeed()
442               
443                else:
444                       
445                        self.pushButtonSpeedEnable.setText('Disabled')
446                        self.progressBarSpeed.setValue(0)
447                        self.stopMotors()
448       
449       
450        ##################################################################
451       
452        def updateHelicopterConcentrationButton(self):
453               
454                if self.pushButtonHelicopterConcentrationEnable.isChecked():
455                       
456                        self.pushButtonHelicopterConcentrationEnable.setText('Enabled')
457               
458                else:
459                       
460                        self.pushButtonHelicopterConcentrationEnable.setText('Disabled')
461                        self.progressBarHelicopterConcentration.setValue(0)
462               
463               
464                self.updateHelicopterSpeed()
465       
466       
467        ##################################################################
468       
469        def updateHelicopterRelaxationButton(self):
470               
471                if self.pushButtonHelicopterRelaxationEnable.isChecked():
472               
473                        self.pushButtonHelicopterRelaxationEnable.setText('Enabled')
474               
475                else:
476                       
477                        self.pushButtonHelicopterRelaxationEnable.setText('Disabled')
478                        self.progressBarHelicopterRelaxation.setValue(0)
479               
480               
481                self.updateHelicopterSpeed()
482       
483       
484        ##################################################################
485       
486        def updateHelicopterSpeedButton(self):
487               
488                if self.pushButtonHelicopterSpeedEnable.isChecked():
489               
490                        self.pushButtonHelicopterSpeedEnable.setText('Enabled')
491                        self.updateHelicopterSpeed()
492               
493                else:
494                       
495                        self.pushButtonHelicopterSpeedEnable.setText('Disabled')
496                        self.progressBarHelicopterSpeed.setValue(0)
497                        self.stopMotors()
498       
499       
500        ##################################################################
501       
502        def connectWidgets(self):
503               
504                # LEGO Mindstorms Buttons
505                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("pressed()"), \
506                             self.turnLeft)
507                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("released()"), \
508                             self.stopMotors)
509               
510                self.connect(self.pushButtonForward, QtCore.SIGNAL("pressed()"), \
511                             self.driveForward)
512                self.connect(self.pushButtonForward, QtCore.SIGNAL("released()"), \
513                             self.stopMotors)
514               
515                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("pressed()"), \
516                             self.turnRight)
517                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("released()"), \
518                             self.stopMotors)
519               
520                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("pressed()"), \
521                             self.turnLeftInReverse)
522                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("released()"), \
523                             self.stopMotors)
524               
525                self.connect(self.pushButtonReverse, QtCore.SIGNAL("pressed()"), \
526                             self.driveReverse)
527                self.connect(self.pushButtonReverse, QtCore.SIGNAL("released()"), \
528                             self.stopMotors)
529               
530                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("pressed()"), \
531                             self.turnRightInReverse)
532                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("released()"), \
533                             self.stopMotors)
534               
535               
536                self.connect(self.pushButtonNXTSearch, \
537                                  QtCore.SIGNAL("clicked()"), \
538                                  self.searchForDevices)
539               
540                self.connect(self.pushButtonNXTConnect, \
541                                  QtCore.SIGNAL("clicked()"), \
542                                  self.connectToBrainstormsServer)
543               
544               
545                self.connect(self.pushButtonConcentrationEnable, \
546                                  QtCore.SIGNAL("clicked()"), \
547                                  self.updateConcentrationButton)
548               
549                self.connect(self.pushButtonRelaxationEnable, \
550                                  QtCore.SIGNAL("clicked()"), \
551                                  self.updateRelaxationButton)
552               
553                self.connect(self.pushButtonSpeedEnable, \
554                                  QtCore.SIGNAL("clicked()"), \
555                                  self.updateSpeedButton)
556               
557               
558                self.connect(self.pushButtonNXTMessageOne, QtCore.SIGNAL("pressed()"), \
559                             self.sendMessageOne)
560               
561                self.connect(self.pushButtonNXTMessageTwo, QtCore.SIGNAL("pressed()"), \
562                             self.sendMessageTwo)
563               
564                self.connect(self.pushButtonNXTMessageThree, QtCore.SIGNAL("pressed()"), \
565                             self.sendMessageThree)
566               
567                self.connect(self.pushButtonNXTMessageFour, QtCore.SIGNAL("pressed()"), \
568                             self.sendMessageFour)
569               
570                self.connect(self.pushButtonNXTMessageFive, QtCore.SIGNAL("pressed()"), \
571                             self.sendMessageFive)
572               
573                self.connect(self.pushButtonNXTMessageSix, QtCore.SIGNAL("pressed()"), \
574                             self.sendMessageSix)
575               
576               
577               
578                # RC Helicopter Buttons
579                self.connect(self.pushButtonHelicopterSearch, \
580                                  QtCore.SIGNAL("clicked()"), \
581                                  self.searchForDevices)
582               
583                #self.connect(self.pushButtonHelicopterConnect, \
584                                  #QtCore.SIGNAL("clicked()"), \
585                                  #self.connectToHelicopter)
586               
587               
588                self.connect(self.pushButtonHelicopterConcentrationEnable, \
589                                  QtCore.SIGNAL("clicked()"), \
590                                  self.updateHelicopterConcentrationButton)
591               
592                self.connect(self.pushButtonHelicopterRelaxationEnable, \
593                                  QtCore.SIGNAL("clicked()"), \
594                                  self.updateHelicopterRelaxationButton)
595               
596                self.connect(self.pushButtonHelicopterSpeedEnable, \
597                                  QtCore.SIGNAL("clicked()"), \
598                                  self.updateHelicopterSpeedButton)
599               
600               
601               
602                # Control Panel Buttons
603                self.connect(self.pushButtonMessageOne, QtCore.SIGNAL("pressed()"), \
604                             self.sendMessageOne)
605               
606                self.connect(self.pushButtonMessageTwo, QtCore.SIGNAL("pressed()"), \
607                             self.sendMessageTwo)
608               
609                self.connect(self.pushButtonMessageThree, QtCore.SIGNAL("pressed()"), \
610                             self.sendMessageThree)
611               
612                self.connect(self.pushButtonMessageFour, QtCore.SIGNAL("pressed()"), \
613                             self.sendMessageFour)
614               
615                self.connect(self.pushButtonMessageFive, QtCore.SIGNAL("pressed()"), \
616                             self.sendMessageFive)
617               
618                self.connect(self.pushButtonMessageSix, QtCore.SIGNAL("pressed()"), \
619                             self.sendMessageSix)
620               
621               
622                self.connect(self.pushButtonThinkGearConnect, \
623                                  QtCore.SIGNAL("clicked()"), \
624                                  self.connectToThinkGearHost)
625               
626               
627                #shortcut = QtGui.QShortcut(self)
628                #shortcut.setKey(tr("Down"))
629                #self.connect(shortcut, QtCore.SIGNAL("pressed()"), self.driveReverse)
630               
631               
632                action = QtGui.QAction(self)
633                action.setShortcut(QtGui.QKeySequence("W"))
634                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
635                self.addAction(action)
636               
637                action = QtGui.QAction(self)
638                action.setShortcut(QtGui.QKeySequence("Up"))
639                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
640                self.addAction(action)
641               
642               
643                action = QtGui.QAction(self)
644                action.setShortcut(QtGui.QKeySequence("Left"))
645                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
646                self.addAction(action)
647               
648                action = QtGui.QAction(self)
649                action.setShortcut(QtGui.QKeySequence("A"))
650                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
651                self.addAction(action)
652               
653               
654                action = QtGui.QAction(self)
655                action.setShortcut(QtGui.QKeySequence("S"))
656                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
657                self.addAction(action)
658               
659                action = QtGui.QAction(self)
660                action.setShortcut(QtGui.QKeySequence("Down"))
661                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
662                self.addAction(action)
663               
664               
665                action = QtGui.QAction(self)
666                action.setShortcut(QtGui.QKeySequence("D"))
667                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
668                self.addAction(action)
669               
670                action = QtGui.QAction(self)
671                action.setShortcut(QtGui.QKeySequence("Right"))
672                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
673                self.addAction(action)
674               
675               
676                action = QtGui.QAction(self)
677                action.setShortcut(QtGui.QKeySequence("Z"))
678                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeftReverse, QtCore.SLOT("animateClick()"))
679                self.addAction(action)
680               
681               
682                action = QtGui.QAction(self)
683                action.setShortcut(QtGui.QKeySequence("C"))
684                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRightReverse, QtCore.SLOT("animateClick()"))
685                self.addAction(action)
686               
687               
688                # Control Panel Buttons
689               
690                action = QtGui.QAction(self)
691                action.setShortcut(QtGui.QKeySequence("1"))
692                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageOne, QtCore.SLOT("animateClick()"))
693                self.addAction(action)
694               
695                action = QtGui.QAction(self)
696                action.setShortcut(QtGui.QKeySequence("2"))
697                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageTwo, QtCore.SLOT("animateClick()"))
698                self.addAction(action)
699               
700                action = QtGui.QAction(self)
701                action.setShortcut(QtGui.QKeySequence("3"))
702                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageThree, QtCore.SLOT("animateClick()"))
703                self.addAction(action)
704               
705                action = QtGui.QAction(self)
706                action.setShortcut(QtGui.QKeySequence("4"))
707                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFour, QtCore.SLOT("animateClick()"))
708                self.addAction(action)
709               
710                action = QtGui.QAction(self)
711                action.setShortcut(QtGui.QKeySequence("5"))
712                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFive, QtCore.SLOT("animateClick()"))
713                self.addAction(action)
714               
715                action = QtGui.QAction(self)
716                action.setShortcut(QtGui.QKeySequence("6"))
717                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageSix, QtCore.SLOT("animateClick()"))
718                self.addAction(action)
719               
720               
721                #self.pushButtonForward.setAutoRepeat(False)
722                #self.pushButtonForward.setAutoRepeatDelay(0)
723                #self.pushButtonForward.setAutoRepeatInterval(0)
724       
725       
726        ##################################################################
727       
728        def searchForDevices(self):
729               
730                nxt_devices = []
731                rc_helicopter_devices = []
732               
733                #if (sys.platform != 'win32'):
734                if False: # temporarily disabled
735                       
736                        # Bluetooth module doesn't compile properly under Windows
737                       
738                        bluetooth_devices = []
739                       
740                        try:
741                                bluetooth_devices = bluetooth.discover_devices( \
742                                                       duration=5, \
743                                                       flush_cache=True, \
744                                                       lookup_names=False)
745                        except:
746                                #command = '%s con' % PATH_TO_HCITOOL
747                                command = '%s scan' % PATH_TO_HCITOOL
748                               
749                                output = os.popen(command, 'r')
750                               
751                                for line in output.readlines():
752                                        print line
753                                        try:
754                                                address = line.split(' ')[2]
755                                        except:
756                                                pass
757                                        else:
758                                                bluetooth_devices.append(address)
759                       
760                        for address in bluetooth_devices:
761                                device_name = bluetooth.lookup_name(address)
762                                if ((device_name == 'NXT') and \
763                                    (address not in nxt_devices)):
764                                        nxt_devices.append(address)
765                       
766                       
767                        if self.DEBUG:
768                                print "Bluetooth NXT devices found:",
769                                print nxt_devices
770               
771               
772                # List all serial devices
773                serial_devices = self.enumerateSerialPorts()
774               
775                for serial_device in serial_devices:
776                        #serial_device = self.fullPortName(serial_device)
777                        nxt_devices.append(serial_device)
778                        rc_helicopter_devices.append(serial_device)
779               
780               
781                # Configure combo boxes
782                if nxt_devices == []:
783                        nxt_devices.append('N/A')
784               
785                if rc_helicopter_devices == []:
786                        rc_helicopter_devices.append('N/A')
787               
788               
789                # Don't reset combo boxes if already connected
790                if self.pushButtonNXTConnect.text != 'Disconnect':
791                       
792                        self.comboBoxNXTPortSelect.clear()
793                       
794                        #nxt_devices.reverse()
795                        for nxt_device in nxt_devices:
796                                self.comboBoxNXTPortSelect.addItem(nxt_device)
797               
798               
799                if self.pushButtonHelicopterConnect.text != 'Disconnect':
800                       
801                        self.comboBoxHelicopterPortSelect.clear()
802                       
803                        #rc_helicopter_devices.reverse()
804                        for rc_helicopter in rc_helicopter_devices:
805                                self.comboBoxHelicopterPortSelect.addItem(rc_helicopter)
806       
807       
808        ##################################################################
809       
810        def enumerateSerialPorts(self):
811               
812                """ Uses the Win32 registry to return an
813                iterator of serial (COM) ports
814                existing on this computer.
815               
816                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
817                """
818               
819                serial_ports = []
820               
821                if (sys.platform == 'win32'):
822                       
823                        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
824                        try:
825                                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
826                        except WindowsError:
827                                #raise IterationError
828                                #return
829                                pass
830                       
831                        for i in itertools.count():
832                                try:
833                                        val = winreg.EnumValue(key, i)
834                                        #yield str(val[1])
835                                        serial_ports.append( str(val[1]) )
836                                except EnvironmentError:
837                                        break
838               
839               
840                else:
841                       
842                        if os.path.exists(DEVICE_PATH):
843                                device_list = os.listdir(DEVICE_PATH)
844                               
845                                device_list.sort()
846                       
847                                for device in device_list:
848                                        if device.startswith('ttyUSB'):
849                                                serial_ports.append( DEVICE_PATH + '/' + device )
850                                        if device.startswith('rfcomm'):
851                                                serial_ports.append( DEVICE_PATH + '/' + device )
852                                        if device.startswith('ttyACM'):
853                                                serial_ports.append( DEVICE_PATH + '/' + device )
854                                        if device.startswith('ttyS'):
855                                                serial_ports.append( DEVICE_PATH + '/' + device )
856               
857               
858                return(serial_ports)
859       
860       
861        ##################################################################
862       
863        def fullPortName(self, portname):
864               
865                """ Given a port-name (of the form COM7,
866                COM12, CNCA0, etc.) returns a full
867                name suitable for opening with the
868                Serial class.
869                """
870               
871                m = re.match('^COM(\d+)$', portname)
872                if m and int(m.group(1)) < 10:
873                        return portname
874               
875                return '\\\\.\\' + portname
876       
877       
878        ##################################################################
879       
880        def turnLeft(self):
881                self.brainstormsClient.sendCommand('turn_left')
882                self.drive_state = 'turn_left'
883       
884        def driveForward(self):
885                #if self.DEBUG:
886                        #print "driveForward"
887                self.pushButtonForward.setDown(True)
888                if (self.drive_state != 'drive_forward'):
889                        self.updateNXTSpeed(new_speed=DEFAULT_NXT_POWER_LEVEL)
890                self.brainstormsClient.sendCommand('drive_forward', power=self.current_speed)
891                self.drive_state = 'drive_forward'
892       
893        def turnRight(self):
894                self.brainstormsClient.sendCommand('turn_right')
895                self.drive_state = 'turn_right'
896       
897        def turnLeftInReverse(self):
898                self.brainstormsClient.sendCommand('turn_left_in_reverse')
899                self.drive_state = 'turn_left_in_reverse'
900       
901        def driveReverse(self):
902                self.brainstormsClient.sendCommand('drive_reverse')
903                self.drive_state = 'drive_reverse'
904       
905        def turnRightInReverse(self):
906                self.brainstormsClient.sendCommand('turn_right_in_reverse')
907                self.drive_state = 'turn_right_in_reverse'
908       
909        def stopMotors(self):
910                self.pushButtonForward.setDown(False)
911                if (self.current_speed != 0):
912                        self.updateNXTSpeed(new_speed=0)
913                if self.brainstormsClient != None:
914                        self.brainstormsClient.sendCommand('stop_motors')
915                self.drive_state = 'stop_motors'
916       
917        def sendMessageOne(self):
918                message = str(self.lineEditMessageOne.text())
919                self.brainstormsClient.sendCommand('send_message_1')
920       
921        def sendMessageTwo(self):
922                message = str(self.lineEditMessageTwo.text())
923                self.brainstormsClient.sendCommand('send_message_2')
924       
925        def sendMessageThree(self):
926                message = str(self.lineEditMessageThree.text())
927                self.brainstormsClient.sendCommand('send_message_3')
928       
929        def sendMessageFour(self):
930                message = str(self.lineEditMessageFour.text())
931                self.brainstormsClient.sendCommand('send_message_4')
932       
933        def sendMessageFive(self):
934                message = str(self.lineEditMessageFive.text())
935                self.brainstormsClient.sendCommand('send_message_5')
936       
937        def sendMessageSix(self):
938                message = str(self.lineEditMessageSix.text())
939                self.brainstormsClient.sendCommand('send_message_6')
940       
941       
942        ##################################################################
943       
944        def updateNXTSpeed(self, new_speed=None):
945               
946                if new_speed == None:
947               
948                        concentration=self.progressBarConcentration.value()
949                        relaxation=self.progressBarRelaxation.value()
950                       
951                        new_speed = self.calculateSpeed(concentration, relaxation)
952               
953               
954                # Update GUI
955                if self.pushButtonSpeedEnable.isChecked():
956                        self.progressBarSpeed.setValue(new_speed)
957               
958               
959                # If there is a change between the new and current speeds
960                # and either the robot is currently driving forward
961                # or the "speed control" button is enabled,
962                # then send the updated speed to the robot
963                if ((self.current_speed != new_speed) and \
964                         ((self.drive_state == 'drive_forward') or \
965                          (self.pushButtonSpeedEnable.isChecked()))):
966                       
967                        if (new_speed == 0):
968                                self.current_speed = new_speed
969                                self.stopMotors()
970                        else:
971                                if ((self.brainstormsClient != None) and \
972                                    (self.pushButtonSpeedEnable.isChecked())):
973                                        self.pushButtonForward.setDown(True)
974                                        self.brainstormsClient.sendCommand('drive_forward', power=new_speed)
975               
976               
977                self.current_speed = new_speed
978       
979       
980        ##################################################################
981       
982        def updateHelicopterSpeed(self, new_speed=None):
983               
984                if new_speed == None:
985               
986                        concentration=self.progressBarHelicopterConcentration.value()
987                        relaxation=self.progressBarHelicopterRelaxation.value()
988                       
989                        new_speed = self.calculateSpeed(concentration, relaxation)
990               
991               
992                # Update GUI
993                if self.pushButtonHelicopterSpeedEnable.isChecked():
994                        self.progressBarHelicopterSpeed.setValue(new_speed)
995               
996               
997                self.current_speed = new_speed
998       
999       
1000        ##################################################################
1001       
1002        def calculateSpeed(self, concentration, relaxation):
1003               
1004                speed = 0
1005               
1006                thresholds = THINKGEAR_POWER_THRESHOLDS
1007               
1008                match = int(concentration)
1009               
1010                while ((match not in thresholds['concentration'].keys()) and \
1011                            (match >= 0)):
1012                        match -= 1
1013               
1014               
1015                if match in thresholds['concentration'].keys():
1016                        speed = thresholds['concentration'][match]
1017               
1018               
1019                match = int(relaxation)
1020               
1021                while ((match not in thresholds['relaxation'].keys()) and \
1022                            (match >= 0)):
1023                        match -= 1
1024               
1025                if match in thresholds['relaxation'].keys():
1026                        speed = speed + thresholds['relaxation'][match]
1027               
1028               
1029                # LEGO Mindstorms power settings cannot exceed 100
1030                # and don't drive well with levels less than 50
1031                if (speed > 100):
1032                        speed = 100
1033                elif (speed < 50):
1034                        speed = 0
1035               
1036               
1037                return(speed)
1038       
1039       
1040        ##################################################################
1041       
1042        def processPacketThinkGear(self, packet):
1043               
1044                if ('eSense' in packet.keys()):
1045                       
1046                        if ('attention' in packet['eSense'].keys()):
1047                                if self.pushButtonConcentrationEnable.isChecked():
1048                                        self.progressBarConcentration.setValue(packet['eSense']['attention'])
1049                                if self.pushButtonHelicopterConcentrationEnable.isChecked():
1050                                        self.progressBarHelicopterConcentration.setValue(packet['eSense']['attention'])
1051                       
1052                        if ('meditation' in packet['eSense'].keys()):
1053                                if self.pushButtonRelaxationEnable.isChecked():
1054                                        self.progressBarRelaxation.setValue(packet['eSense']['meditation'])
1055                                if self.pushButtonHelicopterRelaxationEnable.isChecked():
1056                                        self.progressBarHelicopterRelaxation.setValue(packet['eSense']['meditation'])
1057               
1058               
1059                self.updateNXTSpeed()
1060                self.updateHelicopterSpeed()
1061       
1062       
1063        ##################################################################
1064       
1065        def closeEvent(self, event):
1066               
1067                quit_message = "Are you sure you want to exit the program?"
1068               
1069                reply = QtGui.QMessageBox.question( \
1070                           self, \
1071                          'Message', \
1072                           quit_message, \
1073                           QtGui.QMessageBox.Yes, \
1074                           QtGui.QMessageBox.No)
1075               
1076                if reply == QtGui.QMessageBox.Yes:
1077                       
1078                        if self.brainstormsClient != None:
1079                                self.stopMotors()
1080                                self.brainstormsClient.socket.flush()
1081                               
1082                                if self.brainstormsServer != None:
1083                                       
1084                                        if self.brainstormsServer.rc == None:
1085                                               
1086                                                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
1087                                                self.brainstormsServer.executeCommand( \
1088                                                        'stop_motors', \
1089                                                        bluetooth_device=bluetooth_device)
1090                                               
1091                                        else:
1092                                                self.brainstormsServer.rc.run('stop_motors')
1093                       
1094                       
1095                        event.accept()
1096               
1097                else:
1098                        event.ignore()
1099
1100
1101#####################################################################
1102# Functions
1103#####################################################################
1104
1105#####################################################################
1106# Main
1107#####################################################################
1108
1109if __name__ == '__main__':
1110       
1111        #log = puzzlebox_logger.puzzlebox_logger(logfile='client_interface')
1112        log = None
1113       
1114        app = QtGui.QApplication(sys.argv)
1115       
1116        window = puzzlebox_brainstorms_client_interface(log, DEBUG)
1117        window.show()
1118       
1119        sys.exit(app.exec_())
1120
Note: See TracBrowser for help on using the repository browser.