TimeQueue.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @author Fabian Reister ( fabian dot reister at kit dot edu )
17  * @date 2021
18  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19  * GNU General Public License
20  */
21 
22 #pragma once
23 
24 #include <algorithm>
25 #include <deque>
26 #include <iterator>
27 #include <mutex>
28 #include <shared_mutex>
29 #include <vector>
30 
31 #include <Eigen/Core>
32 #include <Eigen/Geometry>
33 
34 #include <SimoxUtility/math/pose/interpolate.h>
35 
39 
41 {
42 
43  // struct PoseStamped
44  // {
45  // Eigen::Isometry3f pose;
46  // int64_t timestamp;
47  // };
48 
49  template <typename MessageType>
50  class TimeQueue
51  {
52 
53  public:
54  TimeQueue(const std::size_t maxQueueSize) : maxQueueSize(maxQueueSize)
55  {
56  }
57 
58  TimeQueue(TimeQueue&& other) noexcept :
59  queue(std::move(other.queue)), maxQueueSize(other.maxQueueSize)
60  {
61  }
62 
63  // using MessagePtr = std::shared_ptr<MessageType>;
64  // using MessageConstPtr = std::shared_ptr<const MessageType>;
65 
66  void
67  insert(MessageType message)
68  {
70  ARMARX_DEBUG << "Locking insert()";
71  std::unique_lock g{mtx};
72 
73  // if (not queue.empty())
74  // {
75  // ARMARX_CHECK_GREATER(message.timestamp, queue.back().timestamp)
76  // << "Poses have to be passed in with increasing timestamps";
77  // }
78 
80 
81  queue.emplace_back(std::move(message));
82 
83  // only keep the last x seconds specified by duration
84  //trimUntil(poseStamped.timestamp - duration);
85 
86  while (queue.size() > maxQueueSize)
87  {
88  queue.pop_front();
89  }
90  }
91 
92  std::vector<int64_t>
93  timestamps() const
94  {
96  ARMARX_DEBUG << "Locking timestamps()";
97 
98  std::vector<int64_t> ts;
99  ts.reserve(queue.size());
100 
101  std::shared_lock g{mtx};
102  std::transform(queue.begin(),
103  queue.end(),
104  std::back_inserter(ts),
105  [](const MessageType& msg) { return msg.timestamp; });
106 
107  return ts;
108  }
109 
110  const MessageType&
111  lookupAt(int64_t referenceTimestamp) const
112  {
113  ARMARX_TRACE;
114  ARMARX_DEBUG << "Locking lookupAt()";
115  std::shared_lock g{mtx};
116 
117  // ARMARX_CHECK(_has(referenceTimestamp))
118  // << "Cannot perform lookup of timestamp " << referenceTimestamp;
119 
120  // const auto poseNextIt = findFirstElementAtOrAfter(referenceTimestamp);
121  const auto poseIt = findFirstElementAtOrBefore(referenceTimestamp);
122 
123  // TODO(fabian.reister): check if poseBeforeIt is valid and compare dt's
124 
125  return *poseIt;
126  }
127 
128  bool
129  has(int64_t timestamp) const
130  {
131  ARMARX_TRACE;
132  ARMARX_DEBUG << "Locking has()";
133  std::shared_lock g{mtx};
134  return _has(timestamp);
135  }
136 
137  void
139  {
140  ARMARX_TRACE;
141  ARMARX_DEBUG << "Locking trimUntil()";
142 
143  std::unique_lock g{mtx};
144 
145  while (not queue.empty())
146  {
147  if (queue.front().timestamp <= timestamp)
148  {
149  queue.pop_front();
150  }
151 
152  // We reached a valid entry. Done.
153  break;
154  }
155  }
156 
157  void
159  {
160  std::lock_guard g{mtx};
161  queue.clear();
162  }
163 
164  std::size_t
165  size() const noexcept
166  {
167  std::lock_guard g{mtx};
168  return queue.size();
169  }
170 
171  using QueueType = std::deque<MessageType>;
172  using QueueIterator = typename QueueType::iterator;
173  using QueueConstIterator = typename QueueType::const_iterator;
174  using QueueConstReverseIterator = typename QueueType::const_reverse_iterator;
175 
176 
177  protected:
180  {
181  auto timestampBeyond = [timestamp](const MessageType& poseStamped)
182  { return poseStamped.timestamp >= timestamp; };
183 
184  const auto poseNextIt = std::find_if(queue.begin(), queue.end(), timestampBeyond);
185  return poseNextIt;
186  }
187 
190  {
191  auto timestampBefore = [timestamp](const MessageType& poseStamped)
192  { return poseStamped.timestamp <= timestamp; };
193 
194  const auto poseBeforeIt = std::find_if(queue.rbegin(), queue.rend(), timestampBefore);
195  return poseBeforeIt;
196  }
197 
198  bool
199  _has(int64_t timestamp) const
200  {
201  // Cannot perform lookup when queue is empty
202  if (queue.empty())
203  {
204  return false;
205  }
206 
207  // Cannot perform lookup into the future!
208  if (queue.back().timestamp < timestamp)
209  {
210  // ARMARX_DEBUG << "Cannot perform lookup into future";
211  return false;
212  }
213 
214  // Cannot perform lookup. Timestamp too old
215  if (queue.front().timestamp > timestamp)
216  {
217  // ARMARX_DEBUG << "Cannot perform lookup into past";
218  return false;
219  }
220 
221  // => now we know that there is an element right after and before the timestamp within our queue
222  return true;
223  }
224 
225 
226  protected:
228 
229  mutable std::shared_mutex mtx;
230 
231  private:
232  void
233  trimUntilPriv(const size_t pos)
234  {
235  if (pos >= queue.size())
236  {
237  // TODO(fabian.reister): warning
238  return;
239  }
240 
241  if (pos == 0)
242  {
243  queue.clear();
244  }
245 
246  queue.erase(queue.begin(), queue.begin() + pos);
247  }
248 
249  const std::size_t maxQueueSize;
250  };
251 
252 } // namespace armarx::localization_and_mapping::cartographer_adapter
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::findFirstElementAtOrAfter
QueueConstIterator findFirstElementAtOrAfter(int64_t timestamp) const
Definition: TimeQueue.h:179
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::timestamps
std::vector< int64_t > timestamps() const
Definition: TimeQueue.h:93
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::TimeQueue
TimeQueue(TimeQueue &&other) noexcept
Definition: TimeQueue.h:58
armarx::localization_and_mapping::cartographer_adapter::TimeQueue< armarx::localization_and_mapping::cartographer_adapter::PoseStamped >::QueueConstReverseIterator
typename QueueType::const_reverse_iterator QueueConstReverseIterator
Definition: TimeQueue.h:174
message
message(STATUS "Boost-Library-Dir: " "${Boost_LIBRARY_DIRS}") message(STATUS "Boost-LIBRARIES
Definition: CMakeLists.txt:8
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::findFirstElementAtOrBefore
QueueConstReverseIterator findFirstElementAtOrBefore(int64_t timestamp) const
Definition: TimeQueue.h:189
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::trimUntil
void trimUntil(int64_t timestamp)
Definition: TimeQueue.h:138
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::queue
QueueType queue
Definition: TimeQueue.h:227
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::insert
void insert(MessageType message)
Definition: TimeQueue.h:67
timestamp
std::string timestamp()
Definition: CartographerAdapter.cpp:85
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::TimeQueue
TimeQueue(const std::size_t maxQueueSize)
Definition: TimeQueue.h:54
armarx::localization_and_mapping::cartographer_adapter
This file is part of ArmarX.
Definition: ApproximateTimeQueue.cpp:15
armarx::localization_and_mapping::cartographer_adapter::TimeQueue< armarx::localization_and_mapping::cartographer_adapter::PoseStamped >::QueueType
std::deque< armarx::localization_and_mapping::cartographer_adapter::PoseStamped > QueueType
Definition: TimeQueue.h:171
armarx::localization_and_mapping::cartographer_adapter::TimeQueue< armarx::localization_and_mapping::cartographer_adapter::PoseStamped >::QueueIterator
typename QueueType::iterator QueueIterator
Definition: TimeQueue.h:172
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT >>
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:351
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::lookupAt
const MessageType & lookupAt(int64_t referenceTimestamp) const
Definition: TimeQueue.h:111
ExpressionException.h
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::_has
bool _has(int64_t timestamp) const
Definition: TimeQueue.h:199
LogSender.h
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::size
std::size_t size() const noexcept
Definition: TimeQueue.h:165
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::has
bool has(int64_t timestamp) const
Definition: TimeQueue.h:129
armarx::localization_and_mapping::cartographer_adapter::TimeQueue
Definition: TimeQueue.h:50
Logging.h
armarx::localization_and_mapping::cartographer_adapter::TimeQueue< armarx::localization_and_mapping::cartographer_adapter::PoseStamped >::QueueConstIterator
typename QueueType::const_iterator QueueConstIterator
Definition: TimeQueue.h:173
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::mtx
std::shared_mutex mtx
Definition: TimeQueue.h:229
armarx::localization_and_mapping::cartographer_adapter::TimeQueue::clear
void clear()
Definition: TimeQueue.h:158