blob: 6607ce47d29e80bc608e5cfbff75af4e38610126 [file] [log] [blame]
Scott Randolph02f7a322017-05-08 17:41:54 -07001#!/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 Granata9be764a2020-03-23 16:48:15 -070020import argparse
Scott Randolph02f7a322017-05-08 17:41:54 -070021import sys
Scott Randolph18baf5f2017-06-06 15:54:27 -070022from threading import Thread
Scott Randolph02f7a322017-05-08 17:41:54 -070023from PyQt4.QtCore import *
24from PyQt4.QtGui import *
25
Scott Randolph18baf5f2017-06-06 15:54:27 -070026import VehicleHalProto_pb2
Scott Randolph02f7a322017-05-08 17:41:54 -070027from vhal_emulator import Vhal
Chao Yand1a11b52017-10-04 13:54:03 -070028import vhal_consts_2_0 as c
Scott Randolph18baf5f2017-06-06 15:54:27 -070029
30
31# Define a simple thread that receives messages from a vhal object (v) and prints them
32def 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 Randolph02f7a322017-05-08 17:41:54 -070042
43
44# Main window setup
45def 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
104def 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
112def 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 Randolph18baf5f2017-06-06 15:54:27 -0700124 print "slider "+slider.objectName()+" requested "+str(slider.value())+" = "+gearName
Scott Randolph02f7a322017-05-08 17:41:54 -0700125 gearDisplay.setText(gearName)
126
127
128if __name__ == '__main__':
Enrico Granata9be764a2020-03-23 16:48:15 -0700129 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 Randolph02f7a322017-05-08 17:41:54 -0700133 print "Starting VHal driver GUI"
Enrico Granata9be764a2020-03-23 16:48:15 -0700134 vhal = Vhal(c.vhal_types_2_0, device=args.serial)
Scott Randolph02f7a322017-05-08 17:41:54 -0700135
Scott Randolph18baf5f2017-06-06 15:54:27 -0700136 # 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 Randolph02f7a322017-05-08 17:41:54 -0700142 # 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()