00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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
00080 visualization_manager_->createDisplay("rviz/Grid", "Grid", true);
00081
00082
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
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
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
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
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
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
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
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
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
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
00279
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
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
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
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
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
00437 ui_.load_states_filter_text->setText(QString::fromStdString(scene_display_->getPlanningSceneMonitor()->getRobotModel()->getName() + ".*"));
00438
00439
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
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
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
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
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
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
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 }