YARP
Yet Another Robot Platform
Map2DArea.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 #include <yarp/dev/api.h>
7 #include <yarp/dev/Map2DArea.h>
8 #include <yarp/os/Bottle.h>
11 #include <sstream>
12 #include <string>
13 #include <vector>
14 #include <cassert>
15 #include <yarp/os/LogStream.h>
16 #include <random>
17 #include <algorithm>
18 
19 using namespace yarp::dev;
20 using namespace yarp::dev::Nav2D;
21 using namespace yarp::sig;
22 using namespace yarp::os;
23 using namespace yarp::math;
24 
25 int pnpoly(std::vector<yarp::math::Vec2D<double>> points, double testx, double testy)
26 {
27  size_t i, j;
28  int c = 0;
29  for (i = 0, j = points.size() - 1; i < points.size(); j = i++)
30  {
31  if (((points[i].y>testy) != (points[j].y>testy)) &&
32  (testx < (points[j].x - points[i].x) * (testy - points[i].y) / (points[j].y - points[i].y) + points[i].x))
33  {
34  c = !c;
35  }
36  }
37  return c;
38 }
39 
40 Map2DArea::Map2DArea(const std::string& map_name, const std::vector<yarp::math::Vec2D<double>> area_points)
41 {
42  map_id = map_name;
43  points = area_points;
44 }
45 
46 Map2DArea::Map2DArea(const std::string& map_name, const std::vector<Map2DLocation> area_points)
47 {
48  map_id = map_name;
49  for (auto it = area_points.begin(); it != area_points.end(); it++)
50  {
51 #if 0
52  yAssert(it->map_id == map_name);
53 #else
54  if (it->map_id != map_name)
55  {
56  map_id = "";
57  points.clear();
58  yError() << "all area_points must belong to the same map:" << map_name;
59  return;
60  }
61 #endif
62  points.push_back(yarp::math::Vec2D<double>(it->x, it->y));
63  }
64 }
65 
67 {
68  map_id = "";
69 }
70 
72 {
73  // auto-convert text mode interaction
74  connection.convertTextMode();
75 
76  //[[maybe_unused]] int32_t dummy; //@@@FIXME To be used as soon as C++17 becomes available
77  int32_t dummy;
78 
79  dummy = connection.expectInt32();
80  assert(dummy == BOTTLE_TAG_LIST);
81  dummy = connection.expectInt32();
82 
83  dummy = connection.expectInt32();
84  assert(dummy == BOTTLE_TAG_STRING);
85  int string_size = connection.expectInt32();
86  this->map_id.resize(string_size);
87  connection.expectBlock(const_cast<char*>(this->map_id.data()), string_size);
88 
89  dummy = connection.expectInt32();
90  assert(dummy == BOTTLE_TAG_INT32);
91  size_t siz = connection.expectInt32();
92 
93  this->points.clear();
94  for (size_t i = 0; i < siz; i++)
95  {
96  dummy = connection.expectInt32();
97  assert(dummy == BOTTLE_TAG_FLOAT64);
98  double x = connection.expectFloat64();
99  dummy = connection.expectInt32();
100  assert(dummy == BOTTLE_TAG_FLOAT64);
101  double y = connection.expectFloat64();
102  this->points.push_back(yarp::math::Vec2D<double>(x, y));
103  }
104 
105  return !connection.isError();
106 }
107 
109 {
110  size_t siz = this->points.size();
111 
112  connection.appendInt32(BOTTLE_TAG_LIST);
113  connection.appendInt32(2+siz*2);
114 
115  connection.appendInt32(BOTTLE_TAG_STRING);
116  connection.appendString(map_id);
117 
118  connection.appendInt32(BOTTLE_TAG_INT32);
119  connection.appendInt32(siz);
120 
121  for (size_t i = 0; i < siz; i++)
122  {
123  connection.appendInt32(BOTTLE_TAG_FLOAT64);
124  connection.appendFloat64(this->points[i].x);
125  connection.appendInt32(BOTTLE_TAG_FLOAT64);
126  connection.appendFloat64(this->points[i].y);
127  }
128 
129  connection.convertTextMode();
130  return !connection.isError();
131 }
132 
133 std::string Map2DArea::toString() const
134 {
135  std::ostringstream stringStream;
136  stringStream.precision(-1);
137  stringStream.width(-1);
138  stringStream << std::string("map_id:") << map_id << " ";
139  for (size_t i = 0; i<points.size(); i++)
140  {
141  stringStream << " point " << i << "(" << points[i].x << "," << points[i].y << ")";
142  }
143  return stringStream.str();
144 }
145 
147 {
148  if (loc.map_id != this->map_id) {
149  return false;
150  }
151  if (points.size() < 3) {
152  return false;
153  }
154  if (pnpoly(points, loc.x, loc.y) > 0) {
155  return true;
156  }
157  return false;
158 }
159 
160 bool Map2DArea::operator!=(const Map2DArea& r) const
161 {
162  if (
163  map_id != r.map_id ||
164  points != r.points
165  )
166  {
167  return true;
168  }
169  return false;
170 }
171 
172 bool Map2DArea::operator==(const Map2DArea& r) const
173 {
174  if (
175  map_id == r.map_id &&
176  points == r.points
177  )
178  {
179  return true;
180  }
181  return false;
182 }
183 
184 bool Map2DArea::isValid() const
185 {
186  if (points.size() < 3) {
187  return false;
188  }
189  if (map_id == "") {
190  return false;
191  }
192  return true;
193 }
194 
196 {
197  lt.map_id = rb.map_id = this->map_id;
198  lt.x = lt.y = std::numeric_limits<double>::max();
199  rb.x = rb.y = std::numeric_limits<double>::min();
200  if (isValid() == false) {
201  return false;
202  }
203  for (auto it = points.begin(); it != points.end(); it++)
204  {
205  if (it->x > rb.x) { rb.x = it->x; }
206  if (it->y > rb.y) { rb.y = it->y; }
207  if (it->x < lt.x) { lt.x = it->x; }
208  if (it->y < lt.y) { lt.y = it->y; }
209  }
210  return true;
211 }
212 
214 {
215  Map2DLocation lt;
216  Map2DLocation rb;
217  if (findAreaBounds(lt, rb) == false) {
218  return false;
219  }
220 
221  std::random_device rd;
222  std::mt19937 gen(rd());
223  std::uniform_real_distribution<double> dis_x(lt.x, rb.x);
224  std::uniform_real_distribution<double> dis_y(lt.y, rb.y);
225 
226  size_t count_trials = 0;
227  do
228  {
229  double rnd_x = dis_x(gen);
230  double rnd_y = dis_y(gen);
231 
232  loc.map_id = this->map_id;
233  loc.x = rnd_x;
234  loc.y = rnd_y;
235  loc.theta = 0;
236  count_trials++;
237  if (this->checkLocationInsideArea(loc)) {
238  break;
239  }
240  } while (count_trials < 20);
241 
242  if (count_trials >= 20)
243  {
244  yError() << "Problem found in Map2DArea::getRandomLocation()";
245  return false;
246  }
247 
248  return true;
249 }
250 
252 {
253  this->map_id = "";
254  this->points.clear();
255 }
256 
258 {
259  //std::vector::at() function performs bound check, throwing exception.
260  //[] operator, instead, not.
261  return points.at(index);
262 }
#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_LIST
Definition: Bottle.h:28
#define yError(...)
Definition: Log.h:279
#define yAssert(x)
Definition: Log.h:294
int pnpoly(std::vector< yarp::math::Vec2D< double >> points, double testx, double testy)
Definition: Map2DArea.cpp:25
contains the definition of a Map2DArea type
void clear()
Remove all elements from the path.
Definition: Map2DArea.cpp:251
std::string toString() const
Returns text representation of the area.
Definition: Map2DArea.cpp:133
std::vector< yarp::math::Vec2D< double > > points
Definition: Map2DArea.h:111
bool operator==(const Map2DArea &r) const
Compares two Map2DArea.
Definition: Map2DArea.cpp:172
bool operator!=(const Map2DArea &r) const
Compares two Map2DAreas.
Definition: Map2DArea.cpp:160
Map2DArea()
Default constructor: the map name is empty, coordinates are set to zero.
Definition: Map2DArea.cpp:66
bool write(yarp::os::ConnectionWriter &connection) const override
Write a map2DArea to a connection.
Definition: Map2DArea.cpp:108
bool getRandomLocation(yarp::dev::Nav2D::Map2DLocation &loc)
get a random Map2DLocation inside the Map2DArea @loc the computed Map2DLocation
Definition: Map2DArea.cpp:213
bool findAreaBounds(yarp::dev::Nav2D::Map2DLocation &lt, yarp::dev::Nav2D::Map2DLocation &rb)
retrieves two Map2DLocations representing the bounding box of the Map2DArea @lt the left-top vertex @...
Definition: Map2DArea.cpp:195
bool checkLocationInsideArea(yarp::dev::Nav2D::Map2DLocation loc)
Check if a Map2DLocation is inside a Map2DArea.
Definition: Map2DArea.cpp:146
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
Definition: Map2DArea.cpp:71
yarp::math::Vec2D< double > & operator[](size_t index)
Returns a vertex of the area.
Definition: Map2DArea.cpp:257
bool isValid() const
Checks if the Map2DArea is valid return true if the Map2DArea is valid.
Definition: Map2DArea.cpp:184
An interface for reading from a network connection.
virtual bool expectBlock(char *data, size_t len)=0
Read a block of data from the network connection.
virtual std::int32_t expectInt32()=0
Read a 32-bit integer from the network connection.
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
virtual bool isError() const =0
virtual yarp::conf::float64_t expectFloat64()=0
Read a 64-bit floating point number from the network connection.
An interface for writing to a network connection.
virtual bool isError() const =0
virtual bool convertTextMode()=0
Converts a standard description in binary into a textual description, if the connection is in text-mo...
virtual void appendInt32(std::int32_t data)=0
Send a representation of a 32-bit integer to the network connection.
virtual void appendFloat64(yarp::conf::float64_t data)=0
Send a representation of a 64-bit floating point number to the network connection.
virtual void appendString(const char *str, const char terminate='\n') final
Send a character sequence to the network connection.
An interface for the device drivers.
bool isValid()
Check if time is valid (non-zero).
Definition: Time.cpp:314
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:22