Main MRPT website > C++ reference for MRPT 1.9.9
CHolonomicND.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 #include "nav-precomp.h" // Precomp header
11 
13 #include <mrpt/utils/CStream.h>
14 #include <mrpt/utils/round.h>
15 #include <mrpt/math/geometry.h>
17 
18 using namespace mrpt;
19 using namespace mrpt::utils;
20 using namespace mrpt::math;
21 using namespace mrpt::nav;
22 using namespace std;
23 
27 
28 /** Initialize the parameters of the navigator, from some
29 * configuration file, or default values if filename is set to NULL.
30 */
31 CHolonomicND::CHolonomicND(const mrpt::utils::CConfigFileBase* INI_FILE)
33  m_last_selected_sector(std::numeric_limits<unsigned int>::max())
34 {
35  if (INI_FILE != nullptr) initialize(*INI_FILE);
36 }
37 
38 void CHolonomicND::initialize(const mrpt::utils::CConfigFileBase& INI_FILE)
39 {
40  options.loadFromConfigFile(INI_FILE, getConfigFileSectionName());
41 }
42 void CHolonomicND::saveConfigFile(mrpt::utils::CConfigFileBase& c) const
43 {
44  options.saveToConfigFile(c, getConfigFileSectionName());
45 }
46 
47 /*---------------------------------------------------------------
48  Navigate
49  ---------------------------------------------------------------*/
50 void CHolonomicND::navigate(const NavInput& ni, NavOutput& no)
51 {
52  const auto ptg = getAssociatedPTG();
53  const double ptg_ref_dist = ptg ? ptg->getRefDistance() : 1.0;
54 
55  TGapArray gaps;
56  TSituations situation;
57  unsigned int selectedSector;
58  double riskEvaluation;
59  double evaluation;
60 
61  // Create a log record for returning data.
62  CLogFileRecord_ND::Ptr log = mrpt::make_aligned_shared<CLogFileRecord_ND>();
63  no.logRecord = log;
64 
65  // Search gaps:
66  gaps.clear();
67  ASSERT_(!ni.targets.empty());
68  const auto trg = *ni.targets.rbegin();
69 
70  gapsEstimator(ni.obstacles, trg, gaps);
71 
72  // Select best gap:
73  searchBestGap(
74  ni.obstacles, 1.0 /* max obs range*/, gaps, trg, selectedSector,
75  evaluation, situation, riskEvaluation, *log);
76 
77  if (situation == SITUATION_NO_WAY_FOUND)
78  {
79  // No way found!
80  no.desiredDirection = 0;
81  no.desiredSpeed = 0;
82  }
83  else
84  {
85  // A valid movement:
86  no.desiredDirection = CParameterizedTrajectoryGenerator::index2alpha(
87  selectedSector, ni.obstacles.size());
88 
89  // Speed control: Reduction factors
90  // ---------------------------------------------
91  const double targetNearnessFactor =
92  m_enableApproachTargetSlowDown
93  ? std::min(
94  1.0,
95  trg.norm() / (options.TARGET_SLOW_APPROACHING_DISTANCE /
96  ptg_ref_dist))
97  : 1.0;
98 
99  const double riskFactor =
100  std::min(1.0, riskEvaluation / options.RISK_EVALUATION_DISTANCE);
101  no.desiredSpeed =
102  ni.maxRobotSpeed * std::min(riskFactor, targetNearnessFactor);
103  }
104 
105  m_last_selected_sector = selectedSector;
106 
107  // LOG --------------------------
108  if (log)
109  {
110  // gaps:
111  {
112  int i, n = gaps.size();
113  log->gaps_ini.resize(n);
114  log->gaps_end.resize(n);
115  for (i = 0; i < n; i++)
116  {
117  log->gaps_ini[i] = gaps[i].ini;
118  log->gaps_end[i] = gaps[i].end;
119  }
120  }
121  // Selection:
122  log->selectedSector = selectedSector;
123  log->evaluation = evaluation;
124  log->situation = situation;
125  log->riskEvaluation = riskEvaluation;
126  }
127 }
128 
129 /*---------------------------------------------------------------
130  Find gaps in the obtacles (Beta version)
131  ---------------------------------------------------------------*/
132 void CHolonomicND::gapsEstimator(
133  const std::vector<double>& obstacles, const mrpt::math::TPoint2D& target,
134  TGapArray& gaps_out)
135 {
136  const size_t n = obstacles.size();
137  ASSERT_(n > 2);
138 
139  // ================ Parameters ================
140  const int GAPS_MIN_WIDTH = ceil(n * 0.01); // was: 3
141  const double GAPS_MIN_DEPTH_CONSIDERED = 0.6;
142  const double GAPS_MAX_RELATIVE_DEPTH = 0.5;
143  // ============================================
144 
145  // Find the maximum distances to obstacles:
146  // ----------------------------------------------------------
147  float overall_max_dist = std::numeric_limits<float>::min(),
148  overall_min_dist = std::numeric_limits<float>::max();
149  for (size_t i = 1; i < (n - 1); i++)
150  {
151  mrpt::utils::keep_max(overall_max_dist, obstacles[i]);
152  mrpt::utils::keep_min(overall_min_dist, obstacles[i]);
153  }
154  double max_depth = overall_max_dist - overall_min_dist;
155 
156  // Build list of "GAPS":
157  // --------------------------------------------------------
158  TGapArray gaps_temp;
159  gaps_temp.reserve(150);
160 
161  for (double threshold_ratio = 0.95; threshold_ratio >= 0.05;
162  threshold_ratio -= 0.05)
163  {
164  const double dist_threshold =
165  threshold_ratio * overall_max_dist +
166  (1.0f - threshold_ratio) *
167  min(target.norm(), GAPS_MIN_DEPTH_CONSIDERED);
168 
169  bool is_inside = false;
170  size_t sec_ini = 0, sec_end = 0;
171  double maxDist = 0.;
172 
173  for (size_t i = 0; i < n; i++)
174  {
175  if (!is_inside && (obstacles[i] >= dist_threshold)) // A gap begins
176  {
177  sec_ini = i;
178  maxDist = obstacles[i];
179  is_inside = true;
180  }
181  else if (
182  is_inside &&
183  (i == (n - 1) || obstacles[i] < dist_threshold)) // A gap ends
184  {
185  if (obstacles[i] < dist_threshold)
186  sec_end = i - 1;
187  else
188  sec_end = i;
189 
190  is_inside = false;
191 
192  if ((sec_end - sec_ini) >= (size_t)GAPS_MIN_WIDTH)
193  {
194  // Add new gap:
195  gaps_temp.resize(gaps_temp.size() + 1);
196  TGap& newGap = *gaps_temp.rbegin();
197 
198  newGap.ini = sec_ini;
199  newGap.end = sec_end;
200  newGap.minDistance =
201  min(obstacles[sec_ini], obstacles[sec_end]);
202  newGap.maxDistance = maxDist;
203  }
204  }
205 
206  if (is_inside) maxDist = std::max(maxDist, obstacles[i]);
207  }
208  }
209 
210  // Start to filter the gap list
211  //--------------------------------------------------------------
212 
213  const size_t nTempGaps = gaps_temp.size();
214 
215  std::vector<bool> delete_gaps;
216  delete_gaps.assign(nTempGaps, false);
217 
218  // First, remove redundant gaps
219  for (size_t i = 0; i < nTempGaps; i++)
220  {
221  if (delete_gaps[i] == 1) continue;
222 
223  for (size_t j = i + 1; j < nTempGaps; j++)
224  {
225  if (gaps_temp[i].ini == gaps_temp[j].ini ||
226  gaps_temp[i].end == gaps_temp[j].end)
227  delete_gaps[j] = 1;
228  }
229  }
230 
231  // Remove gaps with a big depth
232  for (size_t i = 0; i < nTempGaps; i++)
233  {
234  if (delete_gaps[i] == 1) continue;
235 
236  if ((gaps_temp[i].maxDistance - gaps_temp[i].minDistance) >
237  max_depth * GAPS_MAX_RELATIVE_DEPTH)
238  delete_gaps[i] = 1;
239  }
240 
241  // Delete gaps which contain more than one other gaps
242  for (size_t i = 0; i < nTempGaps; i++)
243  {
244  if (delete_gaps[i]) continue;
245 
246  unsigned int inner_gap_count = 0;
247 
248  for (unsigned int j = 0; j < nTempGaps; j++)
249  {
250  if (i == j || delete_gaps[j]) continue;
251 
252  // j is inside of i?
253  if (gaps_temp[j].ini >= gaps_temp[i].ini &&
254  gaps_temp[j].end <= gaps_temp[i].end)
255  if (++inner_gap_count > 1)
256  {
257  delete_gaps[i] = 1;
258  break;
259  }
260  }
261  }
262 
263  // Delete gaps included in other gaps
264  for (size_t i = 0; i < nTempGaps; i++)
265  {
266  if (delete_gaps[i]) continue;
267 
268  for (unsigned int j = 0; j < nTempGaps; j++)
269  {
270  if (i == j || delete_gaps[j]) continue;
271  if (gaps_temp[i].ini <= gaps_temp[j].ini &&
272  gaps_temp[i].end >= gaps_temp[j].end)
273  delete_gaps[j] = 1;
274  }
275  }
276 
277  // Copy as result only those gaps not marked for deletion:
278  // --------------------------------------------------------
279  gaps_out.clear();
280  gaps_out.reserve(nTempGaps / 2);
281  for (size_t i = 0; i < nTempGaps; i++)
282  {
283  if (delete_gaps[i]) continue;
284 
285  // Compute the representative direction ("sector") for this gap:
286  calcRepresentativeSectorForGap(gaps_temp[i], target, obstacles);
287 
288  gaps_out.push_back(gaps_temp[i]);
289  }
290 }
291 
292 /*---------------------------------------------------------------
293  Search the best gap.
294  ---------------------------------------------------------------*/
295 void CHolonomicND::searchBestGap(
296  const std::vector<double>& obstacles, const double maxObsRange,
297  const TGapArray& in_gaps, const mrpt::math::TPoint2D& target,
298  unsigned int& out_selDirection, double& out_selEvaluation,
299  TSituations& out_situation, double& out_riskEvaluation,
300  CLogFileRecord_ND& log)
301 {
302  // For evaluating the "risk":
303  unsigned int min_risk_eval_sector = 0;
304  unsigned int max_risk_eval_sector = obstacles.size() - 1;
305  const unsigned int target_sector =
306  direction2sector(atan2(target.y, target.x), obstacles.size());
307  const double target_dist = std::max(0.01, target.norm());
308  // (Risk is evaluated at the end, for all the situations)
309 
310  // D1 : Straight path?
311  // --------------------------------------------------------
312  const int freeSectorsNearTarget = ceil(0.02 * obstacles.size());
313  bool theyAreFree = true, caseD1 = false;
314  if (target_sector > static_cast<unsigned int>(freeSectorsNearTarget) &&
315  target_sector <
316  static_cast<unsigned int>(obstacles.size() - freeSectorsNearTarget))
317  {
318  const double min_free_dist =
319  std::min(1.05 * target_dist, 0.95 * maxObsRange);
320  for (int j = -freeSectorsNearTarget;
321  theyAreFree && j <= freeSectorsNearTarget; j++)
322  if (obstacles[(int(target_sector) + j) % obstacles.size()] <
323  min_free_dist)
324  theyAreFree = false;
325  caseD1 = theyAreFree;
326  }
327 
328  if (caseD1)
329  {
330  // S1: Move straight towards target:
331  out_selDirection = target_sector;
332 
333  // In case of several paths, the shortest:
334  out_selEvaluation =
335  1.0 + std::max(0.0, (maxObsRange - target_dist) / maxObsRange);
336  out_situation = SITUATION_TARGET_DIRECTLY;
337  }
338  else
339  {
340  // Evaluate all gaps (if any):
341  std::vector<double> gaps_evaluation;
342  int selected_gap = -1;
343  double selected_gap_eval = -100;
344 
345  evaluateGaps(
346  obstacles, maxObsRange, in_gaps, target_sector, target_dist,
347  gaps_evaluation);
348 
349  log.gaps_eval = gaps_evaluation;
350 
351  // D2: is there any gap "beyond" the target (and not too far away)?
352  // (Not used)
353  // ----------------------------------------------------------------
354 
355  // unsigned int dist;
356  // for ( unsigned int i=0;i<in_gaps.size();i++ )
357  //{
358  // dist = mrpt::utils::abs_diff(target_sector,
359  // in_gaps[i].representative_sector );
360  // if (dist > 0.5*obstacles.size())
361  // dist = obstacles.size() - dist;
362  //
363  // if ( in_gaps[i].maxDistance >= target_dist && dist <=
364  //(int)floor(options.MAX_SECTOR_DIST_FOR_D2_PERCENT * obstacles.size())
365  //)
366  //
367  // if ( gaps_evaluation[i]>selected_gap_eval )
368  // {
369  // selected_gap_eval = gaps_evaluation[i];
370  // selected_gap = i;
371  // }
372  //}
373 
374  // Keep the best gaps (if none was picked up to this point)
375  if (selected_gap == -1)
376  for (unsigned int i = 0; i < in_gaps.size(); i++)
377  if (gaps_evaluation[i] > selected_gap_eval)
378  {
379  selected_gap_eval = gaps_evaluation[i];
380  selected_gap = i;
381  }
382 
383  // D3: Wasn't a good enough gap (or there were none)?
384  // ----------------------------------------------------------
385  if (selected_gap_eval <= 0)
386  {
387  // S2: No way found
388  // ------------------------------------------------------
389  out_selDirection = 0;
390  out_selEvaluation = 0.0; // Worst case
391  out_situation = SITUATION_NO_WAY_FOUND;
392  }
393  else
394  {
395  // The selected gap:
396  const TGap& gap = in_gaps[selected_gap];
397 
398  const unsigned int sectors_to_be_wide =
399  round(options.WIDE_GAP_SIZE_PERCENT * obstacles.size());
400 
401  out_selDirection = in_gaps[selected_gap].representative_sector;
402  out_selEvaluation = selected_gap_eval;
403 
404  // D4: Is it a WIDE gap?
405  // -----------------------------------------------------
406  if ((gap.end - gap.ini) < sectors_to_be_wide)
407  {
408  // S3: Narrow gap
409  // -------------------------------------------
410  out_situation = SITUATION_SMALL_GAP;
411  }
412  else
413  {
414  // S4: Wide gap
415  // -------------------------------------------
416  out_situation = SITUATION_WIDE_GAP;
417  }
418 
419  // Evaluate the risk only within the gap:
420  min_risk_eval_sector = gap.ini;
421  max_risk_eval_sector = gap.end;
422  }
423  }
424 
425  // Evaluate short-term minimum distance to obstacles, in a small interval
426  // around the selected direction:
427  const unsigned int risk_eval_nsectors =
428  round(options.RISK_EVALUATION_SECTORS_PERCENT * obstacles.size());
429  const unsigned int sec_ini = std::max(
430  min_risk_eval_sector, risk_eval_nsectors < out_selDirection
431  ? out_selDirection - risk_eval_nsectors
432  : 0);
433  const unsigned int sec_fin =
434  std::min(max_risk_eval_sector, out_selDirection + risk_eval_nsectors);
435 
436  out_riskEvaluation = 0.0;
437  for (unsigned int i = sec_ini; i <= sec_fin; i++)
438  out_riskEvaluation += obstacles[i];
439  out_riskEvaluation /= (sec_fin - sec_ini + 1);
440 }
441 
442 /*---------------------------------------------------------------
443  Fills in the representative sector
444  field in the gap structure:
445  ---------------------------------------------------------------*/
446 void CHolonomicND::calcRepresentativeSectorForGap(
447  TGap& gap, const mrpt::math::TPoint2D& target,
448  const std::vector<double>& obstacles)
449 {
450  int sector;
451  const unsigned int sectors_to_be_wide =
452  round(options.WIDE_GAP_SIZE_PERCENT * obstacles.size());
453  const unsigned int target_sector =
454  direction2sector(atan2(target.y, target.x), obstacles.size());
455 
456  if ((gap.end - gap.ini) <
457  sectors_to_be_wide) // Select the intermediate sector
458  {
459 #if 1
460  sector = round(0.5f * gap.ini + 0.5f * gap.end);
461 #else
462  float min_dist_obs_near_ini = 1, min_dist_obs_near_end = 1;
463  int i;
464  for (i = gap.ini; i >= max(0, gap.ini - 2); i--)
465  min_dist_obs_near_ini = min(min_dist_obs_near_ini, obstacles[i]);
466  for (i = gap.end; i <= min((int)obstacles.size() - 1, gap.end + 2); i++)
467  min_dist_obs_near_end = min(min_dist_obs_near_end, obstacles[i]);
468  sector = round(
469  (min_dist_obs_near_ini * gap.ini +
470  min_dist_obs_near_end * gap.end) /
471  (min_dist_obs_near_ini + min_dist_obs_near_end));
472 #endif
473  }
474  else // Select a sector close to the target but spaced
475  // "sectors_to_be_wide/2" from it
476  {
477  unsigned int dist_ini = mrpt::utils::abs_diff(target_sector, gap.ini);
478  unsigned int dist_end = mrpt::utils::abs_diff(target_sector, gap.end);
479 
480  if (dist_ini > 0.5 * obstacles.size())
481  dist_ini = obstacles.size() - dist_ini;
482  if (dist_end > 0.5 * obstacles.size())
483  dist_end = obstacles.size() - dist_end;
484 
485  int dir;
486  if (dist_ini < dist_end)
487  {
488  sector = gap.ini;
489  dir = +1;
490  }
491  else
492  {
493  sector = gap.end;
494  dir = -1;
495  }
496 
497  sector = sector + dir * static_cast<int>(sectors_to_be_wide) / 2;
498  }
499 
500  keep_max(sector, 0);
501  keep_min(sector, static_cast<int>(obstacles.size()) - 1);
502 
503  gap.representative_sector = sector;
504 }
505 
506 /*---------------------------------------------------------------
507  Evaluate each gap
508  ---------------------------------------------------------------*/
509 void CHolonomicND::evaluateGaps(
510  const std::vector<double>& obstacles, const double maxObsRange,
511  const TGapArray& gaps, const unsigned int target_sector,
512  const float target_dist, std::vector<double>& out_gaps_evaluation)
513 {
514  out_gaps_evaluation.resize(gaps.size());
515 
516  const double targetAng = CParameterizedTrajectoryGenerator::index2alpha(
517  target_sector, obstacles.size());
518  const double target_x = target_dist * cos(targetAng);
519  const double target_y = target_dist * sin(targetAng);
520 
521  for (unsigned int i = 0; i < gaps.size(); i++)
522  {
523  // Short cut:
524  const TGap* gap = &gaps[i];
525 
526  const float d = min3(
527  obstacles[gap->representative_sector], maxObsRange,
528  0.95 * target_dist);
529 
530  // The TP-Space representative coordinates for this gap:
531  const double phi = CParameterizedTrajectoryGenerator::index2alpha(
532  gap->representative_sector, obstacles.size());
533  const double x = d * cos(phi);
534  const double y = d * sin(phi);
535 
536  // Factor #1: Maximum reachable distance with this PTG:
537  // -----------------------------------------------------
538  // It computes the average free distance of the gap:
539  float meanDist = 0.f;
540  for (unsigned int j = gap->ini; j <= gap->end; j++)
541  meanDist += obstacles[j];
542  meanDist /= (gap->end - gap->ini + 1);
543 
544  double factor1;
545  if (mrpt::utils::abs_diff(gap->representative_sector, target_sector) <=
546  1 &&
547  target_dist < 1)
548  factor1 = std::min(target_dist, meanDist) / target_dist;
549  else
550  factor1 = meanDist;
551 
552  // Factor #2: Distance to target in "sectors"
553  // -------------------------------------------
554  unsigned int dif =
555  mrpt::utils::abs_diff(target_sector, gap->representative_sector);
556 
557  // Handle the -PI,PI circular topology:
558  if (dif > 0.5 * obstacles.size()) dif = obstacles.size() - dif;
559 
560  const double factor2 = exp(-square(dif / (obstacles.size() * 0.25)));
561 
562  // Factor #3: Punish paths that take us far away wrt the target: **** I
563  // don't understand it *********
564  // -----------------------------------------------------
565  double closestX, closestY;
566  double dist_eucl = math::minimumDistanceFromPointToSegment(
567  target_x, target_y, // Point
568  0, 0, x, y, // Segment
569  closestX, closestY // Out
570  );
571 
572  const float factor3 =
573  (maxObsRange - std::min(maxObsRange, dist_eucl)) / maxObsRange;
574 
575  // Factor #4: Stabilizing factor (hysteresis) to avoid quick switch
576  // among very similar paths:
577  // ------------------------------------------------------------------------------------------
578  double factor_AntiCab;
579 
580  if (m_last_selected_sector != std::numeric_limits<unsigned int>::max())
581  {
582  unsigned int dist = mrpt::utils::abs_diff(
583  m_last_selected_sector, gap->representative_sector);
584 
585  if (dist > unsigned(0.1 * obstacles.size()))
586  factor_AntiCab = 0.0;
587  else
588  factor_AntiCab = 1.0;
589  }
590  else
591  {
592  factor_AntiCab = 0;
593  }
594 
595  ASSERT_(options.factorWeights.size() == 4);
596 
597  if (obstacles[gap->representative_sector] <
598  options.TOO_CLOSE_OBSTACLE) // Too close to obstacles
599  out_gaps_evaluation[i] = 0;
600  else
601  out_gaps_evaluation[i] =
602  (options.factorWeights[0] * factor1 +
603  options.factorWeights[1] * factor2 +
604  options.factorWeights[2] * factor3 +
605  options.factorWeights[3] * factor_AntiCab) /
606  (math::sum(options.factorWeights));
607  } // for each gap
608 }
609 
610 unsigned int CHolonomicND::direction2sector(
611  const double a, const unsigned int N)
612 {
613  const int idx = round(0.5 * (N * (1 + mrpt::math::wrapToPi(a) / M_PI) - 1));
614  if (idx < 0)
615  return 0;
616  else
617  return static_cast<unsigned int>(idx);
618 }
619 
620 /*---------------------------------------------------------------
621  writeToStream
622  Implements the writing to a CStream capability of
623  CSerializable objects
624  ---------------------------------------------------------------*/
625 void CLogFileRecord_ND::writeToStream(
626  mrpt::utils::CStream& out, int* version) const
627 {
628  if (version)
629  *version = 1;
630  else
631  {
632  out << gaps_ini << gaps_end << gaps_eval;
633  out << selectedSector << evaluation << riskEvaluation
634  << (uint32_t)situation;
635  }
636 }
637 
638 /*---------------------------------------------------------------
639  readFromStream
640  ---------------------------------------------------------------*/
641 void CLogFileRecord_ND::readFromStream(mrpt::utils::CStream& in, int version)
642 {
643  switch (version)
644  {
645  case 0:
646  {
647  int32_t n;
648 
649  in >> n;
650  gaps_ini.resize(n);
651  gaps_end.resize(n);
652  in.ReadBuffer(&(*gaps_ini.begin()), sizeof(gaps_ini[0]) * n);
653  in.ReadBuffer(&(*gaps_end.begin()), sizeof(gaps_end[0]) * n);
654 
655  in >> n;
656  gaps_eval.resize(n);
657  in.ReadBuffer(&(*gaps_eval.begin()), sizeof(gaps_eval[0]) * n);
658 
659  in >> selectedSector >> evaluation >> riskEvaluation >> n;
660 
661  situation = (CHolonomicND::TSituations)n;
662  }
663  break;
664  case 1:
665  {
666  uint32_t n;
667  in >> gaps_ini >> gaps_end >> gaps_eval;
668  in >> selectedSector >> evaluation >> riskEvaluation >> n;
669  situation = (CHolonomicND::TSituations)n;
670  }
671  break;
672  default:
674  };
675 }
676 
677 /*---------------------------------------------------------------
678  TOptions
679  ---------------------------------------------------------------*/
680 CHolonomicND::TOptions::TOptions()
681  : // Default values:
682  TOO_CLOSE_OBSTACLE(0.15),
683  WIDE_GAP_SIZE_PERCENT(0.25),
684  RISK_EVALUATION_SECTORS_PERCENT(0.10),
685  RISK_EVALUATION_DISTANCE(0.4),
686  MAX_SECTOR_DIST_FOR_D2_PERCENT(0.25),
687  TARGET_SLOW_APPROACHING_DISTANCE(0.60),
688  factorWeights{1.0, 0.5, 2.0, 0.4}
689 {
690 }
691 
693  const mrpt::utils::CConfigFileBase& source, const std::string& section)
694 {
695  MRPT_START
696 
697  // Load from config text:
698  MRPT_LOAD_CONFIG_VAR(WIDE_GAP_SIZE_PERCENT, double, source, section);
700  MAX_SECTOR_DIST_FOR_D2_PERCENT, double, source, section);
702  RISK_EVALUATION_SECTORS_PERCENT, double, source, section);
703  MRPT_LOAD_CONFIG_VAR(RISK_EVALUATION_DISTANCE, double, source, section);
704  MRPT_LOAD_CONFIG_VAR(TOO_CLOSE_OBSTACLE, double, source, section);
706  TARGET_SLOW_APPROACHING_DISTANCE, double, source, section);
707 
708  source.read_vector(
709  section, "factorWeights", std::vector<double>(), factorWeights, true);
710  ASSERT_(factorWeights.size() == 4);
711 
712  MRPT_END
713 }
714 
717 {
718  MRPT_START;
719  const int WN = mrpt::utils::MRPT_SAVE_NAME_PADDING(),
721 
722  MRPT_SAVE_CONFIG_VAR_COMMENT(WIDE_GAP_SIZE_PERCENT, "");
723  MRPT_SAVE_CONFIG_VAR_COMMENT(MAX_SECTOR_DIST_FOR_D2_PERCENT, "");
724  MRPT_SAVE_CONFIG_VAR_COMMENT(RISK_EVALUATION_SECTORS_PERCENT, "");
726  RISK_EVALUATION_DISTANCE, "In normalized ps-meters [0,1]");
727  MRPT_SAVE_CONFIG_VAR_COMMENT(TOO_CLOSE_OBSTACLE, "For stopping gradually");
729  TARGET_SLOW_APPROACHING_DISTANCE, "In normalized ps-meters");
730 
731  ASSERT_EQUAL_(factorWeights.size(), 4)
732  c.write(
733  s, "factorWeights",
734  mrpt::format(
735  "%.2f %.2f %.2f %.2f", factorWeights[0], factorWeights[1],
736  factorWeights[2], factorWeights[3]),
737  WN, WV,
738  "[0]=Free space, [1]=Dist. in sectors, [2]=Closer to target "
739  "(Euclidean), [3]=Hysteresis");
740 
741  MRPT_END
742 }
743 
744 void CHolonomicND::writeToStream(mrpt::utils::CStream& out, int* version) const
745 {
746  if (version)
747  *version = 0;
748  else
749  {
750  // Params:
756  // State:
757  out << m_last_selected_sector;
758  }
759 }
761 {
762  switch (version)
763  {
764  case 0:
765  {
766  // Params:
767  in >> options.factorWeights >>
773  // State:
775  }
776  break;
777  default:
779  };
780 }
#define ASSERT_EQUAL_(__A, __B)
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define min(a, b)
const T min3(const T &A, const T &B, const T &C)
Definition: bits.h:156
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
double x
X,Y coordinates.
An implementation of the holonomic reactive navigation method "Nearness-Diagram". ...
Definition: CHolonomicND.h:55
unsigned int m_last_selected_sector
Definition: CHolonomicND.h:127
std::vector< double > obstacles
Distance to obstacles in polar coordinates, relative to the robot.
GLenum GLsizei n
Definition: glext.h:5074
This file implements several operations that operate element-wise on individual or pairs of container...
A base class for holonomic reactive navigation methods.
std::vector< TGap > TGapArray
Definition: CHolonomicND.h:76
STL namespace.
#define M_PI
Definition: bits.h:92
GLdouble s
Definition: glext.h:3676
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< mrpt::math::TPoint2D > targets
Relative location (x,y) of target point(s).
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:55
TOptions options
Parameters of the algorithm (can be set manually or loaded from CHolonomicND::initialize or options...
Definition: CHolonomicND.h:115
unsigned int representative_sector
Definition: CHolonomicND.h:73
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:41
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
int MRPT_SAVE_NAME_PADDING()
Default padding sizes for macros MRPT_SAVE_CONFIG_VAR_COMMENT(), etc.
#define MRPT_SAVE_CONFIG_VAR_COMMENT(variableName, __comment)
#define MRPT_END
const GLubyte * c
Definition: glext.h:6313
#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].
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
GLuint GLuint end
Definition: glext.h:3528
std::vector< double > factorWeights
Vector of 4 weights: [0]=Free space, [1]=Dist.
Definition: CHolonomicND.h:102
CHolonomicLogFileRecord::Ptr logRecord
The navigation method will create a log record and store it here via a smart pointer.
GLsizei const GLchar ** string
Definition: glext.h:4101
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:53
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...
Definition: bits.h:227
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
double norm() const
Point norm.
double desiredSpeed
The desired motion speed in that direction, from 0 up to NavInput::maxRobotSpeed. ...
#define MRPT_START
__int32 int32_t
Definition: rptypes.h:46
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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...
Definition: bits.h:220
The structure used to store a detected gap in obstacles.
Definition: CHolonomicND.h:67
std::shared_ptr< CLogFileRecord_ND > Ptr
Definition: CHolonomicND.h:167
GLuint in
Definition: glext.h:7274
A class for storing extra information about the execution of CHolonomicND navigation.
Definition: CHolonomicND.h:165
GLsizei GLsizei GLchar * source
Definition: glext.h:4082
#define ASSERT_(f)
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
GLenum GLint GLint y
Definition: glext.h:3538
void readFromStream(mrpt::utils::CStream &in, int version) override
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
Input parameters for CAbstractHolonomicReactiveMethod::navigate()
#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...
GLenum GLint x
Definition: glext.h:3538
IMPLEMENTS_SERIALIZABLE(CHolonomicND, CAbstractHolonomicReactiveMethod, mrpt::nav) CHolonomicND
Initialize the parameters of the navigator, from some configuration file, or default values if filena...
T abs_diff(const T a, const T b)
Efficient and portable evaluation of the absolute difference of two unsigned integer values (but will...
std::vector< double > gaps_eval
Definition: CHolonomicND.h:173
unsigned __int32 uint32_t
Definition: rptypes.h:47
Lightweight 2D point.
double minimumDistanceFromPointToSegment(const double Px, const double Py, const double x1, const double y1, const double x2, const double y2, T &out_x, T &out_y)
Computes the closest point from a given point to a segment, and returns that minimum distance...
Definition: geometry.h:986
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
Output for CAbstractHolonomicReactiveMethod::navigate()
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...
int MRPT_SAVE_VALUE_PADDING()
TSituations
The set of posible situations for each trajectory.
Definition: CHolonomicND.h:80
void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &section) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019