Point2Point.cpp
Go to the documentation of this file.
1#include "Point2Point.h"
2
3#include <cmath>
4#include <optional>
5#include <vector>
6
7#include <range/v3/algorithm/all_of.hpp>
8
9#include <VirtualRobot/Robot.h> // IWYU pragma: keep
10
13#include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
14
16
21#include <armarx/navigation/global_planning/aron/Point2PointParams.aron.generated.h>
24
26{
27
28 namespace
29 {
30
31 std::vector<core::GlobalTrajectoryPoint>
32 resampleStraightLine(const core::Pose& start,
33 const core::Pose& goal,
34 float eps,
35 float velocity)
36 {
37 const float distance =
38 (goal.translation().head<2>() - start.translation().head<2>()).norm();
39
40 if (distance < eps)
41 {
42 return {core::GlobalTrajectoryPoint{.waypoint = core::Waypoint{.pose = start},
43 .velocity = velocity},
44 core::GlobalTrajectoryPoint{.waypoint = core::Waypoint{.pose = goal},
45 .velocity = velocity}};
46 }
47
48 const int numSegments = static_cast<int>(std::ceil(distance / eps));
49 const int numPoints = numSegments + 1;
50
51 const Eigen::Quaternionf startQ(start.linear());
52 const Eigen::Quaternionf goalQ(goal.linear());
53
54 std::vector<core::GlobalTrajectoryPoint> points;
55 points.reserve(numPoints);
56
57 for (int i = 0; i < numPoints; i++)
58 {
59 const float t = static_cast<float>(i) / static_cast<float>(numSegments);
60
61 const Eigen::Vector3f position =
62 (1.F - t) * start.translation() + t * goal.translation();
63
64 const Eigen::Quaternionf orientation = startQ.slerp(t, goalQ);
65
66 core::Pose pose = core::Pose::Identity();
67 pose.translation() = position;
68 pose.linear() = orientation.toRotationMatrix();
69
70 points.push_back(core::GlobalTrajectoryPoint{
71 .waypoint = core::Waypoint{.pose = pose}, .velocity = velocity});
72 }
73
74 return points;
75 }
76
77 bool
78 checkCollisions(const std::vector<core::GlobalTrajectoryPoint>& trajectory,
79 const navigation::algorithms::Costmap& costmap)
80 {
81 const auto isCollisionFree =
82 [&costmap](const core::GlobalTrajectoryPoint& point) -> bool
83 {
84 const auto idx =
85 costmap.toVertex(point.waypoint.pose.translation().head<2>()).index;
86 return costmap.isValid(idx);
87 };
88
89 return ranges::all_of(trajectory, isCollisionFree);
90 }
91
92 } // namespace
93
94 // Point2PointParams
95
101
104 {
105 arondto::Point2PointParams dto;
106
108 aron_conv::toAron(dto, bo);
109
110 return dto.toAron();
111 }
112
115 {
117
118 arondto::Point2PointParams dto;
119 dto.fromAron(dict);
120
122 aron_conv::fromAron(dto, bo);
123
124 return bo;
125 }
126
127 // Point2Point
128
131 const core::Scene& ctx) :
133 impl_(params,
135 ctx.staticScene.has_value() ? ctx.staticScene->distanceToObstaclesCostmap
136 : std::nullopt,
137 ctx.robot)
138 {
139 }
140
141 std::optional<GlobalPlannerResult>
143 {
144 return plan(core::Pose(scene.robot->getGlobalPose()), goal);
145 }
146
147 std::optional<GlobalPlannerResult>
148 Point2Point::plan(const core::Pose& start, const core::Pose& goal)
149 {
150 if (scene.staticScene.has_value())
151 {
152 impl_.updateCostmap(scene.staticScene->distanceToObstaclesCostmap);
153 }
154 return impl_.plan(start, goal);
155 }
156
157 // Point2PointImpl
158
160 const core::GeneralConfig& generalConfig,
161 const std::optional<navigation::algorithms::Costmap>& costmap,
163 params_(params), generalConfig_(generalConfig), costmap_(costmap), robot_(robot)
164 {
165 }
166
167 void
168 Point2PointImpl::updateCostmap(const std::optional<navigation::algorithms::Costmap>& costmap)
169 {
170 if (costmap.has_value())
171 {
172 costmap_.emplace(costmap.value());
173 }
174 else
175 {
176 costmap_.reset();
177 }
178 }
179
180 std::optional<GlobalPlannerResult>
181 Point2PointImpl::plan(const core::Pose& start, const core::Pose& goal)
182 {
183 const auto trajectory =
184 resampleStraightLine(start, goal, 100.F, generalConfig_.maxVel.linear);
185
186 if (params_.checkCollisionsAlongTrajectory)
187 {
188 ARMARX_INFO << "Checking collision along trajectory";
189 ARMARX_CHECK(costmap_.has_value());
190
191 if (not checkCollisions(trajectory, costmap_.value()))
192 {
193 ARMARX_WARNING << "Planned trajectory is in collision!";
194 return std::nullopt;
195 }
196 }
197
198 return GlobalPlannerResult{.trajectory = trajectory, .helperTrajectory = std::nullopt};
199 }
200
201} // namespace armarx::navigation::global_planning
GlobalPlanner(const core::GeneralConfig &generalConfig, const core::Scene &scene)
void updateCostmap(const std::optional< navigation::algorithms::Costmap > &costmap)
std::optional< GlobalPlannerResult > plan(const core::Pose &start, const core::Pose &goal)
Point2PointImpl(const Params &params, const core::GeneralConfig &generalConfig, const std::optional< navigation::algorithms::Costmap > &costmap, VirtualRobot::RobotPtr robot)
std::optional< GlobalPlannerResult > plan(const core::Pose &goal) override
Point2Point(const Params &params, const core::GeneralConfig &generalConfig, const core::Scene &ctx)
#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
Quaternion< float, 0 > Quaternionf
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
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
double distance(const Point &a, const Point &b)
Definition point.hpp:95
static Point2PointParams FromAron(const aron::data::DictPtr &dict)
aron::data::DictPtr toAron() const override