SPFA.cpp
Go to the documentation of this file.
1#include "SPFA.h"
2
3#include <algorithm>
4#include <chrono>
5#include <cmath>
6#include <cstddef>
7#include <iomanip>
8#include <optional>
9#include <sstream>
10#include <tuple>
11#include <vector>
12
13#include <Eigen/Geometry>
14
15#include <IceUtil/Time.h>
16
17#include <range/v3/range/conversion.hpp>
18#include <range/v3/view/transform.hpp>
19#include <range/v3/view/zip.hpp>
20
21#include <VirtualRobot/Robot.h> // IWYU pragma: keep
22#include <VirtualRobot/math/Helpers.h>
23
31
34
44#include <armarx/navigation/global_planning/aron/SPFAParams.aron.generated.h>
48
49namespace
50{
51 struct PipelineTimings
52 {
53 std::chrono::microseconds buildTrajectory{0};
54 std::chrono::microseconds resample{0};
55 std::chrono::microseconds smoothPositions{0};
56 std::chrono::microseconds recomputeVelocities{0};
57 std::chrono::microseconds recoveryHandling{0};
58 std::chrono::microseconds loadOrientationConfig{0};
59 std::chrono::microseconds optimizeOrientation{0};
60 std::chrono::microseconds stitchTrajectory{0};
61 std::chrono::microseconds finalVelocityClamp{0};
62 };
63
64 class ScopedStageTimer
65 {
66 public:
67 explicit ScopedStageTimer(std::chrono::microseconds& out) :
68 out_(out), start_(std::chrono::steady_clock::now())
69 {
70 }
71
72 ~ScopedStageTimer()
73 {
74 out_ = std::chrono::duration_cast<std::chrono::microseconds>(
75 std::chrono::steady_clock::now() - start_);
76 }
77
78 private:
79 std::chrono::microseconds& out_;
80 std::chrono::steady_clock::time_point start_;
81 };
82
83 std::string formatTimings(const PipelineTimings& timings)
84 {
85 const auto ms = [](std::chrono::microseconds us) -> std::string
86 {
87 std::ostringstream oss;
88 oss << std::fixed << std::setprecision(3) << (us.count() / 1000.0);
89 return oss.str();
90 };
91
92 std::ostringstream oss;
93 oss << "[SPFA timing] "
94 << "build=" << ms(timings.buildTrajectory) << "ms "
95 << "resample=" << ms(timings.resample) << "ms "
96 << "smooth=" << ms(timings.smoothPositions) << "ms "
97 << "velocity=" << ms(timings.recomputeVelocities) << "ms "
98 << "recovery=" << ms(timings.recoveryHandling) << "ms "
99 << "orientationConfig=" << ms(timings.loadOrientationConfig) << "ms "
100 << "orientationOptimize=" << ms(timings.optimizeOrientation) << "ms "
101 << "stitch=" << ms(timings.stitchTrajectory) << "ms "
102 << "clamp=" << ms(timings.finalVelocityClamp) << "ms";
103 return oss.str();
104 }
105} // namespace
106
108{
109
110 // SPFAParams
111
114 {
115 return Algorithms::SPFA;
116 }
117
120 {
121 arondto::SPFAParams dto;
122
123 aron_conv::toAron(dto, *this);
124
125 return dto.toAron();
126 }
127
130 {
132
133 // ARMARX_DEBUG << dict->getAllKeysAsString();
134
135 arondto::SPFAParams dto;
136 dto.fromAron(dict);
137
138 SPFAParams bo;
139 aron_conv::fromAron(dto, bo);
140
141 return bo;
142 }
143
144 // SPFA
145
146 SPFA::SPFA(const Params& params,
148 const core::Scene& ctx) :
150 impl_(params,
152 ctx.staticScene.has_value() ? ctx.staticScene->distanceToObstaclesCostmap
153 : std::nullopt)
154 {
155 }
156
157 std::optional<GlobalPlannerResult>
159 {
160 const core::Pose start(scene.robot->getGlobalPose());
161 return plan(start, goal);
162 }
163
164 std::optional<GlobalPlannerResult>
165 SPFA::plan(const core::Pose& start, const core::Pose& goal)
166 {
167 if (scene.staticScene.has_value())
168 {
169 impl_.updateCostmap(scene.staticScene->distanceToObstaclesCostmap);
170 }
171 return impl_.plan(start, goal);
172 }
173
176 {
177 return impl_.executePlanner(start);
178 }
179
180 std::optional<GlobalPlannerResult>
181 SPFA::calculatePath(const PlanningResult& planner, const core::Pose& goal)
182 {
183 return impl_.calculatePath(planner, goal);
184 }
185
186 // SPFAImpl
187
189 const core::GeneralConfig& generalParams,
190 const std::optional<navigation::algorithms::Costmap>& costmap) :
191 params_(params), generalConfig_(generalParams), costmap_(costmap)
192 {
193 }
194
195 void
196 SPFAImpl::updateCostmap(const std::optional<navigation::algorithms::Costmap>& costmap)
197 {
198 if (costmap.has_value())
199 {
200 costmap_.emplace(costmap.value());
201 }
202 else
203 {
204 costmap_.reset();
205 }
206 }
207
208 std::vector<float>
209 SPFAImpl::computeObstacleAwareVelocities(const core::Positions& positions) const
210 {
212 const float defaultVelocity = generalConfig_.maxVel.linear;
213 const auto& spfaParams = params_.algo;
214
215 const auto maxVelocityBasedOnObstacles = [&](const core::Position& position) -> float
216 {
217 const auto minDistanceToObstaclesOpt =
218 costmap_->value(Eigen::Vector2f{position.head<2>()});
219
220 if (not minDistanceToObstaclesOpt.has_value())
221 {
222 return defaultVelocity;
223 }
224
225 const float clippedObstacleDistance =
226 std::min(minDistanceToObstaclesOpt.value(), spfaParams.obstacleMaxDistance);
227
228 const float ds =
229 std::pow(1.F - clippedObstacleDistance / spfaParams.obstacleMaxDistance,
230 spfaParams.obstacleCostExponent);
231
232 const float obstacleFactor = 1.F / (1.F + spfaParams.obstacleDistanceWeight * ds);
233
234 return defaultVelocity * obstacleFactor;
235 };
236
237 return positions | ranges::views::transform(maxVelocityBasedOnObstacles) |
238 ranges::to_vector;
239 }
240
241 std::optional<GlobalPlannerResult>
242 SPFAImpl::plan(const core::Pose& start, const core::Pose& goal)
243 {
244 const Eigen::Vector2f startPos2D = conv::to2D(start.translation());
245
246 // Check if start is in collision
247 if (costmap_->isInCollision(startPos2D))
248 {
249 ARMARX_WARNING << "Start position " << startPos2D << " is in collision. "
250 << "Searching for recovery position within "
251 << generalConfig_.inCollisionDistanceThresholdForRecovery << " mm...";
252
253 const auto recoveryVertex = costmap_->findClosestCollisionFreeVertex(
254 startPos2D, generalConfig_.inCollisionDistanceThresholdForRecovery);
255
256 if (!recoveryVertex)
257 {
258 ARMARX_ERROR << "No valid recovery position found within threshold of "
259 << generalConfig_.inCollisionDistanceThresholdForRecovery << " mm";
260 return std::nullopt;
261 }
262
263 const Eigen::Vector2f recoveryPos = recoveryVertex->position;
264
265 ARMARX_WARNING << "Found recovery position at " << recoveryPos
266 << " (distance: " << (recoveryPos - startPos2D).norm() << " mm). "
267 << "Prepending original start position to trajectory.";
268
269 const auto planningResult = executePlannerFromPosition(recoveryPos);
270
271 if (!planningResult.plan.has_value())
272 {
273 return std::nullopt;
274 }
275
276 const RecoveryInfo recoveryInfo{start, recoveryPos};
277
278 auto result = calculatePath(planningResult, goal, recoveryInfo);
279
280 if (!result && generalConfig_.navigateCloseAsPossible)
281 {
282 const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
284 planningResult.plan.value(), goalPos, costmap_.value());
285 if (closest)
286 {
287 ARMARX_WARNING << "Goal " << goalPos << " is not reachable. "
288 << "Navigating to closest reachable position at "
289 << closest->position
290 << " (distance to goal: " << closest->euclideanDistanceToGoal
291 << " mm)";
292 core::Pose alternativeGoal = goal;
293 alternativeGoal.translation().head<2>() = closest->position;
294 result = calculatePath(planningResult, alternativeGoal, recoveryInfo);
295 }
296 }
297
298 return result;
299 }
300
301 // Normal case: start is valid
302 const auto planningResult = executePlanner(start);
303 auto result = calculatePath(planningResult, goal);
304
305 if (!result && generalConfig_.navigateCloseAsPossible && planningResult.plan.has_value())
306 {
307 const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
309 planningResult.plan.value(), goalPos, costmap_.value());
310 if (closest)
311 {
312 ARMARX_WARNING << "Goal " << goalPos << " is not reachable. "
313 << "Navigating to closest reachable position at "
314 << closest->position
315 << " (distance to goal: " << closest->euclideanDistanceToGoal
316 << " mm)";
317 core::Pose alternativeGoal = goal;
318 alternativeGoal.translation().head<2>() = closest->position;
319 result = calculatePath(planningResult, alternativeGoal);
320 }
321 }
322
323 return result;
324 }
325
328 {
330
331 const Eigen::Vector2f startPosition = conv::to2D(start.translation());
332
333 // FIXME check if costmap is available
334 ARMARX_CHECK(costmap_.has_value());
335
337
338 PlanningResult result{
339 .start = start, // Preserve full pose including orientation
340 .algorithm =
341 algorithms::spfa::ShortestPathFasterAlgorithm(costmap_.value(), spfaParams),
342 .plan = std::nullopt,
343 };
344
345 const auto timeStart = IceUtil::Time::now();
346
348 try
349 {
350 result.plan = result.algorithm.spfa(startPosition, false);
351 }
352 catch (...)
353 {
354 ARMARX_INFO << "Could not execute spfa from " << "(" << startPosition.x() << ","
355 << startPosition.y() << ")" << " due to exception "
357 }
358
359 const auto timeEnd = IceUtil::Time::now();
360
361 ARMARX_VERBOSE << "SPFA execution time: " << (timeEnd - timeStart).toMilliSeconds()
362 << " ms";
363
364 return result;
365 }
366
368 SPFAImpl::executePlannerFromPosition(const Eigen::Vector2f& startPosition)
369 {
370 // Create a pose with identity orientation for backward compatibility
371 const core::Pose startPose(Eigen::Translation3f(conv::to3D(startPosition)));
372 return executePlanner(startPose);
373 }
374
375 std::optional<GlobalPlannerResult>
377 const core::Pose& goal,
378 const std::optional<RecoveryInfo>& recovery)
379 {
380 PipelineTimings timings;
381
382 if (not planner.plan.has_value())
383 {
384 ARMARX_INFO << "Invalid spfa result, could not calculate path!";
385 return std::nullopt;
386 }
387
388 const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
389
390 // Determine effective start position
391 Eigen::Vector2f effectiveStartPos;
392 if (recovery.has_value())
393 {
394 effectiveStartPos = recovery->recoveryPosition;
395 }
396 else
397 {
398 effectiveStartPos = conv::to2D(planner.start.translation());
399 }
400
402 try
403 {
404 plan =
405 planner.algorithm.constructPath(effectiveStartPos, planner.plan->parents, goalPos);
407 }
408 catch (...)
409 {
410 ARMARX_INFO << "Could not plan collision-free path from"
411 << (recovery ? recovery->recoveryPosition
412 : conv::to2D(planner.start.translation()))
413 << " to " << "(" << goal.translation().x() << "," << goal.translation().y()
414 << ")" << " due to exception " << GetHandledExceptionString();
415
416 return std::nullopt;
417 }
418
419 // Prepend original start position if recovery was used
420 if (recovery.has_value())
421 {
422 plan.path.insert(plan.path.begin(),
423 conv::to2D(recovery->originalStartPose.translation()));
424 ARMARX_INFO << "Prepended original start position. Path now has " << plan.path.size()
425 << " points.";
426 }
427
428 ARMARX_VERBOSE << "Path contains " << plan.path.size() << " points";
429
430 ARMARX_DEBUG << "The plan consists of the following positions:";
431 for (const auto& position : plan.path)
432 {
433 ARMARX_DEBUG << position;
434 }
435
437 const auto plan3d = conv::to3D(plan.path);
438
439 std::vector<core::Position> wpts;
440 // when the position is already reached (but not the orientation) the planned path is empty
441 if (plan3d.size() >= 2)
442 {
443 for (size_t i = 1; i < (plan3d.size() - 1); i++)
444 {
445 wpts.push_back(plan3d.at(i));
446 }
447 }
448
449 // ARMARX_TRACE;
450 // auto smoothPlan = postProcessPath(plan.path);
451 // ARMARX_IMPORTANT << "Smooth path contains " << smoothPlan.size() << " points";
452
453 // ARMARX_TRACE;
454 // // we need to strip the first and the last points from the plan as they encode the start and goal position
455 // smoothPlan.erase(smoothPlan.begin());
456 // smoothPlan.pop_back();
457
459
460 // Compute velocities for all positions
461 // For recovery case: includes collision start (which is planner.start) and recovery position (which is wpts[0])
462 core::Positions positionsForInitialVelocities;
463 positionsForInitialVelocities.reserve(wpts.size() + 2);
464
465 // For recovery case: use the collision start pose from recoveryInfo
466 // For normal case: use planner.start
467 const core::Position startPosition = recovery.has_value()
468 ? recovery->originalStartPose.translation()
469 : planner.start.translation();
470
471 positionsForInitialVelocities.emplace_back(startPosition);
472 positionsForInitialVelocities.insert(
473 positionsForInitialVelocities.end(), wpts.begin(), wpts.end());
474 positionsForInitialVelocities.emplace_back(goal.translation());
475
476 const std::vector<float> velocitiesRespectingObstacles =
477 computeObstacleAwareVelocities(positionsForInitialVelocities);
478
480
481 // Build trajectory normally (same for both recovery and non-recovery cases)
482 // Use the collision start pose for recovery case, planner.start for normal case
483 const core::Pose& trajectoryStart =
484 recovery.has_value() ? recovery->originalStartPose : planner.start;
485
487 {
488 ScopedStageTimer timer(timings.buildTrajectory);
490 trajectoryStart, wpts, goal, velocitiesRespectingObstacles);
491 }
492
493 // TODO(fabian.reister): resampling of trajectory
494
495 std::optional<core::GlobalTrajectory> resampledTrajectory;
496
497 {
498 ScopedStageTimer timer(timings.resample);
499 try
500 {
501 resampledTrajectory = trajectory.resample(200);
502 ARMARX_DEBUG << "Terminal velocity: " << resampledTrajectory->points().back().velocity;
503 }
504 catch (...)
505 {
506 ARMARX_INFO << "Caught exception during resampling: " << GetHandledExceptionString();
507 resampledTrajectory = trajectory;
508 }
509
510 ARMARX_VERBOSE << "Resampled trajectory contains " << resampledTrajectory->points().size()
511 << " points";
512
513 resampledTrajectory->setMaxVelocity(generalConfig_.maxVel.linear);
514 ARMARX_DEBUG << "Terminal velocity: " << resampledTrajectory->points().back().velocity;
515 }
516
517 if (resampledTrajectory->points().size() == 2)
518 {
519 ARMARX_VERBOSE << "Only start and goal provided. Not optimizing orientation";
521 ARMARX_INFO << formatTimings(timings);
522 return GlobalPlannerResult{.trajectory = resampledTrajectory.value(),
523 .helperTrajectory = std::nullopt};
524 }
525
526 // Smooth the resampled trajectory using the 2-D distance-to-obstacle costmap.
527 // Theta is not optimized here; orientations are computed afterwards by the
528 // OrientationOptimizer.
529 {
530 ScopedStageTimer timer(timings.smoothPositions);
532 const auto smoothingParams =
535 resampledTrajectory.value(), costmap_.value(), smoothingParams);
536 const auto smoothingResult = smoother.optimize();
537
538 if (smoothingResult.trajectory && smoothingResult.isCollisionFree)
539 {
540 resampledTrajectory = smoothingResult.trajectory.value();
541 ARMARX_INFO << "SPFA position smoothing succeeded.";
542 }
543 else
544 {
545 ARMARX_WARNING << "SPFA position smoothing did not produce a collision-free "
546 "result; using original resampled SPFA path.";
547 }
548 }
549
550 // Recompute velocities based on the (possibly smoothed) positions so that obstacle
551 // proximity is reflected correctly after the path has been deformed.
552 {
553 ScopedStageTimer timer(timings.recomputeVelocities);
555 core::Positions smoothedPositions;
556 smoothedPositions.reserve(resampledTrajectory->points().size());
557 for (const auto& point : resampledTrajectory->points())
558 {
559 smoothedPositions.emplace_back(point.waypoint.pose.translation());
560 }
561
562 const std::vector<float> recomputedVelocities =
563 computeObstacleAwareVelocities(smoothedPositions);
564
565 ARMARX_CHECK(recomputedVelocities.size() == resampledTrajectory->points().size());
566
567 auto& mutablePoints = resampledTrajectory->mutablePoints();
568 for (size_t i = 0; i < mutablePoints.size(); ++i)
569 {
570 mutablePoints[i].velocity = recomputedVelocities[i];
571 }
572 }
573
574 // Compute recovery distance and find sub-trajectory start index
575 size_t subTrajectoryStartIndex = 0;
576 std::optional<core::GlobalTrajectory> trajectoryToOptimize;
577 float recoveryDistance = 0.0f;
578 {
579 ScopedStageTimer timer(timings.recoveryHandling);
580 const auto computeRecoveryDistance = [&]() -> float
581 {
582 if (!recovery.has_value())
583 return 0.0f;
584 return (recovery->recoveryPosition -
585 recovery->originalStartPose.translation().head<2>())
586 .norm();
587 };
588 recoveryDistance = computeRecoveryDistance();
589
590 // Find first point outside recovery distance (for sub-trajectory extraction)
591 if (recoveryDistance > 0)
592 {
593 auto& pts = resampledTrajectory->mutablePoints();
594 const auto startOrientation = pts.front().waypoint.pose.linear();
595
596 // Fix orientations for all points within recovery distance (collision segment)
597 for (size_t i = 0; i < pts.size(); i++)
598 {
599 const float dist =
600 (pts[i].waypoint.pose.translation() - pts.front().waypoint.pose.translation())
601 .norm();
602 if (dist <= recoveryDistance)
603 {
604 pts[i].waypoint.pose.linear() = startOrientation;
605 }
606 else
607 {
608 // Found first point outside collision - fix it for smooth transition
609 subTrajectoryStartIndex = i;
610 if (subTrajectoryStartIndex < pts.size())
611 {
612 pts[subTrajectoryStartIndex].waypoint.pose.linear() = startOrientation;
613 }
614 break;
615 }
616 }
617 ARMARX_INFO << "Recovery distance: " << recoveryDistance << " mm, fixed "
618 << subTrajectoryStartIndex
619 << " collision segment points, sub-trajectory starts at index "
620 << subTrajectoryStartIndex;
621 }
622
623 // Extract sub-trajectory for optimization (full trajectory if no recovery)
624 if (subTrajectoryStartIndex > 0)
625 {
626 trajectoryToOptimize = resampledTrajectory->getSubTrajectory(
627 subTrajectoryStartIndex, resampledTrajectory->points().size());
628 }
629 else
630 {
631 trajectoryToOptimize = resampledTrajectory;
632 }
633 }
634
636 {
637 ScopedStageTimer timer(timings.loadOrientationConfig);
638 const armarx::PackagePath pp("armarx_navigation",
639 "config/global_planning/OrientationOptimizer.json");
640 const std::string filename = pp.toSystemPath();
641
642 ARMARX_CHECK(std::filesystem::exists(filename))
643 << "OrientationOptimizer config file does not exist: " << filename;
644
645 ARMARX_INFO << "Loading config from file `" << filename << "`.";
646 std::ifstream ifs{filename};
647
648 nlohmann::json jsonConfig;
649 ifs >> jsonConfig;
650
651 ARMARX_VERBOSE << "Initializing config";
652
653
655
656 armarx::navigation::global_planning::arondto::OrientationOptimizerParams dto;
657
658 ARMARX_VERBOSE << "reading file.";
659 dto.read(reader, jsonConfig);
660
661 aron_conv::fromAron(dto, params_.optimizerParams);
662 }
663
664 OrientationOptimizer optimizer(trajectoryToOptimize.value(), params_.optimizerParams);
665 auto result = [&]() {
666 ScopedStageTimer timer(timings.optimizeOrientation);
667 return optimizer.optimize();
668 }();
669
670 if (not result)
671 {
672 ARMARX_ERROR << "Optimizer failure";
673 return std::nullopt;
674 }
675
676 // Combine collision segment (fixed) with optimized sub-trajectory
677 core::GlobalTrajectory finalTrajectory = result.trajectory.value();
678
679 {
680 ScopedStageTimer timer(timings.stitchTrajectory);
681 if (recoveryDistance > 0 && subTrajectoryStartIndex > 0)
682 {
683 // Stitch: fixed collision segment + optimized post-collision segment
684 auto& resampledPts = resampledTrajectory->mutablePoints();
685 const auto& optimizedPts = result.trajectory->points();
686
687 // Verify sizes match
688 if (subTrajectoryStartIndex + optimizedPts.size() == resampledPts.size())
689 {
690 // Copy optimized orientations and velocities to the resampled trajectory
691 for (size_t i = 0; i < optimizedPts.size(); i++)
692 {
693 resampledPts[subTrajectoryStartIndex + i].waypoint.pose.linear() =
694 optimizedPts[i].waypoint.pose.linear();
695 resampledPts[subTrajectoryStartIndex + i].velocity = optimizedPts[i].velocity;
696 }
697
698 // Use the resampled trajectory (with fixed collision segment + optimized post-collision)
699 finalTrajectory = resampledTrajectory.value();
700
701 ARMARX_INFO << "Combined fixed collision segment (" << subTrajectoryStartIndex
702 << " points) with optimized trajectory (" << optimizedPts.size()
703 << " points)";
704 }
705 else
706 {
707 ARMARX_WARNING << "Trajectory size mismatch in collision recovery stitching. "
708 << "Using optimized trajectory only.";
709 }
710 }
711 }
712
713 // TODO circular path smoothing should be done now
714
715 // algorithm::CircularPathSmoothing smoothing;
716 // auto smoothTrajectory = smoothing.smooth(result.trajectory.value());
717 // smoothTrajectory.setMaxVelocity(params.linearVelocity);
718
719 ARMARX_CHECK(costmap_.has_value());
720 const auto& costmap = costmap_.value();
721
722 {
723 ScopedStageTimer timer(timings.finalVelocityClamp);
724 for (auto& point : finalTrajectory.mutablePoints())
725 {
726 const float distance = std::min<float>(
727 spfaParams.obstacleMaxDistance,
728 costmap.value(Eigen::Vector2f{point.waypoint.pose.translation().head<2>()})
729 .value_or(0.F));
730
731 if (spfaParams.obstacleDistanceCosts)
732 {
733 const float obstacleBasedVelocity =
734 generalConfig_.maxVel.linear /
735 (1.F + spfaParams.obstacleDistanceWeight *
736 std::pow(1 - distance / spfaParams.obstacleMaxDistance,
737 spfaParams.obstacleCostExponent));
738
739 // only reduce velocity
740 point.velocity = std::min(obstacleBasedVelocity, point.velocity);
741 }
742 }
743 }
744
745
747 ARMARX_DEBUG << "Terminal velocity: " << finalTrajectory.points().back().velocity;
748 ARMARX_INFO << formatTimings(timings);
749 return GlobalPlannerResult{.trajectory = finalTrajectory, .helperTrajectory = std::nullopt};
750 }
751
752 std::vector<Eigen::Vector2f>
753 SPFAImpl::postProcessPath(const std::vector<Eigen::Vector2f>& path)
754 {
755 /// chain approximation
757 path, algorithm::ChainApproximation::Params{.distanceTh = 200.F});
758 approx.approximate();
759 const auto p = approx.approximatedChain();
760
761 // visualizePath(p, "approximated", simox::Color::green());
762
763 // algo::CircularPathSmoothing smoothing;
764 // const auto points = smoothing.smooth(p);
765
766 return p;
767 }
768
769} // namespace armarx::navigation::global_planning
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
PlanningResult constructPath(const Eigen::Vector2f &start, const std::vector< std::vector< Eigen::Vector2i > > &spfaParents, const Eigen::Vector2f &goal) const
PlanningResult plan(const Eigen::Vector2f &start, const Eigen::Vector2f &goal, bool checkStartForCollision=true) const
const std::vector< GlobalTrajectoryPoint > & points() const
std::vector< GlobalTrajectoryPoint > & mutablePoints()
static GlobalTrajectory FromPath(const Path &path, float velocity)
Note: the velocity will not be set!
GlobalPlanner(const core::GeneralConfig &generalConfig, const core::Scene &scene)
::armarx::navigation::global_planning::PlanningResult PlanningResult
Definition SPFA.h:89
void updateCostmap(const std::optional< navigation::algorithms::Costmap > &costmap)
Definition SPFA.cpp:196
std::optional< GlobalPlannerResult > plan(const core::Pose &start, const core::Pose &goal)
Definition SPFA.cpp:242
SPFAImpl(const Params &params, const core::GeneralConfig &generalParams, const std::optional< navigation::algorithms::Costmap > &costmap)
Definition SPFA.cpp:188
PlanningResult executePlannerFromPosition(const Eigen::Vector2f &startPosition)
Definition SPFA.cpp:368
PlanningResult executePlanner(const core::Pose &start)
Definition SPFA.cpp:327
std::vector< Eigen::Vector2f > postProcessPath(const std::vector< Eigen::Vector2f > &path)
Definition SPFA.cpp:753
std::optional< GlobalPlannerResult > calculatePath(const PlanningResult &planner, const core::Pose &goal, const std::optional< RecoveryInfo > &recovery=std::nullopt)
Definition SPFA.cpp:376
::armarx::navigation::global_planning::PlanningResult PlanningResult
Definition SPFA.h:128
std::optional< GlobalPlannerResult > calculatePath(const PlanningResult &planner, const core::Pose &goal)
Definition SPFA.cpp:181
std::optional< GlobalPlannerResult > plan(const core::Pose &goal) override
Definition SPFA.cpp:158
PlanningResult executePlanner(const core::Pose &start)
Definition SPFA.cpp:175
SPFA(const Params &params, const core::GeneralConfig &generalParams, const core::Scene &ctx)
Definition SPFA.cpp:146
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
SmoothingParams loadSmoothingParams(const std::string &filePath)
Definition io.cpp:29
std::optional< ShortestPathFasterAlgorithm::ClosestReachableResult > findClosestReachablePosition(const ShortestPathFasterAlgorithm::Result &spfaResult, const Eigen::Vector2f &goal, const Costmap &costmap)
std::vector< Eigen::Vector2f > to2D(const std::vector< Eigen::Vector3f > &v)
Definition eigen.cpp:29
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition eigen.cpp:14
std::vector< Position > Positions
Definition basic_types.h:37
Eigen::Isometry3f Pose
Definition basic_types.h:31
Eigen::Vector3f Position
Definition basic_types.h:36
void toAron(arondto::GlobalPlannerParams &dto, const GlobalPlannerParams &bo)
void fromAron(const arondto::GlobalPlannerParams &dto, GlobalPlannerParams &bo)
This file is part of ArmarX.
Definition fwd.h:30
std::string GetHandledExceptionString()
double norm(const Point &a)
Definition point.hpp:102
double distance(const Point &a, const Point &b)
Definition point.hpp:95
algorithms::spfa::ShortestPathFasterAlgorithm algorithm
Definition SPFA.h:66
std::optional< algorithms::spfa::ShortestPathFasterAlgorithm::Result > plan
Definition SPFA.h:67
Information about collision recovery.
Definition SPFA.h:77
algorithms::spfa::ShortestPathFasterAlgorithm::Parameters algo
Definition SPFA.h:52
aron::data::DictPtr toAron() const override
Definition SPFA.cpp:119
static SPFAParams FromAron(const aron::data::DictPtr &dict)
Definition SPFA.cpp:129
Algorithms algorithm() const override
Definition SPFA.cpp:113
#define ARMARX_TRACE
Definition trace.h:77