map_merger.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Dirk Thomas, TU Darmstadt
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
00007  * are met:
00008  *
00009  *   * Redistributions of source code must retain the above copyright
00010  *     notice, this list of conditions and the following disclaimer.
00011  *   * Redistributions in binary form must reproduce the above
00012  *     copyright notice, this list of conditions and the following
00013  *     disclaimer in the documentation and/or other materials provided
00014  *     with the distribution.
00015  *   * Neither the name of the TU Darmstadt nor the names of its
00016  *     contributors may be used to endorse or promote products derived
00017  *     from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00027  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00029  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030  * POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #include <rqt_map_merger/map_merger.h>
00034 
00035 #include <pluginlib/class_list_macros.h>
00036 #include <ros/master.h>
00037 #include <sensor_msgs/image_encodings.h>
00038 
00039 #include <cv_bridge/cv_bridge.h>
00040 #include <opencv2/imgproc/imgproc.hpp>
00041 
00042 #include <QMessageBox>
00043 #include <QPainter>
00044 #include <opencv/cv.h>
00045 #include <opencv/highgui.h>
00046 #include <geometry_msgs/Transform.h>
00047 #include "hector_mapstitch/mapstitch.h"
00048 #include "hector_mapstitch/utils.h"
00049 #include <std_msgs/String.h>
00050 #include <sstream>
00051 
00052 namespace rqt_map_merger {
00053 
00054 MapMerger::MapMerger()
00055   : rqt_gui_cpp::Plugin()
00056   , widget_(0)
00057 {
00058   setObjectName("MapMerger");
00059 }
00060 
00061 void MapMerger::initPlugin(qt_gui_cpp::PluginContext& context)
00062 {
00063     std::cout << "started map merging plugin " <<std::endl;
00064   widget_ = new QWidget();
00065   ui_.setupUi(widget_);
00066 
00067   if (context.serialNumber() > 1)
00068   {
00069     widget_->setWindowTitle(widget_->windowTitle() + " (" + QString::number(context.serialNumber()) + ")");
00070   }
00071   context.addWidget(widget_);
00072 
00073   ui_.map2_label->installEventFilter(this);
00074   ui_.map1_label->installEventFilter(this);
00075 
00076   map_1_sub_= my_nh_.subscribe("/original_map_robot_1", 1, &MapMerger::map1Callback,this);
00077   map_2_sub_= my_nh_.subscribe("/original_map_robot_2", 1, &MapMerger::map2Callback,this);
00078 
00079   map_1_to_use_pub_ = my_nh_.advertise<nav_msgs::OccupancyGrid>("/map_to_use_1",10,true);
00080   map_2_to_use_pub_ = my_nh_.advertise<nav_msgs::OccupancyGrid>("/map_to_use_2",10,true);
00081 
00082   hector_command_pub_ = my_nh_.advertise<std_msgs::String>("/syscommand", 10,true);
00083 
00084   //ros::ServiceServer servserv = my_nh_.advertiseService(stitched_map_topic + "_serive",stitchedMapService);
00085 
00086 
00087   //updateTopicList();
00088   //ui_.topics_combo_box->setCurrentIndex(ui_.topics_combo_box->findText(""));
00089   connect(ui_.map_hector1_horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(onSlider1Moved(int)));
00090   connect(ui_.map_hector2_horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(onSlider2Moved(int)));
00091   connect(ui_.merge_button, SIGNAL(pressed()), this, SLOT(onMergePressed()));
00092   connect(ui_.save_geotiff_button, SIGNAL(pressed()), this, SLOT(onSaveGeotiffPressed()));
00093   connect(ui_.use_stored_transform_checkBox, SIGNAL(stateChanged(int)), this, SLOT(onStateUseTransformChanged(int)));
00094   connect(ui_.store_current_transform_button, SIGNAL(pressed()), this, SLOT(onGetTransform()));
00095 
00096   redraw_Label_1();
00097   redraw_Label_2();
00098    map_save_timer_ = my_nh_.createTimer(ros::Duration(20.0), &MapMerger::timerCallback, this, false );
00099   current_idx_1_ = 0;
00100   current_idx_2_ = 0;
00101   stored_idx_1_ = 0;
00102   stored_idx_2_ = 0;
00103   use_stored_transform_ = false;
00104   first_map_1_received =0;
00105   first_map_2_received =0;
00106 
00107   std::stringstream sstr;
00108   sstr << stored_idx_1_ << " | " << stored_idx_2_;
00109 
00110   ui_.stored_transform_text->setText(sstr.str().c_str());
00111 }
00112 
00113  void MapMerger::timerCallback(const ros::TimerEvent& e){
00114   qimages_1_.push_back(qimage_1_);
00115   qimages_2_.push_back(qimage_2_);
00116   cv_maps_1_.push_back(cv_map_1_);
00117   cv_maps_2_.push_back(cv_map_2_);
00118   og_maps_1_.push_back(og_map_1_);
00119   og_maps_2_.push_back(og_map_2_);
00120   ui_.map_hector1_horizontalSlider->setRange(0,qimages_1_.size()-1);
00121   ui_.map_hector2_horizontalSlider->setRange(0,qimages_2_.size()-1);
00122  }
00123 
00124 
00125 
00126 void MapMerger::onSlider1Moved(int idx){
00127   current_idx_1_ = idx;
00128 
00129   std::stringstream sstr;
00130   sstr << idx;
00131 
00132   ui_.map_1_text->setText(sstr.str().c_str());
00133   redraw_Label_1();
00134 }
00135 
00136 void MapMerger::onSlider2Moved(int idx){
00137   current_idx_2_ = idx;
00138 
00139   std::stringstream sstr;
00140   sstr << idx;
00141 
00142   ui_.map_2_text->setText(sstr.str().c_str());
00143   redraw_Label_2();
00144 }
00145 
00146 void MapMerger::onMergePressed(){
00147     redraw_Label_merged();
00148 }
00149 
00150 void MapMerger::onStateUseTransformChanged(int checked){
00151     use_stored_transform_ = checked;
00152     stored_transform = current_transform;
00153 
00154 }
00155 
00156 void MapMerger::onGetTransform(){
00157     std::cout << "1" <<stored_idx_1_ <<"2" <<stored_idx_2_ << std::endl;
00158     stored_transform = current_transform;
00159     stored_idx_1_ = current_idx_1_;
00160     stored_idx_2_ = current_idx_2_;
00161     std::stringstream sstr;
00162     sstr << stored_idx_1_  << " | " << stored_idx_2_;
00163 
00164     ui_.stored_transform_text->setText(sstr.str().c_str());
00165 }
00166 
00167 void MapMerger::onSaveGeotiffPressed(){
00168     std_msgs::String geo_string;
00169     geo_string.data = "savegeotiff";
00170     hector_command_pub_.publish(geo_string);
00171 }
00172 
00173 void MapMerger::redraw_Label_1(){
00174     if (qimages_1_.size()>0)
00175     {
00176 
00177       qimage_mutex_.lock();
00178 
00179       QImage image_scaled = qimages_1_[current_idx_1_].scaled(ui_.map1_label->width(), ui_.map1_label->height(), Qt::IgnoreAspectRatio );
00180        ui_.map1_label->setPixmap(QPixmap::fromImage(image_scaled));
00181 
00182       qimage_mutex_.unlock();
00183 
00184 
00185     } else {
00186       ROS_INFO("no map for robot1 known");
00187     }
00188 
00189 
00190 }
00191 
00192 void MapMerger::redraw_Label_2(){
00193 
00194     if (qimages_2_.size()>0)
00195     {
00196       qimage_mutex_.lock();
00197 
00198 
00199       QImage image_scaled = qimages_2_[current_idx_2_].scaled(ui_.map2_label->width(), ui_.map2_label->height(), Qt::IgnoreAspectRatio );
00200       ui_.map2_label->setPixmap(QPixmap::fromImage(image_scaled));
00201       qimage_mutex_.unlock();
00202 
00203     } else {
00204       ROS_INFO("no map for robot2 known");
00205 
00206 
00207     }
00208 
00209 
00210 }
00211 
00212 void MapMerger::redraw_Label_merged(){
00213 
00214      if (cv_maps_1_.size() > 0 && cv_maps_2_.size()>0 && og_maps_1_.size()>0 && og_maps_2_.size()>0){
00215 
00216          StitchedMap stitched_map(cv_maps_1_[stored_idx_1_], cv_maps_2_[stored_idx_2_],stored_transform);
00217          if (!use_stored_transform_){
00218              stitched_map =StitchedMap(cv_maps_1_[current_idx_1_], cv_maps_2_[current_idx_2_]);
00219          }
00220 
00221 
00222     if(stitched_map.isValid())
00223     {
00224         ui_.merge_button->setText("merging ...");
00225         cv::Mat stitched_cv_map = stitched_map.get_stitch();
00226         ui_.merge_button->setText("merge");
00227         cv::Mat gray;
00228         stitched_cv_map.convertTo(gray, CV_8UC1);
00229         cv::Mat temp;
00230         cv::cvtColor(gray, temp, CV_GRAY2RGB);
00231 
00232 
00233         QImage image(temp.data, temp.cols, temp.rows, QImage::Format_RGB888);
00234         QImage image_scaled = image.scaled(ui_.merged_map_label->width(), ui_.merged_map_label->height(), Qt::IgnoreAspectRatio );
00235         ui_.merged_map_label->setPixmap(QPixmap::fromImage(image_scaled));
00236 
00237         map_1_to_use_pub_.publish(og_maps_1_[current_idx_1_]);
00238         map_2_to_use_pub_.publish(og_maps_2_[current_idx_2_]);
00239 
00240 
00241         current_transform = stitched_map.getRigidTransform().clone();
00242     }
00243 
00244     }
00245 }
00246 
00247 bool MapMerger::eventFilter(QObject* watched, QEvent* event)
00248 {/*bool successfull = true;
00249 
00250   if (watched == ui_.map2_label && event->type() == QEvent::Paint)
00251   {
00252 
00253     redraw_Label_2();
00254     //successfull = false;
00255   }
00256 
00257   if (watched == ui_.map1_label && event->type() == QEvent::Paint)
00258   {
00259     redraw_Label_1();
00260     //successfull = false;
00261   }
00262 
00263   if (successfull){
00264   return QObject::eventFilter(watched, event);}
00265   else{
00266       return false;
00267   }*/
00268     return QObject::eventFilter(watched, event);
00269 }
00270 
00271 void MapMerger::shutdownPlugin()
00272 {
00273   
00274 }
00275 
00276 void MapMerger::map1Callback(nav_msgs::OccupancyGridConstPtr const & map)
00277 {
00278     cv::Mat map1_cv = occupancyGridToCvMat(map.get());
00279     cv::Mat gray;
00280     map1_cv.convertTo(gray, CV_8UC1);
00281     cv::cvtColor(gray, conversion_mat_, CV_GRAY2RGB);
00282 
00283 
00284     QImage image(conversion_mat_.data, conversion_mat_.cols, conversion_mat_.rows, QImage::Format_RGB888);
00285 
00286     qimage_mutex_.lock();
00287     qimage_1_ = image.copy();
00288     qimage_mutex_.unlock();
00289 
00290     cv_map_1_ = map1_cv;
00291     og_map_1_ = *map;
00292 
00293 
00294 
00295 
00296 
00297 
00298 }
00299 
00300 void MapMerger::map2Callback(nav_msgs::OccupancyGridConstPtr const & map)
00301 {
00302     cv::Mat map2_cv = occupancyGridToCvMat(map.get());
00303     cv::Mat gray;
00304     map2_cv.convertTo(gray, CV_8UC1);
00305     cv::cvtColor(gray, conversion_mat_, CV_GRAY2RGB);
00306     QImage image(conversion_mat_.data, conversion_mat_.cols, conversion_mat_.rows, QImage::Format_RGB888);
00307 
00308     qimage_mutex_.lock();
00309     qimage_2_ = image.copy();
00310     qimage_mutex_.unlock();
00311 
00312     cv_map_2_ = map2_cv;
00313     og_map_2_ = *map;
00314 
00315     if (!first_map_2_received){
00316 
00317         first_map_2_received = true;
00318         redraw_Label_2();
00319     }
00320 
00321 
00322 }
00323 
00324 nav_msgs::OccupancyGrid MapMerger::cvMatToOccupancyGrid(const cv::Mat * im)
00325 {
00326     nav_msgs::OccupancyGrid map;
00327 
00328     map.info.height = im->rows;
00329     map.info.width = im->cols;
00330 
00331     map.data.resize(map.info.width * map.info.height);
00332 
00333     for(size_t i = 0; i < map.data.size(); ++i)
00334     {
00335         uint8_t map_val = im->data[i];
00336         if(map_val == 0) map.data[i] = 100;
00337         else if(map_val == 254) map.data[i] = 0;
00338         else map.data[i] = -1;
00339     }
00340 
00341     return map;
00342 }
00343 
00344 
00345 cv::Mat MapMerger::occupancyGridToCvMat(const nav_msgs::OccupancyGrid *map)
00346 {
00347   uint8_t *data = (uint8_t*) map->data.data(),
00348            testpoint = data[0];
00349   bool mapHasPoints = false;
00350 
00351   cv::Mat im(map->info.height, map->info.width, CV_8UC1);
00352 
00353   // transform the map in the same way the map_saver component does
00354   for (size_t i=0; i<map->data.size(); i++)
00355   {
00356     if (data[i] == 0)        im.data[i] = 254;
00357     else if (data[i] == 100) im.data[i] = 0;
00358     else im.data[i] = 205;
00359 
00360     // just check if there is actually something in the map
00361     if (i!=0) mapHasPoints = mapHasPoints || (data[i] != testpoint);
00362     testpoint = data[i];
00363   }
00364 
00365   // sanity check
00366   if (!mapHasPoints) { ROS_WARN("map is empty, ignoring update."); }
00367 
00368   return im;
00369 }
00370 
00371 }
00372 PLUGINLIB_EXPORT_CLASS(rqt_map_merger::MapMerger, rqt_gui_cpp::Plugin)
00373 


hector_rqt_plugins
Author(s): Dirk Thomas, Thorsten Graber, Gregor Gebhardt
autogenerated on Thu Aug 27 2015 13:22:18