Point2Point.cpp
Go to the documentation of this file.
1#include "Point2Point.h"
2
3#include <algorithm>
4#include <cmath>
5#include <optional>
6#include <vector>
7
8#include <range/v3/algorithm/all_of.hpp>
9
10#include <VirtualRobot/Robot.h> // IWYU pragma: keep
11
14#include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
15
17
22#include <armarx/navigation/global_planning/aron/Point2PointParams.aron.generated.h>
25
27{
28
29 namespace
30 {
31
32 constexpr float maxWaypointSpacing = 100.F;
33 constexpr int minWaypointSegments = 9;
34 constexpr float minWaypointSpacing = 5.F;
35
36 std::vector<core::GlobalTrajectoryPoint>
37 resampleStraightLine(const core::Pose& start,
38 const core::Pose& goal,
39 float eps,
40 float velocity)
41 {
42 const float distance =
43 (goal.translation().head<2>() - start.translation().head<2>()).norm();
44
45 // A fixed spacing leaves a short line with fewer than the four waypoints TOPP-RA
46 // needs for its spline, and the navigator then falls back to ramping, which pins a
47 // short move to the goal velocity. Sample short lines finer instead.
48 const float spacing =
49 distance > 0.F
50 ? std::clamp(distance / static_cast<float>(minWaypointSegments),
51 minWaypointSpacing,
52 eps)
53 : eps;
54
55 if (distance < spacing)
56 {
57 return {core::GlobalTrajectoryPoint{.waypoint = core::Waypoint{.pose = start},
58 .velocity = velocity},
59 core::GlobalTrajectoryPoint{.waypoint = core::Waypoint{.pose = goal},
60 .velocity = velocity}};
61 }
62
63 const int numSegments = static_cast<int>(std::ceil(distance / spacing));
64 const int numPoints = numSegments + 1;
65
66 const Eigen::Quaternionf startQ(start.linear());
67 const Eigen::Quaternionf goalQ(goal.linear());
68
69 std::vector<core::GlobalTrajectoryPoint> points;
70 points.reserve(numPoints);
71
72 for (int i = 0; i < numPoints; i++)
73 {
74 const float t = static_cast<float>(i) / static_cast<float>(numSegments);
75
76 const Eigen::Vector3f position =
77 (1.F - t) * start.translation() + t * goal.translation();
78
79 const Eigen::Quaternionf orientation = startQ.slerp(t, goalQ);
80
81 core::Pose pose = core::Pose::Identity();
82 pose.translation() = position;
83 pose.linear() = orientation.toRotationMatrix();
84
85 points.push_back(core::GlobalTrajectoryPoint{
86 .waypoint = core::Waypoint{.pose = pose}, .velocity = velocity});
87 }
88
89 return points;
90 }
91
92 bool
93 checkCollisions(const std::vector<core::GlobalTrajectoryPoint>& trajectory,
94 const navigation::algorithms::Costmap& costmap)
95 {
96 const auto isCollisionFree =
97 [&costmap](const core::GlobalTrajectoryPoint& point) -> bool
98 {
99 const auto idx =
100 costmap.toVertex(point.waypoint.pose.translation().head<2>()).index;
101 return costmap.isValid(idx);
102 };
103
104 return ranges::all_of(trajectory, isCollisionFree);
105 }
106
107 } // namespace
108
109 // Point2PointParams
110
116
119 {
120 arondto::Point2PointParams dto;
121
123 aron_conv::toAron(dto, bo);
124
125 return dto.toAron();
126 }
127
130 {
132
133 arondto::Point2PointParams dto;
134 dto.fromAron(dict);
135
137 aron_conv::fromAron(dto, bo);
138
139 return bo;
140 }
141
142 // Point2Point
143
146 const core::Scene& ctx) :
148 impl_(params,
150 ctx.staticScene.has_value() ? ctx.staticScene->distanceToObstaclesCostmap
151 : std::nullopt,
152 ctx.robot)
153 {
154 }
155
156 std::optional<GlobalPlannerResult>
158 {
159 return plan(core::Pose(scene.robot->getGlobalPose()), goal);
160 }
161
162 std::optional<GlobalPlannerResult>
163 Point2Point::plan(const core::Pose& start, const core::Pose& goal)
164 {
165 if (scene.staticScene.has_value())
166 {
167 impl_.updateCostmap(scene.staticScene->distanceToObstaclesCostmap);
168 }
169 return impl_.plan(start, goal);
170 }
171
172 // Point2PointImpl
173
175 const core::GeneralConfig& generalConfig,
176 const std::optional<navigation::algorithms::Costmap>& costmap,
178 params_(params), generalConfig_(generalConfig), costmap_(costmap), robot_(robot)
179 {
180 }
181
182 void
183 Point2PointImpl::updateCostmap(const std::optional<navigation::algorithms::Costmap>& costmap)
184 {
185 if (costmap.has_value())
186 {
187 costmap_.emplace(costmap.value());
188 }
189 else
190 {
191 costmap_.reset();
192 }
193 }
194
195 std::optional<GlobalPlannerResult>
196 Point2PointImpl::plan(const core::Pose& start, const core::Pose& goal)
197 {
198 const auto trajectory =
199 resampleStraightLine(start, goal, maxWaypointSpacing, generalConfig_.maxVel.linear);
200
201 if (params_.checkCollisionsAlongTrajectory)
202 {
203 ARMARX_INFO << "Checking collision along trajectory";
204 ARMARX_CHECK(costmap_.has_value());
205
206 if (not checkCollisions(trajectory, costmap_.value()))
207 {
208 ARMARX_WARNING << "Planned trajectory is in collision!";
209 return std::nullopt;
210 }
211 }
212
213 return GlobalPlannerResult{.trajectory = trajectory, .helperTrajectory = std::nullopt};
214 }
215
216} // 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:179
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:191
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