• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 argparse
21import sys
22from threading import Thread
23from PyQt4.QtCore import *
24from PyQt4.QtGui import *
25
26import VehicleHalProto_pb2
27from vhal_emulator import Vhal
28import vhal_consts_2_0 as c
29
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;
42
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"
124    print "slider "+slider.objectName()+" requested "+str(slider.value())+" = "+gearName
125    gearDisplay.setText(gearName)
126
127
128if __name__ == '__main__':
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()
133    print "Starting VHal driver GUI"
134    vhal = Vhal(c.vhal_types_2_0, device=args.serial)
135
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
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()
147