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 20import sys 21from threading import Thread 22from PyQt4.QtCore import * 23from PyQt4.QtGui import * 24 25import VehicleHalProto_pb2 26from vhal_emulator import Vhal 27import vhal_consts_2_0 as c 28 29 30# Define a simple thread that receives messages from a vhal object (v) and prints them 31def rxThread(v): 32 while(1): 33 msg = v.rxMsg() 34 if (msg.msg_type == VehicleHalProto_pb2.SET_PROPERTY_RESP): 35 if msg.status == 0: 36 print "Success ("+str(msg.status)+")" 37 else: 38 print "Error ("+str(msg.status)+")" 39 else: 40 print msg; 41 42 43# Main window setup 44def window(): 45 app = QApplication(sys.argv) 46 widget = QWidget() 47 widget.setWindowTitle("VHal Driver") 48 widget.setGeometry(100,100,200,50) 49 topLevelLayout = QHBoxLayout() 50 widget.setLayout(topLevelLayout) 51 52 shiftLayout = QVBoxLayout() 53 topLevelLayout.addLayout(shiftLayout) 54 55 gearTitle = QLabel(widget) 56 gearTitle.setText("Gear Shift") 57 shiftLayout.addWidget(gearTitle); 58 59 gearDisplay = QLabel(widget) 60 shiftLayout.addWidget(gearDisplay); 61 62 slider = QSlider(Qt.Vertical) 63 slider.setMinimum(0) 64 slider.setMaximum(2) 65 slider.setInvertedAppearance(True) 66 slider.valueChanged.connect(lambda:sliderMove(slider, gearDisplay)) 67 shiftLayout.addWidget(slider) 68 sliderMove(slider, gearDisplay) 69 70 71 buttonLayout = QVBoxLayout() 72 topLevelLayout.addLayout(buttonLayout) 73 74 signalButtonGroup = QButtonGroup() 75 76 bNoSignal = QPushButton("None") 77 bNoSignal.setCheckable(True) 78 bNoSignal.setChecked(True) 79 buttonLayout.addWidget(bNoSignal) 80 signalButtonGroup.addButton(bNoSignal) 81 82 bHazards = QPushButton("Hazards") 83 bHazards.setCheckable(True) 84 buttonLayout.addWidget(bHazards) 85 signalButtonGroup.addButton(bHazards) 86 87 bLeft = QPushButton("Left") 88 bLeft.setCheckable(True) 89 buttonLayout.addWidget(bLeft) 90 signalButtonGroup.addButton(bLeft) 91 92 bRight = QPushButton("Right") 93 bRight.setCheckable(True) 94 buttonLayout.addWidget(bRight) 95 signalButtonGroup.addButton(bRight) 96 97 signalButtonGroup.buttonClicked.connect(lambda:onSignalClicked(signalButtonGroup)) 98 99 widget.show() 100 sys.exit(app.exec_()) 101 102 103def onSignalClicked(group): 104 print "signal "+group.checkedButton().text()+" is active" 105 try: 106 vhal.setProperty(c.VEHICLEPROPERTY_TURN_SIGNAL_STATE, 0, group.checkedId()) 107 except: 108 print "Ignoring error setting property 0x{:08X}".format(c.VEHICLEPROPERTY_TURN_SIGNAL_STATE) 109 110 111def sliderMove(slider, gearDisplay): 112 if slider.value() == 0: 113 gearName = 'park' 114 vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_PARK) 115 elif slider.value() == 1: 116 gearName = 'reverse' 117 vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_REVERSE) 118 elif slider.value() == 2: 119 gearName = 'drive' 120 vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_DRIVE) 121 else: 122 gearName = "UNK" 123 print "slider "+slider.objectName()+" requested "+str(slider.value())+" = "+gearName 124 gearDisplay.setText(gearName) 125 126 127if __name__ == '__main__': 128 print "Starting VHal driver GUI" 129 vhal = Vhal(c.vhal_types_2_0) 130 131 # Start a receive thread to consume any replies from the vhal 132 print "Starting receiver thread" 133 rx = Thread(target=rxThread, args=(vhal,)) 134 rx.setDaemon(True) 135 rx.start() 136 137 # Put the car in park so we start in a known state (consistent with the GUI default state) 138 vhal.setProperty(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_PARK) 139 140 # Start the main UI -- never returns 141 window() 142