moveit2
The MoveIt Motion Planning Framework for ROS 2.
kinematic_chain_widget.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Dave Coleman */
36 
37 #include <QVBoxLayout>
38 #include <QHBoxLayout>
39 #include <QGroupBox>
40 #include <QPushButton>
41 #include <QGridLayout>
42 #include <QLineEdit>
43 #include <QMessageBox>
44 #include <QLabel>
45 #include <QTreeWidget>
47 
48 namespace moveit_setup
49 {
50 namespace srdf_setup
51 {
52 // ******************************************************************************************
53 // Constructor
54 // ******************************************************************************************
56  : QWidget(parent), rviz_panel_(rviz_panel)
57 {
58  // Basic widget container
59  QVBoxLayout* layout = new QVBoxLayout();
60 
61  // Label ------------------------------------------------
62  title_ = new QLabel("", this); // specify the title from the parent widget
63  QFont group_title_font(QFont().defaultFamily(), 12, QFont::Bold);
64  title_->setFont(group_title_font);
65  layout->addWidget(title_);
66 
67  // Create link tree ------------------------------------------------------
68  link_tree_ = new QTreeWidget(this);
69  link_tree_->setHeaderLabel("Robot Links");
70  connect(link_tree_, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelected()));
71  layout->addWidget(link_tree_);
72 
73  // Create Grid Layout for form --------------------------------------------
74  QGridLayout* form_grid = new QGridLayout();
75  form_grid->setContentsMargins(20, 20, 20, 20); // left top right bottom
76 
77  // Row 1: Base Link
78  QLabel* base_link_label = new QLabel("Base Link", this);
79  form_grid->addWidget(base_link_label, 0, 0, Qt::AlignRight);
80 
81  base_link_field_ = new QLineEdit(this);
82  base_link_field_->setMinimumWidth(300);
83  form_grid->addWidget(base_link_field_, 0, 1, Qt::AlignLeft);
84 
85  QPushButton* btn_base_link = new QPushButton("Choose Selected", this);
86  connect(btn_base_link, SIGNAL(clicked()), this, SLOT(baseLinkTreeClick()));
87  form_grid->addWidget(btn_base_link, 0, 2, Qt::AlignLeft);
88 
89  // Row 2: Tip Link
90  QLabel* tip_link_label = new QLabel("Tip Link", this);
91  form_grid->addWidget(tip_link_label, 1, 0, Qt::AlignRight);
92 
93  tip_link_field_ = new QLineEdit(this);
94  tip_link_field_->setMinimumWidth(300);
95  form_grid->addWidget(tip_link_field_, 1, 1, Qt::AlignLeft);
96 
97  QPushButton* btn_tip_link = new QPushButton("Choose Selected", this);
98  connect(btn_tip_link, SIGNAL(clicked()), this, SLOT(tipLinkTreeClick()));
99  form_grid->addWidget(btn_tip_link, 1, 2, Qt::AlignLeft);
100 
101  // Add form grid layout
102  layout->addLayout(form_grid);
103 
104  // Bottom Controls ---------------------------------------------------------
105  QHBoxLayout* controls_layout = new QHBoxLayout();
106 
107  // Expand/Contract controls
108  QLabel* expand_controls = new QLabel(this);
109  expand_controls->setText("<a href='expand'>Expand All</a> <a href='contract'>Collapse All</a>");
110  connect(expand_controls, SIGNAL(linkActivated(const QString)), this, SLOT(alterTree(const QString)));
111  controls_layout->addWidget(expand_controls);
112 
113  // Spacer
114  controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
115 
116  // Save
117  QPushButton* btn_save = new QPushButton("&Save", this);
118  btn_save->setMaximumWidth(200);
119  connect(btn_save, SIGNAL(clicked()), this, SIGNAL(doneEditing()));
120  controls_layout->addWidget(btn_save);
121  controls_layout->setAlignment(btn_save, Qt::AlignRight);
122 
123  // Cancel
124  QPushButton* btn_cancel = new QPushButton("&Cancel", this);
125  btn_cancel->setMaximumWidth(200);
126  connect(btn_cancel, SIGNAL(clicked()), this, SIGNAL(cancelEditing()));
127  controls_layout->addWidget(btn_cancel);
128  controls_layout->setAlignment(btn_cancel, Qt::AlignRight);
129 
130  // Add layout
131  layout->addLayout(controls_layout);
132 
133  // Finish Layout --------------------------------------------------
134  this->setLayout(layout);
135 
136  // Remember that we have no loaded the chains yet
137  kinematic_chain_loaded_ = false;
138 }
139 
140 // ******************************************************************************************
141 // Load robot links into tree
142 // ******************************************************************************************
144 {
145  // Only load the kinematic chain once
146  if (kinematic_chain_loaded_)
147  return;
148 
149  QTreeWidgetItem* root_item = addLinkChildRecursive(nullptr, link_name_tree);
150  link_tree_->addTopLevelItem(root_item);
151 
152  // Remember that we have loaded the chain
153  kinematic_chain_loaded_ = true;
154 }
155 
156 // ******************************************************************************************
157 //
158 // ******************************************************************************************
159 QTreeWidgetItem* KinematicChainWidget::addLinkChildRecursive(QTreeWidgetItem* parent, const LinkNameTree& link)
160 {
161  QTreeWidgetItem* new_item = new QTreeWidgetItem(parent);
162  new_item->setText(0, link.data.c_str());
163 
164  for (const LinkNameTree& child : link.children)
165  {
166  QTreeWidgetItem* new_child = addLinkChildRecursive(new_item, child);
167  new_item->addChild(new_child);
168  }
169  return new_item;
170 }
171 
172 // ******************************************************************************************
173 // Set the link field with previous value
174 // ******************************************************************************************
175 void KinematicChainWidget::setSelected(const std::string& base_link, const std::string& tip_link)
176 {
177  base_link_field_->setText(QString(base_link.c_str()));
178  tip_link_field_->setText(QString(tip_link.c_str()));
179 }
180 
181 // ******************************************************************************************
182 // Choose the base link
183 // ******************************************************************************************
184 void KinematicChainWidget::baseLinkTreeClick()
185 {
186  QTreeWidgetItem* item = link_tree_->currentItem();
187  if (item != nullptr)
188  {
189  base_link_field_->setText(item->text(0));
190  }
191 }
192 
193 // ******************************************************************************************
194 // Choose the tip link
195 // ******************************************************************************************
196 void KinematicChainWidget::tipLinkTreeClick()
197 {
198  QTreeWidgetItem* item = link_tree_->currentItem();
199  if (item != nullptr)
200  {
201  tip_link_field_->setText(item->text(0));
202  }
203 }
204 
205 // ******************************************************************************************
206 // Expand/Collapse Tree
207 // ******************************************************************************************
208 void KinematicChainWidget::alterTree(const QString& link)
209 {
210  if (link.contains("expand"))
211  link_tree_->expandAll();
212  else
213  link_tree_->collapseAll();
214 }
215 
216 // ******************************************************************************************
217 // Highlight the currently selected link
218 // ******************************************************************************************
219 void KinematicChainWidget::itemSelected()
220 {
221  QTreeWidgetItem* item = link_tree_->currentItem();
222  if (item != nullptr)
223  {
224  rviz_panel_->unhighlightAll();
225 
226  std::string name = item->text(0).toStdString();
227 
228  // Don't try to highlight empty links!
229  if (name.empty())
230  return;
231 
232  // Check that item is not empty
233  rviz_panel_->highlightLink(item->text(0).toStdString(), QColor(255, 0, 0));
234  }
235 }
236 } // namespace srdf_setup
237 } // namespace moveit_setup
void highlightLink(const std::string &link_name, const QColor &color)
Definition: rviz_panel.hpp:96
QTreeWidgetItem * addLinkChildRecursive(QTreeWidgetItem *parent, const LinkNameTree &link)
KinematicChainWidget(QWidget *parent, RVizPanel *rviz_panel)
Constructor.
void doneEditing()
Event sent when this widget is done making data changes and parent widget can save.
void cancelEditing()
Event sent when user presses cancel button.
void setAvailable(const LinkNameTree &link_name_tree)
Loads the available data list.
void setSelected(const std::string &base_link, const std::string &tip_link)
Set the link field with previous value.
std::vector< LinkNameTree > children
name
Definition: setup.py:7