constint stride = wide_limits_.num_x_cells; // First we compute the maximum probability for each (x0, y) achieved in the // span defined by x0 <= x < x0 + width. std::vector<float>& intermediate = *reusable_intermediate_grid; intermediate.resize(wide_limits_.num_x_cells * limits.num_y_cells); // 对每一行从左到右横着做一次滑窗, 将滑窗后的地图放在intermediate(临时数据)中 for (int y = 0; y != limits.num_y_cells; ++y) { SlidingWindowMaximum current_values; // 获取 grid 的x坐标的索引: 首先获取 (0, y) current_values.AddValue( 1.f - std::abs(grid.GetCorrespondenceCost(Eigen::Array2i(0, y))));
// Step: 1 滑动窗口在x方向开始划入地图, 所以只进行 填入值 // intermediate的索引x + width - 1 + y * stride的范围是 [0, width-2] 再加上 y * stride // grid的索引 x + width 的坐标范围是 [1, width-1] for (int x = -width + 1; x != 0; ++x) { intermediate[x + width - 1 + y * stride] = current_values.GetMaximum(); if (x + width < limits.num_x_cells) { current_values.AddValue(1.f - std::abs(grid.GetCorrespondenceCost( Eigen::Array2i(x + width, y)))); } }
// Step: 2 滑动窗口已经完全在地图里了, 滑窗进行一入一出的操作 // x + width - 1 + y * stride 的范围是 [width-1, limits.num_x_cells-2] 再加上 y * stride // grid的索引 x + width 的坐标范围是 [width, limits.num_x_cells-width-1] for (int x = 0; x < limits.num_x_cells - width; ++x) { intermediate[x + width - 1 + y * stride] = current_values.GetMaximum(); current_values.RemoveValue( 1.f - std::abs(grid.GetCorrespondenceCost(Eigen::Array2i(x, y)))); current_values.AddValue(1.f - std::abs(grid.GetCorrespondenceCost( Eigen::Array2i(x + width, y)))); }
// Step: 3 滑动窗口正在划出, 一次减少一个值, 所以intermediate的宽度比grid多 width-1 // x + width - 1 + y * stride 的范围是 [limits.num_x_cells-1, limits.num_x_cells+width-1] 再加上 y * stride // grid 的索引 x的范围是 [limits.num_x_cells-width, limits.num_x_cells-1] for (int x = std::max(limits.num_x_cells - width, 0); x != limits.num_x_cells; ++x) { intermediate[x + width - 1 + y * stride] = current_values.GetMaximum(); current_values.RemoveValue( 1.f - std::abs(grid.GetCorrespondenceCost(Eigen::Array2i(x, y)))); } // 理论上, 滑窗走完地图的一行之后应该是空的, 经过 只入, 一出一入, 只出, 3个步骤 current_values.CheckIsEmpty(); }
// For each (x, y), we compute the maximum probability in the width x width // region starting at each (x, y) and precompute the resulting bound on the // score.
// 根据intermediate的值, 对每一列从下到上竖着再做一次滑窗, 这个才是真正的地图cells_ for (int x = 0; x != wide_limits_.num_x_cells; ++x) { SlidingWindowMaximum current_values;
current_values.AddValue(intermediate[x]); for (int y = -width + 1; y != 0; ++y) { cells_[x + (y + width - 1) * stride] = ComputeCellValue(current_values.GetMaximum()); if (y + width < limits.num_y_cells) { current_values.AddValue(intermediate[x + (y + width) * stride]); } } for (int y = 0; y < limits.num_y_cells - width; ++y) { cells_[x + (y + width - 1) * stride] = ComputeCellValue(current_values.GetMaximum()); current_values.RemoveValue(intermediate[x + y * stride]); current_values.AddValue(intermediate[x + (y + width) * stride]); } for (int y = std::max(limits.num_y_cells - width, 0); y != limits.num_y_cells; ++y) { cells_[x + (y + width - 1) * stride] = ComputeCellValue(current_values.GetMaximum()); current_values.RemoveValue(intermediate[x + y * stride]); } current_values.CheckIsEmpty(); } }