Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright (C) 2017 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | |
| 18 | # A simple GUI to remotely actuate the Vehicle HAL via the eumalator |
| 19 | |
Enrico Granata | 9be764a | 2020-03-23 16:48:15 -0700 | [diff] [blame] | 20 | import argparse |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 21 | import sys |
Scott Randolph | 18baf5f | 2017-06-06 15:54:27 -0700 | [diff] [blame] | 22 | from threading import Thread |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 23 | from PyQt4.QtCore import * |
| 24 | from PyQt4.QtGui import * |
| 25 | |
Scott Randolph | 18baf5f | 2017-06-06 15:54:27 -0700 | [diff] [blame] | 26 | import VehicleHalProto_pb2 |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 27 | from vhal_emulator import Vhal |
Chao Yan | d1a11b5 | 2017-10-04 13:54:03 -0700 | [diff] [blame] | 28 | import vhal_consts_2_0 as c |
Scott Randolph | 18baf5f | 2017-06-06 15:54:27 -0700 | [diff] [blame] | 29 | |
| 30 | |
| 31 | # Define a simple thread that receives messages from a vhal object (v) and prints them |
| 32 | def rxThread(v): |
| 33 | while(1): |
| 34 | msg = v.rxMsg() |
| 35 | if (msg.msg_type == VehicleHalProto_pb2.SET_PROPERTY_RESP): |
| 36 | if msg.status == 0: |
| 37 | print "Success ("+str(msg.status)+")" |
| 38 | else: |
| 39 | print "Error ("+str(msg.status)+")" |
| 40 | else: |
| 41 | print msg; |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 42 | |
| 43 | |
| 44 | # Main window setup |
| 45 | def window(): |
| 46 | app = QApplication(sys.argv) |
| 47 | widget = QWidget() |
| 48 | widget.setWindowTitle("VHal Driver") |
| 49 | widget.setGeometry(100,100,200,50) |
| 50 | topLevelLayout = QHBoxLayout() |
| 51 | widget.setLayout(topLevelLayout) |
| 52 | |
| 53 | shiftLayout = QVBoxLayout() |
| 54 | topLevelLayout.addLayout(shiftLayout) |
| 55 | |
| 56 | gearTitle = QLabel(widget) |
| 57 | gearTitle.setText("Gear Shift") |
| 58 | shiftLayout.addWidget(gearTitle); |
| 59 | |
| 60 | gearDisplay = QLabel(widget) |
| 61 | shiftLayout.addWidget(gearDisplay); |
| 62 | |
| 63 | slider = QSlider(Qt.Vertical) |
| 64 | slider.setMinimum(0) |
| 65 | slider.setMaximum(2) |
| 66 | slider.setInvertedAppearance(True) |
| 67 | slider.valueChanged.connect(lambda:sliderMove(slider, gearDisplay)) |
| 68 | shiftLayout.addWidget(slider) |
| 69 | sliderMove(slider, gearDisplay) |
| 70 | |
| 71 | |
| 72 | buttonLayout = QVBoxLayout() |
| 73 | topLevelLayout.addLayout(buttonLayout) |
| 74 | |
| 75 | signalButtonGroup = QButtonGroup() |
| 76 | |
| 77 | bNoSignal = QPushButton("None") |
| 78 | bNoSignal.setCheckable(True) |
| 79 | bNoSignal.setChecked(True) |
| 80 | buttonLayout.addWidget(bNoSignal) |
| 81 | signalButtonGroup.addButton(bNoSignal) |
| 82 | |
| 83 | bHazards = QPushButton("Hazards") |
| 84 | bHazards.setCheckable(True) |
| 85 | buttonLayout.addWidget(bHazards) |
| 86 | signalButtonGroup.addButton(bHazards) |
| 87 | |
| 88 | bLeft = QPushButton("Left") |
| 89 | bLeft.setCheckable(True) |
| 90 | buttonLayout.addWidget(bLeft) |
| 91 | signalButtonGroup.addButton(bLeft) |
| 92 | |
| 93 | bRight = QPushButton("Right") |
| 94 | bRight.setCheckable(True) |
| 95 | buttonLayout.addWidget(bRight) |
| 96 | signalButtonGroup.addButton(bRight) |
| 97 | |
| 98 | signalButtonGroup.buttonClicked.connect(lambda:onSignalClicked(signalButtonGroup)) |
| 99 | |
| 100 | widget.show() |
| 101 | sys.exit(app.exec_()) |
| 102 | |
| 103 | |
| 104 | def onSignalClicked(group): |
| 105 | print "signal "+group.checkedButton().text()+" is active" |
| 106 | try: |
| 107 | vhal.setProperty(c.VEHICLEPROPERTY_TURN_SIGNAL_STATE, 0, group.checkedId()) |
| 108 | except: |
| 109 | print "Ignoring error setting property 0x{:08X}".format(c.VEHICLEPROPERTY_TURN_SIGNAL_STATE) |
| 110 | |
| 111 | |
| 112 | def sliderMove(slider, gearDisplay): |
| 113 | if slider.value() == 0: |
| 114 | gearName = 'park' |
| 115 | vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_PARK) |
| 116 | elif slider.value() == 1: |
| 117 | gearName = 'reverse' |
| 118 | vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_REVERSE) |
| 119 | elif slider.value() == 2: |
| 120 | gearName = 'drive' |
| 121 | vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_DRIVE) |
| 122 | else: |
| 123 | gearName = "UNK" |
Scott Randolph | 18baf5f | 2017-06-06 15:54:27 -0700 | [diff] [blame] | 124 | print "slider "+slider.objectName()+" requested "+str(slider.value())+" = "+gearName |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 125 | gearDisplay.setText(gearName) |
| 126 | |
| 127 | |
| 128 | if __name__ == '__main__': |
Enrico Granata | 9be764a | 2020-03-23 16:48:15 -0700 | [diff] [blame] | 129 | parser = argparse.ArgumentParser(description='Vehicle HAL Driver UI') |
| 130 | parser.add_argument("--serial", "-s", action='store', dest='serial', |
| 131 | default=None, required=False, help='Select which device to connect to') |
| 132 | args = parser.parse_args() |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 133 | print "Starting VHal driver GUI" |
Enrico Granata | 9be764a | 2020-03-23 16:48:15 -0700 | [diff] [blame] | 134 | vhal = Vhal(c.vhal_types_2_0, device=args.serial) |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 135 | |
Scott Randolph | 18baf5f | 2017-06-06 15:54:27 -0700 | [diff] [blame] | 136 | # Start a receive thread to consume any replies from the vhal |
| 137 | print "Starting receiver thread" |
| 138 | rx = Thread(target=rxThread, args=(vhal,)) |
| 139 | rx.setDaemon(True) |
| 140 | rx.start() |
| 141 | |
Scott Randolph | 02f7a32 | 2017-05-08 17:41:54 -0700 | [diff] [blame] | 142 | # Put the car in park so we start in a known state (consistent with the GUI default state) |
| 143 | vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_PARK) |
| 144 | |
| 145 | # Start the main UI -- never returns |
| 146 | window() |