AStar.cpp
Go to the documentation of this file.
1#include "AStar.h"
2
3#include <cstddef>
4#include <optional>
5#include <vector>
6
7#include <Eigen/Geometry>
8
9#include <IceUtil/Time.h>
10
11#include <VirtualRobot/Robot.h> // IWYU pragma: keep
12
17
19
27#include <armarx/navigation/global_planning/aron/AStarParams.aron.generated.h>
31
33{
34
35 // AStarParams
36
39 {
40 return Algorithms::AStar;
41 }
42
45 {
46 arondto::AStarParams dto;
47
48 AStarParams bo;
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
64 AStarParams bo;
65 aron_conv::fromAron(dto, bo);
66
67 return bo;
68 }
69
70 // AStar
71
72 AStar::AStar(const Params& params,
74 const core::Scene& ctx) :
76 impl_(params,
78 scene.staticScene.has_value() ? scene.staticScene->distanceToObstaclesCostmap
79 : std::nullopt)
80 {
81 }
82
83 std::optional<GlobalPlannerResult>
85 {
86 const core::Pose start(scene.robot->getGlobalPose());
87 return plan(start, goal);
88 }
89
90 std::optional<GlobalPlannerResult>
91 AStar::plan(const core::Pose& start, const core::Pose& goal)
92 {
93 if (scene.staticScene.has_value())
94 {
95 impl_.updateCostmap(scene.staticScene->distanceToObstaclesCostmap);
96 }
97 return impl_.plan(start, goal);
98 }
99
100 // AStarImpl
101
103 const core::GeneralConfig& generalConfig,
104 const std::optional<navigation::algorithms::Costmap>& costmap) :
105 params(params), costmap_(costmap)
106 {
107 }
108
109 void
110 AStarImpl::updateCostmap(const std::optional<navigation::algorithms::Costmap>& costmap)
111 {
112 if (costmap.has_value())
113 {
114 costmap_.emplace(costmap.value());
115 }
116 else
117 {
118 costmap_.reset();
119 }
120 }
121
122 std::vector<Eigen::Vector2f>
123 AStarImpl::postProcessPath(const std::vector<Eigen::Vector2f>& path)
124 {
125 /// chain approximation
127 path, algorithm::ChainApproximation::Params{.distanceTh = 200.F});
128 approx.approximate();
129 const auto p = approx.approximatedChain();
130 return p;
131 }
132
133 std::optional<GlobalPlannerResult>
134 AStarImpl::plan(const core::Pose& start, const core::Pose& goal)
135 {
137
138 // FIXME check if costmap is available
139 algorithm::astar::AStarPlanner planner(*costmap_);
140
141 const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
142
143 const auto timeStart = IceUtil::Time::now();
144
145 std::vector<Eigen::Vector2f> plan;
146 try
147 {
148 plan = planner.plan(conv::to2D(start.translation()), goalPos);
149 }
150 catch (...)
151 {
152 ARMARX_INFO << "Could not plan collision-free path from" << "("
153 << start.translation().x() << "," << start.translation().y() << ")"
154 << " to " << "(" << goal.translation().x() << "," << goal.translation().y()
155 << ")" << " due to exception " << GetHandledExceptionString();
156
157 return std::nullopt;
158 }
159 const auto timeEnd = IceUtil::Time::now();
160
161 ARMARX_IMPORTANT << "A* planning took " << (timeEnd - timeStart).toMilliSeconds() << " ms";
162 ARMARX_IMPORTANT << "Path contains " << plan.size() << " points";
163
164 if (plan.size() < 2) // failure
165 {
166 ARMARX_INFO << "Could not plan collision-free path from" << "("
167 << start.translation().x() << "," << start.translation().y() << ")"
168 << " to " << "(" << goal.translation().x() << "," << goal.translation().y()
169 << ")";
170 return std::nullopt;
171 }
172
173 ARMARX_DEBUG << "The plan consists of the following positions:";
174 for (const auto& position : plan)
175 {
176 ARMARX_DEBUG << position;
177 }
178
179 const core::Pose startPose(Eigen::Translation3f(conv::to3D(plan.front())));
180 const core::Pose goalPose(Eigen::Translation3f(conv::to3D(plan.back())));
181
182 const auto plan3d = conv::to3D(plan);
183
184 std::vector<core::Position> wpts;
185 for (size_t i = 1; i < (plan3d.size() - 1); i++)
186 {
187 wpts.push_back(plan3d.at(i));
188 }
189
191 auto smoothPlan = postProcessPath(plan);
192 ARMARX_IMPORTANT << "Smooth path contains " << smoothPlan.size() << " points";
193
195 // we need to strip the first and the last points from the plan as they encode the start and goal position
196 smoothPlan.erase(smoothPlan.begin());
197 smoothPlan.pop_back();
198
201 start, conv::to3D(smoothPlan), goal, generalConfig_.maxVel.linear);
202
203 // TODO(fabian.reister): resampling of trajectory
204
205 // FIXME param
206 std::optional<core::GlobalTrajectory> resampledTrajectory;
207
208 if (params.resampleDistance < 0)
209 {
210 resampledTrajectory = trajectory;
211 }
212 else
213 {
214 try
215 {
216 resampledTrajectory = trajectory.resample(params.resampleDistance);
217 }
218 catch (...)
219 {
220 ARMARX_INFO << "Caught exception during resampling: "
222 // return std::nullopt;
223 resampledTrajectory = trajectory;
224 }
225 }
226
227 ARMARX_VERBOSE << "Resampled trajectory contains " << resampledTrajectory->points().size()
228 << " points";
229
230 resampledTrajectory->setMaxVelocity(generalConfig_.maxVel.linear);
231
232 if (resampledTrajectory->points().size() == 2)
233 {
234 ARMARX_INFO << "Only start and goal provided. Not optimizing orientation";
236 return GlobalPlannerResult{.trajectory = resampledTrajectory.value(),
237 .helperTrajectory = std::nullopt};
238 }
239
241 OrientationOptimizer optimizer(resampledTrajectory.value(), OrientationOptimizer::Params{});
242 const auto result = optimizer.optimize();
243
244 if (not result)
245 {
246 ARMARX_WARNING << "Optimizer failure";
247 return std::nullopt;
248 }
249
251
252 // TODO circular path smoothing should be done now
253 // algorithm::CircularPathSmoothing smoothing;
254 // auto smoothTrajectory = smoothing.smooth(result.trajectory.value());
255 // smoothTrajectory.setMaxVelocity(generalConfig.maxVel.linear);
256
258 return GlobalPlannerResult{.trajectory = result.trajectory.value(),
259 .helperTrajectory = std::nullopt};
260 }
261} // namespace armarx::navigation::global_planning
std::vector< Eigen::Vector2f > plan(const Eigen::Vector2f &start, const Eigen::Vector2f &goal)
static GlobalTrajectory FromPath(const Path &path, float velocity)
Note: the velocity will not be set!
void updateCostmap(const std::optional< navigation::algorithms::Costmap > &costmap)
Definition AStar.cpp:110
std::optional< GlobalPlannerResult > plan(const core::Pose &start, const core::Pose &goal)
Definition AStar.cpp:134
AStarImpl(const Params &params, const core::GeneralConfig &generalConfig, const std::optional< navigation::algorithms::Costmap > &costmap)
Definition AStar.cpp:102
std::vector< Eigen::Vector2f > postProcessPath(const std::vector< Eigen::Vector2f > &path)
Definition AStar.cpp:123
std::optional< GlobalPlannerResult > plan(const core::Pose &goal) override
Definition AStar.cpp:84
AStar(const Params &params, const core::GeneralConfig &generalConfig, const core::Scene &ctx)
Definition AStar.cpp:72
GlobalPlanner(const core::GeneralConfig &generalConfig, const core::Scene &scene)
#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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#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
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
Eigen::Isometry3f Pose
Definition basic_types.h:31
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()
static AStarParams FromAron(const aron::data::DictPtr &dict)
Definition AStar.cpp:55
aron::data::DictPtr toAron() const override
Definition AStar.cpp:44
Algorithms algorithm() const override
Definition AStar.cpp:38
#define ARMARX_TRACE
Definition trace.h:77