45 costmapParameters_(costmapParameters), handoverParameters_(handoverParameters)
50 handoverParameters_.handoverDistanceMin);
53 handoverParameters_.handoverAngleMax);
56 handoverParameters_.handoverAnglePreference);
58 handoverParameters_.handoverAngleMax);
64 const std::optional<core::Pose2D> global_T_human_opt =
67 if (not global_T_human_opt.has_value())
74 const auto sceneBounds = [
this, global_T_human = global_T_human_opt.value()]
77 const Eigen::Vector2f human_T_left{-handoverParameters_.humanSceneBoundOffsetSideLeft,
79 const Eigen::Vector2f human_T_right{handoverParameters_.humanSceneBoundOffsetSideRight,
81 const Eigen::Vector2f human_T_front{0, handoverParameters_.humanSceneBoundOffsetFront};
83 const Eigen::Vector2f human_T_back{0, -handoverParameters_.humanSceneBoundOffsetBehind};
88 global_T_human * human_T_right,
89 global_T_human * human_T_front,
90 global_T_human * human_T_back},
100 const auto projectToInterval =
101 [](
const float value,
const float min,
const float max,
const float preference) ->
float
112 if (value == preference)
116 if (value < preference)
118 return -((preference - value) / (preference -
min));
121 return (value - preference) / (
max - preference);
124 const auto costFn = [
this, &projectToInterval](
float distanceToObstacle,
125 float distanceToHuman,
126 float angleToHuman) -> std::optional<float>
129 if (distanceToHuman < handoverParameters_.handoverDistanceMin ||
130 distanceToHuman > handoverParameters_.handoverDistanceMax)
135 if (angleToHuman < handoverParameters_.handoverAngleMin ||
136 angleToHuman > handoverParameters_.handoverAngleMax)
143 const float xDistance =
144 projectToInterval(distanceToHuman,
145 handoverParameters_.handoverDistanceMin,
146 handoverParameters_.handoverDistanceMax,
147 handoverParameters_.handoverDistancePreference);
148 const float xAngle = projectToInterval(angleToHuman,
149 handoverParameters_.handoverAngleMin,
150 handoverParameters_.handoverAngleMax,
151 handoverParameters_.handoverAnglePreference);
155 const double fDistance = std::abs(std::tan(xDistance * M_PI_2));
156 const double fAngle = std::abs(std::tan(xAngle * M_PI_2));
162 const double f = (fDistance + 1) * (fAngle + 1);
164 return distanceToObstacle * f;
174 [&
costmap, &sceneInfo, global_T_human = global_T_human_opt.value(), &costFn](
178 const auto global_P_cell = costmap.toPositionGlobal(idx);
182 const auto vertex = sceneInfo.distanceMap.toVertexOrInvalid(global_P_cell);
186 costmap.getMutableGrid()(idx.x(), idx.y()) = 0.0f;
187 costmap.getMutableMask()->operator()(idx.x(), idx.y()) = false;
190 if (!vertex.has_value())
207 const float distanceToObstacle = d.value();
208 const Eigen::Vector2f human_P_cell = global_T_human.inverse() * global_P_cell;
210 const float distanceToHuman = human_P_cell.norm();
212 const float angleToHuman = std::atan2(human_P_cell.y(), human_P_cell.x());
215 const auto costOpt = costFn(distanceToObstacle, distanceToHuman, angleToHuman);
217 if (not costOpt.has_value())
223 costmap.getMutableGrid()(idx.x(), idx.y()) = costOpt.value();
224 costmap.getMutableMask()->operator()(idx.x(), idx.y()) =
true;
234 const auto costmapOpt =
create(sceneInfo);
236 if (not costmapOpt.has_value())
241 const auto&
costmap = costmapOpt.value();
242 const auto optimum =
costmap.optimum();
244 if (optimum.index.isConstant(-1))
253 if (not global_P_human.has_value())
259 const auto global_P_handover = optimum.position;
261 const Eigen::Vector2f direction =
262 (global_P_human->head<2>() - global_P_handover).normalized();
264 const float yaw = std::atan2(direction.y(), direction.x());
266 return core::Pose2D{Eigen::Translation2f{global_P_handover.x(), global_P_handover.y()} *
267 Eigen::Rotation2Df{yaw}};