Main MRPT website > C++ reference for MRPT 1.5.9
CHolonomicFullEval.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+
9  */
10 
11 #include "nav-precomp.h" // Precomp header
12 
13 #include <cmath>
14 #include <mrpt/math/geometry.h>
16 #include <mrpt/math/utils.h> // make_vector()
18 #include <mrpt/utils/CStream.h>
19 #include <mrpt/utils/round.h>
21 
22 using namespace mrpt;
23 using namespace mrpt::utils;
24 using namespace mrpt::math;
25 using namespace mrpt::nav;
26 using namespace std;
27 
29  mrpt::nav)
31  mrpt::nav)
32 
33 const unsigned int INVALID_K = std::numeric_limits<unsigned int>::max();
34 
35 const unsigned NUM_FACTORS = 7U;
36 
38  const mrpt::utils::CConfigFileBase *INI_FILE)
40  m_last_selected_sector(std::numeric_limits<unsigned int>::max()) {
41  if (INI_FILE != NULL)
42  initialize(*INI_FILE);
43 }
44 
45 void CHolonomicFullEval::saveConfigFile(mrpt::utils::CConfigFileBase &c) const {
46  options.saveToConfigFile(c, getConfigFileSectionName());
47 }
48 
49 void CHolonomicFullEval::initialize(const mrpt::utils::CConfigFileBase &c) {
50  options.loadFromConfigFile(c, getConfigFileSectionName());
51 }
52 
53 struct TGap {
54  int k_from, k_to;
55  double min_eval, max_eval;
57  int k_best_eval; //!< Direction with the best evaluation inside the gap.
58 
59  TGap()
60  : k_from(-1), k_to(-1), min_eval(std::numeric_limits<double>::max()),
61  max_eval(-std::numeric_limits<double>::max()), contains_target_k(false),
62  k_best_eval(-1) {}
63 };
64 
65 void CHolonomicFullEval::evalSingleTarget(unsigned int target_idx,
66  const NavInput &ni, EvalOutput &eo) {
67  ASSERT_(target_idx < ni.targets.size());
68  const auto target = ni.targets[target_idx];
69 
70  using mrpt::utils::square;
71 
72  eo = EvalOutput();
73 
74  const auto ptg = getAssociatedPTG();
75  const size_t nDirs = ni.obstacles.size();
76 
77  const double target_dir = ::atan2(target.y, target.x);
78  const unsigned int target_k =
79  CParameterizedTrajectoryGenerator::alpha2index(target_dir, nDirs);
80  const double target_dist = target.norm();
81 
82  m_dirs_scores.resize(nDirs, options.factorWeights.size() + 2);
83 
84  // TP-Obstacles in 2D:
85  std::vector<mrpt::math::TPoint2D> obstacles_2d(nDirs);
86 
88  sp.aperture = 2.0 * M_PI;
89  sp.nRays = nDirs;
90  sp.rightToLeft = true;
91  const auto &sc_lut = m_sincos_lut.getSinCosForScan(sp);
92 
93  for (unsigned int i = 0; i < nDirs; i++) {
94  obstacles_2d[i].x = ni.obstacles[i] * sc_lut.ccos[i];
95  obstacles_2d[i].y = ni.obstacles[i] * sc_lut.csin[i];
96  }
97 
98  // Sanity checks:
99  ASSERT_EQUAL_(options.factorWeights.size(), NUM_FACTORS);
100  ASSERT_ABOVE_(nDirs, 3);
101 
102  for (unsigned int i = 0; i < nDirs; i++) {
103  double scores[NUM_FACTORS]; // scores for each criterion
104 
105  // Too close to obstacles? (unless target is in between obstacles and
106  // the robot)
107  if (ni.obstacles[i] < options.TOO_CLOSE_OBSTACLE &&
108  !(i == target_k && ni.obstacles[i] > 1.02 * target_dist)) {
109  for (size_t l = 0; l < NUM_FACTORS; l++)
110  m_dirs_scores(i, l) = .0;
111  continue;
112  }
113 
114  const double d = std::min(ni.obstacles[i], 0.95 * target_dist);
115 
116  // The TP-Space representative coordinates for this direction:
117  const double x = d * sc_lut.ccos[i];
118  const double y = d * sc_lut.csin[i];
119 
120  // Factor [0]: collision-free distance
121  // -----------------------------------------------------
122  if (mrpt::utils::abs_diff(i, target_k) <= 1 &&
123  target_dist < 1.0 - options.TOO_CLOSE_OBSTACLE &&
124  ni.obstacles[i] > 1.05 * target_dist) {
125  // Don't count obstacles ahead of the target.
126  scores[0] = std::max(target_dist, ni.obstacles[i]) / (target_dist * 1.05);
127  } else {
128  scores[0] = std::max(0.0, ni.obstacles[i] - options.TOO_CLOSE_OBSTACLE);
129  }
130 
131  // Discount "circular loop aparent free distance" here, but don't count
132  // it for clearance, since those are not real obstacle points.
133  if (ptg != nullptr) {
134  const double max_real_freespace = ptg->getActualUnloopedPathLength(i);
135  const double max_real_freespace_norm =
136  max_real_freespace / ptg->getRefDistance();
137 
138  mrpt::utils::keep_min(scores[0], max_real_freespace_norm);
139  }
140 
141  // Factor [1]: Closest approach to target along straight line
142  // (Euclidean)
143  // -------------------------------------------
145  sg.point1.x = 0;
146  sg.point1.y = 0;
147  sg.point2.x = x;
148  sg.point2.y = y;
149 
150  // Range of attainable values: 0=passes thru target. 2=opposite
151  // direction
152  double min_dist_target_along_path = sg.distance(target);
153 
154  // Idea: if this segment is taking us *away* from target, don't make
155  // the segment to start at (0,0), since all paths "running away"
156  // will then have identical minimum distances to target. Use the
157  // middle of the segment instead:
158  const double endpt_dist_to_target = (target - TPoint2D(x, y)).norm();
159  const double endpt_dist_to_target_norm =
160  std::min(1.0, endpt_dist_to_target);
161 
162  if ((endpt_dist_to_target_norm > target_dist &&
163  endpt_dist_to_target_norm >= 0.95 * target_dist) &&
164  /* the path does not get any closer to trg */
165  min_dist_target_along_path >
166  1.05 * std::min(target_dist, endpt_dist_to_target_norm)) {
167  // path takes us away or way blocked:
168  sg.point1.x = x * 0.5;
169  sg.point1.y = y * 0.5;
170  min_dist_target_along_path = sg.distance(target);
171  }
172 
173  scores[1] = 1.0 / (1.0 + square(min_dist_target_along_path));
174 
175  // Factor [2]: Distance of end collision-free point to target
176  // (Euclidean)
177  // Factor [5]: idem (except: no decimation afterwards)
178  // -----------------------------------------------------
179  scores[2] = std::sqrt(1.01 - endpt_dist_to_target_norm);
180  scores[5] = scores[2];
181  // the 1.01 instead of 1.0 is to be 100% sure we don't get a domain
182  // error in sqrt()
183 
184  // Factor [3]: Stabilizing factor (hysteresis) to avoid quick switch
185  // among very similar paths:
186  // ------------------------------------------------------------------------------------------
187  if (m_last_selected_sector != std::numeric_limits<unsigned int>::max()) {
188  // It's fine here to consider that -PI is far from +PI.
189  const unsigned int hist_dist =
190  mrpt::utils::abs_diff(m_last_selected_sector, i);
191 
192  if (hist_dist >= options.HYSTERESIS_SECTOR_COUNT)
193  scores[3] = square(1.0 - (hist_dist - options.HYSTERESIS_SECTOR_COUNT) /
194  double(nDirs));
195  else
196  scores[3] = 1.0;
197  } else {
198  scores[3] = 1.0;
199  }
200 
201  // Factor [4]: clearance to nearest obstacle along path
202  // Use TP-obstacles instead of real obstacles in Workspace since
203  // it's way faster, despite being an approximation:
204  // -------------------------------------------------------------------
205  {
206  sg.point1.x = 0;
207  sg.point1.y = 0;
208  sg.point2.x = x;
209  sg.point2.y = y;
210 
211  double &closest_obs = scores[4];
212  closest_obs = 1.0;
213 
214  // eval obstacles within a certain region of this "i" direction only
215  const int W = std::max(1, mrpt::utils::round(nDirs * 0.1));
216  const int i_min = std::max(0, static_cast<int>(i) - W);
217  const int i_max =
218  std::min(static_cast<int>(nDirs) - 1, static_cast<int>(i) + W);
219  for (int oi = i_min; oi <= i_max; oi++) {
220  // "no obstacle" (norm_dist=1.0) doesn't count as a real obs:
221  if (ni.obstacles[oi] >= 0.99)
222  continue;
223  mrpt::utils::keep_min(closest_obs, sg.distance(obstacles_2d[oi]));
224  }
225  }
226 
227  // Factor [6]: Direct distance in "sectors":
228  // -------------------------------------------------------------------
229  scores[6] =
230  1.0 / (1.0 + mrpt::utils::square((4.0 / nDirs) *
231  mrpt::utils::abs_diff(i, target_k)));
232 
233  // If target is not directly reachable for this i-th direction, decimate
234  // its scorings:
235  if (target_dist < 1.0 - options.TOO_CLOSE_OBSTACLE &&
236  ni.obstacles[i] < 1.01 * target_dist) {
237  // this direction cannot reach target, so assign a low score:
238  scores[1] *= 0.1;
239  scores[2] *= 0.1;
240  scores[6] *= 0.1;
241  }
242 
243  // Save stats for debugging:
244  for (size_t l = 0; l < NUM_FACTORS; l++)
245  m_dirs_scores(i, l) = scores[l];
246 
247  } // end for each direction "i"
248 
249  // Normalize factors?
250  ASSERT_(options.factorNormalizeOrNot.size() == NUM_FACTORS);
251  for (size_t l = 0; l < NUM_FACTORS; l++) {
252  if (!options.factorNormalizeOrNot[l])
253  continue;
254 
255  const double mmax = m_dirs_scores.col(l).maxCoeff();
256  const double mmin = m_dirs_scores.col(l).minCoeff();
257  const double span = mmax - mmin;
258  if (span <= .0)
259  continue;
260 
261  m_dirs_scores.col(l).array() -= mmin;
262  m_dirs_scores.col(l).array() /= span;
263  }
264 
265  // Phase 1: average of PHASE1_FACTORS and thresholding:
266  // ----------------------------------------------------------------------
267  const unsigned int NUM_PHASES = options.PHASE_FACTORS.size();
268  ASSERT_(NUM_PHASES >= 1);
269 
270  std::vector<double> weights_sum_phase(NUM_PHASES, .0),
271  weights_sum_phase_inv(NUM_PHASES);
272  for (unsigned int i = 0; i < NUM_PHASES; i++) {
273  for (unsigned int l : options.PHASE_FACTORS[i])
274  weights_sum_phase[i] += options.factorWeights.at(l);
275  ASSERT_(weights_sum_phase[i] > .0);
276  weights_sum_phase_inv[i] = 1.0 / weights_sum_phase[i];
277  }
278 
279  eo.phase_scores = std::vector<std::vector<double>>(
280  NUM_PHASES, std::vector<double>(nDirs, .0));
281  auto &phase_scores = eo.phase_scores; // shortcut
282  double last_phase_threshold = -1.0; // don't threshold for the first phase
283 
284  for (unsigned int phase_idx = 0; phase_idx < NUM_PHASES; phase_idx++) {
285  double phase_min = std::numeric_limits<double>::max(), phase_max = .0;
286 
287  for (unsigned int i = 0; i < nDirs; i++) {
288  double this_dir_eval = 0;
289 
290  if (ni.obstacles[i] <
291  options.TOO_CLOSE_OBSTACLE || // Too close to obstacles ?
292  (phase_idx > 0 &&
293  phase_scores[phase_idx - 1][i] <
294  last_phase_threshold) // thresholding of the previous
295  // phase
296  ) {
297  this_dir_eval = .0;
298  } else {
299  // Weighted avrg of factors:
300  for (unsigned int l : options.PHASE_FACTORS[phase_idx])
301  this_dir_eval += options.factorWeights.at(l) *
302  std::log(std::max(1e-6, m_dirs_scores(i, l)));
303 
304  this_dir_eval *= weights_sum_phase_inv[phase_idx];
305  this_dir_eval = std::exp(this_dir_eval);
306  }
307  phase_scores[phase_idx][i] = this_dir_eval;
308 
309  mrpt::utils::keep_max(phase_max, phase_scores[phase_idx][i]);
310  mrpt::utils::keep_min(phase_min, phase_scores[phase_idx][i]);
311 
312  } // for each direction
313 
314  ASSERT_(options.PHASE_THRESHOLDS.size() == NUM_PHASES);
315  ASSERT_(options.PHASE_THRESHOLDS[phase_idx] > .0 &&
316  options.PHASE_THRESHOLDS[phase_idx] < 1.0);
317 
318  last_phase_threshold =
319  options.PHASE_THRESHOLDS[phase_idx] * phase_max +
320  (1.0 - options.PHASE_THRESHOLDS[phase_idx]) * phase_min;
321  } // end for each phase
322 
323  // Give a chance for a derived class to manipulate the final evaluations:
324  auto &dirs_eval = phase_scores.back();
325 
326  postProcessDirectionEvaluations(dirs_eval, ni, target_idx);
327 
328  // Recalculate the threshold just in case the postProcess function above
329  // changed things:
330  {
331  double phase_min = std::numeric_limits<double>::max(), phase_max = .0;
332  for (unsigned int i = 0; i < nDirs; i++) {
333  mrpt::utils::keep_max(phase_max, dirs_eval[i]);
334  mrpt::utils::keep_min(phase_min, dirs_eval[i]);
335  }
336  last_phase_threshold = options.PHASE_THRESHOLDS.back() * phase_max +
337  (1.0 - options.PHASE_THRESHOLDS.back()) * phase_min;
338  }
339 
340  // Thresholding:
341  for (unsigned int i = 0; i < nDirs; i++) {
342  double &val = dirs_eval[i];
343  if (val < last_phase_threshold)
344  val = .0;
345  }
346 }
347 
348 void CHolonomicFullEval::navigate(const NavInput &ni, NavOutput &no) {
349  using mrpt::math::square;
350 
351  ASSERT_(ni.clearance != nullptr);
352  ASSERT_(!ni.targets.empty());
353 
354  // Create a log record for returning data.
355  auto log = CLogFileRecord_FullEval::Create();
356  no.logRecord = log;
357 
358  // Evaluate for each target:
359  const size_t numTrgs = ni.targets.size();
360  std::vector<EvalOutput> evals(numTrgs);
361  for (unsigned int trg_idx = 0; trg_idx < numTrgs; trg_idx++) {
362  evalSingleTarget(trg_idx, ni, evals[trg_idx]);
363  }
364 
365  ASSERT_(!evals.empty());
366  const auto nDirs = evals.front().phase_scores.back().size();
367  ASSERT_EQUAL_(nDirs, ni.obstacles.size());
368 
369  // Now, sum all weights for the last stage for each target into an "overall"
370  // score vector, one score per direction of motion:
371  std::vector<double> overall_scores;
372  overall_scores.assign(nDirs, .0);
373  for (const auto &e : evals) {
374  for (unsigned int i = 0; i < nDirs; i++)
375  overall_scores[i] += e.phase_scores.back()[i];
376  }
377  // Normalize:
378  for (unsigned int i = 0; i < nDirs; i++)
379  overall_scores[i] *= (1.0 / numTrgs);
380 
381  // Search for best direction in the "overall score" vector:
382 
383  // Keep the GAP with the largest maximum value within;
384  // then pick the MIDDLE point as the final selection.
385  std::vector<TGap> gaps;
386  std::size_t best_gap_idx = std::string::npos;
387  {
388  bool inside_gap = false;
389  for (unsigned int i = 0; i < nDirs; i++) {
390  const double val = overall_scores[i];
391  if (val < 0.01) {
392  // This direction didn't pass the cut threshold for the "last
393  // phase":
394  if (inside_gap) {
395  // We just ended a gap:
396  auto &active_gap = *gaps.rbegin();
397  active_gap.k_to = i - 1;
398  inside_gap = false;
399  }
400  } else {
401  // higher or EQUAL to the treshold (equal is important just in case we
402  // have a "flat" diagram...)
403  if (!inside_gap) {
404  // We just started a gap:
405  TGap new_gap;
406  new_gap.k_from = i;
407  gaps.emplace_back(new_gap);
408  inside_gap = true;
409  }
410  }
411 
412  if (inside_gap) {
413  auto &active_gap = *gaps.rbegin();
414  if (val >= active_gap.max_eval) {
415  active_gap.k_best_eval = i;
416  }
417  mrpt::utils::keep_max(active_gap.max_eval, val);
418  mrpt::utils::keep_min(active_gap.min_eval, val);
419 
420  if (best_gap_idx == std::string::npos ||
421  val > gaps[best_gap_idx].max_eval) {
422  best_gap_idx = gaps.size() - 1;
423  }
424  }
425  } // end for i
426 
427  // Handle the case where we end with an open, active gap:
428  if (inside_gap) {
429  auto &active_gap = *gaps.rbegin();
430  active_gap.k_to = nDirs - 1;
431  }
432  }
433 
434  // Not heading to target: go thru the "middle" of the gap to maximize
435  // clearance
436  int best_dir_k = -1;
437  double best_dir_eval = 0;
438 
439  // We may have no gaps if all paths are blocked by obstacles, for example:
440  if (!gaps.empty()) {
441  ASSERT_(best_gap_idx < gaps.size());
442  const TGap &best_gap = gaps[best_gap_idx];
443  best_dir_k = best_gap.k_best_eval;
444  best_dir_eval = overall_scores.at(best_dir_k);
445  }
446 
447  // Prepare NavigationOutput data:
448  if (best_dir_eval == .0) {
449  // No way found!
450  no.desiredDirection = 0;
451  no.desiredSpeed = 0;
452  } else {
453  // A valid movement:
454  const auto ptg = getAssociatedPTG();
455  const double ptg_ref_dist = ptg ? ptg->getRefDistance() : 1.0;
456 
457  no.desiredDirection =
458  CParameterizedTrajectoryGenerator::index2alpha(best_dir_k, nDirs);
459 
460  // Speed control: Reduction factors
461  // ---------------------------------------------
462  const double targetNearnessFactor =
463  m_enableApproachTargetSlowDown
464  ? std::min(1.0, ni.targets.front().norm() /
465  (options.TARGET_SLOW_APPROACHING_DISTANCE /
466  ptg_ref_dist))
467  : 1.0;
468 
469  const double obs_dist = ni.obstacles[best_dir_k];
470  // Was: min with obs_clearance too.
471  const double obs_dist_th =
472  std::max(options.TOO_CLOSE_OBSTACLE,
473  options.OBSTACLE_SLOW_DOWN_DISTANCE * ni.maxObstacleDist);
474  double riskFactor = 1.0;
475  if (obs_dist <= options.TOO_CLOSE_OBSTACLE) {
476  riskFactor = 0.0;
477  } else if (obs_dist < obs_dist_th &&
478  obs_dist_th > options.TOO_CLOSE_OBSTACLE) {
479  riskFactor = (obs_dist - options.TOO_CLOSE_OBSTACLE) /
480  (obs_dist_th - options.TOO_CLOSE_OBSTACLE);
481  }
482  no.desiredSpeed =
483  ni.maxRobotSpeed * std::min(riskFactor, targetNearnessFactor);
484  }
485 
486  m_last_selected_sector = best_dir_k;
487 
488  // LOG --------------------------
489  if (log) {
490  log->selectedTarget = 0; // was: best_trg_idx
491  log->selectedSector = best_dir_k;
492  log->evaluation = best_dir_eval;
493  // Copy the evaluation of first phases for (arbitrarily) the first
494  // target, then overwrite the scores of its last phase with the OVERALL
495  // phase scores:
496  log->dirs_eval = evals.front().phase_scores;
497  log->dirs_eval.back() = overall_scores;
498 
499  if (options.LOG_SCORE_MATRIX) {
500  log->dirs_scores = m_dirs_scores;
501  }
502  }
503 }
504 
505 unsigned int CHolonomicFullEval::direction2sector(const double a,
506  const unsigned int N) {
507  const int idx = round(0.5 * (N * (1 + mrpt::math::wrapToPi(a) / M_PI) - 1));
508  if (idx < 0)
509  return 0;
510  else
511  return static_cast<unsigned int>(idx);
512 }
513 
514 CLogFileRecord_FullEval::CLogFileRecord_FullEval()
515  : selectedSector(0), evaluation(.0), dirs_scores(), selectedTarget(0) {}
516 
518  int *version) const {
519  if (version)
520  *version = 3;
521  else {
523  << evaluation << selectedTarget /*v3*/;
524  }
525 }
526 
527 /*---------------------------------------------------------------
528  readFromStream
529  ---------------------------------------------------------------*/
531  int version) {
532  switch (version) {
533  case 0:
534  case 1:
535  case 2:
536  case 3: {
537  if (version >= 2) {
539  } else {
542  if (version >= 1) {
544  }
545  }
547  if (version >= 3) {
548  in >> selectedTarget;
549  } else {
550  selectedTarget = 0;
551  }
552  } break;
553  default:
555  };
556 }
557 
558 /*---------------------------------------------------------------
559  TOptions
560  ---------------------------------------------------------------*/
562  : // Default values:
563  TOO_CLOSE_OBSTACLE(0.15), TARGET_SLOW_APPROACHING_DISTANCE(0.60),
564  OBSTACLE_SLOW_DOWN_DISTANCE(0.15), HYSTERESIS_SECTOR_COUNT(5),
565  LOG_SCORE_MATRIX(false), clearance_threshold_ratio(0.05),
566  gap_width_ratio_threshold(0.25) {
567  factorWeights = mrpt::math::make_vector<5, double>(0.1, 0.5, 0.5, 0.01, 1);
568  factorNormalizeOrNot = mrpt::math::make_vector<5, int>(0, 0, 0, 0, 1);
569 
570  PHASE_FACTORS.resize(3);
571  PHASE_FACTORS[0] = mrpt::math::make_vector<2, int>(1, 2);
572  PHASE_FACTORS[1] = mrpt::math::make_vector<1, int>(4);
573  PHASE_FACTORS[2] = mrpt::math::make_vector<1, int>(0, 2);
574 
575  PHASE_THRESHOLDS = mrpt::math::make_vector<3, double>(0.5, 0.6, 0.7);
576 }
577 
579  const mrpt::utils::CConfigFileBase &c, const std::string &s) {
580  MRPT_START
581 
582  // Load from config text:
583  MRPT_LOAD_CONFIG_VAR(TOO_CLOSE_OBSTACLE, double, c, s);
584  MRPT_LOAD_CONFIG_VAR(TARGET_SLOW_APPROACHING_DISTANCE, double, c, s);
585  MRPT_LOAD_CONFIG_VAR(OBSTACLE_SLOW_DOWN_DISTANCE, double, c, s);
586  MRPT_LOAD_CONFIG_VAR(HYSTERESIS_SECTOR_COUNT, double, c, s);
587  MRPT_LOAD_CONFIG_VAR(LOG_SCORE_MATRIX, bool, c, s);
588  MRPT_LOAD_CONFIG_VAR(clearance_threshold_ratio, double, c, s);
589  MRPT_LOAD_CONFIG_VAR(gap_width_ratio_threshold, double, c, s);
590 
591  c.read_vector(s, "factorWeights", std::vector<double>(), factorWeights, true);
592  ASSERT_EQUAL_(factorWeights.size(), NUM_FACTORS);
593 
594  c.read_vector(s, "factorNormalizeOrNot", factorNormalizeOrNot,
595  factorNormalizeOrNot);
596  ASSERT_EQUAL_(factorNormalizeOrNot.size(), factorWeights.size());
597 
598  // Phases:
599  int PHASE_COUNT = 0;
600  MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(PHASE_COUNT, int, c, s);
601 
602  PHASE_FACTORS.resize(PHASE_COUNT);
603  PHASE_THRESHOLDS.resize(PHASE_COUNT);
604  for (int i = 0; i < PHASE_COUNT; i++) {
605  c.read_vector(s, mrpt::format("PHASE%i_FACTORS", i + 1), PHASE_FACTORS[i],
606  PHASE_FACTORS[i], true);
607  ASSERT_(!PHASE_FACTORS[i].empty());
608 
609  PHASE_THRESHOLDS[i] =
610  c.read_double(s, mrpt::format("PHASE%i_THRESHOLD", i + 1), .0, true);
611  ASSERT_(PHASE_THRESHOLDS[i] >= .0 && PHASE_THRESHOLDS[i] <= 1.0);
612  }
613 
614  MRPT_END
615 }
616 
618  mrpt::utils::CConfigFileBase &c, const std::string &s) const {
619  MRPT_START;
620 
623 
625  TOO_CLOSE_OBSTACLE,
626  "Directions with collision-free distances below this threshold are not "
627  "elegible.");
629  TARGET_SLOW_APPROACHING_DISTANCE,
630  "Start to reduce speed when closer than this to target.");
632  OBSTACLE_SLOW_DOWN_DISTANCE,
633  "Start to reduce speed when clearance is below this value ([0,1] ratio "
634  "wrt obstacle reference/max distance)");
636  HYSTERESIS_SECTOR_COUNT,
637  "Range of `sectors` (directions) for hysteresis over successive "
638  "timesteps");
639  MRPT_SAVE_CONFIG_VAR_COMMENT(LOG_SCORE_MATRIX,
640  "Save the entire score matrix in log files");
642  clearance_threshold_ratio,
643  "Ratio [0,1], times path_count, gives the minimum number of paths at "
644  "each side of a target direction to be accepted as desired direction");
646  gap_width_ratio_threshold,
647  "Ratio [0,1], times path_count, gives the minimum gap width to accept "
648  "a direct motion towards target.");
649 
650  ASSERT_EQUAL_(factorWeights.size(), NUM_FACTORS);
651  c.write(s, "factorWeights",
652  mrpt::system::sprintf_container("%.2f ", factorWeights), WN, WV,
653  "[0]=Free space, [1]=Dist. in sectors, [2]=Closer to target "
654  "(Euclidean), [3]=Hysteresis, [4]=clearance along path, [5]=Like [2] "
655  "without decimation if path obstructed");
656  c.write(s, "factorNormalizeOrNot",
657  mrpt::system::sprintf_container("%u ", factorNormalizeOrNot), WN, WV,
658  "Normalize factors or not (1/0)");
659 
660  c.write(s, "PHASE_COUNT", PHASE_FACTORS.size(), WN, WV,
661  "Number of evaluation phases to run (params for each phase below)");
662 
663  for (unsigned int i = 0; i < PHASE_FACTORS.size(); i++) {
664  c.write(s, mrpt::format("PHASE%u_THRESHOLD", i + 1), PHASE_THRESHOLDS[i],
665  WN, WV,
666  "Phase scores must be above this relative range threshold [0,1] to "
667  "be considered in next phase (Default:`0.75`)");
668  c.write(s, mrpt::format("PHASE%u_FACTORS", i + 1),
669  mrpt::system::sprintf_container("%d ", PHASE_FACTORS[i]), WN, WV,
670  "Indices of the factors above to be considered in this phase");
671  }
672 
673  MRPT_END;
674 }
675 
677  int *version) const {
678  if (version)
679  *version = 4;
680  else {
681  // Params:
683  << options.PHASE_FACTORS << // v3
685  << options.PHASE_THRESHOLDS // v3
690  ;
691  // State:
692  out << m_last_selected_sector;
693  }
694 }
696  switch (version) {
697  case 0:
698  case 1:
699  case 2:
700  case 3:
701  case 4: {
702  // Params:
704 
705  if (version >= 3) {
707  } else {
708  options.PHASE_THRESHOLDS.resize(2);
710  }
713 
714  if (version >= 3) {
716  } else {
717  options.PHASE_THRESHOLDS.resize(1);
719  }
720 
721  if (version >= 1)
723  if (version >= 2)
725 
726  if (version >= 4) {
729  }
730 
731  // State:
733  } break;
734  default:
736  };
737 }
738 
740  std::vector<double> &dir_evals, const NavInput &ni, unsigned int trg_idx) {
741  // Default: do nothing
742 }
#define ASSERT_EQUAL_(__A, __B)
int BASE_IMPEXP MRPT_SAVE_VALUE_PADDING
Default padding sizes for macros MRPT_SAVE_CONFIG_VAR_COMMENT(), etc.
double gap_width_ratio_threshold
Ratio [0,1], times path_count, gives the minimum gap width to accept a direct motion towards target...
virtual void postProcessDirectionEvaluations(std::vector< double > &dir_evals, const NavInput &ni, unsigned int trg_idx)
double min_eval
int k_best_eval
Direction with the best evaluation inside the gap.
EIGEN_STRONG_INLINE bool empty() const
double y
X,Y coordinates.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
A class for storing extra information about the execution of CHolonomicFullEval navigation.
#define min(a, b)
double TOO_CLOSE_OBSTACLE
Directions with collision-free distances below this threshold are not elegible.
#define ASSERT_ABOVE_(__A, __B)
std::vector< double > obstacles
Distance to obstacles in polar coordinates, relative to the robot.
#define MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(variableName, variableType, configFileObject, sectionNameStr)
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
double distance(const TPoint2D &point) const
Distance to point.
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
This file implements several operations that operate element-wise on individual or pairs of container...
A base class for holonomic reactive navigation methods.
double TARGET_SLOW_APPROACHING_DISTANCE
Start to reduce speed when closer than this to target [m].
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
STL namespace.
#define M_PI
Definition: bits.h:78
void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &section) const MRPT_OVERRIDE
This method saves the options to a ".ini"-like file or memory-stored string list. ...
mrpt::nav const unsigned int INVALID_K
int32_t selectedTarget
Normally = 0. Can be >0 if multiple targets passed simultaneously.
std::vector< int32_t > factorNormalizeOrNot
0/1 to normalize factors.
IMPLEMENTS_SERIALIZABLE(CLogFileRecord_FullEval, CHolonomicLogFileRecord, mrpt::nav) IMPLEMENTS_SERIALIZABLE(CHolonomicFullEval
GLdouble s
Definition: glext.h:3602
double clearance_threshold_ratio
Ratio [0,1], times path_count, gives the minimum number of paths at each side of a target direction t...
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
std::vector< double > PHASE_THRESHOLDS
Phase 1,2,N-1... scores must be above this relative range threshold [0,1] to be considered in phase 2...
std::vector< mrpt::math::TPoint2D > targets
Relative location (x,y) of target point(s). In the same units than obstacles. If many, last targets have higher priority.
bool contains_target_k
This class allows loading and storing values and vectors of different types from a configuration text...
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:52
TOptions options
Parameters of the algorithm (can be set manually or loaded from CHolonomicFullEval::initialize or opt...
double OBSTACLE_SLOW_DOWN_DISTANCE
Start to reduce speed when clearance is below this value ([0,1] ratio wrt obstacle reference/max dist...
int mmin(const int t1, const int t2)
Definition: xmlParser.cpp:33
const unsigned NUM_FACTORS
double maxRobotSpeed
Maximum robot speed, in the same units than obstacles, per second.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:38
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
2D segment, consisting of two points.
#define MRPT_SAVE_CONFIG_VAR_COMMENT(variableName, __comment)
#define MRPT_END
Auxiliary struct that holds all the relevant geometry information about a 2D scan.
const GLubyte * c
Definition: glext.h:5590
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
A base class for log records for different holonomic navigation methods.
double desiredDirection
The desired motion direction, in the range [-PI, PI].
std::vector< double > factorWeights
See docs above.
int val
Definition: mrpt_jpeglib.h:953
int version
Definition: mrpt_jpeglib.h:898
TPoint2D point2
Destiny point.
double maxObstacleDist
Maximum expected value to be found in obstacles. Typically, values in obstacles larger or equal to th...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
GLsizei const GLchar ** string
Definition: glext.h:3919
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:51
Full evaluation of all possible directions within the discrete set of input directions.
std::vector< std::vector< double > > dirs_eval
Final [N-1] and earlier stages [0...N-1] evaluation scores for each direction, in the same order of T...
TPoint2D point1
Origin point.
double desiredSpeed
The desired motion speed in that direction, from 0 up to NavInput::maxRobotSpeed. ...
#define MRPT_START
const mrpt::nav::ClearanceDiagram * clearance
The computed clearance for each direction (optional in some implementations). Leave to default (NULL)...
#define MRPT_LOAD_CONFIG_VAR(variableName, variableType, configFileObject, sectionNameStr)
An useful macro for loading variables stored in a INI-like file under a key with the same name that t...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
T square(const T x)
Inline function for the square of a number.
GLuint in
Definition: glext.h:6301
#define ASSERT_(f)
double HYSTERESIS_SECTOR_COUNT
Range of "sectors" (directions) for hysteresis over successive timesteps.
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:26
GLenum GLint GLint y
Definition: glext.h:3516
Input parameters for CAbstractHolonomicReactiveMethod::navigate()
GLenum GLint x
Definition: glext.h:3516
T abs_diff(const T a, const T b)
Efficient and portable evaluation of the absolute difference of two unsigned integer values (but will...
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
bool rightToLeft
Angles storage order: true=counterclockwise; false=clockwise.
Lightweight 2D point.
GLenum GLenum GLvoid GLvoid GLvoid * span
Definition: glext.h:3533
GLubyte GLubyte GLubyte a
Definition: glext.h:5575
Output for CAbstractHolonomicReactiveMethod::navigate()
mrpt::math::CMatrixD dirs_scores
Individual scores for each direction: (i,j), i (row) are directions, j (cols) are scores...
std::string sprintf_container(const char *fmt, const T &V)
Generates a string for a container in the format [A,B,C,...], and the fmt string for each vector elem...
Definition: string_utils.h:109
std::vector< std::vector< double > > phase_scores
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
std::vector< std::vector< int32_t > > PHASE_FACTORS
Factor indices [0,4] for the factors to consider in each phase 1,2,...N of the movement decision (Def...
int BASE_IMPEXP MRPT_SAVE_NAME_PADDING
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) MRPT_OVERRIDE
This method load the options from a ".ini"-like file or memory-stored string list.
CONTAINER::Scalar norm(const CONTAINER &v)
CHolonomicLogFileRecordPtr logRecord
The navigation method will create a log record and store it here via a smart pointer.



Page generated by Doxygen 1.8.14 for MRPT 1.5.9 Git: 690a4699f Wed Apr 15 19:29:53 2020 +0200 at miƩ abr 15 19:30:12 CEST 2020