Path.cpp
Go to the documentation of this file.
1 //=============================================================================
2 // Copyright (C) 2021-2024 Wageningen University - All Rights Reserved
3 // Author: Gonzalo Mier
4 // BSD-3 License
5 //=============================================================================
6 
7 #include <numeric>
8 #include <steering_functions/utilities/utilities.hpp>
11 
12 namespace f2c::types {
13 
15  return this->states_[i];
16 }
17 
18 const PathState& Path::getState(size_t i) const {
19  return this->states_[i];
20 }
21 
22 void Path::setState(size_t i, const PathState& ps) {
23  this->states_[i] = ps;
24 }
25 
26 void Path::addState(const PathState& ps) {
27  this->states_.emplace_back(ps);
28 }
29 
30 void Path::addState(const Point& p, double ang, double len,
31  PathDirection dir, PathSectionType type, double vel) {
32  PathState ps;
33  ps.point = p;
34  ps.angle = ang;
35  ps.len = len;
36  ps.dir = dir;
37  ps.type = type;
38  ps.velocity = vel;
39  this->states_.emplace_back(ps);
40 }
41 
42 std::vector<PathState>& Path::getStates() {
43  return this->states_;
44 }
45 
46 const std::vector<PathState>& Path::getStates() const {
47  return this->states_;
48 }
49 
50 void Path::setStates(const std::vector<PathState>& v_ps) {
51  this->states_ = v_ps;
52 }
53 
54 double Path::getTaskTime() const {
55  return std::accumulate(this->begin(), this->end(), 0.0,
56  [] (double d, const PathState& s) {return s.len / s.velocity + d;});
57 }
58 
59 std::vector<PathState>::const_iterator Path::cbegin() const {
60  return this->states_.begin();
61 }
62 
63 std::vector<PathState>::const_iterator Path::cend() const {
64  return this->states_.end();
65 }
66 
67 std::vector<PathState>::const_iterator Path::begin() const {
68  return this->cbegin();
69 }
70 
71 std::vector<PathState>::const_iterator Path::end() const {
72  return this->cend();
73 }
74 
75 std::vector<PathState>::iterator Path::begin() {
76  return this->states_.begin();
77 }
78 
79 std::vector<PathState>::iterator Path::end() {
80  return this->states_.end();
81 }
82 
83 const PathState& Path::operator[](size_t idx) const {
84  return this->states_[idx];
85 }
86 
88  return this->states_[idx];
89 }
90 
91 const PathState& Path::back() const {
92  return this->states_.back();
93 }
94 
96  return this->states_.back();
97 }
98 
100  for (auto&& new_state : path) {
101  this->states_.emplace_back(new_state);
102  }
103  return *this;
104 }
105 
106 size_t Path::size() const {
107  return states_.size();
108 }
109 
110 double Path::getDimMinX() const {
111  return std::min_element(this->begin(), this->end(),
112  [](const PathState& s1, const PathState& s2) {
113  return s1.point.getX() < s2.point.getX();
114  })->point.getX();
115 }
116 
117 double Path::getDimMinY() const {
118  return std::min_element(this->begin(), this->end(),
119  [](const PathState& s1, const PathState& s2) {
120  return s1.point.getY() < s2.point.getY();
121  })->point.getY();
122 }
123 
124 double Path::getDimMaxX() const {
125  return std::max_element(this->begin(), this->end(),
126  [](const PathState& s1, const PathState& s2) {
127  return s1.point.getX() < s2.point.getX();
128  })->point.getX();
129 }
130 
131 double Path::getDimMaxY() const {
132  return std::max_element(this->begin(), this->end(),
133  [](const PathState& s1, const PathState& s2) {
134  return s1.point.getY() < s2.point.getY();
135  })->point.getY();
136 }
137 
138 void Path::moveTo(const Point& p) {
139  for (auto&& s : this->states_) {
140  s.point = s.point + p;
141  }
142 }
143 
144 void Path::rotateFromPoint(const Point& p, double ang) {
145  for (auto&& s : this->states_) {
146  s.point = p.rotateFromPoint(ang, s.point);
147  s.angle = s.point.mod_2pi(s.angle + ang);
148  }
149 }
150 
152  for (auto&& s : this->states_) {
153  s.point.setX(-s.point.getX());
154  s.angle = s.point.mod_2pi(M_PI - s.angle);
155  }
156 }
158  for (auto&& s : this->states_) {
159  s.point.setY(-s.point.getY());
160  s.angle = s.point.mod_2pi(-s.angle);
161  }
162 }
163 
165  for (size_t i = 0; i < this->size(); ++i) {
166  this->setBackwardDir(i);
167  }
168 }
169 
170 void Path::setBackwardDir(int i) {
171  this->states_[i].dir = PathDirection::BACKWARD;
172 }
173 
175  for (size_t i = 0; i < this->size(); ++i) {
176  this->setForwardDir(i);
177  }
178 }
179 
180 void Path::setForwardDir(int i) {
181  this->states_[i].dir = PathDirection::FORWARD;
182 }
183 
185  for (size_t i = 0; i < this->size(); ++i) {
186  this->setSwathType(i);
187  }
188 }
189 
190 void Path::setSwathType(int i) {
191  this->states_[i].type = PathSectionType::SWATH;
192 }
193 
195  for (size_t i = 0; i < this->size(); ++i) {
196  this->setTurnType(i);
197  }
198 }
199 
200 void Path::setTurnType(int i) {
201  this->states_[i].type = PathSectionType::TURN;
202 }
203 
204 
205 double Path::length() const {
206  return std::accumulate(states_.begin(), states_.end(), 0.0,
207  [](double d, const PathState& s) {return d + fabs(s.len);});
208 }
209 
210 void Path::appendSwath(const Swath& swath, double cruise_speed) {
211  for (size_t i = 0; i < swath.numPoints() - 1; ++i) {
212  PathState s;
213  s.point = swath.getPoint(i);
214  auto p_ang = Point(swath.getPoint(i + 1).getX() - swath.getPoint(i).getX(),
215  swath.getPoint(i + 1).getY() - swath.getPoint(i).getY());
216  s.angle = p_ang.getAngleFromPoint();
217  s.len = swath.getPoint(i + 1).distance(swath.getPoint(i));
220  s.velocity = cruise_speed;
221  this->addState(s);
222  }
223 }
224 
225 PathState Path::at(double len) const {
226  double total_length = this->length();
227  if (len > total_length) {
228  return this->at(total_length);
229  } else if (len < 0.0) {
230  return this->at(0.0);
231  }
232 
233  PathState state_at;
234  for (size_t i = 0; i < this->size(); ++i) {
235  double len_state = fabs(states_[i].len);
236  if (len_state < len) {
237  len -= len_state;
238  } else {
239  state_at = states_[i];
240  Point p = states_[i].point;
241  double ang = states_[i].angle;
242 
243  len *= static_cast<double>(states_[i].dir);
244  state_at.point = Point(p.getX() + len * cos(ang),
245  p.getY() + len * sin(ang));
246  break;
247  }
248  }
249  return state_at;
250 }
251 
253  return states_[0].point;
254 }
255 
257  return states_.back().atEnd();
258 }
259 
260 template<typename CharT>
261 class DecimalSeparator : public std::numpunct<CharT>{
262  public:
263  explicit DecimalSeparator(CharT Separator) : m_Separator(Separator) {}
264 
265  protected:
266  CharT do_decimal_point() const {
267  return m_Separator;
268  }
269 
270  private:
271  CharT m_Separator;
272 };
273 
274 std::string to_string(double d, const int precision = 6) {
275  std::stringstream ss;
276  ss.precision(precision);
277  ss.imbue(std::locale(std::locale(), new DecimalSeparator<char>('.')));
278  ss << d;
279  return ss.str();
280 }
281 
282 
283 std::string Path::serializePath(size_t digit_precision) const {
284  std::locale::global(std::locale::classic());
285  std::string res = "";
286 
287  for (size_t i = 0; i < size(); ++i) {
288  res += to_string(states_[i].point.getX(), digit_precision) + " ";
289  res += to_string(states_[i].point.getY(), digit_precision) + " ";
290  res += to_string(states_[i].point.getZ(), digit_precision) + " ";
291  res += to_string(states_[i].angle, digit_precision) + " ";
292  res += to_string(states_[i].velocity, digit_precision) + " ";
293  res += to_string(states_[i].len, digit_precision) + " ";
294  res += to_string(static_cast<int>(states_[i].dir)) + " ";
295  res += to_string(static_cast<int>(states_[i].type)) + "\n";
296  }
297  return res;
298 }
299 
305 Path Path::discretizeSwath(double step_size) const {
306  Path new_path;
307  for (auto&& s : this->states_) {
308  if (s.type == PathSectionType::SWATH) {
309  double n_steps = max(1.0, std::round(fabs(s.len / step_size)));
310  Point start2end = s.atEnd() - s.point;
311  for (double j = 0.0; j < n_steps; j += 1.0) {
312  PathState state = s;
313  state.point = s.point + start2end * (j / n_steps);
314  state.len /= n_steps;
315  new_path.addState(state);
316  }
317  } else {
318  new_path.addState(s);
319  }
320  }
321  return new_path;
322 }
323 
324 void Path::saveToFile(const std::string& file, size_t precision) const {
325  std::ofstream out(file);
326  out << serializePath(precision);
327  out.close();
328 }
329 
330 void Path::loadFile(const std::string& file) {
331  std::ifstream in(file);
332  double x, y, z, ang, vel, len, dir, d_type;
333  while (in >> x >> y >> z >> ang >> vel >> len >> dir >> d_type) {
334  PathState s;
335  s.point = Point(x, y, z);
336  s.angle = ang;
337  s.velocity = vel;
338  s.len = len;
339  s.dir = static_cast<f2c::types::PathDirection>(dir);
340  s.type = static_cast<f2c::types::PathSectionType>(d_type);
341  this->states_.emplace_back(s);
342  }
343  in.close();
344 }
345 
346 Path& Path::populate(int number_points) {
347  if (this->size() < 3) { return *this;}
348 
349  std::vector<double> x, y, ang_prov, old_vel, len;
350  std::vector<PathDirection> old_dir;
351  std::vector<PathSectionType> old_type;
352  for (int i = 0; i < this->size(); ++i) {
353  if (this->states_[i].len != 0.0) {
354  x.emplace_back(this->states_[i].point.getX());
355  y.emplace_back(this->states_[i].point.getY());
356  ang_prov.emplace_back(this->states_[i].angle);
357  len.emplace_back(this->states_[i].len);
358  old_vel.emplace_back(this->states_[i].velocity);
359  old_dir.emplace_back(this->states_[i].dir);
360  old_type.emplace_back(this->states_[i].type);
361  }
362  }
363  x.emplace_back(this->states_.back().atEnd().getX());
364  y.emplace_back(this->states_.back().atEnd().getY());
365  ang_prov.emplace_back(this->states_.back().angle);
366  len.emplace_back(0.0);
367  old_vel.emplace_back(this->states_.back().velocity);
368  old_dir.emplace_back(this->states_.back().dir);
369  old_type.emplace_back(this->states_.back().type);
370 
371  auto ang = f2c::types::Point::getAngContinuity(ang_prov);
372  std::vector<double> t(len.size());
373  std::partial_sum(len.begin(), len.end() - 1, t.begin() + 1);
374 
375  CubicSpline s_x(t, x);
376  CubicSpline s_y(t, y);
377  CubicSpline s_ang(t, ang);
378 
379  this->states_.clear();
380 
381  double step = t.back() / static_cast<double>(number_points);
382  PathState state;
383  for (size_t i = 0; i < number_points; ++i) {
384  double d = i * step;
385  state.point = Point(s_x(d), s_y(d));
386  state.angle = Point::mod_2pi(s_ang(d));
387  state.len = step;
388  int it = std::lower_bound(t.begin(), t.end(), d + 1e-10) - t.begin() - 1;
389  state.velocity = old_vel[it];
390  state.dir = old_dir[it];
391  state.type = old_type[it];
392  this->addState(state);
393  }
394  return *this;
395 }
396 
397 Path& Path::reduce(double min_dist_equal) {
398  size_t N = this->size();
399  Path new_path;
400  for (size_t i = 0; i < N;) {
401  double new_len {this->states_[i].len};
402  int j = i + 1;
403  while (j < N &&
404  this->states_[i].type == this->states_[j].type &&
405  this->states_[i].dir == this->states_[j].dir &&
406  this->states_[i].point.distance(
407  this->states_[j].point) < min_dist_equal) {
408  new_len += this->states_[j].len;
409  ++j;
410  }
411  PathState state;
412  state.point = this->states_[i].point;
413  state.angle = this->states_[i].angle;
414  state.velocity = this->states_[i].velocity;
415  state.len = new_len;
416  state.dir = this->states_[i].dir;
417  state.type = this->states_[i].type;
418  new_path.states_.emplace_back(state);
419  i = j;
420  }
421  *this = new_path;
422  return *this;
423 }
424 
426  LineString line;
427  for (auto&& s : this->states_) {
428  line.addPoint(s.point);
429  }
430  line.addPoint(this->atEnd());
431  return line;
432 }
433 
434 Path& Path::discretize(double step_size) {
435  if (this->size() > 1) {
436  int n = static_cast<int>((10.0 / step_size) * this->length());
437  this->populate(n);
438  this->reduce(step_size);
439  }
440  return *this;
441 }
442 
443 } // namespace f2c::types
444 
f2c::types::PathDirection
PathDirection
Definition: PathState.h:21
f2c::types::Path::cend
std::vector< PathState >::const_iterator cend() const
Definition: Path.cpp:63
spline.h
f2c::types::Path::appendSwath
void appendSwath(const Swath &swath, double cruise_speed)
Definition: Path.cpp:210
f2c::types::Path::discretize
Path & discretize(double step_size)
Definition: Path.cpp:434
f2c::types::Swath::numPoints
size_t numPoints() const
Definition: Swath.cpp:139
f2c::types::Path::getStates
std::vector< PathState > & getStates()
Definition: Path.cpp:42
f2c::types
Types used by fields2cover library.
Definition: Cell.h:20
Path.h
2_objective_functions.path
path
Definition: 2_objective_functions.py:88
f2c::types::Path::setTurnType
void setTurnType()
Definition: Path.cpp:194
f2c::types::PathState::point
Point point
Definition: PathState.h:28
f2c::types::Path::getTaskTime
double getTaskTime() const
Definition: Path.cpp:54
f2c::types::Path::rotateFromPoint
void rotateFromPoint(const Point &, double ang)
Definition: Path.cpp:144
f2c::types::PathState::type
PathSectionType type
Definition: PathState.h:32
f2c::types::Path::end
std::vector< PathState >::const_iterator end() const
Definition: Path.cpp:71
f2c::types::Swath
Definition: Swath.h:23
f2c::types::Path::size
size_t size() const
Definition: Path.cpp:106
f2c::types::Path::atStart
Point atStart() const
Definition: Path.cpp:252
f2c::types::Path::at
PathState at(double t) const
Definition: Path.cpp:225
f2c::CubicSpline
Definition: spline.h:44
f2c::types::Path::reduce
Path & reduce(double min_dist_equal=0.1)
Definition: Path.cpp:397
f2c::types::Path::operator+=
Path & operator+=(const Path &path)
Definition: Path.cpp:99
f2c::types::Path::operator[]
const PathState & operator[](size_t idx) const
Definition: Path.cpp:83
f2c::types::PathState::dir
PathDirection dir
Definition: PathState.h:31
f2c::types::PathState
Definition: PathState.h:27
f2c::types::PathSectionType
PathSectionType
Definition: PathState.h:15
f2c::types::Path::begin
std::vector< PathState >::const_iterator begin() const
Definition: Path.cpp:67
f2c::types::Path::getState
PathState & getState(size_t i)
Definition: Path.cpp:14
f2c::types::PathDirection::FORWARD
@ FORWARD
f2c::types::Path::addState
void addState(const PathState &ps)
Definition: Path.cpp:26
f2c::types::Path::populate
Path & populate(int number_points=100)
Definition: Path.cpp:346
f2c::types::Path::setBackwardDir
void setBackwardDir()
Definition: Path.cpp:164
f2c::types::Point::rotateFromPoint
Point rotateFromPoint(double angle, const Point &p_r) const
Definition: Point.cpp:121
f2c::types::Path::getDimMaxX
double getDimMaxX() const
Definition: Path.cpp:124
f2c::types::Path
Definition: Path.h:23
f2c::types::Path::serializePath
std::string serializePath(size_t digit_precision=6) const
Definition: Path.cpp:283
f2c::types::DecimalSeparator::do_decimal_point
CharT do_decimal_point() const
Definition: Path.cpp:266
f2c::types::PathDirection::BACKWARD
@ BACKWARD
f2c::types::DecimalSeparator
Definition: Path.cpp:261
f2c::types::DecimalSeparator::DecimalSeparator
DecimalSeparator(CharT Separator)
Definition: Path.cpp:263
f2c::types::PathSectionType::SWATH
@ SWATH
f2c::types::LineString
Definition: LineString.h:19
f2c::types::Path::setSwathType
void setSwathType()
Definition: Path.cpp:184
8_complete_flow.ps
list ps
Definition: 8_complete_flow.py:43
f2c::types::Swath::getPoint
Point getPoint(int i)
Definition: Swath.cpp:143
f2c::types::Path::getDimMaxY
double getDimMaxY() const
Definition: Path.cpp:131
f2c::types::Path::atEnd
Point atEnd() const
Definition: Path.cpp:256
f2c::types::Geometry::mod_2pi
static double mod_2pi(double val)
Definition: Geometry_impl.hpp:174
f2c::types::LineString::addPoint
void addPoint(double x, double y, double z=0)
Definition: LineString.cpp:107
f2c::types::Geometry< OGRPoint, wkbPoint >::getAngContinuity
static double getAngContinuity(double prev_val, double val)
Definition: Geometry_impl.hpp:179
f2c::types::Path::states_
std::vector< PathState > states_
Definition: Path.h:94
f2c::types::Path::toLineString
LineString toLineString() const
Definition: Path.cpp:425
f2c::types::Path::getDimMinY
double getDimMinY() const
Definition: Path.cpp:117
f2c::types::Point
Definition: Point.h:21
f2c::types::Path::setStates
void setStates(const std::vector< PathState > &v_ps)
Definition: Path.cpp:50
f2c::types::Path::length
double length(void) const
Definition: Path.cpp:205
f2c::types::Path::discretizeSwath
Path discretizeSwath(double step_size) const
Discretize the swath sections of the path and return a new path.
Definition: Path.cpp:305
f2c::types::PathSectionType::TURN
@ TURN
f2c::types::Geometry::distance
double distance(const Geometry< T2, R2 > &p) const
Compute shortest distance between this and another geometry.
Definition: Geometry_impl.hpp:139
f2c::types::Path::back
const PathState & back() const
Definition: Path.cpp:91
f2c::types::Path::setState
void setState(size_t i, const PathState &ps)
Definition: Path.cpp:22
f2c::types::Path::loadFile
void loadFile(const std::string &file)
Definition: Path.cpp:330
f2c::types::Path::moveTo
void moveTo(const Point &)
Definition: Path.cpp:138
f2c::types::PathState::len
double len
Definition: PathState.h:30
f2c::types::PathState::angle
double angle
Definition: PathState.h:29
f2c::types::DecimalSeparator::m_Separator
CharT m_Separator
Definition: Path.cpp:271
f2c::types::Point::getY
double getY() const
Definition: Point.cpp:96
f2c::types::Path::mirrorX
void mirrorX()
Definition: Path.cpp:151
f2c::types::PathState::velocity
double velocity
Definition: PathState.h:33
f2c::types::Path::saveToFile
void saveToFile(const std::string &file, size_t precision=6) const
Definition: Path.cpp:324
f2c::types::Path::mirrorY
void mirrorY()
Definition: Path.cpp:157
f2c::types::Point::getX
double getX() const
Definition: Point.cpp:95
f2c::types::Path::cbegin
std::vector< PathState >::const_iterator cbegin() const
Definition: Path.cpp:59
f2c::types::Path::getDimMinX
double getDimMinX() const
Definition: Path.cpp:110
f2c::types::to_string
std::string to_string(double d, const int precision=6)
Definition: Path.cpp:274
f2c::types::Path::setForwardDir
void setForwardDir()
Definition: Path.cpp:174


fields2cover
Author(s):
autogenerated on Fri Apr 25 2025 02:18:31