YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
MapGrid2D.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#define _USE_MATH_DEFINES
7
9
10#include <yarp/os/Bottle.h>
13#include <yarp/os/LogStream.h>
14#include <yarp/sig/ImageFile.h>
15#include <algorithm>
16#include <fstream>
17#include <cmath>
18
19#if defined (YARP_HAS_ZLIB)
20#include <zlib.h>
21#endif
22
23
24using namespace yarp::dev;
25using namespace yarp::dev::Nav2D;
26using namespace yarp::sig;
27using namespace yarp::os;
28using namespace yarp::math;
29
30#ifndef DEG2RAD
31#define DEG2RAD M_PI/180.0
32#endif
33
34#ifndef RAD2DEG
35#define RAD2DEG 180.0/M_PI
36#endif
37
38//helper functions
39static std::string extractPathFromFile(std::string full_filename)
40{
41 size_t found;
42 found = full_filename.find_last_of('/');
43 if (found != std::string::npos) {
44 return full_filename.substr(0, found) + "/";
45 }
46 found = full_filename.find_last_of('\\');
47 if (found != std::string::npos) {
48 return full_filename.substr(0, found) + "\\";
49 }
50 return full_filename;
51}
52
53static std::string extractExtensionFromFile(std::string full_filename)
54{
55 int start = full_filename.length() - 3;
56 return full_filename.substr(start, 3);
57}
58
59
60bool MapGrid2D::isIdenticalTo(const MapGrid2D& other) const
61{
62 if (m_map_name != other.m_map_name) {
63 return false;
64 }
65 if (m_origin != other.m_origin) {
66 return false;
67 }
68 if (m_resolution != other.m_resolution) {
69 return false;
70 }
71 if (m_width != other.width()) {
72 return false;
73 }
74 if (m_height != other.height()) {
75 return false;
76 }
77 for (size_t y = 0; y < m_height; y++) {
78 for (size_t x = 0; x < m_width; x++) {
79 if (m_map_occupancy.safePixel(x, y) != other.m_map_occupancy.safePixel(x, y)) {
80 return false;
81 }
82 }
83 }
84 for (size_t y = 0; y < m_height; y++) {
85 for (size_t x = 0; x < m_width; x++) {
86 if (m_map_flags.safePixel(x, y) != other.m_map_flags.safePixel(x, y)) {
87 return false;
88 }
89 }
90 }
91 return true;
92}
93
95{
96 m_resolution = 1.0; //each pixel corresponds to 1 m
97 m_width = 2;
98 m_height = 2;
99 m_map_occupancy.setQuantum(1); //we do not want extra padding in map images
100 m_map_flags.setQuantum(1);
101 m_map_occupancy.resize(m_width, m_height);
102 m_map_flags.resize(m_width, m_height);
103 m_occupied_thresh = 0.80;
104 m_free_thresh = 0.20;
105 for (size_t y = 0; y < m_height; y++)
106 {
107 for (size_t x = 0; x < m_width; x++)
108 {
109 m_map_occupancy.safePixel(x, y) = 0;
111 }
112 }
113#if defined (YARP_HAS_ZLIB)
114 m_compressed_data_over_network = true;
115#else
116 m_compressed_data_over_network = false;
117#endif
118}
119
120MapGrid2D::~MapGrid2D() = default;
121
123{
124 if (isInsideMap(cell))
125 {
126 if (m_map_occupancy.safePixel(cell.x, cell.y) != 0) {
127 return true;
128 }
130 return true;
131 }
133 return true;
134 }
136 return true;
137 }
138 }
139 return false;
140}
141
143{
144 if (isInsideMap(cell))
145 {
146 if (m_map_occupancy.safePixel(cell.x, cell.y) == 0 && m_map_flags.safePixel(cell.x, cell.y) == MapGrid2D::map_flags::MAP_CELL_FREE) {
147 return true;
148 }
149 }
150 return false;
151}
152
154{
155 if (isInsideMap(cell))
156 {
158 return true;
159 }
160 }
161 return false;
162}
163
165{
166 if (isInsideMap(cell))
167 {
168 // if (m_map_occupancy.safePixel(cell.x, cell.y) == 0)
169 // return true;
170 if (m_map_flags.safePixel(cell.x, cell.y) == MapGrid2D::map_flags::MAP_CELL_WALL) {
171 return true;
172 }
173 }
174 return false;
175}
176
177size_t MapGrid2D::height() const
178{
179 return m_height;
180}
181
182size_t MapGrid2D::width() const
183{
184 return m_width;
185}
186
188{
189 image.setQuantum(1);
190 image.resize(m_width, m_height);
191 image.zero();
192 for (size_t y = 0; y < m_height; y++)
193 {
194 for (size_t x = 0; x < m_width; x++)
195 {
196 image.safePixel(x, y) = CellFlagDataToPixel(m_map_flags.safePixel(x, y));
197 }
198 }
199 return true;
200}
201
203{
204 if (image.width() != m_width ||
205 image.height() != m_height)
206 {
207 yError() << "The size of given image does not correspond to the current map. Use method setSize() first.";
208 return false;
209 }
210 for (size_t y = 0; y < m_height; y++)
211 {
212 for (size_t x = 0; x < m_width; x++)
213 {
214 m_map_flags.safePixel(x, y) = PixelToCellFlagData(image.safePixel(x, y));
215 }
216 }
217 return true;
218}
219
221{
222 if (size <= 0)
223 {
224 for (size_t y = 0; y < m_height; y++)
225 {
226 for (size_t x = 0; x < m_width; x++)
227 {
228 if (this->m_map_flags.safePixel(x, y) == MapGrid2D::map_flags::MAP_CELL_ENLARGED_OBSTACLE)
229 {
230 this->m_map_flags.safePixel(x, y) = MapGrid2D::map_flags::MAP_CELL_FREE;
231 }
232 }
233 }
234 return true;
235 }
236 auto repeat_num = (size_t)(std::ceil(size/ m_resolution));
237 for (size_t repeat = 0; repeat < repeat_num; repeat++)
238 {
239 //contains the cells to be enlarged;
240 std::vector<XYCell> list_of_cells;
241 for (size_t y = 0; y < m_height; y++)
242 {
243 for (size_t x = 0; x < m_width; x++)
244 {
245 //this check could be optimized...
246 if (this->m_map_flags.safePixel(x, y) == MAP_CELL_KEEP_OUT ||
247 this->m_map_flags.safePixel(x, y) == MAP_CELL_ENLARGED_OBSTACLE ||
248 this->m_map_flags.safePixel(x, y) == MAP_CELL_WALL ||
249 this->m_map_flags.safePixel(x, y) == MAP_CELL_UNKNOWN ||
250 this->m_map_flags.safePixel(x, y) == MAP_CELL_TEMPORARY_OBSTACLE)
251 {
252 list_of_cells.emplace_back(x, y);
253 }
254 }
255 }
256
257 //process each cell of the list and enlarges it
258 for (auto& list_of_cell : list_of_cells)
259 {
260 enlargeCell(list_of_cell);
261 }
262 }
263 return true;
264}
265
266void MapGrid2D::enlargeCell(XYCell cell)
267{
268 size_t i = cell.x;
269 size_t j = cell.y;
270 size_t il = cell.x > 1 ? cell.x - 1 : 0;
271 size_t ir = cell.x + 1 < (m_width)-1 ? cell.x + 1 : (m_width)-1;
272 size_t ju = cell.y > 1 ? cell.y - 1 : 0;
273 size_t jd = cell.y + 1 < (m_height)-1 ? cell.y + 1 : (m_height)-1;
274
275 if (m_map_flags.pixel(il, j) == MAP_CELL_FREE) {
276 m_map_flags.pixel(il, j) = MAP_CELL_ENLARGED_OBSTACLE;
277 }
278 if (m_map_flags.pixel(ir, j) == MAP_CELL_FREE) {
279 m_map_flags.pixel(ir, j) = MAP_CELL_ENLARGED_OBSTACLE;
280 }
281 if (m_map_flags.pixel(i, ju) == MAP_CELL_FREE) {
282 m_map_flags.pixel(i, ju) = MAP_CELL_ENLARGED_OBSTACLE;
283 }
284 if (m_map_flags.pixel(i, jd) == MAP_CELL_FREE) {
285 m_map_flags.pixel(i, jd) = MAP_CELL_ENLARGED_OBSTACLE;
286 }
287 if (m_map_flags.pixel(il, ju) == MAP_CELL_FREE) {
288 m_map_flags.pixel(il, ju) = MAP_CELL_ENLARGED_OBSTACLE;
289 }
290 if (m_map_flags.pixel(il, jd) == MAP_CELL_FREE) {
291 m_map_flags.pixel(il, jd) = MAP_CELL_ENLARGED_OBSTACLE;
292 }
293 if (m_map_flags.pixel(ir, ju) == MAP_CELL_FREE) {
294 m_map_flags.pixel(ir, ju) = MAP_CELL_ENLARGED_OBSTACLE;
295 }
296 if (m_map_flags.pixel(ir, jd) == MAP_CELL_FREE) {
297 m_map_flags.pixel(ir, jd) = MAP_CELL_ENLARGED_OBSTACLE;
298 }
299}
300
301bool MapGrid2D::loadROSParams(std::string ros_yaml_filename, std::string& pgm_occ_filename, double& resolution, double& orig_x, double& orig_y, double& orig_t )
302{
303 std::string file_string;
304 std::ifstream file;
305 file.open(ros_yaml_filename.c_str());
306 if (!file.is_open())
307 {
308 yError() << "failed to open file" << ros_yaml_filename;
309 return false;
310 }
311
312 std::string line;
313 while (getline(file, line))
314 {
315 if (line.find("origin") != std::string::npos)
316 {
317 std::replace(line.begin(), line.end(), ',', ' ');
318 std::replace(line.begin(), line.end(), '[', '(');
319 std::replace(line.begin(), line.end(), ']', ')');
320 /*
321 auto it = line.find('[');
322 if (it != std::string::npos) line.replace(it, 1, "(");
323 it = line.find(']');
324 if(it != std::string::npos) line.replace(it, 1, ")");*/
325 }
326 file_string += (line + '\n');
327 }
328 file.close();
329
330 bool ret = true;
331 Bottle bbb;
332 bbb.fromString(file_string);
333 std::string debug_s = bbb.toString();
334
335 if (bbb.check("image:") == false) { yError() << "missing image"; ret = false; }
336 pgm_occ_filename = bbb.find("image:").asString();
337 //ppm_flg_filename = (pgm_occ_filename.substr(0, pgm_occ_filename.size()-4))+"_yarpflags"+".ppm";
338
339 if (bbb.check("resolution:") == false) { yError() << "missing resolution"; ret = false; }
340 resolution = bbb.find("resolution:").asFloat64();
341
342 if (bbb.check("origin:") == false) { yError() << "missing origin"; ret = false; }
343 Bottle* b = bbb.find("origin:").asList();
344 if (b)
345 {
346 orig_x = b->get(0).asFloat64();
347 orig_y = b->get(1).asFloat64();
348 orig_t = b->get(2).asFloat64() * RAD2DEG;
349 }
350
351 if (bbb.check("occupied_thresh:"))
352 {m_occupied_thresh = bbb.find("occupied_thresh:").asFloat64();}
353
354 if (bbb.check("free_thresh:"))
355 {m_free_thresh = bbb.find("free_thresh:").asFloat64();}
356
357 return ret;
358}
359
360bool MapGrid2D::loadMapYarpAndRos(std::string yarp_filename, std::string ros_yaml_filename)
361{
365 if (b1 == false)
366 {
367 yError() << "Unable to load map data" << yarp_filename;
368 return false;
369 }
370 std::string pgm_occ_filename;
371 double resolution=0;
372 double orig_x = 0;
373 double orig_y = 0;
374 double orig_t = 0;
375 bool b2 = loadROSParams(ros_yaml_filename, pgm_occ_filename, resolution, orig_x, orig_y, orig_t);
376 if (b2 == false)
377 {
378 yError() << "Unable to ros params from" << ros_yaml_filename;
379 return false;
380 }
381 std::string path = extractPathFromFile(ros_yaml_filename);
383 std::string pgm_occ_filename_with_path = path + pgm_occ_filename;
385 if (b3 == false)
386 {
387 yError() << "Unable to load occupancy grid file:" << pgm_occ_filename_with_path;
388 return false;
389 }
390
391 if (yarp_img.width() == ros_img.width() && yarp_img.height() == ros_img.height())
392 {
393 //Everything ok, proceed to internal assignments
394 setSize_in_cells(yarp_img.width(), yarp_img.height());
395 m_resolution = resolution;
397
398 //set YARPS stuff
399 for (size_t y = 0; y < m_height; y++)
400 {
401 for (size_t x = 0; x < m_width; x++)
402 {
403 m_map_flags.safePixel(x, y) = PixelToCellFlagData(yarp_img.safePixel(x, y));
404 }
405 }
406
407 //set ROS Stuff
408 for (size_t y = 0; y < m_height; y++)
409 {
410 for (size_t x = 0; x < m_width; x++)
411 {
412 m_map_occupancy.safePixel(x, y) = PixelToCellOccupancyData(ros_img.safePixel(x, y));
413 }
414 }
415 }
416 else
417 {
418 yError() << "MapGrid2D::loadFromFile() Size of YARP map and ROS do not match";
419 return false;
420 }
421
422 return true;
423}
424
425bool MapGrid2D::loadMapROSOnly(std::string ros_yaml_filename)
426{
428 std::string pgm_occ_filename;
429 double resolution = 0;
430 double orig_x = 0;
431 double orig_y = 0;
432 double orig_t = 0;
433 bool b2 = loadROSParams(ros_yaml_filename, pgm_occ_filename, resolution, orig_x, orig_y, orig_t);
434 if (b2 == false)
435 {
436 yError() << "Unable to ros params from" << ros_yaml_filename;
437 return false;
438 }
439 std::string path = extractPathFromFile(ros_yaml_filename);
441 std::string pgm_occ_filename_with_path = path + pgm_occ_filename;
443 if (b3 == false)
444 {
445 yError() << "Unable to load occupancy grid file:" << pgm_occ_filename;
446 return false;
447 }
448
449 //Everything ok, proceed to internal assignments
450 setSize_in_cells(ros_img.width(), ros_img.height());
451 m_resolution = resolution;
453
454 //set ROS Stuff
455 for (size_t y = 0; y < m_height; y++)
456 {
457 for (size_t x = 0; x < m_width; x++)
458 {
459 m_map_occupancy.safePixel(x, y) = PixelToCellOccupancyData(ros_img.safePixel(x, y));
460 }
461 }
462
463 //generate YARP stuff from ROS Stuff
464 for (size_t y = 0; y < (size_t)(m_map_occupancy.height()); y++)
465 {
466 for (size_t x = 0; x < (size_t)(m_map_occupancy.width()); x++)
467 {
468 //occup_prob is a probability, in the range 0-100 (-1 = 255 = unknown)
469 CellOccupancyData occup_prob = m_map_occupancy.safePixel(x, y);
470 if (occup_prob != (unsigned char)(-1) && occup_prob<50 ) {m_map_flags.safePixel(x, y) = MAP_CELL_FREE;}
471 else if (occup_prob >= 50 && occup_prob<=100) {m_map_flags.safePixel(x, y) = MAP_CELL_WALL;}
472 else if (occup_prob > 100) {m_map_flags.safePixel(x, y) = MAP_CELL_UNKNOWN;}
473 else { yError() << "Unreachable";}
474 }
475 }
476 return true;
477}
478
479bool MapGrid2D::loadMapYarpOnly(std::string yarp_filename)
480{
483 if (b1 == false)
484 {
485 yError() << "Unable to load map" << yarp_filename;
486 return false;
487 }
488 //Everything ok, proceed to internal assignments
489 setSize_in_cells(yarp_img.width(), yarp_img.height());
490 //m_resolution = resolution; //????
491 //m_origin.x = orig_x; //????
492 //m_origin.y = orig_y; //????
493 //m_origin.theta = orig_t; //????
494
495 //set YARPS stuff
496 for (size_t y = 0; y < m_height; y++)
497 {
498 for (size_t x = 0; x < m_width; x++)
499 {
500 m_map_flags.safePixel(x, y) = PixelToCellFlagData(yarp_img.safePixel(x, y));
501 }
502 }
503
504 //generate ROS stuff from YARP Stuff
505 for (size_t y = 0; y < (size_t)(m_map_flags.height()); y++)
506 {
507 for (size_t x = 0; x < (size_t)(m_map_flags.width()); x++)
508 {
509 yarp::sig::PixelMono pix_flg = m_map_flags.safePixel(x, y);
510
511 if (pix_flg == MAP_CELL_FREE) {
512 m_map_occupancy.safePixel(x, y) = 0; //@@@SET HERE
513 } else if (pix_flg == MAP_CELL_KEEP_OUT) {
514 m_map_occupancy.safePixel(x, y) = 0; //@@@SET HERE
515 } else if (pix_flg == MAP_CELL_TEMPORARY_OBSTACLE) {
516 m_map_occupancy.safePixel(x, y) = 0; //@@@SET HERE
517 } else if (pix_flg == MAP_CELL_ENLARGED_OBSTACLE) {
518 m_map_occupancy.safePixel(x, y) = 0; //@@@SET HERE
519 } else if (pix_flg == MAP_CELL_WALL) {
520 m_map_occupancy.safePixel(x, y) = 100; //@@@SET HERE
521 } else if (pix_flg == MAP_CELL_UNKNOWN) {
522 m_map_occupancy.safePixel(x, y) = 255; //@@@SET HERE
523 } else {
524 m_map_occupancy.safePixel(x, y) = 255; //@@@SET HERE
525 }
526 }
527 }
528 m_occupied_thresh = 0.80; //@@@SET HERE
529 m_free_thresh = 0.20;//@@@SET HERE
530 return true;
531}
532
533bool MapGrid2D::parseMapParameters(const Property& mapfile)
534{
535 //Map parameters.
536 //these values can eventually override values previously assigned
537 //(e.g. ROS values found in yaml data)
538 if (mapfile.check("resolution"))
539 {
540 m_resolution = mapfile.find("resolution").asFloat32();
541 }
542 if (mapfile.check("origin"))
543 {
544 Bottle* b = mapfile.find("origin").asList();
545 if (b)
546 {
548 b->get(1).asFloat32(),
549 b->get(2).asFloat32());
550 }
551 }
552
553 return true;
554}
555
557{
560 if (mapfile_prop.fromConfigFile(map_file_with_path) == false)
561 {
562 yError() << "Unable to open .map description file:" << map_file_with_path;
563 return false;
564 }
565
566 if (mapfile_prop.check("MapName") ==false)
567 {
568 yError() << "Unable to find 'MapName' parameter inside:" << map_file_with_path;
569 return false;
570 }
571 m_map_name = mapfile_prop.find("MapName").asString();
572
573 bool YarpMapDataFound = false;
574 std::string ppm_flg_filename;
575 if (mapfile_prop.check("YarpMapData") == false)
576 {
577 yWarning() << "Unable to find 'YarpMapData' parameter inside:" << map_file_with_path;
578 YarpMapDataFound = false;
579 }
580 else
581 {
582 ppm_flg_filename = mapfile_prop.find("YarpMapData").asString();
583 YarpMapDataFound = true;
584 }
585
586 bool RosMapDataFound = false;
587 std::string yaml_filename;
588 if (mapfile_prop.check("RosMapData") == false)
589 {
590 yWarning() << "Unable to find 'RosMapData' parameter inside:" << map_file_with_path;
591 RosMapDataFound = false;
592 }
593 else
594 {
595 yaml_filename = mapfile_prop.find("RosMapData").asString();
596 RosMapDataFound = true;
597 }
598
599 m_width = -1;
600 m_height = -1;
604 {
605 //yarp and ros
606 yDebug() << "Opening files: "<< yarp_flg_filename_with_path << " and " << ros_yaml_filename_with_path;
607 return this->loadMapYarpAndRos(yarp_flg_filename_with_path, ros_yaml_filename_with_path) &&
608 this->parseMapParameters(mapfile_prop);
609 }
611 {
612 //only ros
613 yDebug() << "Opening file:" << ros_yaml_filename_with_path;
614 return this->loadMapROSOnly(ros_yaml_filename_with_path) &&
615 this->parseMapParameters(mapfile_prop);
616 }
618 {
619 //only yarp
620 yDebug() << "Opening file:" << yarp_flg_filename_with_path;
621 return this->loadMapYarpOnly(yarp_flg_filename_with_path) &&
622 this->parseMapParameters(mapfile_prop);
623 }
624 else
625 {
626 yError() << "Critical error: unable to find neither 'RosMapData' nor 'YarpMapData' inside:" << map_file_with_path;
627 return false;
628 }
629 return true;
630}
631
632MapGrid2D::CellFlagData MapGrid2D::PixelToCellFlagData(const yarp::sig::PixelRgb& pixin) const
633{
634 if (pixin.r == 0 && pixin.g == 0 && pixin.b == 0) {
635 return MAP_CELL_WALL;
636 } else if (pixin.r == 205 && pixin.g == 205 && pixin.b == 205) {
637 return MAP_CELL_UNKNOWN;
638 } else if (pixin.r == 254 && pixin.g == 254 && pixin.b == 254) {
639 return MAP_CELL_FREE;
640 } else if (pixin.r == 255 && pixin.g == 0 && pixin.b == 0) {
641 return MAP_CELL_KEEP_OUT;
642 }
643 return MAP_CELL_UNKNOWN;
644}
645
646yarp::sig::PixelRgb MapGrid2D::CellFlagDataToPixel(const MapGrid2D::CellFlagData& cellin) const
647{
648 yarp::sig::PixelRgb pixout_flg;
649 if (cellin == MAP_CELL_WALL) { pixout_flg.r = 0; pixout_flg.g = 0; pixout_flg.b = 0;}
650 else if (cellin == MAP_CELL_UNKNOWN) { pixout_flg.r = 205; pixout_flg.g = 205; pixout_flg.b = 205; }
651 else if (cellin == MAP_CELL_FREE) { pixout_flg.r = 254; pixout_flg.g = 254; pixout_flg.b = 254; }
652 else if (cellin == MAP_CELL_KEEP_OUT) { pixout_flg.r = 255; pixout_flg.g = 0; pixout_flg.b = 0; }
653 else if (cellin == MAP_CELL_ENLARGED_OBSTACLE) { pixout_flg.r = 255; pixout_flg.g = 200; pixout_flg.b = 0; }
654 else if (cellin == MAP_CELL_TEMPORARY_OBSTACLE) { pixout_flg.r = 100; pixout_flg.g = 100; pixout_flg.b = 200; }
655 else
656 {
657 //invalid
658 pixout_flg.r = 200; pixout_flg.g = 0; pixout_flg.b = 200;
659 }
660 return pixout_flg;
661}
662
663yarp::sig::PixelMono MapGrid2D::CellOccupancyDataToPixel(const MapGrid2D::CellOccupancyData& cellin) const
664{
665 //convert from value to image
666
667 //255 (-1) stands for unknown
668 if (cellin == 255)
669 {
670 return 205;
671 }
672 //values in the range 0-100 are converted in the range 0-254
673 else if (cellin != (unsigned char)(-1) && cellin <=100)
674 {
675 return (254 - (cellin * 254 / 100));
676 }
677 else
678 {
679 //invalid values are in the range 100-255.
680 //return invalid value 205
681 return 205;
682 }
683}
684
685MapGrid2D::CellOccupancyData MapGrid2D::PixelToCellOccupancyData(const yarp::sig::PixelMono& pixin) const
686{
687 //convert from image to value
688
689 //205 is a special code, used for unknown
690 if (pixin == 205)
691 {
692 return 255;
693 }
694 //values in the range 0-254 are converted in the range 0-100
695 else if (pixin != (unsigned char)(-1))
696 {
697 auto occ = (unsigned char)((254 - pixin) / 254.0);
698 return occ * 100;
699 }
700 else
701 {
702 //255 is an invalid value
703 return 255;
704 }
705}
706
707bool MapGrid2D::crop (int left, int top, int right, int bottom)
708{
709 if (top < 0)
710 {
711 for (size_t j=0;j<height();j++){
712 for (size_t i=0;i<width();i++){
713 yarp::sig::PixelMono pix = m_map_occupancy.safePixel(i,j);
714 if ( pix != 255)
715 {
716 top = j;
717 goto topFound;
718 }
719 }
720 }
721 }
722 topFound:
723
724 if (bottom < 0)
725 {
726 for (int j=height()-1; j>0; j--){
727 for (int i=width()-1; i>0 ;i--){
728 yarp::sig::PixelMono pix = m_map_occupancy.safePixel(i,j);
729 if ( pix != 255)
730 {
731 bottom = j+1;
732 goto bottomFound;
733 }
734 }
735 }
736 }
738
739 if (left<0)
740 {
741 for (size_t i=0;i<width();i++){
742 for (size_t j=0;j<height();j++){
743 yarp::sig::PixelMono pix = m_map_occupancy.safePixel(i,j);
744 if ( pix != 255)
745 {
746 left = i;
747 goto leftFound;
748 }
749 }
750 }
751 }
752 leftFound:
753
754 if (right<0)
755 {
756 for (size_t i=width()-1;i>0;i--){
757 for (size_t j=0;j<height();j++){
758 yarp::sig::PixelMono pix = m_map_occupancy.safePixel(i,j);
759 if ( pix != 255)
760 {
761 right = i;
762 goto rightFound;
763 }
764 }
765 }
766 }
768
769 if (left > (int)this->width()) {
770 return false;
771 }
772 if (right > (int)this->width()) {
773 return false;
774 }
775 if (top > (int)this->height()) {
776 return false;
777 }
778 if (bottom > (int)this->height()) {
779 return false;
780 }
781
784
785 new_map_occupancy.setQuantum(1);
786 new_map_flags.setQuantum(1);
787 new_map_occupancy.resize(right-left,bottom-top);
788 new_map_flags.resize(right-left,bottom-top);
789
790// size_t original_width = m_map_occupancy.width();
791 size_t original_height = m_map_occupancy.height();
792
793 for (int j = top, y = 0; j < bottom; j++, y++) {
794 for (int i=left, x=0; i<right; i++, x++)
795 {
796 new_map_occupancy.safePixel(x,y) = m_map_occupancy.safePixel(i,j);
797 new_map_flags.safePixel(x,y) = m_map_flags.safePixel(i,j);
798 }
799 }
800 m_map_occupancy.copy(new_map_occupancy);
801 m_map_flags.copy(new_map_flags);
802 this->m_width=m_map_occupancy.width();
803 this->m_height=m_map_occupancy.height();
804 yDebug() << m_origin.get_x() << m_origin.get_y();
805 double new_x0 = m_origin.get_x() +(left*m_resolution);
808 return true;
809}
810
812{
814
815 std::string yarp_filename = this->getMapName() + "_yarpflags.ppm";
816 std::string yaml_filename = this->getMapName() + "_grid.yaml";
817 std::string pgm_occ_filename = this->getMapName() + "_grid.pgm";
818
819 std::ofstream map_file;
821 if (!map_file.is_open())
822 {
823 return false;
824 }
825 map_file << "MapName: "<< this->getMapName() << '\n';
826 map_file << "YarpMapData: "<< yarp_filename << '\n';
827 map_file << "RosMapData: "<< yaml_filename << '\n';
828 map_file.close();
829
830 std::ofstream yaml_file;
832 if (!yaml_file.is_open())
833 {
834 return false;
835 }
836 yaml_file << "image: " << pgm_occ_filename << '\n';
837 yaml_file << "resolution: " << m_resolution << '\n';
838 yaml_file << "origin: [ " << m_origin.get_x() << " " << m_origin.get_y() << " " << m_origin.get_theta() << " ]"<< '\n';
839 yaml_file << "negate: 0" << '\n';
840 yaml_file << "occupied_thresh: " << m_occupied_thresh << '\n';
841 yaml_file << "free_thresh: " << m_free_thresh << '\n';
842
844
847
848 img_flg.resize(m_width, m_height);
849 img_occ.resize(m_width, m_height);
850 for (size_t y = 0; y < m_height; y++)
851 {
852 for (size_t x = 0; x < m_width; x++)
853 {
854 yarp::sig::PixelMono pix_flg = m_map_flags.safePixel(x, y);
855 yarp::sig::PixelMono pix_occ = m_map_occupancy.safePixel(x,y);
856 img_flg.safePixel(x, y) = CellFlagDataToPixel(pix_flg);
857 img_occ.safePixel(x, y) = CellOccupancyDataToPixel(pix_occ);
858 }
859 }
860
861 //std::string ppm_flg_filename = (pgm_occ_filename.substr(0, pgm_occ_filename.size() - 4)) + "_yarpflags" + ".ppm";
862 std::string ppm_flg_filename = yarp_filename;
863 bool ret = true;
866 return ret;
867}
868
870{
871 // auto-convert text mode interaction
872 connection.convertTextMode();
873
874 connection.expectInt32();
875 connection.expectInt32();
876
877 connection.expectInt32();
878 m_width = connection.expectInt32();
879 connection.expectInt32();
880 m_height = connection.expectInt32();
881 connection.expectInt32();
882 double x0 = connection.expectFloat64();
883 connection.expectInt32();
884 double y0 = connection.expectFloat64();
885 connection.expectInt32();
886 double theta0 = connection.expectFloat64();
888 connection.expectInt32();
889 m_resolution = connection.expectFloat64();
890 connection.expectInt32();
891 int siz = connection.expectInt32();
892 char buff[255]; memset(buff, 0, 255);
893 connection.expectBlock((char*)buff, siz);
895 connection.expectInt32();
896 m_compressed_data_over_network = connection.expectInt8();
897 m_map_occupancy.resize(m_width, m_height);
898 m_map_flags.resize(m_width, m_height);
899
900 if (m_compressed_data_over_network)
901 {
902#if defined (YARP_HAS_ZLIB)
903 bool ok = true;
904 {
905 connection.expectInt32();
906 size_t sizeCompressed = connection.expectInt32();
907 unsigned char* dataCompressed = new unsigned char[sizeCompressed];
908 ok &= connection.expectBlock((char*)dataCompressed, sizeCompressed);
909 size_t sizeUncompressed = m_map_occupancy.getRawImageSize();
910 unsigned char* dataUncompressed = m_map_occupancy.getRawImage();
913 delete[] dataCompressed;
914 }
915 {
916 connection.expectInt32();
917 size_t sizeCompressed = connection.expectInt32();
918 unsigned char* dataCompressed = new unsigned char[sizeCompressed];
919 ok &= connection.expectBlock((char*)dataCompressed, sizeCompressed);
920 size_t sizeUncompressed = m_map_flags.getRawImageSize();
921 unsigned char* dataUncompressed = m_map_flags.getRawImage();
924 delete[] dataCompressed;
925 }
926#endif
927 }
928 else
929 {
930 bool ok = true;
931 {
932 connection.expectInt32();
933 size_t memsize = connection.expectInt32();
934 if (memsize != m_map_occupancy.getRawImageSize()) { return false; }
935 unsigned char* mem = m_map_occupancy.getRawImage();
936 ok &= connection.expectBlock((char*)mem, memsize);
937 }
938 {
939 connection.expectInt32();
940 size_t memsize = connection.expectInt32();
941 if (memsize != m_map_flags.getRawImageSize()) { return false; }
942 unsigned char* mem = m_map_flags.getRawImage();
943 ok &= connection.expectBlock((char*)mem, memsize);
944 }
945 if (!ok) {
946 return false;
947 }
948 }
949 return !connection.isError();
950}
951
953{
954 connection.appendInt32(BOTTLE_TAG_LIST);
955 connection.appendInt32(10);
956 connection.appendInt32(BOTTLE_TAG_INT32); //1
957 connection.appendInt32(m_width);
958 connection.appendInt32(BOTTLE_TAG_INT32); //2
959 connection.appendInt32(m_height);
960 connection.appendInt32(BOTTLE_TAG_FLOAT64); // 3
961 connection.appendFloat64(m_origin.get_x());
962 connection.appendInt32(BOTTLE_TAG_FLOAT64); // 4
963 connection.appendFloat64(m_origin.get_y());
964 connection.appendInt32(BOTTLE_TAG_FLOAT64); // 5
965 connection.appendFloat64(m_origin.get_theta());
966 connection.appendInt32(BOTTLE_TAG_FLOAT64); // 6
967 connection.appendFloat64(m_resolution);
968 connection.appendInt32(BOTTLE_TAG_STRING); // 7
969 connection.appendString(m_map_name);
970 connection.appendInt32(BOTTLE_TAG_INT8); // 8
971 connection.appendInt8(m_compressed_data_over_network);
972
973 if (m_compressed_data_over_network)
974 {
975#if defined (YARP_HAS_ZLIB)
976 {
977 size_t sizeUncompressed = m_map_occupancy.getRawImageSize();
978 unsigned char* dataUncompressed = m_map_occupancy.getRawImage();
980 unsigned char* dataCompressed = new unsigned char[sizeCompressed];
983 connection.appendInt32(BOTTLE_TAG_BLOB); // 9
984 connection.appendInt32(sizeCompressed);
985 connection.appendBlock((char*)dataCompressed, sizeCompressed);
986 delete [] dataCompressed;
987 }
988 {
989 size_t sizeUncompressed = m_map_flags.getRawImageSize();
990 unsigned char* dataUncompressed = m_map_flags.getRawImage();
992 unsigned char* dataCompressed = new unsigned char[sizeCompressed];
995 connection.appendInt32(BOTTLE_TAG_BLOB); // 10
996 connection.appendInt32(sizeCompressed);
997 connection.appendBlock((char*)dataCompressed, sizeCompressed);
998 delete[] dataCompressed;
999 }
1000#endif
1001 }
1002 else
1003 {
1004 {
1005 unsigned char* mem = m_map_occupancy.getRawImage();
1006 int memsize = m_map_occupancy.getRawImageSize();
1007 connection.appendInt32(BOTTLE_TAG_BLOB);
1008 connection.appendInt32(memsize);
1009 connection.appendExternalBlock((char*)mem, memsize);
1010 }
1011 {
1012 unsigned char* mem = m_map_flags.getRawImage();
1013 int memsize = m_map_flags.getRawImageSize();
1014 connection.appendInt32(BOTTLE_TAG_BLOB);
1015 connection.appendInt32(memsize);
1016 connection.appendExternalBlock((char*)mem, memsize);
1017 }
1018 }
1019
1020 connection.convertTextMode();
1021 return !connection.isError();
1022}
1023
1024bool MapGrid2D::setOrigin(double x, double y, double theta)
1025{
1026 //the given x and y are referred to the bottom left corner, pointing outwards.
1027 //To check if it is inside the map, I have to convert it to a cell with x and y referred to the upper left corner, pointing inwards
1028 if (m_resolution<=0)
1029 {
1030 yWarning() << "MapGrid2D::setOrigin() requested is not inside map!";
1031 return false;
1032 }
1033
1034 int xc = (int)(x/ m_resolution);
1035 int yc = (int)(y / m_resolution);
1036
1037 XYCell orig(-xc, (m_height-1) + yc);
1038 if (isInsideMap(orig))
1039 {
1040 m_origin.setOrigin(x,y, theta);
1041 return true;
1042 }
1043 else
1044 {
1045 yWarning() << "MapGrid2D::setOrigin() requested is not inside map!";
1046 m_origin.setOrigin(x, y, theta);
1047 return true;
1048 }
1049}
1050
1051void MapGrid2D::getOrigin(double& x, double& y, double& theta) const
1052{
1053 x = m_origin.get_x();
1054 y = m_origin.get_y();
1055 theta = m_origin.get_theta();
1056}
1057
1058bool MapGrid2D::setResolution(double resolution)
1059{
1060 if (resolution <= 0)
1061 {
1062 yError() << "MapGrid2D::setResolution() invalid value:" << resolution;
1063 return false;
1064 }
1065 m_resolution = resolution;
1066 return true;
1067}
1068
1069void MapGrid2D::getResolution(double& resolution) const
1070{
1071 resolution = m_resolution;
1072}
1073
1074bool MapGrid2D::setMapName(std::string map_name)
1075{
1076 if (map_name != "")
1077 {
1078 m_map_name = map_name;
1079 return true;
1080 }
1081 yError() << "MapGrid2D::setMapName() invalid map name";
1082 return false;
1083}
1084
1085std::string MapGrid2D::getMapName() const
1086{
1087 return m_map_name;
1088}
1089
1090bool MapGrid2D::setSize_in_meters(double x, double y)
1091{
1092 if (x <= 0 && y <= 0)
1093 {
1094 yError() << "MapGrid2D::setSize() invalid size";
1095 return false;
1096 }
1097 if (m_resolution <= 0)
1098 {
1099 yError() << "MapGrid2D::setSize() invalid map resolution.";
1100 return false;
1101 }
1102 auto w = (size_t)(x/m_resolution);
1103 auto h = (size_t)(y/m_resolution);
1104 setSize_in_cells(w,h);
1105 return true;
1106}
1107
1108bool MapGrid2D::setSize_in_cells(size_t x, size_t y)
1109{
1110 if (x == 0 && y == 0)
1111 {
1112 yError() << "MapGrid2D::setSize() invalid size";
1113 return false;
1114 }
1115 m_map_occupancy.resize(x, y);
1116 m_map_flags.resize(x, y);
1117 m_map_occupancy.zero();
1118 m_map_flags.zero();
1119 m_width = x;
1120 m_height = y;
1121 return true;
1122}
1123
1124void MapGrid2D::getSize_in_meters(double& x, double& y) const
1125{
1126 x = m_width* m_resolution;
1128}
1129
1130void MapGrid2D::getSize_in_cells(size_t&x, size_t& y) const
1131{
1132 x = m_width;
1133 y = m_height;
1134}
1135
1137{
1138 if (isInsideMap(cell) == false)
1139 {
1140 yError() << "Invalid cell requested " << cell.x << " " << cell.y;
1141 return false;
1142 }
1143 m_map_flags.safePixel(cell.x, cell.y) = flag;
1144 return true;
1145}
1146
1148{
1149 if (isInsideMap(cell) == false)
1150 {
1151 yError() << "Invalid cell requested " << cell.x << " " << cell.y;
1152 return false;
1153 }
1154 flag = (MapGrid2D::map_flags) m_map_flags.safePixel(cell.x, cell.y);
1155 return true;
1156}
1157
1159{
1160 if (isInsideMap(cell) == false)
1161 {
1162 yError() << "Invalid cell requested " << cell.x << " " << cell.y;
1163 return false;
1164 }
1165 if (occupancy <0)
1166 {
1167 m_map_occupancy.safePixel(cell.x, cell.y) = 255;
1168 }
1169 else
1170 {
1171 m_map_occupancy.safePixel(cell.x, cell.y) = (yarp::sig::PixelMono)(occupancy);
1172 }
1173 return true;
1174}
1175
1177{
1178 if (isInsideMap(cell) == false)
1179 {
1180 yError() << "Invalid cell requested " << cell.x << " " << cell.y;
1181 return false;
1182 }
1183 if (m_map_occupancy.safePixel(cell.x, cell.y)==255)
1184 {
1185 occupancy =-1;
1186 }
1187 else
1188 {
1189 occupancy = m_map_occupancy.safePixel(cell.x, cell.y);
1190 }
1191 return true;
1192}
1193
1195{
1196 if ((size_t) image.width() != m_width ||
1197 (size_t) image.height() != m_height)
1198 {
1199 yError() << "The size of given occupancy grid does not correspond to the current map. Use method setSize() first.";
1200 return false;
1201 }
1202 m_map_occupancy = image;
1203 return true;
1204}
1205
1207{
1208 image = m_map_occupancy;
1209 return true;
1210}
1211
1213{
1214 for (size_t y = 0; y < m_height; y++)
1215 {
1216 for (size_t x = 0; x < m_width; x++)
1217 {
1218 switch (m_map_flags.safePixel(x, y))
1219 {
1222 m_map_flags.safePixel(x, y) = MAP_CELL_FREE;
1223 break;
1224 }
1225 }
1226 }
1227}
1228
1230{
1231#if defined (YARP_HAS_ZLIB)
1232 m_compressed_data_over_network = val;
1233 return true;
1234#else
1235 yWarning() << "Zlib library not found, unable to set compression";
1236 return false;
1237#endif
1238}
#define BOTTLE_TAG_INT8
Definition Bottle.h:19
#define BOTTLE_TAG_FLOAT64
Definition Bottle.h:25
#define BOTTLE_TAG_INT32
Definition Bottle.h:21
#define BOTTLE_TAG_STRING
Definition Bottle.h:26
#define BOTTLE_TAG_BLOB
Definition Bottle.h:27
#define BOTTLE_TAG_LIST
Definition Bottle.h:28
bool ret
#define yError(...)
Definition Log.h:361
#define yDebug(...)
Definition Log.h:275
#define yWarning(...)
Definition Log.h:340
static std::string extractExtensionFromFile(std::string full_filename)
Definition MapGrid2D.cpp:53
static std::string extractPathFromFile(std::string full_filename)
Definition MapGrid2D.cpp:39
#define RAD2DEG
Definition MapGrid2D.cpp:35
contains the definition of a map type
bool isInsideMap(XYCell cell) const
Checks if a cell is inside the map.
MapGrid2DOrigin m_origin
pose of the map frame w.r.t. the bottom left corner of the map image
double m_resolution
meters/pixel
void setOrigin(double x_init, double y_init, double t_init)
void getSize_in_cells(size_t &x, size_t &y) const
Returns the size of the map in cells.
bool getMapFlag(XYCell cell, map_flags &flag) const
Get the flag of a specific cell of the map.
void clearMapTemporaryFlags()
Clear map temporary flags, such as: MAP_CELL_TEMPORARY_OBSTACLE, MAP_CELL_ENLARGED_OBSTACLE etc.
bool isIdenticalTo(const MapGrid2D &otherMap) const
Checks is two maps are identical.
Definition MapGrid2D.cpp:60
bool getMapImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) const
bool write(yarp::os::ConnectionWriter &connection) const override
Write vector to a connection.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
size_t height() const
Retrieves the map height, expressed in cells.
bool setResolution(double resolution)
Sets the resolution of the map, i.e.
bool setOrigin(double x, double y, double theta)
Sets the origin of the map reference frame (according to ROS convention)
bool getOccupancyGrid(yarp::sig::ImageOf< yarp::sig::PixelMono > &image) const
std::string getMapName() const
Retrieves the map name.
bool setSize_in_cells(size_t x, size_t y)
Sets the size of the map in cells.
bool enable_map_compression_over_network(bool val)
void getOrigin(double &x, double &y, double &theta) const
Retrieves the origin of the map reference frame (according to ROS convention)
bool setMapImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image)
bool setMapName(std::string map_name)
Sets the map name.
bool setMapFlag(XYCell cell, map_flags flag)
Set the flag of a specific cell of the map.
bool crop(int left, int top, int right, int bottom)
Modifies the map, cropping pixels at the boundaries.
bool isKeepOut(XYCell cell) const
Checks if a specific cell of the map is marked as keep-out.
bool isFree(XYCell cell) const
Checks if a specific cell of the map is free, i.e.
bool isNotFree(XYCell cell) const
Checks if a specific cell of the map contains is not free.
size_t width() const
Retrieves the map width, expressed in cells.
void getSize_in_meters(double &x, double &y) const
Returns the size of the map in meters, according to the current map resolution.
bool enlargeObstacles(double size)
Performs the obstacle enlargement operation.
bool setOccupancyData(XYCell cell, double occupancy)
Set the occupancy data of a specific cell of the map.
bool loadFromFile(std::string map_filename)
Loads a yarp map file from disk.
bool setSize_in_meters(double x, double y)
Sets the size of the map in meters, according to the current map resolution.
yarp::sig::PixelMono CellOccupancyData
Definition MapGrid2D.h:30
bool setOccupancyGrid(yarp::sig::ImageOf< yarp::sig::PixelMono > &image)
bool saveToFile(std::string map_filename) const
Store a yarp map file to disk.
bool getOccupancyData(XYCell cell, double &occupancy) const
Retrieves the occupancy data of a specific cell of the map.
bool isWall(XYCell cell) const
Checks if a specific cell of the map contains a wall.
void getResolution(double &resolution) const
Retrieves the resolution of the map, i.e.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:246
A mini-server for performing network communication in the background.
void close() override
Stop port activity.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
An interface for reading from a network connection.
An interface for writing to a network connection.
A class for storing options and configuration information.
Definition Property.h:33
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition Value.cpp:222
virtual yarp::conf::float32_t asFloat32() const
Get 32-bit floating point value.
Definition Value.cpp:216
Typed image class.
Definition Image.h:605
T & safePixel(size_t x, size_t y)
Definition Image.h:637
T & pixel(size_t x, size_t y)
Definition Image.h:621
void setQuantum(size_t imgQuantum)
Definition Image.cpp:451
size_t width() const
Gets width of image in pixels.
Definition Image.h:171
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition Image.cpp:479
bool copy(const Image &alt)
Copy operator.
Definition Image.cpp:628
size_t getRawImageSize() const
Access to the internal buffer size information (this is how much memory has been allocated for the im...
Definition Image.cpp:488
void resize(size_t imgWidth, size_t imgHeight)
Reallocate an image to be of a desired size, throwing away its current contents.
Definition Image.cpp:402
void zero()
Set all pixels to 0.
Definition Image.cpp:395
size_t height() const
Gets height of image in pixels.
Definition Image.h:177
For streams capable of holding different kinds of content, check what they actually have.
Definition jointData.cpp:13
An interface to the operating system, including Port based communication.
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
#define YARP_UNUSED(var)
Definition api.h:162