main_window.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  * Author: Mario Prats, Ioan Sucan
00030  */
00031 
00032 #include <main_window.h>
00033 #include <ui_utils.h>
00034 
00035 #include <QShortcut>
00036 #include <QFileDialog>
00037 
00038 #include <assert.h>
00039 #include <string>
00040 #include <rviz/tool_manager.h>
00041 #include <rviz/frame_manager.h>
00042 #include <rviz/display_factory.h>
00043 #include <rviz/selection/selection_manager.h>
00044 
00045 namespace benchmark_tool
00046 {
00047 
00048 const char * MainWindow::ROBOT_DESCRIPTION_PARAM = "robot_description";
00049 const char * MainWindow::ROBOT_DESCRIPTION_SEMANTIC_PARAM = "robot_description_semantic";
00050 const unsigned int MainWindow::DEFAULT_WAREHOUSE_PORT = 33830;
00051 
00052 MainWindow::MainWindow(int argc, char **argv, QWidget *parent) :
00053     QMainWindow(parent),
00054     goal_pose_dragging_(false)
00055 {
00056   setWindowTitle("Benchmark Tool");
00057 
00058   goal_offset_.setIdentity();
00059 
00060   ui_.setupUi(this);
00061   settings_.reset(new QSettings("WillowGarage", "Benchmark Tool"));
00062   QVariant previous_database_names = settings_->value("database_name", QStringList());
00063   ui_.db_combo->addItems(previous_database_names.toStringList());
00064 
00065   robot_loader_dialog_ = new QDialog(0,0);
00066   load_robot_ui_.setupUi(robot_loader_dialog_);
00067 
00068   //Rviz render panel
00069   render_panel_ = new rviz::RenderPanel();
00070   ui_.render_widget->addWidget(render_panel_);
00071   ui_.splitter->setStretchFactor(1, 4);
00072 
00073   visualization_manager_ = new rviz::VisualizationManager(render_panel_);
00074   render_panel_->initialize(visualization_manager_->getSceneManager(), visualization_manager_);
00075 
00076   visualization_manager_->initialize();
00077   visualization_manager_->startUpdate();
00078 
00079   //Grid display
00080   visualization_manager_->createDisplay("rviz/Grid", "Grid", true);
00081 
00082   //Planning scene display
00083   scene_display_ = new moveit_rviz_plugin::PlanningSceneDisplay();
00084   scene_display_->setName("Planning Scene");
00085   scene_display_->subProp("Robot Description")->setValue(ROBOT_DESCRIPTION_PARAM);
00086   scene_display_->subProp("Scene Geometry")->subProp("Scene Alpha")->setValue(1.0);
00087   visualization_manager_->addDisplay( scene_display_, true );
00088 
00089   //Interactive Marker display
00090   int_marker_display_ = visualization_manager_->getDisplayFactory()->make("rviz/InteractiveMarkers");
00091   int_marker_display_->initialize(visualization_manager_);
00092   int_marker_display_->setEnabled(true);
00093   int_marker_display_->subProp("Update Topic")->setValue(QString::fromStdString(robot_interaction::RobotInteraction::INTERACTIVE_MARKER_TOPIC + "/update"));
00094 
00095   if ( scene_display_ )
00096   {
00097     if (waitForPlanningSceneMonitor(scene_display_))
00098     {
00099       configure();
00100     }
00101     else
00102     {
00103       ROS_INFO("Couldn't find a valid robot description in the parameter server. Please load a robot on the GUI.");
00104     }
00105 
00106     if (ui_.planning_group_combo->count() > 0)
00107     {
00108       planningGroupChanged(ui_.planning_group_combo->currentText());
00109     }
00110 
00111     rviz::Tool * interact_tool = visualization_manager_->getToolManager()->addTool("rviz/Interact");
00112     if (interact_tool)
00113     {
00114       visualization_manager_->getToolManager()->setCurrentTool(interact_tool);
00115       interact_tool->activate();
00116     }
00117     visualization_manager_->getSelectionManager()->enableInteraction(true);
00118 
00119     //Setup ui: colors and icons
00120     ui_.db_connect_button->setStyleSheet("QPushButton { color : red }");
00121 
00122     ui_.goal_poses_open_button->setIcon(QIcon::fromTheme("document-open", QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon)));
00123     ui_.goal_poses_add_button->setIcon(QIcon::fromTheme("list-add", QApplication::style()->standardIcon(QStyle::SP_FileDialogNewFolder)));
00124     ui_.goal_poses_remove_button->setIcon(QIcon::fromTheme("list-remove", QApplication::style()->standardIcon(QStyle::SP_DialogDiscardButton)));
00125     ui_.goal_poses_save_button->setIcon(QIcon::fromTheme("document-save", QApplication::style()->standardIcon(QStyle::SP_DriveFDIcon)));
00126     ui_.goal_switch_visibility_button->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogDiscardButton));
00127 
00128     ui_.start_states_open_button->setIcon(QIcon::fromTheme("document-open", QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon)));
00129     ui_.start_states_add_button->setIcon(QIcon::fromTheme("list-add", QApplication::style()->standardIcon(QStyle::SP_FileDialogNewFolder)));
00130     ui_.start_states_remove_button->setIcon(QIcon::fromTheme("list-remove", QApplication::style()->standardIcon(QStyle::SP_DialogDiscardButton)));
00131     ui_.start_states_save_button->setIcon(QIcon::fromTheme("document-save", QApplication::style()->standardIcon(QStyle::SP_DriveFDIcon)));
00132 
00133     ui_.trajectory_open_button->setIcon(QIcon::fromTheme("document-open", QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon)));
00134     ui_.trajectory_add_button->setIcon(QIcon::fromTheme("list-add", QApplication::style()->standardIcon(QStyle::SP_FileDialogNewFolder)));
00135     ui_.trajectory_remove_button->setIcon(QIcon::fromTheme("list-remove", QApplication::style()->standardIcon(QStyle::SP_DialogDiscardButton)));
00136     ui_.trajectory_save_button->setIcon(QIcon::fromTheme("document-save", QApplication::style()->standardIcon(QStyle::SP_DriveFDIcon)));
00137 
00138     //Connect signals and slots
00139     connect(ui_.actionExit, SIGNAL( triggered(bool) ), this, SLOT( exitActionTriggered(bool) ));
00140     connect(ui_.actionOpen, SIGNAL( triggered(bool) ), this, SLOT( openActionTriggered(bool) ));
00141     connect(ui_.planning_group_combo, SIGNAL( currentIndexChanged ( const QString & ) ), this, SLOT( planningGroupChanged( const QString & ) ));
00142     connect(ui_.db_connect_button, SIGNAL( clicked() ), this, SLOT( dbConnectButtonClicked() ));
00143     connect(ui_.load_scene_button, SIGNAL( clicked() ), this, SLOT( loadSceneButtonClicked() ));
00144     connect(ui_.planning_scene_list, SIGNAL( itemDoubleClicked (QListWidgetItem *) ), this, SLOT( loadSceneButtonClicked(QListWidgetItem *) ));
00145     connect(ui_.robot_interaction_button, SIGNAL( clicked() ), this, SLOT( robotInteractionButtonClicked() ));
00146 
00147     //Goal poses
00148     connect( ui_.goal_poses_add_button, SIGNAL( clicked() ), this, SLOT( createGoalPoseButtonClicked() ));
00149     connect( ui_.goal_poses_remove_button, SIGNAL( clicked() ), this, SLOT( deleteGoalsOnDBButtonClicked() ));
00150     connect( ui_.load_poses_filter_text, SIGNAL( returnPressed() ), this, SLOT( loadGoalsFromDBButtonClicked() ));
00151     connect( ui_.goal_poses_open_button, SIGNAL( clicked() ), this, SLOT( loadGoalsFromDBButtonClicked() ));
00152     connect( ui_.goal_poses_save_button, SIGNAL( clicked() ), this, SLOT( saveGoalsOnDBButtonClicked() ));
00153     connect( ui_.goal_switch_visibility_button, SIGNAL( clicked() ), this, SLOT( switchGoalVisibilityButtonClicked() ));
00154     connect( ui_.goal_poses_list, SIGNAL( itemSelectionChanged() ), this, SLOT( goalPoseSelectionChanged() ));
00155     connect( ui_.goal_poses_list, SIGNAL( itemDoubleClicked(QListWidgetItem *) ), this, SLOT( goalPoseDoubleClicked(QListWidgetItem *) ));
00156     connect( ui_.show_x_checkbox, SIGNAL( stateChanged( int ) ), this, SLOT( visibleAxisChanged( int ) ));
00157     connect( ui_.show_y_checkbox, SIGNAL( stateChanged( int ) ), this, SLOT( visibleAxisChanged( int ) ));
00158     connect( ui_.show_z_checkbox, SIGNAL( stateChanged( int ) ), this, SLOT( visibleAxisChanged( int ) ));
00159     connect( ui_.goal_offset_roll, SIGNAL( editingFinished ( )), this, SLOT( goalOffsetChanged( ) ));
00160     connect( ui_.goal_offset_pitch, SIGNAL( editingFinished ( )), this, SLOT( goalOffsetChanged( ) ));
00161     connect( ui_.goal_offset_yaw, SIGNAL( editingFinished ( )), this, SLOT( goalOffsetChanged( ) ));
00162 
00163     connect( ui_.check_goal_collisions_button, SIGNAL( clicked( ) ), this, SLOT( checkGoalsInCollision( ) ));
00164     connect( ui_.check_goal_reachability_button, SIGNAL( clicked( ) ), this, SLOT( checkGoalsReachable( ) ));
00165     connect( ui_.run_benchmark_button, SIGNAL( clicked( ) ), this, SLOT( runBenchmark( ) ));
00166     connect( ui_.load_results_button, SIGNAL( clicked( ) ), this, SLOT( loadBenchmarkResults( ) ));
00167 
00168     connect( ui_.start_states_add_button, SIGNAL( clicked() ), this, SLOT( saveStartStateButtonClicked() ));
00169     connect( ui_.start_states_remove_button, SIGNAL( clicked() ), this, SLOT( deleteStatesOnDBButtonClicked() ));
00170     connect( ui_.load_states_filter_text, SIGNAL( returnPressed() ), this, SLOT( loadStatesFromDBButtonClicked() ));
00171     connect( ui_.start_states_open_button, SIGNAL( clicked() ), this, SLOT( loadStatesFromDBButtonClicked() ));
00172     connect( ui_.start_states_save_button, SIGNAL( clicked() ), this, SLOT( saveStatesOnDBButtonClicked() ));
00173     connect( ui_.start_states_list, SIGNAL( itemDoubleClicked(QListWidgetItem*) ), this, SLOT( startStateItemDoubleClicked(QListWidgetItem*) ));
00174 
00175     QShortcut *copy_goals_shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), ui_.goal_poses_list);
00176     connect(copy_goals_shortcut, SIGNAL( activated() ), this, SLOT( copySelectedGoalPoses() ) );
00177 
00178     //Trajectories
00179     connect( ui_.trajectory_add_button, SIGNAL( clicked() ), this, SLOT( createTrajectoryButtonClicked() ));
00180     connect( ui_.trajectory_remove_button, SIGNAL( clicked() ), this, SLOT( removeTrajectoryButtonClicked() ));
00181     connect( ui_.trajectory_open_button, SIGNAL( clicked() ), this, SLOT( loadTrajectoriesFromDBButtonClicked() ));
00182     connect( ui_.trajectory_save_button, SIGNAL( clicked() ), this, SLOT( saveTrajectoriesOnDBButtonClicked() ));
00183     connect( ui_.trajectory_list, SIGNAL( itemSelectionChanged() ), this, SLOT( trajectorySelectionChanged() ));
00184     connect( ui_.trajectory_nwaypoints_spin, SIGNAL( valueChanged ( int )), this, SLOT( trajectoryNWaypointsChanged( int ) ));
00185     connect( ui_.trajectory_execute_button, SIGNAL( clicked() ), this, SLOT( trajectoryExecuteButtonClicked() ));
00186 
00187     //Start a QTimer for handling main loop jobs
00188     main_loop_jobs_timer_.reset(new QTimer(this));
00189     connect(main_loop_jobs_timer_.get(), SIGNAL( timeout() ), this, SLOT( MainLoop() ));
00190     main_loop_jobs_timer_->start(1000 / MAIN_LOOP_RATE);
00191   }
00192   else
00193   {
00194     ROS_ERROR("Cannot load robot. Is the robot_description parameter set?");
00195     exit(0);
00196   }
00197 }
00198 
00199 MainWindow::~MainWindow()
00200 {
00201 }
00202 
00203 bool MainWindow::waitForPlanningSceneMonitor(moveit_rviz_plugin::PlanningSceneDisplay *scene_display)
00204 {
00205   //Wait until the planning scene monitor is up
00206   ros::Time tstart = ros::Time::now();
00207   static const double psm_waiting_timeout = 10.0;
00208   while (! scene_display->getPlanningSceneMonitor() && (ros::Time::now() - tstart) < ros::Duration(psm_waiting_timeout))
00209   {
00210     ROS_INFO_ONCE("Waiting for the planning scene monitor...");
00211     scene_display->update(0.1, 0.1);
00212   }
00213 
00214   return scene_display->getPlanningSceneMonitor();
00215 }
00216 
00217 void MainWindow::exitActionTriggered(bool)
00218 {
00219   QApplication::quit();
00220 }
00221 
00222 void MainWindow::openActionTriggered(bool)
00223 {
00224   QString urdf_path = QFileDialog::getOpenFileName(this, tr("Select a robot description file"), tr(""), tr("URDF files (*.urdf)"));
00225 
00226   if (!urdf_path.isEmpty())
00227   {
00228     QString srdf_path = QFileDialog::getOpenFileName(this, tr("Select a semantic robot description file"), tr(""), tr("SRDF files (*.srdf)"));
00229 
00230     if (!srdf_path.isEmpty())
00231     {
00232       loadNewRobot(urdf_path.toStdString(), srdf_path.toStdString());
00233     }
00234   }
00235 }
00236 
00237 void MainWindow::loadNewRobot(const std::string &urdf_path, const std::string &srdf_path)
00238 {
00239   load_robot_ui_.status_label->setText("");
00240   load_robot_ui_.load_progress_bar->setValue(0);
00241 
00242   robot_loader_dialog_->show();
00243 
00244   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
00245 
00246   //Load urdf
00247   boost::filesystem::path boost_urdf_path(urdf_path);
00248   load_robot_ui_.status_label->setText(QString::fromStdString("Loading urdf " + boost_urdf_path.string()));
00249   load_robot_ui_.load_progress_bar->setValue(10);
00250   if (boost::filesystem::exists(boost_urdf_path))
00251   {
00252     std::ifstream urdf_input_stream(boost_urdf_path.string().c_str());
00253     std::stringstream urdf_sstr;
00254     urdf_sstr << urdf_input_stream.rdbuf();
00255     ros::param::set(ROBOT_DESCRIPTION_PARAM, urdf_sstr.str());
00256   }
00257   else
00258   {
00259     ROS_ERROR("Cannot load URDF file");
00260   }
00261 
00262   //Load srdf
00263   boost::filesystem::path boost_srdf_path(srdf_path);
00264   load_robot_ui_.status_label->setText(QString::fromStdString("Loading srdf " + boost_srdf_path.string()));
00265   load_robot_ui_.load_progress_bar->setValue(20);
00266   if (boost::filesystem::exists(boost_srdf_path))
00267   {
00268     std::ifstream srdf_input_stream(boost_srdf_path.string().c_str());
00269     std::stringstream srdf_sstr;
00270     srdf_sstr << srdf_input_stream.rdbuf();
00271     ros::param::set(ROBOT_DESCRIPTION_SEMANTIC_PARAM, srdf_sstr.str());
00272   }
00273   else
00274   {
00275     ROS_ERROR("Cannot load SRDF file");
00276   }
00277 
00278   //Load kinematics.yaml, joint_limits.yaml and ompl_planning.yaml
00279   //TODO: Can we assume kinematics.yaml to be in the same folder as the srdf?
00280   boost::filesystem::path kinematics_file = boost::filesystem::operator/(boost_srdf_path.branch_path(), "kinematics.yaml");
00281   load_robot_ui_.status_label->setText(QString::fromStdString("Loading " + kinematics_file.string()));
00282   load_robot_ui_.load_progress_bar->setValue(30);
00283   if (boost::filesystem::exists( kinematics_file ) && boost::filesystem::is_regular_file( kinematics_file ))
00284   {
00285     if (system(("rosparam load " + kinematics_file.string()).c_str()) < 0)
00286     {
00287       ROS_ERROR("Couldn't load kinematics.yaml file");
00288     }
00289   }
00290 
00291   boost::filesystem::path joint_limits_file = boost::filesystem::operator/(boost_srdf_path.branch_path(), "joint_limits.yaml");
00292   load_robot_ui_.status_label->setText(QString::fromStdString("Loading " + joint_limits_file.string()));
00293   load_robot_ui_.load_progress_bar->setValue(40);
00294   if (boost::filesystem::exists( joint_limits_file ) && boost::filesystem::is_regular_file( joint_limits_file ))
00295   {
00296     if (system(("rosparam load " + joint_limits_file.string()).c_str()) < 0)
00297     {
00298       ROS_ERROR("Couldn't load joint_limits.yaml file");
00299     }
00300   }
00301 
00302   boost::filesystem::path ompl_planning_file = boost::filesystem::operator/(boost_srdf_path.branch_path(), "ompl_planning.yaml");
00303   load_robot_ui_.status_label->setText(QString::fromStdString("Loading " + ompl_planning_file.string()));
00304   load_robot_ui_.load_progress_bar->setValue(50);
00305   if (boost::filesystem::exists( ompl_planning_file ) && boost::filesystem::is_regular_file( ompl_planning_file ))
00306   {
00307     if (system(("rosparam load " + ompl_planning_file.string()).c_str()) < 0)
00308     {
00309       ROS_ERROR("Couldn't load ompl_planning.yaml file");
00310     }
00311   }
00312 
00313   load_robot_ui_.status_label->setText(QString("Resetting scene display... "));
00314   load_robot_ui_.load_progress_bar->setValue(60);
00315   std::string old_scene_name;
00316   if (scene_display_->getPlanningSceneRO())
00317     old_scene_name = scene_display_->getPlanningSceneRO()->getName();
00318   scene_display_->reset();
00319 
00320   if (waitForPlanningSceneMonitor(scene_display_))
00321   {
00322     if (configure())
00323     {
00324       //Reload the scene geometry if one scene was already loaded
00325       load_robot_ui_.status_label->setText(QString("Reloading scene... "));
00326       load_robot_ui_.load_progress_bar->setValue(90);
00327       QList<QListWidgetItem *> found_items = ui_.planning_scene_list->findItems(QString::fromStdString(old_scene_name), Qt::MatchExactly);
00328       if (found_items.size() > 0)
00329       {
00330         found_items[0]->setSelected(true);
00331         loadSceneButtonClicked();
00332       }
00333 
00334       //Reload the goals
00335       load_robot_ui_.status_label->setText(QString("Reloading goals... "));
00336       load_robot_ui_.load_progress_bar->setValue(95);
00337       if (ui_.goal_poses_list->count() > 0)
00338       {
00339         loadGoalsFromDBButtonClicked();
00340       }
00341       load_robot_ui_.status_label->setText(QString(""));
00342       load_robot_ui_.load_progress_bar->setValue(100);
00343     }
00344   }
00345   else
00346   {
00347     ROS_INFO("Couldn't find a valid robot description in the parameter server. Please load a robot on the GUI.");
00348   }
00349 
00350   robot_loader_dialog_->close();
00351   load_robot_ui_.load_progress_bar->setValue(0);
00352   QApplication::restoreOverrideCursor();
00353 }
00354 
00355 bool MainWindow::configure()
00356 {
00357   if ( ! scene_display_->getPlanningSceneMonitor() || ! scene_display_->getPlanningSceneMonitor()->getRobotModel() )
00358   {
00359     ROS_ERROR("Cannot load robot");
00360     ui_.robot_interaction_button->setEnabled(false);
00361     ui_.load_scene_button->setEnabled(false);
00362     ui_.load_results_button->setEnabled(false);
00363     ui_.check_goal_collisions_button->setEnabled(false);
00364     ui_.check_goal_reachability_button->setEnabled(false);
00365     ui_.db_connect_button->setEnabled(false);
00366     ui_.goal_poses_add_button->setEnabled(false);
00367     ui_.goal_poses_remove_button->setEnabled(false);
00368     ui_.load_poses_filter_text->setEnabled(false);
00369     ui_.goal_poses_open_button->setEnabled(false);
00370     ui_.goal_poses_save_button->setEnabled(false);
00371     ui_.goal_switch_visibility_button->setEnabled(false);
00372     ui_.show_x_checkbox->setEnabled(false);
00373     ui_.show_y_checkbox->setEnabled(false);
00374     ui_.show_z_checkbox->setEnabled(false);
00375     ui_.goal_offset_roll->setEnabled(false);
00376     ui_.goal_offset_pitch->setEnabled(false);
00377     ui_.goal_offset_yaw->setEnabled(false);
00378     ui_.start_states_add_button->setEnabled(false);
00379     ui_.start_states_remove_button->setEnabled(false);
00380     ui_.start_states_open_button->setEnabled(false);
00381     ui_.start_states_save_button->setEnabled(false);
00382     ui_.run_benchmark_button->setEnabled(false);
00383 
00384     ui_.trajectory_nwaypoints_spin->setEnabled(false);
00385     ui_.trajectories_filter_text->setEnabled(false);
00386     ui_.trajectory_add_button->setEnabled(false);
00387     ui_.trajectory_remove_button->setEnabled(false);
00388     ui_.trajectory_save_button->setEnabled(false);
00389     ui_.trajectory_open_button->setEnabled(false);
00390     ui_.trajectory_execute_button->setEnabled(false);
00391     return false;
00392   }
00393 
00394   ui_.robot_interaction_button->setEnabled(true);
00395   ui_.load_scene_button->setEnabled(true);
00396   ui_.load_results_button->setEnabled(true);
00397   ui_.check_goal_collisions_button->setEnabled(true);
00398   ui_.check_goal_reachability_button->setEnabled(true);
00399   ui_.db_connect_button->setEnabled(true);
00400   ui_.goal_poses_add_button->setEnabled(true);
00401   ui_.goal_poses_remove_button->setEnabled(true);
00402   ui_.load_poses_filter_text->setEnabled(true);
00403   ui_.goal_poses_open_button->setEnabled(true);
00404   ui_.goal_poses_save_button->setEnabled(true);
00405   ui_.goal_switch_visibility_button->setEnabled(true);
00406   ui_.show_x_checkbox->setEnabled(true);
00407   ui_.show_y_checkbox->setEnabled(true);
00408   ui_.show_z_checkbox->setEnabled(true);
00409   ui_.goal_offset_roll->setEnabled(true);
00410   ui_.goal_offset_pitch->setEnabled(true);
00411   ui_.goal_offset_yaw->setEnabled(true);
00412   ui_.start_states_add_button->setEnabled(true);
00413   ui_.start_states_remove_button->setEnabled(true);
00414   ui_.start_states_open_button->setEnabled(true);
00415   ui_.start_states_save_button->setEnabled(true);
00416 
00417   ui_.trajectory_nwaypoints_spin->setEnabled(true);
00418   ui_.trajectories_filter_text->setEnabled(true);
00419   ui_.trajectory_add_button->setEnabled(true);
00420   ui_.trajectory_remove_button->setEnabled(true);
00421   ui_.trajectory_save_button->setEnabled(true);
00422   ui_.trajectory_open_button->setEnabled(true);
00423   ui_.trajectory_execute_button->setEnabled(true);
00424 
00425   //Set the fixed frame to the model frame
00426   load_robot_ui_.status_label->setText(QString("Setting fixed frame..."));
00427   load_robot_ui_.load_progress_bar->setValue(65);
00428   visualization_manager_->setFixedFrame(QString(scene_display_->getPlanningSceneMonitor()->getRobotModel()->getModelFrame().c_str()));
00429   int_marker_display_->setFixedFrame(QString::fromStdString(scene_display_->getPlanningSceneMonitor()->getRobotModel()->getModelFrame()));
00430 
00431   //robot interaction
00432   load_robot_ui_.status_label->setText(QString("Resetting robot interaction..."));
00433   load_robot_ui_.load_progress_bar->setValue(75);
00434   robot_interaction_.reset(new robot_interaction::RobotInteraction(scene_display_->getPlanningSceneMonitor()->getRobotModel()));
00435 
00436   //Configure robot-dependent ui elements
00437   ui_.load_states_filter_text->setText(QString::fromStdString(scene_display_->getPlanningSceneMonitor()->getRobotModel()->getName() + ".*"));
00438 
00439   //Get the list of planning groups and fill in the combo box
00440   load_robot_ui_.status_label->setText(QString("Updating planning groups..."));
00441   load_robot_ui_.load_progress_bar->setValue(85);
00442   std::vector<std::string> group_names = scene_display_->getPlanningSceneMonitor()->getRobotModel()->getJointModelGroupNames();
00443   ui_.planning_group_combo->clear();
00444   for (std::size_t i = 0; i < group_names.size(); i++)
00445   {
00446     ui_.planning_group_combo->addItem(QString(group_names[i].c_str()));
00447   }
00448 
00449   if (group_names.size() > 0)
00450     planningGroupChanged(QString(group_names[0].c_str()));
00451 
00452   return true;
00453 }
00454 
00455 void MainWindow::planningGroupChanged(const QString &text)
00456 {
00457   if (robot_interaction_ && ! text.isEmpty())
00458   {
00459     robot_interaction_->decideActiveComponents(text.toStdString());
00460     if (robot_interaction_->getActiveEndEffectors().size() == 0)
00461       ROS_WARN_STREAM("No end-effectors defined for robot " << scene_display_->getPlanningSceneMonitor()->getRobotModel()->getName() << " and group " << text.toStdString());
00462     else
00463     {
00464       //Update the kinematic state associated to the goals
00465       for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end(); ++it)
00466       {
00467         it->second->setRobotState(scene_display_->getPlanningSceneRO()->getCurrentState());
00468         it->second->setEndEffector(robot_interaction_->getActiveEndEffectors()[0]);
00469 
00470         if (query_goal_state_)
00471         {
00472           robotInteractionButtonClicked();
00473           robotInteractionButtonClicked();
00474         }
00475       }
00476     }
00477   }
00478 }
00479 
00480 void MainWindow::robotInteractionButtonClicked()
00481 {
00482   if (query_goal_state_ && robot_interaction_)
00483   {
00484     robot_interaction_->clearInteractiveMarkers();
00485     query_goal_state_.reset();
00486   }
00487   else if (robot_interaction_ && scene_display_)
00488   {
00489     query_goal_state_.reset(new robot_interaction::RobotInteraction::InteractionHandler("goal", scene_display_->getPlanningSceneRO()->getCurrentState(), scene_display_->getPlanningSceneMonitor()->getTFClient()));
00490     query_goal_state_->setUpdateCallback(boost::bind(&MainWindow::scheduleStateUpdate, this));
00491     query_goal_state_->setStateValidityCallback(boost::bind(&MainWindow::isIKSolutionCollisionFree, this, _1, _2));
00492     robot_interaction_->addInteractiveMarkers(query_goal_state_);
00493   }
00494   else
00495   {
00496     ROS_WARN("robot interaction not initialized");
00497   }
00498   robot_interaction_->publishInteractiveMarkers();
00499 }
00500 
00501 bool MainWindow::isIKSolutionCollisionFree(robot_state::JointStateGroup *group, const std::vector<double> &ik_solution)
00502 {
00503   if (scene_display_)
00504   {
00505     group->setVariableValues(ik_solution);
00506     return !scene_display_->getPlanningSceneRO()->isStateColliding(*group->getRobotState(), group->getName());
00507   }
00508   else
00509     return true;
00510 }
00511 
00512 void MainWindow::scheduleStateUpdate()
00513 {
00514   JobProcessing::addBackgroundJob(boost::bind(&MainWindow::scheduleStateUpdateBackgroundJob, this));
00515 }
00516 
00517 void MainWindow::scheduleStateUpdateBackgroundJob()
00518 {
00519   scene_display_->getPlanningSceneRW()->setCurrentState(*query_goal_state_->getState());
00520   scene_display_->queueRenderSceneGeometry();
00521 }
00522 
00523 void MainWindow::dbConnectButtonClicked()
00524 {
00525   JobProcessing::addBackgroundJob(boost::bind(&MainWindow::dbConnectButtonClickedBackgroundJob, this));
00526 }
00527 
00528 void MainWindow::dbConnectButtonClickedBackgroundJob()
00529 {
00530   if (planning_scene_storage_)
00531   {
00532     planning_scene_storage_.reset();
00533     robot_state_storage_.reset();
00534     constraints_storage_.reset();
00535     trajectory_constraints_storage_.reset();
00536     ui_.planning_scene_list->clear();
00537 
00538     JobProcessing::addMainLoopJob(boost::bind(&setButtonState, ui_.db_connect_button, false, "Disconnected", "QPushButton { color : red }"));
00539   }
00540   else
00541   {
00542     int port = -1;
00543     QStringList host_port;
00544 
00545     host_port = ui_.db_combo->currentText().split(":");
00546     if (host_port.size() > 1)
00547     {
00548       try
00549       {
00550         port = boost::lexical_cast<int>(host_port[1].toStdString());
00551       }
00552       catch (...)
00553       {
00554       }
00555     }
00556     else
00557       port = DEFAULT_WAREHOUSE_PORT;
00558 
00559     if (port > 0 && ! host_port[0].isEmpty())
00560     {
00561       //Store into settings
00562       QVariant previous_database_names = settings_->value("database_name", QStringList());
00563       QStringList name_list = previous_database_names.toStringList();
00564       name_list.removeAll(ui_.db_combo->currentText());
00565       name_list.push_front(ui_.db_combo->currentText());
00566       static const short db_names_history_size = 5;
00567       if (name_list.size() > db_names_history_size)
00568         name_list.pop_back();
00569       settings_->setValue("database_name", name_list);
00570       ui_.db_combo->clear();
00571       ui_.db_combo->addItems(name_list);
00572 
00573       //Connect
00574       JobProcessing::addMainLoopJob(boost::bind(&setButtonState, ui_.db_connect_button, true, "Connecting...", "QPushButton { color : yellow }"));
00575       try
00576       {
00577         planning_scene_storage_.reset(new moveit_warehouse::PlanningSceneStorage(host_port[0].toStdString(),
00578                                                                                  port, 5.0));
00579         robot_state_storage_.reset(new moveit_warehouse::RobotStateStorage(host_port[0].toStdString(),
00580                                                                            port, 5.0));
00581         constraints_storage_.reset(new moveit_warehouse::ConstraintsStorage(host_port[0].toStdString(),
00582                                                                             port, 5.0));
00583         trajectory_constraints_storage_.reset(new moveit_warehouse::TrajectoryConstraintsStorage(host_port[0].toStdString(),
00584                                                                             port, 5.0));
00585         JobProcessing::addMainLoopJob(boost::bind(&setButtonState, ui_.db_connect_button, true, "Getting data...", "QPushButton { color : yellow }"));
00586 
00587         //Get all the scenes
00588         populatePlanningSceneList();
00589 
00590         JobProcessing::addMainLoopJob(boost::bind(&setButtonState, ui_.db_connect_button, true, "Connected", "QPushButton { color : green }"));
00591       }
00592       catch(std::runtime_error &ex)
00593       {
00594         ROS_ERROR("%s", ex.what());
00595         JobProcessing::addMainLoopJob(boost::bind(&setButtonState, ui_.db_connect_button, false, "Disconnected", "QPushButton { color : red }"));
00596         JobProcessing::addMainLoopJob(boost::bind(&showCriticalMessage, this, "Error", ex.what()));
00597         return;
00598       }
00599     }
00600     else
00601     {
00602       ROS_ERROR("Warehouse server must be introduced as host:port (eg. server.domain.com:33830)");
00603       JobProcessing::addMainLoopJob(boost::bind(&setButtonState, ui_.db_connect_button, false, "Disconnected", "QPushButton { color : red }"));
00604       JobProcessing::addMainLoopJob(boost::bind(&showCriticalMessage, this, "Error", "Warehouse server must be introduced as host:port (eg. server.domain.com:33830)"));
00605     }
00606   }
00607 }
00608 
00609 void MainWindow::populatePlanningSceneList(void)
00610 {
00611   ui_.planning_scene_list->setUpdatesEnabled(false);
00612 
00613   ui_.planning_scene_list->clear();
00614   ui_.planning_scene_list->setSortingEnabled(true);
00615   ui_.planning_scene_list->sortItems(Qt::AscendingOrder);
00616 
00617   std::vector<std::string> names;
00618   planning_scene_storage_->getPlanningSceneNames(names);
00619   for (std::size_t i = 0; i < names.size(); ++i)
00620   {
00621     ui_.planning_scene_list->addItem(names[i].c_str());
00622   }
00623 
00624   ui_.planning_scene_list->setUpdatesEnabled(true);
00625 }
00626 
00627 void MainWindow::loadSceneButtonClicked(QListWidgetItem *item)
00628 {
00629   loadSceneButtonClicked();
00630 }
00631 
00632 void MainWindow::loadSceneButtonClicked(void)
00633 {
00634   if (ui_.planning_scene_list->currentItem() && ui_.planning_scene_list->currentItem()->text().toStdString() != scene_display_->getPlanningSceneRO()->getName())
00635   {
00636     ui_.goal_poses_list->clear();
00637     ui_.trajectory_list->clear();
00638     goal_poses_.clear();
00639     trajectories_.clear();
00640     JobProcessing::addBackgroundJob(boost::bind(&MainWindow::loadSceneButtonClickedBackgroundJob, this));
00641   }
00642 }
00643 
00644 void MainWindow::loadSceneButtonClickedBackgroundJob(void)
00645 {
00646   if (planning_scene_storage_)
00647   {
00648     QList<QListWidgetItem *> sel = ui_.planning_scene_list->selectedItems();
00649     if ( ! sel.empty())
00650     {
00651       QListWidgetItem *s = sel.front();
00652       std::string scene = s->text().toStdString();
00653 
00654       setStatusFromBackground(STATUS_INFO, QString::fromStdString("Attempting to load scene" + scene + "..."));
00655 
00656       moveit_warehouse::PlanningSceneWithMetadata scene_m;
00657       moveit_msgs::PlanningScene scene_msg;
00658       bool got_ps = false;
00659       try
00660       {
00661         got_ps = planning_scene_storage_->getPlanningScene(scene_m, scene);
00662       }
00663       catch (std::runtime_error &ex)
00664       {
00665         ROS_ERROR("%s", ex.what());
00666       }
00667 
00668       if (got_ps)
00669       {
00670         ROS_DEBUG("Loaded scene '%s'", scene.c_str());
00671         setStatusFromBackground(STATUS_INFO, QString::fromStdString("Rendering Scene..."));
00672 
00673         //Update the planning scene
00674         planning_scene_monitor::LockedPlanningSceneRW ps = scene_display_->getPlanningSceneRW();
00675         if (ps)
00676         {
00677           scene_msg = *scene_m;
00678           ps->getWorldNonConst()->clearObjects();
00679           for (std::size_t i = 0 ; i < scene_msg.object_colors.size() ; ++i)
00680             ps->setObjectColor(scene_msg.object_colors[i].id, scene_msg.object_colors[i].color);
00681           ps->processPlanningSceneWorldMsg(scene_msg.world);
00682           ps->setName(scene_msg.name);
00683           scene_display_->queueRenderSceneGeometry();
00684         }
00685 
00686         //Configure ui elements
00687         ui_.load_poses_filter_text->setText(QString::fromStdString(scene + ".*"));
00688         ui_.trajectories_filter_text->setText(QString::fromStdString(scene + ".*"));
00689         setStatusFromBackground(STATUS_INFO, QString::fromStdString(""));
00690       }
00691       else
00692       {
00693         ROS_WARN("Failed to load scene '%s'. Has the message format changed since the scene was saved?", scene.c_str());
00694       }
00695     }
00696   }
00697 }
00698 
00699 
00700 void MainWindow::updateGoalPoseMarkers(float wall_dt, float ros_dt)
00701 {
00702   if (goal_pose_dragging_) {
00703     for (GoalPoseMap::iterator it = goal_poses_.begin(); it != goal_poses_.end() ; ++it)
00704       if (it->second->isVisible())
00705         it->second->imarker->update(wall_dt);
00706   }
00707 
00708   for (TrajectoryMap::iterator it = trajectories_.begin(); it != trajectories_.end() ; ++it)
00709     if (it->second->control_marker->isVisible())
00710     {
00711       it->second->control_marker->imarker->update(wall_dt);
00712       if (it->second->start_marker)
00713         it->second->start_marker->imarker->update(wall_dt);
00714       if (it->second->end_marker)
00715         it->second->end_marker->imarker->update(wall_dt);
00716     }
00717 }
00718 
00719 void MainWindow::MainLoop()
00720 {
00721   int_marker_display_->update(1.0 / MAIN_LOOP_RATE, 1.0 / MAIN_LOOP_RATE);
00722   updateGoalPoseMarkers(1.0 / MAIN_LOOP_RATE, 1.0 / MAIN_LOOP_RATE);
00723 
00724   JobProcessing::executeMainLoopJobs();
00725 }
00726 
00727 void MainWindow::selectItemJob(QListWidgetItem *item, bool flag)
00728 {
00729   item->setSelected(flag);
00730 }
00731 
00732 void MainWindow::setItemSelectionInList(const std::string &item_name, bool selection, QListWidget *list)
00733 {
00734   QList<QListWidgetItem*> found_items = list->findItems(QString(item_name.c_str()), Qt::MatchExactly);
00735   for (std::size_t i = 0 ; i < found_items.size(); ++i)
00736     found_items[i]->setSelected(selection);
00737 }
00738 
00739 }


benchmarks_gui
Author(s): Mario Prats
autogenerated on Mon Oct 6 2014 02:34:25