Added DBDriver tests

This commit is contained in:
matlabbe
2026-05-16 18:51:17 -07:00
parent 551c9e8a0f
commit f6ba3e6d7d
3 changed files with 1689 additions and 326 deletions
+460 -326
View File
@@ -1,326 +1,460 @@
/* /*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the * Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef DBDRIVER_H_ #ifndef DBDRIVER_H_
#define DBDRIVER_H_ #define DBDRIVER_H_
#include "rtabmap/core/rtabmap_core_export.h" // DLL export/import defines #include "rtabmap/core/rtabmap_core_export.h" // DLL export/import defines
#include <string> #include <string>
#include <list> #include <list>
#include <map> #include <map>
#include <set> #include <set>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "rtabmap/utilite/UMutex.h" #include "rtabmap/utilite/UMutex.h"
#include "rtabmap/utilite/UThreadNode.h" #include "rtabmap/utilite/UThreadNode.h"
#include "rtabmap/core/Parameters.h" #include "rtabmap/core/Parameters.h"
#include "rtabmap/core/SensorData.h" #include "rtabmap/core/SensorData.h"
#include <rtabmap/core/Statistics.h> #include <rtabmap/core/Statistics.h>
#include <rtabmap/core/Transform.h> #include <rtabmap/core/Transform.h>
#include <rtabmap/core/Link.h> #include <rtabmap/core/Link.h>
namespace rtabmap { namespace rtabmap {
class Signature; class Signature;
class VWDictionary; class VWDictionary;
class VisualWord; class VisualWord;
// Todo This class needs a refactoring, the _dbSafeAccessMutex problem when the trash is emptying (transaction) /**
// "Of course, it has always been the case and probably always will be * @class DBDriver
//that you cannot use the same sqlite3 connection in two or more * @brief Abstract database driver for RTAB-Map maps (signatures, links, words, statistics).
//threads at the same time. You can use different sqlite3 connections *
//at the same time in different threads, or you can move the same * DBDriver is the persistence layer used by @ref Memory, @ref DBReader and tools that
//sqlite3 connection across threads (subject to the constraints above) * read or write \c .db files. The default implementation is @ref DBDriverSqlite3, created
//but never, never try to use the same connection simultaneously in * by @ref create().
//two or more threads." *
// * The driver extends @ref UThreadNode: pending @ref Signature and @ref VisualWord objects
class RTABMAP_CORE_EXPORT DBDriver : public UThreadNode * are queued with @ref asyncSave() and flushed to the database by @ref emptyTrashes()
{ * (also called from the background thread on @ref closeConnection()).
public: *
static DBDriver * create(const ParametersMap & parameters = ParametersMap()); * Public methods are thread-safe where noted (mutex-protected wrappers). Subclasses
* implement SQL-specific logic in protected \c *Query() virtual methods.
public: *
virtual ~DBDriver(); * @see DBDriverSqlite3
* @see Memory
virtual void parseParameters(const ParametersMap & parameters); */
virtual bool isInMemory() const {return _url.empty();} class RTABMAP_CORE_EXPORT DBDriver : public UThreadNode
const std::string & getUrl() const {return _url;} {
const std::string & getTargetVersion() const {return _targetVersion;} public:
/**
void beginTransaction() const; * @brief Factory: returns a SQLite database driver (@ref DBDriverSqlite3).
void commit() const; * @param parameters Optional driver parameters (e.g. @ref Parameters::kDbTargetVersion()).
* @return New driver instance; caller owns the pointer.
void asyncSave(Signature * s); //ownership transferred */
void asyncSave(VisualWord * vw); //ownership transferred static DBDriver * create(const ParametersMap & parameters = ParametersMap());
void emptyTrashes(bool async = false);
double getEmptyTrashesTime() const {return _emptyTrashesTime;} public:
void setTimestampUpdateEnabled(bool enabled) {_timestampUpdate = enabled;} // used on Update Signature and Word queries virtual ~DBDriver();
// Warning: the following functions don't look in the trash, direct database modifications /** @brief Parse driver parameters from the map (e.g. target schema version). */
void generateGraph( virtual void parseParameters(const ParametersMap & parameters);
const std::string & fileName, /**
const std::set<int> & ids = std::set<int>(), * @brief True when no database file URL was set at open time.
const std::map<int, Signature *> & otherSignatures = std::map<int, Signature *>()); * @note @ref DBDriverSqlite3 overrides this when @ref Parameters::kDbSqlite3InMemory() is enabled.
void addLink(const Link & link); */
void removeLink(int from, int to); virtual bool isInMemory() const {return _url.empty();}
void updateLink(const Link & link); /** @return Database file path last passed to @ref openConnection(). */
void updateOccupancyGrid( const std::string & getUrl() const {return _url;}
int nodeId, /** @return Target schema version for new databases (from parameters). */
const cv::Mat & ground, const std::string & getTargetVersion() const {return _targetVersion;}
const cv::Mat & obstacles,
const cv::Mat & empty, /** @brief Queue a signature for deferred save; ownership is transferred. */
float cellSize, void asyncSave(Signature * s);
const cv::Point3f & viewpoint); /** @brief Queue a visual word for deferred save; ownership is transferred. */
void updateCalibration( void asyncSave(VisualWord * vw);
int nodeId, /**
const std::vector<CameraModel> & models, * @brief Flush queued signatures and visual words to the database.
const std::vector<StereoCameraModel> & stereoModels); * @param async If true, signal the background thread instead of flushing synchronously.
void updateDepthImage(int nodeId, const cv::Mat & image, const std::string & format); */
void updateLaserScan(int nodeId, const LaserScan & scan); void emptyTrashes(bool async = false);
double getEmptyTrashesTime() const {return _emptyTrashesTime;}
public: void setTimestampUpdateEnabled(bool enabled) {_timestampUpdate = enabled;} // used on Update Signature and Word queries
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap & parameters) const;
void addStatistics(const Statistics & statistics, bool saveWmState) const; /**
void savePreviewImage(const cv::Mat & image) const; * @brief Export the pose graph to a Graphviz DOT file for visualization.
cv::Mat loadPreviewImage() const; *
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const; * Reads nodes and links from the database (and optionally from @p otherSignatures
std::map<int, Transform> loadOptimizedPoses(Transform * lastlocalizationPose = 0) const; * not yet persisted) and writes @p fileName. Does not modify the database.
void save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const; * If @p ids is empty, all node ids are included.
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const; */
void saveOptimizedMesh( void generateGraph(
const cv::Mat & cloud, const std::string & fileName,
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons = std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > >(), // Textures -> polygons -> vertices const std::set<int> & ids = std::set<int>(),
#if PCL_VERSION_COMPARE(>=, 1, 8, 0) const std::map<int, Signature *> & otherSignatures = std::map<int, Signature *>());
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
#else /**
const std::vector<std::vector<Eigen::Vector2f> > & texCoords = std::vector<std::vector<Eigen::Vector2f> >(), // Textures -> uv coords for each vertex of the polygons * @name Direct database updates
#endif * @brief Write node or link data immediately (not via the async trash).
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size); * @{
cv::Mat loadOptimizedMesh( */
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons = 0, /** @brief Insert or replace a link in the database. */
#if PCL_VERSION_COMPARE(>=, 1, 8, 0) void addLink(const Link & link);
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0, /** @brief Remove a link between two nodes. */
#else void removeLink(int from, int to);
std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0, /** @brief Update an existing link in the database. */
#endif void updateLink(const Link & link);
cv::Mat * textures = 0) const; /**
void saveFlannIndex(const std::vector<unsigned char> & indexData) const; * @brief Update occupancy grid cells for a node.
* @param ground Ground cells (raw @c CV_32FC2/@c CV_32FC3, or compressed @c CV_8UC1 1×N).
public: * @param obstacles Obstacle cells (same formats as @p ground).
// Mutex-protected methods of abstract versions below * @param empty Empty cells (same formats as @p ground; ignored on DB schema &lt; 0.16.0).
* Raw mats are compressed internally via @ref SensorData::setOccupancyGrid() before writing.
bool openConnection(const std::string & url, bool overwritten = false, bool readOnly = false); */
void closeConnection(bool save = true, const std::string & outputUrl = ""); void updateOccupancyGrid(
bool isConnected() const; int nodeId,
unsigned long getMemoryUsed() const; // In bytes const cv::Mat & ground,
std::string getDatabaseVersion() const; const cv::Mat & obstacles,
long getNodesMemoryUsed() const; const cv::Mat & empty,
long getLinksMemoryUsed() const; float cellSize,
long getImagesMemoryUsed() const; const cv::Point3f & viewpoint);
long getDepthImagesMemoryUsed() const; /** @brief Update camera calibration stored for a node. */
long getCalibrationsMemoryUsed() const; void updateCalibration(
long getGridsMemoryUsed() const; int nodeId,
long getLaserScansMemoryUsed() const; const std::vector<CameraModel> & models,
long getUserDataMemoryUsed() const; const std::vector<StereoCameraModel> & stereoModels);
long getWordsMemoryUsed() const; /**
long getFeaturesMemoryUsed() const; * @brief Update the depth image stored for a node.
long getStatisticsMemoryUsed() const; * @param image Raw depth image, or pre-compressed blob (@c CV_8UC1, single row).
int getLastNodesSize() const; // working memory * @param format Compression format when @p image is raw (e.g. @c ".png"); ignored if already compressed.
int getLastDictionarySize() const; // working memory * Uncompressed images are compressed with @ref Compression::compressImage2() before writing.
int getTotalNodesSize() const; */
int getTotalDictionarySize() const; void updateDepthImage(int nodeId, const cv::Mat & image, const std::string & format);
ParametersMap getLastParameters() const; /**
std::map<std::string, float> getStatistics(int nodeId, double & stamp, std::vector<int> * wmState=0) const; * @brief Update the laser scan stored for a node.
std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatistics() const; * @param scan Uncompressed scan, or already compressed (@ref LaserScan::isCompressed()).
std::map<int, std::vector<int> > getAllStatisticsWmStates() const; * Uncompressed data is compressed with @ref Compression::compressData2() before writing.
*/
void executeNoResult(const std::string & sql) const; void updateLaserScan(int nodeId, const LaserScan & scan);
/** @} */
// Load objects
void load(VWDictionary & dictionary, bool lastStateOnly = true) const; public:
void loadLastNodes(std::list<Signature *> & signatures, bool loadWordIdsOnly = false) const; // returned signatures must be freed after usage /**
Signature * loadSignature(int id, bool * loadedFromTrash = 0); // returned signature must be freed after usage, call loadSignatures() instead if more than one signature should be loaded * @name Session exports and map artifacts
void loadSignatures(const std::list<int> & ids, std::list<Signature *> & signatures, std::set<int> * loadedFromTrash = 0, bool loadWordIdsOnly = false); // returned signatures must be freed after usage * @brief Statistics, preview image, optimized poses, 2D map, mesh and FLANN index.
void loadWords(const std::set<int> & wordIds, std::list<VisualWord *> & vws); // returned words must be freed after usage * @{*/
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap & parameters) const;
// Specific queries... /**
void loadNodeData(Signature & signature, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; * @brief Append a @ref Statistics record for a processed node.
void loadNodeData(std::list<Signature *> & signatures, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; * @param statistics Metrics for @ref Statistics::refImageId() (insert skipped if id &le; 0 or data empty).
void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; * @param saveWmState If true and schema &ge; 0.16.2, also store compressed working-memory state.
bool getCalibration(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const; */
bool getLaserScanInfo(int signatureId, LaserScan & info) const; void addStatistics(const Statistics & statistics, bool saveWmState) const;
bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const; /**
void getLocalFeatures(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const; * @brief Save the map preview thumbnail in the Admin table.
void loadLinks(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const; * @param image Raw image or JPEG-compressed blob (@c CV_8UC1, single row); empty clears it.
void getWeight(int signatureId, int & weight) const; * @note Requires database schema &ge; 0.12.0.
void getLastNodeIds(std::set<int> & ids) const; */
void getAllNodeIds(std::set<int> & ids, bool ignoreChildren = false, bool ignoreBadSignatures = false, bool ignoreIntermediateNodes = false) const; void savePreviewImage(const cv::Mat & image) const;
void getAllOdomPoses(std::map<int, Transform> & poses, bool ignoreChildren = false, bool ignoreIntermediateNodes = false) const; /** @brief Load and uncompress the map preview thumbnail from the Admin table. */
void getAllLinks(std::multimap<int, Link> & links, bool ignoreNullLinks = true, bool withLandmarks = false) const; cv::Mat loadPreviewImage() const;
void getLastNodeId(int & id) const; /** @brief Persist graph-optimized poses and last localization pose. */
void getLastMapId(int & mapId) const; void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
void getLastWordId(int & id) const; /** @brief Load optimized poses; optional last localization pose output. */
void getInvertedIndexNi(int signatureId, int & ni) const; std::map<int, Transform> loadOptimizedPoses(Transform * lastlocalizationPose = 0) const;
void getNodesObservingLandmark(int landmarkId, std::map<int, Link> & nodes) const; /** @brief Save the assembled 2D occupancy grid and its origin metadata. */
void getNodeIdByLabel(const std::string & label, int & id) const; void save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
void getAllLabels(std::map<int, std::string> & labels) const; /** @brief Load the 2D map and fill origin/cell size outputs. */
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
protected: /**
DBDriver(const ParametersMap & parameters = ParametersMap()); * @brief Persist the global optimized 3D mesh to the database.
* @param cloud Point cloud (@c CV_32FC1 or @c CV_32FC3).
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false) = 0; * @param polygons Optional per-texture polygon index lists (texture → polygon → vertex indices).
virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "") = 0; * @param texCoords Optional UV coordinates per texture (one per polygon vertex).
virtual bool isConnectedQuery() const = 0; * @param textures Optional concatenated square texture images (same size per texture).
virtual unsigned long getMemoryUsedQuery() const = 0; // In bytes */
virtual bool getDatabaseVersionQuery(std::string & version) const = 0; void saveOptimizedMesh(
virtual long getNodesMemoryUsedQuery() const = 0; const cv::Mat & cloud,
virtual long getLinksMemoryUsedQuery() const = 0; const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons = std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > >(), // Textures -> polygons -> vertices
virtual long getImagesMemoryUsedQuery() const = 0; #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
virtual long getDepthImagesMemoryUsedQuery() const = 0; const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
virtual long getCalibrationsMemoryUsedQuery() const = 0; #else
virtual long getGridsMemoryUsedQuery() const = 0; const std::vector<std::vector<Eigen::Vector2f> > & texCoords = std::vector<std::vector<Eigen::Vector2f> >(), // Textures -> uv coords for each vertex of the polygons
virtual long getLaserScansMemoryUsedQuery() const = 0; #endif
virtual long getUserDataMemoryUsedQuery() const = 0; const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size);
virtual long getWordsMemoryUsedQuery() const = 0; cv::Mat loadOptimizedMesh(
virtual long getFeaturesMemoryUsedQuery() const = 0; std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons = 0,
virtual long getStatisticsMemoryUsedQuery() const = 0; #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
virtual int getLastNodesSizeQuery() const = 0; std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
virtual int getLastDictionarySizeQuery() const = 0; #else
virtual int getTotalNodesSizeQuery() const = 0; std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0,
virtual int getTotalDictionarySizeQuery() const = 0; #endif
virtual ParametersMap getLastParametersQuery() const = 0; cv::Mat * textures = 0) const;
virtual std::map<std::string, float> getStatisticsQuery(int nodeId, double & stamp, std::vector<int> * wmState) const = 0; /**
virtual std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatisticsQuery() const = 0; * @brief Persist the visual word dictionary FLANN index (serialized blob).
virtual std::map<int, std::vector<int> > getAllStatisticsWmStatesQuery() const = 0; * @param indexData Serialized index from @ref VWDictionary::serializeIndex(); pass empty to clear.
* @note Requires database schema &ge; 0.23.0. Used when @ref Parameters::kKpFlannIndexSaved() is enabled.
virtual void executeNoResultQuery(const std::string & sql) const = 0; */
void saveFlannIndex(const std::vector<unsigned char> & indexData) const;
virtual void getWeightQuery(int signatureId, int & weight) const = 0; /** @} */
virtual void saveQuery(const std::list<Signature *> & signatures) = 0; public:
virtual void saveQuery(const std::list<VisualWord *> & words) const = 0; /**
virtual void updateQuery(const std::list<Signature *> & signatures, bool updateTimestamp) const = 0; * @name Connection and database introspection
virtual void updateQuery(const std::list<VisualWord *> & words, bool updateTimestamp) const = 0; * @brief Mutex-protected wrappers around protected \c *Query() methods.
* @{*/
virtual void addLinkQuery(const Link & link) const = 0; /** @brief Open or create the database at @p url (empty @p url uses an in-memory database). */
virtual void updateLinkQuery(const Link & link) const = 0; bool openConnection(const std::string & url, bool overwritten = false, bool readOnly = false);
/** @brief Close the connection; optionally flush trashes and save in-memory DB to @p outputUrl. */
virtual void updateOccupancyGridQuery( void closeConnection(bool save = true, const std::string & outputUrl = "");
int nodeId, /** @return True if a database connection is active. */
const cv::Mat & ground, bool isConnected() const;
const cv::Mat & obstacles, unsigned long getMemoryUsed() const; // In bytes
const cv::Mat & empty, /** @return Schema version string stored in the database (e.g. "0.21.0"). */
float cellSize, std::string getDatabaseVersion() const;
const cv::Point3f & viewpoint) const = 0; long getNodesMemoryUsed() const;
long getLinksMemoryUsed() const;
virtual void updateCalibrationQuery( long getImagesMemoryUsed() const;
int nodeId, long getDepthImagesMemoryUsed() const;
const std::vector<CameraModel> & models, long getCalibrationsMemoryUsed() const;
const std::vector<StereoCameraModel> & stereoModels) const = 0; long getGridsMemoryUsed() const;
long getLaserScansMemoryUsed() const;
virtual void updateDepthImageQuery( long getUserDataMemoryUsed() const;
int nodeId, long getWordsMemoryUsed() const;
const cv::Mat & image, long getFeaturesMemoryUsed() const;
const std::string & format) const = 0; long getStatisticsMemoryUsed() const;
int getLastNodesSize() const; // working memory
virtual void updateLaserScanQuery( int getLastDictionarySize() const; // working memory
int nodeId, int getTotalNodesSize() const;
const LaserScan & scan) const = 0; int getTotalDictionarySize() const;
ParametersMap getLastParameters() const;
virtual void addStatisticsQuery(const Statistics & statistics, bool saveWmState) const = 0; std::map<std::string, float> getStatistics(int nodeId, double & stamp, std::vector<int> * wmState=0) const;
virtual void savePreviewImageQuery(const cv::Mat & image) const = 0; std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatistics() const;
virtual cv::Mat loadPreviewImageQuery() const = 0; std::map<int, std::vector<int> > getAllStatisticsWmStates() const;
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const = 0;
virtual std::map<int, Transform> loadOptimizedPosesQuery(Transform * lastlocalizationPose = 0) const = 0; /** @} */
virtual void save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const = 0;
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const = 0; /**
virtual void saveOptimizedMeshQuery( * @brief Run a SQL statement that does not return result rows.
const cv::Mat & cloud, *
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons, * Executes @p sql on the open database (e.g. @c INSERT, @c UPDATE, @c DELETE,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0) * @c CREATE, @c PRAGMA). Thread-safe wrapper around @ref executeNoResultQuery().
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords, *
#else * For reads, use the dedicated @ref loadSignature(), @ref loadLinks() and related
const std::vector<std::vector<Eigen::Vector2f> > & texCoords, * query methods instead of raw SQL.
#endif *
const cv::Mat & textures) const = 0; * @param sql Complete SQL statement (SQLite syntax for @ref DBDriverSqlite3).
virtual cv::Mat loadOptimizedMeshQuery( * @note The connection must be open (@ref isConnected()). On failure the driver
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons, * aborts with an assertion (SQLite backend).
#if PCL_VERSION_COMPARE(>=, 1, 8, 0) * @warning @p sql is passed verbatim; sanitize any user-controlled values before calling.
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords, */
#else void executeNoResult(const std::string & sql) const;
std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif /**
cv::Mat * textures) const = 0; * @name Load and query
virtual void saveFlannIndexQuery(const std::vector<unsigned char> & indexData) const = 0; * @brief Load signatures, words, links and node metadata from the database.
* @{*/
// Load objects
virtual void loadQuery(VWDictionary & dictionary, bool lastStateOnly = true) const = 0; // Load objects
virtual void loadLastNodesQuery(std::list<Signature *> & signatures, bool loadWordIdsOnly) const = 0; void load(VWDictionary & dictionary, bool lastStateOnly = true) const;
virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures, bool loadWordIdsOnly) const = 0; void loadLastNodes(std::list<Signature *> & signatures, bool loadWordIdsOnly = false) const; // returned signatures must be freed after usage
virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const = 0; /** @brief Load one signature by id; caller must delete the returned pointer. */
virtual void loadLinksQuery(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const = 0; Signature * loadSignature(int id, bool * loadedFromTrash = 0); // returned signature must be freed after usage, call loadSignatures() instead if more than one signature should be loaded
void loadSignatures(const std::list<int> & ids, std::list<Signature *> & signatures, std::set<int> * loadedFromTrash = 0, bool loadWordIdsOnly = false); // returned signatures must be freed after usage
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const = 0; void loadWords(const std::set<int> & wordIds, std::list<VisualWord *> & vws); // returned words must be freed after usage
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const = 0;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const = 0; // Specific queries...
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const = 0; void loadNodeData(Signature & signature, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
virtual void getLocalFeaturesQuery(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const = 0; void loadNodeData(std::list<Signature *> & signatures, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
virtual void getLastNodeIdsQuery(std::set<int> & ids) const = 0; void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures, bool ignoreIntermediateNodes) const = 0; bool getCalibration(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const;
virtual void getAllOdomPosesQuery(std::map<int, Transform> & poses, bool ignoreChildren, bool ignoreIntermediateNodes) const = 0; bool getLaserScanInfo(int signatureId, LaserScan & info) const;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks, bool withLandmarks) const = 0; bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const;
virtual void getLastIdQuery(const std::string & tableName, int & id, const std::string & fieldName="id") const = 0; void getLocalFeatures(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const;
virtual void getInvertedIndexNiQuery(int signatureId, int & ni) const = 0; /** @brief Load outgoing links from @p signatureId, optionally filtered by @p type. */
virtual void getNodesObservingLandmarkQuery(int landmarkId, std::map<int, Link> & nodes) const = 0; void loadLinks(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const;
virtual void getNodeIdByLabelQuery(const std::string & label, int & id) const = 0; void getWeight(int signatureId, int & weight) const;
virtual void getAllLabelsQuery(std::map<int, std::string> & labels) const = 0; void getLastNodeIds(std::set<int> & ids) const;
void getAllNodeIds(std::set<int> & ids, bool ignoreChildren = false, bool ignoreBadSignatures = false, bool ignoreIntermediateNodes = false) const;
private: void getAllOdomPoses(std::map<int, Transform> & poses, bool ignoreChildren = false, bool ignoreIntermediateNodes = false) const;
//non-abstract methods void getAllLinks(std::multimap<int, Link> & links, bool ignoreNullLinks = true, bool withLandmarks = false) const;
void saveOrUpdate(const std::vector<Signature *> & signatures); void getLastNodeId(int & id) const;
void saveOrUpdate(const std::vector<VisualWord *> & words) const; void getLastMapId(int & mapId) const;
void getLastWordId(int & id) const;
//thread stuff void getInvertedIndexNi(int signatureId, int & ni) const;
virtual void mainLoop(); void getNodesObservingLandmark(int landmarkId, std::map<int, Link> & nodes) const;
void getNodeIdByLabel(const std::string & label, int & id) const;
private: void getAllLabels(std::map<int, std::string> & labels) const;
UMutex _transactionMutex; /** @} */
std::map<int, Signature *> _trashSignatures;//<id, Signature*>
std::map<int, VisualWord *> _trashVisualWords; //<id, VisualWord*> protected:
UMutex _trashesMutex; /**
UMutex _dbSafeAccessMutex; * @brief Protected constructor for subclasses.
USemaphore _addSem; */
double _emptyTrashesTime; DBDriver(const ParametersMap & parameters = ParametersMap());
std::string _url;
std::string _targetVersion; /**
bool _timestampUpdate; * @name Backend implementation (subclass responsibility)
}; * @brief Pure virtual SQL/backend hooks invoked by public wrappers above.
* @{*/
} virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false) = 0;
virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "") = 0;
#endif /* DBDRIVER_H_ */ virtual bool isConnectedQuery() const = 0;
virtual unsigned long getMemoryUsedQuery() const = 0; // In bytes
virtual bool getDatabaseVersionQuery(std::string & version) const = 0;
virtual long getNodesMemoryUsedQuery() const = 0;
virtual long getLinksMemoryUsedQuery() const = 0;
virtual long getImagesMemoryUsedQuery() const = 0;
virtual long getDepthImagesMemoryUsedQuery() const = 0;
virtual long getCalibrationsMemoryUsedQuery() const = 0;
virtual long getGridsMemoryUsedQuery() const = 0;
virtual long getLaserScansMemoryUsedQuery() const = 0;
virtual long getUserDataMemoryUsedQuery() const = 0;
virtual long getWordsMemoryUsedQuery() const = 0;
virtual long getFeaturesMemoryUsedQuery() const = 0;
virtual long getStatisticsMemoryUsedQuery() const = 0;
virtual int getLastNodesSizeQuery() const = 0;
virtual int getLastDictionarySizeQuery() const = 0;
virtual int getTotalNodesSizeQuery() const = 0;
virtual int getTotalDictionarySizeQuery() const = 0;
virtual ParametersMap getLastParametersQuery() const = 0;
virtual std::map<std::string, float> getStatisticsQuery(int nodeId, double & stamp, std::vector<int> * wmState) const = 0;
virtual std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatisticsQuery() const = 0;
virtual std::map<int, std::vector<int> > getAllStatisticsWmStatesQuery() const = 0;
virtual void executeNoResultQuery(const std::string & sql) const = 0;
virtual void getWeightQuery(int signatureId, int & weight) const = 0;
virtual void saveQuery(const std::list<Signature *> & signatures) = 0;
virtual void saveQuery(const std::list<VisualWord *> & words) const = 0;
virtual void updateQuery(const std::list<Signature *> & signatures, bool updateTimestamp) const = 0;
virtual void updateQuery(const std::list<VisualWord *> & words, bool updateTimestamp) const = 0;
virtual void addLinkQuery(const Link & link) const = 0;
virtual void updateLinkQuery(const Link & link) const = 0;
virtual void updateOccupancyGridQuery(
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint) const = 0;
virtual void updateCalibrationQuery(
int nodeId,
const std::vector<CameraModel> & models,
const std::vector<StereoCameraModel> & stereoModels) const = 0;
virtual void updateDepthImageQuery(
int nodeId,
const cv::Mat & image,
const std::string & format) const = 0;
virtual void updateLaserScanQuery(
int nodeId,
const LaserScan & scan) const = 0;
virtual void addStatisticsQuery(const Statistics & statistics, bool saveWmState) const = 0;
virtual void savePreviewImageQuery(const cv::Mat & image) const = 0;
virtual cv::Mat loadPreviewImageQuery() const = 0;
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const = 0;
virtual std::map<int, Transform> loadOptimizedPosesQuery(Transform * lastlocalizationPose = 0) const = 0;
virtual void save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const = 0;
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const = 0;
virtual void saveOptimizedMeshQuery(
const cv::Mat & cloud,
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
#endif
const cv::Mat & textures) const = 0;
virtual cv::Mat loadOptimizedMeshQuery(
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const = 0;
virtual void saveFlannIndexQuery(const std::vector<unsigned char> & indexData) const = 0;
// Load objects
virtual void loadQuery(VWDictionary & dictionary, bool lastStateOnly = true) const = 0;
virtual void loadLastNodesQuery(std::list<Signature *> & signatures, bool loadWordIdsOnly) const = 0;
virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures, bool loadWordIdsOnly) const = 0;
virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const = 0;
virtual void loadLinksQuery(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const = 0;
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const = 0;
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const = 0;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const = 0;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const = 0;
virtual void getLocalFeaturesQuery(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const = 0;
virtual void getLastNodeIdsQuery(std::set<int> & ids) const = 0;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures, bool ignoreIntermediateNodes) const = 0;
virtual void getAllOdomPosesQuery(std::map<int, Transform> & poses, bool ignoreChildren, bool ignoreIntermediateNodes) const = 0;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks, bool withLandmarks) const = 0;
virtual void getLastIdQuery(const std::string & tableName, int & id, const std::string & fieldName="id") const = 0;
virtual void getInvertedIndexNiQuery(int signatureId, int & ni) const = 0;
virtual void getNodesObservingLandmarkQuery(int landmarkId, std::map<int, Link> & nodes) const = 0;
virtual void getNodeIdByLabelQuery(const std::string & label, int & id) const = 0;
virtual void getAllLabelsQuery(std::map<int, std::string> & labels) const = 0;
/** @} */
private:
/** @brief Begin a database transaction (nested calls are serialized). */
void beginTransaction() const;
/** @brief Commit the current transaction. */
void commit() const;
//non-abstract methods
void saveOrUpdate(const std::vector<Signature *> & signatures);
void saveOrUpdate(const std::vector<VisualWord *> & words) const;
//thread stuff
virtual void mainLoop();
private:
UMutex _transactionMutex;
std::map<int, Signature *> _trashSignatures;//<id, Signature*>
std::map<int, VisualWord *> _trashVisualWords; //<id, VisualWord*>
UMutex _trashesMutex;
UMutex _dbSafeAccessMutex;
USemaphore _addSem;
double _emptyTrashesTime;
std::string _url;
std::string _targetVersion;
bool _timestampUpdate;
};
}
#endif /* DBDRIVER_H_ */
+5
View File
@@ -121,6 +121,11 @@ add_executable(test_odometry test_odometry.cpp)
target_link_libraries(test_odometry gtest_main rtabmap_core) target_link_libraries(test_odometry gtest_main rtabmap_core)
gtest_discover_tests(test_odometry) gtest_discover_tests(test_odometry)
#DBDriver.h
add_executable(test_dbdriver test_dbdriver.cpp)
target_link_libraries(test_dbdriver gtest_main rtabmap_core)
gtest_discover_tests(test_dbdriver)
#Signature.h #Signature.h
add_executable(test_signature test_signature.cpp) add_executable(test_signature test_signature.cpp)
target_link_libraries(test_signature gtest_main rtabmap_core) target_link_libraries(test_signature gtest_main rtabmap_core)
File diff suppressed because it is too large Load Diff