WUT Velma robot API
subsystem_state_history.py
Go to the documentation of this file.
1 # Copyright (c) 2014, Robot Control and Pattern Recognition Group, Warsaw University of Technology
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution.
11 # * Neither the name of the Warsaw University of Technology nor the
12 # names of its contributors may be used to endorse or promote products
13 # derived from this software without specific prior written permission.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL <COPYright HOLDER> BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 from __future__ import division
27 import os
28 import math
29 
30 from python_qt_binding import loadUi
31 from python_qt_binding.QtCore import Qt, QTimer, Signal, Slot, QRectF, QPointF, QSize, QRect, QPoint
32 from python_qt_binding.QtWidgets import QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QListWidgetItem, QDialog, QGraphicsView, QGraphicsScene, QGraphicsPathItem, QTableWidgetItem, QHeaderView, QStyle, QCommonStyle
33 from python_qt_binding.QtGui import QColor, QPen, QBrush, QPainterPath, QPolygonF, QTransform, QPainter, QIcon, QPixmap, QPaintEvent, QPalette
34 from python_qt_binding.QtSvg import QSvgGenerator
35 import roslib
36 import rospkg
37 import rospy
38 from rospy.exceptions import ROSException
39 
40 from subsystem_msgs.srv import *
41 
42 class StateHistoryDialog(QDialog):
43 
44  @Slot()
45  def closeClick(self):
46  self.close()
47 
48  @Slot()
49  def radio_historyClick(self):
50  self._mode = "history"
51 
52  @Slot()
54  self._mode = "switches"
55 
56  class MyStyle(QCommonStyle):
57  def drawControl (self, element, opt, painter, widget=None):
58 
59 # print element
60  if element == QStyle.CE_HeaderLabel:
61  hv = widget
62 # if not hv or hv.orientation() != Qt.Horizontal:
63 # return super(StateHistoryDialog.MyStyle, self).drawControl(element, opt, p, widget)
64  header = opt
65 
66  if header.section < 3:
67  return super(StateHistoryDialog.MyStyle, self).drawControl(element, opt, painter, widget)
68 
69  painter.save()
70  #// painter->translate(header->rect.topLeft())
71  rect = header.rect.bottomLeft()
72  painter.translate(QPoint(rect.x() + 10, rect.y() + 5))
73 # print "drawControl"
74  painter.rotate(-90)
75  painter.drawText(0,0,header.text)
76  painter.restore()
77  return
78 # return QProxyStyle::drawControl(element, option, painter, widget);
79 # print "drawControl"
80  return super(StateHistoryDialog.MyStyle, self).drawControl(element, opt, painter, widget)
81 
82 # def drawItemText( painter, rectangle, alignment, palette, enabled, text, textRole = QPalette.NoRole):
83 # pass
84 
85  class MyHorizHeader(QHeaderView):
86  def __init__(self, parent=None):
87  super(StateHistoryDialog.MyHorizHeader, self).__init__(Qt.Horizontal, parent)
89  self.setStyle(style)
90 
91  def sizeHint(self):
92  # Get the base implementation size.
93  baseSize = super(StateHistoryDialog.MyHorizHeader, self).sizeHint()
94  # Override the height with a custom value.
95  baseSize.setHeight( 150 );
96 # baseSize.setWidth( 20 );
97  return baseSize;
98 
99  def __init__(self, subsystem_name, parent=None):
100  super(StateHistoryDialog, self).__init__(parent)
101 
102  self.parent = parent
103 
104  self.setWindowFlags(Qt.Window)
105 
106  rp = rospkg.RosPack()
107  ui_file = os.path.join(rp.get_path('rqt_agent'), 'resource', 'StateHistory.ui')
108  loadUi(ui_file, self)
109 
110  self.setWindowTitle(subsystem_name + " - state history")
111 
112  self._mode = "history"
113 
114  # connect slots
115  self.pushButton_close.clicked.connect(self.closeClick)
116  self.radio_history.clicked.connect(self.radio_historyClick)
117  self.radio_switches.clicked.connect(self.radio_switchesClick)
118 
119  self.initialized = False
120 
121  hdr = self.MyHorizHeader(self.tableWidget)
122  hdr.setMinimumSectionSize(40)
123  hdr.setDefaultSectionSize(40)
124  self.tableWidget.setHorizontalHeader(hdr)
125  item0 = QTableWidgetItem("state")
126  item1 = QTableWidgetItem("reason")
127  item2 = QTableWidgetItem("time")
128  self.tableWidget.setHorizontalHeaderItem (0, item0)
129  self.tableWidget.setHorizontalHeaderItem (1, item1)
130  self.tableWidget.setHorizontalHeaderItem (2, item2)
131  self.tableWidget.setColumnWidth(0, 100)
132  self.tableWidget.setColumnWidth(1, 50)
133  self.tableWidget.setColumnWidth(2, 75)
134 
135 # hdr_2 = self.MyHorizHeader(self.tableWidget_2)
136 # hdr_2.setMinimumSectionSize(40)
137 # hdr_2.setDefaultSectionSize(40)
138 # self.tableWidget_2.setHorizontalHeader(hdr_2)
139 # item0 = QTableWidgetItem("state")
140 # item1 = QTableWidgetItem("reason")
141 # item2 = QTableWidgetItem("time")
142 # self.tableWidget_2.setHorizontalHeaderItem (0, item0)
143 # self.tableWidget_2.setHorizontalHeaderItem (1, item1)
144 # self.tableWidget_2.setHorizontalHeaderItem (2, item2)
145 # self.tableWidget_2.setColumnWidth(0, 100)
146 # self.tableWidget_2.setColumnWidth(1, 50)
147 # self.tableWidget_2.setColumnWidth(2, 75)
148 
150 
151  def setUsedPredicatesInfo(self, used_predicates_info):
152  self.used_predicates_info = used_predicates_info
153 
154  def updateState(self, mcd):
155  curr_pred_v = []
156  for pv in mcd.current_predicates:
157  if pv.value == True:
158  curr_pred_v.append("t")
159  elif pv.value == False:
160  curr_pred_v.append("f")
161  else:
162  raise ValueError("wrong predicate value: '" + str(pv.value) + "' for predicate: '" + pv.name + "'")
163 
164  if not self.initialized:
165  self.initialized = True
166  predicates = []
167  for pv in mcd.current_predicates:
168  predicates.append( pv.name )
169  self.tableWidget.setColumnCount(len(predicates)+3)
170 # self.tableWidget_2.setColumnCount(len(predicates)+3)
171  idx = 3
172  for p in predicates:
173  item = QTableWidgetItem(p)
174  self.tableWidget.setHorizontalHeaderItem(idx, item)
175 # item_2 = QTableWidgetItem(p)
176 # self.tableWidget_2.setHorizontalHeaderItem(idx, item_2)
177  idx += 1
178 
179  if self._mode == "history":
180  # history
181  if self.tableWidget.rowCount() != len(mcd.history):
182  self.tableWidget.setRowCount( len(mcd.history) )
183  row = 0
184  for ss in mcd.history:
185  self.tableWidget.setItem(row, 0, QTableWidgetItem(ss.state_name))
186  self.tableWidget.setItem(row, 1, QTableWidgetItem(ss.reason))
187  self.tableWidget.setItem(row, 2, QTableWidgetItem(str(ss.switch_interval)))
188  idx = 0
189  for pv in ss.predicates:
190  pred_used = False
191  if self.used_predicates_info != None and (ss.prev_state_name, ss.state_name) in self.used_predicates_info:
192  if pv.name in self.used_predicates_info[(ss.prev_state_name, ss.state_name)]:
193  pred_used = True
194  if pv.value == True:
195  p_str = "T"
196  elif pv.value == False:
197  p_str = "F"
198  else:
199  raise ValueError("wrong predicate value: '" + str(pv.value) + "' for predicate: '" + pv.name + "'")
200 
201  if row == 0:
202  item = QTableWidgetItem(p_str + " ("+curr_pred_v[idx]+")")
203  else:
204  item = QTableWidgetItem(p_str)
205  if pred_used:
206  item.setBackground(QBrush(QColor(0,255,0)))
207 
208  self.tableWidget.setItem(row, 3+idx, item)
209  idx += 1
210  row = row + 1
211  elif self._mode == "switches":
212  # state switch info
213  if self.tableWidget.rowCount() != len(mcd.state_switch_info):
214  self.tableWidget.setRowCount( len(mcd.state_switch_info) )
215  row = 0
216  state_switch_info = sorted(mcd.state_switch_info, key=lambda ss: ss.switch_interval)
217  for ss in state_switch_info:
218  self.tableWidget.setItem(row, 0, QTableWidgetItem(ss.prev_state_name + " -> " + ss.state_name))
219  self.tableWidget.setItem(row, 1, QTableWidgetItem(ss.reason))
220  self.tableWidget.setItem(row, 2, QTableWidgetItem(str(ss.switch_interval)))
221 
222  idx = 0
223  for pv in ss.predicates:
224  pred_used = False
225  if self.used_predicates_info != None and (ss.prev_state_name, ss.state_name) in self.used_predicates_info:
226  if pv.name in self.used_predicates_info[(ss.prev_state_name, ss.state_name)]:
227  pred_used = True
228  if pv.value == True:
229  p_str = "T"
230  elif pv.value == False:
231  p_str = "F"
232  else:
233  raise ValueError("wrong predicate value: '" + str(pv.value) + "' for predicate: '" + pv.name + "'")
234  item = QTableWidgetItem(p_str)
235  if pred_used:
236  item.setBackground(QBrush(QColor(0,255,0)))
237  self.tableWidget.setItem(row, 3+idx, item)
238  idx += 1
239  row = row + 1
240 
def drawControl(self, element, opt, painter, widget=None)