setup_assistant_widget.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Dave Coleman */
00036 
00037 // SA
00038 #include "setup_screen_widget.h" // a base class for screens in the setup assistant
00039 #include "setup_assistant_widget.h"
00040 // Qt
00041 #include <QStackedLayout>
00042 #include <QListWidget>
00043 #include <QListWidgetItem>
00044 #include <QDebug>
00045 #include <QFont>
00046 #include <QLabel>
00047 #include <QPushButton>
00048 #include <QCloseEvent>
00049 #include <QMessageBox>
00050 #include <pluginlib/class_loader.h> // for loading all avail kinematic planners
00051 // Rviz
00052 #include <rviz/render_panel.h>
00053 #include <rviz/visualization_manager.h>
00054 #include <rviz/view_manager.h>
00055 #include <rviz/default_plugin/view_controllers/orbit_view_controller.h>
00056 #include <moveit/robot_state_rviz_plugin/robot_state_display.h>
00057 
00058 namespace moveit_setup_assistant
00059 {
00060 
00061 // ******************************************************************************************
00062 // Outer User Interface for MoveIt Configuration Assistant
00063 // ******************************************************************************************
00064 SetupAssistantWidget::SetupAssistantWidget( QWidget *parent, boost::program_options::variables_map args )
00065   : QWidget( parent )
00066 {
00067   rviz_manager_ = NULL;
00068   rviz_render_panel_ = NULL;
00069 
00070   // Create object to hold all moveit configuration data
00071   config_data_.reset( new MoveItConfigData() );
00072 
00073   // Set debug mode flag if necessary
00074   if (args.count("debug"))
00075     config_data_->debug_ = true;
00076 
00077   // Basic widget container -----------------------------------------
00078   QHBoxLayout *layout = new QHBoxLayout();
00079   layout->setAlignment( Qt::AlignTop );
00080 
00081   // Create main content stack for various screens
00082   main_content_ = new QStackedLayout();
00083   current_index_ = 0;
00084 
00085   // Wrap main_content_ with a widget
00086   middle_frame_ = new QWidget( this );
00087   middle_frame_->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
00088   middle_frame_->setLayout( main_content_ );
00089 
00090   // Screens --------------------------------------------------------
00091 
00092   // Start Screen
00093   ssw_ = new StartScreenWidget( this, config_data_ );
00094   ssw_->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
00095   connect( ssw_, SIGNAL( readyToProgress() ), this, SLOT( progressPastStartScreen() ) );
00096   connect( ssw_, SIGNAL( loadRviz() ), this, SLOT( loadRviz() ) );
00097   main_content_->addWidget(ssw_);
00098 
00099   // Pass command arg values to start screen
00100   if (args.count( "urdf_path" ))
00101   {
00102     ssw_->urdf_file_->setPath( args["urdf_path"].as<std::string>() );
00103   }
00104   if (args.count( "config_pkg" ))
00105   {
00106     ssw_->stack_path_->setPath( args["config_pkg"].as<std::string>() );
00107 
00108     // Show this part of screen
00109     ssw_->select_mode_->btn_exist_->click();
00110   }
00111 
00112   // Add Navigation Buttons (but do not load widgets yet except start screen)
00113   nav_name_list_ << "Start";
00114   nav_name_list_ << "Self-Collisions";
00115   nav_name_list_ << "Virtual Joints";
00116   nav_name_list_ << "Planning Groups";
00117   nav_name_list_ << "Robot Poses";
00118   nav_name_list_ << "End Effectors";
00119   nav_name_list_ << "Passive Joints";
00120   nav_name_list_ << "Configuration Files";
00121 
00122   // Navigation Left Pane --------------------------------------------------
00123   navs_view_ = new NavigationWidget( this );
00124   navs_view_->setNavs(nav_name_list_);
00125   navs_view_->setDisabled( true );
00126   navs_view_->setSelected( 0 ); // start screen
00127 
00128   // Rviz View Right Pane ---------------------------------------------------
00129   rviz_container_ = new QWidget( this );
00130   rviz_container_->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
00131   rviz_container_->hide(); // do not show until after the start screen
00132 
00133   // Split screen -----------------------------------------------------
00134   splitter_ = new QSplitter( Qt::Horizontal, this );
00135   splitter_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00136   splitter_->addWidget( navs_view_ );
00137   splitter_->addWidget( middle_frame_ );
00138   splitter_->addWidget( rviz_container_ );
00139   splitter_->setHandleWidth( 6 );
00140   //splitter_->setCollapsible( 0, false ); // don't let navigation collapse
00141   layout->addWidget( splitter_ );
00142 
00143   // Add event for switching between screens -------------------------
00144   connect( navs_view_, SIGNAL(clicked(const QModelIndex&)), this, SLOT(navigationClicked(const QModelIndex&)) );
00145 
00146   // Final Layout Setup ---------------------------------------------
00147   this->setLayout(layout);
00148 
00149   // Title
00150   this->setWindowTitle("MoveIt Setup Assistant"); // title of window
00151 
00152   // Show screen before message
00153   QApplication::processEvents();
00154 }
00155 
00156 // ******************************************************************************************
00157 // Decontructor
00158 // ******************************************************************************************
00159 SetupAssistantWidget::~SetupAssistantWidget()
00160 {
00161   if( rviz_manager_ != NULL )
00162     rviz_manager_->removeAllDisplays();
00163   if ( rviz_render_panel_ != NULL )
00164     delete rviz_render_panel_;
00165   if ( rviz_manager_ != NULL )
00166     delete rviz_manager_;
00167 }
00168 
00169 void SetupAssistantWidget::virtualJointReferenceFrameChanged()
00170 {
00171   if (rviz_manager_ && robot_state_display_)
00172   {
00173     rviz_manager_->setFixedFrame( QString::fromStdString( config_data_->getRobotModel()->getModelFrame() ) );
00174     robot_state_display_->reset();
00175   }
00176 }
00177 
00178 // ******************************************************************************************
00179 // Change screens of Setup Assistant
00180 // ******************************************************************************************
00181 void SetupAssistantWidget::navigationClicked( const QModelIndex& index )
00182 {
00183   // Convert QModelIndex to int
00184   moveToScreen( index.row() );
00185 }
00186 
00187 // ******************************************************************************************
00188 // Change screens
00189 // ******************************************************************************************
00190 void SetupAssistantWidget::moveToScreen( const int index )
00191 {
00192   boost::mutex::scoped_lock slock(change_screen_lock_);
00193 
00194   if( current_index_ != index )
00195   {
00196     current_index_ = index;
00197 
00198     // Unhighlight anything on robot
00199     unhighlightAll();
00200 
00201     // Change screens
00202     main_content_->setCurrentIndex( index );
00203 
00204     // Send the focus given command to the screen widget
00205     SetupScreenWidget *ssw = qobject_cast< SetupScreenWidget* >( main_content_->widget( index ) );
00206     ssw->focusGiven();
00207 
00208     // Change navigation selected option
00209     navs_view_->setSelected( index ); // Select first item in list
00210   }
00211 }
00212 
00213 // ******************************************************************************************
00214 // Loads other windows, enables navigation
00215 // ******************************************************************************************
00216 void SetupAssistantWidget::progressPastStartScreen()
00217 {
00218   // Load all widgets ------------------------------------------------
00219 
00220   // Self-Collisions
00221   dcw_ = new DefaultCollisionsWidget( this, config_data_);
00222   main_content_->addWidget( dcw_ );
00223   connect( dcw_, SIGNAL( highlightLink( const std::string& ) ), this, SLOT( highlightLink( const std::string& ) ) );
00224   connect( dcw_, SIGNAL( highlightGroup( const std::string& ) ), this, SLOT( highlightGroup( const std::string& ) ) );
00225   connect( dcw_, SIGNAL( unhighlightAll() ), this, SLOT( unhighlightAll() ) );
00226 
00227   // Virtual Joints
00228   vjw_ = new VirtualJointsWidget( this, config_data_ );
00229   main_content_->addWidget(vjw_);
00230   connect( vjw_, SIGNAL( isModal( bool ) ), this, SLOT( setModalMode( bool ) ) );
00231   connect( vjw_, SIGNAL( highlightLink( const std::string& ) ), this, SLOT( highlightLink( const std::string& ) ) );
00232   connect( vjw_, SIGNAL( highlightGroup( const std::string& ) ), this, SLOT( highlightGroup( const std::string& ) ) );
00233   connect( vjw_, SIGNAL( unhighlightAll() ), this, SLOT( unhighlightAll() ) );
00234   connect( vjw_, SIGNAL( referenceFrameChanged() ), this, SLOT( virtualJointReferenceFrameChanged() ) );
00235 
00236   // Planning Groups
00237   pgw_ = new PlanningGroupsWidget( this, config_data_ );
00238   main_content_->addWidget(pgw_);
00239   connect( pgw_, SIGNAL( isModal( bool ) ), this, SLOT( setModalMode( bool ) ) );
00240   connect( pgw_, SIGNAL( highlightLink( const std::string& ) ), this, SLOT( highlightLink( const std::string& ) ) );
00241   connect( pgw_, SIGNAL( highlightGroup( const std::string& ) ), this, SLOT( highlightGroup( const std::string& ) ) );
00242   connect( pgw_, SIGNAL( unhighlightAll() ), this, SLOT( unhighlightAll() ) );
00243 
00244   // Robot Poses
00245   rpw_ = new RobotPosesWidget( this, config_data_ );
00246   main_content_->addWidget(rpw_);
00247   connect( rpw_, SIGNAL( isModal( bool ) ), this, SLOT( setModalMode( bool ) ) );
00248   connect( rpw_, SIGNAL( highlightLink( const std::string& ) ), this, SLOT( highlightLink( const std::string& ) ) );
00249   connect( rpw_, SIGNAL( highlightGroup( const std::string& ) ), this, SLOT( highlightGroup( const std::string& ) ) );
00250   connect( rpw_, SIGNAL( unhighlightAll() ), this, SLOT( unhighlightAll() ) );
00251 
00252   // End Effectors
00253   efw_ = new EndEffectorsWidget( this, config_data_ );
00254   main_content_->addWidget(efw_);
00255   connect( efw_, SIGNAL( isModal( bool ) ), this, SLOT( setModalMode( bool ) ) );
00256   connect( efw_, SIGNAL( highlightLink( const std::string& ) ), this, SLOT( highlightLink( const std::string& ) ) );
00257   connect( efw_, SIGNAL( highlightGroup( const std::string& ) ), this, SLOT( highlightGroup( const std::string& ) ) );
00258   connect( efw_, SIGNAL( unhighlightAll() ), this, SLOT( unhighlightAll() ) );
00259 
00260   // Virtual Joints
00261   pjw_ = new PassiveJointsWidget( this, config_data_ );
00262   main_content_->addWidget(pjw_);
00263   connect( pjw_, SIGNAL( isModal( bool ) ), this, SLOT( setModalMode( bool ) ) );
00264   connect( pjw_, SIGNAL( highlightLink( const std::string& ) ), this, SLOT( highlightLink( const std::string& ) ) );
00265   connect( pjw_, SIGNAL( highlightGroup( const std::string& ) ), this, SLOT( highlightGroup( const std::string& ) ) );
00266   connect( pjw_, SIGNAL( unhighlightAll() ), this, SLOT( unhighlightAll() ) );
00267 
00268   // Configuration Files
00269   cfw_ = new ConfigurationFilesWidget( this, config_data_ );
00270   main_content_->addWidget(cfw_);
00271 
00272   // Enable all nav buttons -------------------------------------------
00273   for( int i = 0; i < nav_name_list_.count(); ++i)
00274   {
00275     navs_view_->setEnabled( i, true );
00276   }
00277 
00278   // Enable navigation
00279   navs_view_->setDisabled( false );
00280 
00281   // Replace logo with Rviz screen
00282   rviz_container_->show();
00283 
00284   // Move to next screen in debug mode
00285   if( config_data_->debug_)
00286   {
00287     moveToScreen(3);
00288   }
00289 }
00290 
00291 // ******************************************************************************************
00292 // Ping ROS on internval
00293 // ******************************************************************************************
00294 void SetupAssistantWidget::updateTimer()
00295 {
00296   ros::spinOnce(); // keep ROS node alive
00297 }
00298 
00299 // ******************************************************************************************
00300 // Load Rviz once we have a robot description ready
00301 // ******************************************************************************************
00302 void SetupAssistantWidget::loadRviz()
00303 {
00304   // Create rviz frame
00305   rviz_render_panel_ = new rviz::RenderPanel();
00306   rviz_render_panel_->setMinimumWidth( 200 );
00307   rviz_render_panel_->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
00308 
00309   rviz_manager_ = new rviz::VisualizationManager( rviz_render_panel_ );
00310   rviz_render_panel_->initialize( rviz_manager_->getSceneManager(), rviz_manager_ );
00311   rviz_manager_->initialize();
00312   rviz_manager_->startUpdate();
00313 
00314   // Set the fixed and target frame
00315   rviz_manager_->setFixedFrame( QString::fromStdString( config_data_->getRobotModel()->getModelFrame() ) );
00316 
00317   // Create the MoveIt Rviz Plugin and attach to display
00318   robot_state_display_ = new moveit_rviz_plugin::RobotStateDisplay();
00319   robot_state_display_->setName( "Robot State" );
00320 
00321   rviz_manager_->addDisplay( robot_state_display_, true );
00322 
00323   // Set the topic on which the moveit_msgs::PlanningScene messages are recieved
00324   robot_state_display_->subProp("Robot State Topic")->setValue(QString::fromStdString( MOVEIT_ROBOT_STATE ));
00325 
00326   // Set robot description
00327   robot_state_display_->subProp("Robot Description")->setValue(QString::fromStdString( ROBOT_DESCRIPTION ));
00328 
00329   // Zoom into robot
00330   rviz::ViewController* view = rviz_manager_->getViewManager()->getCurrent();
00331   view->subProp( "Distance" )->setValue( 4.0f );
00332 
00333   // Add Rviz to Planning Groups Widget
00334   QHBoxLayout *rviz_layout = new QHBoxLayout();
00335   rviz_layout->addWidget( rviz_render_panel_ );
00336   rviz_container_->setLayout( rviz_layout );
00337 
00338   rviz_container_->show();
00339 }
00340 
00341 // ******************************************************************************************
00342 // Highlight a robot link
00343 // ******************************************************************************************
00344 void SetupAssistantWidget::highlightLink( const std::string& link_name )
00345 {
00346   const robot_model::LinkModel *lm = config_data_->getRobotModel()->getLinkModel(link_name);
00347   if (lm->getShape()) // skip links with no geometry
00348     robot_state_display_->setLinkColor( link_name, QColor(255, 0, 0) );
00349 }
00350 
00351 // ******************************************************************************************
00352 // Highlight a robot group
00353 // ******************************************************************************************
00354 void SetupAssistantWidget::highlightGroup( const std::string& group_name )
00355 {
00356   // Highlight the selected planning group by looping through the links
00357   if (!config_data_->getRobotModel()->hasJointModelGroup( group_name ))
00358     return;
00359 
00360   const robot_model::JointModelGroup *joint_model_group =
00361     config_data_->getRobotModel()->getJointModelGroup( group_name );
00362   if (joint_model_group)
00363   {
00364     const std::vector<const robot_model::LinkModel*> &link_models = joint_model_group->getLinkModels();
00365     // Iterate through the links
00366     for( std::vector<const robot_model::LinkModel*>::const_iterator link_it = link_models.begin();
00367          link_it < link_models.end(); ++link_it )
00368       highlightLink( (*link_it)->getName() );
00369   }
00370 }
00371 
00372 // ******************************************************************************************
00373 // Unhighlight all robot links
00374 // ******************************************************************************************
00375 void SetupAssistantWidget::unhighlightAll()
00376 {
00377   // Get the names of the all links robot
00378   const std::vector<std::string> &links = config_data_->getRobotModel()->getLinkModelNamesWithCollisionGeometry();
00379 
00380   // Quit if no links found
00381   if( links.empty() )
00382   {
00383     return;
00384   }
00385 
00386   // check if rviz is ready
00387   if( !rviz_manager_ || !robot_state_display_)
00388   {
00389     return;
00390   }
00391 
00392   // Iterate through the links
00393   for( std::vector<std::string>::const_iterator link_it = links.begin();
00394        link_it < links.end(); ++link_it )
00395   {
00396     if( (*link_it).empty() )
00397       continue;
00398 
00399     robot_state_display_->unsetLinkColor( *link_it );
00400   }
00401 
00402 }
00403 
00404 // ******************************************************************************************
00405 // Qt close event function for reminding user to save
00406 // ******************************************************************************************
00407 void SetupAssistantWidget::closeEvent( QCloseEvent * event )
00408 {
00409   // Only prompt to close if not in debug mode
00410   if( !config_data_->debug_ )
00411   {
00412     if( QMessageBox::question( this, "Exit Setup Assistant",
00413                                QString("Are you sure you want to exit the MoveIt Setup Assistant?"),
00414                                QMessageBox::Ok | QMessageBox::Cancel)
00415         == QMessageBox::Cancel )
00416     {
00417       event->ignore();
00418       return;
00419     }
00420   }
00421 
00422   // Shutdown app
00423   event->accept();
00424 }
00425 
00426 // ******************************************************************************************
00427 // Qt Error Handling - TODO
00428 // ******************************************************************************************
00429 bool SetupAssistantWidget::notify( QObject * reciever, QEvent * event )
00430 {
00431   QMessageBox::critical( this, "Error", "An error occurred and was caught by Qt notify event handler.", QMessageBox::Ok);
00432 
00433   return false;
00434 }
00435 
00436 // ******************************************************************************************
00437 // Change the widget modal state based on subwidgets state
00438 // ******************************************************************************************
00439 void SetupAssistantWidget::setModalMode( bool isModal )
00440 {
00441   navs_view_->setDisabled( isModal );
00442 
00443   for( int i = 0; i < nav_name_list_.count(); ++i)
00444   {
00445     navs_view_->setEnabled( i, !isModal );
00446   }
00447 }
00448 
00449 
00450 } // namespace


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Mon Oct 6 2014 02:32:27