ros_controllers_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 // SA
37 #include "ros_controllers_widget.h"
38 #include <moveit_msgs/JointLimits.h>
39 // Qt
40 #include <QFormLayout>
41 #include <QMessageBox>
42 #include <QDoubleValidator>
43 #include <QTreeWidgetItem>
44 #include <QApplication>
45 
46 #include <regex>
48 
49 namespace moveit_ros_control
50 {
51 // ******************************************************************************************
52 // Outer User Interface for MoveIt Configuration Assistant
53 // ******************************************************************************************
54 ROSControllersWidget::ROSControllersWidget(QWidget* parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
55  : SetupScreenWidget(parent), config_data_(config_data)
56 {
57  // Basic widget container
58  QVBoxLayout* layout = new QVBoxLayout();
59 
60  layout->setAlignment(Qt::AlignTop);
61 
62  // Title
63  this->setWindowTitle("ROS Control Controllers"); // title of window
64 
65  // Top Header Area ------------------------------------------------
67  "Setup ROS Controllers", "Configure MoveIt! to work with ROS Control to control the robot's physical hardware",
68  this);
69  layout->addWidget(header);
70 
71  // Tree Box ----------------------------------------------------------------------
73 
74  // Joints edit widget
75  joints_widget_ = new moveit_setup_assistant::DoubleListWidget(this, config_data_, "Joint Collection", "Joint");
76  connect(joints_widget_, SIGNAL(cancelEditing()), this, SLOT(cancelEditing()));
77  connect(joints_widget_, SIGNAL(doneEditing()), this, SLOT(saveJointsScreen()));
78  connect(joints_widget_, SIGNAL(previewSelected(std::vector<std::string>)), this,
79  SLOT(previewSelectedJoints(std::vector<std::string>)));
80 
81  // Joints Groups Widget
83  new moveit_setup_assistant::DoubleListWidget(this, config_data_, "Group Joints Collection", "Group");
84  connect(joint_groups_widget_, SIGNAL(cancelEditing()), this, SLOT(cancelEditing()));
85  connect(joint_groups_widget_, SIGNAL(doneEditing()), this, SLOT(saveJointsGroupsScreen()));
86  connect(joint_groups_widget_, SIGNAL(previewSelected(std::vector<std::string>)), this,
87  SLOT(previewSelectedGroup(std::vector<std::string>)));
88 
89  // Controller Edit Widget
91  connect(controller_edit_widget_, SIGNAL(cancelEditing()), this, SLOT(cancelEditing()));
92  connect(controller_edit_widget_, SIGNAL(deleteController()), this, SLOT(deleteController()));
93  connect(controller_edit_widget_, SIGNAL(save()), this, SLOT(saveControllerScreenEdit()));
94  connect(controller_edit_widget_, SIGNAL(saveJoints()), this, SLOT(saveControllerScreenJoints()));
95  connect(controller_edit_widget_, SIGNAL(saveJointsGroups()), this, SLOT(saveControllerScreenGroups()));
96 
97  // Combine into stack
98  stacked_layout_ = new QStackedLayout(this);
99  stacked_layout_->addWidget(controllers_tree_widget_); // screen index 0
100  stacked_layout_->addWidget(joints_widget_); // screen index 1
101  stacked_layout_->addWidget(controller_edit_widget_); // screen index 2
102  stacked_layout_->addWidget(joint_groups_widget_); // screen index 3
103 
104  // Finish GUI -----------------------------------------------------------
105 
106  // Create Widget wrapper for layout
107  QWidget* stacked_layout_widget = new QWidget(this);
108  stacked_layout_widget->setLayout(stacked_layout_);
109 
110  layout->addWidget(stacked_layout_widget);
111 
112  this->setLayout(layout);
113 }
114 
115 // ******************************************************************************************
116 // Create the main tree view widget
117 // ******************************************************************************************
119 {
120  // Main widget
121  QWidget* content_widget = new QWidget(this);
122 
123  // Basic widget container
124  QVBoxLayout* layout = new QVBoxLayout(this);
125 
126  QHBoxLayout* upper_controls_layout = new QHBoxLayout();
127 
128  // Add default controller
129  QPushButton* btn_add_default =
130  new QPushButton("Auto Add &FollowJointsTrajectory \n Controllers For Each Planning Group", this);
131  btn_add_default->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
132  btn_add_default->setMaximumWidth(600);
133  connect(btn_add_default, SIGNAL(clicked()), this, SLOT(addDefaultControllers()));
134  upper_controls_layout->addWidget(btn_add_default);
135  upper_controls_layout->setAlignment(btn_add_default, Qt::AlignLeft);
136 
137  // Add Controls to layout
138  layout->addLayout(upper_controls_layout);
139 
140  // Tree Box ----------------------------------------------------------------------
141  controllers_tree_ = new QTreeWidget(this);
142  controllers_tree_->setColumnCount(2);
143  QStringList labels;
144  labels << "Controller"
145  << "Controller Type";
146  controllers_tree_->setHeaderLabels(labels);
147  controllers_tree_->setColumnWidth(0, 250);
148  connect(controllers_tree_, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(editSelected()));
149  connect(controllers_tree_, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this,
150  SLOT(previewSelected(QTreeWidgetItem*, int)));
151  connect(controllers_tree_, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
152  layout->addWidget(controllers_tree_);
153 
154  // Bottom Controls -------------------------------------------------------------
155 
156  controls_layout_ = new QHBoxLayout();
157 
158  // Expand/Contract controls
159  QLabel* expand_controls = new QLabel(this);
160  expand_controls->setText("<a href='expand'>Expand All</a> <a href='contract'>Collapse All</a>");
161  connect(expand_controls, SIGNAL(linkActivated(const QString)), this, SLOT(alterTree(const QString)));
162  controls_layout_->addWidget(expand_controls);
163 
164  // Spacer
165  QWidget* spacer = new QWidget(this);
166  spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
167  controls_layout_->addWidget(spacer);
168 
169  // Delete
170  btn_delete_ = new QPushButton("&Delete Controller", this);
171  btn_delete_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
172  btn_delete_->setMaximumWidth(200);
173  connect(btn_delete_, SIGNAL(clicked()), this, SLOT(deleteController()));
174  controls_layout_->addWidget(btn_delete_);
175  controls_layout_->setAlignment(btn_delete_, Qt::AlignRight);
176 
177  // Add Controller Button
178  btn_add_ = new QPushButton("&Add Controller", this);
179  btn_add_->setMaximumWidth(300);
180  connect(btn_add_, SIGNAL(clicked()), this, SLOT(addController()));
181  controls_layout_->addWidget(btn_add_);
182  controls_layout_->setAlignment(btn_add_, Qt::AlignRight);
183 
184  // Edit
185  btn_edit_ = new QPushButton("&Edit Selected", this);
186  btn_edit_->setMaximumWidth(300);
187  connect(btn_edit_, SIGNAL(clicked()), this, SLOT(editSelected()));
188  controls_layout_->addWidget(btn_edit_);
189  controls_layout_->setAlignment(btn_edit_, Qt::AlignRight);
190 
191  // Add Controls to layout
192  layout->addLayout(controls_layout_);
193 
194  // Set layout
195  content_widget->setLayout(layout);
196 
197  return content_widget;
198 }
199 
200 // ******************************************************************************************
201 // Displays data in the ros_controllers_config_ data structure into a QtTableWidget
202 // ******************************************************************************************
204 {
205  // Disable Tree
206  controllers_tree_->setUpdatesEnabled(false); // prevent table from updating until we are completely done
207  controllers_tree_->setDisabled(true); // make sure we disable it so that the cellChanged event is not called
208  controllers_tree_->clear(); // reset the tree
209 
210  // Display all controllers by looping through them
211  for (std::vector<moveit_setup_assistant::ROSControlConfig>::iterator controller_it =
212  config_data_->getROSControllers().begin();
213  controller_it != config_data_->getROSControllers().end(); ++controller_it)
214  {
215  loadToControllersTree(*controller_it);
216  }
217 
218  // Reenable Tree
219  controllers_tree_->setUpdatesEnabled(true); // prevent table from updating until we are completely done
220  controllers_tree_->setDisabled(false); // make sure we disable it so that the cellChanged event is not called
221  current_edit_controller_.clear(); // no controller is being edited
222  alterTree("expand");
223 }
224 
225 // ******************************************************************************************
226 // Displays data in the controller_config_ data structure into a QtTableWidget
227 // ******************************************************************************************
229 {
230  // Fonts for tree
231  const QFont top_level_font(QFont().defaultFamily(), 11, QFont::Bold);
232  const QFont type_font(QFont().defaultFamily(), 11, QFont::Normal, QFont::StyleItalic);
233 
234  QTreeWidgetItem* controller;
235 
236  controller = new QTreeWidgetItem();
237 
238  // First column
239  controller->setText(0, controller_it.name_.c_str());
240  controller->setFont(0, top_level_font);
241  controller->setData(0, Qt::UserRole, QVariant::fromValue(0));
242 
243  // Second column
244  controller->setText(1, controller_it.type_.c_str());
245  controller->setFont(1, type_font);
246  controller->setData(1, Qt::UserRole, QVariant::fromValue(4));
247  controllers_tree_->addTopLevelItem(controller);
248 
249  if (!controller_it.joints_.empty())
250  {
251  // Joints --------------------------------------------------------------
252  QTreeWidgetItem* joints = new QTreeWidgetItem(controller);
253  joints->setText(0, "Joints");
254  joints->setFont(0, type_font);
255  joints->setData(0, Qt::UserRole, QVariant::fromValue(1));
256  controller->addChild(joints);
257 
258  // Loop through all available joints
259  for (std::vector<std::string>::const_iterator joint_it = controller_it.joints_.begin();
260  joint_it != controller_it.joints_.end(); ++joint_it)
261  {
262  QTreeWidgetItem* joint_item = new QTreeWidgetItem(joints);
263  joint_item->setData(0, Qt::UserRole, QVariant::fromValue(2));
264 
265  // Add to tree
266  joint_item->setText(0, (*joint_it).c_str());
267  joints->addChild(joint_item);
268  }
269  }
270 }
271 
272 // ******************************************************************************************
273 // Called when setup assistant navigation switches to this screen
274 // ******************************************************************************************
276 {
277  // load controllers tree
278  btn_edit_->setEnabled(false);
279  btn_delete_->setEnabled(false);
281 }
282 
283 // ******************************************************************************************
284 // Load the popup screen with correct data for joints
285 // ******************************************************************************************
287 {
288  // Retrieve pointer to the shared kinematic model
289  const robot_model::RobotModelConstPtr& model = config_data_->getRobotModel();
290 
291  // Get the names of the all joints
292  const std::vector<std::string>& joints = model->getJointModelNames();
293 
294  if (joints.size() == 0)
295  {
296  QMessageBox::critical(this, "Error Loading", "No joints found for robot model");
297  return;
298  }
299 
300  // Set the available joints (left box)
301  joints_widget_->setAvailable(joints);
302 
303  // Set the selected joints (right box)
304  joints_widget_->setSelected(this_controller->joints_);
305 
306  // Set the title
307  joints_widget_->title_->setText(
308  QString("Edit '").append(QString::fromUtf8(this_controller->name_.c_str())).append("' Joint Collection"));
309 
310  // Remember what is currently being edited so we can later save changes
311  current_edit_controller_ = this_controller->name_;
312 }
313 
314 // ******************************************************************************************
315 // Load the popup screen with correct data for gcroups
316 // ******************************************************************************************
318 {
319  // Load all groups into the subgroup screen
320  std::vector<std::string> groups;
321 
322  // Display all groups by looping through them
323  for (std::vector<srdf::Model::Group>::const_iterator group_it = config_data_->srdf_->srdf_model_->getGroups().begin();
324  group_it != config_data_->srdf_->srdf_model_->getGroups().end(); ++group_it)
325  {
326  // Add to available groups list
327  groups.push_back(group_it->name_);
328  }
329 
330  // Set the available groups (left box)
332 
333  // Set the selected groups (right box)
334  joint_groups_widget_->setSelected(this_controller->joints_);
335 
336  // Set the title
337  joint_groups_widget_->title_->setText(
338  QString("Edit '").append(QString::fromUtf8(this_controller->name_.c_str())).append("' Joints groups collection"));
339 
340  // Remember what is currently being edited so we can later save changes
341  current_edit_controller_ = this_controller->name_;
342 }
343 
344 // ******************************************************************************************
345 // Delete a controller
346 // ******************************************************************************************
348 {
349  std::string controller_name = current_edit_controller_;
350 
351  if (controller_name.empty())
352  {
353  QTreeWidgetItem* item = controllers_tree_->currentItem();
354  // Check that something was actually selected
355  if (item == NULL)
356  return;
357 
358  // Get the user custom properties of the currently selected row
359  int type_ = item->data(0, Qt::UserRole).value<int>();
360  if (type_ == 0)
361  controller_name = item->text(0).toUtf8().constData();
362  }
363 
364  // Confirm user wants to delete controller
365  if (QMessageBox::question(
366  this, "Confirm Controller Deletion",
367  QString("Are you sure you want to delete the controller '").append(controller_name.c_str()).append(" ?"),
368  QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
369  {
370  return;
371  }
372  // Delete actual controller
373  if (config_data_->deleteROSController(controller_name))
374  {
375  ROS_INFO_STREAM_NAMED("Setup Assistant", "Controller " << controller_name << " deleted succefully");
376  }
377  else
378  {
379  ROS_WARN_STREAM_NAMED("Setup Assistant", "Couldn't delete Controller " << controller_name);
380  }
381 
382  current_edit_controller_.clear();
383 
384  // Switch to main screen
385  showMainScreen();
386 
387  // Reload main screen table
389 }
390 
391 // ******************************************************************************************
392 // Create a new controller
393 // ******************************************************************************************
395 {
396  // New Controller
397  adding_new_controller_ = true;
398 
399  // Load the data
400  loadControllerScreen(NULL); // NULL indicates this is a new controller, not an existing one
401  changeScreen(2); // 1 is index of controller edit
402 }
403 
404 // ******************************************************************************************
405 // Add a Follow Joint Trajectory action Controller for each Planning Group
406 // ******************************************************************************************
408 {
409  if (!config_data_->addDefaultControllers())
410  QMessageBox::warning(this, "Error adding contollers", "No Planning Groups configured!");
412 }
413 
414 // ******************************************************************************************
415 // Load the popup screen with correct data for controllers
416 // ******************************************************************************************
418 {
419  // Load the avail controllers. This function only runs once
421 
422  if (this_controller == NULL) // this is a new screen
423  {
424  current_edit_controller_.clear(); // provide a blank controller name
425  controller_edit_widget_->setTitle("Create New Controller");
427  controller_edit_widget_->showNewButtonsWidget(); // helps user choose next step
428  controller_edit_widget_->showSave(); // this is only for edit mode
429  }
430  else // load the controller name into the widget
431  {
432  current_edit_controller_ = this_controller->name_;
434  QString("Edit Controller '").append(current_edit_controller_.c_str()).append("'"));
436  controller_edit_widget_->hideNewButtonsWidget(); // not necessary for existing controllers
437  controller_edit_widget_->showSave(); // this is only for edit mode
438  }
439 
440  // Set the data in the edit box
442 }
443 
444 // ******************************************************************************************
445 // Call when edit screen is canceled
446 // ******************************************************************************************
448 {
450  {
452  if (editing && editing->joints_.empty())
453  {
454  config_data_->deleteROSController(current_edit_controller_);
455  current_edit_controller_.clear();
456 
457  // Load the data to the tree
459  }
460  }
461  else
462  {
463  current_edit_controller_.clear();
464  }
465 
466  // Switch to main screen
467  showMainScreen();
468 }
469 
470 // ******************************************************************************************
471 // Called from Double List widget to highlight joints
472 // ******************************************************************************************
473 void ROSControllersWidget::previewSelectedJoints(std::vector<std::string> joints)
474 {
475  // Unhighlight all links
476  Q_EMIT unhighlightAll();
477 
478  for (std::size_t i = 0; i < joints.size(); ++i)
479  {
480  const robot_model::JointModel* joint_model = config_data_->getRobotModel()->getJointModel(joints[i]);
481 
482  // Check that a joint model was found
483  if (!joint_model)
484  {
485  continue;
486  }
487 
488  // Get the name of the link
489  const std::string link = joint_model->getChildLinkModel()->getName();
490 
491  if (link.empty())
492  {
493  continue;
494  }
495 
496  // Highlight link
497  Q_EMIT highlightLink(link, QColor(255, 0, 0));
498  }
499 }
500 
501 // ******************************************************************************************
502 // Called from Double List widget to highlight a group
503 // ******************************************************************************************
504 void ROSControllersWidget::previewSelectedGroup(std::vector<std::string> groups)
505 {
506  // Unhighlight all links
507  Q_EMIT unhighlightAll();
508 
509  for (std::size_t i = 0; i < groups.size(); ++i)
510  {
511  // Highlight group
512  Q_EMIT highlightGroup(groups[i]);
513  }
514 }
515 
516 // ******************************************************************************************
517 // Called when an item is seleceted from the controllers tree
518 // ******************************************************************************************
519 void ROSControllersWidget::previewSelected(QTreeWidgetItem* selected_item, int column)
520 {
521  // Get the user custom properties of the currently selected row
522  int type = selected_item->data(0, Qt::UserRole).value<int>();
523  btn_edit_->setEnabled(true);
524 
525  // Enable delete button if a controller was selected
526  if (type == 0)
527  {
528  btn_delete_->setEnabled(true);
529  }
530  else
531  {
532  btn_delete_->setEnabled(false);
533  }
534 }
535 
536 // ******************************************************************************************
537 // Call when a new controller is created and ready to progress to next screen
538 // ******************************************************************************************
540 {
541  // Save the controller
542  if (!saveControllerScreen())
543  return;
544 
545  // Find the controller we are editing based on the controller name string
546  moveit_setup_assistant::ROSControlConfig* editing_controller =
547  config_data_->findROSControllerByName(current_edit_controller_);
548 
549  loadJointsScreen(editing_controller);
550 
551  // Switch to screen
552  changeScreen(1); // 1 is index of joints
553 }
554 
555 // ******************************************************************************************
556 // Call when a new controller is created and ready to progress to next screen
557 // ******************************************************************************************
559 {
560  // Save the controller
561  if (!saveControllerScreen())
562  return;
563 
564  // Find the controller we are editing based on the controller name string
565  moveit_setup_assistant::ROSControlConfig* editing_controller =
566  config_data_->findROSControllerByName(current_edit_controller_);
567 
568  loadGroupsScreen(editing_controller);
569 
570  // Switch to screen
571  changeScreen(3); // 3 is index of groups
572 }
573 
574 // ******************************************************************************************
575 // Call when joints edit sceen is done and needs to be saved
576 // ******************************************************************************************
578 {
579  // Find the controller we are editing based on the controller name string
580  moveit_setup_assistant::ROSControlConfig* searched_controller =
581  config_data_->findROSControllerByName(current_edit_controller_);
582 
583  // Clear the old data
584  searched_controller->joints_.clear();
585 
586  // Copy the data
587  for (int i = 0; i < joints_widget_->selected_data_table_->rowCount(); ++i)
588  {
589  searched_controller->joints_.push_back(joints_widget_->selected_data_table_->item(i, 0)->text().toStdString());
590  }
591 
592  // Switch to main screen
593  showMainScreen();
594 
595  // Reload main screen table
597 }
598 
599 // ******************************************************************************************
600 // Call when joints edit sceen is done and needs to be saved
601 // ******************************************************************************************
603 {
604  // Find the controller we are editing based on the controller name string
605  moveit_setup_assistant::ROSControlConfig* searched_controller =
606  config_data_->findROSControllerByName(current_edit_controller_);
607 
608  // Clear the old data
609  searched_controller->joints_.clear();
610 
611  // Copy the data
612  for (int i = 0; i < joint_groups_widget_->selected_data_table_->rowCount(); ++i)
613  {
614  // Get list of associated joints
615  const robot_model::JointModelGroup* joint_model_group = config_data_->getRobotModel()->getJointModelGroup(
616  joint_groups_widget_->selected_data_table_->item(i, 0)->text().toStdString());
617  const std::vector<const robot_model::JointModel*>& joint_models = joint_model_group->getActiveJointModels();
618 
619  // Iterate through the joints
620  for (const robot_model::JointModel* joint : joint_models)
621  {
622  if (joint->isPassive() || joint->getMimic() != NULL || joint->getType() == robot_model::JointModel::FIXED)
623  continue;
624  searched_controller->joints_.push_back(joint->getName());
625  }
626  }
627 
628  // Switch to main screen
629  showMainScreen();
630 
631  // Reload main screen table
633 }
634 
635 // ******************************************************************************************
636 // Call when joints edit sceen is done and needs to be saved
637 // ******************************************************************************************
639 {
640  // Save the controller
641  if (!saveControllerScreen())
642  return;
643 
644  // Switch to main screen
645  showMainScreen();
646 }
647 
648 // ******************************************************************************************
649 // Call when controller edit sceen is done and needs to be saved
650 // ******************************************************************************************
652 {
653  // Get a reference to the supplied strings
654  const std::string& controller_name = controller_edit_widget_->getControllerName();
655  const std::string& controller_type = controller_edit_widget_->getControllerType();
656 
657  // Used for editing existing controllers
658  moveit_setup_assistant::ROSControlConfig* searched_controller = NULL;
659 
660  std::smatch invalid_name_match;
661  std::regex invalid_reg_ex("[^a-z|^1-9|^_]");
662 
663  // Check that a valid controller name has been given
664  if (controller_name.empty() || std::regex_search(controller_name, invalid_name_match, invalid_reg_ex))
665  {
666  QMessageBox::warning(this, "Error Saving", "Invalid ROS controller name");
667  return false;
668  }
669 
670  // Check if this is an existing controller
671  if (!current_edit_controller_.empty())
672  {
673  // Find the controller we are editing based on the goup name string
674  searched_controller = config_data_->findROSControllerByName(current_edit_controller_);
675  }
676 
677  // Check that the controller name is unique
678  for (std::vector<moveit_setup_assistant::ROSControlConfig>::const_iterator controller_it =
679  config_data_->getROSControllers().begin();
680  controller_it != config_data_->getROSControllers().end(); ++controller_it)
681  {
682  if (controller_it->name_.compare(controller_name) == 0) // the names are the same
683  {
684  // is this our existing controller? check if controller pointers are same
685  if (&(*controller_it) != searched_controller)
686  {
687  QMessageBox::warning(this, "Error Saving", "A controller already exists with that name!");
688  return false;
689  }
690  }
691  }
692 
693  adding_new_controller_ = false;
694 
695  // Save the new controller name or create the new controller
696  if (searched_controller == NULL) // create new
697  {
699  new_controller.name_ = controller_name;
700  new_controller.type_ = controller_type;
701  config_data_->addROSController(new_controller);
702 
703  adding_new_controller_ = true; // remember this controller is new
704  }
705  else
706  {
707  // Remember old controller name and type
708  const std::string old_controller_name = searched_controller->name_;
709 
710  // Change controller name
711  searched_controller->name_ = controller_name;
712  searched_controller->type_ = controller_type;
713  }
714 
715  // Reload main screen table
717 
718  // Update the current edit controller so that we can proceed to the next screen, if user desires
719  current_edit_controller_ = controller_name;
720 
721  return true;
722 }
723 
724 // ******************************************************************************************
725 // Edit whenever element is selected in the controllers tree view
726 // ******************************************************************************************
728 {
729  QTreeWidgetItem* item = controllers_tree_->currentItem();
730  QTreeWidgetItem* controller_item;
731 
732  // Check that something was actually selected
733  if (item == NULL)
734  return;
735 
736  adding_new_controller_ = false;
737 
738  // Get the user custom properties of the currently selected row
739  int type = item->data(0, Qt::UserRole).value<int>();
740 
741  if (type == 2)
742  {
743  // The controller this joint belong to
744  controller_item = item->parent()->parent();
745  current_edit_controller_ = controller_item->text(0).toUtf8().constData();
747  config_data_->findROSControllerByName(current_edit_controller_);
748 
749  // Load the data
750  loadJointsScreen(this_controller);
751 
752  // Switch to screen
753  changeScreen(1); // 1 is index of joints
754  }
755  else if (type == 1)
756  {
757  controller_item = item->parent();
758  current_edit_controller_ = controller_item->text(0).toUtf8().constData();
760  config_data_->findROSControllerByName(current_edit_controller_);
761 
762  // Load the data
763  loadJointsScreen(this_controller);
764 
765  // Switch to screen
766  changeScreen(1); // 1 is index of joints
767  }
768  else if (type == 0)
769  {
770  // Load the data
771  current_edit_controller_ = item->text(0).toUtf8().constData();
773  config_data_->findROSControllerByName(current_edit_controller_);
774  loadControllerScreen(this_controller);
775 
776  // Switch to screen
777  changeScreen(2); // 1 is index of controller edit
778  }
779  else
780  {
781  QMessageBox::critical(this, "Error Loading", "An internal error has occured while loading.");
782  }
783 }
784 
785 // ******************************************************************************************
786 // Edit a controller
787 // ******************************************************************************************
789 {
790  QTreeWidgetItem* item = controllers_tree_->currentItem();
791 
792  // Check that something was actually selected
793  if (item == NULL)
794  return;
795 
796  adding_new_controller_ = false;
797 
799 
800  // Switch to screen
801  changeScreen(2); // 1 is index of controller edit
802 }
803 
804 // ******************************************************************************************
805 // Switch to current controllers view
806 // ******************************************************************************************
808 {
809  stacked_layout_->setCurrentIndex(0);
810 
811  // Announce that this widget is not in modal mode
812  Q_EMIT isModal(false);
813 }
814 
815 // ******************************************************************************************
816 // Switch which screen is being shown
817 // ******************************************************************************************
819 {
820  stacked_layout_->setCurrentIndex(index);
821 
822  // Announce this widget's mode
823  Q_EMIT isModal(index != 0);
824 }
825 
826 // ******************************************************************************************
827 // Expand/Collapse Tree
828 // ******************************************************************************************
829 void ROSControllersWidget::alterTree(const QString& link)
830 {
831  if (link.contains("expand"))
832  controllers_tree_->expandAll();
833  else
834  controllers_tree_->collapseAll();
835 }
836 
838 {
839  QList<QTreeWidgetItem*> selected_items = controllers_tree_->selectedItems();
840  if (selected_items.size() == 0)
841  {
842  btn_edit_->setEnabled(false);
843  btn_delete_->setEnabled(false);
844  }
845 }
846 
847 } // namespace
std::string current_edit_controller_
Remember what controller we are editing when an edit screen is being shown.
#define NULL
QWidget * createContentsWidget()
Builds the main screen list widget.
void editSelected()
Called whenever element is selected in the controllers tree view.
void setSelected(const std::vector< std::string > &items)
Set the right box.
std::string getControllerName()
Get controller name.
void isModal(bool isModal)
Event for when the current screen is in modal view. Essential disabled the left navigation.
void hideDelete()
Hide delete controller button.
QTreeWidget * controllers_tree_
Main table for holding controllers.
void showSave()
Show save controller button.
void loadJointsScreen(moveit_setup_assistant::ROSControlConfig *this_controller)
void setSelected(const std::string &controller_name)
Set the previous data.
void loadGroupsScreen(moveit_setup_assistant::ROSControlConfig *this_controller)
#define ROS_INFO_STREAM_NAMED(name, args)
void previewSelectedGroup(std::vector< std::string > groups)
Called from Double List widget to highlight a group.
void highlightLink(const std::string &name, const QColor &)
Event for telling rviz to highlight a link of the robot.
void showNewButtonsWidget()
Show new buttons widget.
void addController()
Create a new controller.
moveit_setup_assistant::DoubleListWidget * joint_groups_widget_
void setTitle(const QString &title)
Set widget title.
void loadToControllersTree(const moveit_setup_assistant::ROSControlConfig &controller_it)
void unhighlightAll()
Event for telling rviz to unhighlight all links of the robot.
void setAvailable(const std::vector< std::string > &items)
Loads the availble data list.
void hideNewButtonsWidget()
Hide new buttons widget.
void previewSelectedJoints(std::vector< std::string > joints)
Called from Double List widget to highlight a joint.
ROSControllersWidget(QWidget *parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
void previewSelected(QTreeWidgetItem *selected_item, int column)
Called when an item is seleceted from the controllers tree.
std::string getControllerType()
Get controller type.
void itemSelectionChanged()
Called sleceted item changed.
void showDelete()
Show delete controller button.
moveit_setup_assistant::DoubleListWidget * joints_widget_
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
void deleteController()
Delete an existing controller.
QStackedLayout * stacked_layout_
For changing between table and different add/edit views.
groups
void highlightGroup(const std::string &name)
Event for telling rviz to highlight a group of the robot.
void loadControllerScreen(moveit_setup_assistant::ROSControlConfig *this_controller)
void loadControllersTypesComboBox()
Populate the combo dropdown box with controllers types.
moveit_setup_assistant::MoveItConfigDataPtr config_data_
Contains all the configuration data for the setup assistant.
void saveControllerScreenJoints()
Call when screen is done being edited.
virtual void focusGiven()
Received when this widget is chosen from the navigation menu.
bool adding_new_controller_
Remember whethere we&#39;re editing a controller or adding a new one.
void editController()
Edit an existing controller.
#define ROS_WARN_STREAM_NAMED(name, args)


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Sun Oct 18 2020 13:19:28