tab_states_and_goals.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: Mario Prats, Ioan Sucan */
00036 
00037 #include <main_window.h>
00038 #include <job_processing.h>
00039 #include <benchmark_processing_thread.h>
00040 
00041 #include <moveit/kinematic_constraints/utils.h>
00042 #include <moveit/robot_state/conversions.h>
00043 #include <moveit/warehouse/constraints_storage.h>
00044 #include <moveit/warehouse/state_storage.h>
00045 #include <moveit/benchmarks/benchmark_execution.h>
00046 #include <moveit/planning_interface/planning_interface.h>
00047 
00048 #include <pluginlib/class_loader.h>
00049 
00050 #include <rviz/display_context.h>
00051 #include <rviz/window_manager_interface.h>
00052 
00053 #include <eigen_conversions/eigen_msg.h>
00054 
00055 #include <QMessageBox>
00056 #include <QInputDialog>
00057 #include <QFileDialog>
00058 #include <QProgressDialog>
00059 
00060 #include <boost/math/constants/constants.hpp>
00061 
00062 namespace benchmark_tool
00063 {
00064 
00065 void MainWindow::createGoalAtPose(const std::string &name, const Eigen::Affine3d &pose)
00066 {
00067   goals_initial_pose_.insert(std::pair<std::string, Eigen::Affine3d>(name, pose));
00068 
00069   geometry_msgs::Pose marker_pose;
00070   tf::poseEigenToMsg(pose * goal_offset_, marker_pose);
00071   static const float marker_scale = 0.15;
00072 
00073   GripperMarkerPtr goal_pose(new GripperMarker(scene_display_->getPlanningSceneRO()->getCurrentState(), scene_display_->getSceneNode(), visualization_manager_, name, scene_display_->getRobotModel()->getModelFrame(),
00074                                                robot_interaction_->getActiveEndEffectors()[0], marker_pose, marker_scale, GripperMarker::NOT_TESTED));
00075   goal_poses_.insert(GoalPosePair(name,  goal_pose));
00076 
00077   // Connect signals
00078   goal_pose->connect(this, SLOT( goalPoseFeedback(visualization_msgs::InteractiveMarkerFeedback &) ));
00079 
00080   //If connected to a database, save all the goals back to the database
00081   if (constraints_storage_)
00082   {
00083     saveGoalsToDB();
00084   }
00085 }
00086 
00087 void MainWindow::saveGoalsToDB()
00088 {
00089   if (constraints_storage_)
00090   {
00091     //Convert all goal pose markers into constraints and store them
00092     for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00093     {
00094       moveit_msgs::Constraints constraints;
00095       constraints.name = it->first;
00096 
00097       shape_msgs::SolidPrimitive sp;
00098       sp.type = sp.BOX;
00099       sp.dimensions.resize(3, std::numeric_limits<float>::epsilon() * 10.0);
00100 
00101       moveit_msgs::PositionConstraint pc;
00102       pc.header.frame_id = scene_display_->getRobotModel()->getModelFrame();
00103       pc.link_name = robot_interaction_->getActiveEndEffectors()[0].parent_link; // TODO this is hacky i think
00104       pc.constraint_region.primitives.push_back(sp);
00105       geometry_msgs::Pose posemsg;
00106       it->second->getPosition(posemsg.position);
00107       posemsg.orientation.x = 0.0;
00108       posemsg.orientation.y = 0.0;
00109       posemsg.orientation.z = 0.0;
00110       posemsg.orientation.w = 1.0;
00111       pc.constraint_region.primitive_poses.push_back(posemsg);
00112       pc.weight = 1.0;
00113       constraints.position_constraints.push_back(pc);
00114 
00115       moveit_msgs::OrientationConstraint oc;
00116       oc.header.frame_id = scene_display_->getRobotModel()->getModelFrame();
00117       oc.link_name = robot_interaction_->getActiveEndEffectors()[0].parent_link; // TODO this is hacky i think
00118       it->second->getOrientation(oc.orientation);
00119       oc.absolute_x_axis_tolerance = oc.absolute_y_axis_tolerance =
00120         oc.absolute_z_axis_tolerance = std::numeric_limits<float>::epsilon() * 10.0;
00121       oc.weight = 1.0;
00122       constraints.orientation_constraints.push_back(oc);
00123 
00124       try
00125       {
00126         constraints_storage_->addConstraints(constraints);
00127       }
00128       catch (std::runtime_error &ex)
00129       {
00130         ROS_ERROR("Cannot save constraint: %s", ex.what());
00131       }
00132     }
00133   }
00134   else
00135   {
00136     QMessageBox::warning(this, "Warning", "Not connected to a database.");
00137   }
00138 }
00139 
00140 void MainWindow::createGoalPoseButtonClicked(void)
00141 {
00142   std::stringstream ss;
00143 
00144   {
00145     const planning_scene_monitor::LockedPlanningSceneRO &ps = scene_display_->getPlanningSceneRO();
00146     if ( ! ps || robot_interaction_->getActiveEndEffectors().empty() )
00147     {
00148       if ( ! ps ) ROS_ERROR("Not planning scene");
00149       if ( robot_interaction_->getActiveEndEffectors().empty() ) ROS_ERROR("No end effector");
00150       return;
00151     }
00152     else
00153       ss << ps->getName().c_str() << "_pose_" << std::setfill('0') << std::setw(4) << goal_poses_.size();
00154   }
00155 
00156   bool ok = false;
00157   QString text = QInputDialog::getText(this, tr("Choose a name"),
00158                                        tr("Goal pose name:"), QLineEdit::Normal,
00159                                        QString(ss.str().c_str()), &ok);
00160 
00161   std::string name;
00162   if (ok)
00163   {
00164     if ( ! text.isEmpty() )
00165     {
00166       name = text.toStdString();
00167       if (goal_poses_.find(name) != goal_poses_.end())
00168         QMessageBox::warning(this, "Name already exists", QString("The name '").append(name.c_str()).
00169                              append("' already exists. Not creating goal."));
00170       else
00171       {
00172         //Create the new goal pose at the current eef pose, and attach an interactive marker to it
00173         scene_display_->getPlanningSceneRW()->getCurrentStateNonConst().update();
00174         Eigen::Affine3d tip_pose = scene_display_->getPlanningSceneRO()->getCurrentState().getGlobalLinkTransform(robot_interaction_->getActiveEndEffectors()[0].parent_link);
00175         createGoalAtPose(name, tip_pose);
00176       }
00177     }
00178     else
00179       QMessageBox::warning(this, "Goal not created", "Cannot use an empty name for a new goal pose.");
00180   }
00181 
00182   populateGoalPosesList();
00183 }
00184 
00185 void MainWindow::showBBoxGoalsDialog()
00186 {
00187   std::string goals_base_name;
00188   {
00189     const planning_scene_monitor::LockedPlanningSceneRO &ps = scene_display_->getPlanningSceneRO();
00190     if ( ! ps || robot_interaction_->getActiveEndEffectors().empty() )
00191     {
00192       if ( ! ps ) ROS_ERROR("No planning scene");
00193       if ( robot_interaction_->getActiveEndEffectors().empty() ) ROS_ERROR("No end effector");
00194       return;
00195     }
00196     goals_base_name = ps->getName() + "_pose_";
00197   }
00198 
00199   bbox_dialog_ui_.base_name_text->setText(QString(goals_base_name.c_str()));
00200 
00201   bbox_dialog_->exec();
00202 }
00203 
00204 void MainWindow::createBBoxGoalsButtonClicked(void)
00205 {
00206   bbox_dialog_->close();
00207 
00208   double minx = bbox_dialog_ui_.center_x_text->text().toDouble() - bbox_dialog_ui_.size_x_text->text().toDouble() / 2.0;
00209   double maxx = bbox_dialog_ui_.center_x_text->text().toDouble() + bbox_dialog_ui_.size_x_text->text().toDouble() / 2.0;
00210   double stepx = (maxx - minx) / std::max<double>(bbox_dialog_ui_.ngoals_x_text->text().toDouble() - 1, 1);
00211   double miny = bbox_dialog_ui_.center_y_text->text().toDouble() - bbox_dialog_ui_.size_y_text->text().toDouble() / 2.0;
00212   double maxy = bbox_dialog_ui_.center_y_text->text().toDouble() + bbox_dialog_ui_.size_y_text->text().toDouble() / 2.0;
00213   double stepy = (maxy - miny) / std::max<double>(bbox_dialog_ui_.ngoals_y_text->text().toDouble() - 1, 1);
00214   double minz = bbox_dialog_ui_.center_z_text->text().toDouble() - bbox_dialog_ui_.size_z_text->text().toDouble() / 2.0;
00215   double maxz = bbox_dialog_ui_.center_z_text->text().toDouble() + bbox_dialog_ui_.size_z_text->text().toDouble() / 2.0;
00216   double stepz = (maxz - minz) / std::max<double>(bbox_dialog_ui_.ngoals_z_text->text().toDouble() - 1, 1);
00217 
00218   Eigen::Affine3d goal_pose;
00219   goal_pose.setIdentity();
00220   for (std::size_t x = 0; x < bbox_dialog_ui_.ngoals_x_text->text().toShort(); ++x)
00221     for (std::size_t y = 0; y < bbox_dialog_ui_.ngoals_y_text->text().toShort(); ++y)
00222       for (std::size_t z = 0; z < bbox_dialog_ui_.ngoals_z_text->text().toShort(); ++z)
00223       {
00224         goal_pose(0,3) = minx + x * stepx;
00225         goal_pose(1,3) = miny + y * stepy;
00226         goal_pose(2,3) = minz + z * stepz;
00227 
00228         std::stringstream ss;
00229         ss << bbox_dialog_ui_.base_name_text->text().toStdString() << std::setfill('0') << std::setw(4) << goal_poses_.size();
00230 
00231         createGoalAtPose(ss.str(), goal_pose);
00232       }
00233 
00234   populateGoalPosesList();
00235 }
00236 
00237 void MainWindow::removeSelectedGoalsButtonClicked(void)
00238 {
00239   QList<QListWidgetItem*> found_items = ui_.goal_poses_list->selectedItems();
00240   for ( unsigned int i = 0 ; i < found_items.size() ; i++ )
00241   {
00242     goal_poses_.erase(found_items[i]->text().toStdString());
00243   }
00244   populateGoalPosesList();
00245 }
00246 
00247 void MainWindow::removeAllGoalsButtonClicked(void)
00248 {
00249   goal_poses_.clear();
00250   goals_initial_pose_.clear();
00251   populateGoalPosesList();
00252 }
00253 
00254 void MainWindow::loadGoalsFromDBButtonClicked(void)
00255 {
00256   //Get all the constraints from the database, convert to goal pose markers
00257   if (constraints_storage_ && !robot_interaction_->getActiveEndEffectors().empty())
00258   {
00259     //First clear the current list
00260     removeAllGoalsButtonClicked();
00261 
00262     std::vector<std::string> names;
00263     try
00264     {
00265       constraints_storage_->getKnownConstraints(ui_.load_poses_filter_text->text().toStdString(), names);
00266     }
00267     catch (std::runtime_error &ex)
00268     {
00269       QMessageBox::warning(this, "Cannot query the database", QString("Wrongly formatted regular expression for goal poses: ").append(ex.what()));
00270       return;
00271     }
00272 
00273     for (unsigned int i = 0 ; i < names.size() ; i++)
00274     {
00275       //Create a goal pose marker
00276       moveit_warehouse::ConstraintsWithMetadata c;
00277       bool got_constraint = false;
00278       try
00279       {
00280         got_constraint = constraints_storage_->getConstraints(c, names[i]);
00281       }
00282       catch (std::runtime_error &ex)
00283       {
00284         ROS_ERROR("%s", ex.what());
00285       }
00286       if (!got_constraint)
00287         continue;
00288 
00289       if ( c->position_constraints.size() > 0 && c->position_constraints[0].constraint_region.primitive_poses.size() > 0 && c->orientation_constraints.size() > 0 )
00290       {
00291         //Overwrite if exists. TODO: Ask the user before overwriting? copy the existing one with another name before?
00292         if ( goal_poses_.find(c->name) != goal_poses_.end() )
00293         {
00294           goal_poses_.erase(c->name);
00295         }
00296         geometry_msgs::Pose shape_pose;
00297         shape_pose.position = c->position_constraints[0].constraint_region.primitive_poses[0].position;
00298         shape_pose.orientation = c->orientation_constraints[0].orientation;
00299 
00300         Eigen::Affine3d shape_pose_eigen;
00301         tf::poseMsgToEigen(shape_pose, shape_pose_eigen);
00302         goals_initial_pose_.insert(std::pair<std::string, Eigen::Affine3d>(c->name, shape_pose_eigen));
00303 
00304         tf::poseEigenToMsg(shape_pose_eigen * goal_offset_, shape_pose);
00305 
00306         static const float marker_scale = 0.15;
00307         GripperMarkerPtr goal_pose(new GripperMarker(scene_display_->getPlanningSceneRO()->getCurrentState(), scene_display_->getSceneNode(), visualization_manager_, c->name, scene_display_->getRobotModel()->getModelFrame(),
00308                                 robot_interaction_->getActiveEndEffectors()[0], shape_pose, marker_scale, GripperMarker::NOT_TESTED, false,
00309                                 ui_.show_x_checkbox->isChecked(), ui_.show_y_checkbox->isChecked(), ui_.show_z_checkbox->isChecked()));
00310         // Connect signals
00311         goal_pose->connect(this, SLOT( goalPoseFeedback(visualization_msgs::InteractiveMarkerFeedback &) ));
00312 
00313         goal_poses_.insert(GoalPosePair(c->name, goal_pose));
00314       }
00315     }
00316     populateGoalPosesList();
00317    }
00318   else
00319   {
00320     if (!constraints_storage_)
00321       QMessageBox::warning(this, "Warning", "Not connected to a database.");
00322   }
00323 }
00324 
00325 void MainWindow::saveGoalsOnDBButtonClicked(void)
00326 {
00327   saveGoalsToDB();
00328 }
00329 
00330 void MainWindow::deleteGoalsOnDBButtonClicked(void)
00331 {
00332   if (constraints_storage_)
00333   {
00334     //Warn the user
00335     QMessageBox msgBox;
00336     msgBox.setText("All the selected items will be removed from the database");
00337     msgBox.setInformativeText("Do you want to continue?");
00338     msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
00339     msgBox.setDefaultButton(QMessageBox::No);
00340     int ret = msgBox.exec();
00341 
00342     switch (ret)
00343     {
00344       case QMessageBox::Yes:
00345       {
00346         //Go through the list of goal poses, and delete those selected
00347         QList<QListWidgetItem*> found_items = ui_.goal_poses_list->selectedItems();
00348         for ( std::size_t i = 0 ; i < found_items.size() ; i++ )
00349         {
00350           try
00351           {
00352             constraints_storage_->removeConstraints(found_items[i]->text().toStdString());
00353           }
00354           catch (std::runtime_error &ex)
00355           {
00356             ROS_ERROR("%s", ex.what());
00357           }
00358         }
00359         break;
00360       }
00361     }
00362   }
00363   removeSelectedGoalsButtonClicked();
00364 }
00365 
00366 
00367 void MainWindow::loadStatesFromDBButtonClicked(void)
00368 {
00369   //Get all the start states from the database
00370   if (robot_state_storage_)
00371   {
00372     //First clear the current list
00373     removeAllStatesButtonClicked();
00374 
00375     std::vector<std::string> names;
00376     try
00377     {
00378       robot_state_storage_->getKnownRobotStates(ui_.load_states_filter_text->text().toStdString(), names);
00379     }
00380     catch (std::runtime_error &ex)
00381     {
00382       QMessageBox::warning(this, "Cannot query the database", QString("Wrongly formatted regular expression for goal poses: ").append(ex.what()));
00383       return;
00384     }
00385 
00386     for ( unsigned int i = 0 ; i < names.size() ; i++ )
00387     {
00388       moveit_warehouse::RobotStateWithMetadata rs;
00389       bool got_state = false;
00390       try
00391       {
00392         got_state = robot_state_storage_->getRobotState(rs, names[i]);
00393       }
00394       catch(std::runtime_error &ex)
00395       {
00396         ROS_ERROR("%s", ex.what());
00397       }
00398       if (!got_state)
00399         continue;
00400 
00401       //Overwrite if exists.
00402       if (start_states_.find(names[i]) != start_states_.end())
00403       {
00404         start_states_.erase(names[i]);
00405       }
00406 
00407       //Store the current start state
00408       start_states_.insert(StartStatePair(names[i], StartStatePtr(new StartState(*rs))));
00409     }
00410     populateStartStatesList();
00411   }
00412   else
00413   {
00414     QMessageBox::warning(this, "Warning", "Not connected to a database.");
00415   }
00416 }
00417 
00418 void MainWindow::saveStatesOnDBButtonClicked(void)
00419 {
00420   if (robot_state_storage_)
00421   {
00422     //Store all start states
00423     for (StartStateMap::iterator it = start_states_.begin(); it != start_states_.end(); ++it)
00424       try
00425       {
00426         robot_state_storage_->addRobotState(it->second->state_msg, it->first);
00427       }
00428       catch (std::runtime_error &ex)
00429       {
00430         ROS_ERROR("Cannot save robot state: %s", ex.what());
00431       }
00432   }
00433   else
00434   {
00435     QMessageBox::warning(this, "Warning", "Not connected to a database.");
00436   }
00437 }
00438 
00439 void MainWindow::deleteStatesOnDBButtonClicked(void)
00440 {
00441   if (robot_state_storage_)
00442   {
00443     //Warn the user
00444     QMessageBox msgBox;
00445     msgBox.setText("All the selected items will be removed from the database");
00446     msgBox.setInformativeText("Do you want to continue?");
00447     msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
00448     msgBox.setDefaultButton(QMessageBox::No);
00449     int ret = msgBox.exec();
00450 
00451     switch (ret)
00452     {
00453       case QMessageBox::Yes:
00454       {
00455         QList<QListWidgetItem*> found_items =  ui_.start_states_list->selectedItems();
00456         for (unsigned int i = 0; i < found_items.size() ; ++i)
00457         {
00458           try
00459           {
00460             robot_state_storage_->removeRobotState(found_items[i]->text().toStdString());
00461           }
00462           catch (std::runtime_error &ex)
00463           {
00464             ROS_ERROR("%s", ex.what());
00465           }
00466         }
00467         break;
00468       }
00469     }
00470   }
00471   removeSelectedStatesButtonClicked();
00472 }
00473 
00474 void MainWindow::visibleAxisChanged(int state)
00475 {
00476   if ( ! robot_interaction_->getActiveEndEffectors().empty() )
00477   {
00478     for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00479     {
00480       if (it->second->isVisible())
00481       {
00482         it->second->setAxisVisibility(ui_.show_x_checkbox->isChecked(), ui_.show_y_checkbox->isChecked(), ui_.show_z_checkbox->isChecked());
00483       }
00484     }
00485   }
00486 }
00487 
00488 void MainWindow::populateGoalPosesList(void)
00489 {
00490   ui_.goal_poses_list->clear();
00491   for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00492   {
00493     QListWidgetItem *item = new QListWidgetItem(QString(it->first.c_str()));
00494     ui_.goal_poses_list->addItem(item);
00495     if (! it->second->isVisible())
00496     {
00497       item->setBackground(QBrush(Qt::Dense4Pattern));
00498     }
00499     else if (it->second->isSelected())
00500     {
00501       //If selected, highlight in the list
00502       item->setSelected(true);
00503     }
00504   }
00505 }
00506 
00507 void MainWindow::switchGoalVisibilityButtonClicked(void)
00508 {
00509   QList<QListWidgetItem*> selection = ui_.goal_poses_list->selectedItems();
00510   for (std::size_t i = 0; i < selection.size() ; ++i)
00511   {
00512     std::string name = selection[i]->text().toStdString();
00513     if (goal_poses_[name]->isVisible())
00514     {
00515       //Set invisible
00516       goal_poses_[name]->hide();
00517       selection[i]->setBackground(QBrush(Qt::Dense4Pattern));
00518     }
00519     else
00520     {
00521       //Set visible
00522       goal_poses_[name]->show(scene_display_->getSceneNode(), visualization_manager_);
00523       selection[i]->setBackground(QBrush(Qt::NoBrush));
00524     }
00525   }
00526 }
00527 
00528 void MainWindow::goalPoseSelectionChanged(void)
00529 {
00530   for (unsigned int i = 0; i < ui_.goal_poses_list->count() ; ++i)
00531   {
00532     QListWidgetItem *item = ui_.goal_poses_list->item(i);
00533     std::string name = item->text().toStdString();
00534     if ( goal_poses_.find(name) != goal_poses_.end() &&
00535         ( (item->isSelected() && ! goal_poses_[name]->isSelected() )
00536             || ( ! item->isSelected() && goal_poses_[name]->isSelected() )))
00537       switchGoalPoseMarkerSelection(name);
00538   }
00539 }
00540 
00541 void MainWindow::goalPoseDoubleClicked(QListWidgetItem * item)
00542 {
00543   JobProcessing::addBackgroundJob(boost::bind(&MainWindow::computeGoalPoseDoubleClicked, this, item));
00544 }
00545 
00546 void MainWindow::computeGoalPoseDoubleClicked(QListWidgetItem * item)
00547 {
00548   if ( ! robot_interaction_ || robot_interaction_->getActiveEndEffectors().empty() )
00549     return;
00550 
00551   std::string item_text = item->text().toStdString();
00552 
00553   //Switch the marker color to processing color while processing
00554   JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, item_text, GripperMarker::PROCESSING));
00555 
00556   checkIfGoalReachable(item_text, true);
00557 }
00558 
00559 /* Receives feedback from the interactive marker attached to a goal pose */
00560 void MainWindow::goalPoseFeedback(visualization_msgs::InteractiveMarkerFeedback &feedback)
00561 {
00562   if (feedback.event_type == feedback.BUTTON_CLICK)
00563   {
00564     //Unselect all but the clicked one. Needs to be in order, first unselect, then select.
00565     QListWidgetItem *item = 0;
00566     for (unsigned int i = 0; i < ui_.goal_poses_list->count(); ++i)
00567     {
00568       item = ui_.goal_poses_list->item(i);
00569       if ( item->text().toStdString() != feedback.marker_name)
00570         JobProcessing::addMainLoopJob(boost::bind(&MainWindow::selectItemJob, this, item, false));
00571     }
00572 
00573     for (unsigned int i = 0; i < ui_.goal_poses_list->count(); ++i)
00574     {
00575       item = ui_.goal_poses_list->item(i);
00576       if (item->text().toStdString() == feedback.marker_name)
00577         JobProcessing::addMainLoopJob(boost::bind(&MainWindow::selectItemJob, this, item, true));
00578     }
00579   }
00580   else if (feedback.event_type == feedback.MOUSE_DOWN)
00581   {
00582     // First check to see if this mouse_down is happening on an
00583     // already-selected goal pose.  A mouse_down event is sent even if
00584     // the gesture turns out to be nothing but a click.
00585     bool this_goal_already_selected = false;
00586     for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00587     {
00588       if (it->second->isSelected() &&
00589           it->second->isVisible() &&
00590           it->second->imarker->getName() == feedback.marker_name)
00591       {
00592         this_goal_already_selected = true;
00593       }
00594     }
00595 
00596     // If this is a mouse-down on an already-selected goal pose, we
00597     // want to initialize dragging all selected goal poses at the same
00598     // time.
00599     if(this_goal_already_selected) {
00600       //Store current poses
00601       goals_dragging_initial_pose_.clear();
00602       for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00603       {
00604         if (it->second->isSelected() && it->second->isVisible())
00605         {
00606           Eigen::Affine3d pose(Eigen::Quaterniond(it->second->imarker->getOrientation().w, it->second->imarker->getOrientation().x,
00607                                                   it->second->imarker->getOrientation().y, it->second->imarker->getOrientation().z));
00608           pose(0,3) = it->second->imarker->getPosition().x;
00609           pose(1,3) = it->second->imarker->getPosition().y;
00610           pose(2,3) = it->second->imarker->getPosition().z;
00611           goals_dragging_initial_pose_.insert(std::pair<std::string, Eigen::Affine3d>(it->second->imarker->getName(), pose));
00612 
00613           if (it->second->imarker->getName() == feedback.marker_name)
00614             drag_initial_pose_ = pose;
00615         }
00616       }
00617       goal_pose_dragging_=true;
00618     }
00619   }
00620   else if (feedback.event_type == feedback.POSE_UPDATE && goal_pose_dragging_)
00621   {
00622     //Compute displacement from stored pose, and apply to the rest of selected markers
00623     Eigen::Affine3d current_pose_eigen;
00624     tf::poseMsgToEigen(feedback.pose, current_pose_eigen);
00625 
00626     Eigen::Affine3d current_wrt_initial = drag_initial_pose_.inverse() * current_pose_eigen;
00627 
00628     //Display the pose in the ui
00629     Eigen::Vector3d v = current_pose_eigen.linear().eulerAngles(0,1,2);
00630     setStatusFromBackground(STATUS_INFO, QString().sprintf(
00631         "%.2f %.2f %.2f    %.2f %.2f %.2f",
00632         current_pose_eigen(0,3),
00633         current_pose_eigen(1,3),
00634         current_pose_eigen(2,3),
00635         v(0) * 180.0 / boost::math::constants::pi<double>(),
00636         v(1) * 180.0 / boost::math::constants::pi<double>(),
00637         v(2) * 180.0 / boost::math::constants::pi<double>()));
00638 
00639     //Update the rest of selected markers
00640     for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end() ; ++it)
00641     {
00642       if (it->second->isVisible() && it->second->imarker->getName() != feedback.marker_name && it->second->isSelected())
00643       {
00644         visualization_msgs::InteractiveMarkerPose impose;
00645 
00646         Eigen::Affine3d newpose = drag_initial_pose_ * current_wrt_initial * drag_initial_pose_.inverse() * goals_dragging_initial_pose_[it->second->imarker->getName()];
00647         tf::poseEigenToMsg(newpose, impose.pose);
00648 
00649         it->second->imarker->setPose(Ogre::Vector3(impose.pose.position.x, impose.pose.position.y, impose.pose.position.z),
00650                                       Ogre::Quaternion(impose.pose.orientation.w, impose.pose.orientation.x, impose.pose.orientation.y, impose.pose.orientation.z), "");
00651       }
00652     }
00653   } else if (feedback.event_type == feedback.MOUSE_UP)
00654   {
00655     goal_pose_dragging_ = false;
00656     JobProcessing::addBackgroundJob(boost::bind(&MainWindow::checkIfGoalInCollision, this, feedback.marker_name));
00657   }
00658 }
00659 
00660 void MainWindow::checkGoalsReachable(void)
00661 {
00662   for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00663     JobProcessing::addBackgroundJob(boost::bind(&MainWindow::checkIfGoalReachable, this, it->first, false));
00664 }
00665 
00666 void MainWindow::checkGoalsInCollision(void)
00667 {
00668   for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00669     JobProcessing::addBackgroundJob(boost::bind(&MainWindow::checkIfGoalInCollision, this, it->first));
00670 }
00671 
00672 void MainWindow::checkIfGoalReachable(const std::string &goal_name, bool update_if_reachable)
00673 {
00674   if ( goal_poses_.find(goal_name) == goal_poses_.end())
00675     return;
00676 
00677   if ( ! goal_poses_[goal_name]->isVisible())
00678     return;
00679 
00680   const boost::shared_ptr<rviz::InteractiveMarker> &imarker = goal_poses_[goal_name]->imarker;
00681 
00682   geometry_msgs::Pose current_pose_msg;
00683   current_pose_msg.position.x = imarker->getPosition().x;
00684   current_pose_msg.position.y = imarker->getPosition().y;
00685   current_pose_msg.position.z = imarker->getPosition().z;
00686   current_pose_msg.orientation.x = imarker->getOrientation().x;
00687   current_pose_msg.orientation.y = imarker->getOrientation().y;
00688   current_pose_msg.orientation.z = imarker->getOrientation().z;
00689   current_pose_msg.orientation.w = imarker->getOrientation().w;
00690 
00691   // Call to IK
00692   setStatusFromBackground(STATUS_INFO, "Computing inverse kinematics...");
00693   robot_state::RobotState ks(scene_display_->getPlanningSceneRO()->getCurrentState());
00694   static const int ik_attempts = 5;
00695   static const float ik_timeout = 0.2;
00696   bool feasible = robot_interaction_->updateState(ks,
00697                                                   robot_interaction_->getActiveEndEffectors()[0],
00698                                                   current_pose_msg, ik_attempts, ik_timeout);
00699   if (feasible)
00700   {
00701     setStatusFromBackground(STATUS_INFO, "Updating state...");
00702     if (update_if_reachable)
00703     {
00704       scene_display_->getPlanningSceneRW()->setCurrentState(ks);
00705       scene_display_->queueRenderSceneGeometry();
00706     }
00707 
00708     setStatusFromBackground(STATUS_INFO, "Updating marker...");
00709     //Switch the marker color to reachable
00710     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
00711                                                   GripperMarker::REACHABLE));
00712   }
00713   else
00714   {
00715     //Switch the marker color to not-reachable
00716     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
00717                                                   GripperMarker::NOT_REACHABLE));
00718   }
00719   setStatusFromBackground(STATUS_INFO, "");
00720 }
00721 
00722 bool MainWindow::isGroupCollidingWithWorld(robot_state::RobotState& robot_state, const std::string& group_name)
00723 {
00724   collision_detection::AllowedCollisionMatrix acm( scene_display_->getPlanningSceneRO()->getAllowedCollisionMatrix() );
00725   // get link names in group_name
00726   const std::vector<std::string>& group_link_names =
00727     scene_display_->getRobotModel()->getJointModelGroup(group_name)->getLinkModelNamesWithCollisionGeometry();
00728 
00729   // Create a set of links which is all links minus links in the group.
00730   const std::vector<std::string>& all_links = scene_display_->getRobotModel()->getLinkModelNames();
00731   std::set<std::string> link_set(all_links.begin(), all_links.end());
00732   for(size_t i = 0; i < group_link_names.size(); i++ )
00733   {
00734     link_set.erase(group_link_names[i]);
00735   }
00736 
00737   // for each link name in the set,
00738   for(std::set<std::string>::const_iterator it = link_set.begin(); it != link_set.end(); it++ )
00739   {
00740     // allow collisions with link.
00741     acm.setEntry(*it, true);
00742   }
00743 
00744   // call checkCollision();
00745   collision_detection::CollisionRequest req;
00746   req.verbose = false;
00747   collision_detection::CollisionResult  res;
00748   scene_display_->getPlanningSceneRO()->checkCollision(req, res, robot_state, acm);
00749 
00750   // return result boolean.
00751   return res.collision;
00752 }
00753 
00754 void MainWindow::checkIfGoalInCollision(const std::string & goal_name)
00755 {
00756   if ( goal_poses_.find(goal_name) == goal_poses_.end())
00757     return;
00758 
00759   // Check if the end-effector is in collision at the current pose
00760   if ( ! goal_poses_[goal_name]->isVisible())
00761     return;
00762 
00763   const robot_interaction::RobotInteraction::EndEffector &eef = robot_interaction_->getActiveEndEffectors()[0];
00764 
00765   const boost::shared_ptr<rviz::InteractiveMarker> &im = goal_poses_[goal_name]->imarker;
00766   Eigen::Affine3d marker_pose_eigen;
00767   goal_poses_[goal_name]->getPose(marker_pose_eigen);
00768 
00769   robot_state::RobotState ks(scene_display_->getPlanningSceneRO()->getCurrentState());
00770   ks.updateStateWithLinkAt(eef.parent_link, marker_pose_eigen);
00771   bool in_collision = isGroupCollidingWithWorld(ks, eef.eef_group);
00772 
00773   if ( in_collision )
00774   {
00775     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
00776                                                   GripperMarker::IN_COLLISION));
00777   }
00778   else
00779   {
00780     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
00781                                                       GripperMarker::NOT_TESTED));
00782   }
00783 }
00784 
00785 void MainWindow::switchGoalPoseMarkerSelection(const std::string &marker_name)
00786 {
00787   if (robot_interaction_->getActiveEndEffectors().empty() || ! goal_poses_[marker_name]->isVisible())
00788     return;
00789 
00790   if (goal_poses_[marker_name]->isSelected())
00791   {
00792     //If selected, unselect
00793     goal_poses_[marker_name]->unselect();
00794     setItemSelectionInList(marker_name, false, ui_.goal_poses_list);
00795   }
00796   else
00797   {
00798     //If unselected, select. Only display the gripper mesh for one
00799     if (ui_.goal_poses_list->selectedItems().size() == 1)
00800       goal_poses_[marker_name]->select(true);
00801     else
00802       goal_poses_[marker_name]->select(false);
00803     setItemSelectionInList(marker_name, true, ui_.goal_poses_list);
00804   }
00805 }
00806 
00807 void MainWindow::copySelectedGoalPoses(void)
00808 {
00809   QList<QListWidgetItem *> sel = ui_.goal_poses_list->selectedItems();
00810   if (sel.empty() || robot_interaction_->getActiveEndEffectors().empty())
00811     return;
00812 
00813   std::string scene_name;
00814   {
00815     const planning_scene_monitor::LockedPlanningSceneRO &ps = scene_display_->getPlanningSceneRO();
00816     if (!ps)
00817       return;
00818     else
00819       scene_name = ps->getName();
00820   }
00821 
00822   for (int i = 0 ; i < sel.size() ; ++i)
00823   {
00824     std::string name = sel[i]->text().toStdString();
00825     if (! goal_poses_[name]->isVisible())
00826       continue;
00827 
00828     std::stringstream ss;
00829     ss << scene_name.c_str() << "_pose_" << std::setfill('0') << std::setw(4) << goal_poses_.size();
00830 
00831     scene_display_->getPlanningSceneRW()->getCurrentStateNonConst().update();
00832     Eigen::Affine3d tip_pose = scene_display_->getPlanningSceneRO()->getCurrentState().getGlobalLinkTransform(robot_interaction_->getActiveEndEffectors()[0].parent_link);
00833     geometry_msgs::Pose marker_pose;
00834     marker_pose.position.x = goal_poses_[name]->imarker->getPosition().x;
00835     marker_pose.position.y = goal_poses_[name]->imarker->getPosition().y;
00836     marker_pose.position.z = goal_poses_[name]->imarker->getPosition().z;
00837     marker_pose.orientation.x = goal_poses_[name]->imarker->getOrientation().x;
00838     marker_pose.orientation.y = goal_poses_[name]->imarker->getOrientation().y;
00839     marker_pose.orientation.z = goal_poses_[name]->imarker->getOrientation().z;
00840     marker_pose.orientation.w = goal_poses_[name]->imarker->getOrientation().w;
00841 
00842     static const float marker_scale = 0.15;
00843     GripperMarkerPtr goal_pose(new GripperMarker(scene_display_->getPlanningSceneRO()->getCurrentState(), scene_display_->getSceneNode(), visualization_manager_, ss.str(), scene_display_->getRobotModel()->getModelFrame(),
00844                             robot_interaction_->getActiveEndEffectors()[0], marker_pose, marker_scale, GripperMarker::NOT_TESTED, true));
00845 
00846     goal_poses_.insert(GoalPosePair(ss.str(), goal_pose));
00847 
00848     // Connect signals
00849     goal_pose->connect(this, SLOT( goalPoseFeedback(visualization_msgs::InteractiveMarkerFeedback &)));
00850 
00851     //Unselect the marker source of the copy
00852     switchGoalPoseMarkerSelection(name);
00853   }
00854 
00855   JobProcessing::addMainLoopJob(boost::bind(&MainWindow::populateGoalPosesList, this));
00856 }
00857 
00858 void MainWindow::saveStartStateButtonClicked(void)
00859 {
00860   bool ok = false;
00861 
00862   std::stringstream ss;
00863   ss << scene_display_->getRobotModel()->getName().c_str() << "_state_" << std::setfill('0') << std::setw(4) << start_states_.size();
00864 
00865   QString text = QInputDialog::getText(this, tr("Choose a name"),
00866                                        tr("Start state name:"), QLineEdit::Normal,
00867                                        QString(ss.str().c_str()), &ok);
00868 
00869   std::string name;
00870   if (ok)
00871   {
00872     if (!text.isEmpty())
00873     {
00874       name = text.toStdString();
00875       if (start_states_.find(name) != start_states_.end())
00876         QMessageBox::warning(this, "Name already exists", QString("The name '").append(name.c_str()).
00877                              append("' already exists. Not creating state."));
00878       else
00879       {
00880         //Store the current start state
00881         moveit_msgs::RobotState msg;
00882         robot_state::robotStateToRobotStateMsg(scene_display_->getPlanningSceneRO()->getCurrentState(), msg);
00883         start_states_.insert(StartStatePair(name, StartStatePtr(new StartState(msg))));
00884 
00885         //Save to the database if connected
00886         if (robot_state_storage_)
00887         {
00888           try
00889           {
00890               robot_state_storage_->addRobotState(msg, name);
00891           }
00892           catch (std::runtime_error &ex)
00893           {
00894             ROS_ERROR("Cannot save robot state on the database: %s", ex.what());
00895           }
00896         }
00897       }
00898     }
00899     else
00900       QMessageBox::warning(this, "Start state not saved", "Cannot use an empty name for a new start state.");
00901   }
00902   populateStartStatesList();
00903 }
00904 
00905 void MainWindow::removeSelectedStatesButtonClicked(void)
00906 {
00907   QList<QListWidgetItem*> found_items = ui_.start_states_list->selectedItems();
00908   for (unsigned int i = 0; i < found_items.size(); i++)
00909   {
00910     start_states_.erase(found_items[i]->text().toStdString());
00911   }
00912   populateStartStatesList();
00913 }
00914 
00915 void MainWindow::removeAllStatesButtonClicked(void)
00916 {
00917   start_states_.clear();
00918   populateStartStatesList();
00919 }
00920 
00921 void MainWindow::populateStartStatesList(void)
00922 {
00923   ui_.start_states_list->clear();
00924   for (StartStateMap::iterator it = start_states_.begin(); it != start_states_.end(); ++it)
00925   {
00926     QListWidgetItem *item = new QListWidgetItem(QString(it->first.c_str()));
00927     ui_.start_states_list->addItem(item);
00928     if (it->second->selected)
00929     {
00930       //If selected, highlight in the list
00931       item->setSelected(true);
00932     }
00933   }
00934 }
00935 
00936 void MainWindow::startStateItemDoubleClicked(QListWidgetItem * item)
00937 {
00938   scene_display_->getPlanningSceneRW()->setCurrentState(start_states_[item->text().toStdString()]->state_msg);
00939   scene_display_->queueRenderSceneGeometry();
00940 }
00941 
00942 void MainWindow::runBenchmark(void)
00943 {
00944   if (! robot_interaction_ || robot_interaction_->getActiveEndEffectors().size() == 0)
00945   {
00946     QMessageBox::warning(this, "Error", "Please make sure a planning group with an end-effector is active");
00947     return;
00948   }
00949 
00950   run_benchmark_ui_.benchmark_goal_text->setText(ui_.load_poses_filter_text->text());
00951   run_benchmark_ui_.benchmark_start_state_text->setText(ui_.load_states_filter_text->text());
00952 
00953   // Load available planners
00954   boost::shared_ptr<pluginlib::ClassLoader<planning_interface::PlannerManager> > planner_plugin_loader;
00955   std::map<std::string, planning_interface::PlannerManagerPtr> planner_interfaces;
00956   try
00957   {
00958     planner_plugin_loader.reset(new pluginlib::ClassLoader<planning_interface::PlannerManager>("moveit_core", "planning_interface::PlannerManager"));
00959   }
00960   catch(pluginlib::PluginlibException& ex)
00961   {
00962     ROS_FATAL_STREAM("Exception while creating planning plugin loader " << ex.what());
00963   }
00964 
00965   if (planner_plugin_loader)
00966   {
00967     // load the planning plugins
00968     const std::vector<std::string> &classes = planner_plugin_loader->getDeclaredClasses();
00969     for (std::size_t i = 0 ; i < classes.size() ; ++i)
00970     {
00971       ROS_DEBUG("Attempting to load and configure %s", classes[i].c_str());
00972       try
00973       {
00974         boost::shared_ptr<planning_interface::PlannerManager> p = planner_plugin_loader->createInstance(classes[i]);
00975         p->initialize(scene_display_->getPlanningSceneRO()->getRobotModel(), "");
00976         planner_interfaces[classes[i]] = p;
00977       }
00978       catch (pluginlib::PluginlibException& ex)
00979       {
00980         ROS_ERROR_STREAM("Exception while loading planner '" << classes[i] << "': " << ex.what());
00981       }
00982     }
00983 
00984     //Get the list of planning interfaces and planning algorithms
00985     if (! planner_interfaces.empty())
00986     {
00987       std::stringstream interfaces_ss, algorithms_ss;
00988       for (std::map<std::string, boost::shared_ptr<planning_interface::PlannerManager> >::const_iterator it = planner_interfaces.begin() ;
00989           it != planner_interfaces.end(); ++it)
00990       {
00991         interfaces_ss << it->first << " ";
00992 
00993         std::vector<std::string> known;
00994         it->second->getPlanningAlgorithms(known);
00995         for (std::size_t i = 0; i < known.size(); ++i)
00996           algorithms_ss << known[i] << " ";
00997       }
00998       ROS_DEBUG("Available planner instances: %s. Available algorithms: %s", interfaces_ss.str().c_str(), algorithms_ss.str().c_str());
00999       run_benchmark_ui_.planning_interfaces_text->setText(QString(interfaces_ss.str().c_str()));
01000       run_benchmark_ui_.planning_algorithms_text->setText(QString(algorithms_ss.str().c_str()));
01001     }
01002   }
01003 
01004   run_benchmark_dialog_->show();
01005 }
01006 
01007 void MainWindow::benchmarkFolderButtonClicked(void)
01008 {
01009   QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
01010                                                   "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
01011   run_benchmark_ui_.benchmark_output_folder_text->setText(dir);
01012 }
01013 
01014 void MainWindow::cancelBenchmarkButtonClicked(void)
01015 {
01016   run_benchmark_dialog_->close();
01017 }
01018 
01019 bool MainWindow::saveBenchmarkConfigButtonClicked(void)
01020 {
01021   if (run_benchmark_ui_.benchmark_output_folder_text->text().isEmpty())
01022   {
01023     QMessageBox::warning(this, "Missing data", "Must specify an output folder");
01024     return false;
01025   }
01026 
01027   QString outfilename =  run_benchmark_ui_.benchmark_output_folder_text->text().append("/config.cfg");
01028   std::ofstream outfile(outfilename.toUtf8());
01029   if (outfile)
01030   {
01031     outfile << "[scene]" << std::endl;
01032     outfile << "group=" << ui_.planning_group_combo->currentText().toStdString() << std::endl;
01033     outfile << "default_constrained_link=" << robot_interaction_->getActiveEndEffectors()[0].parent_link << std::endl;
01034     outfile << "planning_frame=" << scene_display_->getPlanningSceneMonitor()->getRobotModel()->getModelFrame() << std::endl;
01035     outfile << "name=" << scene_display_->getPlanningSceneRO()->getName() << std::endl;
01036 
01037     outfile << "timeout=" << run_benchmark_ui_.timeout_spin->value() << std::endl;
01038     outfile << "runs=" << run_benchmark_ui_.number_of_runs_spin->value() << std::endl;
01039     outfile << "output=" << run_benchmark_ui_.benchmark_output_folder_text->text().toStdString() << "/" << scene_display_->getPlanningSceneMonitor()->getRobotModel()->getName() << "_" <<
01040         scene_display_->getPlanningSceneRO()->getName() << "_" <<
01041         ros::Time::now() << std::endl;
01042     outfile << "start=" << run_benchmark_ui_.benchmark_start_state_text->text().toStdString() << std::endl;
01043     outfile << "query=" << std::endl;
01044     outfile << "goal=" << run_benchmark_ui_.benchmark_goal_text->text().toStdString() << std::endl;
01045     outfile << "goal_offset_roll=" << ui_.goal_offset_roll->value() << std::endl;
01046     outfile << "goal_offset_pitch=" << ui_.goal_offset_pitch->value() << std::endl;
01047     outfile << "goal_offset_yaw=" << ui_.goal_offset_yaw->value() << std::endl << std::endl;
01048 
01049     outfile << "[plugin]" << std::endl;
01050     outfile << "name=" << run_benchmark_ui_.planning_interfaces_text->text().toStdString() << std::endl;
01051     outfile << "planners=" << run_benchmark_ui_.planning_algorithms_text->text().toStdString() << std::endl;
01052 
01053     outfile.close();
01054 
01055     run_benchmark_dialog_->close();
01056   }
01057   else
01058   {
01059     QMessageBox::warning(this, "Error", QString("Cannot open file ").append(outfilename).append(" for writing"));
01060     return false;
01061   }
01062 
01063   return true;
01064 }
01065 
01066 void MainWindow::runBenchmarkButtonClicked(void)
01067 {
01068   if (! saveBenchmarkConfigButtonClicked())
01069     return;
01070 
01071   QMessageBox msgBox;
01072   msgBox.setText("This will run the benchmark pipeline. The process will take several minutes during which you will not be able to interact with the interface. You can follow the progress in the console output");
01073   msgBox.setInformativeText("Do you want to continue?");
01074   msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
01075   msgBox.setDefaultButton(QMessageBox::Yes);
01076   int ret = msgBox.exec();
01077 
01078   switch (ret)
01079   {
01080     case QMessageBox::Yes:
01081     {
01082       QString outfilename =  run_benchmark_ui_.benchmark_output_folder_text->text().append("/config.cfg");
01083       moveit_benchmarks::BenchmarkType btype = 0;
01084       moveit_benchmarks::BenchmarkExecution be(scene_display_->getPlanningSceneMonitor()->getPlanningScene(), database_host_, database_port_);
01085       if (run_benchmark_ui_.benchmark_include_planners_checkbox->isChecked())
01086         btype += moveit_benchmarks::BENCHMARK_PLANNERS;
01087       if (run_benchmark_ui_.benchmark_check_reachability_checkbox->isChecked())
01088         btype += moveit_benchmarks::BENCHMARK_GOAL_EXISTANCE;
01089 
01090       if (be.readOptions(outfilename.toStdString()))
01091       {
01092         std::stringstream ss;
01093         be.printOptions(ss);
01094         ROS_INFO_STREAM("Calling benchmark with options:" << std::endl << ss.str() << std::endl);
01095 
01096         BenchmarkProcessingThread benchmark_thread(be, btype, this);
01097         benchmark_thread.startAndShow();
01098 
01099         if (benchmark_thread.isRunning())
01100         {
01101           benchmark_thread.terminate();
01102           benchmark_thread.wait();
01103           QMessageBox::warning(this, "", "Benchmark computation canceled");
01104         }
01105         else
01106         {
01107           QMessageBox::information(this, "Benchmark computation finished", QString("The results were logged into '").append(run_benchmark_ui_.benchmark_output_folder_text->text()));
01108         }
01109       }
01110 
01111       break;
01112     }
01113   }
01114 }
01115 
01116 void MainWindow::loadBenchmarkResults(void)
01117 {
01118   //Select a log file of the set.
01119   QString path = QFileDialog::getOpenFileName(this, tr("Select a log file in the set"), tr(""), tr("Log files (*.log)"));
01120   if (!path.isEmpty())
01121   {
01122     JobProcessing::addBackgroundJob(boost::bind(&MainWindow::computeLoadBenchmarkResults, this, path.toStdString()));
01123   }
01124 }
01125 
01126 void MainWindow::computeLoadBenchmarkResults(const std::string &file)
01127 {
01128   std::string logid, basename, logid_text;
01129   try
01130   {
01131     logid = file.substr( file.find_last_of(".", file.length()-5) + 1, file.find_last_of(".") - file.find_last_of(".", file.length()-5) - 1 );
01132     basename = file.substr(0, file.find_last_of(".", file.length()-5));
01133     logid_text = logid.substr(logid.find_first_of("_"), logid.length() - logid.find_first_of("_"));
01134   }
01135   catch (...)
01136   {
01137     ROS_ERROR("Invalid benchmark log file. Cannot load results.");
01138     return;
01139   }
01140 
01141   int count = 1;
01142   bool more_files = true;
01143   //Parse all the log files in the set
01144   while (more_files)
01145   {
01146     std::ifstream ifile;
01147     std::stringstream file_to_load;
01148     file_to_load << basename << "." << count << logid_text << ".log";
01149 
01150     ifile.open(file_to_load.str().c_str());
01151     if (ifile.good())
01152     {
01153       //Parse results
01154       char text_line[512];
01155       static std::streamsize text_line_length = 512;
01156       bool valid_file = false;
01157       ifile.getline(text_line, text_line_length);
01158 
01159       //Check if the file is valid. The first line must contain "Experiment <scene>". There must be a "total_time" line, followed by the results
01160       if (ifile.good() && strstr(text_line, "Experiment") != NULL && strlen(text_line) > 11
01161           && strncmp(&text_line[11], scene_display_->getPlanningSceneRO()->getName().c_str(), scene_display_->getPlanningSceneRO()->getName().length()) == 0)
01162       {
01163         while (ifile.good())
01164         {
01165           if ( strstr(text_line, "total_time REAL") != NULL)
01166           {
01167             valid_file = true;
01168             break;
01169           }
01170 
01171           ifile.getline(text_line, text_line_length);
01172         }
01173       }
01174       else
01175       {
01176         ROS_ERROR("Not a valid log file, or a different planning scene loaded");
01177       }
01178 
01179       if (valid_file)
01180       {
01181         if (basename.find(".trajectory") != std::string::npos)
01182         {
01183           //Trajectory results may contain multiple goals
01184           int nwaypoint = 0;
01185           while (ifile.getline(text_line, text_line_length) && ifile.good() && strlen(text_line) > 6)
01186           {
01187             //This should be a reachability results line composed of reachable, collision-free and time fields (bool; bool; float)
01188             try
01189             {
01190               bool reachable = boost::lexical_cast<bool>(text_line[0]);
01191               bool collision_free = boost::lexical_cast<bool>(text_line[3]);
01192 
01193 
01194               //Update colors accordingly
01195               if (count <= trajectories_.size())
01196               {
01197                 std::string trajectory_name = ui_.trajectory_list->item(count-1)->text().toStdString();
01198                 if ( nwaypoint < trajectories_[trajectory_name]->waypoint_markers.size() )
01199                 {
01200                   if (reachable)
01201                   {
01202                     if (collision_free)
01203                     {
01204                       //Reachable and collision-free
01205                       JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateMarkerState, this, trajectories_[trajectory_name]->waypoint_markers[nwaypoint],
01206                                                                 GripperMarker::REACHABLE));
01207                     }
01208                     else
01209                     {
01210                       //Reachable, but in collision
01211                       JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateMarkerState, this, trajectories_[trajectory_name]->waypoint_markers[nwaypoint],
01212                                                                 GripperMarker::IN_COLLISION));
01213                     }
01214                   }
01215                   else
01216                   {
01217                     //Not reachable
01218                     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateMarkerState, this, trajectories_[trajectory_name]->waypoint_markers[nwaypoint],
01219                                                               GripperMarker::NOT_REACHABLE));
01220                   }
01221                 }
01222               }
01223               nwaypoint++;
01224             }
01225             catch (...)
01226             {
01227               ROS_ERROR("Error parsing the log file");
01228             }
01229           }
01230         }
01231         else
01232         {
01233           ifile.getline(text_line, text_line_length);
01234           if (ifile.good() && strlen(text_line) > 6)
01235           {
01236             //This should be the reachability results line composed of reachable, collision-free and time fields (bool; bool; float)
01237             try
01238             {
01239               bool reachable = boost::lexical_cast<bool>(text_line[0]);
01240               bool collision_free = boost::lexical_cast<bool>(text_line[3]);
01241 
01242               //Update colors accordingly
01243               if (count <= goal_poses_.size())
01244               {
01245                 std::string goal_name = ui_.goal_poses_list->item(count-1)->text().toStdString();
01246                 if (reachable)
01247                 {
01248                   if (collision_free)
01249                   {
01250                     //Reachable and collision-free
01251                     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
01252                                                               GripperMarker::REACHABLE));
01253                   }
01254                   else
01255                   {
01256                     //Reachable, but in collision
01257                     JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
01258                                                               GripperMarker::IN_COLLISION));
01259                   }
01260                 }
01261                 else
01262                 {
01263                   //Not reachable
01264                   JobProcessing::addMainLoopJob(boost::bind(&MainWindow::updateGoalMarkerStateFromName, this, goal_name,
01265                                                             GripperMarker::NOT_REACHABLE));
01266                 }
01267               }
01268             }
01269             catch (...)
01270             {
01271               ROS_ERROR("Error parsing the log file");
01272             }
01273           }
01274         }
01275       }
01276       else
01277       {
01278         ROS_ERROR("Invalid benchmark log file. Cannot load results.");
01279       }
01280 
01281       ifile.close();
01282     }
01283     else
01284     {
01285       more_files = false;
01286     }
01287     count++;
01288   }
01289 }
01290 
01291 void MainWindow::updateGoalMarkerStateFromName(const std::string &name, const GripperMarker::GripperMarkerState &state)
01292 {
01293   if ( goal_poses_.find(name) != goal_poses_.end())
01294     goal_poses_[name]->setState(state);
01295 }
01296 
01297 void MainWindow::updateMarkerState(GripperMarkerPtr marker, const GripperMarker::GripperMarkerState &state)
01298 {
01299   marker->setState(state);
01300 }
01301 
01302 void MainWindow::goalOffsetChanged()
01303 {
01304   goal_offset_.setIdentity();
01305   goal_offset_ = Eigen::AngleAxisd(ui_.goal_offset_roll->value() * boost::math::constants::pi<double>() / 180.0, Eigen::Vector3d::UnitX()) *
01306       Eigen::AngleAxisd(ui_.goal_offset_pitch->value() * boost::math::constants::pi<double>() / 180.0, Eigen::Vector3d::UnitY()) *
01307       Eigen::AngleAxisd(ui_.goal_offset_yaw->value() * boost::math::constants::pi<double>() / 180.0, Eigen::Vector3d::UnitZ());
01308 
01309   if ( ! robot_interaction_->getActiveEndEffectors().empty() )
01310   {
01311     Eigen::Affine3d current_pose;
01312     for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
01313     {
01314       current_pose = goals_initial_pose_[it->first] * goal_offset_;
01315       it->second->setPose(current_pose);
01316     }
01317   }
01318 }
01319 
01320 } //namespace


benchmarks_gui
Author(s): Mario Prats
autogenerated on Wed Aug 26 2015 12:44:27