visualizer_app.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, 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 
00030 #include <QApplication>
00031 #include <QTimer>
00032 
00033 #include <boost/thread.hpp>
00034 #include <boost/program_options.hpp>
00035 #include <signal.h>
00036 
00037 #include <OGRE/OgreHighLevelGpuProgramManager.h>
00038 #include <OGRE/OgreLogManager.h>
00039 #include <std_srvs/Empty.h>
00040 
00041 #ifdef Q_OS_MAC
00042 #include <ApplicationServices/ApplicationServices.h>
00043 // Apparently OSX #defines 'check' to be an empty string somewhere.  
00044 // That was fun to figure out.
00045 #undef check
00046 #endif
00047 
00048 #include <ros/ros.h>
00049 
00050 #include <ogre_tools/version.h>
00051 
00052 #include "visualization_frame.h"
00053 #include "version.h"
00054 #include "wait_for_master_dialog.h"
00055 #include "visualizer_app.h"
00056 
00057 namespace po = boost::program_options;
00058 
00059 namespace rviz
00060 {
00061 
00062 bool reloadShaders(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
00063 {
00064   Ogre::ResourceManager::ResourceMapIterator it = Ogre::HighLevelGpuProgramManager::getSingleton().getResourceIterator();
00065   while (it.hasMoreElements())
00066   {
00067     Ogre::ResourcePtr resource = it.getNext();
00068     resource->reload();
00069   }
00070   return true;
00071 }
00072 
00073 VisualizerApp::VisualizerApp()
00074   : timer_( 0 )
00075 {
00076 }
00077 
00078 void VisualizerApp::onTimer()
00079 {
00080   if( !continue_ )
00081   {
00082     QApplication::closeAllWindows();
00083   }
00084 }
00085 
00086 bool VisualizerApp::init( int argc, char** argv )
00087 {
00088   ROS_INFO( "rviz revision number %s", get_version().c_str() );
00089   ROS_INFO( "ogre_tools revision number %s", ogre_tools::get_version().c_str() );
00090   ROS_INFO( "compiled against OGRE version %d.%d.%d%s (%s)",
00091             OGRE_VERSION_MAJOR, OGRE_VERSION_MINOR, OGRE_VERSION_PATCH,
00092             OGRE_VERSION_SUFFIX, OGRE_VERSION_NAME );
00093 
00094 #ifdef Q_OS_MAC
00095   ProcessSerialNumber PSN;
00096   GetCurrentProcess(&PSN);
00097   TransformProcessType(&PSN,kProcessTransformToForegroundApplication);
00098   SetFrontProcess(&PSN);
00099 #endif
00100 
00101   try
00102   {
00103     ros::init( argc, argv, "rviz", ros::init_options::AnonymousName | ros::init_options::NoSigintHandler );
00104 
00105     po::options_description options;
00106     options.add_options()
00107       ("help,h", "Produce this help message")
00108       ("splash-screen,s", po::value<std::string>(), "A custom splash-screen image to display")
00109       ("display-config,d", po::value<std::string>(), "A display config file (.vcg) to load")
00110       ("target-frame,t", po::value<std::string>(), "Set the target frame")
00111       ("fixed-frame,f", po::value<std::string>(), "Set the fixed frame")
00112       ("ogre-log,l", "Enable the Ogre.log file (output in cwd)")
00113       ("verbose,v", "Enable debug visualizations");
00114     po::variables_map vm;
00115     std::string display_config, target_frame, fixed_frame, splash_path;
00116     bool enable_ogre_log = false;
00117     bool verbose = false;
00118     try
00119     {
00120       po::store( po::parse_command_line( argc, argv, options ), vm );
00121       po::notify( vm );
00122 
00123       if( vm.count( "help" ))
00124       {
00125         std::cout << "rviz command line options:\n" << options;
00126         return false;
00127       }
00128 
00129       if (vm.count("display-config"))
00130       {
00131         display_config = vm["display-config"].as<std::string>();
00132       }
00133 
00134       if (vm.count("splash-screen"))
00135       {
00136         splash_path = vm["splash-screen"].as<std::string>();
00137       }
00138 
00139       if (vm.count("target-frame"))
00140       {
00141         target_frame = vm["target-frame"].as<std::string>();
00142       }
00143 
00144       if (vm.count("fixed-frame"))
00145       {
00146         fixed_frame = vm["fixed-frame"].as<std::string>();
00147       }
00148 
00149       if (vm.count("ogre-log"))
00150       {
00151         enable_ogre_log = true;
00152       }
00153 
00154       if (vm.count("verbose"))
00155       {
00156         verbose = true;
00157       }
00158     }
00159     catch (std::exception& e)
00160     {
00161       ROS_ERROR("Error parsing command line: %s", e.what());
00162       return false;
00163     }
00164 
00165     if( !ros::master::check() )
00166     {
00167       WaitForMasterDialog* dialog = new WaitForMasterDialog;
00168       if( dialog->exec() != QDialog::Accepted )
00169       {
00170         return false;
00171       }
00172     }
00173 
00174     // block kill signals on all threads, since this also disables signals in threads
00175     // created by this one (the main thread)
00176     sigset_t sig_set;
00177     sigemptyset(&sig_set);
00178     sigaddset(&sig_set, SIGKILL);
00179     sigaddset(&sig_set, SIGTERM);
00180     sigaddset(&sig_set, SIGQUIT);
00181     sigaddset(&sig_set, SIGINT);
00182     pthread_sigmask(SIG_BLOCK, &sig_set, NULL);
00183 
00184     // Start up our signal handler
00185     continue_ = true;
00186     signal_handler_thread_ = boost::thread(boost::bind(&VisualizerApp::signalHandler, this));
00187 
00188     nh_.reset( new ros::NodeHandle );
00189 
00190     Ogre::LogManager* log_manager = new Ogre::LogManager();
00191     log_manager->createLog( "Ogre.log", false, false, !enable_ogre_log );
00192 
00193     frame_ = new VisualizationFrame;
00194     frame_->initialize( display_config, fixed_frame, target_frame, splash_path, verbose );
00195     frame_->show();
00196 
00197     timer_ = new QTimer( this );
00198     connect( timer_, SIGNAL( timeout() ), this, SLOT( onTimer() ));
00199     timer_->start( 100 );
00200 
00201     ros::NodeHandle private_nh("~");
00202     reload_shaders_service_ = private_nh.advertiseService("reload_shaders", reloadShaders);
00203   }
00204   catch (std::exception& e)
00205   {
00206     ROS_ERROR("Caught exception while loading: %s", e.what());
00207     return false;
00208   }
00209 
00210   return true;
00211 }
00212 
00213 VisualizerApp::~VisualizerApp()
00214 {
00215   if( timer_ )
00216   {
00217     timer_->stop();
00218   }
00219   continue_ = false;
00220 
00221   delete frame_;
00222 
00223   raise(SIGQUIT);
00224 
00225   signal_handler_thread_.join();
00226 }
00227 
00228 void VisualizerApp::signalHandler()
00229 {
00230   sigset_t signal_set;
00231   while(continue_)
00232   {
00233     // Wait for any signals
00234     sigfillset(&signal_set);
00235 
00236 #if defined(Q_OS_MAC)
00237     int sig;
00238     sigwait(&signal_set, &sig);
00239 #else
00240     struct timespec ts = {0, 100000000};
00241     int sig = sigtimedwait(&signal_set, NULL, &ts);
00242 #endif
00243 
00244     switch( sig )
00245     {
00246     case SIGKILL:
00247     case SIGTERM:
00248     case SIGQUIT:
00249     {
00250       exit(1);
00251     }
00252     break;
00253 
00254     case SIGINT:
00255     {
00256       ros::shutdown();
00257       continue_ = false;
00258       return;
00259     }
00260     break;
00261 
00262     default:
00263       break;
00264     }
00265   }
00266 }
00267 
00268 } // namespace rviz


rviz_qt
Author(s): Dave Hershberger
autogenerated on Fri Dec 6 2013 20:56:53