trajectory_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 math import cos, sin
34 
35 from python_qt_binding.QtCore import Qt
36 from python_qt_binding.QtGui import QBrush, QPainter, QPen
37 from python_qt_binding.QtWidgets import QWidget
38 
39 from .bounds import Bounds
40 from .util import subtractPose
41 
42 
43 def expand_bounds(bounds, extra=0.10):
44  """Expand the negative bounds of the x axis by 10 percent so the area behind the robot is visible."""
45  bounds.x_min -= (bounds.x_max - bounds.x_min) * extra
46 
47 
48 class TrajectoryWidget(QWidget):
49  """This widget displays the actual trajectories of the robot's position through time in robot coordinate space."""
50 
51  def __init__(self, parent, bounds=None):
52  QWidget.__init__(self, parent)
53  self.evaluation = None
54  self.plan = None
55  self.selected = []
56 
57  if not bounds:
58  self.dynamic_bounds = True
59  self.bounds = Bounds()
60  else:
61  self.dynamic_bounds = False
62  self.bounds = bounds
63  expand_bounds(self.bounds)
64 
65  def setEvaluation(self, evaluation):
66  self.evaluation = evaluation
67  if self.dynamic_bounds:
68  self.bounds = Bounds(evaluation)
69  expand_bounds(self.bounds)
70  self.selected = []
71  self.update()
72 
73  def setSelected(self, selected):
74  self.selected = selected
75  self.update()
76 
77  def setPlan(self, plan):
78  self.plan = plan
79 
80  def start(self, event):
81  desired_width = self.bounds.x_max - self.bounds.x_min
82  desired_height = self.bounds.y_max - self.bounds.y_min
83  rect = event.rect()
84  if desired_width == 0 or desired_height == 0:
85  self.ratio = 1.0
86  else:
87  wr = rect.width() / desired_width
88  hr = rect.height() / desired_height
89  self.ratio = min(wr, hr)
90 
91  self.qp = QPainter()
92  self.qp.begin(self)
93 
94  def end(self):
95  self.qp.end()
96 
97  def t_x(self, x):
98  return self.ratio * (x - self.bounds.x_min)
99 
100  def t_y(self, y):
101  return self.ratio * (self.bounds.y_max - y)
102 
103  def drawLine(self, x0, y0, x1, y1):
104  x0 = self.t_x(x0)
105  y0 = self.t_y(y0)
106 
107  x1 = self.t_x(x1)
108  y1 = self.t_y(y1)
109  self.qp.drawLine(x0, y0, x1, y1)
110 
111  def drawCircle(self, x, y, radius):
112  x = self.t_x(x)
113  y = self.t_y(y)
114  self.qp.drawEllipse(x - radius, y - radius, 2 * radius, 2 * radius)
115 
116  def fillRect(self, x, y, width, height):
117  self.qp.fillRect(self.t_x(x), self.t_y(y), self.ratio * width, self.ratio * height, QBrush(Qt.white))
118 
119  def drawPoses(self, poses, base_pose, pose_radius=4, final_pose_radius=5, draw_final_orientation=True):
120  last = None
121  for pose in poses:
122  if base_pose:
123  pose = subtractPose(pose, base_pose)
124  if last:
125  self.drawLine(last.x, last.y, pose.x, pose.y)
126  if pose_radius > 0:
127  self.drawCircle(pose.x, pose.y, pose_radius)
128  last = pose
129 
130  self.drawCircle(last.x, last.y, final_pose_radius)
131 
132  if draw_final_orientation:
133  scale_radius = final_pose_radius / self.ratio
134  self.drawLine(last.x, last.y,
135  last.x + scale_radius * cos(last.theta),
136  last.y + scale_radius * sin(last.theta))
137 
138  def paintEvent(self, event):
139  self.start(event)
140 
141  self.qp.setPen(QPen(Qt.black, 0))
142 
143  self.fillRect(self.bounds.x_min, self.bounds.y_max,
144  self.bounds.x_max - self.bounds.x_min,
145  self.bounds.y_max - self.bounds.y_min)
146 
147  self.drawLine(self.bounds.x_min, 0, self.bounds.x_max, 0)
148  self.drawLine(0, self.bounds.y_min, 0, self.bounds.y_max)
149 
150  if self.evaluation is not None:
151  # Cache the brush
152  brush = self.qp.brush()
153 
154  if len(self.selected) != 0:
155  self.qp.setPen(QPen(Qt.gray, 0))
156 
157  for twist in self.evaluation.twists:
158  self.drawPoses(twist.traj.poses, twist.traj.poses[0], 0, draw_final_orientation=False)
159 
160  for index in self.selected:
161  self.qp.setPen(QPen(Qt.black, 0))
162  self.qp.setBrush(self.selected[index])
163  poses = self.evaluation.twists[index].traj.poses
164  self.drawPoses(poses, poses[0])
165 
166  # Uncache the brush
167  self.qp.setBrush(brush)
168 
169  if self.plan is not None:
170  self.qp.setPen(QPen(Qt.green, 0))
171  self.drawPoses(self.plan.poses, self.evaluation.twists[0].traj.poses[0], 0, 20.0)
172  self.qp.end()
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.setPlan
def setPlan(self, plan)
Definition: trajectory_widget.py:77
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget
Definition: trajectory_widget.py:48
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.evaluation
evaluation
Definition: trajectory_widget.py:53
rqt_dwb_plugin.bounds.Bounds
Definition: bounds.py:36
rqt_dwb_plugin.util.subtractPose
def subtractPose(pose_a, pose_b)
Definition: util.py:48
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.start
def start(self, event)
Definition: trajectory_widget.py:80
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.paintEvent
def paintEvent(self, event)
Definition: trajectory_widget.py:138
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.plan
plan
Definition: trajectory_widget.py:54
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.end
def end(self)
Definition: trajectory_widget.py:94
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.ratio
ratio
Definition: trajectory_widget.py:85
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.selected
selected
Definition: trajectory_widget.py:55
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.drawCircle
def drawCircle(self, x, y, radius)
Definition: trajectory_widget.py:111
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.t_y
def t_y(self, y)
Definition: trajectory_widget.py:100
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.setEvaluation
def setEvaluation(self, evaluation)
Definition: trajectory_widget.py:65
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.drawLine
def drawLine(self, x0, y0, x1, y1)
Definition: trajectory_widget.py:103
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.qp
qp
Definition: trajectory_widget.py:91
rqt_dwb_plugin.trajectory_widget.expand_bounds
def expand_bounds(bounds, extra=0.10)
Definition: trajectory_widget.py:43
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.__init__
def __init__(self, parent, bounds=None)
Definition: trajectory_widget.py:51
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.t_x
def t_x(self, x)
Definition: trajectory_widget.py:97
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.drawPoses
def drawPoses(self, poses, base_pose, pose_radius=4, final_pose_radius=5, draw_final_orientation=True)
Definition: trajectory_widget.py:119
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.fillRect
def fillRect(self, x, y, width, height)
Definition: trajectory_widget.py:116
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.dynamic_bounds
dynamic_bounds
Definition: trajectory_widget.py:58
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.bounds
bounds
Definition: trajectory_widget.py:59
rqt_dwb_plugin.trajectory_widget.TrajectoryWidget.setSelected
def setSelected(self, selected)
Definition: trajectory_widget.py:73


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