map_merger.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Dirk Thomas, TU Darmstadt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following
13  * disclaimer in the documentation and/or other materials provided
14  * with the distribution.
15  * * Neither the name of the TU Darmstadt nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
34 
36 #include <ros/master.h>
38 
39 #include <cv_bridge/cv_bridge.h>
40 #include <opencv2/imgproc/imgproc.hpp>
41 
42 #include <QMessageBox>
43 #include <QPainter>
44 #include <opencv/cv.h>
45 #include <opencv/highgui.h>
46 #include <geometry_msgs/Transform.h>
47 #include "hector_mapstitch/mapstitch.h"
48 #include "hector_mapstitch/utils.h"
49 #include <std_msgs/String.h>
50 #include <sstream>
51 
52 namespace rqt_map_merger {
53 
55  : rqt_gui_cpp::Plugin()
56  , widget_(0)
57 {
58  setObjectName("MapMerger");
59 }
60 
62 {
63  std::cout << "started map merging plugin " <<std::endl;
64  widget_ = new QWidget();
65  ui_.setupUi(widget_);
66 
67  if (context.serialNumber() > 1)
68  {
69  widget_->setWindowTitle(widget_->windowTitle() + " (" + QString::number(context.serialNumber()) + ")");
70  }
71  context.addWidget(widget_);
72 
73  ui_.map2_label->installEventFilter(this);
74  ui_.map1_label->installEventFilter(this);
75 
76  map_1_sub_= my_nh_.subscribe("/original_map_robot_1", 1, &MapMerger::map1Callback,this);
77  map_2_sub_= my_nh_.subscribe("/original_map_robot_2", 1, &MapMerger::map2Callback,this);
78 
79  map_1_to_use_pub_ = my_nh_.advertise<nav_msgs::OccupancyGrid>("/map_to_use_1",10,true);
80  map_2_to_use_pub_ = my_nh_.advertise<nav_msgs::OccupancyGrid>("/map_to_use_2",10,true);
81 
82  hector_command_pub_ = my_nh_.advertise<std_msgs::String>("/syscommand", 10,true);
83 
84  //ros::ServiceServer servserv = my_nh_.advertiseService(stitched_map_topic + "_serive",stitchedMapService);
85 
86 
87  //updateTopicList();
88  //ui_.topics_combo_box->setCurrentIndex(ui_.topics_combo_box->findText(""));
89  connect(ui_.map_hector1_horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(onSlider1Moved(int)));
90  connect(ui_.map_hector2_horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(onSlider2Moved(int)));
91  connect(ui_.merge_button, SIGNAL(pressed()), this, SLOT(onMergePressed()));
92  connect(ui_.save_geotiff_button, SIGNAL(pressed()), this, SLOT(onSaveGeotiffPressed()));
93  connect(ui_.use_stored_transform_checkBox, SIGNAL(stateChanged(int)), this, SLOT(onStateUseTransformChanged(int)));
94  connect(ui_.store_current_transform_button, SIGNAL(pressed()), this, SLOT(onGetTransform()));
95 
99  current_idx_1_ = 0;
100  current_idx_2_ = 0;
101  stored_idx_1_ = 0;
102  stored_idx_2_ = 0;
103  use_stored_transform_ = false;
106 
107  std::stringstream sstr;
108  sstr << stored_idx_1_ << " | " << stored_idx_2_;
109 
110  ui_.stored_transform_text->setText(sstr.str().c_str());
111 }
112 
114  qimages_1_.push_back(qimage_1_);
115  qimages_2_.push_back(qimage_2_);
116  cv_maps_1_.push_back(cv_map_1_);
117  cv_maps_2_.push_back(cv_map_2_);
118  og_maps_1_.push_back(og_map_1_);
119  og_maps_2_.push_back(og_map_2_);
120  ui_.map_hector1_horizontalSlider->setRange(0,qimages_1_.size()-1);
121  ui_.map_hector2_horizontalSlider->setRange(0,qimages_2_.size()-1);
122  }
123 
124 
125 
127  current_idx_1_ = idx;
128 
129  std::stringstream sstr;
130  sstr << idx;
131 
132  ui_.map_1_text->setText(sstr.str().c_str());
133  redraw_Label_1();
134 }
135 
137  current_idx_2_ = idx;
138 
139  std::stringstream sstr;
140  sstr << idx;
141 
142  ui_.map_2_text->setText(sstr.str().c_str());
143  redraw_Label_2();
144 }
145 
148 }
149 
151  use_stored_transform_ = checked;
153 
154 }
155 
157  std::cout << "1" <<stored_idx_1_ <<"2" <<stored_idx_2_ << std::endl;
161  std::stringstream sstr;
162  sstr << stored_idx_1_ << " | " << stored_idx_2_;
163 
164  ui_.stored_transform_text->setText(sstr.str().c_str());
165 }
166 
168  std_msgs::String geo_string;
169  geo_string.data = "savegeotiff";
170  hector_command_pub_.publish(geo_string);
171 }
172 
174  if (qimages_1_.size()>0)
175  {
176 
177  qimage_mutex_.lock();
178 
179  QImage image_scaled = qimages_1_[current_idx_1_].scaled(ui_.map1_label->width(), ui_.map1_label->height(), Qt::IgnoreAspectRatio );
180  ui_.map1_label->setPixmap(QPixmap::fromImage(image_scaled));
181 
182  qimage_mutex_.unlock();
183 
184 
185  } else {
186  ROS_INFO("no map for robot1 known");
187  }
188 
189 
190 }
191 
193 
194  if (qimages_2_.size()>0)
195  {
196  qimage_mutex_.lock();
197 
198 
199  QImage image_scaled = qimages_2_[current_idx_2_].scaled(ui_.map2_label->width(), ui_.map2_label->height(), Qt::IgnoreAspectRatio );
200  ui_.map2_label->setPixmap(QPixmap::fromImage(image_scaled));
201  qimage_mutex_.unlock();
202 
203  } else {
204  ROS_INFO("no map for robot2 known");
205 
206 
207  }
208 
209 
210 }
211 
213 
214  if (cv_maps_1_.size() > 0 && cv_maps_2_.size()>0 && og_maps_1_.size()>0 && og_maps_2_.size()>0){
215 
217  if (!use_stored_transform_){
218  stitched_map =StitchedMap(cv_maps_1_[current_idx_1_], cv_maps_2_[current_idx_2_]);
219  }
220 
221 
222  if(stitched_map.isValid())
223  {
224  ui_.merge_button->setText("merging ...");
225  cv::Mat stitched_cv_map = stitched_map.get_stitch();
226  ui_.merge_button->setText("merge");
227  cv::Mat gray;
228  stitched_cv_map.convertTo(gray, CV_8UC1);
229  cv::Mat temp;
230  cv::cvtColor(gray, temp, CV_GRAY2RGB);
231 
232 
233  QImage image(temp.data, temp.cols, temp.rows, QImage::Format_RGB888);
234  QImage image_scaled = image.scaled(ui_.merged_map_label->width(), ui_.merged_map_label->height(), Qt::IgnoreAspectRatio );
235  ui_.merged_map_label->setPixmap(QPixmap::fromImage(image_scaled));
236 
239 
240 
241  current_transform = stitched_map.getRigidTransform().clone();
242  }
243 
244  }
245 }
246 
247 bool MapMerger::eventFilter(QObject* watched, QEvent* event)
248 {/*bool successfull = true;
249 
250  if (watched == ui_.map2_label && event->type() == QEvent::Paint)
251  {
252 
253  redraw_Label_2();
254  //successfull = false;
255  }
256 
257  if (watched == ui_.map1_label && event->type() == QEvent::Paint)
258  {
259  redraw_Label_1();
260  //successfull = false;
261  }
262 
263  if (successfull){
264  return QObject::eventFilter(watched, event);}
265  else{
266  return false;
267  }*/
268  return QObject::eventFilter(watched, event);
269 }
270 
272 {
273 
274 }
275 
276 void MapMerger::map1Callback(nav_msgs::OccupancyGridConstPtr const & map)
277 {
278  cv::Mat map1_cv = occupancyGridToCvMat(map.get());
279  cv::Mat gray;
280  map1_cv.convertTo(gray, CV_8UC1);
281  cv::cvtColor(gray, conversion_mat_, CV_GRAY2RGB);
282 
283 
284  QImage image(conversion_mat_.data, conversion_mat_.cols, conversion_mat_.rows, QImage::Format_RGB888);
285 
286  qimage_mutex_.lock();
287  qimage_1_ = image.copy();
288  qimage_mutex_.unlock();
289 
290  cv_map_1_ = map1_cv;
291  og_map_1_ = *map;
292 
293 
294 
295 
296 
297 
298 }
299 
300 void MapMerger::map2Callback(nav_msgs::OccupancyGridConstPtr const & map)
301 {
302  cv::Mat map2_cv = occupancyGridToCvMat(map.get());
303  cv::Mat gray;
304  map2_cv.convertTo(gray, CV_8UC1);
305  cv::cvtColor(gray, conversion_mat_, CV_GRAY2RGB);
306  QImage image(conversion_mat_.data, conversion_mat_.cols, conversion_mat_.rows, QImage::Format_RGB888);
307 
308  qimage_mutex_.lock();
309  qimage_2_ = image.copy();
310  qimage_mutex_.unlock();
311 
312  cv_map_2_ = map2_cv;
313  og_map_2_ = *map;
314 
315  if (!first_map_2_received){
316 
317  first_map_2_received = true;
318  redraw_Label_2();
319  }
320 
321 
322 }
323 
324 nav_msgs::OccupancyGrid MapMerger::cvMatToOccupancyGrid(const cv::Mat * im)
325 {
326  nav_msgs::OccupancyGrid map;
327 
328  map.info.height = im->rows;
329  map.info.width = im->cols;
330 
331  map.data.resize(map.info.width * map.info.height);
332 
333  for(size_t i = 0; i < map.data.size(); ++i)
334  {
335  uint8_t map_val = im->data[i];
336  if(map_val == 0) map.data[i] = 100;
337  else if(map_val == 254) map.data[i] = 0;
338  else map.data[i] = -1;
339  }
340 
341  return map;
342 }
343 
344 
345 cv::Mat MapMerger::occupancyGridToCvMat(const nav_msgs::OccupancyGrid *map)
346 {
347  uint8_t *data = (uint8_t*) map->data.data(),
348  testpoint = data[0];
349  bool mapHasPoints = false;
350 
351  cv::Mat im(map->info.height, map->info.width, CV_8UC1);
352 
353  // transform the map in the same way the map_saver component does
354  for (size_t i=0; i<map->data.size(); i++)
355  {
356  if (data[i] == 0) im.data[i] = 254;
357  else if (data[i] == 100) im.data[i] = 0;
358  else im.data[i] = 205;
359 
360  // just check if there is actually something in the map
361  if (i!=0) mapHasPoints = mapHasPoints || (data[i] != testpoint);
362  testpoint = data[i];
363  }
364 
365  // sanity check
366  if (!mapHasPoints) { ROS_WARN("map is empty, ignoring update."); }
367 
368  return im;
369 }
370 
371 }
373 
ros::Publisher map_2_to_use_pub_
Definition: map_merger.h:147
bool eventFilter(QObject *watched, QEvent *event)
Definition: map_merger.cpp:247
virtual void shutdownPlugin()
Definition: map_merger.cpp:271
std::vector< QImage > qimages_1_
Definition: map_merger.h:112
ros::Publisher map_1_to_use_pub_
Definition: map_merger.h:146
void publish(const boost::shared_ptr< M > &message) const
void onSlider1Moved(int idx)
Definition: map_merger.cpp:126
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::vector< cv::Mat > cv_maps_2_
Definition: map_merger.h:119
std::vector< QImage > qimages_2_
Definition: map_merger.h:118
std::vector< cv::Mat > cv_maps_1_
Definition: map_merger.h:113
nav_msgs::OccupancyGrid og_map_1_
Definition: map_merger.h:117
void addWidget(QWidget *widget)
nav_msgs::OccupancyGrid og_map_2_
Definition: map_merger.h:123
Ui::MapMergerWidget ui_
Definition: map_merger.h:103
#define ROS_WARN(...)
cv::Mat occupancyGridToCvMat(const nav_msgs::OccupancyGrid *map)
Definition: map_merger.cpp:345
ros::NodeHandle my_nh_
Definition: map_merger.h:132
std::vector< nav_msgs::OccupancyGrid > og_maps_1_
Definition: map_merger.h:114
ros::Publisher hector_command_pub_
Definition: map_merger.h:148
#define ROS_INFO(...)
void map2Callback(nav_msgs::OccupancyGridConstPtr const &map)
Definition: map_merger.cpp:300
void timerCallback(const ros::TimerEvent &e)
Definition: map_merger.cpp:113
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::Subscriber map_2_sub_
Definition: map_merger.h:110
void map1Callback(nav_msgs::OccupancyGridConstPtr const &map)
Definition: map_merger.cpp:276
virtual void initPlugin(qt_gui_cpp::PluginContext &context)
Definition: map_merger.cpp:61
void onStateUseTransformChanged(int checked)
Definition: map_merger.cpp:150
void onSlider2Moved(int idx)
Definition: map_merger.cpp:136
ros::Subscriber map_1_sub_
Definition: map_merger.h:109
nav_msgs::OccupancyGrid cvMatToOccupancyGrid(const cv::Mat *im)
Definition: map_merger.cpp:324
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
std::vector< nav_msgs::OccupancyGrid > og_maps_2_
Definition: map_merger.h:120


hector_rqt_plugins
Author(s): Dirk Thomas, Thorsten Graber, Gregor Gebhardt
autogenerated on Mon Jun 10 2019 13:36:34