30 const
unsigned int INVALID_K = std::numeric_limits<
unsigned int>::max();
35 m_last_selected_sector(std::numeric_limits<
unsigned int>::max())
37 if (INI_FILE !=
nullptr) initialize(*INI_FILE);
42 options.saveToConfigFile(
c, getConfigFileSectionName());
47 options.loadFromConfigFile(
c, getConfigFileSectionName());
61 min_eval(std::numeric_limits<double>::max()),
62 max_eval(-std::numeric_limits<double>::max()),
63 contains_target_k(false),
69 CHolonomicFullEval::EvalOutput::EvalOutput() : best_k(
INVALID_K), best_eval(.0)
77 const auto target = ni.
targets[target_idx];
84 const double ptg_ref_dist = ptg ? ptg->getRefDistance() : 1.0;
87 const double target_dir = ::atan2(target.y, target.x);
88 const unsigned int target_k =
90 const double target_dist = target.norm();
95 std::vector<mrpt::math::TPoint2D> obstacles_2d(nDirs);
103 for (
unsigned int i = 0; i < nDirs; i++)
105 obstacles_2d[i].x = ni.
obstacles[i] * sc_lut.ccos[i];
106 obstacles_2d[i].y = ni.
obstacles[i] * sc_lut.csin[i];
109 const int NUM_FACTORS = 5;
113 for (
unsigned int i = 0; i < nDirs; i++)
115 double scores[NUM_FACTORS];
124 for (
int l = 0; l < NUM_FACTORS; l++)
m_dirs_scores(i, l) = .0;
131 const double x = d * sc_lut.ccos[i];
132 const double y = d * sc_lut.csin[i];
142 std::max(target_dist, ni.
obstacles[i]) / (target_dist * 1.05);
154 const double max_real_freespace =
155 ptg->getActualUnloopedPathLength(i);
156 const double max_real_freespace_norm =
157 max_real_freespace / ptg->getRefDistance();
172 double min_dist_target_along_path = sg.
distance(target);
178 const double endpt_dist_to_target = (target -
TPoint2D(
x,
y)).
norm();
179 const double endpt_dist_to_target_norm =
180 std::min(1.0, endpt_dist_to_target);
182 if ((endpt_dist_to_target_norm > target_dist &&
183 endpt_dist_to_target_norm >= 0.95 * target_dist) &&
184 min_dist_target_along_path >
187 endpt_dist_to_target_norm)
195 min_dist_target_along_path = sg.
distance(target);
198 scores[1] = 1.0 / (1.0 +
square(min_dist_target_along_path));
203 scores[2] = std::sqrt(
204 1.01 - endpt_dist_to_target_norm);
235 const double query_dist_norm =
std::min(0.99, target_dist * 0.95);
237 i , query_dist_norm,
true );
239 i , query_dist_norm,
false );
240 scores[4] = 0.5 * (avr_path_clearance + point_clearance);
244 for (
int l = 0; l < NUM_FACTORS; l++)
m_dirs_scores(i, l) = scores[l];
249 for (
int l = 0; l < NUM_FACTORS; l++)
256 if (
span <= .0)
continue;
267 std::vector<double> weights_sum_phase(NUM_PHASES, .0),
268 weights_sum_phase_inv(NUM_PHASES);
269 for (
unsigned int i = 0; i < NUM_PHASES; i++)
273 ASSERT_(weights_sum_phase[i] > .0);
274 weights_sum_phase_inv[i] = 1.0 / weights_sum_phase[i];
278 NUM_PHASES, std::vector<double>(nDirs, .0));
280 double last_phase_threshold = -1.0;
282 for (
unsigned int phase_idx = 0; phase_idx < NUM_PHASES; phase_idx++)
284 double phase_min = std::numeric_limits<double>::max(), phase_max = .0;
286 for (
unsigned int i = 0; i < nDirs; i++)
288 double this_dir_eval = 0;
293 phase_scores[phase_idx - 1][i] <
294 last_phase_threshold)
308 this_dir_eval *= weights_sum_phase_inv[phase_idx];
309 this_dir_eval = std::exp(this_dir_eval);
311 phase_scores[phase_idx][i] = this_dir_eval;
323 last_phase_threshold =
329 auto& dirs_eval = *phase_scores.rbegin();
336 double phase_min = std::numeric_limits<double>::max(), phase_max = .0;
337 for (
unsigned int i = 0; i < nDirs; i++)
342 last_phase_threshold =
352 std::vector<TGap> gaps;
353 int best_gap_idx = -1;
354 int gap_idx_for_target_dir = -1;
356 bool inside_gap =
false;
357 for (
unsigned int i = 0; i < nDirs; i++)
359 const double val = dirs_eval[i];
360 if (
val < last_phase_threshold)
365 auto& active_gap = *gaps.rbegin();
366 active_gap.k_to = i - 1;
379 gaps.emplace_back(new_gap);
386 auto& active_gap = *gaps.rbegin();
387 if (
val >= active_gap.max_eval)
389 active_gap.k_best_eval = i;
396 active_gap.contains_target_k =
true;
397 gap_idx_for_target_dir = gaps.size() - 1;
400 if (best_gap_idx == -1 ||
val > gaps[best_gap_idx].max_eval)
402 best_gap_idx = gaps.size() - 1;
410 auto& active_gap = *gaps.rbegin();
411 active_gap.k_to = nDirs - 1;
416 ASSERT_(best_gap_idx >= 0 && best_gap_idx <
int(gaps.size()));
418 const TGap& best_gap = gaps[best_gap_idx];
423 if (best_gap_idx == gap_idx_for_target_dir)
428 const auto cl_right =
431 const auto smallest_clearance_in_k_units =
std::min(cl_left, cl_right);
432 const unsigned int clearance_threshold =
435 const unsigned int gap_width = best_gap.
k_to - best_gap.
k_from;
436 const unsigned int width_threshold =
440 if (smallest_clearance_in_k_units >= clearance_threshold &&
441 gap_width >= width_threshold &&
442 ni.
obstacles[target_k] > target_dist * 1.01)
461 if (target_dist < 0.99 &&
464 (ni.
obstacles[target_k] > target_dist * 1.01 &&
466 target_k ,
std::min(0.99, target_dist * 0.95),
471 (target_dist + 0.15 / ptg_ref_dist) &&
472 target_dist < (1.5 / ptg_ref_dist))) &&
473 dirs_eval[target_k] >
481 phase_scores[NUM_PHASES - 1][target_k] += 2.0;
494 mrpt::make_aligned_shared<CLogFileRecord_FullEval>();
497 const size_t numTrgs = ni.
targets.size();
499 std::vector<EvalOutput> evals(numTrgs);
500 double best_eval = .0;
501 unsigned int best_trg_idx = 0;
503 for (
unsigned int trg_idx = 0; trg_idx < numTrgs; trg_idx++)
505 auto& eo = evals[trg_idx];
511 best_eval = eo.best_eval;
512 best_trg_idx = trg_idx;
527 const double ptg_ref_dist = ptg ? ptg->getRefDistance() : 1.0;
530 evals[best_trg_idx].best_k, ni.
obstacles.size());
534 const double targetNearnessFactor =
537 1.0, ni.
targets[best_trg_idx].norm() /
542 const double obs_dist =
543 ni.
obstacles[evals[best_trg_idx].best_k];
545 const double obs_dist_th = std::max(
549 double riskFactor = 1.0;
569 log->selectedTarget = best_trg_idx;
570 log->selectedSector = evals[best_trg_idx].best_k;
571 log->evaluation = evals[best_trg_idx].best_eval;
572 log->dirs_eval = evals[best_trg_idx].phase_scores;
582 const double a,
const unsigned int N)
588 return static_cast<unsigned int>(idx);
592 : selectedSector(0), evaluation(.0), dirs_scores(), selectedTarget(0)
651 TOO_CLOSE_OBSTACLE(0.15),
652 TARGET_SLOW_APPROACHING_DISTANCE(0.60),
653 OBSTACLE_SLOW_DOWN_DISTANCE(0.15),
654 HYSTERESIS_SECTOR_COUNT(5),
655 factorWeights{0.1, 0.5, 0.5, 0.01, 1},
656 factorNormalizeOrNot{0, 0, 0, 0, 1},
657 PHASE_FACTORS{{1, 2}, {4}, {0, 2}},
658 PHASE_THRESHOLDS{0.5, 0.6, 0.7},
659 LOG_SCORE_MATRIX(
false),
660 clearance_threshold_ratio(0.05),
661 gap_width_ratio_threshold(0.25)
680 s,
"factorWeights", std::vector<double>(), factorWeights,
true);
681 ASSERT_(factorWeights.size() == 5);
684 s,
"factorNormalizeOrNot", factorNormalizeOrNot, factorNormalizeOrNot);
685 ASSERT_(factorNormalizeOrNot.size() == factorWeights.size());
691 PHASE_FACTORS.resize(PHASE_COUNT);
692 PHASE_THRESHOLDS.resize(PHASE_COUNT);
693 for (
int i = 0; i < PHASE_COUNT; i++)
697 PHASE_FACTORS[i],
true);
700 PHASE_THRESHOLDS[i] =
c.read_double(
702 ASSERT_(PHASE_THRESHOLDS[i] >= .0 && PHASE_THRESHOLDS[i] <= 1.0);
718 "Directions with collision-free distances below this threshold are not "
721 TARGET_SLOW_APPROACHING_DISTANCE,
722 "Start to reduce speed when closer than this to target.");
724 OBSTACLE_SLOW_DOWN_DISTANCE,
725 "Start to reduce speed when clearance is below this value ([0,1] ratio "
726 "wrt obstacle reference/max distance)");
728 HYSTERESIS_SECTOR_COUNT,
729 "Range of `sectors` (directions) for hysteresis over successive "
732 LOG_SCORE_MATRIX,
"Save the entire score matrix in log files");
734 clearance_threshold_ratio,
735 "Ratio [0,1], times path_count, gives the minimum number of paths at "
736 "each side of a target direction to be accepted as desired direction");
738 gap_width_ratio_threshold,
739 "Ratio [0,1], times path_count, gives the minimum gap width to accept "
740 "a direct motion towards target.");
746 "[0]=Free space, [1]=Dist. in sectors, [2]=Closer to target "
747 "(Euclidean), [3]=Hysteresis, [4]=clearance along path");
749 s,
"factorNormalizeOrNot",
751 "Normalize factors or not (1/0)");
754 s,
"PHASE_COUNT", PHASE_FACTORS.size(), WN, WV,
755 "Number of evaluation phases to run (params for each phase below)");
757 for (
unsigned int i = 0; i < PHASE_FACTORS.size(); i++)
760 s,
mrpt::format(
"PHASE%u_THRESHOLD", i + 1), PHASE_THRESHOLDS[i],
762 "Phase scores must be above this relative range threshold [0,1] to "
763 "be considered in next phase (Default:`0.75`)");
767 "Indices of the factors above to be considered in this phase");
844 std::vector<double>& dir_evals,
const NavInput& ni,
unsigned int trg_idx)