00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030
00031
00032
00033
00034 #include <QLineEdit>
00035 #include <QFileInfo>
00036 #include <QFileDialog>
00037 #include <QStringList>
00038 #include <QStandardItemModel>
00039 #include <QModelIndex>
00040
00041
00042 #include "rqt_marble_plugin/marble_plugin.h"
00043
00044
00045 #include <pluginlib/class_list_macros.h>
00046
00047
00048
00049 #include <marble/MarbleWidget.h>
00050 #include <marble/MarbleModel.h>
00051 #include <marble/MapThemeManager.h>
00052 #include <marble/GeoPainter.h>
00053
00054 #include <ros/package.h>
00055 #include "drawable_marble_widget.h"
00056 #include "manage_kml_dialog.h"
00057
00058
00059
00060
00061
00062 namespace rqt_marble_plugin {
00063
00064 MarblePlugin::MarblePlugin()
00065 : rqt_gui_cpp::Plugin()
00066 , widget_(0)
00067 {
00068
00069 setObjectName("MarbleWidgetPlugin");
00070 }
00071
00072
00073
00074 void MarblePlugin::initPlugin(qt_gui_cpp::PluginContext& context)
00075 {
00076
00077 QStringList argv = context.argv();
00078 qRegisterMetaType<FlyToMode>( "FlyToMode" );
00079 qRegisterMetaType<GeoDataLookAt>( "GeoDataLookAt" );
00080
00081
00082 widget_ = new QWidget();
00083
00084
00085 ui_.setupUi( widget_ );
00086
00087 ui_.MarbleWidget->setMapThemeId("earth/openstreetmap/openstreetmap.dgml");
00088 ui_.MarbleWidget->setProjection( Marble::Mercator );
00089
00090 ui_.MarbleWidget->centerOn( 8.426, 49.01, false );
00091 ui_.MarbleWidget->setDistance(0.05);
00092
00093 context.addWidget(widget_);
00094 ui_.comboBox_theme->setModel( m_map_theme_manager.mapThemeModel() );
00095
00096
00097
00098 QIcon refresh_icon;
00099 std::string path = ros::package::getPath("rqt_marble_plugin")+"/etc/refresh.png";
00100 QString icon_path(path.c_str());
00101 refresh_icon.addFile(icon_path);
00102 ui_.refreshButton->setIcon(refresh_icon);
00103
00104
00105 m_selected_gps_pos_publisher = getNodeHandle().advertise< sensor_msgs::NavSatFix >("gps_position", 1);
00106
00107
00108 if(ui_.checkBox_process_marker->isChecked())
00109 subscribeVisualization();
00110
00111 m_mapcontrol_subscriber = getNodeHandle().subscribe< geometry_msgs::Twist >( "/mapcontrol" , 1 , &MarblePlugin::mapcontrolCallback, this );
00112
00113 FindNavSatFixTopics();
00114
00115
00116 connect(ui_.comboBox_current_gps, SIGNAL(activated (const QString &)), this, SLOT (ChangeGPSTopicCurrentGPS(const QString &)));
00117 connect(ui_.comboBox_matched_gps, SIGNAL(activated (const QString &)), this, SLOT (ChangeGPSTopicMatchedGPS(const QString &)));
00118
00119
00120 connect(ui_.checkBox_process_marker, SIGNAL(clicked()), this, SLOT(processMarkerCheckBoxCLicked()));
00121 connect(ui_.refreshButton, SIGNAL(clicked()), this, SLOT(FindNavSatFixTopics()));
00122 connect(ui_.manageKMLButton, SIGNAL(clicked()), this, SLOT(ManageKML()));
00123
00124 connect( this , SIGNAL(NewGPSPosition(qreal,qreal)) , ui_.MarbleWidget , SLOT(centerOn(qreal,qreal)) );
00125
00126 connect(this, SIGNAL(ZoomIn(FlyToMode)), ui_.MarbleWidget, SLOT(zoomIn(FlyToMode)));
00127 connect(this, SIGNAL(ZoomOut(FlyToMode)), ui_.MarbleWidget, SLOT(zoomOut(FlyToMode)));
00128 connect(this, SIGNAL(flyTo(GeoDataLookAt,FlyToMode)), ui_.MarbleWidget, SLOT(flyTo(GeoDataLookAt,FlyToMode)));
00129
00130 connect( ui_.comboBox_theme , SIGNAL(currentIndexChanged(int)) , this , SLOT(ChangeMarbleModelTheme(int)));
00131
00132 connect( ui_.MarbleWidget, SIGNAL(mouseClickGeoPosition(qreal,qreal,GeoDataCoordinates::Unit)), this, SLOT(gpsCoordinateSelected(qreal,qreal,GeoDataCoordinates::Unit)));
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 }
00149
00150 void MarblePlugin::ManageKML()
00151 {
00152 ManageKmlDialog kmlDialog(m_last_kml_data);
00153 if(kmlDialog.exec() == QDialog::Accepted)
00154 {
00155 std::map< QString, bool> kml_files = kmlDialog.getKmlFiles();
00156 addKMLData(kml_files, true);
00157 }
00158 }
00159
00160 void MarblePlugin::addKMLData(std::map< QString, bool>& kml_files, bool overwrite)
00161 {
00162 if(overwrite)
00163 {
00164 clearKMLData();
00165 }
00166
00167 std::map<QString, bool>::iterator it;
00168 for(it=kml_files.begin(); it != kml_files.end(); it++)
00169 {
00170 QString filepath = it->first;
00171 bool show = it->second;
00172
00173 if(show)
00174 {
00175 ui_.MarbleWidget->model()->addGeoDataFile( filepath );
00176 }
00177 m_last_kml_data[filepath] = show;
00178 }
00179 }
00180
00181 void MarblePlugin::mapcontrolCallback(const geometry_msgs::TwistConstPtr &msg)
00182 {
00183 FlyToMode mode;
00184 mode = Linear;
00185
00186 GeoDataLookAt lookAt;
00187 lookAt = ui_.MarbleWidget->lookAt();
00188
00189 double lon = lookAt.longitude();
00190 double lat = lookAt.latitude();
00191
00192 double muted_move_step = 0.025 * ui_.MarbleWidget->moveStep();
00193 float step_lon = muted_move_step * std::max(std::min(msg->linear.x, 1.0), -1.0);
00194 float step_lat = muted_move_step * std::max(std::min(msg->linear.y, 1.0), -1.0);
00195
00196 lon+=step_lon;
00197 lat+=step_lat;
00198
00199 if(lon!=lookAt.longitude() || lat!=lookAt.latitude())
00200 {
00201 lookAt.setLatitude(lat);
00202 lookAt.setLongitude(lon);
00203
00204 emit flyTo(lookAt, mode);
00205 }
00206
00207 if(msg->linear.z < 0)
00208 emit ZoomIn(mode);
00209 if(msg->linear.z > 0)
00210 emit ZoomOut(mode);
00211
00212 }
00213
00214 void MarblePlugin::clearKMLData()
00215 {
00216 for(std::map< QString, bool>::iterator it = m_last_kml_data.begin(); it != m_last_kml_data.end(); it++)
00217 {
00218 ui_.MarbleWidget->model()->removeGeoData(it->first);
00219 }
00220 m_last_kml_data.clear();
00221 }
00222
00223
00224
00225 void MarblePlugin::FindNavSatFixTopics()
00226 {
00227 using namespace ros::master;
00228
00229 std::vector<TopicInfo> topic_infos;
00230 getTopics(topic_infos);
00231
00232
00233 ui_.comboBox_current_gps->clear();
00234 ui_.comboBox_matched_gps->clear();
00235 for(std::vector<TopicInfo>::iterator it=topic_infos.begin(); it!=topic_infos.end();it++)
00236 {
00237 TopicInfo topic = (TopicInfo)(*it);
00238 if(topic.datatype.compare("sensor_msgs/NavSatFix")==0)
00239 {
00240 QString lineEdit_string(topic.name.c_str());
00241 ui_.comboBox_current_gps->addItem(lineEdit_string);
00242 ui_.comboBox_matched_gps->addItem(lineEdit_string);
00243 }
00244 }
00245 }
00246
00247
00248 void MarblePlugin::ChangeMarbleModelTheme(int idx )
00249 {
00250 QStandardItemModel* model = m_map_theme_manager.mapThemeModel();
00251 QModelIndex index = model->index( idx , 0 );
00252 QString theme = model->data( index , Qt::UserRole+1 ).toString();
00253
00254 ui_.MarbleWidget->setMapThemeId( theme );
00255 }
00256
00257 void MarblePlugin::ChangeGPSTopicCurrentGPS(const QString &topic_name)
00258 {
00259 m_current_pos_subscriber.shutdown();
00260 m_current_pos_subscriber = getNodeHandle().subscribe< sensor_msgs::NavSatFix >(
00261 topic_name.toStdString().c_str() , 1 , &MarblePlugin::GpsCallbackCurrent, this );
00262
00263 int idx = ui_.comboBox_current_gps->findText( topic_name );
00264 if( idx != -1 )
00265 {
00266 ui_.comboBox_current_gps->setCurrentIndex( idx );
00267 }
00268 }
00269
00270 void MarblePlugin::ChangeGPSTopicMatchedGPS(const QString &topic_name)
00271 {
00272 m_matched_pos_subscriber.shutdown();
00273 m_matched_pos_subscriber = getNodeHandle().subscribe< sensor_msgs::NavSatFix >(
00274 topic_name.toStdString().c_str() , 1 , &MarblePlugin::GpsCallbackMatched, this );
00275
00276 int idx = ui_.comboBox_matched_gps->findText( topic_name );
00277 if( idx != -1 )
00278 {
00279 ui_.comboBox_matched_gps->setCurrentIndex( idx );
00280 }
00281
00282 }
00283
00284 void MarblePlugin::GpsCallbackMatched( const sensor_msgs::NavSatFixConstPtr& gpspt )
00285 {
00286
00287 assert( widget_ );
00288
00289 GeoDataCoordinates postition(gpspt->longitude, gpspt->latitude, gpspt->altitude, GeoDataCoordinates::Degree);
00290 ui_.MarbleWidget->setMatchedPosition(postition);
00291
00292
00293 static qreal _x = -1;
00294 static qreal _y = -1;
00295
00296 qreal x;
00297 qreal y;
00298
00299 ui_.MarbleWidget->screenCoordinates(gpspt->longitude,gpspt->latitude , x , y );
00300
00301 bool recenter = ui_.checkBox_center->isChecked();
00302
00303
00304 qreal threshold = 20;
00305 recenter &= ((x - _x) * (x - _x) + (y - _y) * (y - _y)) > threshold;
00306
00307 if( recenter )
00308 {
00309 ui_.MarbleWidget->screenCoordinates(gpspt->longitude,gpspt->latitude , _x , _y );
00310 emit NewGPSPosition( gpspt->longitude , gpspt->latitude );
00311 }
00312 }
00313
00314 void MarblePlugin::GpsCallbackCurrent( const sensor_msgs::NavSatFixConstPtr& gpspt )
00315 {
00316
00317 assert( widget_ );
00318
00319 GeoDataCoordinates postition(gpspt->longitude, gpspt->latitude, gpspt->altitude, GeoDataCoordinates::Degree);
00320 ui_.MarbleWidget->setCurrentPosition(postition);
00321
00322
00324 ui_.MarbleWidget->referenceGpsCallback(gpspt);
00325
00326
00327 }
00328
00329 void MarblePlugin::gpsCoordinateSelected(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) {
00330 GeoDataCoordinates coords(lon, lat, unit);
00331
00332 if(ui_.checkBox_publish_gps->isChecked())
00333 {
00334 sensor_msgs::NavSatFix msg;
00335 msg.longitude = coords.longitude(GeoDataCoordinates::Degree);
00336 msg.latitude = coords.latitude(GeoDataCoordinates::Degree);
00337
00338 m_selected_gps_pos_publisher.publish(msg);
00339 }
00340 }
00341
00342 void MarblePlugin::processMarkerCheckBoxCLicked()
00343 {
00344 if(ui_.checkBox_process_marker->isChecked())
00345 {
00346 subscribeVisualization();
00347 }
00348 else
00349 {
00350 m_visualization_subscriber.shutdown();
00351 m_visualization_marker_array_subscriber.shutdown();
00352 m_reference_gps_subscriber.shutdown();
00353 }
00354 }
00355
00356 void MarblePlugin::subscribeVisualization()
00357 {
00358 m_visualization_subscriber = getNodeHandle().subscribe("/visualization_marker", 1, &DrawableMarbleWidget::visualizationCallback, ui_.MarbleWidget);
00359 m_visualization_marker_array_subscriber = getNodeHandle().subscribe("/visualization_marker_array", 1, &DrawableMarbleWidget::visualizationMarkerArrayCallback, ui_.MarbleWidget);
00360
00361 }
00362
00363 void MarblePlugin::saveSettings(qt_gui_cpp::Settings& plugin_settings, qt_gui_cpp::Settings& instance_settings) const
00364 {
00365
00366 QString topic(m_current_pos_subscriber.getTopic().c_str());
00367 instance_settings.setValue( "marble_plugin_topic_current", topic );
00368
00369 topic = QString(m_matched_pos_subscriber.getTopic().c_str());
00370 instance_settings.setValue( "marble_plugin_topic_matched", topic );
00371
00372 instance_settings.setValue( "marble_plugin_zoom" , ui_.MarbleWidget->distance() );
00373 instance_settings.setValue( "marble_theme_index" , ui_.comboBox_theme->currentIndex() );
00374 instance_settings.setValue( "marble_center" , ui_.checkBox_center->isChecked() );
00375 instance_settings.setValue( "piblish_gps" , ui_.checkBox_publish_gps->isChecked() );
00376 instance_settings.setValue( "process_marker" , ui_.checkBox_process_marker->isChecked() );
00377
00378
00379
00380 int i=0;
00381 instance_settings.setValue("kml_number", QVariant::fromValue(m_last_kml_data.size()) );
00382 for(std::map< QString, bool>::const_iterator it = m_last_kml_data.begin(); it != m_last_kml_data.end(); it++)
00383 {
00384 QString key("kml_file_");
00385 key.append(i);
00386 instance_settings.setValue(key, it->first);
00387
00388
00389
00390
00391 i++;
00392 }
00393 }
00394
00395 void MarblePlugin::restoreSettings(const qt_gui_cpp::Settings& plugin_settings, const qt_gui_cpp::Settings& instance_settings)
00396 {
00397
00398 const QString topic_current = instance_settings.value("marble_plugin_topic_current").toString();
00399 ChangeGPSTopicCurrentGPS(topic_current);
00400
00401 const QString topic_matched = instance_settings.value("marble_plugin_topic_matched").toString();
00402 ChangeGPSTopicMatchedGPS(topic_matched);
00403
00404 ui_.comboBox_theme->setCurrentIndex( instance_settings.value( "marble_theme_index" , 0 ).toInt() );
00405 ui_.checkBox_center->setChecked( instance_settings.value( "marble_center" , true ).toBool());
00406 ui_.checkBox_publish_gps->setChecked( instance_settings.value( "piblish_gps" , true ).toBool());
00407 ui_.checkBox_process_marker->setChecked( instance_settings.value( "process_marker" , true ).toBool());
00408
00409
00410
00411 std::map< QString, bool> kml_files;
00412 int number = instance_settings.value("kml_number",0).toInt();
00413 for(int i=0; i<number; i++)
00414 {
00415 QString key("kml_file_");
00416 key.append(i);
00417 kml_files[instance_settings.value(key,0).toString()] = true;
00418 }
00419 addKMLData(kml_files, true);
00420
00421
00422
00423
00424
00425 ui_.MarbleWidget->setDistance( instance_settings.value( "marble_plugin_zoom" , 0.05 ).toReal() );
00426 }
00427
00428 void MarblePlugin::shutdownPlugin()
00429 {
00430
00431 m_current_pos_subscriber.shutdown();
00432 m_matched_pos_subscriber.shutdown();
00433 m_selected_gps_pos_publisher.shutdown();
00434 m_mapcontrol_subscriber.shutdown();
00435 m_visualization_subscriber.shutdown();
00436 m_visualization_marker_array_subscriber.shutdown();
00437 m_reference_gps_subscriber.shutdown();
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 }
00451 PLUGINLIB_EXPORT_CLASS( rqt_marble_plugin::MarblePlugin , rqt_gui_cpp::Plugin )