moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
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
48namespace moveit_setup
49{
50namespace 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 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// ******************************************************************************************
159QTreeWidgetItem* 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// ******************************************************************************************
175void 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// ******************************************************************************************
184void 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// ******************************************************************************************
196void 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// ******************************************************************************************
208void KinematicChainWidget::alterTree(const QString& link)
209{
210 if (link.contains("expand"))
211 {
212 link_tree_->expandAll();
213 }
214 else
215 {
216 link_tree_->collapseAll();
217 }
218}
219
220// ******************************************************************************************
221// Highlight the currently selected link
222// ******************************************************************************************
223void KinematicChainWidget::itemSelected()
224{
225 QTreeWidgetItem* item = link_tree_->currentItem();
226 if (item != nullptr)
227 {
228 rviz_panel_->unhighlightAll();
229
230 std::string name = item->text(0).toStdString();
231
232 // Don't try to highlight empty links!
233 if (name.empty())
234 return;
235
236 // Check that item is not empty
237 rviz_panel_->highlightLink(item->text(0).toStdString(), QColor(255, 0, 0));
238 }
239}
240} // namespace srdf_setup
241} // namespace moveit_setup
void highlightLink(const std::string &link_name, const QColor &color)
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