AStarWithOrientation.cpp
Go to the documentation of this file.
2
3#include <optional>
4#include <vector>
5
6#include <Eigen/Core>
7#include <Eigen/Geometry>
8
9#include <range/v3/algorithm/transform.hpp>
10#include <range/v3/range/conversion.hpp>
11#include <range/v3/view/transform.hpp>
12
13#include <VirtualRobot/Nodes/RobotNode.h>
14#include <VirtualRobot/Robot.h> // IWYU pragma: keep
15#include <VirtualRobot/XML/RobotIO.h>
16
21#include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
22
24
32#include <armarx/navigation/core/aron/Trajectory.aron.generated.h>
36#include <armarx/navigation/global_planning/aron/AStarWithOrientationParams.aron.generated.h>
39
41{
42 // AStarWithOrientationParams
43
49
52 {
53 arondto::AStarWithOrientationParams dto;
54
56 aron_conv::toAron(dto, bo);
57
58 return dto.toAron();
59 }
60
63 {
65
66 arondto::AStarWithOrientationParams dto;
67 dto.fromAron(dict);
68
70 aron_conv::fromAron(dto, bo);
71
72 return bo;
73 }
74
75 // AStarWithOrientation
76
77 // TODO: How can we work with arbitrary robot shapes?
78 // Maybe take a 2D-shape as input and create a 5 degree sweep shape out of it
79 //
80 // How to work with orientation?
81 // - One option would be to keep the robot center at the same location
82 // This way, we could make use of the precomputed costmap and check the cart borders for collisions.
83 //
84
87 const core::Scene& ctx) :
89 impl(params, ctx.staticScene->orientationAwareCostmap.value(), ctx.robot)
90 {
91 }
92
93 std::optional<GlobalPlannerResult>
95 {
96 const core::Pose start(scene.robot->getGlobalPose());
97 return plan(start, goal);
98 }
99
100 std::optional<GlobalPlannerResult>
101 AStarWithOrientation::plan(const core::Pose& startRobotRoot, const core::Pose& goalRobotRoot)
102 {
103 if (scene.staticScene.has_value() && scene.staticScene->orientationAwareCostmap.has_value())
104 {
105 impl.updateCostmap(scene.staticScene->orientationAwareCostmap.value());
106 }
107 return impl.plan(startRobotRoot, goalRobotRoot);
108 }
109
110 void
112 const std::string& vizLayerNamePrefix)
113 {
114 impl.visualizeDebugInfo(vizClient, vizLayerNamePrefix);
115 }
116
117 // AStarWithOrientationImpl
118
119
121 const Params& params,
122 const std::optional<navigation::algorithms::orientation_aware::Costmap3D>& costmap,
125 {
126 }
127
128 void
130 const std::optional<navigation::algorithms::orientation_aware::Costmap3D>& costmap)
131 {
132 if (costmap.has_value())
133 {
134 this->costmap.emplace(costmap.value());
135 }
136 else
137 {
138 this->costmap.reset();
139 }
140 }
141
142 std::optional<GlobalPlannerResult>
144 const core::Pose& goalRobotRoot)
145 {
146 ARMARX_CHECK(costmap.has_value())
147 << "AStarWithOrientation cannot be executed because there is no 3D costmap available";
148 const auto aStarParams =
150 algorithms::orientation_aware::AStarPlanner planner{costmap.value(), aStarParams};
151
152
153 const Eigen::Isometry3f root_T_used_root =
155
156 // start and goal in the costmap; consistent with the generation of the costmap
157 const core::Pose start = startRobotRoot * root_T_used_root;
158 const core::Pose goal = goalRobotRoot * root_T_used_root;
159
160 const auto plan = planner.plan(conv::to2D(start), conv::to2D(goal));
161
162 if (plan.empty())
163 {
164 ARMARX_WARNING << "Could not calculate a path with orientation_aware A*";
165 return {};
166 }
167
168 std::vector<core::GlobalTrajectoryPoint> trajectory;
169 trajectory.reserve(plan.size() + 2);
170 std::vector<core::GlobalTrajectoryPoint> trajBeforeTransform;
171 trajBeforeTransform.reserve(plan.size() + 2);
172
173 const Eigen::Isometry3f root_used_T_root = root_T_used_root.inverse();
174
175 trajectory.push_back({.waypoint = {start * root_used_T_root}, .velocity = 300.F});
176 trajBeforeTransform.push_back({.waypoint = {start}, .velocity = 300.F});
177
178 for (std::size_t i = 1; i < plan.size(); ++i)
179 {
180 const auto& pose2d = plan[i];
181 // need to transform points back to robot's root frame
183 .waypoint = {conv::to3D(pose2d) * root_used_T_root},
184 .velocity = 300.F,
185 });
186 trajBeforeTransform.push_back(core::GlobalTrajectoryPoint{
187 .waypoint = {conv::to3D(pose2d)},
188 .velocity = 300.F,
189 });
190 }
191
192 trajectory.back().velocity = 0;
193 trajBeforeTransform.back().velocity = 0;
194
196
197 // Resampling
198 //traj = traj.resample(30.F); // not working properly for orientation
199 //traj = traj.calcSubsampledTrajectory(3); // working, but not really needed (smoothing is good enough without
200
202 core::GlobalTrajectory{trajBeforeTransform},
203 costmap.value(),
205 const auto optimizationResult = smoother.optimize();
206 auto traj_smoothed = optimizationResult.trajectory.value();
207 auto traj_smoothed_converted = traj_smoothed.mutablePoints() |
208 ranges::views::transform(
209 [root_used_T_root](const core::GlobalTrajectoryPoint& pt)
210 {
211 auto pt2 = pt;
212 pt2.waypoint.pose =
213 pt2.waypoint.pose * root_used_T_root;
214 return pt2;
215 }) |
216 ranges::to_vector;
217
218 lastPointsInCollision = smoother.checkCenterTrajectory(traj_smoothed);
219
220 if (lastPointsInCollision.empty())
221 {
222 ARMARX_INFO << "Smoothed trajectory is collision-free.";
223 return GlobalPlannerResult{.trajectory = traj_smoothed_converted,
224 .helperTrajectory = traj_smoothed};
225 }
226 // return GlobalPlannerResult{.trajectory = traj_smoothed_converted,
227 // .helperTrajectory = traj_smoothed};
228
230 << "Smoothed trajectory is NOT collision-free. Using original trajectory instead";
231 return GlobalPlannerResult{.trajectory = trajectory,
232 .helperTrajectory = trajBeforeTransform};
233 }
234
235 void
237 const std::string& vizLayerNamePrefix)
238 {
239 // visualize points in collision
240 auto layer = vizClient.layer(vizLayerNamePrefix + "_points_in_collision");
241 layer.clear();
242 for (std::size_t i = 0; i < lastPointsInCollision.size(); ++i)
243 {
244 const auto& p = lastPointsInCollision[i];
245 std::stringstream ss;
246 ss << "point_in_collision_" << i;
247 viz::Ellipsoid ellipsoid =
248 viz::Ellipsoid(ss.str())
249 .pose(Eigen::Isometry3f{Eigen::Translation3f{p.waypoint.pose.translation()}}
250 .matrix())
251 .axisLengths(Eigen::Vector3f{100.0F, 100.0F, 100.0F})
252 .color(simox::Color::red());
253 layer.add(ellipsoid);
254 }
255 vizClient.commit(layer);
256 }
257
258} // namespace armarx::navigation::global_planning
The A* planner (3D version including orientation dimension)
std::vector< core::GlobalTrajectoryPoint > checkCenterTrajectory(core::GlobalTrajectory &centerTrajectory) const
Definition Smoothing.cpp:81
std::optional< GlobalPlannerResult > plan(const core::Pose &start, const core::Pose &goal)
void updateCostmap(const std::optional< navigation::algorithms::orientation_aware::Costmap3D > &costmap)
std::optional< navigation::algorithms::orientation_aware::Costmap3D > costmap
AStarWithOrientationImpl(const Params &params, const std::optional< navigation::algorithms::orientation_aware::Costmap3D > &costmap, VirtualRobot::RobotPtr robot)
void visualizeDebugInfo(viz::Client &vizClient, const std::string &vizLayerNamePrefix="global_planner_debug")
void visualizeDebugInfo(viz::Client &vizClient, const std::string &vizLayerNamePrefix="global_planner_debug") override
std::optional< GlobalPlannerResult > plan(const core::Pose &goal) override
AStarWithOrientation(const Params &params, const core::GeneralConfig &generalConfig, const core::Scene &ctx)
GlobalPlanner(const core::GeneralConfig &generalConfig, const core::Scene &scene)
virtual Layer layer(std::string const &name) const
Definition Client.cpp:80
CommitResult commit(StagedCommit const &commit)
Definition Client.cpp:89
DerivedT & pose(Eigen::Matrix4f const &pose)
Definition ElementOps.h:176
#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_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
AStarWithOrientationParams loadAStarWithOrientationParams(const std::string &filePath="algorithms/astarwithorientation.cfg")
Definition io.h:24
SmoothingParams loadSmoothingParams(const std::string &filePath="algorithms/orientation-aware-smoothing.cfg")
Definition io.h:37
Eigen::Isometry3f get_root_T_used_root(const armarx::navigation::algorithms::orientation_aware::Costmap3D &costmap, const VirtualRobot::RobotPtr &robot_in)
Definition util.h:31
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
static AStarWithOrientationParams FromAron(const aron::data::DictPtr &dict)
Ellipsoid & axisLengths(const Eigen::Vector3f &axisLengths)
Definition Elements.h:156