70 const std::optional<core::Pose2D> global_T_human_opt =
75 if (not global_T_human_opt.has_value())
82 const auto sceneBounds = [
this, global_T_human = global_T_human_opt.value()]
85 const Eigen::Vector2f human_T_left{-handoverParameters_.humanSceneBoundOffsetSideLeft,
87 const Eigen::Vector2f human_T_right{handoverParameters_.humanSceneBoundOffsetSideRight,
89 const Eigen::Vector2f human_T_front{0, handoverParameters_.humanSceneBoundOffsetFront};
91 const Eigen::Vector2f human_T_back{0, -handoverParameters_.humanSceneBoundOffsetBehind};
96 global_T_human * human_T_right,
97 global_T_human * human_T_front,
98 global_T_human * human_T_back},
108 const auto projectToInterval =
109 [](
const float value,
const float min,
const float max,
const float preference) ->
float
120 if (value == preference)
124 if (value < preference)
126 return -((preference - value) / (preference -
min));
129 return (value - preference) / (
max - preference);
132 const auto costFn = [
this, &projectToInterval](
float distanceToObstacle,
133 float distanceToHuman,
134 float angleToHuman) -> std::optional<float>
137 if (distanceToHuman < handoverParameters_.handoverDistanceMin ||
138 distanceToHuman > handoverParameters_.handoverDistanceMax)
143 if (angleToHuman < handoverParameters_.handoverAngleMin ||
144 angleToHuman > handoverParameters_.handoverAngleMax)
151 const float xDistance =
152 projectToInterval(distanceToHuman,
153 handoverParameters_.handoverDistanceMin,
154 handoverParameters_.handoverDistanceMax,
155 handoverParameters_.handoverDistancePreference);
156 const float xAngle = projectToInterval(angleToHuman,
157 handoverParameters_.handoverAngleMin,
158 handoverParameters_.handoverAngleMax,
159 handoverParameters_.handoverAnglePreference);
163 const double fDistance = std::abs(std::tan(xDistance * M_PI_2));
164 const double fAngle = std::abs(std::tan(xAngle * M_PI_2));
170 const double f = (fDistance + 1) * (fAngle + 1);
174 const double obstaclePenalty =
175 (distanceToObstacle < handoverParameters_.obstacleProximityThreshold)
176 ? handoverParameters_.obstacleProximityPenalty
179 return static_cast<float>(f + obstaclePenalty);
194 [&
costmap, &sceneInfo, global_T_human = global_T_human_opt.value(), &costFn](
198 const auto global_P_cell = costmap.toPositionGlobal(idx);
202 const auto vertex = sceneInfo.distanceMap.toVertexOrInvalid(global_P_cell);
206 costmap.getMutableGrid()(idx.x(), idx.y()) = 0.0f;
207 costmap.getMutableMask()->operator()(idx.x(), idx.y()) = false;
210 if (!vertex.has_value())
230 const float distanceToObstacle =
231 sceneInfo.distanceMap.getGrid()(vertex->index.x(), vertex->index.y());
232 const Eigen::Vector2f human_P_cell = global_T_human.inverse() * global_P_cell;
234 const float distanceToHuman = human_P_cell.norm();
236 const float angleToHuman = std::atan2(human_P_cell.y(), human_P_cell.x());
239 const auto costOpt = costFn(distanceToObstacle, distanceToHuman, angleToHuman);
241 if (not costOpt.has_value())
247 costmap.getMutableGrid()(idx.x(), idx.y()) = costOpt.value();
248 costmap.getMutableMask()->operator()(idx.x(), idx.y()) =
true;
257 if (sceneInfo.robotPosition.has_value())
259 const auto robotVertexOpt =
260 sceneInfo.distanceMap.toVertexOrInvalid(sceneInfo.robotPosition.value());
261 if (not robotVertexOpt.has_value())
263 ARMARX_WARNING <<
"Robot position is outside the distance map; ignoring robot "
264 "path cost and reachability.";
268 spfa::ShortestPathFasterAlgorithm spfa(sceneInfo.distanceMap,
269 handoverParameters_.robotPathParams);
270 const auto spfaResult = spfa.spfa(sceneInfo.robotPosition.value());
275 if (not costmap.isValid(idx))
280 const Eigen::Vector2f globalP = costmap.toPositionGlobal(idx);
281 const auto vertexOpt = sceneInfo.distanceMap.toVertexOrInvalid(globalP);
282 if (not vertexOpt.has_value())
284 costmap.getMutableMask()->operator()(idx.x(), idx.y()) =
false;
288 const Eigen::Vector2i dmIdx = vertexOpt->index;
289 if (not sceneInfo.distanceMap.isValid(dmIdx) or
290 not spfaResult.reachable(dmIdx.x(), dmIdx.y()))
292 costmap.getMutableMask()->operator()(idx.x(), idx.y()) =
false;
296 const float pathCostMM = spfaResult.distances(dmIdx.x(), dmIdx.y());
297 const float normalizedCost =
298 std::min(pathCostMM / handoverParameters_.robotPathMaxCostMM, 1.F);
300 costmap.getMutableGrid()(idx.x(), idx.y()) +=
301 handoverParameters_.robotPathCostWeight * normalizedCost;