37 template <
typename IndexT,
typename WeightT,
int size>
38 struct LinearInterpolationResult
40 std::array<IndexT, size> indices;
41 std::array<WeightT, size> weights;
45 calcWeightedAccess(std::function<
T(
const IndexT&)> accessor)
const
48 for (
int i = 0; i < size; ++i)
50 result += weights[i] * accessor(indices[i]);
56 template <
typename IndexT1,
typename IndexT2,
typename CommonWeightT,
int size1,
int size2>
57 static LinearInterpolationResult<std::tuple<IndexT1, IndexT2>, CommonWeightT, size1 * size2>
58 combineLinearInterpolationResults(
59 LinearInterpolationResult<IndexT1, CommonWeightT, size1> r1,
60 LinearInterpolationResult<IndexT2, CommonWeightT, size2> r2)
62 LinearInterpolationResult<std::tuple<IndexT1, IndexT2>, CommonWeightT, size1 * size2>
64 for (
int i = 0; i < size1; ++i)
66 for (
int j = 0; j < size2; ++j)
68 result.indices[i * size2 + j] = std::make_tuple(r1.indices[i], r2.indices[j]);
69 result.weights[i * size2 + j] = r1.weights[i] * r2.weights[j];
79 cell_size_ = map_.params().cellSize;
80 inv_cell_size_ = 1.0f / cell_size_;
81 grid_size_ = map_.getSize();
82 map_.convertToPseudoSDF();
90 const T*
const theta_ptr,
96 const auto rotation_indices = closestRotationIndexFromDegreesBilinear(*theta_ptr);
98 const auto combined_interpolation =
99 combineLinearInterpolationResults(rotation_indices, position_indices);
100 out_cost[0] = combined_interpolation.template calcWeightedAccess<T>(
101 [
this](
const std::tuple<
int, Eigen::Array<int, 2, 1, 0, 2, 1>>& idx) ->
T
103 auto& [rot, pos] = idx;
105 auto v = map_.value(posIdx, rot);
109 ARMARX_DEBUG <<
"Accessing masked-out costmap cell at index "
114 T value =
T(v.value());
117 value -=
T(cell_size_ * 5.0F);
128 float inv_cell_size_;
131 template <
typename T>
135 if constexpr (std::is_same_v<T, double> || std::is_same_v<T, float>)
136 return static_cast<float>(val);
138 return static_cast<float>(val.a);
142 template <
typename T>
144 wrapDegrees(
const T& deg)
147 d = d -
T(360.0) * ceres::floor(d /
T(360.0));
156 wrapRotationIndex(
const int index)
const
166 template <
typename T>
167 LinearInterpolationResult<Costmap3D::RotationIndex, T, 2>
168 closestRotationIndexFromDegreesBilinear(
const T& degrees_in)
const
170 const T degrees = wrapDegrees(degrees_in);
171 const T deg_per_orientation =
T(360.F) /
T(map_.parameters.
orientations);
174 const int lower_index = wrapRotationIndex(
175 static_cast<int>(
toFloat(ceres::floor(degrees / deg_per_orientation))));
176 const int higher_index = wrapRotationIndex(lower_index + 1);
178 if (lower_index < 0 || lower_index > map_.parameters.
orientations)
180 ARMARX_DEBUG <<
"lower_index out of range: " << lower_index;
184 if (lower_index < 0 || higher_index > map_.parameters.
orientations)
186 ARMARX_DEBUG <<
"higher_index out of range: " << higher_index;
189 const T error_to_lower_normalized =
190 (degrees -
T(lower_index) * deg_per_orientation) / deg_per_orientation;
192 return {.indices = {lower_index, higher_index},
193 .weights = {
T(1) - error_to_lower_normalized, error_to_lower_normalized}};
196 template <
typename T>
197 static Eigen::Transform<T, 2, 1>
198 convertTransform(
const Eigen::Transform<float, 2, 1>& tf)
200 Eigen::Transform<T, 2, 1> out;
201 out.matrix() = tf.matrix().template cast<T>();
205 template <
typename T>
206 LinearInterpolationResult<Costmap3D::Index, T, 4>
207 toIndexBilinear(
const Eigen::Matrix<T, 2, 1>& globalPosition)
const
210 auto tfT = convertTransform<T>(map_.global_T_Costmap3D);
211 Eigen::Matrix<T, 2, 1> localPosition = tfT.inverse() * globalPosition;
213 const T cell =
T(map_.parameters.cellSize);
216 const T vX = (localPosition.x() - cell /
T(2) -
T(map_.sceneBounds.min.x())) / cell;
218 const T vY = (localPosition.y() - cell /
T(2) -
T(map_.sceneBounds.min.y())) / cell;
221 const T vX_shift = vX -
T(0.01);
222 const T vY_shift = vY -
T(0.01);
225 int iXlow =
static_cast<int>(toFloat(ceres::floor(vX_shift)));
226 int iXhigh =
static_cast<int>(toFloat(ceres::ceil(vX_shift)));
227 int iYlow =
static_cast<int>(toFloat(ceres::floor(vY_shift)));
228 int iYhigh =
static_cast<int>(toFloat(ceres::ceil(vY_shift)));
231 const auto size = map_.getSize();
232 int iXlow_cl = std::clamp(iXlow, 0, size.x() - 1);
233 int iXhigh_cl = std::clamp(iXhigh, 0, size.x() - 1);
234 int iYlow_cl = std::clamp(iYlow, 0, size.y() - 1);
235 int iYhigh_cl = std::clamp(iYhigh, 0, size.y() - 1);
239 const T w00 = (
T(iXhigh) - vX) * (
T(iYhigh) - vY);
240 const T w10 = (vX -
T(iXlow)) * (
T(iYhigh) - vY);
241 const T w01 = (
T(iXhigh) - vX) * (vY -
T(iYlow));
242 const T w11 = (vX -
T(iXlow)) * (vY -
T(iYlow));
244 LinearInterpolationResult<Costmap3D::Index, T, 4> result;
246 result.indices[0] = {iXlow_cl, iYlow_cl};
247 result.indices[1] = {iXhigh_cl, iYlow_cl};
248 result.indices[2] = {iXlow_cl, iYhigh_cl};
249 result.indices[3] = {iXhigh_cl, iYhigh_cl};
251 result.weights[0] = w00;
252 result.weights[1] = w10;
253 result.weights[2] = w01;
254 result.weights[3] = w11;