velocity_space_widget.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2018-2019, Locus Robotics
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of the copyright holder nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 from python_qt_binding.QtCore import Qt
34 from python_qt_binding.QtGui import QBrush, QPainter, QPen
35 from python_qt_binding.QtWidgets import QWidget
36 
37 from .util import scale
38 
39 
40 class VelocitySpaceWidget(QWidget):
41  """This widget displays the velocities for each trajectory in the evaluation."""
42 
43  def __init__(self, parent, selection_callback):
44  QWidget.__init__(self, parent)
45  self.evaluation = None
46  self.vel_space = {}
47  self.scores = {}
48  self.n_x = 0
49  self.n_theta = 0
50  self.selected = []
51  self.selection_callback = selection_callback
52  self.vel = None
53 
54  def setVelocity(self, vel):
55  self.vel = vel
56 
57  def setEvaluation(self, evaluation):
58  self.evaluation = evaluation
59  self.selected = []
60  self.vel_space = {}
61  self.scores = {}
62  xs = set()
63  thetas = set()
64  self.x_min = self.x_max = None
65  self.t_min = self.t_max = None
66  for i, twist in enumerate(self.evaluation.twists):
67  v = twist.traj.velocity.x, twist.traj.velocity.theta
68  xs.add(v[0])
69  thetas.add(v[1])
70  self.vel_space[v] = i
71  self.scores[v] = twist.total
72 
73  if self.x_min is None:
74  self.x_min = self.x_max = v[0]
75  self.t_min = self.t_max = v[1]
76  else:
77  self.x_min = min(self.x_min, v[0])
78  self.x_max = max(self.x_max, v[0])
79  self.t_min = min(self.t_min, v[1])
80  self.t_max = max(self.t_max, v[1])
81  self.n_x = len(xs)
82  self.n_theta = len(thetas)
83  self.update()
84 
85  def setSelected(self, selected):
86  self.selected = selected
87  self.update()
88 
89  def paintEvent(self, event):
90  if self.evaluation is None or self.n_x == 0:
91  return
92  rect = event.rect()
93  w, h = rect.width(), rect.height()
94  self.left = w * 0.2
95  self.width = w * 0.7
96  self.top = h * 0.1
97  self.height = h * 0.85
98 
99  horizontal_size = self.width / self.n_x
100  vertical_size = self.height / self.n_theta
101  diameter = max(5, min(horizontal_size, vertical_size))
102  radius = diameter / 2
103 
104  self.qp = QPainter()
105  self.qp.begin(self)
106  self.qp.setBrush(QBrush(Qt.white))
107  self.qp.drawRect(self.left, self.top, self.width, self.height)
108 
109  zx, zy = self.toScreen(0, 0)
110  if zy >= self.top and zy <= self.top + self.height:
111  self.qp.drawLine(self.left, zy, self.left + self.width, zy)
112  if zx >= self.left and zx <= self.left + self.width:
113  self.qp.drawLine(zx, self.top, zx, self.top + self.height)
114 
115  self.qp.drawText(self.left, 0, self.width, self.top, Qt.AlignCenter, 'x')
116  self.qp.drawText(0, 0, self.left * 2, self.top, Qt.AlignCenter, '%.2f' % self.x_min)
117  self.qp.drawText(w - self.left, 0, self.left, self.top, Qt.AlignCenter, '%.2f' % self.x_max)
118 
119  right_center = Qt.AlignVCenter | Qt.AlignRight
120  self.qp.drawText(0, self.top, self.left - radius, self.height, right_center, 'theta')
121  self.qp.drawText(0, 0, self.left - radius, self.top * 2, right_center, '%.2f' % self.t_max)
122  self.qp.drawText(0, h - self.top, self.left - radius, self.top, right_center, '%.2f' % self.t_min)
123 
124  for (x, theta), index in self.vel_space.items():
125  dx, dy = self.toScreen(x, theta)
126  if index in self.selected:
127  self.qp.setBrush(QBrush(self.selected[index]))
128  else:
129  self.qp.setBrush(QBrush())
130 
131  if self.scores[x, theta] < 0.0:
132  self.qp.setPen(QPen(Qt.red))
133  else:
134  self.qp.setPen(QPen(Qt.black))
135  self.qp.drawEllipse(dx - radius, dy - radius, diameter, diameter)
136 
137  if self.vel:
138  self.qp.setBrush(QBrush())
139  dx, dy = self.toScreen(self.vel.x, self.vel.theta)
140  self.qp.drawEllipse(dx - diameter, dy - diameter, diameter * 2, diameter * 2)
141 
142  self.qp.end()
143 
144  def toScreen(self, x, theta):
145  return scale(x, self.x_min, self.x_max, self.width, self.left), \
146  scale(theta, self.t_max, self.t_min, self.height, self.top)
147 
148  def toVelocity(self, x, y):
149  xv = (x - self.left) / self.width * (self.x_max - self.x_min) + self.x_min
150  yv = self.t_max - (y - self.top) / self.height * (self.t_max - self.t_min)
151  return xv, yv
152 
153  def getNearestVelocity(self, xv, tv):
154  best_d = None
155  best = None
156  for (x, theta), index in self.vel_space.items():
157  d = abs(x - xv) + abs(theta - tv)
158  if best_d is None or d < best_d:
159  best_d = d
160  best = index
161  return best
162 
163  def mousePressEvent(self, event):
164  pos = event.pos()
165  xv, tv = self.toVelocity(pos.x(), pos.y())
166 
167  new_selected = list(self.selected)
168  selection = self.getNearestVelocity(xv, tv)
169  if selection in self.selected:
170  new_selected.remove(selection)
171  self.selection_callback(new_selected)
172  else:
173  new_selected.append(selection)
174  self.selection_callback(new_selected)
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.x_min
x_min
Definition: velocity_space_widget.py:64
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.width
width
Definition: velocity_space_widget.py:95
rqt_dwb_plugin.util.scale
def scale(v, minval, maxval, dest_size=1.0, offset=0.0)
Definition: util.py:42
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.__init__
def __init__(self, parent, selection_callback)
Definition: velocity_space_widget.py:43
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.t_max
t_max
Definition: velocity_space_widget.py:65
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.getNearestVelocity
def getNearestVelocity(self, xv, tv)
Definition: velocity_space_widget.py:153
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.toVelocity
def toVelocity(self, x, y)
Definition: velocity_space_widget.py:148
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.setSelected
def setSelected(self, selected)
Definition: velocity_space_widget.py:85
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.height
height
Definition: velocity_space_widget.py:97
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.setEvaluation
def setEvaluation(self, evaluation)
Definition: velocity_space_widget.py:57
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.scores
scores
Definition: velocity_space_widget.py:47
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.n_x
n_x
Definition: velocity_space_widget.py:48
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.paintEvent
def paintEvent(self, event)
Definition: velocity_space_widget.py:89
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.mousePressEvent
def mousePressEvent(self, event)
Definition: velocity_space_widget.py:163
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.top
top
Definition: velocity_space_widget.py:96
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.evaluation
evaluation
Definition: velocity_space_widget.py:45
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.toScreen
def toScreen(self, x, theta)
Definition: velocity_space_widget.py:144
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.vel_space
vel_space
Definition: velocity_space_widget.py:46
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.n_theta
n_theta
Definition: velocity_space_widget.py:49
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.vel
vel
Definition: velocity_space_widget.py:52
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.setVelocity
def setVelocity(self, vel)
Definition: velocity_space_widget.py:54
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.selection_callback
selection_callback
Definition: velocity_space_widget.py:51
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget
Definition: velocity_space_widget.py:40
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.t_min
t_min
Definition: velocity_space_widget.py:65
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.left
left
Definition: velocity_space_widget.py:94
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.qp
qp
Definition: velocity_space_widget.py:104
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.selected
selected
Definition: velocity_space_widget.py:50
rqt_dwb_plugin.velocity_space_widget.VelocitySpaceWidget.x_max
x_max
Definition: velocity_space_widget.py:64


rqt_dwb_plugin
Author(s):
autogenerated on Sun May 18 2025 02:47:58