id.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CARTOGRAPHER_MAPPING_ID_H_
18 #define CARTOGRAPHER_MAPPING_ID_H_
19 
20 #include <algorithm>
21 #include <iostream>
22 #include <iterator>
23 #include <limits>
24 #include <map>
25 #include <memory>
26 #include <ostream>
27 #include <tuple>
28 #include <vector>
29 
33 #include "cartographer/mapping/proto/pose_graph.pb.h"
34 #include "glog/logging.h"
35 
36 namespace cartographer {
37 namespace mapping {
38 namespace internal {
39 
40 template <class T>
41 auto GetTimeImpl(const T& t, int) -> decltype(t.time()) {
42  return t.time();
43 }
44 template <class T>
45 auto GetTimeImpl(const T& t, unsigned) -> decltype(t.time) {
46  return t.time;
47 }
48 template <class T>
49 common::Time GetTime(const T& t) {
50  return GetTimeImpl(t, 0);
51 }
52 
53 } // namespace internal
54 
55 // Uniquely identifies a trajectory node using a combination of a unique
56 // trajectory ID and a zero-based index of the node inside that trajectory.
57 struct NodeId {
60 
61  bool operator==(const NodeId& other) const {
62  return std::forward_as_tuple(trajectory_id, node_index) ==
63  std::forward_as_tuple(other.trajectory_id, other.node_index);
64  }
65 
66  bool operator!=(const NodeId& other) const { return !operator==(other); }
67 
68  bool operator<(const NodeId& other) const {
69  return std::forward_as_tuple(trajectory_id, node_index) <
70  std::forward_as_tuple(other.trajectory_id, other.node_index);
71  }
72 
73  void ToProto(proto::NodeId* proto) const {
74  proto->set_trajectory_id(trajectory_id);
75  proto->set_node_index(node_index);
76  }
77 };
78 
79 inline std::ostream& operator<<(std::ostream& os, const NodeId& v) {
80  return os << "(" << v.trajectory_id << ", " << v.node_index << ")";
81 }
82 
83 // Uniquely identifies a submap using a combination of a unique trajectory ID
84 // and a zero-based index of the submap inside that trajectory.
85 struct SubmapId {
88 
89  bool operator==(const SubmapId& other) const {
90  return std::forward_as_tuple(trajectory_id, submap_index) ==
91  std::forward_as_tuple(other.trajectory_id, other.submap_index);
92  }
93 
94  bool operator!=(const SubmapId& other) const { return !operator==(other); }
95 
96  bool operator<(const SubmapId& other) const {
97  return std::forward_as_tuple(trajectory_id, submap_index) <
98  std::forward_as_tuple(other.trajectory_id, other.submap_index);
99  }
100 
101  void ToProto(proto::SubmapId* proto) const {
102  proto->set_trajectory_id(trajectory_id);
103  proto->set_submap_index(submap_index);
104  }
105 };
106 
107 inline std::ostream& operator<<(std::ostream& os, const SubmapId& v) {
108  return os << "(" << v.trajectory_id << ", " << v.submap_index << ")";
109 }
110 
111 template <typename IteratorType>
112 class Range {
113  public:
114  Range(const IteratorType& begin, const IteratorType& end)
115  : begin_(begin), end_(end) {}
116 
117  IteratorType begin() const { return begin_; }
118  IteratorType end() const { return end_; }
119 
120  private:
121  IteratorType begin_;
122  IteratorType end_;
123 };
124 
125 // Reminiscent of std::map, but indexed by 'IdType' which can be 'NodeId' or
126 // 'SubmapId'.
127 // Note: This container will only ever contain non-empty trajectories. Trimming
128 // the last remaining node of a trajectory drops the trajectory.
129 template <typename IdType, typename DataType>
130 class MapById {
131  private:
132  struct MapByIndex;
133 
134  public:
136  IdType id;
137  const DataType& data;
138  };
139 
141  public:
142  using iterator_category = std::bidirectional_iterator_tag;
145  using pointer = std::unique_ptr<const IdDataReference>;
146  using reference = const IdDataReference&;
147 
148  explicit ConstIterator(const MapById& map_by_id, const int trajectory_id)
149  : current_trajectory_(
150  map_by_id.trajectories_.lower_bound(trajectory_id)),
151  end_trajectory_(map_by_id.trajectories_.end()) {
152  if (current_trajectory_ != end_trajectory_) {
153  current_data_ = current_trajectory_->second.data_.begin();
154  AdvanceToValidDataIterator();
155  }
156  }
157 
158  explicit ConstIterator(const MapById& map_by_id, const IdType& id)
159  : current_trajectory_(map_by_id.trajectories_.find(id.trajectory_id)),
160  end_trajectory_(map_by_id.trajectories_.end()) {
161  if (current_trajectory_ != end_trajectory_) {
162  current_data_ =
163  current_trajectory_->second.data_.find(MapById::GetIndex(id));
164  if (current_data_ == current_trajectory_->second.data_.end()) {
165  current_trajectory_ = end_trajectory_;
166  }
167  }
168  }
169 
171  CHECK(current_trajectory_ != end_trajectory_);
172  return IdDataReference{
173  IdType{current_trajectory_->first, current_data_->first},
174  current_data_->second};
175  }
176 
177  std::unique_ptr<const IdDataReference> operator->() const {
178  return common::make_unique<const IdDataReference>(this->operator*());
179  }
180 
182  CHECK(current_trajectory_ != end_trajectory_);
183  ++current_data_;
184  AdvanceToValidDataIterator();
185  return *this;
186  }
187 
189  while (current_trajectory_ == end_trajectory_ ||
190  current_data_ == current_trajectory_->second.data_.begin()) {
191  --current_trajectory_;
192  current_data_ = current_trajectory_->second.data_.end();
193  }
194  --current_data_;
195  return *this;
196  }
197 
198  bool operator==(const ConstIterator& it) const {
199  if (current_trajectory_ == end_trajectory_ ||
201  return current_trajectory_ == it.current_trajectory_;
202  }
203  return current_trajectory_ == it.current_trajectory_ &&
204  current_data_ == it.current_data_;
205  }
206 
207  bool operator!=(const ConstIterator& it) const { return !operator==(it); }
208 
209  private:
211  CHECK(current_trajectory_ != end_trajectory_);
212  while (current_data_ == current_trajectory_->second.data_.end()) {
213  ++current_trajectory_;
214  if (current_trajectory_ == end_trajectory_) {
215  return;
216  }
217  current_data_ = current_trajectory_->second.data_.begin();
218  }
219  }
220 
221  typename std::map<int, MapByIndex>::const_iterator current_trajectory_;
222  typename std::map<int, MapByIndex>::const_iterator end_trajectory_;
223  typename std::map<int, DataType>::const_iterator current_data_;
224  };
225 
227  public:
228  using iterator_category = std::bidirectional_iterator_tag;
229  using value_type = int;
231  using pointer = const int*;
232  using reference = const int&;
233 
235  typename std::map<int, MapByIndex>::const_iterator current_trajectory)
236  : current_trajectory_(current_trajectory) {}
237 
238  int operator*() const { return current_trajectory_->first; }
239 
241  ++current_trajectory_;
242  return *this;
243  }
244 
246  --current_trajectory_;
247  return *this;
248  }
249 
250  bool operator==(const ConstTrajectoryIterator& it) const {
251  return current_trajectory_ == it.current_trajectory_;
252  }
253 
254  bool operator!=(const ConstTrajectoryIterator& it) const {
255  return !operator==(it);
256  }
257 
258  private:
259  typename std::map<int, MapByIndex>::const_iterator current_trajectory_;
260  };
261 
262  // Appends data to a 'trajectory_id', creating trajectories as needed.
263  IdType Append(const int trajectory_id, const DataType& data) {
264  CHECK_GE(trajectory_id, 0);
265  auto& trajectory = trajectories_[trajectory_id];
266  CHECK(trajectory.can_append_);
267  const int index =
268  trajectory.data_.empty() ? 0 : trajectory.data_.rbegin()->first + 1;
269  trajectory.data_.emplace(index, data);
270  return IdType{trajectory_id, index};
271  }
272 
273  // Returns an iterator to the element at 'id' or the end iterator if it does
274  // not exist.
275  ConstIterator find(const IdType& id) const {
276  return ConstIterator(*this, id);
277  }
278 
279  // Inserts data (which must not exist already) into a trajectory.
280  void Insert(const IdType& id, const DataType& data) {
281  CHECK_GE(id.trajectory_id, 0);
282  CHECK_GE(GetIndex(id), 0);
283  auto& trajectory = trajectories_[id.trajectory_id];
284  trajectory.can_append_ = false;
285  CHECK(trajectory.data_.emplace(GetIndex(id), data).second);
286  }
287 
288  // Removes the data for 'id' which must exist.
289  void Trim(const IdType& id) {
290  auto& trajectory = trajectories_.at(id.trajectory_id);
291  const auto it = trajectory.data_.find(GetIndex(id));
292  CHECK(it != trajectory.data_.end());
293  if (std::next(it) == trajectory.data_.end()) {
294  // We are removing the data with the highest index from this trajectory.
295  // We assume that we will never append to it anymore. If we did, we would
296  // have to make sure that gaps in indices are properly chosen to maintain
297  // correct connectivity.
298  trajectory.can_append_ = false;
299  }
300  trajectory.data_.erase(it);
301  if (trajectory.data_.empty()) {
302  trajectories_.erase(id.trajectory_id);
303  }
304  }
305 
306  bool Contains(const IdType& id) const {
307  return trajectories_.count(id.trajectory_id) != 0 &&
308  trajectories_.at(id.trajectory_id).data_.count(GetIndex(id)) != 0;
309  }
310 
311  const DataType& at(const IdType& id) const {
312  return trajectories_.at(id.trajectory_id).data_.at(GetIndex(id));
313  }
314 
315  DataType& at(const IdType& id) {
316  return trajectories_.at(id.trajectory_id).data_.at(GetIndex(id));
317  }
318 
319  // Support querying by trajectory.
320  ConstIterator BeginOfTrajectory(const int trajectory_id) const {
321  return ConstIterator(*this, trajectory_id);
322  }
323  ConstIterator EndOfTrajectory(const int trajectory_id) const {
324  return BeginOfTrajectory(trajectory_id + 1);
325  }
326 
327  // Returns 0 if 'trajectory_id' does not exist.
328  size_t SizeOfTrajectoryOrZero(const int trajectory_id) const {
329  return trajectories_.count(trajectory_id)
330  ? trajectories_.at(trajectory_id).data_.size()
331  : 0;
332  }
333 
334  // Returns count of all elements.
335  size_t size() const {
336  size_t size = 0;
337  for (const auto& item : trajectories_) {
338  size += item.second.data_.size();
339  }
340  return size;
341  }
342 
343  // Returns Range object for range-based loops over the nodes of a trajectory.
344  Range<ConstIterator> trajectory(const int trajectory_id) const {
345  return Range<ConstIterator>(BeginOfTrajectory(trajectory_id),
346  EndOfTrajectory(trajectory_id));
347  }
348 
349  // Returns Range object for range-based loops over the trajectory IDs.
352  ConstTrajectoryIterator(trajectories_.begin()),
353  ConstTrajectoryIterator(trajectories_.end()));
354  }
355 
356  ConstIterator begin() const { return BeginOfTrajectory(0); }
357  ConstIterator end() const {
358  return BeginOfTrajectory(std::numeric_limits<int>::max());
359  }
360 
361  bool empty() const { return begin() == end(); }
362 
363  // Returns an iterator to the first element in the container belonging to
364  // trajectory 'trajectory_id' whose time is not considered to go before
365  // 'time', or EndOfTrajectory(trajectory_id) if all keys are considered to go
366  // before 'time'.
367  ConstIterator lower_bound(const int trajectory_id,
368  const common::Time time) const {
369  if (SizeOfTrajectoryOrZero(trajectory_id) == 0) {
370  return EndOfTrajectory(trajectory_id);
371  }
372 
373  const std::map<int, DataType>& trajectory =
374  trajectories_.at(trajectory_id).data_;
375  if (internal::GetTime(std::prev(trajectory.end())->second) < time) {
376  return EndOfTrajectory(trajectory_id);
377  }
378  auto left = trajectory.begin();
379  auto right = std::prev(trajectory.end());
380  while (left != right) {
381  const int middle = left->first + (right->first - left->first) / 2;
382  const auto lower_bound_middle = trajectory.lower_bound(middle);
383  if (internal::GetTime(lower_bound_middle->second) < time) {
384  left = std::next(lower_bound_middle);
385  } else {
386  right = lower_bound_middle;
387  }
388  }
389 
390  return ConstIterator(*this, IdType{trajectory_id, left->first});
391  }
392 
393  private:
394  struct MapByIndex {
395  bool can_append_ = true;
396  std::map<int, DataType> data_;
397  };
398 
399  static int GetIndex(const NodeId& id) { return id.node_index; }
400  static int GetIndex(const SubmapId& id) { return id.submap_index; }
401 
402  std::map<int, MapByIndex> trajectories_;
403 };
404 
405 } // namespace mapping
406 } // namespace cartographer
407 
408 #endif // CARTOGRAPHER_MAPPING_ID_H_
std::unique_ptr< const IdDataReference > operator->() const
Definition: id.h:177
bool operator==(const ConstTrajectoryIterator &it) const
Definition: id.h:250
IteratorType begin_
Definition: id.h:121
bool operator<(const NodeId &other) const
Definition: id.h:68
ConstIterator end() const
Definition: id.h:357
std::map< int, MapByIndex >::const_iterator current_trajectory_
Definition: id.h:221
ConstTrajectoryIterator & operator--()
Definition: id.h:245
bool operator!=(const NodeId &other) const
Definition: id.h:66
bool empty() const
Definition: id.h:361
bool operator==(const ConstIterator &it) const
Definition: id.h:198
void Trim(const IdType &id)
Definition: id.h:289
bool operator<(const SubmapId &other) const
Definition: id.h:96
std::map< int, DataType > data_
Definition: id.h:396
common::Time GetTime(const T &t)
Definition: id.h:49
const DataType & at(const IdType &id) const
Definition: id.h:311
void ToProto(proto::SubmapId *proto) const
Definition: id.h:101
int64_t int64
Definition: port.h:33
std::bidirectional_iterator_tag iterator_category
Definition: id.h:228
size_t SizeOfTrajectoryOrZero(const int trajectory_id) const
Definition: id.h:328
void Insert(const IdType &id, const DataType &data)
Definition: id.h:280
static int GetIndex(const NodeId &id)
Definition: id.h:399
Range< ConstIterator > trajectory(const int trajectory_id) const
Definition: id.h:344
UniversalTimeScaleClock::time_point Time
Definition: time.h:44
std::map< int, DataType >::const_iterator current_data_
Definition: id.h:223
IteratorType end() const
Definition: id.h:118
bool operator!=(const ConstIterator &it) const
Definition: id.h:207
ConstIterator(const MapById &map_by_id, const int trajectory_id)
Definition: id.h:148
Rigid2< FloatType > operator*(const Rigid2< FloatType > &lhs, const Rigid2< FloatType > &rhs)
bool Contains(const IdType &id) const
Definition: id.h:306
IdType Append(const int trajectory_id, const DataType &data)
Definition: id.h:263
ConstIterator EndOfTrajectory(const int trajectory_id) const
Definition: id.h:323
static time_point time
IteratorType begin() const
Definition: id.h:117
std::map< int, MapByIndex > trajectories_
Definition: id.h:402
size_t size() const
Definition: id.h:335
IteratorType end_
Definition: id.h:122
bool operator==(const NodeId &other) const
Definition: id.h:61
std::bidirectional_iterator_tag iterator_category
Definition: id.h:142
ConstTrajectoryIterator & operator++()
Definition: id.h:240
void ToProto(proto::NodeId *proto) const
Definition: id.h:73
bool operator!=(const ConstTrajectoryIterator &it) const
Definition: id.h:254
Range< ConstTrajectoryIterator > trajectory_ids() const
Definition: id.h:350
ConstIterator begin() const
Definition: id.h:356
bool operator==(const SubmapId &other) const
Definition: id.h:89
static int GetIndex(const SubmapId &id)
Definition: id.h:400
ConstIterator find(const IdType &id) const
Definition: id.h:275
DataType & at(const IdType &id)
Definition: id.h:315
std::map< int, MapByIndex >::const_iterator current_trajectory_
Definition: id.h:259
bool operator!=(const SubmapId &other) const
Definition: id.h:94
ConstIterator(const MapById &map_by_id, const IdType &id)
Definition: id.h:158
std::ostream & operator<<(std::ostream &os, const NodeId &v)
Definition: id.h:79
ConstIterator BeginOfTrajectory(const int trajectory_id) const
Definition: id.h:320
ConstTrajectoryIterator(typename std::map< int, MapByIndex >::const_iterator current_trajectory)
Definition: id.h:234
ConstIterator lower_bound(const int trajectory_id, const common::Time time) const
Definition: id.h:367
std::unique_ptr< const IdDataReference > pointer
Definition: id.h:145
auto GetTimeImpl(const T &t, int) -> decltype(t.time())
Definition: id.h:41
IdDataReference operator*() const
Definition: id.h:170
Range(const IteratorType &begin, const IteratorType &end)
Definition: id.h:114
std::map< int, MapByIndex >::const_iterator end_trajectory_
Definition: id.h:222


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58