mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-03 01:50:24 +08:00
ios: added recovery feature
This commit is contained in:
@@ -64,6 +64,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <rtabmap/core/Memory.h>
|
#include <rtabmap/core/Memory.h>
|
||||||
#include <rtabmap/core/GainCompensator.h>
|
#include <rtabmap/core/GainCompensator.h>
|
||||||
#include <rtabmap/core/DBDriver.h>
|
#include <rtabmap/core/DBDriver.h>
|
||||||
|
#include <rtabmap/core/Recovery.h>
|
||||||
#include <pcl/common/common.h>
|
#include <pcl/common/common.h>
|
||||||
#include <pcl/filters/extract_indices.h>
|
#include <pcl/filters/extract_indices.h>
|
||||||
#include <pcl/io/ply_io.h>
|
#include <pcl/io/ply_io.h>
|
||||||
@@ -305,9 +306,9 @@ void RTABMapApp::setScreenRotation(int displayRotation, int cameraRotation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, const std::string & databaseSource)
|
int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, bool clearDatabase)
|
||||||
{
|
{
|
||||||
LOGW("Opening database %s (inMemory=%d, optimize=%d)", databasePath.c_str(), databaseInMemory?1:0, optimize?1:0);
|
LOGW("Opening database %s (inMemory=%d, optimize=%d, clearDatabase=%d)", databasePath.c_str(), databaseInMemory?1:0, optimize?1:0, clearDatabase?1:0);
|
||||||
this->unregisterFromEventsManager(); // to ignore published init events when closing rtabmap
|
this->unregisterFromEventsManager(); // to ignore published init events when closing rtabmap
|
||||||
status_.first = rtabmap::RtabmapEventInit::kInitializing;
|
status_.first = rtabmap::RtabmapEventInit::kInitializing;
|
||||||
rtabmapMutex_.lock();
|
rtabmapMutex_.lock();
|
||||||
@@ -360,11 +361,11 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
|
|||||||
std::vector<std::vector<Eigen::Vector2f> > texCoords;
|
std::vector<std::vector<Eigen::Vector2f> > texCoords;
|
||||||
#endif
|
#endif
|
||||||
cv::Mat textures;
|
cv::Mat textures;
|
||||||
if(!databaseSource.empty())
|
if(!databasePath.empty() && UFile::exists(databasePath) && !clearDatabase)
|
||||||
{
|
{
|
||||||
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading optimized cloud/mesh..."));
|
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading optimized cloud/mesh..."));
|
||||||
rtabmap::DBDriver * driver = rtabmap::DBDriver::create();
|
rtabmap::DBDriver * driver = rtabmap::DBDriver::create();
|
||||||
if(driver->openConnection(databaseSource))
|
if(driver->openConnection(databasePath))
|
||||||
{
|
{
|
||||||
cloudMat = driver->loadOptimizedMesh(&polygons, &texCoords, &textures);
|
cloudMat = driver->loadOptimizedMesh(&polygons, &texCoords, &textures);
|
||||||
if(!cloudMat.empty())
|
if(!cloudMat.empty())
|
||||||
@@ -416,12 +417,10 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
|
|||||||
}
|
}
|
||||||
|
|
||||||
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading database..."));
|
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading database..."));
|
||||||
|
if(clearDatabase)
|
||||||
|
{
|
||||||
LOGI("Erasing database \"%s\"...", databasePath.c_str());
|
LOGI("Erasing database \"%s\"...", databasePath.c_str());
|
||||||
UFile::erase(databasePath);
|
UFile::erase(databasePath);
|
||||||
if(!databaseSource.empty())
|
|
||||||
{
|
|
||||||
LOGI("Copying database source \"%s\" to \"%s\"...", databaseSource.c_str(), databasePath.c_str());
|
|
||||||
UFile::copy(databaseSource, databasePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Rtabmap
|
//Rtabmap
|
||||||
@@ -2557,6 +2556,26 @@ void RTABMapApp::save(const std::string & databasePath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RTABMapApp::recover(const std::string & from, const std::string & to)
|
||||||
|
{
|
||||||
|
std::string errorMsg;
|
||||||
|
if(!databaseRecovery(from, false, &errorMsg, &progressionStatus_))
|
||||||
|
{
|
||||||
|
LOGE("Recovery Error: %s", errorMsg.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGI("Renaming %s to %s", from.c_str(), to.c_str());
|
||||||
|
if(UFile::rename(from, to) != 0)
|
||||||
|
{
|
||||||
|
LOGE("Failed renaming %s to %s", from.c_str(), to.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RTABMapApp::cancelProcessing()
|
void RTABMapApp::cancelProcessing()
|
||||||
{
|
{
|
||||||
UWARN("Processing canceled!");
|
UWARN("Processing canceled!");
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
|
|
||||||
void setScreenRotation(int displayRotation, int cameraRotation);
|
void setScreenRotation(int displayRotation, int cameraRotation);
|
||||||
|
|
||||||
int openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, const std::string & databaseSource=std::string());
|
int openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, bool clearDatabase);
|
||||||
|
|
||||||
bool isBuiltWith(int cameraDriver) const;
|
bool isBuiltWith(int cameraDriver) const;
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
@@ -153,6 +153,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
void addEnvSensor(int type, float value);
|
void addEnvSensor(int type, float value);
|
||||||
|
|
||||||
void save(const std::string & databasePath);
|
void save(const std::string & databasePath);
|
||||||
|
bool recover(const std::string & from, const std::string & to);
|
||||||
void cancelProcessing();
|
void cancelProcessing();
|
||||||
bool exportMesh(
|
bool exportMesh(
|
||||||
float cloudVoxelSize,
|
float cloudVoxelSize,
|
||||||
|
|||||||
@@ -981,7 +981,7 @@
|
|||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 10;
|
CURRENT_PROJECT_VERSION = 11;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 3RRB6NV8U9;
|
DEVELOPMENT_TEAM = 3RRB6NV8U9;
|
||||||
EXCLUDED_ARCHS = "";
|
EXCLUDED_ARCHS = "";
|
||||||
@@ -1006,7 +1006,7 @@
|
|||||||
"$(PROJECT_DIR)/RTABMapApp/Libraries/lib",
|
"$(PROJECT_DIR)/RTABMapApp/Libraries/lib",
|
||||||
"$(PROJECT_DIR)/RTABMapApp/Libraries/share/OpenCV/3rdparty/lib",
|
"$(PROJECT_DIR)/RTABMapApp/Libraries/share/OpenCV/3rdparty/lib",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.20.16;
|
MARKETING_VERSION = "0.20.16-2";
|
||||||
OTHER_CFLAGS = "";
|
OTHER_CFLAGS = "";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.introlab.rtabmap;
|
PRODUCT_BUNDLE_IDENTIFIER = com.introlab.rtabmap;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -1038,7 +1038,7 @@
|
|||||||
CLANG_USE_OPTIMIZATION_PROFILE = NO;
|
CLANG_USE_OPTIMIZATION_PROFILE = NO;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 10;
|
CURRENT_PROJECT_VERSION = 11;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 3RRB6NV8U9;
|
DEVELOPMENT_TEAM = 3RRB6NV8U9;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@@ -1063,7 +1063,7 @@
|
|||||||
"$(PROJECT_DIR)/RTABMapApp/Libraries/lib",
|
"$(PROJECT_DIR)/RTABMapApp/Libraries/lib",
|
||||||
"$(PROJECT_DIR)/RTABMapApp/Libraries/share/OpenCV/3rdparty/lib",
|
"$(PROJECT_DIR)/RTABMapApp/Libraries/share/OpenCV/3rdparty/lib",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.20.16;
|
MARKETING_VERSION = "0.20.16-2";
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
OTHER_CFLAGS = "";
|
OTHER_CFLAGS = "";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.introlab.rtabmap;
|
PRODUCT_BUNDLE_IDENTIFIER = com.introlab.rtabmap;
|
||||||
|
|||||||
@@ -69,24 +69,11 @@ void setScreenRotationNative(const void *object, int displayRotation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize)
|
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize, bool clearDatabase)
|
||||||
{
|
{
|
||||||
if(object)
|
if(object)
|
||||||
{
|
{
|
||||||
return native(object)->openDatabase(databasePath, databaseInMemory, optimize);
|
return native(object)->openDatabase(databasePath, databaseInMemory, optimize, clearDatabase);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UERROR("object is null!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int openDatabase2Native(const void *object, const char * databaseSource, const char * databasePath, bool databaseInMemory, bool optimize)
|
|
||||||
{
|
|
||||||
if(object)
|
|
||||||
{
|
|
||||||
return native(object)->openDatabase(databasePath, databaseInMemory, optimize, databaseSource);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -107,6 +94,31 @@ void saveNative(const void *object, const char * databasePath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool recoverNative(const void *object, const char * from, const char * to)
|
||||||
|
{
|
||||||
|
if(object)
|
||||||
|
{
|
||||||
|
return native(object)->recover(from, to);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("object is null!");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelProcessingNative(const void *object)
|
||||||
|
{
|
||||||
|
if(object)
|
||||||
|
{
|
||||||
|
native(object)->cancelProcessing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("object is null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int postProcessingNative(const void *object, int approach)
|
int postProcessingNative(const void *object, int approach)
|
||||||
{
|
{
|
||||||
if(object)
|
if(object)
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ void setupCallbacksNative(const void *object, void * classPtr,
|
|||||||
float, float, float, float, float, float));
|
float, float, float, float, float, float));
|
||||||
void destroyNativeApplication(const void *object);
|
void destroyNativeApplication(const void *object);
|
||||||
void setScreenRotationNative(const void *object, int displayRotation);
|
void setScreenRotationNative(const void *object, int displayRotation);
|
||||||
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize);
|
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize, bool clearDatabase);
|
||||||
int openDatabase2Native(const void *object, const char * databaseSource, const char * databasePath, bool databaseInMemory, bool optimize);
|
|
||||||
void saveNative(const void *object, const char * databasePath);
|
void saveNative(const void *object, const char * databasePath);
|
||||||
|
bool recoverNative(const void *object, const char * from, const char * to);
|
||||||
|
void cancelProcessingNative(const void * object);
|
||||||
int postProcessingNative(const void *object, int approach);
|
int postProcessingNative(const void *object, int approach);
|
||||||
bool exportMeshNative(
|
bool exportMeshNative(
|
||||||
const void *object,
|
const void *object,
|
||||||
|
|||||||
@@ -113,17 +113,9 @@ class RTABMap {
|
|||||||
setupGraphicNative(native_rtabmap, Int32(size.width), Int32(size.height));
|
setupGraphicNative(native_rtabmap, Int32(size.width), Int32(size.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
func openDatabase(databasePath:String, databaseInMemory:Bool, optimize:Bool) -> Int {
|
func openDatabase(databasePath:String, databaseInMemory:Bool, optimize:Bool, clearDatabase: Bool) -> Int {
|
||||||
databasePath.utf8CString.withUnsafeBufferPointer { buffer -> Int in
|
databasePath.utf8CString.withUnsafeBufferPointer { buffer -> Int in
|
||||||
return Int(openDatabaseNative(native_rtabmap, buffer.baseAddress, databaseInMemory, optimize))
|
return Int(openDatabaseNative(native_rtabmap, buffer.baseAddress, databaseInMemory, optimize, clearDatabase))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func openDatabase(databaseSource:String, databasePath:String, databaseInMemory:Bool, optimize:Bool) -> Int {
|
|
||||||
databasePath.utf8CString.withUnsafeBufferPointer { buffer -> Int in
|
|
||||||
databaseSource.utf8CString.withUnsafeBufferPointer { bufferSource -> Int in
|
|
||||||
return Int(openDatabase2Native(native_rtabmap, bufferSource.baseAddress, buffer.baseAddress, databaseInMemory, optimize))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +125,18 @@ class RTABMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func recover(from: String, to: String) -> Bool {
|
||||||
|
from.utf8CString.withUnsafeBufferPointer { bufferFrom -> Bool in
|
||||||
|
to.utf8CString.withUnsafeBufferPointer { bufferTo -> Bool in
|
||||||
|
return recoverNative(native_rtabmap, bufferFrom.baseAddress, bufferTo.baseAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancelProcessing() {
|
||||||
|
cancelProcessingNative(native_rtabmap);
|
||||||
|
}
|
||||||
|
|
||||||
func postProcessing(approach: Int) -> Int {
|
func postProcessing(approach: Int) -> Int {
|
||||||
return Int(postProcessingNative(native_rtabmap, Int32(approach)))
|
return Int(postProcessingNative(native_rtabmap, Int32(approach)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1428,9 +1428,114 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
mMapNodes = 0;
|
mMapNodes = 0;
|
||||||
self.openedDatabasePath = nil
|
self.openedDatabasePath = nil
|
||||||
let tmpDatabase = self.getTmpDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
|
let tmpDatabase = self.getTmpDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
|
||||||
|
|
||||||
let inMemory = UserDefaults.standard.bool(forKey: "DatabaseInMemory")
|
let inMemory = UserDefaults.standard.bool(forKey: "DatabaseInMemory")
|
||||||
self.rtabmap!.openDatabase(databasePath: tmpDatabase.path, databaseInMemory: inMemory, optimize: false)
|
if(!(self.mState == State.STATE_CAMERA || self.mState == State.STATE_MAPPING) &&
|
||||||
|
FileManager.default.fileExists(atPath: tmpDatabase.path) &&
|
||||||
|
tmpDatabase.fileSize > 1024*1024) // > 1MB
|
||||||
|
{
|
||||||
|
dismiss(animated: true, completion: {
|
||||||
|
let msg = "The previous session (\(tmpDatabase.fileSizeString)) was not correctly saved, do you want to recover it?"
|
||||||
|
let alert = UIAlertController(title: "Recovery", message: msg, preferredStyle: .alert)
|
||||||
|
let alertActionNo = UIAlertAction(title: "Ignore", style: .destructive) {
|
||||||
|
(UIAlertAction) -> Void in
|
||||||
|
do {
|
||||||
|
try FileManager.default.removeItem(at: tmpDatabase)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
print("Could not clear tmp database: \(error)")
|
||||||
|
}
|
||||||
|
self.newScan()
|
||||||
|
}
|
||||||
|
alert.addAction(alertActionNo)
|
||||||
|
let alertActionCancel = UIAlertAction(title: "Cancel", style: .cancel) {
|
||||||
|
(UIAlertAction) -> Void in
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
alert.addAction(alertActionCancel)
|
||||||
|
let alertActionYes = UIAlertAction(title: "Yes", style: .default) {
|
||||||
|
(UIAlertAction2) -> Void in
|
||||||
|
|
||||||
|
let fileName = Date().getFormattedDate(format: "yyMMdd-HHmmss") + ".db"
|
||||||
|
let outputDbPath = self.getDocumentDirectory().appendingPathComponent(fileName).path
|
||||||
|
|
||||||
|
var indicator: UIActivityIndicatorView?
|
||||||
|
|
||||||
|
let alertView = UIAlertController(title: "Recovering", message: "Please wait while recovering data...", preferredStyle: .alert)
|
||||||
|
let alertViewActionCancel = UIAlertAction(title: "Cancel", style: .cancel) {
|
||||||
|
(UIAlertAction) -> Void in
|
||||||
|
self.dismiss(animated: true, completion: {
|
||||||
|
self.progressView = nil
|
||||||
|
|
||||||
|
indicator = UIActivityIndicatorView(style: .large)
|
||||||
|
indicator?.frame = CGRect(x: 0.0, y: 0.0, width: 60.0, height: 60.0)
|
||||||
|
indicator?.center = self.view.center
|
||||||
|
self.view.addSubview(indicator!)
|
||||||
|
indicator?.bringSubviewToFront(self.view)
|
||||||
|
|
||||||
|
indicator?.startAnimating()
|
||||||
|
self.rtabmap!.cancelProcessing();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
alertView.addAction(alertViewActionCancel)
|
||||||
|
|
||||||
|
let previousState = self.mState
|
||||||
|
self.updateState(state: .STATE_PROCESSING);
|
||||||
|
|
||||||
|
self.present(alertView, animated: true, completion: {
|
||||||
|
// Add your progressbar after alert is shown (and measured)
|
||||||
|
let margin:CGFloat = 8.0
|
||||||
|
let rect = CGRect(x: margin, y: 84.0, width: alertView.view.frame.width - margin * 2.0 , height: 2.0)
|
||||||
|
self.progressView = UIProgressView(frame: rect)
|
||||||
|
self.progressView!.progress = 0
|
||||||
|
self.progressView!.tintColor = self.view.tintColor
|
||||||
|
alertView.view.addSubview(self.progressView!)
|
||||||
|
|
||||||
|
var success : Bool = false
|
||||||
|
DispatchQueue.background(background: {
|
||||||
|
|
||||||
|
success = self.rtabmap!.recover(from: tmpDatabase.path, to: outputDbPath)
|
||||||
|
|
||||||
|
}, completion:{
|
||||||
|
if(indicator != nil)
|
||||||
|
{
|
||||||
|
indicator!.stopAnimating()
|
||||||
|
indicator!.removeFromSuperview()
|
||||||
|
}
|
||||||
|
if self.progressView != nil
|
||||||
|
{
|
||||||
|
self.dismiss(animated: self.openedDatabasePath == nil, completion: {
|
||||||
|
if(success)
|
||||||
|
{
|
||||||
|
let alertSaved = UIAlertController(title: "Database saved!", message: String(format: "Database \"%@\" successfully recovered!", fileName), preferredStyle: .alert)
|
||||||
|
let yes = UIAlertAction(title: "OK", style: .default) {
|
||||||
|
(UIAlertAction) -> Void in
|
||||||
|
self.openDatabase(fileUrl: URL(fileURLWithPath: outputDbPath))
|
||||||
|
}
|
||||||
|
alertSaved.addAction(yes)
|
||||||
|
self.present(alertSaved, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.updateState(state: previousState);
|
||||||
|
self.showToast(message: "Recovery failed!", seconds: 4)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.showToast(message: "Recovery canceled", seconds: 2)
|
||||||
|
self.updateState(state: previousState);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
alert.addAction(alertActionYes)
|
||||||
|
self.present(alert, animated: true, completion: nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.rtabmap!.openDatabase(databasePath: tmpDatabase.path, databaseInMemory: inMemory, optimize: false, clearDatabase: true)
|
||||||
|
|
||||||
if(!(self.mState == State.STATE_CAMERA || self.mState == State.STATE_MAPPING))
|
if(!(self.mState == State.STATE_CAMERA || self.mState == State.STATE_MAPPING))
|
||||||
{
|
{
|
||||||
@@ -1438,6 +1543,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
self.startCamera();
|
self.startCamera();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func save()
|
func save()
|
||||||
{
|
{
|
||||||
@@ -1519,12 +1625,19 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
|
|
||||||
self.openedDatabasePath = URL(fileURLWithPath: filePath)
|
self.openedDatabasePath = URL(fileURLWithPath: filePath)
|
||||||
|
|
||||||
let alert = UIAlertController(title: "Database saved!", message: String(format: "Database \"%@\" successfully saved on the SD-CARD!", fileName), preferredStyle: .alert)
|
let alert = UIAlertController(title: "Database saved!", message: String(format: "Database \"%@\" successfully saved!", fileName), preferredStyle: .alert)
|
||||||
let yes = UIAlertAction(title: "OK", style: .default) {
|
let yes = UIAlertAction(title: "OK", style: .default) {
|
||||||
(UIAlertAction) -> Void in
|
(UIAlertAction) -> Void in
|
||||||
}
|
}
|
||||||
alert.addAction(yes)
|
alert.addAction(yes)
|
||||||
self.present(alert, animated: true, completion: nil)
|
self.present(alert, animated: true, completion: nil)
|
||||||
|
do {
|
||||||
|
let tmpDatabase = self.getTmpDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
|
||||||
|
try FileManager.default.removeItem(at: tmpDatabase)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
print("Could not clear tmp database: \(error)")
|
||||||
|
}
|
||||||
self.updateDatabases()
|
self.updateDatabases()
|
||||||
self.updateState(state: previousState)
|
self.updateState(state: previousState)
|
||||||
})
|
})
|
||||||
@@ -1560,6 +1673,8 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
indicator?.bringSubviewToFront(self.view)
|
indicator?.bringSubviewToFront(self.view)
|
||||||
|
|
||||||
indicator?.startAnimating()
|
indicator?.startAnimating()
|
||||||
|
|
||||||
|
self.rtabmap!.cancelProcessing()
|
||||||
})
|
})
|
||||||
|
|
||||||
}))
|
}))
|
||||||
@@ -1664,6 +1779,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
|
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
|
||||||
self.dismiss(animated: true)
|
self.dismiss(animated: true)
|
||||||
self.progressView = nil
|
self.progressView = nil
|
||||||
|
self.rtabmap!.cancelProcessing()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let previousState = mState
|
let previousState = mState
|
||||||
@@ -1800,7 +1916,6 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
stopMapping(ignoreSaving: true)
|
stopMapping(ignoreSaving: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmpDatabase = self.getTmpDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
|
|
||||||
openedDatabasePath = fileUrl;
|
openedDatabasePath = fileUrl;
|
||||||
let fileName: String = self.openedDatabasePath!.lastPathComponent
|
let fileName: String = self.openedDatabasePath!.lastPathComponent
|
||||||
|
|
||||||
@@ -1812,7 +1927,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
updateState(state: .STATE_PROCESSING);
|
updateState(state: .STATE_PROCESSING);
|
||||||
var status = 0
|
var status = 0
|
||||||
DispatchQueue.background(background: {
|
DispatchQueue.background(background: {
|
||||||
status = self.rtabmap!.openDatabase(databaseSource: self.openedDatabasePath!.path, databasePath: tmpDatabase.path, databaseInMemory: true, optimize: false)
|
status = self.rtabmap!.openDatabase(databasePath: self.openedDatabasePath!.path, databaseInMemory: true, optimize: false, clearDatabase: false)
|
||||||
}, completion:{
|
}, completion:{
|
||||||
// main thread
|
// main thread
|
||||||
if(status == -1) {
|
if(status == -1) {
|
||||||
@@ -1974,6 +2089,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
|
|||||||
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
|
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
|
||||||
self.dismiss(animated: true)
|
self.dismiss(animated: true)
|
||||||
self.progressView = nil
|
self.progressView = nil
|
||||||
|
self.rtabmap!.cancelProcessing()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let previousState = mState;
|
let previousState = mState;
|
||||||
|
|||||||
Reference in New Issue
Block a user