__init__.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2010, Willow Garage, Inc.
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 Willow Garage, Inc. 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 OWNER 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 import math
34 import random
35 
36 import rospy
37 
38 from python_qt_binding.QtCore import pyqtSlot
39 from python_qt_binding.QtCore import Qt
40 from python_qt_binding.QtCore import Signal
41 from python_qt_binding.QtGui import QFont
42 from python_qt_binding.QtWidgets import QApplication
43 from python_qt_binding.QtWidgets import QHBoxLayout
44 from python_qt_binding.QtWidgets import QLabel
45 from python_qt_binding.QtWidgets import QLineEdit
46 from python_qt_binding.QtWidgets import QPushButton
47 from python_qt_binding.QtWidgets import QSlider
48 from python_qt_binding.QtWidgets import QVBoxLayout
49 from python_qt_binding.QtWidgets import QGridLayout
50 from python_qt_binding.QtWidgets import QScrollArea
51 from python_qt_binding.QtWidgets import QSpinBox
52 from python_qt_binding.QtWidgets import QWidget
53 
54 RANGE = 10000
55 
56 
57 class JointStatePublisherGui(QWidget):
58  sliderUpdateTrigger = Signal()
59 
60  def __init__(self, title, jsp, num_rows=0):
61  super(JointStatePublisherGui, self).__init__()
62  self.setWindowTitle(title)
63  self.jsp = jsp
64  self.joint_map = {}
65  self.vlayout = QVBoxLayout(self)
66  self.scrollable = QWidget()
67  self.gridlayout = QGridLayout()
68  self.scroll = QScrollArea()
69  self.scroll.setWidgetResizable(True)
70 
71  self.jsp.set_source_update_cb(self.source_update_cb)
72 
73  font = QFont("Helvetica", 9, QFont.Bold)
74 
75 
76  sliders = []
77  for name in self.jsp.joint_list:
78  if name not in self.jsp.free_joints:
79  continue
80  joint = self.jsp.free_joints[name]
81 
82  if joint['min'] == joint['max']:
83  continue
84 
85  joint_layout = QVBoxLayout()
86  row_layout = QHBoxLayout()
87 
88  label = QLabel(name)
89  label.setFont(font)
90  row_layout.addWidget(label)
91  display = QLineEdit("0.00")
92  display.setAlignment(Qt.AlignRight)
93  display.setFont(font)
94  display.setReadOnly(True)
95  row_layout.addWidget(display)
96 
97  joint_layout.addLayout(row_layout)
98 
99  slider = QSlider(Qt.Horizontal)
100 
101  slider.setFont(font)
102  slider.setRange(0, RANGE)
103  slider.setValue(int(RANGE/2))
104 
105  joint_layout.addWidget(slider)
106 
107  self.joint_map[name] = {'slidervalue': 0, 'display': display,
108  'slider': slider, 'joint': joint}
109  # Connect to the signal provided by QSignal
110  slider.valueChanged.connect(lambda event,name=name: self.onValueChangedOne(name))
111 
112  sliders.append(joint_layout)
113 
114  # Determine number of rows to be used in grid
115  self.num_rows = num_rows
116  # if desired num of rows wasn't set, default behaviour is a vertical layout
117  if self.num_rows == 0:
118  self.num_rows = len(sliders) # equals VBoxLayout
119  # Generate positions in grid and place sliders there
120  self.positions = self.generate_grid_positions(len(sliders), self.num_rows)
121  for item, pos in zip(sliders, self.positions):
122  self.gridlayout.addLayout(item, *pos)
123 
124  # Set zero positions read from parameters
125  self.center()
126 
127  # Synchronize slider and displayed value
128  self.sliderUpdate(None)
129 
130  # Set up a signal for updating the sliders based on external joint info
131  self.sliderUpdateTrigger.connect(self.updateSliders)
132 
133  self.scrollable.setLayout(self.gridlayout)
134  self.scroll.setWidget(self.scrollable)
135  self.vlayout.addWidget(self.scroll)
136 
137  # Buttons for randomizing and centering sliders and
138  # Spinbox for on-the-fly selecting number of rows
139  self.randbutton = QPushButton('Randomize', self)
140  self.randbutton.clicked.connect(self.randomize_event)
141  self.vlayout.addWidget(self.randbutton)
142  self.ctrbutton = QPushButton('Center', self)
143  self.ctrbutton.clicked.connect(self.center_event)
144  self.vlayout.addWidget(self.ctrbutton)
145  self.maxrowsupdown = QSpinBox()
146  self.maxrowsupdown.setMinimum(1)
147  self.maxrowsupdown.setMaximum(len(sliders))
148  self.maxrowsupdown.setValue(self.num_rows)
149  self.maxrowsupdown.valueChanged.connect(self.reorggrid_event)
150  self.vlayout.addWidget(self.maxrowsupdown)
151  self.setLayout(self.vlayout)
152 
153  def source_update_cb(self):
154  self.sliderUpdateTrigger.emit()
155 
156  def onValueChangedOne(self, name):
157  # A slider value was changed, but we need to change the joint_info metadata.
158  joint_info = self.joint_map[name]
159  joint_info['slidervalue'] = joint_info['slider'].value()
160  joint = joint_info['joint']
161  joint['position'] = self.sliderToValue(joint_info['slidervalue'], joint)
162  joint_info['display'].setText("%.3f" % joint['position'])
163 
164  @pyqtSlot()
165  def updateSliders(self):
166  self.update_sliders()
167 
168  def update_sliders(self):
169  for name, joint_info in self.joint_map.items():
170  joint = joint_info['joint']
171  joint_info['slidervalue'] = self.valueToSlider(joint['position'],
172  joint)
173  joint_info['slider'].setValue(joint_info['slidervalue'])
174 
175  def center_event(self, event):
176  self.center()
177 
178  def center(self):
179  rospy.loginfo("Centering")
180  for name, joint_info in self.joint_map.items():
181  joint = joint_info['joint']
182  joint_info['slider'].setValue(self.valueToSlider(joint['zero'], joint))
183 
184  def reorggrid_event(self, event):
185  self.reorganize_grid(event)
186 
187  def reorganize_grid(self, number_of_rows):
188  self.num_rows = number_of_rows
189 
190  # Remove items from layout (won't destroy them!)
191  items = []
192  for pos in self.positions:
193  item = self.gridlayout.itemAtPosition(*pos)
194  items.append(item)
195  self.gridlayout.removeItem(item)
196 
197  # Generate new positions for sliders and place them in their new spots
198  self.positions = self.generate_grid_positions(len(items), self.num_rows)
199  for item, pos in zip(items, self.positions):
200  self.gridlayout.addLayout(item, *pos)
201 
202  def generate_grid_positions(self, num_items, num_rows):
203  if num_rows == 0:
204  return []
205  positions = [(y, x) for x in range(int((math.ceil(float(num_items) / num_rows)))) for y in range(num_rows)]
206  positions = positions[:num_items]
207  return positions
208 
209  def randomize_event(self, event):
210  self.randomize()
211 
212  def randomize(self):
213  rospy.loginfo("Randomizing")
214  for name, joint_info in self.joint_map.items():
215  joint = joint_info['joint']
216  joint_info['slider'].setValue(
217  self.valueToSlider(random.uniform(joint['min'], joint['max']), joint))
218 
219  def sliderUpdate(self, event):
220  for name, joint_info in self.joint_map.items():
221  joint_info['slidervalue'] = joint_info['slider'].value()
222  self.update_sliders()
223 
224  def valueToSlider(self, value, joint):
225  return int((value - joint['min']) * float(RANGE) / (joint['max'] - joint['min']))
226 
227  def sliderToValue(self, slider, joint):
228  pctvalue = slider / float(RANGE)
229  return joint['min'] + (joint['max']-joint['min']) * pctvalue
joint_state_publisher_gui.JointStatePublisherGui.reorggrid_event
def reorggrid_event(self, event)
Definition: __init__.py:184
joint_state_publisher_gui.JointStatePublisherGui.ctrbutton
ctrbutton
Definition: __init__.py:142
joint_state_publisher_gui.JointStatePublisherGui.sliderToValue
def sliderToValue(self, slider, joint)
Definition: __init__.py:227
joint_state_publisher_gui.JointStatePublisherGui.scrollable
scrollable
Definition: __init__.py:66
joint_state_publisher_gui.JointStatePublisherGui.gridlayout
gridlayout
Definition: __init__.py:67
joint_state_publisher_gui.JointStatePublisherGui.valueToSlider
def valueToSlider(self, value, joint)
Definition: __init__.py:224
joint_state_publisher_gui.JointStatePublisherGui.maxrowsupdown
maxrowsupdown
Definition: __init__.py:145
joint_state_publisher_gui.JointStatePublisherGui.onValueChangedOne
def onValueChangedOne(self, name)
Definition: __init__.py:156
joint_state_publisher_gui.JointStatePublisherGui.reorganize_grid
def reorganize_grid(self, number_of_rows)
Definition: __init__.py:187
joint_state_publisher_gui.JointStatePublisherGui.sliderUpdateTrigger
sliderUpdateTrigger
Definition: __init__.py:58
joint_state_publisher_gui.JointStatePublisherGui.joint_map
joint_map
Definition: __init__.py:64
joint_state_publisher_gui.JointStatePublisherGui.scroll
scroll
Definition: __init__.py:68
joint_state_publisher_gui.JointStatePublisherGui.center
def center(self)
Definition: __init__.py:178
joint_state_publisher_gui.JointStatePublisherGui.center_event
def center_event(self, event)
Definition: __init__.py:175
joint_state_publisher_gui.JointStatePublisherGui.sliderUpdate
def sliderUpdate(self, event)
Definition: __init__.py:219
joint_state_publisher_gui.JointStatePublisherGui.randomize
def randomize(self)
Definition: __init__.py:212
joint_state_publisher_gui.JointStatePublisherGui.vlayout
vlayout
Definition: __init__.py:65
joint_state_publisher_gui.JointStatePublisherGui.randomize_event
def randomize_event(self, event)
Definition: __init__.py:209
joint_state_publisher_gui.JointStatePublisherGui.generate_grid_positions
def generate_grid_positions(self, num_items, num_rows)
Definition: __init__.py:202
joint_state_publisher_gui.JointStatePublisherGui.jsp
jsp
Definition: __init__.py:63
joint_state_publisher_gui.JointStatePublisherGui.updateSliders
def updateSliders(self)
Definition: __init__.py:165
joint_state_publisher_gui.JointStatePublisherGui.positions
positions
Definition: __init__.py:120
joint_state_publisher_gui.JointStatePublisherGui.randbutton
randbutton
Definition: __init__.py:139
joint_state_publisher_gui.JointStatePublisherGui.num_rows
num_rows
Generate sliders ###.
Definition: __init__.py:115
joint_state_publisher_gui.JointStatePublisherGui.__init__
def __init__(self, title, jsp, num_rows=0)
Definition: __init__.py:60
joint_state_publisher_gui.JointStatePublisherGui.source_update_cb
def source_update_cb(self)
Definition: __init__.py:153
joint_state_publisher_gui.JointStatePublisherGui
Definition: __init__.py:57
joint_state_publisher_gui.JointStatePublisherGui.update_sliders
def update_sliders(self)
Definition: __init__.py:168


joint_state_publisher_gui
Author(s): David V. Lu!! , Jackie Kay
autogenerated on Sat Apr 12 2025 02:38:34