id
cartographer主要处理数据包括:node和submap;这些数据,主要通过MapById 类进行封装,并处理,因此,有必要研究下MapById类。理解了id类,也就理解类carto中数据结构以及trajectroy nodeid submapid等重要概念。
namespace cartographer {
namespace mapping {
/*
每一个轨迹trajectory上有多个节点node。
如何唯一的表达这些节点node?节点标号:轨迹id+{0,1,2,...}
*/
struct NodeId {
NodeId(int trajectory_id, int node_index)
: trajectory_id(trajectory_id), node_index(node_index) {}
int trajectory_id;
int node_index;
};
/*
一般来说,重建全局地图global map时,是由多个submap组成。
如何给这些submap标号? 轨迹id+ {0,1,2,3...}
*/
struct SubmapId {
SubmapId(int trajectory_id, int submap_index)
: trajectory_id(trajectory_id), submap_index(submap_index) {}
int trajectory_id;
int submap_index;
};
template <typename IteratorType>
class Range {
private:
IteratorType begin_;
IteratorType end_;
public:
Range(const IteratorType& begin, const IteratorType& end)
: begin_(begin), end_(end) {}
};
// Reminiscent of std::map, but indexed by 'IdType' which can be 'NodeId' or
// 'SubmapId'.
/*
MapById:通过id(IdType,包括 trajectory_id, submap_index;),和 data(DataType)形成 一个表(map),结构如下:
1 trajectory1 : can_append_(true),{(0,submap),(1,submap),(2,submap),(3,submap),(4,submap)...}
2 trajectory2 : can_append_(true),{(0,submap),(1,submap),(2,submap),(3,submap),(4,submap)...}
3 trajectory3 : can_append_(true),{(0,submap),(1,submap),(2,submap),(3,submap),(4,submap)...}
自定义该表(map中data)的索引,包括三个元素。
ConstIterator{
typename std::map<int, MapByIndex>::const_iterator current_trajectory_; //当前轨迹iter
typename std::map<int, MapByIndex>::const_iterator end_trajectory_;// 最后轨迹iter
typename std::map<int, DataType>::const_iterator current_data_;//当前值,指向当前轨迹的某个data
}
ConstTrajectoryIterator{
typename std::map<int, MapByIndex>::const_iterator current_trajectory_;
}
*/
template <typename IdType, typename DataType>
class MapById {
private:
struct MapByIndex {
bool can_append_ = true;
std::map<int, DataType> data_;
};
std::map<int, MapByIndex> trajectories_;
public:
struct IdDataReference {
IdType id;
const DataType& data;
};
class ConstIterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = IdDataReference;
using difference_type = int64;
using pointer = std::unique_ptr<const IdDataReference>;
using reference = const IdDataReference&;
// 通过表和轨迹id(trajectory_id)获得索引,current_data_为该轨迹的第一个validData值
explicit ConstIterator(const MapById& map_by_id, const int trajectory_id)
: current_trajectory_(
map_by_id.trajectories_.lower_bound(trajectory_id)),
end_trajectory_(map_by_id.trajectories_.end()) {
if (current_trajectory_ != end_trajectory_) {
current_data_ = current_trajectory_->second.data_.begin();
AdvanceToValidDataIterator();
}
}
// 通过表和data的Id获取索引。
explicit ConstIterator(const MapById& map_by_id, const IdType& id)
: current_trajectory_(map_by_id.trajectories_.find(id.trajectory_id)),
end_trajectory_(map_by_id.trajectories_.end()) {
if (current_trajectory_ != end_trajectory_) {
current_data_ =
current_trajectory_->second.data_.find(MapById::GetIndex(id));
if (current_data_ == current_trajectory_->second.data_.end()) {
current_trajectory_ = end_trajectory_;
}
}
}
IdDataReference operator*() const { // 对* 重载
CHECK(current_trajectory_ != end_trajectory_);
return IdDataReference{
IdType{current_trajectory_->first, current_data_->first},
current_data_->second};
}
std::unique_ptr<const IdDataReference> operator->() const {
return absl::make_unique<const IdDataReference>(this->operator*());
}
private:
// 如果数据到了current_trajectory_末尾,那么移动到下一个trajectory_的begin()
void AdvanceToValidDataIterator() {
CHECK(current_trajectory_ != end_trajectory_);
while (current_data_ == current_trajectory_->second.data_.end()) {
++current_trajectory_;
if (current_trajectory_ == end_trajectory_) {
return;
}
current_data_ = current_trajectory_->second.data_.begin();
}
}
typename std::map<int, MapByIndex>::const_iterator current_trajectory_;
typename std::map<int, MapByIndex>::const_iterator end_trajectory_;
typename std::map<int, DataType>::const_iterator current_data_;
};
class ConstTrajectoryIterator {
typename std::map<int, MapByIndex>::const_iterator current_trajectory_;
};
// Appends data to a trajectories_[trajectory_id], creating trajectories as needed.
// 把某个数据加入到trajectory_id对应的trajectory下
IdType Append(const int trajectory_id, const DataType& data) {
CHECK_GE(trajectory_id, 0);
auto& trajectory = trajectories_[trajectory_id];
CHECK(trajectory.can_append_);
const int index =
trajectory.data_.empty() ? 0 : trajectory.data_.rbegin()->first + 1; //rbegin,Return reverse iterator to reverse beginning
trajectory.data_.emplace(index, data);
return IdType{trajectory_id, index};
}
// Returns an iterator to the element at 'id' or the end iterator if it does
// not exist.
// 返回 本表(map)中,id对应索引(ConstIterator形式)
ConstIterator find(const IdType& id) const {
return ConstIterator(*this, id);
}
// Inserts data (which must not exist already) into a trajectory.
// 把id对应的data插入到表中
void Insert(const IdType& id, const DataType& data) {
CHECK_GE(id.trajectory_id, 0);
CHECK_GE(GetIndex(id), 0);
auto& trajectory = trajectories_[id.trajectory_id];
trajectory.can_append_ = false;
CHECK(trajectory.data_.emplace(GetIndex(id), data).second);
}
// Removes the data for 'id' which must exist.
// 删除表中对应id的数据
void Trim(const IdType& id) {
auto& trajectory = trajectories_.at(id.trajectory_id);
const auto it = trajectory.data_.find(GetIndex(id));
CHECK(it != trajectory.data_.end()) << id;
if (std::next(it) == trajectory.data_.end()) {
// We are removing the data with the highest index from this trajectory.
// We assume that we will never append to it anymore. If we did, we would
// have to make sure that gaps in indices are properly chosen to maintain
// correct connectivity.
trajectory.can_append_ = false;
}
trajectory.data_.erase(it);
if (trajectory.data_.empty()) {
trajectories_.erase(id.trajectory_id);
}
}
// 查看是否有对应id的数据
bool Contains(const IdType& id) const {
return trajectories_.count(id.trajectory_id) != 0 &&
trajectories_.at(id.trajectory_id).d ata_.count(GetIndex(id)) != 0;
}
// 返回表中固定id对应的数据
const DataType& at(const IdType& id) const {
return trajectories_.at(id.trajectory_id).data_.at(GetIndex(id));
}
DataType& at(const IdType& id) {
return trajectories_.at(id.trajectory_id).data_.at(GetIndex(id));
}
// 某个trajectory_id 对应的首地址ConstIterator表示形式
ConstIterator BeginOfTrajectory(const int trajectory_id) const {
return ConstIterator(*this, trajectory_id);
}
// 某个trajectory_id 对应的尾地址ConstIterator表示形式
ConstIterator EndOfTrajectory(const int trajectory_id) const {
return BeginOfTrajectory(trajectory_id + 1);
}
// Returns 0 if 'trajectory_id' does not exist.
//整个表轨迹个数
size_t SizeOfTrajectoryOrZero(const int trajectory_id) const {
return trajectories_.count(trajectory_id)
? trajectories_.at(trajectory_id).data_.size()
: 0;
}
// Returns count of all elements.
//整个表数据个数
size_t size() const {
size_t size = 0;
for (const auto& item : trajectories_) {
size += item.second.data_.size();
}
return size;
}
// Returns Range object for range-based loops over the nodes of a trajectory.
Range<ConstIterator> trajectory(const int trajectory_id) const {
return Range<ConstIterator>(BeginOfTrajectory(trajectory_id),
EndOfTrajectory(trajectory_id));
}
// Returns Range object for range-based loops over the trajectory IDs.
Range<ConstTrajectoryIterator> trajectory_ids() const {
return Range<ConstTrajectoryIterator>(
ConstTrajectoryIterator(trajectories_.begin()),
ConstTrajectoryIterator(trajectories_.end()));
}
ConstIterator begin() const { return BeginOfTrajectory(0); }
ConstIterator end() const {
return BeginOfTrajectory(std::numeric_limits<int>::max());
}
bool empty() const { return begin() == end(); }
// Returns an iterator to the first element in the container belonging to
// trajectory 'trajectory_id' whose time is not considered to go before
// 'time', or EndOfTrajectory(trajectory_id) if all keys are considered to go
// before 'time'.
ConstIterator lower_bound(const int trajectory_id,
const common::Time time) const {
if (SizeOfTrajectoryOrZero(trajectory_id) == 0) {
return EndOfTrajectory(trajectory_id);
}
const std::map<int, DataType>& trajectory =
trajectories_.at(trajectory_id).data_;
if (internal::GetTime(std::prev(trajectory.end())->second) < time) {
return EndOfTrajectory(trajectory_id);
}
auto left = trajectory.begin();
auto right = std::prev(trajectory.end());
while (left != right) {
const int middle = left->first + (right->first - left->first) / 2;
const auto lower_bound_middle = trajectory.lower_bound(middle);
if (internal::GetTime(lower_bound_middle->second) < time) {
left = std::next(lower_bound_middle);
} else {
right = lower_bound_middle;
}
}
return ConstIterator(*this, IdType{trajectory_id, left->first});
}
private:
static int GetIndex(const NodeId& id) { return id.node_index; }
static int GetIndex(const SubmapId& id) { return id.submap_index; }
};
} // namespace mapping
} // namespace cartographer