default_collisions_widget.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Dave Coleman */
00036 
00037 #include <QHBoxLayout>
00038 #include <QMessageBox>
00039 #include <QProgressDialog>
00040 #include <QString>
00041 #include <QFont>
00042 #include <QApplication>
00043 #include "default_collisions_widget.h"
00044 #include <boost/unordered_map.hpp>
00045 #include <boost/assign.hpp>
00046 #include <ros/console.h>
00047 
00048 namespace moveit_setup_assistant
00049 {
00051 const boost::unordered_map<moveit_setup_assistant::DisabledReason, const char*> longReasonsToString =
00052     boost::assign::map_list_of(moveit_setup_assistant::NEVER, "Never in Collision")(moveit_setup_assistant::DEFAULT,
00053                                                                                     "Collision by Default")(
00054         moveit_setup_assistant::ADJACENT, "Adjacent Links")(moveit_setup_assistant::ALWAYS, "Always in Collision")(
00055         moveit_setup_assistant::USER, "User Disabled")(moveit_setup_assistant::NOT_DISABLED, "");
00056 
00060 class CheckboxSortWidgetItem : public QTableWidgetItem
00061 {
00062 public:
00066   bool operator<(const QTableWidgetItem& other) const
00067   {
00068     return checkState() < other.checkState();
00069   }
00070 };
00071 
00072 // ******************************************************************************************
00073 // User interface for editing the default collision matrix list in an SRDF
00074 // ******************************************************************************************
00075 DefaultCollisionsWidget::DefaultCollisionsWidget(QWidget* parent, MoveItConfigDataPtr config_data)
00076   : SetupScreenWidget(parent), config_data_(config_data)
00077 {
00078   // Basic widget container
00079   layout_ = new QVBoxLayout(this);
00080 
00081   // Top Label Area ------------------------------------------------
00082   HeaderWidget* header = new HeaderWidget(
00083       "Optimize Self-Collision Checking",
00084       "The Default Self-Collision Matrix Generator will search for pairs of links on the robot that can safely be "
00085       "disabled from collision checking, decreasing motion planning processing time. These pairs of links are disabled "
00086       "when they are always in collision, never in collision, in collision in the robot's default position or when the "
00087       "links are adjacent to each other on the kinematic chain. Sampling density specifies how many random robot "
00088       "positions to check for self collision. Higher densities require more computation time.",
00089       this);
00090   layout_->addWidget(header);
00091 
00092   // Top Button Area -----------------------------------------------
00093   controls_box_ = new QGroupBox(this);
00094   layout_->addWidget(controls_box_);
00095   QHBoxLayout* controls_box_layout = new QHBoxLayout(controls_box_);
00096   controls_box_layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
00097 
00098   // Slider Label
00099   QLabel* density_left_label = new QLabel(this);
00100   density_left_label->setText("Sampling Density: Low");
00101   controls_box_layout->addWidget(density_left_label);
00102 
00103   // Slider
00104   density_slider_ = new QSlider(this);
00105   density_slider_->setTickPosition(QSlider::TicksBelow);
00106   density_slider_->setMinimum(0);
00107   density_slider_->setMaximum(99);
00108   density_slider_->setSingleStep(10);
00109   density_slider_->setPageStep(50);
00110   density_slider_->setSliderPosition(9);  // 10,000 is default
00111   density_slider_->setTickInterval(10);
00112   density_slider_->setOrientation(Qt::Horizontal);
00113   controls_box_layout->addWidget(density_slider_);
00114   connect(density_slider_, SIGNAL(valueChanged(int)), this, SLOT(changeDensityLabel(int)));
00115 
00116   // Slider Right Label
00117   QLabel* density_right_label = new QLabel(this);
00118   density_right_label->setText("High   ");
00119   controls_box_layout->addWidget(density_right_label);
00120 
00121   // Slider Value Label
00122   density_value_label_ = new QLabel(this);
00123   density_value_label_->setMinimumWidth(50);
00124   controls_box_layout->addWidget(density_value_label_);
00125   changeDensityLabel(density_slider_->value());  // initialize label with value
00126 
00127   // Generate Button
00128   btn_generate_ = new QPushButton(this);
00129   btn_generate_->setText("&Generate Collision Matrix");
00130   btn_generate_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00131   connect(btn_generate_, SIGNAL(clicked()), this, SLOT(generateCollisionTable()));
00132   layout_->addWidget(btn_generate_);
00133   layout_->setAlignment(btn_generate_, Qt::AlignRight);
00134 
00135   // Progress Bar Area ---------------------------------------------
00136 
00137   // Progress Label
00138   progress_label_ = new QLabel(this);
00139   progress_label_->setText("Generating Default Collision Matrix");
00140   progress_label_->hide();
00141   layout_->addWidget(progress_label_);
00142 
00143   // Progress Bar
00144   progress_bar_ = new QProgressBar(this);
00145   progress_bar_->setMaximum(100);
00146   progress_bar_->setMinimum(0);
00147   progress_bar_->hide();              // only show when computation begins
00148   layout_->addWidget(progress_bar_);  //,Qt::AlignCenter);
00149 
00150   // Table Area --------------------------------------------
00151 
00152   // Table
00153   collision_table_ = new QTableWidget(this);
00154   collision_table_->setColumnCount(4);
00155   collision_table_->setSortingEnabled(true);
00156   collision_table_->setSelectionMode(QAbstractItemView::SingleSelection);
00157   collision_table_->setSelectionBehavior(QAbstractItemView::SelectRows);
00158   connect(collision_table_, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(previewSelected(int)));
00159   connect(collision_table_, SIGNAL(cellChanged(int, int)), this, SLOT(toggleCheckBox(int, int)));
00160   layout_->addWidget(collision_table_);
00161 
00162   QStringList header_list;
00163   header_list.append("Link A");
00164   header_list.append("Link B");
00165   header_list.append("Disabled");
00166   header_list.append("Reason To Disable");
00167   collision_table_->setHorizontalHeaderLabels(header_list);
00168 
00169   // Resize headers
00170   collision_table_->resizeColumnToContents(0);
00171   collision_table_->resizeColumnToContents(1);
00172   collision_table_->resizeColumnToContents(2);
00173   collision_table_->resizeColumnToContents(3);
00174 
00175   // Bottom Area ----------------------------------------
00176   controls_box_bottom_ = new QGroupBox(this);
00177   layout_->addWidget(controls_box_bottom_);
00178   QHBoxLayout* controls_box_bottom_layout = new QHBoxLayout(controls_box_bottom_);
00179 
00180   // Checkbox
00181   collision_checkbox_ = new QCheckBox(this);
00182   collision_checkbox_->setText("Show Non-Disabled Link Pairs");
00183   connect(collision_checkbox_, SIGNAL(toggled(bool)), this, SLOT(collisionCheckboxToggle()));
00184   controls_box_bottom_layout->addWidget(collision_checkbox_);
00185 
00186   fraction_label_ = new QLabel(this);
00187   fraction_label_->setText("Min. collisions for \"always\"-colliding pairs:");
00188 
00189   controls_box_bottom_layout->addWidget(fraction_label_);
00190 
00191   fraction_spinbox_ = new QSpinBox(this);
00192   fraction_spinbox_->setRange(1, 100);
00193   fraction_spinbox_->setValue(95);
00194   fraction_spinbox_->setSuffix("%");
00195   controls_box_bottom_layout->addWidget(fraction_spinbox_);
00196 
00197   controls_box_bottom_layout->setAlignment(collision_checkbox_, Qt::AlignLeft);
00198 
00199   setLayout(layout_);
00200 
00201   setWindowTitle("Default Collision Matrix");
00202 }
00203 
00204 // ******************************************************************************************
00205 // Qt close event function for reminding user to save
00206 // ******************************************************************************************
00207 void DefaultCollisionsWidget::generateCollisionTable()
00208 {
00209   // Confirm the user wants to overwrite the current disabled collisions
00210   if (!config_data_->srdf_->disabled_collisions_.empty())
00211   {
00212     if (QMessageBox::question(this, "Confirm Disabled Collision Overwrite", "Are you sure you want to overwrite the "
00213                                                                             "current default collisions matrix with a "
00214                                                                             "newly generated one?",
00215                               QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
00216     {
00217       return;  // abort
00218     }
00219   }
00220   QApplication::processEvents();  // allow the progress bar to be shown
00221   progress_label_->setText("Computing default collision matrix for robot model...");
00222 
00223   // Disable controls on form
00224   disableControls(true);
00225 
00226   // Create a progress variable that will be shared with the compute_default_collisions tool and its threads
00227   // NOTE: be sure not to delete this variable until the subprograms have finished using it. Because of the simple
00228   // use case of this variable (1 thread writes to it, the parent process reads it) it was decided a boost shared
00229   // pointer is not necessary.
00230   unsigned int collision_progress = 0;
00231   progress_bar_->setValue(collision_progress);
00232 
00233   QApplication::processEvents();  // allow the progress bar to be shown
00234 
00235   // Create thread to do actual work
00236   boost::thread workerThread(
00237       boost::bind(&DefaultCollisionsWidget::generateCollisionTableThread, this, &collision_progress));
00238   // Check interval
00239   boost::posix_time::seconds check_interval(1);
00240 
00241   // Continually loop until threaded computation is finished
00242   while (collision_progress < 100)
00243   {
00244     // Set updated progress value.
00245     progress_bar_->setValue(collision_progress);
00246 
00247     // Allow GUI thread to do its stuff
00248     QApplication::processEvents();
00249 
00250     // 1 second sleep
00251     boost::this_thread::sleep(check_interval);
00252     // usleep(1000 * 1000);
00253   }
00254 
00255   // Wait for thread to finish
00256   workerThread.join();
00257 
00258   // Load the results into the GUI
00259   loadCollisionTable();
00260 
00261   // Hide the progress bar
00262   disableControls(false);  // enable everything else
00263 
00264   config_data_->changes |= MoveItConfigData::COLLISIONS;
00265 }
00266 
00267 // ******************************************************************************************
00268 // The thread that is called to allow the GUI to update. Calls an external function to do calcs
00269 // ******************************************************************************************
00270 void DefaultCollisionsWidget::generateCollisionTableThread(unsigned int* collision_progress)
00271 {
00272   unsigned int num_trials = density_slider_->value() * 1000 + 1000;  // scale to trials amount
00273   double min_frac = (double)fraction_spinbox_->value() / 100.0;
00274 
00275   const bool verbose = true;  // Output benchmarking and statistics
00276   const bool include_never_colliding = true;
00277 
00278   // clear previously loaded collision matrix entries
00279   config_data_->getPlanningScene()->getAllowedCollisionMatrixNonConst().clear();
00280 
00281   // Find the default collision matrix - all links that are allowed to collide
00282   link_pairs_ = moveit_setup_assistant::computeDefaultCollisions(
00283       config_data_->getPlanningScene(), collision_progress, include_never_colliding, num_trials, min_frac, verbose);
00284 
00285   // Copy data changes to srdf_writer object
00286   linkPairsToSRDF();
00287 
00288   // End the progress bar loop
00289   *collision_progress = 100;
00290 
00291   ROS_INFO_STREAM("Thread complete " << link_pairs_.size());
00292 }
00293 
00294 // ******************************************************************************************
00295 // Displays data in the link_pairs_ data structure into a QtTableWidget
00296 // ******************************************************************************************
00297 void DefaultCollisionsWidget::loadCollisionTable()
00298 {
00299   int row = 0;
00300   int progress_counter = 0;
00301 
00302   // Show Progress Bar
00303   progress_bar_->setValue(0);
00304 
00305   QApplication::processEvents();  // allow the progress bar to be shown
00306   progress_label_->setText("Loading table...");
00307 
00308   // Setup Collision Table
00309   collision_table_->setUpdatesEnabled(false);  // prevent table from updating until we are completely done
00310   collision_table_->setDisabled(true);         // make sure we disable it so that the cellChanged event is not called
00311   collision_table_->clearContents();
00312 
00313   // Check if there are no disabled collisions (unprobable?)
00314   if (link_pairs_.empty())
00315   {
00316     collision_table_->setRowCount(1);
00317     QTableWidgetItem* no_collide = new QTableWidgetItem("No Link Pairs Of This Kind");
00318     collision_table_->setItem(0, 0, no_collide);
00319   }
00320   else
00321   {
00322     // The table will be populated, so indicate it on the button
00323     btn_generate_->setText("Regenerate Default Collision Matrix");
00324   }
00325 
00326   // Intially set the table to be worst-case scenario of every possible element pair
00327   collision_table_->setRowCount(link_pairs_.size());
00328 
00329   for (moveit_setup_assistant::LinkPairMap::const_iterator pair_it = link_pairs_.begin(); pair_it != link_pairs_.end();
00330        ++pair_it)
00331   {
00332     // Add link pair row if 1) it is disabled from collision checking or 2) the SHOW ALL LINK PAIRS checkbox is checked
00333     if (pair_it->second.disable_check || collision_checkbox_->isChecked())
00334     {
00335       // Create row elements
00336       QTableWidgetItem* linkA = new QTableWidgetItem(pair_it->first.first.c_str());
00337       linkA->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00338 
00339       QTableWidgetItem* linkB = new QTableWidgetItem(pair_it->first.second.c_str());
00340       linkB->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00341 
00342       CheckboxSortWidgetItem* disable_check = new CheckboxSortWidgetItem();
00343       disable_check->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable);
00344       if (pair_it->second.disable_check)  // Checked means no collision checking
00345         disable_check->setCheckState(Qt::Checked);
00346       else
00347         disable_check->setCheckState(Qt::Unchecked);
00348 
00349       QTableWidgetItem* reason = new QTableWidgetItem(longReasonsToString.at(pair_it->second.reason));
00350       reason->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00351 
00352       // Insert row elements into collision table
00353       collision_table_->setItem(row, 0, linkA);
00354       collision_table_->setItem(row, 1, linkB);
00355       collision_table_->setItem(row, 2, disable_check);
00356       collision_table_->setItem(row, 3, reason);
00357 
00358       // Increment row count
00359       ++row;
00360     }
00361 
00362     ++progress_counter;  // for calculating progress bar
00363 
00364     if (progress_counter % 200 == 0)
00365     {
00366       // Update Progress Bar
00367       progress_bar_->setValue(progress_counter * 100 / link_pairs_.size());
00368       QApplication::processEvents();  // allow the progress bar to be shown
00369     }
00370   }
00371 
00372   // Reduce the table size to only the number of used rows.
00373   collision_table_->setRowCount(row);
00374 
00375   // Resize headers. The hiding is a hack so that it resizes correctly
00376   collision_table_->setVisible(false);
00377   collision_table_->resizeColumnToContents(0);
00378   collision_table_->resizeColumnToContents(1);
00379   collision_table_->resizeColumnToContents(2);
00380   collision_table_->resizeColumnToContents(3);
00381   collision_table_->setVisible(true);
00382 
00383   collision_table_->setUpdatesEnabled(true);  // prevent table from updating until we are completely done
00384 }
00385 
00386 // ******************************************************************************************
00387 // GUI func for showing sampling density amount
00388 // ******************************************************************************************
00389 void DefaultCollisionsWidget::changeDensityLabel(int value)
00390 {
00391   density_value_label_->setText(QString::number(value * 1000 + 1000));  //.append(" samples") );
00392 }
00393 
00394 // ******************************************************************************************
00395 // Helper function to disable parts of GUI during computation
00396 // ******************************************************************************************
00397 void DefaultCollisionsWidget::disableControls(bool disable)
00398 {
00399   controls_box_->setDisabled(disable);
00400   collision_table_->setDisabled(disable);
00401   collision_checkbox_->setDisabled(disable);
00402 
00403   if (disable)
00404   {
00405     progress_bar_->show();  // only show when computation begins
00406     progress_label_->show();
00407   }
00408   else
00409   {
00410     progress_label_->hide();
00411     progress_bar_->hide();
00412   }
00413 
00414   QApplication::processEvents();  // allow the progress bar to be shown
00415 }
00416 
00417 // ******************************************************************************************
00418 // Changes the table to show or hide collisions that are not disabled (that have collision checking enabled)
00419 // ******************************************************************************************
00420 void DefaultCollisionsWidget::collisionCheckboxToggle()
00421 {
00422   // Show Progress bar
00423   disableControls(true);
00424 
00425   // Now update collision table with updates
00426   loadCollisionTable();
00427 
00428   // Hide Progress bar
00429   disableControls(false);
00430 }
00431 
00432 // ******************************************************************************************
00433 // Called when user changes data in table, really just the checkbox
00434 // ******************************************************************************************
00435 void DefaultCollisionsWidget::toggleCheckBox(int row, int column)
00436 {
00437   // Only accept cell changes if table is enabled, otherwise it is this program making changes
00438   // Also make sure the change is in the checkbox column
00439   if (!collision_table_->isEnabled() || column != 2)
00440     return;
00441 
00442   // Convert row to pair
00443   std::pair<std::string, std::string> link_pair;
00444   link_pair.first = collision_table_->item(row, 0)->text().toStdString();
00445   link_pair.second = collision_table_->item(row, 1)->text().toStdString();
00446 
00447   // Get the state of checkbox
00448   bool check_state = collision_table_->item(row, 2)->checkState();
00449 
00450   // Check if the checkbox state has changed from original value
00451   if (link_pairs_[link_pair].disable_check != check_state)
00452   {
00453     // Save the change
00454     link_pairs_[link_pair].disable_check = check_state;
00455 
00456     // Handle USER Reasons: 1) pair is disabled by user
00457     if (link_pairs_[link_pair].disable_check == true &&
00458         link_pairs_[link_pair].reason == moveit_setup_assistant::NOT_DISABLED)
00459     {
00460       link_pairs_[link_pair].reason = moveit_setup_assistant::USER;
00461 
00462       // Change Reason in Table
00463       collision_table_->item(row, 3)->setText(longReasonsToString.at(link_pairs_[link_pair].reason));
00464     }
00465     // Handle USER Reasons: 2) pair was disabled by user and now is enabled (not checked)
00466     else if (link_pairs_[link_pair].disable_check == false &&
00467              link_pairs_[link_pair].reason == moveit_setup_assistant::USER)
00468     {
00469       link_pairs_[link_pair].reason = moveit_setup_assistant::NOT_DISABLED;
00470 
00471       // Change Reason in Table
00472       collision_table_->item(row, 3)->setText("");
00473     }
00474 
00475     config_data_->changes |= MoveItConfigData::COLLISIONS;
00476   }
00477 
00478   // Copy data changes to srdf_writer object
00479   linkPairsToSRDF();
00480 
00481   previewSelected(row);
00482 }
00483 
00484 // ******************************************************************************************
00485 // Output Link Pairs to SRDF Format and update the collision matrix
00486 // ******************************************************************************************
00487 void DefaultCollisionsWidget::linkPairsToSRDF()
00488 {
00489   // reset the data in the SRDF Writer class
00490   config_data_->srdf_->disabled_collisions_.clear();
00491 
00492   // Create temp disabled collision
00493   srdf::Model::DisabledCollision dc;
00494 
00495   // copy the data in this class's LinkPairMap datastructure to srdf::Model::DisabledCollision format
00496   for (moveit_setup_assistant::LinkPairMap::const_iterator pair_it = link_pairs_.begin(); pair_it != link_pairs_.end();
00497        ++pair_it)
00498   {
00499     // Only copy those that are actually disabled
00500     if (pair_it->second.disable_check)
00501     {
00502       dc.link1_ = pair_it->first.first;
00503       dc.link2_ = pair_it->first.second;
00504       dc.reason_ = moveit_setup_assistant::disabledReasonToString(pair_it->second.reason);
00505       config_data_->srdf_->disabled_collisions_.push_back(dc);
00506     }
00507   }
00508 
00509   // Update collision_matrix for robot pose's use
00510   config_data_->loadAllowedCollisionMatrix();
00511 }
00512 
00513 // ******************************************************************************************
00514 // Load Link Pairs from SRDF Format
00515 // ******************************************************************************************
00516 void DefaultCollisionsWidget::linkPairsFromSRDF()
00517 {
00518   // Clear all the previous data in the compute_default_collisions tool
00519   link_pairs_.clear();
00520 
00521   // Create new instance of planning scene using pointer
00522   planning_scene::PlanningScenePtr scene = config_data_->getPlanningScene()->diff();
00523 
00524   // Populate link_pairs_ list with every possible n choose 2 combination of links
00525   moveit_setup_assistant::computeLinkPairs(*scene, link_pairs_);
00526 
00527   // Create temp link pair data struct
00528   moveit_setup_assistant::LinkPairData link_pair_data;
00529   std::pair<std::string, std::string> link_pair;
00530 
00531   // Loop through all disabled collisions in SRDF and update the comprehensive list that has already been created
00532   for (std::vector<srdf::Model::DisabledCollision>::const_iterator collision_it =
00533            config_data_->srdf_->disabled_collisions_.begin();
00534        collision_it != config_data_->srdf_->disabled_collisions_.end(); ++collision_it)
00535   {
00536     // Set the link names
00537     link_pair.first = collision_it->link1_;
00538     link_pair.second = collision_it->link2_;
00539 
00540     // Set the link meta data
00541     link_pair_data.reason = moveit_setup_assistant::disabledReasonFromString(collision_it->reason_);
00542     link_pair_data.disable_check = true;  // disable checking the collision btw the 2 links
00543 
00544     // Insert into map
00545     link_pairs_[link_pair] = link_pair_data;
00546   }
00547 }
00548 
00549 // ******************************************************************************************
00550 // Preview whatever element is selected
00551 // ******************************************************************************************
00552 void DefaultCollisionsWidget::previewSelected(int row)
00553 {
00554   // Unhighlight all links
00555   Q_EMIT unhighlightAll();
00556 
00557   // Highlight link
00558   QTableWidgetItem* first_link_item = collision_table_->item(row, 0);
00559   if (!first_link_item)
00560     return;  // nothing to highlight
00561 
00562   const QString& first_link = first_link_item->text();
00563   const QString& second_link = collision_table_->item(row, 1)->text();
00564   Qt::CheckState check_state = collision_table_->item(row, 2)->checkState();
00565 
00566   QColor color = (check_state == Qt::Checked) ? QColor(0, 255, 0) : QColor(255, 0, 0);
00567   Q_EMIT highlightLink(first_link.toStdString(), color);
00568   Q_EMIT highlightLink(second_link.toStdString(), color);
00569 }
00570 
00571 // ******************************************************************************************
00572 // Called when setup assistant navigation switches to this screen
00573 // ******************************************************************************************
00574 void DefaultCollisionsWidget::focusGiven()
00575 {
00576   // Convert the SRDF data to LinkPairData format
00577   linkPairsFromSRDF();
00578 
00579   // Load the data to the table
00580   loadCollisionTable();
00581 
00582   // Enable the table
00583   disableControls(false);
00584 }
00585 
00586 }  // namespace


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Mon Jul 24 2017 02:22:29