ethzasl-msf - Modular Sensor Fusion
Time delay compensated single and multi sensor fusion framework based on an EKF
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
msf_sortedContainer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2013 Simon Lynen, ASL, ETH Zurich, Switzerland
3  * You can contact the author at <slynen at ethz dot ch>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef MSF_SORTEDCONTAINER_H_
18 #define MSF_SORTEDCONTAINER_H_
19 
20 #include <msf_core/msf_types.hpp>
21 #include <msf_core/msf_tools.h>
22 #include <msf_core/msf_macros.h>
23 #include <iomanip>
24 
25 #define CHECK_IN_BOUNDS(iterator, container) \
26  do { \
27  decltype(iterator) __it = it; \
28  ++__it; \
29  if (__it == container.begin()) { \
30  MSF_ERROR_STREAM("Iterator out of bounds (begin) " << \
31  __FILE__ << ":" << __LINE__); \
32  } \
33  if (iterator == container.end()) { \
34  MSF_ERROR_STREAM("Iterator out of bounds (end) " << \
35  __FILE__ << ":" << __LINE__); \
36  } \
37  } while(0);
38 
39 
40 namespace msf_core {
46 template<typename T, typename PrototypeInvalidT = T>
48 
49  public:
50  typedef shared_ptr<T> Ptr_T;
51  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
52 
53  private:
54  typedef std::map<double, Ptr_T> ListT;
57  public:
58  typedef typename ListT::iterator iterator_T;
59 
61  invalid.reset(new PrototypeInvalidT());
62  invalid->time = -1;
63  }
68  inline shared_ptr<T>& getInvalid() {
69  return invalid;
70  }
71 
75  inline void clear() {
76  stateList.clear();
77  }
78 
83  inline typename ListT::size_type size() {
84  return stateList.size();
85  }
86 
91  inline typename ListT::iterator insert(const shared_ptr<T>& value) {
92  std::pair<typename ListT::iterator, bool> itpr = stateList.insert(
93  std::pair<double, shared_ptr<T> >(value->time, value));
94  if (!itpr.second) {
96  "Wanted to insert a value to the sorted container at time " <<
97  std::fixed << std::setprecision(9) << value->time <<
98  " but the map already contained a value at this time. discarding.");
99  }
100  return itpr.first;
101  }
102 
106  inline typename ListT::iterator getIteratorBegin() {
107  return stateList.begin();
108  }
109 
113  inline typename ListT::iterator getIteratorBeforeBegin() {
114  typename ListT::iterator it = stateList.begin();
115  return --it;
116  }
117 
121  inline typename ListT::iterator getIteratorEnd() {
122  return stateList.end();
123  }
124 
131  inline typename ListT::iterator getIteratorAtValue(const shared_ptr<T>& value,
132  bool warnIfNotExistant =
133  true) {
134  typename ListT::iterator it = stateList.find(value->time);
135  if (it == stateList.end()) { // There is no value in the map with this time.
136  if (warnIfNotExistant)
138  "getIteratorAtValue(state): Could not find value for time " <<
139  std::fixed << std::setprecision(9) << value->time);
140  it = stateList.lower_bound(value->time);
141  }
142  return it;
143  }
144 
151  inline typename ListT::iterator getIteratorAtValue(const double& time,
152  bool warnIfNotExistant =
153  true) {
154  typename ListT::iterator it = stateList.find(time);
155  if (it == stateList.end()) { //there is no value in the map with this time
156  if (warnIfNotExistant)
158  "getIteratorAtValue(double): Could not find value for time " <<
159  std::fixed << std::setprecision(9) << time);
160  it = stateList.lower_bound(time);
161  }
162  return it;
163  }
164 
170  inline typename ListT::iterator getIteratorClosestBefore(
171  const double& statetime) {
172  typename ListT::iterator it = stateList.lower_bound(statetime);
173  it--;
174  return it;
175  }
176 
182  inline typename ListT::iterator getIteratorClosestAfter(
183  const double& statetime) {
184  typename ListT::iterator it = stateList.upper_bound(statetime);
185  return it;
186  }
187 
193  inline typename ListT::iterator getIteratorClosest(const double& statetime) {
194 
195  // First check if we have a value at this time in the buffer.
196  typename ListT::iterator it_at = stateList.find(statetime);
197  if (it_at != stateList.end()) {
198  return it_at;
199  }
200 
201  // If not, find the closest one.
202  typename ListT::iterator tauMinus = getIteratorClosestBefore(statetime);
203  typename ListT::iterator tauPlus = getIteratorClosestAfter(statetime);
204 
205  typename ListT::iterator it_end = getIteratorEnd();
206  if (tauMinus == it_end) {
207  return tauPlus;
208  }
209  if (tauPlus == it_end) {
210  return tauMinus;
211  }
212  if (fabs(tauPlus->second->time - statetime)
213  < fabs(tauMinus->second->time - statetime)) {
214  return tauPlus;
215  } else {
216  return tauMinus;
217  }
218  }
219 
225  inline shared_ptr<T>& getClosestBefore(const double& statetime) {
226  typename ListT::iterator it = stateList.lower_bound(statetime);
227  if (stateList.empty()) {
228  MSF_WARN_STREAM("Requested the first object before time " << statetime <<
229  "but the container is empty");
230  return getInvalid();
231  }
232  if (it == stateList.begin()) {
233  return it->second;
234  }
235  it--;
236  return it->second;
237  }
238  ;
239 
246  inline shared_ptr<T>& getClosestAfter(const double& statetime) {
247  typename ListT::iterator it = stateList.upper_bound(statetime);
248  if (it == stateList.end()) {
249  return getInvalid();
250  }
251  return it->second;
252  }
253  ;
254 
261  inline shared_ptr<T>& getValueAt(const double& statetime) {
262  typename ListT::iterator it = stateList.find(statetime);
263  if (it == stateList.end()) {
264  return getInvalid();
265  }
266  return it->second;
267  }
268  ;
269 
275  inline shared_ptr<T>& getClosest(const double& statetime) {
276  shared_ptr<T>& at = getValueAt(statetime); // Is there one exactly at this point?
277  if (at != getInvalid()) {
278  return at;
279  }
280 
281  shared_ptr<T>& tauMinus = getClosestBefore(statetime);
282  shared_ptr<T>& tauPlus = getClosestAfter(statetime);
283 
284  if (tauMinus->time == -1) {
285  return tauPlus;
286  } else if (tauPlus->time == -1) {
287  return tauMinus;
288  }
289 
290  if (fabs(tauPlus->time - statetime) < fabs(tauMinus->time - statetime)) {
291  return tauPlus;
292  } else {
293  return tauMinus;
294  }
295  }
296 
303  inline void clearOlderThan(double age) {
304  double newest = getLast()->time;
305  iterator_T it = getIteratorClosest(newest - age);
306  if (newest - it->second->time < age)
307  return; //there is no state older than time
308  if (it->second->time > stateList.begin()->second->time)
309  stateList.erase(stateList.begin(), it);
310  }
311 
317  inline shared_ptr<T>& getLast() {
318  if (stateList.empty()) {
319  MSF_WARN_STREAM("Requested the last object in the sorted container, but "
320  "the container is empty");
321  return getInvalid();
322  }
323  typename ListT::iterator end = stateList.end();
324  return (--end)->second;
325  }
326 
332  inline shared_ptr<T>& getFirst() {
333  if (stateList.empty()) {
334  MSF_WARN_STREAM("Requested the first object in the sorted container, "
335  "but the container is empty");
336  return getInvalid();
337  }
338  typename ListT::iterator start = stateList.begin();
339  return start->second;
340  }
341 
352  inline shared_ptr<T> updateTime(double timeOld, double timeNew)
353  __attribute__ ((warn_unused_result)) {
354  typename ListT::iterator it = stateList.find(timeOld);
355  if (it == stateList.end()) {
356  std::stringstream ss;
357  ss
358  << "Wanted to update a states/measurements time, but could not find "
359  "the old state, for which the time was asked to be updated. time "
360  << std::fixed << std::setprecision(9) << timeOld << std::endl;
361 
362  ss << "Map: " << std::endl;
363  for (typename ListT::iterator it2 = stateList.begin();
364  it2 != stateList.end(); ++it2) {
365  ss << it2->first << std::endl;
366  }
367  MSF_WARN_STREAM(ss.str());
368 
369  return getClosest(timeOld);
370  }
371  // Get the data from the map, we need to update, then reinsert.
372  shared_ptr<T> copy = it->second;
373  stateList.erase(it->first);
374  copy->time = timeNew;
375  typename ListT::iterator inserted = insert(copy);
376  return inserted->second;
377  }
378 
384  std::string echoBufferContentTimes() {
385  std::stringstream ss;
386 
387  for (typename ListT::iterator it = getIteratorBegin();
388  it != getIteratorEnd(); ++it) {
389  ss << std::fixed << std::setprecision(9) << it->second->time << std::endl;
390  }
391  return ss.str();
392 
393  }
394 
395 };
396 }
397 
398 #endif // MSF_SORTEDCONTAINER_H_