41 #include <moveit_msgs/JointLimits.h>
43 #include <QApplication>
44 #include <QDoubleValidator>
45 #include <QFormLayout>
47 #include <QHBoxLayout>
50 #include <QMessageBox>
51 #include <QPushButton>
52 #include <QScrollArea>
53 #include <QStackedWidget>
55 #include <QTableWidget>
56 #include <QTreeWidget>
57 #include <QTreeWidgetItem>
58 #include <QVBoxLayout>
72 QVBoxLayout* layout =
new QVBoxLayout();
74 layout->setAlignment(Qt::AlignTop);
77 this->setWindowTitle(
"Controller Configuration");
82 "Configure controllers to be used by MoveIt's controller manager(s) to operate the robot's physical hardware",
84 layout->addWidget(header);
87 controllers_tree_widget_ = createContentsWidget();
92 connect(joints_widget_, SIGNAL(doneEditing()),
this, SLOT(saveJointsScreen()));
93 connect(joints_widget_, SIGNAL(previewSelected(std::vector<std::string>)),
this,
94 SLOT(previewSelectedJoints(std::vector<std::string>)));
97 joint_groups_widget_ =
100 connect(joint_groups_widget_, SIGNAL(doneEditing()),
this, SLOT(saveJointsGroupsScreen()));
101 connect(joint_groups_widget_, SIGNAL(previewSelected(std::vector<std::string>)),
this,
102 SLOT(previewSelectedGroup(std::vector<std::string>)));
108 connect(controller_edit_widget_, SIGNAL(
save()),
this, SLOT(saveControllerScreenEdit()));
109 connect(controller_edit_widget_, SIGNAL(
saveJoints()),
this, SLOT(saveControllerScreenJoints()));
110 connect(controller_edit_widget_, SIGNAL(
saveJointsGroups()),
this, SLOT(saveControllerScreenGroups()));
113 stacked_widget_ =
new QStackedWidget(
this);
114 stacked_widget_->addWidget(controllers_tree_widget_);
115 stacked_widget_->addWidget(joints_widget_);
116 stacked_widget_->addWidget(controller_edit_widget_);
117 stacked_widget_->addWidget(joint_groups_widget_);
118 layout->addWidget(stacked_widget_);
120 this->setLayout(layout);
129 QWidget* content_widget =
new QWidget(
this);
132 QVBoxLayout* layout =
new QVBoxLayout(
this);
134 QHBoxLayout* upper_controls_layout =
new QHBoxLayout();
137 QPushButton* btn_add_default =
138 new QPushButton(
"Auto Add &FollowJointsTrajectory \n Controllers For Each Planning Group",
this);
139 btn_add_default->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
140 btn_add_default->setMaximumWidth(600);
142 upper_controls_layout->addWidget(btn_add_default);
143 upper_controls_layout->setAlignment(btn_add_default, Qt::AlignLeft);
146 layout->addLayout(upper_controls_layout);
152 labels <<
"Controller"
153 <<
"Controller Type";
167 QLabel* expand_controls =
new QLabel(
this);
168 expand_controls->setText(
"<a href='expand'>Expand All</a> <a href='contract'>Collapse All</a>");
169 connect(expand_controls, SIGNAL(linkActivated(
const QString)),
this, SLOT(
alterTree(
const QString)));
173 controls_layout_->addItem(
new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
176 btn_delete_ =
new QPushButton(
"&Delete Controller",
this);
177 btn_delete_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
184 btn_add_ =
new QPushButton(
"&Add Controller",
this);
191 btn_edit_ =
new QPushButton(
"&Edit Selected",
this);
201 content_widget->setLayout(layout);
203 return content_widget;
235 const QFont top_level_font(QFont().defaultFamily(), 11, QFont::Bold);
236 const QFont type_font(QFont().defaultFamily(), 11, QFont::Normal, QFont::StyleItalic);
238 QTreeWidgetItem* controller;
240 controller =
new QTreeWidgetItem();
243 controller->setText(0, controller_it.
name_.c_str());
244 controller->setFont(0, top_level_font);
245 controller->setData(0, Qt::UserRole, QVariant::fromValue(0));
248 controller->setText(1, controller_it.
type_.c_str());
249 controller->setFont(1, type_font);
250 controller->setData(1, Qt::UserRole, QVariant::fromValue(4));
253 if (!controller_it.
joints_.empty())
256 QTreeWidgetItem* joints =
new QTreeWidgetItem(controller);
257 joints->setText(0,
"Joints");
258 joints->setFont(0, type_font);
259 joints->setData(0, Qt::UserRole, QVariant::fromValue(1));
260 controller->addChild(joints);
263 for (
const std::string& joint : controller_it.
joints_)
265 QTreeWidgetItem* joint_item =
new QTreeWidgetItem(joints);
266 joint_item->setData(0, Qt::UserRole, QVariant::fromValue(2));
269 joint_item->setText(0, joint.c_str());
270 joints->addChild(joint_item);
292 const moveit::core::RobotModelConstPtr& model =
config_data_->getRobotModel();
295 const std::vector<std::string>& joints = model->getJointModelNames();
299 QMessageBox::critical(
this,
"Error Loading",
"No joints found for robot model");
311 QString(
"Edit '").
append(QString::fromUtf8(this_controller->
name_.c_str())).append(
"' Joint Collection"));
323 std::vector<std::string> groups;
329 groups.push_back(
group.name_);
340 QString(
"Edit '").
append(QString::fromUtf8(this_controller->
name_.c_str())).append(
"' Joints groups collection"));
353 if (controller_name.empty())
361 int type = item->data(0, Qt::UserRole).value<
int>();
363 controller_name = item->text(0).toUtf8().constData();
367 if (QMessageBox::question(
368 this,
"Confirm Controller Deletion",
369 QString(
"Are you sure you want to delete the controller '").
append(controller_name.c_str()).append(
" ?"),
370 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
412 QMessageBox::warning(
this,
"Error adding contollers",
"No Planning Groups configured!");
424 if (this_controller ==
nullptr)
453 if (editing && editing->
joints_.empty())
479 for (
const std::string& joint : joints)
510 for (
const std::string&
group : groups)
523 int type = selected_item->data(0, Qt::UserRole).value<
int>();
585 searched_controller->
joints_.clear();
610 searched_controller->
joints_.clear();
618 const std::vector<const moveit::core::JointModel*>& joint_models = joint_model_group->
getActiveJointModels();
625 searched_controller->
joints_.push_back(joint->getName());
661 std::smatch invalid_name_match;
662 std::regex invalid_reg_ex(
"[^a-z|^0-9|^_]");
665 if (controller_name.empty() || std::regex_search(controller_name, invalid_name_match, invalid_reg_ex))
667 QMessageBox::warning(
this,
"Error Saving",
"Invalid controller name");
679 for (
const auto& controller :
config_data_->getControllers())
681 if (controller.name_.compare(controller_name) == 0)
684 if (&controller != searched_controller)
686 QMessageBox::warning(
this,
"Error Saving",
"A controller already exists with that name!");
695 if (searched_controller ==
nullptr)
698 new_controller.
name_ = controller_name;
699 new_controller.
type_ = controller_type;
707 const std::string old_controller_name = searched_controller->
name_;
710 searched_controller->
name_ = controller_name;
711 searched_controller->
type_ = controller_type;
729 QTreeWidgetItem* controller_item;
738 int type = item->data(0, Qt::UserRole).value<
int>();
743 controller_item = item->parent()->parent();
756 controller_item = item->parent();
780 QMessageBox::critical(
this,
"Error Loading",
"An internal error has occured while loading.");
830 if (link.contains(
"expand"))
839 if (selected_items.empty())