ProbabilityGrid->Grid2D->MapLimits->CellLimits
class Grid2D
{
//成员变量
MapLimits limits_; // 表示2d地图的分辨率,大小
std::vector correspondenct_cost // 对应的值大小为celllimits.num_x_cells * celllimits.num_y_cells
float min_correspondece_cost_;
float max_correspondece_cost_;
std::vector update_indices_;
Eigen::AlignedBox2i known_cells_box_;
// 维护更新时候用的值
protected:
const std::vector& correspondence_cost_cells() const
{
return correspondence_cost_cells_;
}
const std::vector& update_indices() const { return update_indices_; }
const Eigen::AlignedBox2i& known_cells_box() const {return known_cells_box_;}
std::vector* mutable_correspondence_cost_cells() {return &correspondence_cost_cells_;}
std::vector* mutable_update_indices() { return &update_indices_; }
Eigen::AlignedBox2i* mutable_known_cells_box() { return &known_cells_box_; }
// Converts a 'cell_index' into an index into 'cells_'.
int ToFlatIndex(const Eigen::Array2i& cell_index) const;
};
注意就是应用查找表更新地图
bool ProbabilityGrid::ApplyLookupTable(const Eigen::Array2i& cell_index,
const std::vector& table)
{
DCHECK_EQ(table.size(), kUpdateMarker);
const int flat_index = ToFlatIndex(cell_index);
uint16* cell = &(*mutable_correspondence_cost_cells())[flat_index];
if (*cell >= kUpdateMarker)
{
return false;
}
mutable_update_indices()->push_back(flat_index);
*cell = table[*cell];
DCHECK_GE(*cell, kUpdateMarker);
mutable_known_cells_box()->extend(cell_index.matrix());
return true;
}
这里面主要维护几个表和有几个转换关于Probability和CorrespondenceCost
inline float ProbabilityToCorrespondenceCost(const float probability)
{
return 1.f - probability;
}
inline float CorrespondenceCostToProbability(const float correspondence_cost)
{
return 1.f - correspondence_cost;
}
// odds = p/(1-p)
inline float Odds(float probability)
{
return probability / (1.f - probability);
}
// p = odds/(odds+1)
inline float ProbabilityFromOdds(const float odds)
{
return odds / (odds + 1.f);
}
constexpr float kMinProbability = 0.1f; // min probability
constexpr float kMaxProbability = 1.f - kMinProbability; // max probability
constexpr float kMinCorrespondenceCost = 1.f - kMaxProbability; // minc = 1-maxp
constexpr float kMaxCorrespondenceCost = 1.f - kMinProbability; // maxc = 1-minp
inline float ClampProbability(const float probability)
{
return Clamp(probability, kMinProbability, kMaxProbability);
}
inline float ClampCorrespondenceCost(const float correspondence_cost)
{
return Clamp(correspondence_cost, kMinCorrespondenceCost,kMaxCorrespondenceCost);
}
constexpr uint16 kUnknownProbabilityValue = 0;
constexpr uint16 kUnknownCorrespondenceValue = kUnknownProbabilityValue;
constexpr uint16 kUpdateMarker = 1u << 15; // 32768
inline uint16 CorrespondenceCostToValue(const float correspondence_cost)
{
return BoundedFloatToValue(correspondence_cost, kMinCorrespondenceCost, kMaxCorrespondenceCost);
}
//converts a probability to a uint16 in the range[1, 32767] range
inline uint16 ProbabilityToValue(const float probability)
{
return BoundedFloatToValue(probability, kMinProbability, kMaxProbability);
}
kValueToCorrespondenceCost
extern const std::vector* const kValueToProbability;
extern const std::vector* const kValueToCorrespondenceCost;
const std::vector* const kValueToProbability = PrecomputeValueToProbability().release();
const std::vector* const kValueToCorrespondenceCost = PrecomputeValueToCorrespondenceCost().release();
重点介绍
PrecomputeValueToProbability
PrecomputeValueToCorrespondenceCost
均使用了PrecomputeValueToBoundedFloat函数继续计算用于保留更新和不更新时候的表
计算出结果result为65536个元素,里面对应float值
std::unique_ptr> PrecomputeValueToBoundedFloat(const uint16 unknown_value,
const float unknown_result,
const float lower_bound,
const float upper_bound)
{
auto result = make_unique>();
// Repeat two times, so that both values with and without the update marker
// can be converted to a probability.
for (int repeat = 0; repeat != 2; ++repeat)
{
for (int value = 0; value != 32768; ++value)
{
result->push_back(SlowValueToBoundedFloat(value, unknown_value, unknown_result, lower_bound, upper_bound));
}
}
return result;
}
// converts a uint16 to a probability in the range[kMinProbability, kMaxProbability]
// loop up table
inline float ValueToProbability(const uint16 value)
{
return (*kValueToProbability)[value];
}
// Converts a uint16 (which may or may not have the update marker set) to a
// correspondence cost in the range [kMinCorrespondenceCost,
// kMaxCorrespondenceCost].
inline float ValueToCorrespondenceCost(const uint16 value)
{
return (*kValueToCorrespondenceCost)[value];
}
举一个例子,CorrespondenceCostValueToProbabilityValue同理
inline uint16 ProbabilityValueToCorrespondenceCostValue(uint16 probability_value)
{
if (probability_value == kUnknownProbabilityValue)
{
return kUnknownCorrespondenceValue;
}
// !!!!!!!!!!注意
bool update_carry = false;
if (probability_value > kUpdateMarker) // 概率值大于32768
probability_value -= kUpdateMarker; //
update_carry = true;
}
uint16 result = CorrespondenceCostToValue( // correspondcost->uint16
ProbabilityToCorrespondenceCost( // probability->correspondcost
ValueToProbability(probability_value))); // value->probability
if (update_carry) result += kUpdateMarker;
return result;
}
std::vector ComputeLookupTableToApplyCorrespondenceCostOdds(float odds)
{
std::vector result;
result.push_back(CorrespondenceCostToValue(
ProbabilityToCorrespondenceCost(
ProbabilityFromOdds(odds))) +
kUpdateMarker);
//公式3
for (int cell = 1; cell != 32768; ++cell)
{
result.push_back(CorrespondenceCostToValue(
ProbabilityToCorrespondenceCost(ProbabilityFromOdds(
odds * Odds(CorrespondenceCostToProbability((*kValueToCorrespondenceCost)[cell]))))) +
kUpdateMarker);
}
return result;
}
int main(int argc, char *argv[])
{
//模拟一帧激光数据
RangeData range_data;
range_data.returns.emplace_back(-3.5f, 0.5f, 0.f);
range_data.returns.emplace_back(-2.5f, 1.5f, 0.f);
range_data.returns.emplace_back(-1.5f, 2.5f, 0.f);
range_data.returns.emplace_back(-0.5f, 3.5f, 0.f);
range_data.returns.emplace_back(-13.5f, 1.5f, 0.f);
range_data.returns.emplace_back(-20.5f, 1.5f, 0.f);
range_data.returns.emplace_back(-1.5f, 9.5f, 0.f);
range_data.returns.emplace_back(-5.5f, 7.5f, 0.f);
range_data.returns.emplace_back(30.5f, 20.5f, 0.f);
range_data.returns.emplace_back(200.5f, 100.5f, 0.f);
range_data.returns.emplace_back(1.5f, 2.5f, 0.f);
range_data.returns.emplace_back(0.5f, 3.5f, 0.f);
range_data.returns.emplace_back(13.5f, 1.5f, 0.f);
range_data.returns.emplace_back(20.5f, 1.5f, 0.f);
range_data.returns.emplace_back(1.5f, 9.5f, 0.f);
range_data.returns.emplace_back(5.5f, 7.5f, 0.f);
range_data.returns.emplace_back(30.5f, 20.5f, 0.f);
range_data.returns.emplace_back(200.5f, 100.5f, 0.f);
range_data.returns.emplace_back(100.5f, 200.5f, 0.f);
range_data.returns.emplace_back(60.5f, 30.5f, 0.f);
range_data.returns.emplace_back(13.5f, 15.f, 0.f);
range_data.returns.emplace_back(20.5f, 150.f, 0.f);
range_data.returns.emplace_back(5.f, 49.5f, 0.f);
range_data.returns.emplace_back(56.5f, 17.5f, 0.f);
range_data.origin.x() = 70.5f;
range_data.origin.y() = 72.5f;
ProbabilityGrid grid(MapLimits(1., Eigen::Vector2d(150., 150.), CellLimits(150, 150))); //定义一个map
//将这帧激光数据插入地图中
Insert(range_data, &grid);
constexpr int kUnKnown = 128;
const CellLimits& celllimits = grid.limits().cell_limits();
const int width = celllimits.num_x_cells;
const int height = celllimits.num_y_cells;
cv::Mat image = cv::Mat(width, height, CV_8UC3);
for(const Eigen::Array2i& xy_index: XYIndexRangeIterator(grid.limits().cell_limits()))
{
CHECK(grid.limits().Contains(xy_index));
const unsigned char value = grid.IsKnown(xy_index)? RoundToInt((1-grid.GetProbability(xy_index))*255+0):kUnKnown;
image.at(xy_index.x(), xy_index.y()) = cv::Vec3b(value, value, value);
}
cv::imshow("image", image);
cv::imwrite("image.png", image);
cv::waitKey(0);
return 1;
}
Insert函数, 两个表维护hit和miss
void Insert(const RangeData& range_data, ProbabilityGrid* const probability_grid)
{
const std::vector hit_table_(ComputeLookupTableToApplyCorrespondenceCostOdds(
Odds(0.9)));
const std::vector miss_table_(ComputeLookupTableToApplyCorrespondenceCostOdds(
Odds(0.1)));
// By not finishing the update after hits are inserted, we give hits priority
// (i.e. no hits will be ignored because of a miss in the same cell).
CastRays(range_data, hit_table_, miss_table_, true,
CHECK_NOTNULL(probability_grid));
probability_grid->FinishUpdate();
}