Costmap3D.h
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4#include <cstddef>
5#include <optional>
6#include <string>
7#include <utility>
8#include <vector>
9
10#include <Eigen/Core>
11
15
17{
18 namespace smoothing
19 {
20 class Costmap3DWrapper;
21 } // namespace smoothing
22
24 {
25 public:
26 friend class Costmap3DBuilder;
28
30 {
31 // if set to false, distance to obstacles will be computed and not only a binary collision check
32 bool binaryGrid{false};
33
34 /// How big each cell is in the uniform grid.
35 float cellSize = 100.F; // [mm]
36
37 /// How many orientations of the robot each cell contains
38 int orientations = 72; // 360 deg / 72 = 5 deg discretization
39
40 float sceneBoundsMargin = 1000.F; // [mm]
41
43 {
44 std::string rootNode = "";
45 std::string packageName = "";
46 std::string relativePath = "";
48 };
49
50 using Index = Eigen::Array2i;
51 using Position = Eigen::Vector2f;
52
53 // Simpler Grid version, but probably much slower than storing the orientations together
54 // each vector element corresponds to one orientation
55 using Grid = std::vector<Eigen::MatrixXf>;
56
57 using RotationIndex = int;
59
60 // if 0, the cell is invalid
62
63 Costmap3D(const Grid& grid,
64 const Parameters& parameters,
65 const SceneBounds& sceneBounds,
66 const std::optional<Mask>& mask = std::nullopt,
67 const core::Pose2D& origin = core::Pose2D::Identity());
68
69 /**
70 * @brief Create a Costmap3D with the same dimensions and parameters as the given one. Only the content (grid and mask) are altered.
71 *
72 * @param other The Costmap3D providing the dimensions and parameters
73 * @param grid
74 * @param mask
75 * @return Costmap3D
76 */
77 static Costmap3D WithSameDimsAs(const Costmap3D& other,
78 const Grid& grid,
79 const std::optional<Mask>& mask = std::nullopt);
80
81 struct Vertex
82 {
83 Index index; // row corresponds to y; column corresponds to x
85 };
86
87 Position toPositionLocal(const Index& index) const;
89 Vertex toVertex(const Position& globalPosition) const;
90
96
98
100
101 /**
102 * @brief The two orientation slices bracketing the given continuous rotation.
103 *
104 * If the rotation lies exactly on a slice, that slice and its successor are returned.
105 * The second slice wraps around to index 0 for rotations in the last segment.
106 */
107 std::pair<Rotation, Rotation> bracketingRotationsFromDegrees(RotationDegrees degrees) const;
108
109 Eigen::Rotation2Df
110 rotationLocal(const RotationDegrees degrees) const
111 {
112 return Eigen::Rotation2Df{degrees * static_cast<float>(M_PI) / 180.F};
113 }
114
116 globalPose(const Index& index, const RotationDegrees& rotationDeg) const
117 {
118 Eigen::Rotation2Df rot{rotationDeg * static_cast<float>(M_PI) / 180.F};
119 return global_T_Costmap3D * Eigen::Translation2f(toPositionLocal(index)) * rot;
120 }
121
123 rotationDegrees(const core::Pose2D& pose) const
124 {
125 return Eigen::Rotation2Df{pose.linear()}.angle() * 180.F / M_PI;
126 }
127
128 constexpr static Rotation ALL_ORIENTATIONS = {.index = -1, .degrees = -1};
129
130 const Grid& getGrid() const;
131
132 Grid&
134 {
135 return grid;
136 }
137
138 bool isInCollision(const Position& p,
139 std::optional<Rotation> rotation = std::nullopt) const;
140
141 /**
142 * @brief Whether the robot fits at the given position and continuous orientation with
143 * more than the given obstacle clearance.
144 *
145 * Checks the two orientation slices bracketing the continuous orientation, so the
146 * result is conservative with respect to the orientation discretization.
147 */
148 bool isFreeWithClearance(const Position& p,
149 RotationDegrees orientationDeg,
150 float clearance = 0.F) const;
151
152 /**
153 * @brief Find the closest position where the robot fits at the given continuous
154 * orientation with more than minClearance distance to obstacles.
155 *
156 * The two orientation slices bracketing the orientation are overlapped (element-wise
157 * minimum) and the resulting 2D costmap is searched in expanding circles up to
158 * maxDistance. Intended for recovery planning when the robot is standing in collision.
159 *
160 * @param position The starting position to search from
161 * @param orientationDeg The robot's continuous orientation [deg]
162 * @param maxDistance Maximum search radius [mm]
163 * @param minClearance Required distance to obstacles [mm]
164 * @return The closest vertex fulfilling the clearance, or nullopt if none within range
165 */
166 std::optional<Vertex> findClosestCollisionFreeVertex(const Position& position,
167 RotationDegrees orientationDeg,
168 float maxDistance,
169 float minClearance = 0.F) const;
170
171 const Parameters& params() const noexcept;
172
173 // get the scene bounds in the Costmap3D's base frame (aka 'origin')
174 const SceneBounds& getLocalSceneBounds() const noexcept;
175
176 core::Pose2D
177 centerPose(std::optional<Rotation> rotation = std::nullopt) const
178 {
179 const Eigen::Vector2f Costmap3D_P_center{
180 (getLocalSceneBounds().max.x() - getLocalSceneBounds().min.x()) / 2 +
182 (getLocalSceneBounds().max.y() - getLocalSceneBounds().min.y()) / 2 +
184
185 auto rotationDeg = 0.F;
186 if (rotation.has_value())
187 {
188 rotationDeg = rotation->degrees;
189 }
190 Eigen::Rotation2Df rot{rotationDeg * static_cast<float>(M_PI) / 180.F};
191
192 // TODO: Debug
193 return global_T_Costmap3D * Eigen::Translation2f(Costmap3D_P_center) * rot;
194 }
195
196 struct Optimum
197 {
198 float value;
201 };
202
203 Optimum optimum(Rotation rotation = ALL_ORIENTATIONS) const;
204
205 //! checks whether the cell is masked out
206 bool isValid(const Index& index) const noexcept;
207
208 bool isWithinRange(const Index& index) const noexcept;
209
210 bool isMaskedOut(const Index& index) const noexcept;
211
212 const std::optional<Mask>& getMask() const noexcept;
213
214 std::optional<Costmap3D::Mask>& getMutableMask() noexcept;
215
216 float value_ignore_mask(const Index& index, const RotationIndex rot_index) const;
217
218 std::optional<float> value(const Index& index, const RotationIndex rot_index) const;
219
220 std::optional<float> value(const Position& position,
221 const RotationDegrees rotation_degrees) const;
222
224
225 const core::Pose2D&
226 origin() const
227 {
228 return global_T_Costmap3D;
229 }
230
231 void
233 {
234 global_T_Costmap3D = globalPose;
235 }
236
237 std::size_t numberOfValidElements() const;
238
239 std::pair<Index, Index> getValidBoundingBox() const;
240
241 Index getSize() const;
242
244 bool initializeMask = false) const;
245
246 void convertToPseudoSDF();
248
250
251 private:
252 void validateSizes() const;
253
254 Grid grid;
255 std::optional<Mask> mask;
256
257 SceneBounds sceneBounds;
258
259 const Parameters parameters;
260
261 core::Pose2D global_T_Costmap3D = core::Pose2D::Identity();
262 };
263
264
265} // namespace armarx::navigation::algorithms::orientation_aware
#define float
Definition 16_Level.h:22
uint8_t index
#define M_PI
Definition MathTools.h:17
std::pair< Rotation, Rotation > bracketingRotationsFromDegrees(RotationDegrees degrees) const
The two orientation slices bracketing the given continuous rotation.
Costmap costmapForOrientation(RotationIndex rotationIndex, bool initializeMask=false) const
bool isWithinRange(const Index &index) const noexcept
const SceneBounds & getLocalSceneBounds() const noexcept
static Costmap3D WithSameDimsAs(const Costmap3D &other, const Grid &grid, const std::optional< Mask > &mask=std::nullopt)
Create a Costmap3D with the same dimensions and parameters as the given one.
std::optional< Vertex > findClosestCollisionFreeVertex(const Position &position, RotationDegrees orientationDeg, float maxDistance, float minClearance=0.F) const
Find the closest position where the robot fits at the given continuous orientation with more than min...
Costmap3D(const Grid &grid, const Parameters &parameters, const SceneBounds &sceneBounds, const std::optional< Mask > &mask=std::nullopt, const core::Pose2D &origin=core::Pose2D::Identity())
Definition Costmap3D.cpp:29
core::Pose2D globalPose(const Index &index, const RotationDegrees &rotationDeg) const
Definition Costmap3D.h:116
bool isInCollision(const Position &p, std::optional< Rotation > rotation=std::nullopt) const
const std::optional< Mask > & getMask() const noexcept
Eigen::Rotation2Df rotationLocal(const RotationDegrees degrees) const
Definition Costmap3D.h:110
bool isMaskedOut(const Index &index) const noexcept
Eigen::Matrix< bool, Eigen::Dynamic, Eigen::Dynamic > Mask
Definition Costmap3D.h:61
Rotation rotationFromIndex(RotationIndex index) const
Rotation closestRotationFromDegrees(RotationDegrees degrees) const
std::optional< Costmap3D::Mask > & getMutableMask() noexcept
std::optional< float > value(const Index &index, const RotationIndex rot_index) const
RotationDegrees rotationDegrees(const core::Pose2D &pose) const
Definition Costmap3D.h:123
Vertex toVertex(const Position &globalPosition) const
core::Pose2D centerPose(std::optional< Rotation > rotation=std::nullopt) const
Definition Costmap3D.h:177
bool isValid(const Index &index) const noexcept
checks whether the cell is masked out
Definition Costmap3D.cpp:89
Optimum optimum(Rotation rotation=ALL_ORIENTATIONS) const
bool isFreeWithClearance(const Position &p, RotationDegrees orientationDeg, float clearance=0.F) const
Whether the robot fits at the given position and continuous orientation with more than the given obst...
float value_ignore_mask(const Index &index, const RotationIndex rot_index) const
This file is part of ArmarX.
Eigen::Isometry2f Pose2D
Definition basic_types.h:34
int orientations
How many orientations of the robot each cell contains.
Definition Costmap3D.h:38
float cellSize
How big each cell is in the uniform grid.
Definition Costmap3D.h:35
struct armarx::navigation::algorithms::orientation_aware::Costmap3D::Parameters::RobotModel robotModel