38 #include <QFileDialog>
39 #include <QFormLayout>
41 #include <QHBoxLayout>
44 #include <QDoubleSpinBox>
45 #include <QMessageBox>
46 #include <QPushButton>
48 #include <QVBoxLayout>
60 : QWidget(parent), config_data_(config_data)
62 auto add_line_edit = [
this](QFormLayout* form,
const QString&
label) {
63 QLineEdit* field =
new QLineEdit(
this);
64 field->setMaximumWidth(FORM_CONTROL_WIDTH);
65 form->addRow(label, field);
69 auto add_spin_box = [
this](QFormLayout* form,
const QString&
label,
double min,
double max,
double step,
71 QDoubleSpinBox* field =
new QDoubleSpinBox(
this);
72 field->setMaximumWidth(FORM_CONTROL_WIDTH);
73 field->setRange(min, max);
74 field->setDecimals(decimals);
75 field->setSingleStep(step);
76 form->addRow(label, field);
80 auto add_combo_box = [
this](QFormLayout* form,
const QString&
label,
bool editable =
false) {
81 QComboBox* field =
new QComboBox(
this);
82 field->setEditable(editable);
83 field->setMaximumWidth(FORM_CONTROL_WIDTH);
84 form->addRow(label, field);
89 QVBoxLayout* layout =
new QVBoxLayout();
91 QGroupBox* group1 =
new QGroupBox(
"Kinematics");
92 QGroupBox* group2 =
new QGroupBox(
"OMPL Planning");
95 title_ =
new QLabel(
this);
96 QFont group_title_font(QFont().defaultFamily(), 12, QFont::Bold);
97 title_->setFont(group_title_font);
98 layout->addWidget(title_);
101 QFormLayout* form_layout =
new QFormLayout();
102 form_layout->setContentsMargins(0, 12, 0, 12);
108 kinematics_solver_field_ = add_combo_box(form_layout,
"Kinematic Solver:");
111 kinematics_resolution_field_ = add_line_edit(form_layout,
"Kin. Search Resolution:");
114 kinematics_timeout_field_ = add_line_edit(form_layout,
"Kin. Search Timeout (sec):");
117 goal_joint_tolerance_field_ = add_spin_box(form_layout,
"Goal Joint Tolerance (m|rad):", MIN_TOLERANCE, MAX_TOLERANCE,
118 STEP_TOLERANCE, DECIMALS_TOLERANCE);
121 goal_position_tolerance_field_ = add_spin_box(form_layout,
"Goal Position Tolerance (m):", MIN_TOLERANCE,
122 MAX_TOLERANCE, STEP_TOLERANCE, DECIMALS_TOLERANCE);
125 goal_orientation_tolerance_field_ = add_spin_box(form_layout,
"Goal Orientation Tolerance (rad):", MIN_TOLERANCE,
126 MAX_TOLERANCE, STEP_TOLERANCE, DECIMALS_TOLERANCE);
129 kinematics_parameters_file_field_ =
new QLineEdit(
this);
130 QPushButton* kinematics_parameters_file_button =
new QPushButton(
"...",
this);
131 kinematics_parameters_file_button->setMaximumWidth(50);
132 kinematics_parameters_file_button->setMaximumHeight(42);
133 connect(kinematics_parameters_file_button, SIGNAL(clicked()),
this, SLOT(selectKinematicsFile()));
134 QBoxLayout* kinematics_parameters_file_layout =
new QHBoxLayout(
this);
135 kinematics_parameters_file_layout->addWidget(kinematics_parameters_file_field_);
136 kinematics_parameters_file_layout->addWidget(kinematics_parameters_file_button);
137 kinematics_parameters_file_layout->setContentsMargins(0, 0, 0, 0);
138 QWidget* container =
new QWidget(
this);
139 container->setMaximumWidth(FORM_CONTROL_WIDTH);
140 container->setLayout(kinematics_parameters_file_layout);
141 form_layout->addRow(
"Kin. parameters file:", container);
143 group1->setLayout(form_layout);
147 QFormLayout* form_layout2 =
new QFormLayout();
148 form_layout2->setContentsMargins(0, 12, 0, 12);
151 default_planner_field_ = add_combo_box(form_layout2,
"Group Default Planner:");
153 group2->setLayout(form_layout2);
155 layout->addWidget(group1);
156 layout->addWidget(group2);
158 layout->setAlignment(Qt::AlignTop);
161 new_buttons_widget_ =
new QWidget();
163 QVBoxLayout* new_buttons_layout_container =
new QVBoxLayout();
164 QHBoxLayout* label_layout =
new QHBoxLayout();
165 QHBoxLayout* recommended_options =
new QHBoxLayout();
166 QHBoxLayout* advanced_options =
new QHBoxLayout();
168 QLabel* save_and_add =
new QLabel(
"Next, Add Components To Group:",
this);
169 QFont save_and_add_font(QFont().defaultFamily(), 12, QFont::Bold);
170 save_and_add->setFont(save_and_add_font);
171 label_layout->addWidget(save_and_add);
174 QLabel* add_subtitle =
new QLabel(
"Recommended: ",
this);
175 QFont add_subtitle_font(QFont().defaultFamily(), 10, QFont::Bold);
176 add_subtitle->setFont(add_subtitle_font);
177 recommended_options->addWidget(add_subtitle, 0, Qt::AlignLeft);
180 QPushButton* btn_save_chain =
new QPushButton(
"Add Kin. Chain",
this);
181 btn_save_chain->setMaximumWidth(200);
182 connect(btn_save_chain, SIGNAL(clicked()),
this, SIGNAL(saveChain()));
183 recommended_options->addWidget(btn_save_chain);
186 QPushButton* btn_save_joints =
new QPushButton(
"Add Joints",
this);
187 btn_save_joints->setMaximumWidth(200);
188 connect(btn_save_joints, SIGNAL(clicked()),
this, SIGNAL(saveJoints()));
189 recommended_options->addWidget(btn_save_joints);
192 QLabel* add_subtitle2 =
new QLabel(
"Advanced Options:",
this);
193 add_subtitle2->setFont(add_subtitle_font);
194 advanced_options->addWidget(add_subtitle2, 0, Qt::AlignLeft);
197 QPushButton* btn_save_subgroups =
new QPushButton(
"Add Subgroups",
this);
198 btn_save_subgroups->setMaximumWidth(200);
199 connect(btn_save_subgroups, SIGNAL(clicked()),
this, SIGNAL(saveSubgroups()));
200 advanced_options->addWidget(btn_save_subgroups);
203 QPushButton* btn_save_links =
new QPushButton(
"Add Links",
this);
204 btn_save_links->setMaximumWidth(200);
205 connect(btn_save_links, SIGNAL(clicked()),
this, SIGNAL(saveLinks()));
206 advanced_options->addWidget(btn_save_links);
209 new_buttons_layout_container->addLayout(label_layout);
210 new_buttons_layout_container->addLayout(recommended_options);
211 new_buttons_layout_container->addLayout(advanced_options);
214 new_buttons_widget_->setLayout(new_buttons_layout_container);
215 layout->addWidget(new_buttons_widget_);
218 layout->addItem(
new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
221 QHBoxLayout* controls_layout =
new QHBoxLayout();
224 btn_delete_ =
new QPushButton(
"&Delete Group",
this);
226 connect(
btn_delete_, SIGNAL(clicked()),
this, SIGNAL(deleteGroup()));
228 controls_layout->setAlignment(
btn_delete_, Qt::AlignRight);
231 controls_layout->addItem(
new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
234 btn_save_ =
new QPushButton(
"&Save",
this);
236 connect(
btn_save_, SIGNAL(clicked()),
this, SIGNAL(save()));
238 controls_layout->setAlignment(
btn_save_, Qt::AlignRight);
241 QPushButton* btn_cancel =
new QPushButton(
"&Cancel",
this);
242 btn_cancel->setMaximumWidth(200);
243 connect(btn_cancel, SIGNAL(clicked()),
this, SIGNAL(
cancelEditing()));
244 controls_layout->addWidget(btn_cancel);
245 controls_layout->setAlignment(btn_cancel, Qt::AlignRight);
248 layout->addLayout(controls_layout);
251 this->setLayout(layout);
262 auto set_spin_box_value = [](
double&
value,
const double defaultValue, QDoubleSpinBox* widget) {
264 value = defaultValue;
266 widget->setValue(value);
269 auto set_line_edit_value = [](
double&
value,
const double defaultValue, QLineEdit* widget) {
271 value = defaultValue;
273 widget->setText(QString::number(value));
276 GroupMetaData& group_metadata =
config_data_->group_meta_data_[group_name];
286 set_spin_box_value(group_metadata.goal_joint_tolerance_,
291 set_spin_box_value(group_metadata.goal_position_tolerance_,
296 set_spin_box_value(group_metadata.goal_orientation_tolerance_,
301 std::string kin_solver = group_metadata.kinematics_solver_;
304 if (kin_solver.empty())
313 QMessageBox::warning(
this,
"Missing Kinematic Solvers",
314 QString(
"Unable to find the kinematic solver '")
315 .
append(kin_solver.c_str())
316 .append(
"'. Trying running rosmake for this package. Until fixed, this setting will be "
317 "lost the next time the MoveIt configuration files are generated"));
328 std::string default_planner = group_metadata.default_planner_;
331 if (default_planner.empty())
333 default_planner =
"None";
339 QMessageBox::warning(
this,
"Missing Default Planner",
340 QString(
"Unable to find the default planner '%1'").arg(default_planner.c_str()));
354 static bool has_loaded =
false;
368 std::unique_ptr<pluginlib::ClassLoader<kinematics::KinematicsBase>> loader;
371 loader = std::make_unique<pluginlib::ClassLoader<kinematics::KinematicsBase>>(
"moveit_core",
372 "kinematics::KinematicsBase");
376 QMessageBox::warning(
this,
"Missing Kinematic Solvers",
377 "Exception while creating class loader for kinematic "
384 const std::vector<std::string>& classes = loader->getDeclaredClasses();
389 QMessageBox::warning(
this,
"Missing Kinematic Solvers",
390 "No MoveIt-compatible kinematics solvers found. Try "
391 "installing moveit_kinematics (sudo apt-get install "
392 "ros-${ROS_DISTRO}-moveit-kinematics)");
397 for (
const std::string& kinematics_plugin_name : classes)
402 std::vector<OMPLPlannerDescription> planners =
config_data_->getOMPLPlanners();
403 for (OMPLPlannerDescription& planner : planners)
405 std::string planner_name = planner.name_;
412 QString filename = QFileDialog::getOpenFileName(
this,
"Select a parameter file",
"",
"YAML files (*.yaml)");
414 if (filename.isEmpty())
419 std::string package_name;
420 std::string relative_filename;
422 config_data_->extractPackageNameFromPath(filename.toStdString(), package_name, relative_filename);
424 QString lookup_path = filename;
427 lookup_path = QString(
"$(find %1)/%2").arg(package_name.c_str()).arg(relative_filename.c_str());