Skip to content

Commit 4e23fa3

Browse files
committed
progress mrpt_nav update
1 parent f502c4b commit 4e23fa3

19 files changed

+612
-278
lines changed

doc/source/doxygen-docs/port_mrpt3.md

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -338,43 +338,13 @@ increasing risk/effort. Each item is prefixed with a priority tag:
338338
339339
---
340340
341-
#### 13.6.2 `[[nodiscard]]` annotations (remaining)
342-
343-
Still pending: `CAbstractPTGBasedReactive` getters, holonomic `TOptions` getters.
344-
345-
---
346-
347341
#### 13.6.3 Naming consistency (remaining)
348342
349343
- **Config structs**: Holonomic classes use `TOptions`; navigator/optimizer/graphslam
350344
classes use `TParams`. Low-value cosmetic change across multiple modules — deferred.
351345
352346
---
353347
354-
#### 13.6.4 Thread-safety fixes (remaining)
355-
356-
Global mutable `OUTPUT_DEBUG_PATH_PREFIX` / `COLLISION_BEHAVIOR` statics
357-
have no synchronisation — consider moving to per-instance fields or guarding with mutex.
358-
359-
---
360-
361-
#### 13.6.5 Return-value modernisation (remaining)
362-
363-
| Method | Current | Proposed |
364-
|--------|---------|----------|
365-
| `CRobot2NavInterface::getCurrentPoseAndSpeeds()` | 4 output `&` params | Return `struct PoseAndSpeeds { TPose2D pose; TTwist2D vel; … };` |
366-
| `CParameterizedTrajectoryGenerator::inverseMap_WS2TP()` | `int& k, double& d` output | Return `std::optional<std::pair<uint16_t,double>>` |
367-
368-
---
369-
370-
#### 13.6.6 Raw-pointer cleanup (remaining)
371-
372-
`CAbstractPTGBasedReactive::getHoloMethod()` returns a raw pointer;
373-
consider returning `CAbstractHolonomicReactiveMethod&` (with assert) for non-nullable
374-
use sites.
375-
376-
---
377-
378348
#### 13.6.7 Decompose `CAbstractPTGBasedReactive`
379349
380350
**[P2]** This 467-line header (11 virtual methods, 6 nested structs,
@@ -414,10 +384,8 @@ abstraction. Each should be broken into named helpers:
414384
415385
Zero dedicated unit tests for:
416386
417-
- `CWaypointsNavigator` / `TWaypointSequence` state machine.
387+
- `CWaypointsNavigator` state machine (requires full robot interface mock).
418388
- `CNavigatorManualSequence`.
419-
- `PlannerRRT_SE2_TPS`, `PlannerRRT_common`.
420-
- `CMultiObjectiveMotionOptimizerBase`, `CMultiObjMotionOpt_Scalarization`.
421389
422390
---
423391

modules/mrpt_nav/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ set(LIB_SOURCES
6161
tests/CLogFileRecord_unittest.cpp
6262
tests/holonomic_unittest.cpp
6363
tests/rnav_unittest.cpp
64+
tests/waypoints_and_rrt_unittest.cpp
6465
)
6566

6667
set(LIB_PUBLIC_HEADERS

modules/mrpt_nav/include/mrpt/nav/planners/TMoveTree.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,13 +271,11 @@ struct PoseDistanceMetric<TNodeSE2_TP>
271271
}
272272
double distance(const TNodeSE2_TP& src, const TNodeSE2_TP& dst) const
273273
{
274-
double d;
275-
int k;
276274
mrpt::poses::CPose2D relPose(mrpt::poses::UNINITIALIZED_POSE);
277275
relPose.inverseComposeFrom(mrpt::poses::CPose2D(dst.state), mrpt::poses::CPose2D(src.state));
278-
bool tp_point_is_exact = m_ptg.inverseMap_WS2TP(relPose.x(), relPose.y(), k, d);
279-
if (tp_point_is_exact)
280-
return d * m_ptg.getRefDistance(); // de-normalize distance
276+
const auto res = m_ptg.inverseMap_WS2TP(relPose.x(), relPose.y());
277+
if (res)
278+
return res->second * m_ptg.getRefDistance(); // de-normalize distance
281279
else
282280
return std::numeric_limits<double>::max(); // not in range: we
283281
// can't evaluate this

modules/mrpt_nav/include/mrpt/nav/reactive/CAbstractPTGBasedReactive.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,17 +234,18 @@ class CAbstractPTGBasedReactive : public CWaypointsNavigator
234234
void enableTimeLog(bool enable = true) { m_timelogger.enable(enable); }
235235
/** Gives access to a const-ref to the internal time logger \sa
236236
* enableTimeLog */
237-
const mrpt::system::CTimeLogger& getTimeLogger() const { return m_timelogger; }
237+
[[nodiscard]] const mrpt::system::CTimeLogger& getTimeLogger() const { return m_timelogger; }
238238

239239
/** Returns the number of different PTGs that have been setup */
240-
virtual size_t getPTG_count() const = 0;
240+
[[nodiscard]] virtual size_t getPTG_count() const = 0;
241241
/** Gets the i'th PTG */
242-
virtual CParameterizedTrajectoryGenerator* getPTG(size_t i) = 0;
242+
[[nodiscard]] virtual CParameterizedTrajectoryGenerator* getPTG(size_t i) = 0;
243243
/** Gets the i'th PTG */
244-
virtual const CParameterizedTrajectoryGenerator* getPTG(size_t i) const = 0;
244+
[[nodiscard]] virtual const CParameterizedTrajectoryGenerator* getPTG(size_t i) const = 0;
245245

246246
/** Get the current, global (honored for all PTGs) robot speed limits */
247-
const mrpt::kinematics::CVehicleVelCmd::TVelCmdParams& getCurrentRobotSpeedLimits() const
247+
[[nodiscard]] const mrpt::kinematics::CVehicleVelCmd::TVelCmdParams& getCurrentRobotSpeedLimits()
248+
const
248249
{
249250
return params_abstract_ptg_navigator.robot_absolute_speed_limits;
250251
}
@@ -261,13 +262,13 @@ class CAbstractPTGBasedReactive : public CWaypointsNavigator
261262
void setTargetApproachSlowDownDistance(const double dist);
262263
/** Returns this parameter for the first inner holonomic navigator instances
263264
* [m] (should be the same in all of them?) */
264-
double getTargetApproachSlowDownDistance() const;
265+
[[nodiscard]] double getTargetApproachSlowDownDistance() const;
265266

266267
protected:
267268
/** The main method for the navigator */
268269
void performNavigationStep() override;
269270

270-
virtual CAbstractHolonomicReactiveMethod* getHoloMethod(int idx);
271+
[[nodiscard]] virtual CAbstractHolonomicReactiveMethod* getHoloMethod(int idx);
271272

272273
/** The holonomic navigation algorithm (one object per PTG, so internal
273274
* states are maintained) */

modules/mrpt_nav/include/mrpt/nav/tpspace/CPTG_DiffDrive_C.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ class CPTG_DiffDrive_C : public CPTG_DiffDrive_CollisionGridBased
5757
mrpt::config::CConfigFileBase& cfg, const std::string& sSection) const override;
5858

5959
std::string getDescription() const override;
60-
bool inverseMap_WS2TP(
61-
double x, double y, int& out_k, double& out_d, double tolerance_dist = 0.10) const override;
60+
std::optional<std::pair<int, double>> inverseMap_WS2TP(
61+
double x, double y, double tolerance_dist = 0.10) const override;
6262
bool PTG_IsIntoDomain(double x, double y) const override;
6363
void ptgDiffDriveSteeringFunction(
6464
float alpha, float t, float x, float y, float phi, float& v, float& w) const override;

modules/mrpt_nav/include/mrpt/nav/tpspace/CPTG_DiffDrive_CollisionGridBased.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ class CPTG_DiffDrive_CollisionGridBased : public CPTG_RobotShape_Polygonal
7676
* exist.
7777
* See full docs in base class
7878
* CParameterizedTrajectoryGenerator::inverseMap_WS2TP() */
79-
bool inverseMap_WS2TP(
80-
double x, double y, int& out_k, double& out_d, double tolerance_dist = 0.10) const override;
79+
std::optional<std::pair<int, double>> inverseMap_WS2TP(
80+
double x, double y, double tolerance_dist = 0.10) const override;
8181

8282
/** In this class, `out_action_cmd` contains: [0]: linear velocity (m/s),
8383
* [1]: angular velocity (rad/s).

modules/mrpt_nav/include/mrpt/nav/tpspace/CPTG_Holo_Blend.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class CPTG_Holo_Blend : public CPTG_RobotShape_Circular
4444
double maxTimeInVelCmdNOP(int path_k) const override;
4545

4646
std::string getDescription() const override;
47-
bool inverseMap_WS2TP(
48-
double x, double y, int& out_k, double& out_d, double tolerance_dist = 0.10) const override;
47+
std::optional<std::pair<int, double>> inverseMap_WS2TP(
48+
double x, double y, double tolerance_dist = 0.10) const override;
4949
bool PTG_IsIntoDomain(double x, double y) const override;
5050
void onNewNavDynamicState() override;
5151

modules/mrpt_nav/include/mrpt/nav/tpspace/CParameterizedTrajectoryGenerator.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <mrpt/serialization/CSerializable.h>
2828

2929
#include <cstdint>
30+
#include <optional>
31+
#include <utility>
3032

3133
namespace mrpt
3234
{
@@ -329,9 +331,17 @@ class CParameterizedTrajectoryGenerator :
329331
void updateNavDynamicState(const TNavDynamicState& newState, const bool force_update = false);
330332
const TNavDynamicState& getCurrentNavDynamicState() const { return m_nav_dyn_state; }
331333

332-
/** The path used as default output in, for example, debugDumpInFiles.
333-
* (Default="./reactivenav.logs/") */
334-
static std::string& OUTPUT_DEBUG_PATH_PREFIX();
334+
/** Returns the path used as default output in, for example,
335+
* debugDumpInFiles. (Default="./reactivenav.logs/") */
336+
[[nodiscard]] static std::string getOutputDebugPathPrefix();
337+
/** Sets the path used as default output in, for example, debugDumpInFiles.
338+
*/
339+
static void setOutputDebugPathPrefix(const std::string& path);
340+
341+
/** @deprecated Use getOutputDebugPathPrefix() / setOutputDebugPathPrefix()
342+
*/
343+
[[deprecated("Use getOutputDebugPathPrefix()/setOutputDebugPathPrefix()")]] static std::string&
344+
OUTPUT_DEBUG_PATH_PREFIX();
335345

336346
/** Must be called after setting all PTG parameters and before requesting
337347
* converting obstacles to TP-Space, inverseMap_WS2TP(), etc. */
@@ -418,11 +428,17 @@ class CParameterizedTrajectoryGenerator :
418428
mrpt::viz::CSetOfLines& gl_shape,
419429
const mrpt::poses::CPose2D& origin = mrpt::poses::CPose2D()) const = 0;
420430

421-
/** Defines the behavior when there is an obstacle *inside* the robot shape
422-
* right at the beginning of a PTG trajectory.
423-
* Default value: PTGCollisionBehavior::BACK_AWAY
424-
*/
425-
static PTGCollisionBehavior& COLLISION_BEHAVIOR();
431+
/** Returns the behavior when there is an obstacle inside the robot shape
432+
* at the beginning of a PTG trajectory.
433+
* Default value: PTGCollisionBehavior::BACK_AWAY */
434+
[[nodiscard]] static PTGCollisionBehavior getCollisionBehavior();
435+
/** Sets the behavior when there is an obstacle inside the robot shape
436+
* at the beginning of a PTG trajectory. */
437+
static void setCollisionBehavior(PTGCollisionBehavior behavior);
438+
439+
/** @deprecated Use getCollisionBehavior() / setCollisionBehavior() */
440+
[[deprecated("Use getCollisionBehavior()/setCollisionBehavior()")]] static PTGCollisionBehavior&
441+
COLLISION_BEHAVIOR();
426442

427443
/** Must be called to resize a CD to its correct size, before calling
428444
* updateClearance() */

modules/mrpt_nav/src/holonomic/CHolonomicFullEval.cpp

Lines changed: 51 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,55 @@ struct TGap
6565
}
6666
};
6767

68+
// Returns the list of gaps found in `overall_scores` and the index of the
69+
// best (highest max_eval) gap, or npos if no gaps exist.
70+
static std::pair<std::vector<TGap>, std::size_t> findScoreGaps(
71+
const std::vector<double>& overall_scores)
72+
{
73+
const auto nDirs = overall_scores.size();
74+
std::vector<TGap> gaps;
75+
std::size_t best_gap_idx = std::string::npos;
76+
77+
bool inside_gap = false;
78+
for (unsigned int i = 0; i < nDirs; i++)
79+
{
80+
const double val = overall_scores[i];
81+
if (val < 0.01)
82+
{
83+
if (inside_gap)
84+
{
85+
gaps.back().k_to = i - 1;
86+
inside_gap = false;
87+
}
88+
}
89+
else
90+
{
91+
if (!inside_gap)
92+
{
93+
TGap new_gap;
94+
new_gap.k_from = i;
95+
gaps.emplace_back(new_gap);
96+
inside_gap = true;
97+
}
98+
}
99+
100+
if (inside_gap)
101+
{
102+
auto& active_gap = gaps.back();
103+
if (val >= active_gap.max_eval) active_gap.k_best_eval = i;
104+
mrpt::keep_max(active_gap.max_eval, val);
105+
mrpt::keep_min(active_gap.min_eval, val);
106+
107+
if (best_gap_idx == std::string::npos || val > gaps[best_gap_idx].max_eval)
108+
best_gap_idx = gaps.size() - 1;
109+
}
110+
}
111+
112+
if (inside_gap) gaps.back().k_to = static_cast<int>(nDirs) - 1;
113+
114+
return {gaps, best_gap_idx};
115+
}
116+
68117
void CHolonomicFullEval::evalSingleTarget(
69118
unsigned int target_idx, const NavInput& ni, EvalOutput& eo)
70119
{
@@ -428,69 +477,9 @@ CHolonomicFullEval::NavOutput CHolonomicFullEval::navigate(const NavInput& ni)
428477
for (unsigned int i = 0; i < nDirs; i++) overall_scores[i] *= (1.0 / numTrgs);
429478

430479
// Search for best direction in the "overall score" vector:
480+
// Keep the GAP with the largest maximum value; pick its best-eval direction.
481+
const auto [gaps, best_gap_idx] = findScoreGaps(overall_scores);
431482

432-
// Keep the GAP with the largest maximum value within;
433-
// then pick the MIDDLE point as the final selection.
434-
std::vector<TGap> gaps;
435-
std::size_t best_gap_idx = std::string::npos;
436-
{
437-
bool inside_gap = false;
438-
for (unsigned int i = 0; i < nDirs; i++)
439-
{
440-
const double val = overall_scores[i];
441-
if (val < 0.01)
442-
{
443-
// This direction didn't pass the cut threshold for the "last
444-
// phase":
445-
if (inside_gap)
446-
{
447-
// We just ended a gap:
448-
auto& active_gap = *gaps.rbegin();
449-
active_gap.k_to = i - 1;
450-
inside_gap = false;
451-
}
452-
}
453-
else
454-
{
455-
// higher or EQUAL to the treshold (equal is important just in
456-
// case we have a "flat" diagram...)
457-
if (!inside_gap)
458-
{
459-
// We just started a gap:
460-
TGap new_gap;
461-
new_gap.k_from = i;
462-
gaps.emplace_back(new_gap);
463-
inside_gap = true;
464-
}
465-
}
466-
467-
if (inside_gap)
468-
{
469-
auto& active_gap = *gaps.rbegin();
470-
if (val >= active_gap.max_eval)
471-
{
472-
active_gap.k_best_eval = i;
473-
}
474-
mrpt::keep_max(active_gap.max_eval, val);
475-
mrpt::keep_min(active_gap.min_eval, val);
476-
477-
if (best_gap_idx == std::string::npos || val > gaps[best_gap_idx].max_eval)
478-
{
479-
best_gap_idx = gaps.size() - 1;
480-
}
481-
}
482-
} // end for i
483-
484-
// Handle the case where we end with an open, active gap:
485-
if (inside_gap)
486-
{
487-
auto& active_gap = *gaps.rbegin();
488-
active_gap.k_to = nDirs - 1;
489-
}
490-
}
491-
492-
// Not heading to target: go thru the "middle" of the gap to maximize
493-
// clearance
494483
int best_dir_k = -1;
495484
double best_dir_eval = 0;
496485

0 commit comments

Comments
 (0)