AStar.cpp
Go to the documentation of this file.
1 #include "AStar.h"
2 
3 #include <algorithm>
4 #include <mutex>
5 #include <optional>
6 
7 #include <Eigen/Geometry>
8 
9 #include <VirtualRobot/RobotNodeSet.h>
10 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
11 
15 
18 
26 #include <armarx/navigation/global_planning/aron/AStarParams.aron.generated.h>
30 
31 
33 {
34 
35  // AStarParams
36 
39  {
40  return Algorithms::AStar;
41  }
42 
45  {
46  arondto::AStarParams dto;
47 
49  aron_conv::toAron(dto, bo);
50 
51  return dto.toAron();
52  }
53 
56  {
58 
59  // ARMARX_DEBUG << dict->getAllKeysAsString();
60 
61  arondto::AStarParams dto;
62  dto.fromAron(dict);
63 
65  aron_conv::fromAron(dto, bo);
66 
67  return bo;
68  }
69 
70  // AStar
71 
72  AStar::AStar(const AStarParams& params, const core::Scene& ctx) :
73  GlobalPlanner(ctx), params(params)
74  {
75  }
76 
77  // auto
78  // robotCollisionModel()
79  // {
80 
81  // constexpr float platformHeight = 600;
82  // constexpr float bodyHeight = 1400;
83  // constexpr float fullHeight = platformHeight + bodyHeight;
84 
85  // constexpr float platformRadius = 600.F;
86  // constexpr float bodyRadius = 300.F;
87  // constexpr float simpleRadius = std::max(platformRadius, bodyRadius);
88 
89  // // combined model made out of two stacked cylinders.
90  // [[maybe_unused]] const auto createCombinedVisuModel = []()
91  // {
92  // VirtualRobot::CoinVisualizationFactory factory;
93 
94  // auto cylinderPlatform = factory.createCylinder(platformRadius, platformHeight);
95  // factory.applyDisplacement(
96  // cylinderPlatform,
97  // core::Pose(Eigen::Translation3f{platformHeight / 2 * Eigen::Vector3f::UnitY()})
98  // .matrix());
99 
100  // auto cylinderBody = factory.createCylinder(bodyRadius, bodyHeight);
101  // factory.applyDisplacement(
102  // cylinderPlatform,
103  // core::Pose(Eigen::Translation3f{(bodyHeight / 2 + platformHeight) *
104  // Eigen::Vector3f::UnitY()})
105  // .matrix());
106 
107 
108  // return factory.createUnitedVisualization({cylinderPlatform, cylinderBody});
109  // };
110 
111  // // simple model made of one cylinder only
112  // const auto createSimpleVisuModel = []()
113  // {
114  // VirtualRobot::CoinVisualizationFactory factory;
115 
116  // auto cylinderPlatform = factory.createCylinder(simpleRadius, fullHeight);
117  // factory.applyDisplacement(
118  // cylinderPlatform,
119  // core::Pose(Eigen::Translation3f{fullHeight / 2 * Eigen::Vector3f::UnitY()})
120  // .matrix());
121 
122  // return cylinderPlatform;
123  // };
124 
125  // const auto visuModel = createSimpleVisuModel();
126 
127  // VirtualRobot::CollisionModelPtr collisionModel(new VirtualRobot::CollisionModel(visuModel));
128 
129  // return collisionModel;
130  // }
131 
132  std::vector<Eigen::Vector2f>
133  AStar::postProcessPath(const std::vector<Eigen::Vector2f>& path)
134  {
135  /// chain approximation
138  approx.approximate();
139  const auto p = approx.approximatedChain();
140 
141  // visualizePath(p, "approximated", simox::Color::green());
142 
143  // algo::CircularPathSmoothing smoothing;
144  // const auto points = smoothing.smooth(p);
145 
146  return p;
147  }
148 
149  std::optional<GlobalPlannerResult>
150  AStar::plan(const core::Pose& goal)
151  {
152  const core::Pose start(scene.robot->getGlobalPose());
153  return plan(start, goal);
154  }
155 
156  std::optional<GlobalPlannerResult>
157  AStar::plan(const core::Pose& start, const core::Pose& goal)
158  {
159  ARMARX_TRACE;
160 
161  // FIXME check if costmap is available
162  algorithm::astar::AStarPlanner planner(*scene.staticScene->distanceToObstaclesCostmap);
163 
164  const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
165 
166  const auto timeStart = IceUtil::Time::now();
167 
168  std::vector<Eigen::Vector2f> plan;
169  try
170  {
171  plan = planner.plan(conv::to2D(start.translation()), goalPos);
172  }
173  catch (...)
174  {
175  ARMARX_INFO << "Could not plan collision-free path from"
176  << "(" << start.translation().x() << "," << start.translation().y() << ")"
177  << " to "
178  << "(" << goal.translation().x() << "," << goal.translation().y() << ")"
179  << " due to exception " << GetHandledExceptionString();
180 
181  return std::nullopt;
182  }
183  const auto timeEnd = IceUtil::Time::now();
184 
185  ARMARX_IMPORTANT << "A* planning took " << (timeEnd - timeStart).toMilliSeconds() << " ms";
186  ARMARX_IMPORTANT << "Path contains " << plan.size() << " points";
187 
188  if (plan.size() < 2) // failure
189  {
190  ARMARX_INFO << "Could not plan collision-free path from"
191  << "(" << start.translation().x() << "," << start.translation().y() << ")"
192  << " to "
193  << "(" << goal.translation().x() << "," << goal.translation().y() << ")";
194  return std::nullopt;
195  }
196 
197  ARMARX_DEBUG << "The plan consists of the following positions:";
198  for (const auto& position : plan)
199  {
200  ARMARX_DEBUG << position;
201  }
202 
203  const core::Pose startPose(Eigen::Translation3f(conv::to3D(plan.front())));
204  const core::Pose goalPose(Eigen::Translation3f(conv::to3D(plan.back())));
205 
206  const auto plan3d = conv::to3D(plan);
207 
208  // std::vector<core::Pose> plan3d = plan3dtmp | ranges::views::transform([](const core::Position& p) -> core::Pose{
209  // return core::Pose(Eigen::Translation3f(p));
210  // }) | ranges::to_vector;
211 
212  // auto waypoints =
213  // // plan3d | ranges::views::counted(plan3d.begin(), 2) |
214  // plan3d | ranges::make_subrange(plan3d.begin(), plan3d.end()) |
215  // ranges::to_vector;
216 
217  std::vector<core::Position> wpts;
218  for (size_t i = 1; i < (plan3d.size() - 1); i++)
219  {
220  wpts.push_back(plan3d.at(i));
221  }
222 
223  // TODO remove start and goal and use plan front and back instead
224  // return GlobalPlannerResult{
225  // .trajectory = core::Trajectory::FromPath(
226  // startPose, wpts, goalPose, params.linearVelocity)}; // FIXME remove
227 
228  ARMARX_TRACE;
229  auto smoothPlan = postProcessPath(plan);
230  ARMARX_IMPORTANT << "Smooth path contains " << smoothPlan.size() << " points";
231 
232  ARMARX_TRACE;
233  // we need to strip the first and the last points from the plan as they encode the start and goal position
234  smoothPlan.erase(smoothPlan.begin());
235  smoothPlan.pop_back();
236 
237  ARMARX_TRACE;
238  auto trajectory = core::GlobalTrajectory::FromPath(
239  start, conv::to3D(smoothPlan), goal, params.linearVelocity);
240 
241  // TODO(fabian.reister): resampling of trajectory
242 
243  // FIXME param
244  std::optional<core::GlobalTrajectory> resampledTrajectory;
245 
246  if (params.resampleDistance < 0)
247  {
248  resampledTrajectory = trajectory;
249  }
250  else
251  {
252  try
253  {
254  resampledTrajectory = trajectory.resample(params.resampleDistance);
255  }
256  catch (...)
257  {
258  ARMARX_INFO << "Caught exception during resampling: "
260  // return std::nullopt;
261  resampledTrajectory = trajectory;
262  }
263  }
264 
265  ARMARX_VERBOSE << "Resampled trajectory contains " << resampledTrajectory->points().size()
266  << " points";
267 
268  resampledTrajectory->setMaxVelocity(params.linearVelocity);
269 
270 
271  // ARMARX_CHECK(resampledTrajectory.hasMaxDistanceBetweenWaypoints(params.resampleDistance));
272 
273  if (resampledTrajectory->points().size() == 2)
274  {
275  ARMARX_INFO << "Only start and goal provided. Not optimizing orientation";
276  ARMARX_TRACE;
277  return GlobalPlannerResult{.trajectory = resampledTrajectory.value()};
278  }
279 
280  ARMARX_TRACE;
281  OrientationOptimizer optimizer(resampledTrajectory.value(), OrientationOptimizer::Params{});
282  const auto result = optimizer.optimize();
283 
284  if (not result)
285  {
286  ARMARX_WARNING << "Optimizer failure";
287  return std::nullopt;
288  }
289 
290  ARMARX_TRACE;
291 
292  // TODO circular path smoothing should be done now
293  // algorithm::CircularPathSmoothing smoothing;
294  // auto smoothTrajectory = smoothing.smooth(result.trajectory.value());
295  // smoothTrajectory.setMaxVelocity(params.linearVelocity);
296 
297  ARMARX_TRACE;
298  return GlobalPlannerResult{.trajectory = result.trajectory.value()};
299  }
300 } // namespace armarx::navigation::global_planning
ChainApproximation.h
armarx::navigation::core::Scene::robot
VirtualRobot::RobotPtr robot
Definition: types.h:78
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::navigation::global_planning::AStarParams
Parameters for AStar.
Definition: AStar.h:35
armarx::navigation::core::Scene::staticScene
std::optional< core::StaticScene > staticScene
Definition: types.h:75
aron_conversions.h
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
LocalException.h
armarx::navigation::algorithm::detail::ChainApproximationParams
Definition: ChainApproximation.h:32
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
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::global_planning::AStar::postProcessPath
std::vector< Eigen::Vector2f > postProcessPath(const std::vector< Eigen::Vector2f > &path)
Definition: AStar.cpp:133
armarx::navigation::global_planning::GlobalPlanner::scene
const core::Scene & scene
Definition: GlobalPlanner.h:75
constants.h
armarx::navigation::global_planning::AStarParams::toAron
aron::data::DictPtr toAron() const override
Definition: AStar.cpp:44
Dict.h
armarx::navigation::global_planning::aron_conv::toAron
void toAron(arondto::GlobalPlannerParams &dto, const GlobalPlannerParams &bo)
Definition: aron_conversions.cpp:23
armarx::navigation::global_planning::AStarParams::resampleDistance
float resampleDistance
Definition: AStar.h:38
armarx::navigation::algorithm::astar::AStarPlanner::plan
std::vector< Eigen::Vector2f > plan(const Eigen::Vector2f &start, const Eigen::Vector2f &goal)
Definition: AStarPlanner.cpp:154
armarx::navigation::global_planning::optimization::OrientationOptimizerParams
Definition: OrientationOptimizer.h:37
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:147
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::navigation::global_planning::AStar::AStar
AStar(const Params &params, const core::Scene &ctx)
Definition: AStar.cpp:72
CircularPathSmoothing.h
armarx::navigation::global_planning::aron_conv::fromAron
void fromAron(const arondto::GlobalPlannerParams &dto, GlobalPlannerParams &bo)
Definition: aron_conversions.cpp:28
armarx::navigation::global_planning::AStar::plan
std::optional< GlobalPlannerResult > plan(const core::Pose &goal) override
Definition: AStar.cpp:150
AStarPlanner.h
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::navigation::global_planning::AStarParams::FromAron
static AStarParams FromAron(const aron::data::DictPtr &dict)
Definition: AStar.cpp:55
armarx::navigation::algorithm::astar::AStarPlanner
The A* planner.
Definition: AStarPlanner.h:17
armarx::navigation::algorithm::ChainApproximation
Definition: ChainApproximation.h:56
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::navigation::global_planning::GlobalPlannerResult
Definition: GlobalPlanner.h:38
armarx::navigation::global_planning::AStarParams::algorithm
Algorithms algorithm() const override
Definition: AStar.cpp:38
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::global_planning::AStarParams::linearVelocity
float linearVelocity
Definition: AStar.h:37
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::navigation::conv::to3D
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition: eigen.cpp:11
core.h
eigen.h
Logging.h
armarx::navigation::global_planning::Algorithms
Algorithms
Definition: core.h:38
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
Trajectory.h
String.h
armarx::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:168
armarx::navigation::global_planning
This file is part of ArmarX.
Definition: fwd.h:29
armarx::navigation::global_planning::optimization::OrientationOptimizer
Definition: OrientationOptimizer.h:54
armarx::navigation::global_planning::Algorithms::AStar
@ AStar
see AStar
AStar.h