SPFA.cpp
Go to the documentation of this file.
1 #include "SPFA.h"
2 
3 #include <algorithm>
4 #include <iterator>
5 #include <mutex>
6 #include <optional>
7 
8 #include <Eigen/Geometry>
9 
10 #include <VirtualRobot/Robot.h>
11 #include <VirtualRobot/RobotNodeSet.h>
12 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
13 
17 
20 
29 #include <armarx/navigation/global_planning/aron/SPFAParams.aron.generated.h>
33 
34 #include <range/v3/range/conversion.hpp>
35 #include <range/v3/view/transform.hpp>
36 
38 {
39 
40  // SPFAParams
41 
44  {
45  return Algorithms::SPFA;
46  }
47 
50  {
51  arondto::SPFAParams dto;
52 
53  aron_conv::toAron(dto, *this);
54 
55  return dto.toAron();
56  }
57 
60  {
62 
63  // ARMARX_DEBUG << dict->getAllKeysAsString();
64 
65  arondto::SPFAParams dto;
66  dto.fromAron(dict);
67 
68  SPFAParams bo;
69  aron_conv::fromAron(dto, bo);
70 
71  return bo;
72  }
73 
74  // SPFA
75 
76  SPFA::SPFA(const SPFAParams& params, const core::Scene& ctx) :
77  GlobalPlanner(ctx), params_(params)
78  {
79  }
80 
81  std::optional<GlobalPlannerResult>
82  SPFA::plan(const core::Pose& goal)
83  {
84  const core::Pose start(scene.robot->getGlobalPose());
85  return plan(start, goal);
86  }
87 
88  std::optional<GlobalPlannerResult>
89  SPFA::plan(const core::Pose& start, const core::Pose& goal)
90  {
92 
93  // FIXME check if costmap is available
94 
96 
97  ARMARX_CHECK(scene.staticScene.has_value());
98  ARMARX_CHECK(scene.staticScene->distanceToObstaclesCostmap.has_value());
100  *scene.staticScene->distanceToObstaclesCostmap, spfaParams);
101 
102  const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
103 
104  const auto timeStart = IceUtil::Time::now();
105 
107  try
108  {
109  plan = planner.plan(conv::to2D(start.translation()), goalPos);
111  }
112  catch (...)
113  {
114  ARMARX_INFO << "Could not plan collision-free path from"
115  << "(" << start.translation().x() << "," << start.translation().y() << ")"
116  << " to "
117  << "(" << goal.translation().x() << "," << goal.translation().y() << ")"
118  << " due to exception " << GetHandledExceptionString();
119 
120  return std::nullopt;
121  }
122  const auto timeEnd = IceUtil::Time::now();
123 
124  ARMARX_VERBOSE << "A* planning took " << (timeEnd - timeStart).toMilliSeconds() << " ms";
125  ARMARX_VERBOSE << "Path contains " << plan.path.size() << " points";
126 
127  ARMARX_DEBUG << "The plan consists of the following positions:";
128  for (const auto& position : plan.path)
129  {
130  ARMARX_DEBUG << position;
131  }
132 
133  ARMARX_TRACE;
134  const auto plan3d = conv::to3D(plan.path);
135 
136  std::vector<core::Position> wpts;
137  // when the position is already reached (but not the orientation) the planned path is empty
138  if (plan3d.size() >= 2)
139  {
140  for (size_t i = 1; i < (plan3d.size() - 1); i++)
141  {
142  wpts.push_back(plan3d.at(i));
143  }
144  }
145 
146  // ARMARX_TRACE;
147  // auto smoothPlan = postProcessPath(plan.path);
148  // ARMARX_IMPORTANT << "Smooth path contains " << smoothPlan.size() << " points";
149 
150  // ARMARX_TRACE;
151  // // we need to strip the first and the last points from the plan as they encode the start and goal position
152  // smoothPlan.erase(smoothPlan.begin());
153  // smoothPlan.pop_back();
154 
155  const std::vector<float> velocities = [&]()
156  {
157  const float defaultVelocity = params_.linearVelocity;
158 
159  core::Positions positions;
160  positions.reserve(wpts.size() + 2);
161 
162  positions.emplace_back(start.translation());
163  positions.insert(positions.end(), wpts.begin(), wpts.end());
164  positions.emplace_back(goal.translation());
165 
166  const auto maxVelocityBasedOnObstacles = [&](const core::Position& position) -> float
167  {
168  const auto minDistanceToObstaclesOpt =
169  scene.staticScene->distanceToObstaclesCostmap->value(
170  Eigen::Vector2f{position.head<2>()});
171 
172  if (not minDistanceToObstaclesOpt.has_value())
173  {
174  return defaultVelocity;
175  }
176 
177  const float clippedObstacleDistance =
178  std::min(minDistanceToObstaclesOpt.value(), spfaParams.obstacleMaxDistance);
179 
180  const float ds =
181  std::pow(1.F - clippedObstacleDistance / spfaParams.obstacleMaxDistance,
182  spfaParams.obstacleCostExponent);
183 
184  const float obstacleFactor = 1 / (1 + spfaParams.obstacleDistanceWeight * ds);
185 
186  return defaultVelocity * obstacleFactor;
187  };
188 
189  return positions | ranges::views::transform(maxVelocityBasedOnObstacles) |
190  ranges::to_vector;
191  }();
192 
193  ARMARX_TRACE;
194  auto trajectory = core::GlobalTrajectory::FromPath(start, wpts, goal, velocities);
195 
196  // TODO(fabian.reister): resampling of trajectory
197 
198  // FIXME param
199  std::optional<core::GlobalTrajectory> resampledTrajectory;
200 
201  try
202  {
203  // if (params.resampleDistance > 0 or false)
204  // {
205  resampledTrajectory = trajectory.resample(200);
206  // }
207  // else
208  // {
209  // resampledTrajectory = trajectory;
210  // }
211  }
212  catch (...)
213  {
214  ARMARX_INFO << "Caught exception during resampling: " << GetHandledExceptionString();
215  // return std::nullopt;
216  resampledTrajectory = trajectory;
217  }
218 
219  ARMARX_VERBOSE << "Resampled trajectory contains " << resampledTrajectory->points().size()
220  << " points";
221 
222  resampledTrajectory->setMaxVelocity(params_.linearVelocity);
223 
224 
225  // ARMARX_CHECK(resampledTrajectory.hasMaxDistanceBetweenWaypoints(params.resampleDistance));
226 
227  if (resampledTrajectory->points().size() == 2)
228  {
229  ARMARX_INFO << "Only start and goal provided. Not optimizing orientation";
230  ARMARX_TRACE;
231  return GlobalPlannerResult{.trajectory = resampledTrajectory.value()};
232  }
233 
234  ARMARX_TRACE;
235  OrientationOptimizer optimizer(resampledTrajectory.value(), params_.optimizerParams);
236  auto result = optimizer.optimize();
237 
238  if (not result)
239  {
240  ARMARX_ERROR << "Optimizer failure";
241  return std::nullopt;
242  }
243 
244  // TODO circular path smoothing should be done now
245 
246  // algorithm::CircularPathSmoothing smoothing;
247  // auto smoothTrajectory = smoothing.smooth(result.trajectory.value());
248  // smoothTrajectory.setMaxVelocity(params.linearVelocity);
249 
250  ARMARX_CHECK(scene.staticScene->distanceToObstaclesCostmap.has_value());
251  const auto& costmap = scene.staticScene->distanceToObstaclesCostmap.value();
252 
253 
254  for (auto& point : result.trajectory->mutablePoints())
255  {
256  const float distance = std::min<float>(
257  spfaParams.obstacleMaxDistance,
258  costmap.value(Eigen::Vector2f{point.waypoint.pose.translation().head<2>()})
259  .value_or(0.F));
260 
261  if (spfaParams.obstacleDistanceCosts)
262  {
263  point.velocity = params_.linearVelocity /
264  (1.F + spfaParams.obstacleDistanceWeight *
265  std::pow(1 - distance / spfaParams.obstacleMaxDistance,
266  spfaParams.obstacleCostExponent));
267  }
268  }
269 
270 
271  ARMARX_TRACE;
272  return GlobalPlannerResult{.trajectory = result.trajectory.value()};
273  }
274 
275  std::vector<Eigen::Vector2f>
276  SPFA::postProcessPath(const std::vector<Eigen::Vector2f>& path)
277  {
278  /// chain approximation
281  approx.approximate();
282  const auto p = approx.approximatedChain();
283 
284  // visualizePath(p, "approximated", simox::Color::green());
285 
286  // algo::CircularPathSmoothing smoothing;
287  // const auto points = smoothing.smooth(p);
288 
289  return p;
290  }
291 
292 
293 } // namespace armarx::navigation::global_planning
ChainApproximation.h
armarx::navigation::core::Scene::robot
VirtualRobot::RobotPtr robot
Definition: types.h:78
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::Parameters
Definition: ShortestPathFasterAlgorithm.h:36
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
SPFA.h
armarx::navigation::core::Scene::staticScene
std::optional< core::StaticScene > staticScene
Definition: types.h:75
aron_conversions.h
LocalException.h
armarx::navigation::algorithm::detail::ChainApproximationParams
Definition: ChainApproximation.h:32
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
basic_types.h
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
OrientationOptimizer.h
armarx::navigation::algorithm::ChainApproximation::approximate
ApproximationResult approximate()
Definition: ChainApproximation.cpp:27
armarx::navigation::global_planning::GlobalPlannerResult::trajectory
core::GlobalTrajectory trajectory
Definition: GlobalPlanner.h:40
armarx::navigation::global_planning::optimization::OrientationOptimizer::optimize
OptimizationResult optimize()
Definition: OrientationOptimizer.cpp:41
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::Parameters::obstacleDistanceWeight
float obstacleDistanceWeight
Definition: ShortestPathFasterAlgorithm.h:41
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::PlanningResult
Definition: ShortestPathFasterAlgorithm.h:62
armarx::navigation::global_planning::SPFA::postProcessPath
std::vector< Eigen::Vector2f > postProcessPath(const std::vector< Eigen::Vector2f > &path)
Definition: SPFA.cpp:276
armarx::navigation::global_planning::GlobalPlanner::scene
const core::Scene & scene
Definition: GlobalPlanner.h:75
armarx::navigation::global_planning::SPFA::SPFA
SPFA(const Params &params, const core::Scene &ctx)
Definition: SPFA.cpp:76
constants.h
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::Parameters::obstacleMaxDistance
float obstacleMaxDistance
Definition: ShortestPathFasterAlgorithm.h:39
Dict.h
armarx::navigation::global_planning::SPFAParams::optimizerParams
optimization::OrientationOptimizerParams optimizerParams
Definition: SPFA.h:55
armarx::navigation::global_planning::aron_conv::toAron
void toAron(arondto::GlobalPlannerParams &dto, const GlobalPlannerParams &bo)
Definition: aron_conversions.cpp:23
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
ShortestPathFasterAlgorithm.h
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:147
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
CircularPathSmoothing.h
armarx::navigation::global_planning::aron_conv::fromAron
void fromAron(const arondto::GlobalPlannerParams &dto, GlobalPlannerParams &bo)
Definition: aron_conversions.cpp:28
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::plan
PlanningResult plan(const Eigen::Vector2f &start, const Eigen::Vector2f &goal, bool checkStartForCollision=true) const
Definition: ShortestPathFasterAlgorithm.cpp:67
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::Parameters::obstacleCostExponent
float obstacleCostExponent
Definition: ShortestPathFasterAlgorithm.h:42
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::navigation::global_planning::SPFAParams::algorithm
Algorithms algorithm() const override
Definition: SPFA.cpp:43
armarx::navigation::algorithm::ChainApproximation
Definition: ChainApproximation.h:56
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm::Parameters::obstacleDistanceCosts
bool obstacleDistanceCosts
Definition: ShortestPathFasterAlgorithm.h:38
armarx::navigation::core::GlobalTrajectory::FromPath
static GlobalTrajectory FromPath(const Path &path, float velocity)
Note: the velocity will not be set!
Definition: Trajectory.cpp:359
GlobalPlanner.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::navigation::global_planning::GlobalPlannerResult
Definition: GlobalPlanner.h:38
armarx::navigation::global_planning::SPFAParams::algo
algorithms::spfa::ShortestPathFasterAlgorithm::Parameters algo
Definition: SPFA.h:53
armarx::navigation::core::Scene
Definition: types.h:71
armarx::navigation::conv::to2D
std::vector< Eigen::Vector2f > to2D(const std::vector< Eigen::Vector3f > &v)
Definition: eigen.cpp:26
ExpressionException.h
armarx::navigation::global_planning::GlobalPlanner
Definition: GlobalPlanner.h:64
armarx::navigation::algorithm::detail::ChainApproximationParams::distanceTh
float distanceTh
Definition: ChainApproximation.h:34
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::navigation::core::Positions
std::vector< Position > Positions
Definition: basic_types.h:37
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::navigation::global_planning::SPFAParams::toAron
aron::data::DictPtr toAron() const override
Definition: SPFA.cpp:49
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:315
F
Definition: ExportDialogControllerTest.cpp:16
armarx::navigation::global_planning::SPFAParams::linearVelocity
float linearVelocity
Definition: SPFA.h:43
armarx::navigation::conv::to3D
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition: eigen.cpp:11
armarx::navigation::global_planning::Algorithms::SPFA
@ SPFA
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
armarx::navigation::global_planning::SPFAParams::FromAron
static SPFAParams FromAron(const aron::data::DictPtr &dict)
Definition: SPFA.cpp:59
core.h
armarx::navigation::global_planning::SPFA::plan
std::optional< GlobalPlannerResult > plan(const core::Pose &goal) override
Definition: SPFA.cpp:82
eigen.h
Logging.h
armarx::navigation::global_planning::Algorithms
Algorithms
Definition: core.h:38
armarx::navigation::core::Position
Eigen::Vector3f Position
Definition: basic_types.h:36
min
T min(T t1, T t2)
Definition: gdiam.h:42
armarx::navigation::algorithms::spfa::ShortestPathFasterAlgorithm
Definition: ShortestPathFasterAlgorithm.h:33
Trajectory.h
String.h
armarx::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:168
armarx::navigation::global_planning::SPFAParams
Parameters for AStar.
Definition: SPFA.h:41
armarx::navigation::global_planning
This file is part of ArmarX.
Definition: fwd.h:29
armarx::navigation::global_planning::optimization::OrientationOptimizer
Definition: OrientationOptimizer.h:54