OdometryThread.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of the Universite de Sherbrooke nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
30 #include "rtabmap/core/Odometry.h"
36 
37 namespace rtabmap {
38 
39 OdometryThread::OdometryThread(Odometry * odometry, unsigned int dataBufferMaxSize) :
40  _odometry(odometry),
41  _dataBufferMaxSize(dataBufferMaxSize),
42  _resetOdometry(false),
43  _resetPose(Transform::getIdentity()),
44  _lastImuStamp(0.0),
45  _imuEstimatedDelay(0.0)
46 {
47  UASSERT(_odometry != 0);
48 }
49 
51 {
53  this->join(true);
54  delete _odometry;
55  UDEBUG("");
56 }
57 
59 {
60  if(this->isRunning())
61  {
62  if(event->getClassName().compare("CameraEvent") == 0)
63  {
64  CameraEvent * cameraEvent = (CameraEvent*)event;
65  if(cameraEvent->getCode() == CameraEvent::kCodeData)
66  {
67  this->addData(cameraEvent->data());
68  }
69  }
70  else if(event->getClassName().compare("IMUEvent") == 0)
71  {
72  IMUEvent * imuEvent = (IMUEvent*)event;
73  if(!imuEvent->getData().empty())
74  {
75  this->addData(SensorData(imuEvent->getData(), 0, imuEvent->getStamp()));
76  }
77  }
78  }
79  if(event->getClassName().compare("OdometryResetEvent") == 0)
80  {
81  OdometryResetEvent * odomEvent = (OdometryResetEvent*)event;
83  if(!odomEvent->getPose().isNull())
84  {
85  _resetPose = odomEvent->getPose();
86  }
87  _resetOdometry = true;
88  }
89  return false;
90 }
91 
93 {
95 }
96 
98 {
100 }
101 
102 //============================================================
103 // MAIN LOOP
104 //============================================================
106 {
107  if(_resetOdometry)
108  {
110  _resetOdometry = false;
111  }
112 
113  SensorData data;
114  if(getData(data))
115  {
116  OdometryInfo info;
117  UDEBUG("Processing data...");
118  Transform pose = _odometry->process(data, &info);
119  if(!data.imageRaw().empty() || (pose.isNull() && data.imu().empty()))
120  {
121  UDEBUG("Odom pose = %s", pose.prettyPrint().c_str());
122  // a null pose notify that odometry could not be computed
123  this->post(new OdometryEvent(data, pose, info));
124  }
125  }
126 }
127 
129 {
130  if(data.imu().empty())
131  {
132  if(dynamic_cast<OdometryMono*>(_odometry) == 0)
133  {
134  if(data.imageRaw().empty() || data.depthOrRightRaw().empty() || (data.cameraModels().size()==0 && !data.stereoCameraModel().isValidForProjection()))
135  {
136  ULOGGER_ERROR("Missing some information (images empty or missing calibration)!?");
137  return;
138  }
139  }
140  else
141  {
142  // Mono can accept RGB only
143  if(data.imageRaw().empty() || (data.cameraModels().size()==0 && !data.stereoCameraModel().isValidForProjection()))
144  {
145  ULOGGER_ERROR("Missing some information (image empty or missing calibration)!?");
146  return;
147  }
148  }
149  }
150 
151  bool notify = true;
152  _dataMutex.lock();
153  {
154  if(data.imu().empty())
155  {
156  _dataBuffer.push_back(data);
157  while(_dataBufferMaxSize > 0 && _dataBuffer.size() > _dataBufferMaxSize)
158  {
159  UDEBUG("Data buffer is full, the oldest data is removed to add the new one.");
160  _dataBuffer.erase(_dataBuffer.begin());
161  notify = false;
162  }
163  if(notify && _imuEstimatedDelay>0.0 && data.stamp() > (_lastImuStamp+_imuEstimatedDelay))
164  {
165  // Don't notify if IMU data before this image has not been received yet
166  notify = false;
167  }
168  }
169  else
170  {
171  _imuBuffer.push_back(data);
172  if(_lastImuStamp != 0.0 && data.stamp() > _lastImuStamp)
173  {
175  }
176  _lastImuStamp = data.stamp();
177  }
178  }
179  _dataMutex.unlock();
180 
181  if(notify)
182  {
184  }
185 }
186 
188 {
189  bool dataFilled = false;
191  _dataMutex.lock();
192  {
193  if(!_dataBuffer.empty() || !_imuBuffer.empty())
194  {
195  if(_dataBuffer.empty() ||
196  (!_dataBuffer.empty() && !_imuBuffer.empty() && _imuBuffer.front().stamp() < _dataBuffer.front().stamp()))
197  {
198  data = _imuBuffer.front();
199  _imuBuffer.pop_front();
200  }
201  else
202  {
203  data = _dataBuffer.front();
204  _dataBuffer.pop_front();
205  }
206  dataFilled = true;
207  }
208  }
209  _dataMutex.unlock();
210  return dataFilled;
211 }
212 
213 } // namespace rtabmap
int getCode() const
Definition: UEvent.h:74
void release(int n=1)
Definition: USemaphore.h:168
std::string prettyPrint() const
Definition: Transform.cpp:274
Definition: UEvent.h:57
bool empty() const
Definition: IMU.h:62
int lock() const
Definition: UMutex.h:87
virtual void reset(const Transform &initialPose=Transform::getIdentity())
Definition: Odometry.cpp:182
bool isRunning() const
Definition: UThread.cpp:245
virtual void mainLoopBegin()
bool acquire(int n=1, int ms=0)
Definition: USemaphore.h:101
const cv::Mat & imageRaw() const
Definition: SensorData.h:161
void post(UEvent *event, bool async=true) const
Transform process(SensorData &data, OdometryInfo *info=0)
Definition: Odometry.cpp:235
virtual void mainLoopKill()
#define UASSERT(condition)
bool isNull() const
Definition: Transform.cpp:107
std::list< SensorData > _dataBuffer
virtual std::string getClassName() const =0
void addData(const SensorData &data)
static void registerCurrentThread(const std::string &name)
Definition: ULogger.cpp:218
const IMU & getData() const
Definition: IMU.h:93
const cv::Mat & depthOrRightRaw() const
Definition: SensorData.h:162
double stamp() const
Definition: SensorData.h:154
unsigned int _dataBufferMaxSize
#define false
Definition: ConvertUTF.c:56
const IMU & imu() const
Definition: SensorData.h:248
const std::vector< CameraModel > & cameraModels() const
Definition: SensorData.h:193
const Transform & getPose() const
#define UDEBUG(...)
int unlock() const
Definition: UMutex.h:113
double getStamp() const
Definition: IMU.h:94
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
Definition: SensorData.h:194
bool getData(SensorData &data)
const SensorData & data() const
Definition: CameraEvent.h:79
void unregisterFromEventsManager()
void join(bool killFirst=false)
Definition: UThread.cpp:85
virtual bool handleEvent(UEvent *event)
#define ULOGGER_ERROR(...)
Definition: ULogger.h:56
OdometryThread(Odometry *odometry, unsigned int dataBufferMaxSize=1)
std::list< SensorData > _imuBuffer


rtabmap
Author(s): Mathieu Labbe
autogenerated on Wed Jun 5 2019 22:41:32