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 #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
00044
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
00175
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
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
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 }