moveit2
The MoveIt Motion Planning Framework for ROS 2.
controller_edit_widget.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2018, Mohamad Ayman.
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  * * The name of Mohamad Ayman 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 
34 /* Author: Mohamad Ayman */
35 
36 #include <QComboBox>
37 #include <QFormLayout>
38 #include <QGroupBox>
39 #include <QHBoxLayout>
40 #include <QLabel>
41 #include <QLineEdit>
42 #include <QMessageBox>
43 #include <QPushButton>
44 #include <QString>
45 #include <QVBoxLayout>
47 
48 namespace moveit_setup
49 {
50 namespace controllers
51 {
52 // ******************************************************************************************
53 // ControllerEditWidget constructor, create controller edit screen GUI
54 // ******************************************************************************************
55 ControllerEditWidget::ControllerEditWidget(QWidget* parent, const FieldPointers& additional_fields)
56  : QWidget(parent), additional_fields_(additional_fields)
57 {
58  // Basic widget container
59  QVBoxLayout* layout = new QVBoxLayout();
60 
61  QGroupBox* controller_options_group = new QGroupBox("Controller Options");
62 
63  // Label ------------------------------------------------
64  title_ = new QLabel(this); // specify the title from the parent widget
65  QFont group_title_font(QFont().defaultFamily(), 12, QFont::Bold);
66  title_->setFont(group_title_font);
67  layout->addWidget(title_);
68 
69  QFormLayout* form_layout = new QFormLayout();
70  form_layout->setContentsMargins(0, 15, 0, 15);
71 
72  // Controller Name
73  controller_name_field_ = new QLineEdit(this);
74  controller_name_field_->setMaximumWidth(400);
75  form_layout->addRow("Controller Name:", controller_name_field_);
76 
77  // Controller Type
78  controller_type_field_ = new QComboBox(this);
79  controller_type_field_->setEditable(false);
80  controller_type_field_->setMaximumWidth(400);
81  connect(controller_type_field_, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
82  form_layout->addRow("Controller Type:", controller_type_field_);
83 
84  for (const auto& field : additional_fields_)
85  {
86  QLineEdit* input = new QLineEdit(this);
87  input->setMaximumWidth(400);
88  form_layout->addRow(field->display_name_.c_str(), input);
89  additional_fields_inputs_.push_back(input);
90  }
91 
92  controller_options_group->setLayout(form_layout);
93 
94  layout->addWidget(controller_options_group);
95 
96  layout->setAlignment(Qt::AlignTop);
97 
98  // New Controller Options ---------------------------------------------------------
99  new_buttons_widget_ = new QWidget();
100  QVBoxLayout* new_buttons_layout = new QVBoxLayout();
101 
102  QLabel* save_and_add = new QLabel("Next, Add Components To Controller:", this);
103  QFont save_and_add_font(QFont().defaultFamily(), 12, QFont::Bold);
104  save_and_add->setFont(save_and_add_font);
105  new_buttons_layout->addWidget(save_and_add);
106 
107  QLabel* add_subtitle = new QLabel("Recommended: ", this);
108  QFont add_subtitle_font(QFont().defaultFamily(), 10, QFont::Bold);
109  add_subtitle->setFont(add_subtitle_font);
110  new_buttons_layout->addWidget(add_subtitle);
111 
112  // Save and add groups
113  QPushButton* btn_save_groups_joints = new QPushButton("Add Planning Group Joints", this);
114  btn_save_groups_joints->setMaximumWidth(200);
115  connect(btn_save_groups_joints, SIGNAL(clicked()), this, SIGNAL(saveJointsGroups()));
116  new_buttons_layout->addWidget(btn_save_groups_joints);
117 
118  QLabel* add_subtitle2 = new QLabel("Advanced Options:", this);
119  add_subtitle2->setFont(add_subtitle_font);
120  new_buttons_layout->addWidget(add_subtitle2);
121 
122  // Save and add joints
123  QPushButton* btn_save_joints = new QPushButton("Add Individual Joints", this);
124  btn_save_joints->setMaximumWidth(200);
125  connect(btn_save_joints, SIGNAL(clicked()), this, SIGNAL(saveJoints()));
126  new_buttons_layout->addWidget(btn_save_joints);
127 
128  // Create widget and add to main layout
129  new_buttons_widget_->setLayout(new_buttons_layout);
130  layout->addWidget(new_buttons_widget_);
131 
132  // Vertical Spacer
133  layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
134 
135  // Bottom Controls ---------------------------------------------------------
136  QHBoxLayout* controls_layout = new QHBoxLayout();
137 
138  // Delete
139  btn_delete_ = new QPushButton("&Delete Controller", this);
140  btn_delete_->setMaximumWidth(200);
141  connect(btn_delete_, SIGNAL(clicked()), this, SIGNAL(deleteController()));
142  controls_layout->addWidget(btn_delete_);
143  controls_layout->setAlignment(btn_delete_, Qt::AlignRight);
144 
145  // Horizontal Spacer
146  controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
147 
148  // Save
149  btn_save_ = new QPushButton("&Save", this);
150  btn_save_->setMaximumWidth(200);
151  connect(btn_save_, SIGNAL(clicked()), this, SIGNAL(save()));
152  controls_layout->addWidget(btn_save_);
153  controls_layout->setAlignment(btn_save_, Qt::AlignRight);
154 
155  // Cancel
156  QPushButton* btn_cancel = new QPushButton("&Cancel", this);
157  btn_cancel->setMaximumWidth(200);
158  connect(btn_cancel, SIGNAL(clicked()), this, SIGNAL(cancelEditing()));
159  controls_layout->addWidget(btn_cancel);
160  controls_layout->setAlignment(btn_cancel, Qt::AlignRight);
161 
162  // Add layout
163  layout->addLayout(controls_layout);
164 
165  // Finish Layout --------------------------------------------------
166  this->setLayout(layout);
167 }
168 
169 // ******************************************************************************************
170 // Set the fields with previous values
171 // ******************************************************************************************
172 void ControllerEditWidget::setSelected(const std::string& controller_name, const ControllerInfo* searched_controller)
173 {
174  controller_name_field_->setText(QString(controller_name.c_str()));
175  if (searched_controller != nullptr)
176  {
177  const std::string controller_type = searched_controller->type_;
178  int type_index = controller_type_field_->findText(controller_type.c_str());
179 
180  // Set the controller type combo box
181  if (type_index == -1)
182  {
183  QMessageBox::warning(this, "Missing Controller Type", QString("Setting controller type to the default value"));
184  return;
185  }
186  else
187  {
188  controller_type_field_->setCurrentIndex(type_index);
189  }
190 
191  for (unsigned int i = 0; i < additional_fields_.size(); i++)
192  {
193  std::string key = additional_fields_[i]->parameter_name_;
194  const auto& it = searched_controller->parameters_.find(key);
195  if (it != searched_controller->parameters_.end())
196  {
197  additional_fields_inputs_[i]->setText(it->second.c_str());
198  }
199  }
200  }
201  else
202  {
203  controller_type_field_->setCurrentIndex(0);
204  }
205 }
206 
207 // ******************************************************************************************
208 // Populate the combo dropdown box with controllers types
209 // ******************************************************************************************
210 void ControllerEditWidget::loadControllersTypesComboBox(const std::vector<std::string>& controller_types)
211 {
212  // Only load this combo box once
213  if (has_loaded_)
214  return;
215  has_loaded_ = true;
216 
217  // Remove all old items
218  controller_type_field_->clear();
219 
220  // Loop through all controller types and add to combo box
221  for (const std::string& type : controller_types)
222  controller_type_field_->addItem(type.c_str());
223 }
224 
226 {
227  btn_delete_->hide();
228 }
229 
231 {
232  btn_save_->hide();
233 }
234 
236 {
237  new_buttons_widget_->hide();
238 }
239 
241 {
242  btn_delete_->show();
243 }
244 
246 {
247  btn_save_->show();
248 }
249 
251 {
252  new_buttons_widget_->show();
253 }
254 
255 void ControllerEditWidget::setTitle(const QString& title)
256 {
257  title_->setText(title);
258 }
259 
261 {
262  return controller_name_field_->text().trimmed().toStdString();
263 }
264 
266 {
267  return controller_type_field_->currentText().toStdString();
268 }
269 
270 std::map<std::string, std::string> ControllerEditWidget::getAdditionalParameters()
271 {
272  std::map<std::string, std::string> parameters;
273  for (unsigned int i = 0; i < additional_fields_.size(); i++)
274  {
275  std::string key = additional_fields_[i]->parameter_name_;
276  std::string value = additional_fields_inputs_[i]->text().trimmed().toStdString();
277  parameters[key] = value;
278  }
279  return parameters;
280 }
281 
282 void ControllerEditWidget::typeChanged(int /*index*/)
283 {
284  std::string controller_type = getControllerType();
285  for (unsigned int i = 0; i < additional_fields_.size(); i++)
286  {
287  std::string new_value = additional_fields_[i]->getDefaultValue(controller_type);
288  additional_fields_inputs_[i]->setText(new_value.c_str());
289  }
290 }
291 
292 } // namespace controllers
293 } // namespace moveit_setup
ControllerEditWidget(QWidget *parent, const FieldPointers &additional_fields)
Constructor.
void cancelEditing()
Event sent when user presses cancel button.
void save()
Button event for just saving, when in edit mode.
void saveJoints()
Button event for new groups, progressing to adding joints.
std::map< std::string, std::string > getAdditionalParameters()
Get the names and values for any additional parameters.
void deleteController()
Event sent when delete is being requested for controller.
void setSelected(const std::string &controller_name, const ControllerInfo *info)
Set the previous data.
void saveJointsGroups()
Button event for new groups, progressing to adding subgroups.
void loadControllersTypesComboBox(const std::vector< std::string > &controller_types)
Populate the combo dropdown box with controllers types.
void setTitle(const QString &title)
Set widget title.
std::vector< std::shared_ptr< AdditionalControllerField > > FieldPointers
Convenience alias.
Definition: controllers.hpp:77
std::map< std::string, std::string > parameters_