Reprocess: added -track_changes option. Added rtabmap-dpupdate.

This commit is contained in:
matlabbe
2026-07-10 19:39:22 -07:00
parent e321999b15
commit 15109dfa9e
19 changed files with 179202 additions and 47017 deletions

View File

@@ -21,8 +21,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
# VERSION # VERSION
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 23) SET(RTABMAP_MINOR_VERSION 24)
SET(RTABMAP_PATCH_VERSION 8) SET(RTABMAP_PATCH_VERSION 0)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})

View File

@@ -72,6 +72,14 @@ public:
const std::string & getUrl() const {return _url;} const std::string & getUrl() const {return _url;}
const std::string & getTargetVersion() const {return _targetVersion;} const std::string & getTargetVersion() const {return _targetVersion;}
// Start recording changes made to the database until it is closed, then write a compact
// delta of those changes to outputUrl (empty disables). Returns true if recording is
// active. Only the SQLite backend supports it (session extension + database version
// >= 0.24); other backends return false.
// NOTE: recorded changes are held in RAM until the database is closed, so only enable
// this when the expected set of changes is small.
virtual bool trackDatabaseChanges(const std::string & outputUrl) {(void)outputUrl; return false;}
void beginTransaction() const; void beginTransaction() const;
void commit() const; void commit() const;

View File

@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef struct sqlite3_stmt sqlite3_stmt; typedef struct sqlite3_stmt sqlite3_stmt;
typedef struct sqlite3 sqlite3; typedef struct sqlite3 sqlite3;
typedef struct sqlite3_session sqlite3_session;
namespace rtabmap { namespace rtabmap {
@@ -49,6 +50,26 @@ public:
void setCacheSize(unsigned int cacheSize); void setCacheSize(unsigned int cacheSize);
void setSynchronous(int synchronous); void setSynchronous(int synchronous);
void setTempStore(int tempStore); void setTempStore(int tempStore);
// Start recording changes made to the database from now until it is closed, then write
// a compact patchset delta to outputUrl (empty disables). Can be called before the
// connection is opened or on an already-open connection (e.g. after init(), so the
// baseline is the current content). Returns true if recording is active. Only effective
// if the build/runtime SQLite has the session extension and the database is version >= 0.24.
// NOTE: the SQLite session extension holds ALL recorded changes in RAM until the database
// is closed (there is no incremental spill to disk), so only enable this when the expected
// set of changes is small (e.g. appending a few sessions), not for rewriting a whole map.
virtual bool trackDatabaseChanges(const std::string & outputUrl);
// Apply a change delta previously written by setTrackChangesOutput() onto the database
// at databasePath (which must be the same database, at the same state, the delta was
// generated from). The file is decompressed (same codec as the other rtabmap blobs) then
// applied with the SQLite session extension. Returns true on success; on failure returns
// false and, if errorMsg is not null, sets a human-readable message. Requires a SQLite
// library built with the session extension (both at build and runtime).
static bool applyChangesFromFile(
const std::string & databasePath,
const std::string & patchsetPath,
std::string * errorMsg = 0);
protected: protected:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false); virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false);
@@ -197,6 +218,7 @@ private:
void loadWordIdsQuery(std::list<Signature *> & signatures) const; void loadWordIdsQuery(std::list<Signature *> & signatures) const;
void loadLinksQuery(std::list<Signature *> & signatures) const; void loadLinksQuery(std::list<Signature *> & signatures) const;
int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const; int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const;
void startChangeTracking(); // attach the change-tracking session on the open connection
protected: protected:
sqlite3 * _ppDb; sqlite3 * _ppDb;
@@ -209,6 +231,12 @@ private:
int _journalMode; int _journalMode;
int _synchronous; int _synchronous;
int _tempStore; int _tempStore;
// DB change tracking (SQLite session extension). Members are always present to keep
// the class layout stable regardless of RTABMAP_WITH_SQLITE3_SESSION; the session is
// only created/used when the feature is compiled in and enabled.
sqlite3_session * _session;
std::string _trackChangesOutput;
}; };
} }

View File

@@ -182,6 +182,9 @@ public:
int getDatabaseMemoryUsed() const; // in bytes int getDatabaseMemoryUsed() const; // in bytes
std::string getDatabaseVersion() const; std::string getDatabaseVersion() const;
std::string getDatabaseUrl() const; std::string getDatabaseUrl() const;
// Record changes made to the database until it is closed, then write a compact delta
// to outputUrl (empty disables). Returns true if recording started. See DBDriver.
bool trackDatabaseChanges(const std::string & outputUrl);
double getDbSavingTime() const; double getDbSavingTime() const;
int getMapId(int id, bool lookInDatabase = false) const; int getMapId(int id, bool lookInDatabase = false) const;
Transform getOdomPose(int signatureId, bool lookInDatabase = false) const; Transform getOdomPose(int signatureId, bool lookInDatabase = false) const;

View File

@@ -146,6 +146,13 @@ public:
Transform getPose(int locationId) const; Transform getPose(int locationId) const;
Transform getMapCorrection() const {return _mapCorrection;} Transform getMapCorrection() const {return _mapCorrection;}
const Memory * getMemory() const {return _memory;} const Memory * getMemory() const {return _memory;}
// Record changes made to the working database from now until it is closed, then write a
// compact delta to outputUrl (empty disables). Call after init(), so the delta reflects
// only what is added/modified afterwards. Returns true if recording started (requires the
// SQLite session extension and a database version >= 0.24). See DBDriver.
// NOTE: recorded changes are held in RAM until the database is closed, so only enable this
// when the expected set of changes is small (e.g. appending a few sessions).
bool trackDatabaseChanges(const std::string & outputUrl);
float getGoalReachedRadius() const {return _goalReachedRadius;} float getGoalReachedRadius() const {return _goalReachedRadius;}
float getLocalRadius() const {return _localRadius;} float getLocalRadius() const {return _localRadius;}
const Transform & getLastLocalizationPose() const {return _lastLocalizationPose;} const Transform & getLastLocalizationPose() const {return _lastLocalizationPose;}

View File

@@ -196,6 +196,16 @@ IF(SQLite3_FOUND)
${LIBRARIES} ${LIBRARIES}
${SQLite3_LIBRARIES} ${SQLite3_LIBRARIES}
) )
# The SQLite session extension (used to track DB diffs) needs SQLite >= 3.13.0.
# Defining SQLITE_ENABLE_SESSION here only exposes the session declarations in the
# system sqlite3.h; whether the linked library was actually built with the extension
# is verified at runtime with sqlite3_compileoption_used("ENABLE_SESSION").
IF(SQLite3_VERSION VERSION_GREATER_EQUAL "3.13.0")
SET(SQLITE3_SESSION_DEFINITIONS SQLITE_ENABLE_SESSION SQLITE_ENABLE_PREUPDATE_HOOK RTABMAP_WITH_SQLITE3_SESSION)
MESSAGE(STATUS " With SQLite3 session ext = YES (system SQLite3 ${SQLite3_VERSION}, verified at runtime)")
ELSE()
MESSAGE(STATUS " With SQLite3 session ext = NO (system SQLite3 ${SQLite3_VERSION} < 3.13.0)")
ENDIF()
ELSE() ELSE()
SET(SRC_FILES SET(SRC_FILES
${SRC_FILES} ${SRC_FILES}
@@ -205,6 +215,9 @@ ELSE()
${CMAKE_CURRENT_SOURCE_DIR}/sqlite3 ${CMAKE_CURRENT_SOURCE_DIR}/sqlite3
${INCLUDE_DIRS} ${INCLUDE_DIRS}
) )
# We compile the bundled amalgamation ourselves, so enable the session extension in it.
SET(SQLITE3_SESSION_DEFINITIONS SQLITE_ENABLE_SESSION SQLITE_ENABLE_PREUPDATE_HOOK RTABMAP_WITH_SQLITE3_SESSION)
MESSAGE(STATUS " With SQLite3 session ext = YES (bundled SQLite3)")
ENDIF() ENDIF()
IF(TORCH_FOUND) IF(TORCH_FOUND)
@@ -830,6 +843,7 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql.in ${CMA
SET(RESOURCES SET(RESOURCES
${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_23_0.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_22_0.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_22_0.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_20_0.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_20_0.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_3.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_3.sql
@@ -893,6 +907,13 @@ TARGET_LINK_LIBRARIES(rtabmap_core
PRIVATE PRIVATE
${LIBRARIES}) ${LIBRARIES})
# Enable the SQLite session extension for the core sources (bundled sqlite3.c and
# DBDriverSqlite3.cpp). Kept PRIVATE so it only affects rtabmap_core's own TUs and
# never changes the public header layout for downstream consumers.
IF(SQLITE3_SESSION_DEFINITIONS)
target_compile_definitions(rtabmap_core PRIVATE ${SQLITE3_SESSION_DEFINITIONS})
ENDIF()
SET_TARGET_PROPERTIES( SET_TARGET_PROPERTIES(
rtabmap_core rtabmap_core
PROPERTIES PROPERTIES

View File

@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/util3d.h" #include "rtabmap/core/util3d.h"
#include "rtabmap/core/Compression.h" #include "rtabmap/core/Compression.h"
#include "DatabaseSchema_sql.h" #include "DatabaseSchema_sql.h"
#include "DatabaseSchema_0_23_0_sql.h"
#include "DatabaseSchema_0_22_0_sql.h" #include "DatabaseSchema_0_22_0_sql.h"
#include "DatabaseSchema_0_20_0_sql.h" #include "DatabaseSchema_0_20_0_sql.h"
#include "DatabaseSchema_0_18_3_sql.h" #include "DatabaseSchema_0_18_3_sql.h"
@@ -45,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set> #include <set>
#include <cstdio>
#include "rtabmap/utilite/UtiLite.h" #include "rtabmap/utilite/UtiLite.h"
@@ -59,7 +61,8 @@ DBDriverSqlite3::DBDriverSqlite3(const ParametersMap & parameters) :
_cacheSize(Parameters::defaultDbSqlite3CacheSize()), _cacheSize(Parameters::defaultDbSqlite3CacheSize()),
_journalMode(Parameters::defaultDbSqlite3JournalMode()), _journalMode(Parameters::defaultDbSqlite3JournalMode()),
_synchronous(Parameters::defaultDbSqlite3Synchronous()), _synchronous(Parameters::defaultDbSqlite3Synchronous()),
_tempStore(Parameters::defaultDbSqlite3TempStore()) _tempStore(Parameters::defaultDbSqlite3TempStore()),
_session(0)
{ {
ULOGGER_DEBUG("treadSafe=%d", sqlite3_threadsafe()); ULOGGER_DEBUG("treadSafe=%d", sqlite3_threadsafe());
this->parseParameters(parameters); this->parseParameters(parameters);
@@ -218,6 +221,149 @@ void DBDriverSqlite3::setDbInMemory(bool dbInMemory)
} }
} }
void DBDriverSqlite3::startChangeTracking()
{
#ifdef RTABMAP_WITH_SQLITE3_SESSION
if(_session != 0 || _trackChangesOutput.empty() || _ppDb == 0)
{
// Already tracking, nothing requested, or not connected yet.
return;
}
if(uStrNumCmp(_version, "0.24.0") < 0)
{
UWARN("Database change tracking to \"%s\" was requested but the database "
"version is %s (< 0.24.0). Older schemas lack the primary keys required "
"by the SQLite session extension, so change tracking is disabled.",
_trackChangesOutput.c_str(), _version.c_str());
}
else if(!sqlite3_compileoption_used("ENABLE_SESSION"))
{
UWARN("Database change tracking to \"%s\" was requested but the linked SQLite "
"library was not built with the session extension (ENABLE_SESSION); "
"change tracking is disabled.", _trackChangesOutput.c_str());
}
else if(sqlite3session_create(_ppDb, "main", &_session) == SQLITE_OK)
{
sqlite3session_attach(_session, 0); // 0 = track all tables
UINFO("Tracking database changes; a patchset will be written to \"%s\" on close.",
_trackChangesOutput.c_str());
}
else
{
UWARN("Could not create a SQLite session to track database changes to \"%s\".",
_trackChangesOutput.c_str());
_session = 0;
}
#endif
}
bool DBDriverSqlite3::trackDatabaseChanges(const std::string & outputUrl)
{
UDEBUG("outputUrl=%s", outputUrl.c_str());
_trackChangesOutput = outputUrl;
#ifdef RTABMAP_WITH_SQLITE3_SESSION
// If the connection is already open (e.g. set after connect(), as rtabmap-reprocess
// does after init()), start tracking now on the current baseline state. Otherwise it
// will start automatically when the connection is opened.
if(!outputUrl.empty() && _ppDb != 0)
{
this->startChangeTracking();
}
return _session != 0;
#else
if(!outputUrl.empty())
{
UWARN("Database change tracking to \"%s\" was requested but rtabmap was built "
"against a SQLite library without the session extension; it is disabled.",
outputUrl.c_str());
}
return false;
#endif
}
#ifdef RTABMAP_WITH_SQLITE3_SESSION
static int rtabmapChangesetConflict(void * pCtx, int eConflict, sqlite3_changeset_iter * pIter)
{
// A patchset upgrade must apply cleanly onto the exact database it was generated from.
// Any conflict means the wrong base database (or an already-applied delta), so abort
// rather than silently produce an inconsistent result.
return SQLITE_CHANGESET_ABORT;
}
#endif
bool DBDriverSqlite3::applyChangesFromFile(
const std::string & databasePath,
const std::string & patchsetPath,
std::string * errorMsg)
{
#ifdef RTABMAP_WITH_SQLITE3_SESSION
if(!sqlite3_compileoption_used("ENABLE_SESSION"))
{
if(errorMsg) *errorMsg = "The linked SQLite library was not built with the session extension.";
return false;
}
// Read the compressed patchset file.
FILE * fp = fopen(patchsetPath.c_str(), "rb");
if(!fp)
{
if(errorMsg) *errorMsg = uFormat("Could not open patchset file \"%s\".", patchsetPath.c_str());
return false;
}
fseek(fp, 0, SEEK_END);
long fileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if(fileSize <= 0)
{
fclose(fp);
if(errorMsg) *errorMsg = uFormat("Patchset file \"%s\" is empty or unreadable.", patchsetPath.c_str());
return false;
}
std::vector<unsigned char> fileBytes((size_t)fileSize);
size_t bytesRead = fread(fileBytes.data(), 1, (size_t)fileSize, fp);
fclose(fp);
if((long)bytesRead != fileSize)
{
if(errorMsg) *errorMsg = uFormat("Could not read patchset file \"%s\".", patchsetPath.c_str());
return false;
}
// Decompress to the raw patchset (same codec used to write it).
cv::Mat patch = uncompressData(fileBytes.data(), (unsigned long)fileSize);
if(patch.empty())
{
if(errorMsg) *errorMsg = uFormat("Could not decompress patchset file \"%s\".", patchsetPath.c_str());
return false;
}
// Apply onto the target database.
sqlite3 * db = 0;
int rc = sqlite3_open_v2(databasePath.c_str(), &db, SQLITE_OPEN_READWRITE, 0);
if(rc != SQLITE_OK)
{
if(errorMsg) *errorMsg = uFormat("Could not open database \"%s\": %s", databasePath.c_str(), sqlite3_errmsg(db));
sqlite3_close(db);
return false;
}
int nPatch = (int)(patch.total()*patch.elemSize());
rc = sqlite3changeset_apply(db, nPatch, patch.data, 0, rtabmapChangesetConflict, 0);
if(rc != SQLITE_OK)
{
if(errorMsg) *errorMsg = uFormat("Failed to apply patchset to \"%s\" (SQLite error %d: %s). Make "
"sure it is applied to the exact database state the delta was generated from.",
databasePath.c_str(), rc, sqlite3_errstr(rc));
sqlite3_close(db);
return false;
}
sqlite3_close(db);
return true;
#else
if(errorMsg) *errorMsg = "rtabmap was built without SQLite session support.";
return false;
#endif
}
/* /*
** This function is used to load the contents of a database file on disk ** This function is used to load the contents of a database file on disk
** into the "main" database of open database connection pInMemory, or ** into the "main" database of open database connection pInMemory, or
@@ -406,6 +552,7 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
schemas.push_back(std::make_pair("0.18.3", DATABASESCHEMA_0_18_3_SQL)); schemas.push_back(std::make_pair("0.18.3", DATABASESCHEMA_0_18_3_SQL));
schemas.push_back(std::make_pair("0.20.0", DATABASESCHEMA_0_20_0_SQL)); schemas.push_back(std::make_pair("0.20.0", DATABASESCHEMA_0_20_0_SQL));
schemas.push_back(std::make_pair("0.22.0", DATABASESCHEMA_0_22_0_SQL)); schemas.push_back(std::make_pair("0.22.0", DATABASESCHEMA_0_22_0_SQL));
schemas.push_back(std::make_pair("0.23.0", DATABASESCHEMA_0_23_0_SQL));
schemas.push_back(std::make_pair(uNumber2Str(RTABMAP_VERSION_MAJOR)+"."+uNumber2Str(RTABMAP_VERSION_MINOR), DATABASESCHEMA_SQL)); schemas.push_back(std::make_pair(uNumber2Str(RTABMAP_VERSION_MAJOR)+"."+uNumber2Str(RTABMAP_VERSION_MINOR), DATABASESCHEMA_SQL));
for(size_t i=0; i<schemas.size(); ++i) for(size_t i=0; i<schemas.size(); ++i)
{ {
@@ -446,6 +593,14 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
this->setSynchronous(_synchronous); // this will call the SQL this->setSynchronous(_synchronous); // this will call the SQL
this->setTempStore(_tempStore); // this will call the SQL this->setTempStore(_tempStore); // this will call the SQL
// Start tracking database changes if a recording path was already set (before the
// connection was opened). Done here, after any initial load and once the version is
// known, so the delta reflects only the changes made between open and close.
if(!readOnly)
{
this->startChangeTracking();
}
return true; return true;
} }
void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & outputUrl) void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & outputUrl)
@@ -489,6 +644,56 @@ void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & out
} }
} }
#ifdef RTABMAP_WITH_SQLITE3_SESSION
// If change tracking is active, emit the accumulated patchset before closing.
if(_session)
{
int nBuf = 0;
void * pBuf = 0;
int rcp = sqlite3session_patchset(_session, &nBuf, &pBuf);
if(rcp == SQLITE_OK && pBuf && nBuf > 0)
{
// Compress the patchset with the same zlib-based codec used for every other
// rtabmap blob, so the delta is compact for transfer. To apply it later,
// uncompressData() the file and pass the bytes to sqlite3changeset_apply().
cv::Mat compressed = compressData2(cv::Mat(1, nBuf, CV_8UC1, pBuf));
FILE * fp = fopen(_trackChangesOutput.c_str(), "wb");
if(fp)
{
size_t toWrite = compressed.total()*compressed.elemSize();
size_t written = fwrite(compressed.data, 1, toWrite, fp);
fclose(fp);
if(written == toWrite)
{
UINFO("Wrote compressed database patchset (%d -> %d bytes) to \"%s\".",
nBuf, (int)toWrite, _trackChangesOutput.c_str());
}
else
{
UERROR("Could only write %d/%d bytes of the database patchset to \"%s\".",
(int)written, (int)toWrite, _trackChangesOutput.c_str());
}
}
else
{
UERROR("Could not open \"%s\" to write the database patchset.", _trackChangesOutput.c_str());
}
}
else if(rcp != SQLITE_OK)
{
UERROR("Could not generate the database patchset for \"%s\" (SQLite error %d).",
_trackChangesOutput.c_str(), rcp);
}
else
{
UINFO("No database changes to write; \"%s\" was not created.", _trackChangesOutput.c_str());
}
sqlite3_free(pBuf);
sqlite3session_delete(_session);
_session = 0;
}
#endif
// Then close (delete) the database connection // Then close (delete) the database connection
UINFO("Disconnecting database %s...", this->getUrl().c_str()); UINFO("Disconnecting database %s...", this->getUrl().c_str());
sqlite3_close(_ppDb); sqlite3_close(_ppDb);

View File

@@ -1994,6 +1994,11 @@ double Memory::getDbSavingTime() const
return _dbDriver?_dbDriver->getEmptyTrashesTime():0; return _dbDriver?_dbDriver->getEmptyTrashesTime():0;
} }
bool Memory::trackDatabaseChanges(const std::string & outputUrl)
{
return _dbDriver?_dbDriver->trackDatabaseChanges(outputUrl):false;
}
std::set<int> Memory::getAllSignatureIds(bool ignoreChildren) const std::set<int> Memory::getAllSignatureIds(bool ignoreChildren) const
{ {
std::set<int> ids; std::set<int> ids;

View File

@@ -885,6 +885,11 @@ Transform Rtabmap::getPose(int locationId) const
return uValue(_optimizedPoses, locationId, Transform()); return uValue(_optimizedPoses, locationId, Transform());
} }
bool Rtabmap::trackDatabaseChanges(const std::string & outputUrl)
{
return _memory?_memory->trackDatabaseChanges(outputUrl):false;
}
void Rtabmap::setInitialPose(const Transform & initialPose) void Rtabmap::setInitialPose(const Transform & initialPose)
{ {
if(_memory) if(_memory)

View File

@@ -52,6 +52,7 @@ CREATE TABLE Data (
); );
CREATE TABLE Link ( CREATE TABLE Link (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking); (from_id,to_id) is not unique (a node pair can have several links)
from_id INTEGER NOT NULL, from_id INTEGER NOT NULL,
to_id INTEGER NOT NULL, to_id INTEGER NOT NULL,
type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8 type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8
@@ -72,6 +73,7 @@ CREATE TABLE Word (
); );
CREATE TABLE Feature ( CREATE TABLE Feature (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
node_id INTEGER NOT NULL, node_id INTEGER NOT NULL,
word_id INTEGER NOT NULL, word_id INTEGER NOT NULL,
pos_x FLOAT NOT NULL, pos_x FLOAT NOT NULL,
@@ -89,6 +91,7 @@ CREATE TABLE Feature (
); );
CREATE TABLE GlobalDescriptor ( CREATE TABLE GlobalDescriptor (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
node_id INTEGER NOT NULL, node_id INTEGER NOT NULL,
type INTEGER NOT NULL, type INTEGER NOT NULL,
info BLOB, info BLOB,
@@ -99,6 +102,7 @@ CREATE TABLE GlobalDescriptor (
-- --
CREATE TABLE Info ( CREATE TABLE Info (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
STM_size INTEGER, STM_size INTEGER,
last_sign_added INTEGER, last_sign_added INTEGER,
process_mem_used INTEGER, process_mem_used INTEGER,
@@ -113,11 +117,12 @@ CREATE TABLE Statistics (
stamp FLOAT, stamp FLOAT,
data BLOB, -- compressed string data BLOB, -- compressed string
wm_state BLOB, -- compressed data wm_state BLOB, -- compressed data
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES Node(id) FOREIGN KEY (id) REFERENCES Node(id)
); );
CREATE TABLE Admin ( CREATE TABLE Admin (
version TEXT, version TEXT PRIMARY KEY,
preview_image BLOB, -- compressed image preview_image BLOB, -- compressed image
opt_cloud BLOB, -- compressed data opt_cloud BLOB, -- compressed data
@@ -176,7 +181,6 @@ CREATE INDEX IDX_Feature_node_id on Feature (node_id);
CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id); CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id);
CREATE INDEX IDX_Link_from_id on Link (from_id); CREATE INDEX IDX_Link_from_id on Link (from_id);
CREATE UNIQUE INDEX IDX_node_label on Node (label); CREATE UNIQUE INDEX IDX_node_label on Node (label);
CREATE UNIQUE INDEX IDX_Statistics_id on Statistics (id);
-- ******************************************************************* -- *******************************************************************
-- VERSION -- VERSION

View File

@@ -0,0 +1,184 @@
-- *******************************************************************
-- DatabaseSchema: Script for creating the database
-- Usage:
-- $ sqlite3 LTM.db < DatabaseSchema.sql
--
-- *******************************************************************
-- *******************************************************************
-- CLEAN
-- *******************************************************************
/*DROP TABLE Node;*/
-- *******************************************************************
-- CREATE
-- *******************************************************************
CREATE TABLE Node (
id INTEGER NOT NULL,
map_id INTEGER NOT NULL,
weight INTEGER,
stamp FLOAT,
pose BLOB, -- 3x4 float
ground_truth_pose BLOB, -- 3x4 float
velocity BLOB, -- 6 float (vx,vy,vz,vroll,vpitch,vyaw) m/s and rad/s
label TEXT,
gps BLOB, -- 1x6 double: stamp, longitude (DD), latitude (DD), altitude (m), accuracy (m), bearing (North 0->360 deg clockwise)
env_sensors BLOB, -- Variable 3xdouble: (sensorId1, value, stamp, sensorId2, value, stamp, ...)
time_enter DATE,
PRIMARY KEY (id)
);
CREATE TABLE Data (
id INTEGER NOT NULL,
image BLOB, -- compressed image (Grayscale or RGB)
depth BLOB, -- compressed image (Depth or Right image)
depth_confidence BLOB, -- compressed data (low=0 high=100)
calibration BLOB, -- fx, fy, cx, cy, [baseline,] width, height, local_transform
scan BLOB, -- compressed data (Laser scan)
scan_info BLOB, -- scan_max_pts, scan_max_range, scan_format, local_transform
ground_cells BLOB, -- compressed data (occupancy grid)
obstacle_cells BLOB, -- compressed data (occupancy grid)
empty_cells BLOB, -- compressed data (occupancy grid)
cell_size FLOAT,
view_point_x FLOAT,
view_point_y FLOAT,
view_point_z FLOAT,
user_data BLOB, -- compressed data (User data)
time_enter DATE,
PRIMARY KEY (id)
);
CREATE TABLE Link (
from_id INTEGER NOT NULL,
to_id INTEGER NOT NULL,
type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8
information_matrix BLOB NOT NULL, -- 6x6 double (inverse covariance)
transform BLOB, -- 3x4 float
user_data BLOB, -- compressed data (User data)
FOREIGN KEY (from_id) REFERENCES Node(id),
FOREIGN KEY (to_id) REFERENCES Node(id)
);
--
CREATE TABLE Word (
id INTEGER NOT NULL,
descriptor_size INTEGER NOT NULL,
descriptor BLOB NOT NULL,
time_enter DATE,
PRIMARY KEY (id)
);
CREATE TABLE Feature (
node_id INTEGER NOT NULL,
word_id INTEGER NOT NULL,
pos_x FLOAT NOT NULL,
pos_y FLOAT NOT NULL,
size INTEGER NOT NULL,
dir FLOAT NOT NULL,
response FLOAT NOT NULL,
octave INTEGER NOT NULL,
depth_x FLOAT,
depth_y FLOAT,
depth_z FLOAT,
descriptor_size INTEGER,
descriptor BLOB,
FOREIGN KEY (node_id) REFERENCES Node(id)
);
CREATE TABLE GlobalDescriptor (
node_id INTEGER NOT NULL,
type INTEGER NOT NULL,
info BLOB,
data BLOB NOT NULL,
FOREIGN KEY (node_id) REFERENCES Node(id)
);
--
CREATE TABLE Info (
STM_size INTEGER,
last_sign_added INTEGER,
process_mem_used INTEGER,
database_mem_used INTEGER,
dictionary_size INTEGER,
parameters TEXT,
time_enter DATE
);
CREATE TABLE Statistics (
id INTEGER NOT NULL,
stamp FLOAT,
data BLOB, -- compressed string
wm_state BLOB, -- compressed data
FOREIGN KEY (id) REFERENCES Node(id)
);
CREATE TABLE Admin (
version TEXT,
preview_image BLOB, -- compressed image
opt_cloud BLOB, -- compressed data
opt_ids BLOB, -- Node ids used to generate the optimized cloud/mesh
opt_poses BLOB, -- compressed N*3x4 float
opt_last_localization BLOB, -- 3x4 float
opt_polygons_size INTEGER, -- e.g., 3
opt_polygons BLOB, -- compressed data [length_v0, i0,i1,i3, length_v1, i0,i1,i3]
opt_tex_coords BLOB, -- compressed data [length_v0, u0,v0,u1,v1,u2,v2, length_v1, u0,v0,u1,v1,u2,v2]
opt_tex_materials BLOB, -- compressed image
opt_map BLOB, -- compressed CV_8SC1 occupancy grid
opt_map_x_min FLOAT,
opt_map_y_min FLOAT,
opt_map_resolution FLOAT,
dictionary_index BLOB, -- serialized dictionary index
time_enter DATE
);
-- *******************************************************************
-- TRIGGERS
-- *******************************************************************
CREATE TRIGGER insert_Feature BEFORE INSERT ON Feature
WHEN NOT EXISTS (SELECT Node.id FROM Node WHERE Node.id = NEW.node_id)
BEGIN
SELECT RAISE(ABORT, 'Foreign key constraint failed in Feature table');
END;
-- Creating a trigger for time_enter
CREATE TRIGGER insert_Node_timeEnter AFTER INSERT ON Node
BEGIN
UPDATE Node SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
CREATE TRIGGER insert_Data_timeEnter AFTER INSERT ON Data
BEGIN
UPDATE Node SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
CREATE TRIGGER insert_Word_timeEnter AFTER INSERT ON Word
BEGIN
UPDATE Word SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
CREATE TRIGGER insert_Info_timeEnter AFTER INSERT ON Info
BEGIN
UPDATE Info SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
-- *******************************************************************
-- INDEXES
-- *******************************************************************
CREATE UNIQUE INDEX IDX_Node_id on Node (id);
CREATE INDEX IDX_Feature_node_id on Feature (node_id);
CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id);
CREATE INDEX IDX_Link_from_id on Link (from_id);
CREATE UNIQUE INDEX IDX_node_label on Node (label);
CREATE UNIQUE INDEX IDX_Statistics_id on Statistics (id);
-- *******************************************************************
-- VERSION
-- *******************************************************************
INSERT INTO Admin(version) VALUES('0.23.0');

View File

@@ -1,3 +1,3 @@
Version 3.53.3
Info: https://www.sqlite.org/ Info: https://www.sqlite.org/
License: Public domain (https://www.sqlite.org/copyright.html) License: Public domain (https://www.sqlite.org/copyright.html)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,12 +15,10 @@
** as extensions by SQLite should #include this file instead of ** as extensions by SQLite should #include this file instead of
** sqlite3.h. ** sqlite3.h.
*/ */
#ifndef _SQLITE3EXT_H_ #ifndef SQLITE3EXT_H
#define _SQLITE3EXT_H_ #define SQLITE3EXT_H
#include "sqlite3.h" #include "sqlite3.h"
typedef struct sqlite3_api_routines sqlite3_api_routines;
/* /*
** The following structure holds pointers to all of the SQLite API ** The following structure holds pointers to all of the SQLite API
** routines. ** routines.
@@ -28,7 +26,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** WARNING: In order to maintain backwards compatibility, add new ** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new ** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different ** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each others' shared ** versions of SQLite will not be able to load each other's shared
** libraries! ** libraries!
*/ */
struct sqlite3_api_routines { struct sqlite3_api_routines {
@@ -136,7 +134,7 @@ struct sqlite3_api_routines {
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*); const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...); char * (*xsnprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*); int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*); char const**,char const**,int*,int*,int*);
@@ -248,13 +246,151 @@ struct sqlite3_api_routines {
int (*uri_boolean)(const char*,const char*,int); int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*); const char *(*uri_parameter)(const char*,const char*);
char *(*vsnprintf)(int,char*,const char*,va_list); char *(*xvsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(sqlite3_value*);
void (*result_subtype)(sqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(sqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(sqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
/* Version 3.20.0 and later */
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
sqlite3_stmt**,const char**);
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
sqlite3_stmt**,const void**);
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
void *(*value_pointer)(sqlite3_value*,const char*);
int (*vtab_nochange)(sqlite3_context*);
int (*value_nochange)(sqlite3_value*);
const char *(*vtab_collation)(sqlite3_index_info*,int);
/* Version 3.24.0 and later */
int (*keyword_count)(void);
int (*keyword_name)(int,const char**,int*);
int (*keyword_check)(const char*,int);
sqlite3_str *(*str_new)(sqlite3*);
char *(*str_finish)(sqlite3_str*);
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
void (*str_append)(sqlite3_str*, const char *zIn, int N);
void (*str_appendall)(sqlite3_str*, const char *zIn);
void (*str_appendchar)(sqlite3_str*, int N, char C);
void (*str_reset)(sqlite3_str*);
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
/* Version 3.25.0 and later */
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
void(*xDestroy)(void*));
/* Version 3.26.0 and later */
const char *(*normalized_sql)(sqlite3_stmt*);
/* Version 3.28.0 and later */
int (*stmt_isexplain)(sqlite3_stmt*);
int (*value_frombind)(sqlite3_value*);
/* Version 3.30.0 and later */
int (*drop_modules)(sqlite3*,const char**);
/* Version 3.31.0 and later */
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
const char *(*uri_key)(const char*,int);
const char *(*filename_database)(const char*);
const char *(*filename_journal)(const char*);
const char *(*filename_wal)(const char*);
/* Version 3.32.0 and later */
const char *(*create_filename)(const char*,const char*,const char*,
int,const char**);
void (*free_filename)(const char*);
sqlite3_file *(*database_file_object)(const char*);
/* Version 3.34.0 and later */
int (*txn_state)(sqlite3*,const char*);
/* Version 3.36.1 and later */
sqlite3_int64 (*changes64)(sqlite3*);
sqlite3_int64 (*total_changes64)(sqlite3*);
/* Version 3.37.0 and later */
int (*autovacuum_pages)(sqlite3*,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*, void(*)(void*));
/* Version 3.38.0 and later */
int (*error_offset)(sqlite3*);
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
int (*vtab_distinct)(sqlite3_index_info*);
int (*vtab_in)(sqlite3_index_info*,int,int);
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
/* Version 3.39.0 and later */
int (*deserialize)(sqlite3*,const char*,unsigned char*,
sqlite3_int64,sqlite3_int64,unsigned);
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
unsigned int);
const char *(*db_name)(sqlite3*,int);
/* Version 3.40.0 and later */
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
/* Version 3.43.0 and later */
int (*stmt_explain)(sqlite3_stmt*,int);
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
/* Version 3.50.0 and later */
int (*setlk_timeout)(sqlite3*,int,int);
/* Version 3.51.0 and later */
int (*set_errmsg)(sqlite3*,int,const char*);
int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
/* Version 3.52.0 and later */
void (*str_truncate)(sqlite3_str*,int);
void (*str_free)(sqlite3_str*);
int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
}; };
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
sqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/* /*
** The following macros redefine the API routines so that they are ** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure. ** redirected through the global sqlite3_api structure.
** **
** This header file is also used by the loadext.c source file ** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that ** (part of the main SQLite library - not an extension) so that
@@ -263,7 +399,7 @@ struct sqlite3_api_routines {
** the API. So the redefinition macros are only valid if the ** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined. ** SQLITE_CORE macros is undefined.
*/ */
#ifndef SQLITE_CORE #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context sqlite3_api->aggregate_context #define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED #ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count #define sqlite3_aggregate_count sqlite3_api->aggregate_count
@@ -366,7 +502,7 @@ struct sqlite3_api_routines {
#define sqlite3_rollback_hook sqlite3_api->rollback_hook #define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer #define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata #define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf #define sqlite3_snprintf sqlite3_api->xsnprintf
#define sqlite3_step sqlite3_api->step #define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
@@ -390,6 +526,7 @@ struct sqlite3_api_routines {
#define sqlite3_value_text16le sqlite3_api->value_text16le #define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type #define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf #define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function #define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 #define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
@@ -465,11 +602,126 @@ struct sqlite3_api_routines {
#define sqlite3_uri_boolean sqlite3_api->uri_boolean #define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64 #define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter #define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf #define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */ /* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype sqlite3_api->value_subtype
#define sqlite3_result_subtype sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64 sqlite3_api->status64
#define sqlite3_strlike sqlite3_api->strlike
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
/* Version 3.20.0 and later */
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
#define sqlite3_result_pointer sqlite3_api->result_pointer
#define sqlite3_value_pointer sqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
#define sqlite3_value_nochange sqlite3_api->value_nochange
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
/* Version 3.24.0 and later */
#define sqlite3_keyword_count sqlite3_api->keyword_count
#define sqlite3_keyword_name sqlite3_api->keyword_name
#define sqlite3_keyword_check sqlite3_api->keyword_check
#define sqlite3_str_new sqlite3_api->str_new
#define sqlite3_str_finish sqlite3_api->str_finish
#define sqlite3_str_appendf sqlite3_api->str_appendf
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
#define sqlite3_str_append sqlite3_api->str_append
#define sqlite3_str_appendall sqlite3_api->str_appendall
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
#define sqlite3_str_reset sqlite3_api->str_reset
#define sqlite3_str_errcode sqlite3_api->str_errcode
#define sqlite3_str_length sqlite3_api->str_length
#define sqlite3_str_value sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
/* Version 3.26.0 and later */
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
/* Version 3.28.0 and later */
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
#define sqlite3_value_frombind sqlite3_api->value_frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules sqlite3_api->drop_modules
/* Version 3.31.0 and later */
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
#define sqlite3_uri_key sqlite3_api->uri_key
#define sqlite3_filename_database sqlite3_api->filename_database
#define sqlite3_filename_journal sqlite3_api->filename_journal
#define sqlite3_filename_wal sqlite3_api->filename_wal
/* Version 3.32.0 and later */
#define sqlite3_create_filename sqlite3_api->create_filename
#define sqlite3_free_filename sqlite3_api->free_filename
#define sqlite3_database_file_object sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlite3_txn_state sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64 sqlite3_api->changes64
#define sqlite3_total_changes64 sqlite3_api->total_changes64
/* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
/* Version 3.38.0 and later */
#define sqlite3_error_offset sqlite3_api->error_offset
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
#define sqlite3_vtab_in sqlite3_api->vtab_in
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
/* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
#define sqlite3_deserialize sqlite3_api->deserialize
#define sqlite3_serialize sqlite3_api->serialize
#endif
#define sqlite3_db_name sqlite3_api->db_name
/* Version 3.40.0 and later */
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
/* Version 3.43.0 and later */
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
/* Version 3.50.0 and later */
#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
/* Version 3.51.0 and later */
#define sqlite3_set_errmsg sqlite3_api->set_errmsg
#define sqlite3_db_status64 sqlite3_api->db_status64
/* Version 3.52.0 and later */
#define sqlite3_str_truncate sqlite3_api->str_truncate
#define sqlite3_str_free sqlite3_api->str_free
#define sqlite3_carray_bind sqlite3_api->carray_bind
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#ifndef SQLITE_CORE #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable /* This case when the file really is being compiled as a loadable
** extension */ ** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
@@ -484,4 +736,4 @@ struct sqlite3_api_routines {
# define SQLITE_EXTENSION_INIT3 /*no-op*/ # define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif #endif
#endif /* _SQLITE3EXT_H_ */ #endif /* SQLITE3EXT_H */

View File

@@ -10,6 +10,7 @@ ADD_SUBDIRECTORY( EurocDataset )
ADD_SUBDIRECTORY( CidSimsDataset ) ADD_SUBDIRECTORY( CidSimsDataset )
ADD_SUBDIRECTORY( Recovery ) ADD_SUBDIRECTORY( Recovery )
ADD_SUBDIRECTORY( Reprocess ) ADD_SUBDIRECTORY( Reprocess )
ADD_SUBDIRECTORY( DatabaseUpdate )
ADD_SUBDIRECTORY( DetectMoreLoopClosures ) ADD_SUBDIRECTORY( DetectMoreLoopClosures )
ADD_SUBDIRECTORY( Export ) ADD_SUBDIRECTORY( Export )
ADD_SUBDIRECTORY( Report ) ADD_SUBDIRECTORY( Report )

View File

@@ -0,0 +1,11 @@
ADD_EXECUTABLE(dbupdate main.cpp)
TARGET_LINK_LIBRARIES(dbupdate rtabmap_core)
SET_TARGET_PROPERTIES( dbupdate
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-dbupdate)
INSTALL(TARGETS dbupdate
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)

View File

@@ -0,0 +1,87 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap/core/DBDriverSqlite3.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UFile.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace rtabmap;
void showUsage()
{
printf("\nUpdate a database with a set of changes recorded while another database was opened with\n"
"change tracking enabled (i.e. DBDriverSqlite3::setTrackChangesOutput()). This applies the\n"
"data changes only; it does NOT upgrade the database schema/version.\n"
"\n"
"Usage:\n"
" rtabmap-dbupdate \"database.db\" \"changes.update\"\n"
"\n"
"The changes must be applied to the exact database state they were recorded from; otherwise\n"
"the operation is aborted and the database is left unchanged.\n"
"\n");
exit(1);
}
int main(int argc, char * argv[])
{
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kWarning);
if(argc < 3)
{
showUsage();
}
std::string databasePath = argv[argc-2];
std::string updatePath = argv[argc-1];
if(!UFile::exists(databasePath))
{
printf("Database \"%s\" does not exist.\n", databasePath.c_str());
return 1;
}
if(!UFile::exists(updatePath))
{
printf("Update file \"%s\" does not exist.\n", updatePath.c_str());
return 1;
}
printf("Updating database \"%s\" with changes from \"%s\"...\n", databasePath.c_str(), updatePath.c_str());
std::string error;
if(DBDriverSqlite3::applyChangesFromFile(databasePath, updatePath, &error))
{
printf("Done! Database \"%s\" was updated successfully.\n", databasePath.c_str());
return 0;
}
printf("Error: %s\n", error.c_str());
return 1;
}

View File

@@ -85,6 +85,11 @@ void showUsage()
" -stop_loop Stop after the first loop closure is detected.\n" " -stop_loop Stop after the first loop closure is detected.\n"
" -a Append mode: if Mem/IncrementalMemory is true, RTAB-Map is initialized with the first input database,\n" " -a Append mode: if Mem/IncrementalMemory is true, RTAB-Map is initialized with the first input database,\n"
" then next databases are reprocessed on top of the first one.\n" " then next databases are reprocessed on top of the first one.\n"
" --track-changes \"changes.update\"\n"
" Only with append mode (-a): record the changes made on top of the first (copied) database and\n"
" write a compact delta to the given file. Apply it later on the original database with\n"
" rtabmap-dbupdate. Requires the database to be version 0.24 or newer. Note: the recorded\n"
" changes are held in memory until closing, so use this only when appending a small amount.\n"
" -cam # Camera index to stream. Ignored if a database doesn't contain multi-camera data. Can also be multiple \n" " -cam # Camera index to stream. Ignored if a database doesn't contain multi-camera data. Can also be multiple \n"
" indices split by spaces in a string like \"0 2\" to stream cameras 0 and 2 only.\n" " indices split by spaces in a string like \"0 2\" to stream cameras 0 and 2 only.\n"
" -cam_tf \"x y z roll pitch yaw\" Camera local transform override(s) without optical rotation. For multi-cameras, \n" " -cam_tf \"x y z roll pitch yaw\" Camera local transform override(s) without optical rotation. For multi-cameras, \n"
@@ -274,6 +279,7 @@ int main(int argc, char * argv[])
int stopMapId = -1; int stopMapId = -1;
bool stopOnLoopClosure = false; bool stopOnLoopClosure = false;
bool appendMode = false; bool appendMode = false;
std::string trackChangesOutput;
std::vector<unsigned int> cameraIndices; std::vector<unsigned int> cameraIndices;
std::vector<Transform> cameraLocalTransformOverrides; std::vector<Transform> cameraLocalTransformOverrides;
std::vector<float> cameraLocalTransformOffsetOverrides; std::vector<float> cameraLocalTransformOffsetOverrides;
@@ -430,6 +436,20 @@ int main(int argc, char * argv[])
appendMode = true; appendMode = true;
printf("Append mode enabled (initialize with first database then reprocess next ones)\n"); printf("Append mode enabled (initialize with first database then reprocess next ones)\n");
} }
else if (strcmp(argv[i], "--track-changes") == 0)
{
++i;
if(i < argc - 2)
{
trackChangesOutput = argv[i];
printf("Change tracking enabled, delta will be written to \"%s\" (apply later with rtabmap-dbupdate).\n", trackChangesOutput.c_str());
}
else
{
printf("Missing value for --track-changes option!\n");
showUsage();
}
}
else if (strcmp(argv[i], "-cam") == 0 || strcmp(argv[i], "--cam") == 0) else if (strcmp(argv[i], "-cam") == 0 || strcmp(argv[i], "--cam") == 0)
{ {
++i; ++i;
@@ -886,6 +906,22 @@ int main(int argc, char * argv[])
Rtabmap rtabmap; Rtabmap rtabmap;
rtabmap.init(parameters, outputDatabasePath); rtabmap.init(parameters, outputDatabasePath);
// Start change tracking now, after init loaded the copied baseline database, so the
// delta captures only what reprocessing appends. Only meaningful in append mode, where
// the output starts as a copy of the first input database.
if(!trackChangesOutput.empty())
{
if(appendMode)
{
rtabmap.trackDatabaseChanges(trackChangesOutput);
}
else
{
printf("Warning: --track-changes requires append mode (-a); it is ignored because "
"append mode is not enabled.\n");
}
}
if(!incrementalMemory && locNull) if(!incrementalMemory && locNull)
{ {
rtabmap.setInitialPose(Transform()); rtabmap.setInitialPose(Transform());