Recovery.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2010-2017, 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 
28 #include <rtabmap/core/Recovery.h>
29 #include <rtabmap/core/Rtabmap.h>
30 #include <rtabmap/core/DBDriver.h>
31 #include <rtabmap/core/DBReader.h>
32 #include <rtabmap/core/Graph.h>
34 #include <rtabmap/utilite/UFile.h>
35 #include <rtabmap/utilite/UStl.h>
36 
37 namespace rtabmap {
38 
40  const std::string & corruptedDatabase,
41  bool keepCorruptedDatabase,
42  std::string * errorMsg,
43  ProgressState * progressState)
44 {
45  UDEBUG("Recovering \"%s\"", corruptedDatabase.c_str());
46 
47  std::string databasePath = uReplaceChar(corruptedDatabase, '~', UDirectory::homeDir());
48  if(!UFile::exists(databasePath))
49  {
50  if(errorMsg)
51  *errorMsg = uFormat("File \"%s\" doesn't exist!", databasePath.c_str());
52  return false;
53  }
54 
55  if(UFile::getExtension(databasePath).compare("db") != 0)
56  {
57  if(errorMsg)
58  *errorMsg = uFormat("File \"%s\" is not a database (*.db)!", databasePath.c_str());
59  return false;
60  }
61  std::list<std::string> strList = uSplit(databasePath, '.');
62  strList.pop_back();
63 
64  std::string recoveryPath;
65  recoveryPath = uJoin(strList, ".") + ".recovery.db";
66  if(UFile::exists(recoveryPath))
67  {
68  if(UFile::erase(recoveryPath) != 0)
69  {
70  if(errorMsg)
71  *errorMsg = uFormat("Failed to remove temporary recovery database \"%s\", is it opened by another app?", recoveryPath.c_str());
72  return false;
73  }
74  }
75 
76  DBDriver * dbDriver = DBDriver::create();
77  if(!dbDriver->openConnection(databasePath, false))
78  {
79  if(errorMsg)
80  *errorMsg = uFormat("Failed opening database!");
81  delete dbDriver;
82  return false;
83  }
84 
85  ParametersMap parameters = dbDriver->getLastParameters();
86  if(parameters.empty())
87  {
88  if(errorMsg)
89  *errorMsg = uFormat("Failed getting parameters from database, recovery cannot be done.");
90  dbDriver->closeConnection(false);
91  delete dbDriver;
92  return false;
93  }
94  std::set<int> ids;
95  dbDriver->getAllNodeIds(ids);
96  if(ids.empty())
97  {
98  if(errorMsg)
99  *errorMsg = uFormat("Input database doesn't have any nodes saved in it.");
100  dbDriver->closeConnection(false);
101  delete dbDriver;
102  return false;
103  }
104  if(progressState)
105  progressState->callback(uFormat("Found %d nodes to recover.", (int)ids.size()));
106 
107  //Detect if the database is corrupted
108  std::multimap<int, Link> links;
109  dbDriver->getAllLinks(links, true);
110  bool corrupted = false;
111  for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
112  {
113  if(iter->second.type() == Link::kNeighbor &&
114  graph::findLink(links, iter->second.to(), iter->second.from(), false) == links.end())
115  {
116  corrupted = true;
117  break;
118  }
119  }
120 
121  if(progressState)
122  {
123  if(corrupted)
124  progressState->callback("Database is indeed corrupted, found one or more neighbor links missing.");
125  else
126  progressState->callback("Database doesn't seem to be corrupted, still recovering it.");
127  }
128 
129  dbDriver->closeConnection(false);
130  delete dbDriver;
131 
132  bool incrementalMemory = true;
133  bool dbInMemory = false;
134  Parameters::parse(parameters, Parameters::kMemIncrementalMemory(), incrementalMemory);
135  Parameters::parse(parameters, Parameters::kDbSqlite3InMemory(), dbInMemory);
136  if(!incrementalMemory)
137  {
138  if(progressState)
139  {
140  progressState->callback("Database is in localization mode, setting it to mapping mode to recover.");
141  }
142  uInsert(parameters, ParametersPair(Parameters::kMemIncrementalMemory(), "true"));
143  }
144  if(dbInMemory)
145  {
146  if(progressState)
147  {
148  progressState->callback(uFormat("Database has %s=true, setting it to false to avoid RAM problems during recovery.", Parameters::kDbSqlite3InMemory().c_str()));
149  }
150  uInsert(parameters, ParametersPair(Parameters::kDbSqlite3InMemory(), "false"));
151  }
152 
154  rtabmap.init(parameters, recoveryPath);
155 
156  bool rgbdEnabled = Parameters::defaultRGBDEnabled();
157  Parameters::parse(parameters, Parameters::kRGBDEnabled(), rgbdEnabled);
158  bool odometryIgnored = !rgbdEnabled;
159  {
160  DBReader dbReader(databasePath, 0, odometryIgnored);
161  dbReader.init();
162 
164  SensorData data = dbReader.takeImage(&info);
165  int processed = 0;
166  if (progressState)
167  progressState->callback(uFormat("Recovering data of \"%s\"...", databasePath.c_str()));
168  while (data.isValid() && (progressState == 0 || !progressState->isCanceled()))
169  {
170  std::string status;
171  if (!odometryIgnored && info.odomPose.isNull())
172  {
173  status = uFormat("Skipping node %d as it doesn't have odometry pose set.", data.id());
174  }
175  else
176  {
177  if (!odometryIgnored && !info.odomCovariance.empty() && info.odomCovariance.at<double>(0, 0) >= 9999)
178  {
179  status = uFormat("High variance detected, triggering a new map...");
180  rtabmap.triggerNewMap();
181  }
182  if (!rtabmap.process(data, info.odomPose, info.odomCovariance, info.odomVelocity))
183  {
184  status = uFormat("Failed processing node %d.", data.id());
185  }
186  }
187  if (status.empty())
188  {
189  if (progressState)
190  progressState->callback(status);
191  }
192 
193  data = dbReader.takeImage(&info);
194 
195  if (progressState)
196  progressState->callback(uFormat("Processed %d/%d nodes...", ++processed, (int)ids.size()));
197  }
198  }
199 
200  if(progressState)
201  {
202  if(progressState->isCanceled())
203  {
204  rtabmap.close(false);
205  if(errorMsg)
206  *errorMsg = uFormat("Recovery canceled, removing temporary recovery database \"%s\".", recoveryPath.c_str());
207 
208  UFile::erase(recoveryPath);
209  return false;
210  }
211  }
212 
213  if(progressState)
214  progressState->callback(uFormat("Closing database \"%s\"...", recoveryPath.c_str()));
215  rtabmap.close(true);
216  if(progressState)
217  progressState->callback(uFormat("Closing database \"%s\"... done!", recoveryPath.c_str()));
218 
219  if(keepCorruptedDatabase)
220  {
221  std::string backupPath;
222  backupPath = uJoin(strList, ".") + ".backup.db";
223 
224  if(!UFile::exists(backupPath))
225  {
226  if(progressState)
227  progressState->callback(uFormat("Renaming \"%s\" to \"%s\"... (keep corrupted database backup option is enabled).", UFile::getName(databasePath).c_str(), UFile::getName(backupPath).c_str()));
228  if(UFile::rename(databasePath, backupPath) != 0)
229  {
230  if(errorMsg)
231  *errorMsg = uFormat("Failed renaming database file from \"%s\" to \"%s\". Is it opened by another app?", UFile::getName(databasePath).c_str(), UFile::getName(backupPath).c_str());
232  return false;
233  }
234  if(progressState)
235  progressState->callback(uFormat("Renaming \"%s\" to \"%s\"... done!", UFile::getName(databasePath).c_str(), UFile::getName(backupPath).c_str()));
236  }
237  else
238  {
239  if(progressState)
240  progressState->callback(uFormat("Backup \"%s\" already exists, won't copy again.", UFile::getName(backupPath).c_str()));
241  }
242  }
243  else if(UFile::erase(databasePath) != 0)
244  {
245  if(errorMsg)
246  *errorMsg = uFormat("Failed remove original database file \"%s\". Is it opened by another app? The recovered database cannot be copied back to original name.", UFile::getName(databasePath).c_str(), UFile::getName(recoveryPath).c_str());
247  return false;
248  }
249 
250  if(progressState)
251  progressState->callback(uFormat("Renaming \"%s\" to \"%s\"...", UFile::getName(recoveryPath).c_str(), UFile::getName(databasePath).c_str()));
252  if(UFile::rename(recoveryPath, databasePath) != 0)
253  {
254  if(errorMsg)
255  *errorMsg = uFormat("Failed renaming database file from \"%s\" to \"%s\". Is it opened by another app?", UFile::getName(recoveryPath).c_str(), UFile::getName(databasePath).c_str());
256  return false;
257  }
258  if(progressState)
259  progressState->callback(uFormat("Renaming \"%s\" to \"%s\"... done!", UFile::getName(recoveryPath).c_str(), UFile::getName(databasePath).c_str()));
260 
261  return true;
262 }
263 
264 }
265 
266 
267 
268 
rtabmap::SensorData
Definition: SensorData.h:51
UFile::rename
static int rename(const std::string &oldFilePath, const std::string &newFilePath)
Definition: UFile.cpp:63
rtabmap::ParametersPair
std::pair< std::string, std::string > ParametersPair
Definition: Parameters.h:44
compare
bool compare
UFile::getName
std::string getName()
Definition: UFile.h:135
rtabmap::DBDriver::getLastParameters
ParametersMap getLastParameters() const
Definition: DBDriver.cpp:239
UFile::erase
static int erase(const std::string &filePath)
Definition: UFile.cpp:58
rtabmap::DBDriver::openConnection
bool openConnection(const std::string &url, bool overwritten=false)
Definition: DBDriver.cpp:86
uJoin
std::string uJoin(const std::list< std::string > &strings, const std::string &separator="")
Definition: UStl.h:601
DBReader.h
rtabmap::ProgressState::callback
virtual bool callback(const std::string &msg) const
Definition: ProgressState.h:39
ProgressState.h
rtabmap::ParametersMap
std::map< std::string, std::string > ParametersMap
Definition: Parameters.h:43
rtabmap::Parameters::parse
static bool parse(const ParametersMap &parameters, const std::string &key, bool &value)
Definition: Parameters.cpp:500
rtabmap::SensorCaptureInfo
Definition: SensorCaptureInfo.h:36
UDirectory::homeDir
static std::string homeDir()
Definition: UDirectory.cpp:355
uInsert
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
Definition: UStl.h:441
rtabmap::DBReader::init
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
Definition: DBReader.cpp:146
data
int data[]
UFile::getExtension
std::string getExtension()
Definition: UFile.h:140
Rtabmap.h
rtabmap::ProgressState::isCanceled
bool isCanceled() const
Definition: ProgressState.h:51
info
else if n * info
rtabmap::ProgressState
Definition: ProgressState.h:35
DBDriver.h
rtabmap::graph::findLink
std::multimap< int, Link >::iterator RTABMAP_CORE_EXPORT findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true, Link::Type type=Link::kUndef)
Definition: Graph.cpp:1024
rtabmap::DBDriver
Definition: DBDriver.h:62
uFormat
std::string UTILITE_EXPORT uFormat(const char *fmt,...)
Definition: UConversion.cpp:365
uReplaceChar
std::string UTILITE_EXPORT uReplaceChar(const std::string &str, char before, char after)
Definition: UConversion.cpp:33
uSplit
std::list< std::string > uSplit(const std::string &str, char separator=' ')
Definition: UStl.h:564
Graph.h
iter
iterator iter(handle obj)
c_str
const char * c_str(Args &&...args)
UStl.h
Wrappers of STL for convenient functions.
UDEBUG
#define UDEBUG(...)
rtabmap::DBReader
Definition: DBReader.h:46
rtabmap::Rtabmap
Definition: Rtabmap.h:54
rtabmap::DBDriver::getAllNodeIds
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false, bool ignoreIntermediateNodes=false) const
Definition: DBDriver.cpp:886
UFile.h
rtabmap
Definition: CameraARCore.cpp:35
UFile::exists
bool exists()
Definition: UFile.h:104
rtabmap::Camera::takeImage
SensorData takeImage(SensorCaptureInfo *info=0)
Definition: Camera.h:48
rtabmap::databaseRecovery
bool RTABMAP_CORE_EXPORT databaseRecovery(const std::string &corruptedDatabase, bool keepCorruptedDatabase=true, std::string *errorMsg=0, ProgressState *progressState=0)
Definition: Recovery.cpp:39
rtabmap::DBDriver::getAllLinks
void getAllLinks(std::multimap< int, Link > &links, bool ignoreNullLinks=true, bool withLandmarks=false) const
Definition: DBDriver.cpp:925
rtabmap::DBDriver::closeConnection
void closeConnection(bool save=true, const std::string &outputUrl="")
Definition: DBDriver.cpp:64
Recovery.h
rtabmap::DBDriver::create
static DBDriver * create(const ParametersMap &parameters=ParametersMap())
Definition: DBDriver.cpp:41


rtabmap
Author(s): Mathieu Labbe
autogenerated on Thu Jul 25 2024 02:50:15