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 
163  CameraInfo info;
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 
static std::string homeDir()
Definition: UDirectory.cpp:355
static bool parse(const ParametersMap &parameters, const std::string &key, bool &value)
Definition: Parameters.cpp:497
cv::Mat odomCovariance
Definition: CameraInfo.h:70
std::string getName()
Definition: UFile.h:135
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true, Link::Type type=Link::kUndef)
Definition: Graph.cpp:992
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
Definition: DBReader.cpp:142
std::pair< std::string, std::string > ParametersPair
Definition: Parameters.h:44
data
static int erase(const std::string &filePath)
Definition: UFile.cpp:58
std::map< std::string, std::string > ParametersMap
Definition: Parameters.h:43
void init(const ParametersMap &parameters, const std::string &databasePath="", bool loadDatabaseParameters=false)
Definition: Rtabmap.cpp:310
std::vector< float > odomVelocity
Definition: CameraInfo.h:71
std::string getExtension()
Definition: UFile.h:140
int triggerNewMap()
Definition: Rtabmap.cpp:868
bool openConnection(const std::string &url, bool overwritten=false)
Definition: DBDriver.cpp:86
void getAllLinks(std::multimap< int, Link > &links, bool ignoreNullLinks=true, bool withLandmarks=false) const
Definition: DBDriver.cpp:915
SensorData takeImage(CameraInfo *info=0)
Definition: Camera.cpp:72
Wrappers of STL for convenient functions.
std::list< std::string > uSplit(const std::string &str, char separator=' ')
Definition: UStl.h:566
std::string uJoin(const std::list< std::string > &strings, const std::string &separator="")
Definition: UStl.h:603
int id() const
Definition: SensorData.h:174
void close(bool databaseSaved=true, const std::string &ouputDatabasePath="")
Definition: Rtabmap.cpp:453
virtual bool callback(const std::string &msg) const
Definition: ProgressState.h:39
void closeConnection(bool save=true, const std::string &outputUrl="")
Definition: DBDriver.cpp:64
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false, bool ignoreIntermediateNodes=false) const
Definition: DBDriver.cpp:876
bool process(const SensorData &data, Transform odomPose, const cv::Mat &odomCovariance=cv::Mat::eye(6, 6, CV_64FC1), const std::vector< float > &odomVelocity=std::vector< float >(), const std::map< std::string, float > &externalStats=std::map< std::string, float >())
Main loop of rtabmap.
Definition: Rtabmap.cpp:1151
std::string UTILITE_EXP uReplaceChar(const std::string &str, char before, char after)
Definition: UConversion.cpp:33
static DBDriver * create(const ParametersMap &parameters=ParametersMap())
Definition: DBDriver.cpp:41
bool isNull() const
Definition: Transform.cpp:107
#define UDEBUG(...)
bool isCanceled() const
Definition: ProgressState.h:51
bool exists()
Definition: UFile.h:104
bool RTABMAP_EXP databaseRecovery(const std::string &corruptedDatabase, bool keepCorruptedDatabase=true, std::string *errorMsg=0, ProgressState *progressState=0)
Definition: Recovery.cpp:39
ParametersMap getLastParameters() const
Definition: DBDriver.cpp:239
static int rename(const std::string &oldFilePath, const std::string &newFilePath)
Definition: UFile.cpp:63
bool isValid() const
Definition: SensorData.h:156
Transform odomPose
Definition: CameraInfo.h:69
std::string UTILITE_EXP uFormat(const char *fmt,...)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
Definition: UStl.h:443


rtabmap
Author(s): Mathieu Labbe
autogenerated on Mon Jan 23 2023 03:37:29