mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-03 16:27:46 +08:00
DatabaseViewer: using DBDriver directly instead of Memory to save RAM on large databases
This commit is contained in:
@@ -60,6 +60,9 @@ class VisualWord;
|
||||
//
|
||||
class RTABMAP_EXP DBDriver : public UThreadNode
|
||||
{
|
||||
public:
|
||||
static DBDriver * create(const ParametersMap & parameters = ParametersMap());
|
||||
|
||||
public:
|
||||
virtual ~DBDriver();
|
||||
|
||||
@@ -75,6 +78,15 @@ public:
|
||||
double getEmptyTrashesTime() const {return _emptyTrashesTime;}
|
||||
void setTimestampUpdateEnabled(bool enabled) {_timestampUpdate = enabled;} // used on Update Signature and Word queries
|
||||
|
||||
// Warning: the following functions don't look in the trash, direct database modifications
|
||||
void generateGraph(
|
||||
const std::string & fileName,
|
||||
const std::set<int> & ids = std::set<int>(),
|
||||
const std::map<int, Signature *> & otherSignatures = std::map<int, Signature *>());
|
||||
void addLink(const Link & link);
|
||||
void removeLink(int from, int to);
|
||||
void updateLink(const Link & link);
|
||||
|
||||
public:
|
||||
void addStatisticsAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize) const;
|
||||
|
||||
@@ -128,6 +140,8 @@ private:
|
||||
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;
|
||||
|
||||
// Load objects
|
||||
virtual void loadQuery(VWDictionary * dictionary) const = 0;
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace rtabmap {
|
||||
|
||||
class Signature;
|
||||
class DBDriver;
|
||||
class GraphNode;
|
||||
class VWDictionary;
|
||||
class VisualWord;
|
||||
class Feature2D;
|
||||
@@ -164,10 +163,7 @@ public:
|
||||
virtual void dumpSignatures(const char * fileNameSign, bool words3D) const;
|
||||
void dumpDictionary(const char * fileNameRef, const char * fileNameDesc) const;
|
||||
|
||||
void generateGraph(const std::string & fileName, std::set<int> ids = std::set<int>());
|
||||
void createGraph(GraphNode * parent,
|
||||
unsigned int maxDepth,
|
||||
const std::set<int> & endIds = std::set<int>());
|
||||
void generateGraph(const std::string & fileName, const std::set<int> & ids = std::set<int>());
|
||||
|
||||
//keypoint stuff
|
||||
const VWDictionary * getVWDictionary() const;
|
||||
|
||||
@@ -34,9 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rtabmap/utilite/ULogger.h"
|
||||
#include "rtabmap/utilite/UTimer.h"
|
||||
#include "rtabmap/utilite/UStl.h"
|
||||
#include "DBDriverSqlite3.h"
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
DBDriver * DBDriver::create(const ParametersMap & parameters)
|
||||
{
|
||||
// well, we only have Sqlite3 database type for now :P
|
||||
return new DBDriverSqlite3(parameters);
|
||||
}
|
||||
|
||||
DBDriver::DBDriver(const ParametersMap & parameters) :
|
||||
_emptyTrashesTime(0),
|
||||
_timestampUpdate(true)
|
||||
@@ -291,6 +298,23 @@ void DBDriver::saveOrUpdate(const std::vector<VisualWord *> & words) const
|
||||
}
|
||||
}
|
||||
|
||||
void DBDriver::addLink(const Link & link)
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
this->addLinkQuery(link);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
void DBDriver::removeLink(int from, int to)
|
||||
{
|
||||
this->executeNoResult(uFormat("DELETE FROM Link WHERE from_id=%d and to_id=%d", from, to).c_str());
|
||||
}
|
||||
void DBDriver::updateLink(const Link & link)
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
this->updateLinkQuery(link);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
|
||||
void DBDriver::load(VWDictionary * dictionary) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
@@ -715,4 +739,155 @@ void DBDriver::addStatisticsAfterRun(int stMemSize, int lastSignAdded, int proce
|
||||
}
|
||||
}
|
||||
|
||||
void DBDriver::generateGraph(
|
||||
const std::string & fileName,
|
||||
const std::set<int> & idsInput,
|
||||
const std::map<int, Signature *> & otherSignatures)
|
||||
{
|
||||
if(this->isConnected())
|
||||
{
|
||||
if(!fileName.empty())
|
||||
{
|
||||
FILE* fout = 0;
|
||||
#ifdef _MSC_VER
|
||||
fopen_s(&fout, fileName.c_str(), "w");
|
||||
#else
|
||||
fout = fopen(fileName.c_str(), "w");
|
||||
#endif
|
||||
|
||||
if (!fout)
|
||||
{
|
||||
UERROR("Cannot open file %s!", fileName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<int> ids;
|
||||
if(idsInput.size() == 0)
|
||||
{
|
||||
this->getAllNodeIds(ids);
|
||||
UDEBUG("ids.size()=%d", ids.size());
|
||||
for(std::map<int, Signature*>::const_iterator iter=otherSignatures.begin(); iter!=otherSignatures.end(); ++iter)
|
||||
{
|
||||
ids.insert(iter->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ids = idsInput;
|
||||
}
|
||||
|
||||
const char * colorG = "green";
|
||||
const char * colorP = "pink";
|
||||
; UINFO("Generating map with %d locations", ids.size());
|
||||
fprintf(fout, "digraph G {\n");
|
||||
for(std::set<int>::iterator i=ids.begin(); i!=ids.end(); ++i)
|
||||
{
|
||||
if(otherSignatures.find(*i) == otherSignatures.end())
|
||||
{
|
||||
int id = *i;
|
||||
std::map<int, Link> links;
|
||||
this->loadLinks(id, links);
|
||||
int weight = 0;
|
||||
this->getWeight(id, weight);
|
||||
for(std::map<int, Link>::iterator iter = links.begin(); iter!=links.end(); ++iter)
|
||||
{
|
||||
int weightNeighbor = 0;
|
||||
if(otherSignatures.find(iter->first) == otherSignatures.end())
|
||||
{
|
||||
this->getWeight(iter->first, weightNeighbor);
|
||||
}
|
||||
else
|
||||
{
|
||||
weightNeighbor = otherSignatures.find(iter->first)->second->getWeight();
|
||||
}
|
||||
//UDEBUG("Add neighbor link from %d to %d", id, iter->first);
|
||||
if(iter->second.type() == Link::kNeighbor)
|
||||
{
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\"\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor);
|
||||
}
|
||||
else if(iter->first > id)
|
||||
{
|
||||
//loop
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorG);
|
||||
}
|
||||
else
|
||||
{
|
||||
//child
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(std::map<int, Signature*>::const_iterator i=otherSignatures.begin(); i!=otherSignatures.end(); ++i)
|
||||
{
|
||||
if(ids.find(i->first) != ids.end())
|
||||
{
|
||||
int id = i->second->id();
|
||||
const std::map<int, Link> & links = i->second->getLinks();
|
||||
int weight = i->second->getWeight();
|
||||
for(std::map<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
|
||||
{
|
||||
int weightNeighbor = 0;
|
||||
const Signature * s = uValue(otherSignatures, iter->first, (Signature*)0);
|
||||
if(s)
|
||||
{
|
||||
weightNeighbor = s->getWeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->getWeight(iter->first, weightNeighbor);
|
||||
}
|
||||
//UDEBUG("Add neighbor link from %d to %d", id, iter->first);
|
||||
if(iter->second.type() == Link::kNeighbor)
|
||||
{
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\"\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor);
|
||||
}
|
||||
else if(iter->first > id)
|
||||
{
|
||||
//loop
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorG);
|
||||
}
|
||||
else
|
||||
{
|
||||
//child
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fout, "}\n");
|
||||
fclose(fout);
|
||||
UINFO("Graph saved to \"%s\" (Tip: $ neato -Tpdf \"%s\" -o out.pdf)", fileName.c_str(), fileName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rtabmap
|
||||
|
||||
@@ -2179,6 +2179,61 @@ void DBDriverSqlite3::saveQuery(const std::list<VisualWord *> & words) const
|
||||
}
|
||||
}
|
||||
|
||||
void DBDriverSqlite3::addLinkQuery(const Link & link) const
|
||||
{
|
||||
UDEBUG("");
|
||||
if(_ppDb)
|
||||
{
|
||||
std::string type;
|
||||
UTimer timer;
|
||||
timer.start();
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
|
||||
// Create new entries in table Link
|
||||
std::string query = queryStepLink();
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Save link
|
||||
stepLink(ppStmt, link);
|
||||
|
||||
// Finalize (delete) the statement
|
||||
rc = sqlite3_finalize(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
UDEBUG("Time=%fs", timer.ticks());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DBDriverSqlite3::updateLinkQuery(const Link & link) const
|
||||
{
|
||||
UDEBUG("");
|
||||
if(_ppDb)
|
||||
{
|
||||
std::string type;
|
||||
UTimer timer;
|
||||
timer.start();
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
|
||||
// Create new entries in table Link
|
||||
std::string query = queryStepLinkUpdate();
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Save link
|
||||
stepLink(ppStmt, link);
|
||||
|
||||
// Finalize (delete) the statement
|
||||
rc = sqlite3_finalize(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
UDEBUG("Time=%fs", timer.ticks());
|
||||
}
|
||||
}
|
||||
|
||||
std::string DBDriverSqlite3::queryStepNode() const
|
||||
{
|
||||
if(uStrNumCmp(_version, "0.10.1") >= 0)
|
||||
@@ -2549,23 +2604,43 @@ void DBDriverSqlite3::stepSensorData(sqlite3_stmt * ppStmt,
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
|
||||
std::string DBDriverSqlite3::queryStepLink() const
|
||||
std::string DBDriverSqlite3::queryStepLinkUpdate() const
|
||||
{
|
||||
if(uStrNumCmp(_version, "0.10.10") >= 0)
|
||||
{
|
||||
return "INSERT INTO Link(from_id, to_id, type, rot_variance, trans_variance, transform, user_data) VALUES(?,?,?,?,?,?,?);";
|
||||
return "UPDATE Link SET type=?, rot_variance=?, trans_variance=?, transform=?, user_data=? WHERE from_id=? AND to_id = ?;";
|
||||
}
|
||||
else if(uStrNumCmp(_version, "0.8.4") >= 0)
|
||||
{
|
||||
return "INSERT INTO Link(from_id, to_id, type, rot_variance, trans_variance, transform) VALUES(?,?,?,?,?,?);";
|
||||
return "UPDATE Link SET type=?, rot_variance=?, trans_variance=?, transform=? WHERE from_id=? AND to_id = ?;";
|
||||
}
|
||||
else if(uStrNumCmp(_version, "0.7.4") >= 0)
|
||||
{
|
||||
return "INSERT INTO Link(from_id, to_id, type, variance, transform) VALUES(?,?,?,?,?);";
|
||||
return "UPDATE Link SET type=?, variance=?, transform=? WHERE from_id=? AND to_id = ?;";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "INSERT INTO Link(from_id, to_id, type, transform) VALUES(?,?,?,?);";
|
||||
return "UPDATE Link SET type=?, transform=? WHERE from_id=? AND to_id = ?;";
|
||||
}
|
||||
}
|
||||
std::string DBDriverSqlite3::queryStepLink() const
|
||||
{
|
||||
// from_id, to_id are at the end to match the update query above
|
||||
if(uStrNumCmp(_version, "0.10.10") >= 0)
|
||||
{
|
||||
return "INSERT INTO Link(type, rot_variance, trans_variance, transform, user_data, from_id, to_id) VALUES(?,?,?,?,?,?,?);";
|
||||
}
|
||||
else if(uStrNumCmp(_version, "0.8.4") >= 0)
|
||||
{
|
||||
return "INSERT INTO Link(type, rot_variance, trans_variance, transform, from_id, to_id) VALUES(?,?,?,?,?,?);";
|
||||
}
|
||||
else if(uStrNumCmp(_version, "0.7.4") >= 0)
|
||||
{
|
||||
return "INSERT INTO Link(type, variance, transform, from_id, to_id) VALUES(?,?,?,?,?);";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "INSERT INTO Link(type, transform, from_id, to_id) VALUES(?,?,?,?);";
|
||||
}
|
||||
}
|
||||
void DBDriverSqlite3::stepLink(
|
||||
@@ -2587,10 +2662,6 @@ void DBDriverSqlite3::stepLink(
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
int index = 1;
|
||||
rc = sqlite3_bind_int(ppStmt, index++, link.from());
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_int(ppStmt, index++, link.to());
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_int(ppStmt, index++, link.type());
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
@@ -2624,6 +2695,11 @@ void DBDriverSqlite3::stepLink(
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
|
||||
rc = sqlite3_bind_int(ppStmt, index++, link.from());
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_int(ppStmt, index++, link.to());
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
rc=sqlite3_step(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ private:
|
||||
virtual void updateQuery(const std::list<Signature *> & signatures, bool updateTimestamp) const;
|
||||
virtual void updateQuery(const std::list<VisualWord *> & words, bool updateTimestamp) const;
|
||||
|
||||
virtual void addLinkQuery(const Link & link) const;
|
||||
virtual void updateLinkQuery(const Link & link) const;
|
||||
|
||||
// Load objects
|
||||
virtual void loadQuery(VWDictionary * dictionary) const;
|
||||
virtual void loadLastNodesQuery(std::list<Signature *> & signatures) const;
|
||||
@@ -85,6 +88,7 @@ private:
|
||||
std::string queryStepImage() const;
|
||||
std::string queryStepDepth() const;
|
||||
std::string queryStepSensorData() const;
|
||||
std::string queryStepLinkUpdate() const;
|
||||
std::string queryStepLink() const;
|
||||
std::string queryStepWordsChanged() const;
|
||||
std::string queryStepKeypoint() const;
|
||||
|
||||
+4
-232
@@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <rtabmap/core/EpipolarGeometry.h>
|
||||
#include "rtabmap/core/VisualWord.h"
|
||||
#include "rtabmap/core/Features2d.h"
|
||||
#include "DBDriverSqlite3.h"
|
||||
#include "rtabmap/core/DBDriver.h"
|
||||
#include "rtabmap/core/util3d_features.h"
|
||||
#include "rtabmap/core/util3d_filtering.h"
|
||||
#include "rtabmap/core/util3d_correspondences.h"
|
||||
@@ -184,7 +184,7 @@ bool Memory::init(const std::string & dbUrl, bool dbOverwritten, const Parameter
|
||||
|
||||
if(_dbDriver == 0 && !dbUrl.empty())
|
||||
{
|
||||
_dbDriver = new DBDriverSqlite3(parameters);
|
||||
_dbDriver = DBDriver::create(parameters);
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
@@ -3523,7 +3523,7 @@ SensorData Memory::getSignatureDataConst(int locationId) const
|
||||
return r;
|
||||
}
|
||||
|
||||
void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
|
||||
void Memory::generateGraph(const std::string & fileName, const std::set<int> & ids)
|
||||
{
|
||||
if(!_dbDriver)
|
||||
{
|
||||
@@ -3531,235 +3531,7 @@ void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!fileName.empty())
|
||||
{
|
||||
FILE* fout = 0;
|
||||
#ifdef _MSC_VER
|
||||
fopen_s(&fout, fileName.c_str(), "w");
|
||||
#else
|
||||
fout = fopen(fileName.c_str(), "w");
|
||||
#endif
|
||||
|
||||
if (!fout)
|
||||
{
|
||||
UERROR("Cannot open file %s!", fileName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if(ids.size() == 0)
|
||||
{
|
||||
_dbDriver->getAllNodeIds(ids);
|
||||
UDEBUG("ids.size()=%d", ids.size());
|
||||
for(std::map<int, Signature*>::iterator iter=_signatures.begin(); iter!=_signatures.end(); ++iter)
|
||||
{
|
||||
ids.insert(iter->first);
|
||||
}
|
||||
}
|
||||
|
||||
const char * colorG = "green";
|
||||
const char * colorP = "pink";
|
||||
; UINFO("Generating map with %d locations", ids.size());
|
||||
fprintf(fout, "digraph G {\n");
|
||||
for(std::set<int>::iterator i=ids.begin(); i!=ids.end(); ++i)
|
||||
{
|
||||
if(_signatures.find(*i) == _signatures.end())
|
||||
{
|
||||
int id = *i;
|
||||
std::map<int, Link> links;
|
||||
_dbDriver->loadLinks(id, links);
|
||||
int weight = 0;
|
||||
_dbDriver->getWeight(id, weight);
|
||||
for(std::map<int, Link>::iterator iter = links.begin(); iter!=links.end(); ++iter)
|
||||
{
|
||||
int weightNeighbor = 0;
|
||||
if(_signatures.find(iter->first) == _signatures.end())
|
||||
{
|
||||
_dbDriver->getWeight(iter->first, weightNeighbor);
|
||||
}
|
||||
else
|
||||
{
|
||||
weightNeighbor = _signatures.find(iter->first)->second->getWeight();
|
||||
}
|
||||
//UDEBUG("Add neighbor link from %d to %d", id, iter->first);
|
||||
if(iter->second.type() == Link::kNeighbor)
|
||||
{
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\"\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor);
|
||||
}
|
||||
else if(iter->first > id)
|
||||
{
|
||||
//loop
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorG);
|
||||
}
|
||||
else
|
||||
{
|
||||
//child
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(std::map<int, Signature*>::iterator i=_signatures.begin(); i!=_signatures.end(); ++i)
|
||||
{
|
||||
if(ids.find(i->first) != ids.end())
|
||||
{
|
||||
int id = i->second->id();
|
||||
const std::map<int, Link> & links = i->second->getLinks();
|
||||
int weight = i->second->getWeight();
|
||||
for(std::map<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
|
||||
{
|
||||
int weightNeighbor = 0;
|
||||
const Signature * s = this->getSignature(iter->first);
|
||||
if(s)
|
||||
{
|
||||
weightNeighbor = s->getWeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
_dbDriver->getWeight(iter->first, weightNeighbor);
|
||||
}
|
||||
//UDEBUG("Add neighbor link from %d to %d", id, iter->first);
|
||||
if(iter->second.type() == Link::kNeighbor)
|
||||
{
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\"\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor);
|
||||
}
|
||||
else if(iter->first > id)
|
||||
{
|
||||
//loop
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorG);
|
||||
}
|
||||
else
|
||||
{
|
||||
//child
|
||||
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n",
|
||||
id,
|
||||
weight,
|
||||
iter->first,
|
||||
weightNeighbor,
|
||||
colorP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fout, "}\n");
|
||||
fclose(fout);
|
||||
UINFO("Graph saved to \"%s\"", fileName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Only used to generate a .dot file
|
||||
class GraphNode
|
||||
{
|
||||
public:
|
||||
GraphNode(int id, GraphNode * parent = 0) :
|
||||
_parent(parent),
|
||||
_id(id)
|
||||
{
|
||||
if(_parent)
|
||||
{
|
||||
_parent->addChild(this);
|
||||
}
|
||||
}
|
||||
virtual ~GraphNode()
|
||||
{
|
||||
//We copy the set because when a child is destroyed, it is removed from its parent.
|
||||
std::set<GraphNode*> children = _children;
|
||||
_children.clear();
|
||||
for(std::set<GraphNode*>::iterator iter=children.begin(); iter!=children.end(); ++iter)
|
||||
{
|
||||
delete *iter;
|
||||
}
|
||||
children.clear();
|
||||
if(_parent)
|
||||
{
|
||||
_parent->removeChild(this);
|
||||
}
|
||||
}
|
||||
int id() const {return _id;}
|
||||
bool isAncestor(int id) const
|
||||
{
|
||||
if(_parent)
|
||||
{
|
||||
if(_parent->id() == id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return _parent->isAncestor(id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void expand(std::list<std::list<int> > & paths, std::list<int> currentPath = std::list<int>()) const
|
||||
{
|
||||
currentPath.push_back(_id);
|
||||
if(_children.size() == 0)
|
||||
{
|
||||
paths.push_back(currentPath);
|
||||
return;
|
||||
}
|
||||
for(std::set<GraphNode*>::const_iterator iter=_children.begin(); iter!=_children.end(); ++iter)
|
||||
{
|
||||
(*iter)->expand(paths, currentPath);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void addChild(GraphNode * child)
|
||||
{
|
||||
_children.insert(child);
|
||||
}
|
||||
void removeChild(GraphNode * child)
|
||||
{
|
||||
_children.erase(child);
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<GraphNode*> _children;
|
||||
GraphNode * _parent;
|
||||
int _id;
|
||||
};
|
||||
|
||||
//recursive
|
||||
void Memory::createGraph(GraphNode * parent, unsigned int maxDepth, const std::set<int> & endIds)
|
||||
{
|
||||
if(maxDepth == 0 || !parent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::map<int, int> neighbors = this->getNeighborsId(parent->id(), 1, -1, false);
|
||||
for(std::map<int, int>::iterator iter=neighbors.begin(); iter!=neighbors.end(); ++iter)
|
||||
{
|
||||
if(!parent->isAncestor(iter->first))
|
||||
{
|
||||
GraphNode * n = new GraphNode(iter->first, parent);
|
||||
if(endIds.find(iter->first) == endIds.end())
|
||||
{
|
||||
this->createGraph(n, maxDepth-1, endIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
_dbDriver->generateGraph(fileName, ids, _signatures);
|
||||
}
|
||||
|
||||
int Memory::getNi(int signatureId) const
|
||||
|
||||
@@ -50,7 +50,7 @@ class QLabel;
|
||||
|
||||
namespace rtabmap
|
||||
{
|
||||
class Memory;
|
||||
class DBDriver;
|
||||
class ImageView;
|
||||
class SensorData;
|
||||
class CloudViewer;
|
||||
@@ -155,7 +155,7 @@ private:
|
||||
QMap<int, int> idToIndex_;
|
||||
QList<rtabmap::Link> neighborLinks_;
|
||||
QList<rtabmap::Link> loopLinks_;
|
||||
rtabmap::Memory * memory_;
|
||||
rtabmap::DBDriver * dbDriver_;
|
||||
QString pathDatabase_;
|
||||
std::string databaseFileName_;
|
||||
std::list<std::map<int, rtabmap::Transform> > graphes_;
|
||||
|
||||
+258
-159
@@ -45,7 +45,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <rtabmap/utilite/UTimer.h>
|
||||
#include <rtabmap/utilite/UFile.h>
|
||||
#include "rtabmap/core/Memory.h"
|
||||
#include "rtabmap/core/DBDriver.h"
|
||||
#include "rtabmap/gui/KeypointItem.h"
|
||||
#include "rtabmap/utilite/UCv2Qt.h"
|
||||
@@ -57,6 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rtabmap/core/util3d_mapping.h"
|
||||
#include "rtabmap/core/util2d.h"
|
||||
#include "rtabmap/core/Signature.h"
|
||||
#include "rtabmap/core/Memory.h"
|
||||
#include "rtabmap/core/Features2d.h"
|
||||
#include "rtabmap/core/Compression.h"
|
||||
#include "rtabmap/core/Graph.h"
|
||||
@@ -74,7 +74,7 @@ namespace rtabmap {
|
||||
|
||||
DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
||||
QMainWindow(parent),
|
||||
memory_(0),
|
||||
dbDriver_(0),
|
||||
savedMaximized_(false),
|
||||
firstCall_(true)
|
||||
{
|
||||
@@ -332,9 +332,9 @@ DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
||||
DatabaseViewer::~DatabaseViewer()
|
||||
{
|
||||
delete ui_;
|
||||
if(memory_)
|
||||
if(dbDriver_)
|
||||
{
|
||||
delete memory_;
|
||||
delete dbDriver_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,10 +577,10 @@ bool DatabaseViewer::openDatabase(const QString & path)
|
||||
UDEBUG("Open database \"%s\"", path.toStdString().c_str());
|
||||
if(QFile::exists(path))
|
||||
{
|
||||
if(memory_)
|
||||
if(dbDriver_)
|
||||
{
|
||||
delete memory_;
|
||||
memory_ = 0;
|
||||
delete dbDriver_;
|
||||
dbDriver_ = 0;
|
||||
ids_.clear();
|
||||
idToIndex_.clear();
|
||||
neighborLinks_.clear();
|
||||
@@ -602,16 +602,10 @@ bool DatabaseViewer::openDatabase(const QString & path)
|
||||
}
|
||||
|
||||
std::string driverType = "sqlite3";
|
||||
rtabmap::ParametersMap parameters;
|
||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), "false"));
|
||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemIncrementalMemory(), "false"));
|
||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemInitWMWithAllNodes(), "true"));
|
||||
// use BruteForce dictionary because we don't know which type of descriptors are saved in database
|
||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpNNStrategy(), "3"));
|
||||
|
||||
memory_ = new rtabmap::Memory();
|
||||
dbDriver_ = DBDriver::create();
|
||||
|
||||
if(!memory_->init(path.toStdString(), false, parameters))
|
||||
if(!dbDriver_->openConnection(path.toStdString()))
|
||||
{
|
||||
QMessageBox::warning(this, "Database error", tr("Can't open database \"%1\"").arg(path));
|
||||
}
|
||||
@@ -673,21 +667,13 @@ void DatabaseViewer::closeEvent(QCloseEvent* event)
|
||||
std::multimap<int, rtabmap::Link>::iterator refinedIter = rtabmap::graph::findLink(linksRefined_, iter->second.from(), iter->second.to());
|
||||
if(refinedIter != linksRefined_.end())
|
||||
{
|
||||
memory_->addLink(Link(
|
||||
refinedIter->second.from(),
|
||||
refinedIter->second.to(),
|
||||
refinedIter->second.type(),
|
||||
refinedIter->second.transform(),
|
||||
refinedIter->second.infMatrix()));
|
||||
dbDriver_->addLink(refinedIter->second);
|
||||
dbDriver_->addLink(refinedIter->second.inverse());
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_->addLink(Link(
|
||||
iter->second.from(),
|
||||
iter->second.to(),
|
||||
iter->second.type(),
|
||||
iter->second.transform(),
|
||||
iter->second.infMatrix()));
|
||||
dbDriver_->addLink(iter->second);
|
||||
dbDriver_->addLink(iter->second.inverse());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,18 +682,16 @@ void DatabaseViewer::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
if(!containsLink(linksAdded_, iter->second.from(), iter->second.to()))
|
||||
{
|
||||
memory_->updateLink(
|
||||
iter->second.from(),
|
||||
iter->second.to(),
|
||||
iter->second.transform(),
|
||||
iter->second.infMatrix());
|
||||
dbDriver_->updateLink(iter->second);
|
||||
dbDriver_->updateLink(iter->second.inverse());
|
||||
}
|
||||
}
|
||||
|
||||
// Rejected links
|
||||
for(std::multimap<int, rtabmap::Link>::iterator iter=linksRemoved_.begin(); iter!=linksRemoved_.end(); ++iter)
|
||||
{
|
||||
memory_->removeLink(iter->second.to(), iter->second.from());
|
||||
dbDriver_->removeLink(iter->second.to(), iter->second.from());
|
||||
dbDriver_->removeLink(iter->second.from(), iter->second.to());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,10 +711,10 @@ void DatabaseViewer::closeEvent(QCloseEvent* event)
|
||||
|
||||
if(event->isAccepted())
|
||||
{
|
||||
if(memory_)
|
||||
if(dbDriver_)
|
||||
{
|
||||
delete memory_;
|
||||
memory_ = 0;
|
||||
delete dbDriver_;
|
||||
dbDriver_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -778,7 +762,7 @@ bool DatabaseViewer::eventFilter(QObject *obj, QEvent *event)
|
||||
|
||||
void DatabaseViewer::exportDatabase()
|
||||
{
|
||||
if(!memory_ || ids_.size() == 0)
|
||||
if(!dbDriver_ || ids_.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -807,7 +791,7 @@ void DatabaseViewer::exportDatabase()
|
||||
int mapId = -1;
|
||||
std::string label;
|
||||
double stamp = 0;
|
||||
if(memory_->getNodeInfo(ids_[i], odomPose, mapId, weight, label, stamp, true))
|
||||
if(dbDriver_->getNodeInfo(ids_[i], odomPose, mapId, weight, label, stamp))
|
||||
{
|
||||
if(frameRate == 0 ||
|
||||
previousStamp == 0 ||
|
||||
@@ -846,17 +830,17 @@ void DatabaseViewer::exportDatabase()
|
||||
{
|
||||
int id = ids.at(i);
|
||||
|
||||
SensorData data = memory_->getNodeData(id, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(id, data);
|
||||
data.uncompressData();
|
||||
cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
|
||||
if(dialog.isOdomExported())
|
||||
{
|
||||
if(memory_->getSignature(id) == 0)
|
||||
std::map<int, Link> links;
|
||||
dbDriver_->loadLinks(id, links, Link::kNeighbor);
|
||||
if(links.size() && links.begin()->first < id)
|
||||
{
|
||||
UERROR("could not find node %d in memory.", id);
|
||||
}
|
||||
else
|
||||
{
|
||||
covariance = memory_->getSignature(id)->getPoseCovariance();
|
||||
covariance = links.begin()->second.infMatrix().inv();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,7 +900,7 @@ void DatabaseViewer::exportDatabase()
|
||||
|
||||
void DatabaseViewer::extractImages()
|
||||
{
|
||||
if(!memory_ || ids_.size() == 0)
|
||||
if(!dbDriver_ || ids_.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -927,7 +911,9 @@ void DatabaseViewer::extractImages()
|
||||
if(ids_.size())
|
||||
{
|
||||
int id = ids_.at(0);
|
||||
SensorData data = memory_->getNodeData(id, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(id, data);
|
||||
data.uncompressData();
|
||||
if(!data.imageRaw().empty() && !data.rightRaw().empty())
|
||||
{
|
||||
QDir dir;
|
||||
@@ -1009,7 +995,9 @@ void DatabaseViewer::extractImages()
|
||||
for(int i=0; i<ids_.size(); ++i)
|
||||
{
|
||||
int id = ids_.at(i);
|
||||
SensorData data = memory_->getNodeData(id, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(id, data);
|
||||
data.uncompressData();
|
||||
if(!data.imageRaw().empty() && !data.rightRaw().empty())
|
||||
{
|
||||
cv::imwrite(QString("%1/left/%2.jpg").arg(path).arg(id).toStdString(), data.imageRaw());
|
||||
@@ -1033,15 +1021,22 @@ void DatabaseViewer::extractImages()
|
||||
|
||||
void DatabaseViewer::updateIds()
|
||||
{
|
||||
if(!memory_)
|
||||
if(!dbDriver_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<int> ids = memory_->getAllSignatureIds();
|
||||
std::set<int> ids;
|
||||
dbDriver_->getAllNodeIds(ids);
|
||||
ids_ = QList<int>::fromStdList(std::list<int>(ids.begin(), ids.end()));
|
||||
idToIndex_.clear();
|
||||
mapIds_.clear();
|
||||
poses_.clear();
|
||||
links_.clear();
|
||||
linksAdded_.clear();
|
||||
linksRefined_.clear();
|
||||
linksRemoved_.clear();
|
||||
ui_->label_optimizeFrom->setText(tr("Optimize from"));
|
||||
for(int i=0; i<ids_.size(); ++i)
|
||||
{
|
||||
idToIndex_.insert(ids_[i], i);
|
||||
@@ -1051,22 +1046,27 @@ void DatabaseViewer::updateIds()
|
||||
std::string l;
|
||||
double s;
|
||||
int mapId;
|
||||
memory_->getNodeInfo(ids_[i], p, mapId, w, l, s, true);
|
||||
dbDriver_->getNodeInfo(ids_[i], p, mapId, w, l, s);
|
||||
mapIds_.insert(std::make_pair(ids_[i], mapId));
|
||||
poses_.insert(std::make_pair(ids_[i], p));
|
||||
|
||||
//links
|
||||
std::map<int, Link> neighbors;
|
||||
dbDriver_->loadLinks(ids_[i], neighbors); // including loop closures
|
||||
for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
|
||||
{
|
||||
if( jter->second.isValid() && // null transform means a rehearsed location
|
||||
uContains(poses_, jter->first) &&
|
||||
graph::findLink(links_, ids_[i], jter->first) == links_.end() &&
|
||||
(jter->second.type() == Link::kNeighbor || jter->first < ids_[i])) //Loop parent to child
|
||||
{
|
||||
links_.insert(std::make_pair(ids_[i], jter->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
poses_.clear();
|
||||
links_.clear();
|
||||
linksAdded_.clear();
|
||||
linksRefined_.clear();
|
||||
linksRemoved_.clear();
|
||||
ui_->label_optimizeFrom->setText(tr("Optimize from"));
|
||||
if(memory_->getLastWorkingSignature())
|
||||
if(ids.size())
|
||||
{
|
||||
//get constraints only for parent links
|
||||
|
||||
memory_->getMetricConstraints(ids, poses_, links_, true);
|
||||
|
||||
if(poses_.size())
|
||||
{
|
||||
bool nullPoses = poses_.begin()->second.isNull();
|
||||
@@ -1092,9 +1092,9 @@ void DatabaseViewer::updateIds()
|
||||
}
|
||||
|
||||
int first = *ids.begin();
|
||||
ui_->spinBox_optimizationsFrom->setRange(first, memory_->getLastWorkingSignature()->id());
|
||||
ui_->spinBox_optimizationsFrom->setValue(memory_->getLastWorkingSignature()->id());
|
||||
ui_->label_optimizeFrom->setText(tr("Optimize from [%1, %2]").arg(first).arg(memory_->getLastWorkingSignature()->id()));
|
||||
ui_->spinBox_optimizationsFrom->setRange(first, ids_.last());
|
||||
ui_->spinBox_optimizationsFrom->setValue(ids_.first());
|
||||
ui_->label_optimizeFrom->setText(tr("Optimize from [%1, %2]").arg(first).arg(ids_.first()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,7 +1167,7 @@ void DatabaseViewer::updateIds()
|
||||
|
||||
void DatabaseViewer::generateGraph()
|
||||
{
|
||||
if(!memory_)
|
||||
if(!dbDriver_)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot generate a graph"), tr("A database must must loaded first...\nUse File->Open database."));
|
||||
return;
|
||||
@@ -1176,13 +1176,13 @@ void DatabaseViewer::generateGraph()
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save File"), pathDatabase_+"/Graph.dot", tr("Graphiz file (*.dot)"));
|
||||
if(!path.isEmpty())
|
||||
{
|
||||
memory_->generateGraph(path.toStdString());
|
||||
dbDriver_->generateGraph(path.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::generateLocalGraph()
|
||||
{
|
||||
if(!ids_.size() || !memory_)
|
||||
if(!ids_.size() || !dbDriver_)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot generate a graph"), tr("The database is empty..."));
|
||||
return;
|
||||
@@ -1196,9 +1196,53 @@ void DatabaseViewer::generateLocalGraph()
|
||||
if(ok)
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save File"), pathDatabase_+"/Graph" + QString::number(id) + ".dot", tr("Graphiz file (*.dot)"));
|
||||
if(!path.isEmpty())
|
||||
if(!path.isEmpty() && id>0)
|
||||
{
|
||||
std::map<int, int> ids = memory_->getNeighborsId(id, margin, -1, false);
|
||||
std::map<int, int> ids;
|
||||
std::list<int> curentMarginList;
|
||||
std::set<int> currentMargin;
|
||||
std::set<int> nextMargin;
|
||||
nextMargin.insert(id);
|
||||
int m = 0;
|
||||
while((margin == 0 || m < margin) && nextMargin.size())
|
||||
{
|
||||
curentMarginList = std::list<int>(nextMargin.rbegin(), nextMargin.rend());
|
||||
nextMargin.clear();
|
||||
|
||||
for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
|
||||
{
|
||||
if(ids.find(*jter) == ids.end())
|
||||
{
|
||||
std::map<int, Link> links;
|
||||
ids.insert(std::pair<int, int>(*jter, m));
|
||||
|
||||
UTimer timer;
|
||||
dbDriver_->loadLinks(*jter, links);
|
||||
|
||||
// links
|
||||
for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
|
||||
{
|
||||
if( !uContains(ids, iter->first))
|
||||
{
|
||||
UASSERT(iter->second.type() != Link::kUndef);
|
||||
if(iter->second.type() == Link::kNeighbor)
|
||||
{
|
||||
nextMargin.insert(iter->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
// loop closures are on same margin
|
||||
if(currentMargin.insert(iter->first).second)
|
||||
{
|
||||
curentMarginList.push_back(iter->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++m;
|
||||
}
|
||||
|
||||
if(ids.size() > 0)
|
||||
{
|
||||
@@ -1210,7 +1254,7 @@ void DatabaseViewer::generateLocalGraph()
|
||||
UINFO("Node %d", iter->first);
|
||||
}
|
||||
UINFO("idsSet=%d", idsSet.size());
|
||||
memory_->generateGraph(path.toStdString(), idsSet);
|
||||
dbDriver_->generateGraph(path.toStdString(), idsSet);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1287,7 +1331,7 @@ void DatabaseViewer::generateG2OGraph()
|
||||
|
||||
void DatabaseViewer::view3DMap()
|
||||
{
|
||||
if(!ids_.size() || !memory_)
|
||||
if(!ids_.size() || !dbDriver_)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot view 3D map"), tr("The database is empty..."));
|
||||
return;
|
||||
@@ -1350,7 +1394,9 @@ void DatabaseViewer::view3DMap()
|
||||
rtabmap::Transform pose = iter->second;
|
||||
if(!pose.isNull())
|
||||
{
|
||||
SensorData data = memory_->getNodeData(iter->first, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(iter->first, data);
|
||||
data.uncompressData();
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
UASSERT(data.imageRaw().empty() || data.imageRaw().type()==CV_8UC3 || data.imageRaw().type() == CV_8UC1);
|
||||
UASSERT(data.depthOrRightRaw().empty() || data.depthOrRightRaw().type()==CV_8UC1 || data.depthOrRightRaw().type() == CV_16UC1 || data.depthOrRightRaw().type() == CV_32FC1);
|
||||
@@ -1363,7 +1409,7 @@ void DatabaseViewer::view3DMap()
|
||||
Transform odomPose;
|
||||
std::string label;
|
||||
double stamp;
|
||||
if(memory_->getNodeInfo(iter->first, odomPose, mapId, weight, label, stamp, true))
|
||||
if(dbDriver_->getNodeInfo(iter->first, odomPose, mapId, weight, label, stamp))
|
||||
{
|
||||
color = (Qt::GlobalColor)(mapId % 12 + 7 );
|
||||
}
|
||||
@@ -1394,7 +1440,7 @@ void DatabaseViewer::view3DMap()
|
||||
|
||||
void DatabaseViewer::generate3DMap()
|
||||
{
|
||||
if(!ids_.size() || !memory_)
|
||||
if(!ids_.size() || !dbDriver_)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot generate a graph"), tr("The database is empty..."));
|
||||
return;
|
||||
@@ -1434,7 +1480,9 @@ void DatabaseViewer::generate3DMap()
|
||||
const rtabmap::Transform & pose = iter->second;
|
||||
if(!pose.isNull())
|
||||
{
|
||||
SensorData data = memory_->getNodeData(iter->first, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(iter->first, data);
|
||||
data.uncompressData();
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
UASSERT(data.imageRaw().empty() || data.imageRaw().type()==CV_8UC3 || data.imageRaw().type() == CV_8UC1);
|
||||
UASSERT(data.depthOrRightRaw().empty() || data.depthOrRightRaw().type()==CV_8UC1 || data.depthOrRightRaw().type() == CV_16UC1 || data.depthOrRightRaw().type() == CV_32FC1);
|
||||
@@ -1696,9 +1744,11 @@ void DatabaseViewer::update(int value,
|
||||
//image
|
||||
QImage img;
|
||||
QImage imgDepth;
|
||||
if(memory_)
|
||||
if(dbDriver_)
|
||||
{
|
||||
SensorData data = memory_->getNodeData(id, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(id, data);
|
||||
data.uncompressData();
|
||||
if(!data.imageRaw().empty())
|
||||
{
|
||||
img = uCvMat2QImage(data.imageRaw());
|
||||
@@ -1708,18 +1758,23 @@ void DatabaseViewer::update(int value,
|
||||
imgDepth = uCvMat2QImage(data.depthOrRightRaw());
|
||||
}
|
||||
|
||||
const Signature * signature = memory_->getSignature(id);
|
||||
std::list<int> ids;
|
||||
ids.push_back(id);
|
||||
std::list<Signature*> signatures;
|
||||
dbDriver_->loadSignatures(ids, signatures);
|
||||
|
||||
if(signature && signature->getWords().size())
|
||||
if(signatures.size() && signatures.front()!=0 && signatures.front()->getWords().size())
|
||||
{
|
||||
view->setFeatures(signature->getWords(), data.depthOrRightRaw().type() == CV_8UC1?cv::Mat():data.depthOrRightRaw(), Qt::yellow);
|
||||
view->setFeatures(signatures.front()->getWords(), data.depthOrRightRaw().type() == CV_8UC1?cv::Mat():data.depthOrRightRaw(), Qt::yellow);
|
||||
delete signatures.front();
|
||||
signatures.clear();
|
||||
}
|
||||
|
||||
Transform odomPose;
|
||||
int w;
|
||||
std::string l;
|
||||
double s;
|
||||
memory_->getNodeInfo(id, odomPose, mapId, w, l, s, true);
|
||||
dbDriver_->getNodeInfo(id, odomPose, mapId, w, l, s);
|
||||
|
||||
weight->setNum(w);
|
||||
label->setText(l.c_str());
|
||||
@@ -1781,20 +1836,23 @@ void DatabaseViewer::update(int value,
|
||||
}
|
||||
|
||||
// loops
|
||||
std::map<int, rtabmap::Link> loopClosures;
|
||||
loopClosures = memory_->getLoopClosureLinks(id, true);
|
||||
if(loopClosures.size())
|
||||
std::map<int, rtabmap::Link> links;
|
||||
dbDriver_->loadLinks(id, links);
|
||||
if(links.size())
|
||||
{
|
||||
QString strParents, strChildren;
|
||||
for(std::map<int, rtabmap::Link>::iterator iter=loopClosures.begin(); iter!=loopClosures.end(); ++iter)
|
||||
for(std::map<int, rtabmap::Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
|
||||
{
|
||||
if(iter->first < id)
|
||||
if(iter->second.type() != Link::kNeighbor)
|
||||
{
|
||||
strChildren.append(QString("%1 ").arg(iter->first));
|
||||
}
|
||||
else
|
||||
{
|
||||
strParents.append(QString("%1 ").arg(iter->first));
|
||||
if(iter->first < id)
|
||||
{
|
||||
strChildren.append(QString("%1 ").arg(iter->first));
|
||||
}
|
||||
else
|
||||
{
|
||||
strParents.append(QString("%1 ").arg(iter->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
labelParents->setText(strParents);
|
||||
@@ -1906,7 +1964,9 @@ void DatabaseViewer::updateStereo()
|
||||
if(ui_->horizontalSlider_A->maximum())
|
||||
{
|
||||
int id = ids_.at(ui_->horizontalSlider_A->value());
|
||||
SensorData data = memory_->getNodeData(id, true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(id, data);
|
||||
data.uncompressData();
|
||||
updateStereo(&data);
|
||||
}
|
||||
}
|
||||
@@ -2240,7 +2300,7 @@ void DatabaseViewer::updateConstraintView(
|
||||
ui_->label_constraint->clear();
|
||||
ui_->label_constraint_opt->clear();
|
||||
ui_->checkBox_showOptimized->setEnabled(false);
|
||||
UASSERT(!t.isNull() && memory_);
|
||||
UASSERT(!t.isNull() && dbDriver_);
|
||||
|
||||
ui_->label_type->setNum(link.type());
|
||||
ui_->label_variance->setText(QString("%1, %2")
|
||||
@@ -2316,11 +2376,13 @@ void DatabaseViewer::updateConstraintView(
|
||||
{
|
||||
SensorData dataFrom, dataTo;
|
||||
|
||||
dataFrom = memory_->getNodeData(link.from(), true, false);
|
||||
dbDriver_->getNodeData(link.from(), dataFrom);
|
||||
dataFrom.uncompressData();
|
||||
UASSERT(dataFrom.imageRaw().empty() || dataFrom.imageRaw().type()==CV_8UC3 || dataFrom.imageRaw().type() == CV_8UC1);
|
||||
UASSERT(dataFrom.depthOrRightRaw().empty() || dataFrom.depthOrRightRaw().type()==CV_8UC1 || dataFrom.depthOrRightRaw().type() == CV_16UC1 || dataFrom.depthOrRightRaw().type() == CV_32FC1);
|
||||
|
||||
dataTo = memory_->getNodeData(link.to(), true, false);
|
||||
dbDriver_->getNodeData(link.to(), dataTo);
|
||||
dataTo.uncompressData();
|
||||
UASSERT(dataTo.imageRaw().empty() || dataTo.imageRaw().type()==CV_8UC3 || dataTo.imageRaw().type() == CV_8UC1);
|
||||
UASSERT(dataTo.depthOrRightRaw().empty() || dataTo.depthOrRightRaw().type()==CV_8UC1 || dataTo.depthOrRightRaw().type() == CV_16UC1 || dataTo.depthOrRightRaw().type() == CV_32FC1);
|
||||
|
||||
@@ -2351,10 +2413,16 @@ void DatabaseViewer::updateConstraintView(
|
||||
}
|
||||
if(ui_->checkBox_show3DWords->isChecked())
|
||||
{
|
||||
const Signature * sFrom = memory_->getSignature(link.from());
|
||||
const Signature * sTo = memory_->getSignature(link.to());
|
||||
if(sFrom && sTo)
|
||||
std::list<int> ids;
|
||||
ids.push_back(link.from());
|
||||
ids.push_back(link.to());
|
||||
std::list<Signature*> signatures;
|
||||
dbDriver_->loadSignatures(ids, signatures);
|
||||
if(signatures.size() == 2)
|
||||
{
|
||||
const Signature * sFrom = signatures.front();
|
||||
const Signature * sTo = signatures.back();
|
||||
UASSERT(sFrom && sTo);
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudFrom(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTo(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloudFrom->resize(sFrom->getWords3().size());
|
||||
@@ -2412,6 +2480,11 @@ void DatabaseViewer::updateConstraintView(
|
||||
ui_->constraintsViewer->removeCloud("words0");
|
||||
ui_->constraintsViewer->removeCloud("words1");
|
||||
}
|
||||
//cleanup
|
||||
for(std::list<Signature*>::iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
|
||||
{
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2539,7 +2612,8 @@ void DatabaseViewer::updateConstraintView(
|
||||
if(iter->first != link.to()) // already added to view
|
||||
{
|
||||
//create scan
|
||||
SensorData data = memory_->getNodeData(iter->first, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(iter->first, data);
|
||||
cv::Mat scan;
|
||||
data.uncompressDataConst(0, 0, &scan, 0);
|
||||
if(!scan.empty())
|
||||
@@ -2684,7 +2758,7 @@ void DatabaseViewer::updateConstraintButtons()
|
||||
|
||||
void DatabaseViewer::sliderIterationsValueChanged(int value)
|
||||
{
|
||||
if(memory_ && value >=0 && value < (int)graphes_.size())
|
||||
if(dbDriver_ && value >=0 && value < (int)graphes_.size())
|
||||
{
|
||||
std::map<int, rtabmap::Transform> & graph = uValueAt(graphes_, value);
|
||||
std::map<int, rtabmap::Transform> graphFiltered = graph;
|
||||
@@ -2707,7 +2781,9 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
|
||||
bool added = false;
|
||||
if(ui_->groupBox_gridFromProjection->isChecked())
|
||||
{
|
||||
SensorData data = memory_->getNodeData(ids.at(i), true, false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(ids.at(i), data);
|
||||
data.uncompressData();
|
||||
if(!data.depthOrRightRaw().empty())
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
|
||||
@@ -2741,7 +2817,8 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
|
||||
}
|
||||
else
|
||||
{
|
||||
SensorData data = memory_->getNodeData(ids.at(i), false);
|
||||
SensorData data;
|
||||
dbDriver_->getNodeData(ids.at(i), data);
|
||||
if(!data.laserScanCompressed().empty())
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
|
||||
@@ -3114,8 +3191,8 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent, bool update
|
||||
Transform transform;
|
||||
|
||||
SensorData dataFrom, dataTo;
|
||||
dataFrom = memory_->getNodeData(currentLink.from(), false);
|
||||
dataTo = memory_->getNodeData(currentLink.to(), false);
|
||||
dbDriver_->getNodeData(currentLink.from(), dataFrom);
|
||||
dbDriver_->getNodeData(currentLink.to(), dataTo);
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudA(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudB(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
@@ -3337,31 +3414,35 @@ void DatabaseViewer::refineConstraintVisually(int from, int to, bool silent, boo
|
||||
return;
|
||||
}
|
||||
|
||||
// create a fake memory to compute transform
|
||||
ParametersMap parameters;
|
||||
parameters.insert(ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(ui_->comboBox_featureType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNNStrategy(), uNumber2Str(ui_->comboBox_nnType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(ui_->doubleSpinBox_visual_maxCorrespDistance->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpMaxDepth(), uNumber2Str(ui_->doubleSpinBox_visual_maxDepth->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNndrRatio(), uNumber2Str(ui_->doubleSpinBox_visual_nndr->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(ui_->spinBox_visual_iteration->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(ui_->spinBox_visual_minCorrespondences->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowEstimationType(), uNumber2Str(ui_->comboBox_estimationType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowPnPFlags(), uNumber2Str(ui_->comboBox_pnpFlags->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kMemGenerateIds(), "false"));
|
||||
parameters.insert(ParametersPair(Parameters::kMemRehearsalSimilarity(), "1.0"));
|
||||
parameters.insert(ParametersPair(Parameters::kKpWordsPerImage(), "0"));
|
||||
Memory tmpMemory(parameters);
|
||||
|
||||
Transform t;
|
||||
std::string rejectedMsg;
|
||||
double variance = -1.0;
|
||||
int inliers = -1;
|
||||
if(ui_->groupBox_visual_recomputeFeatures->isChecked())
|
||||
{
|
||||
// create a fake memory to regenerate features
|
||||
ParametersMap parameters;
|
||||
parameters.insert(ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(ui_->comboBox_featureType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNNStrategy(), uNumber2Str(ui_->comboBox_nnType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(ui_->doubleSpinBox_visual_maxCorrespDistance->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpMaxDepth(), uNumber2Str(ui_->doubleSpinBox_visual_maxDepth->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNndrRatio(), uNumber2Str(ui_->doubleSpinBox_visual_nndr->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(ui_->spinBox_visual_iteration->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(ui_->spinBox_visual_minCorrespondences->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowEstimationType(), uNumber2Str(ui_->comboBox_estimationType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowPnPFlags(), uNumber2Str(ui_->comboBox_pnpFlags->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kMemGenerateIds(), "false"));
|
||||
parameters.insert(ParametersPair(Parameters::kMemRehearsalSimilarity(), "1.0"));
|
||||
parameters.insert(ParametersPair(Parameters::kKpWordsPerImage(), "0"));
|
||||
Memory tmpMemory(parameters);
|
||||
|
||||
// Add signatures
|
||||
SensorData dataFrom = memory_->getNodeData(from, true, false);
|
||||
SensorData dataTo = memory_->getNodeData(to, true, false);
|
||||
// Add sensor data to generate features
|
||||
SensorData dataFrom;
|
||||
dbDriver_->getNodeData(from, dataFrom);
|
||||
dataFrom.uncompressData();
|
||||
SensorData dataTo;
|
||||
dbDriver_->getNodeData(to, dataTo);
|
||||
dataTo.uncompressData();
|
||||
|
||||
if(from > to)
|
||||
{
|
||||
@@ -3379,14 +3460,21 @@ void DatabaseViewer::refineConstraintVisually(int from, int to, bool silent, boo
|
||||
}
|
||||
else
|
||||
{
|
||||
ParametersMap parameters;
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(ui_->doubleSpinBox_visual_maxCorrespDistance->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(ui_->spinBox_visual_iteration->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(ui_->spinBox_visual_minCorrespondences->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowEstimationType(), uNumber2Str(ui_->comboBox_estimationType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowPnPFlags(), uNumber2Str(ui_->comboBox_pnpFlags->currentIndex())));
|
||||
memory_->parseParameters(parameters);
|
||||
t = memory_->computeVisualTransform(to, from, &rejectedMsg, &inliers, &variance);
|
||||
std::list<int> ids;
|
||||
ids.push_back(to);
|
||||
ids.push_back(from);
|
||||
std::list<Signature*> signatures;
|
||||
dbDriver_->loadSignatures(ids, signatures);
|
||||
|
||||
if(signatures.size() == 2)
|
||||
{
|
||||
t = tmpMemory.computeVisualTransform(*signatures.front(), *signatures.back(), &rejectedMsg, &inliers, &variance);
|
||||
}
|
||||
//cleanup
|
||||
for(std::list<Signature*>::iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
|
||||
{
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
if(!t.isNull())
|
||||
@@ -3458,31 +3546,35 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool updateGra
|
||||
UASSERT(!containsLink(linksRemoved_, from, to));
|
||||
UASSERT(!containsLink(linksRefined_, from, to));
|
||||
|
||||
// create a fake memory to compute the transform
|
||||
ParametersMap parameters;
|
||||
parameters.insert(ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(ui_->comboBox_featureType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNNStrategy(), uNumber2Str(ui_->comboBox_nnType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(ui_->doubleSpinBox_visual_maxCorrespDistance->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpMaxDepth(), uNumber2Str(ui_->doubleSpinBox_visual_maxDepth->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNndrRatio(), uNumber2Str(ui_->doubleSpinBox_visual_nndr->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(ui_->spinBox_visual_iteration->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(ui_->spinBox_visual_minCorrespondences->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowEstimationType(), uNumber2Str(ui_->comboBox_estimationType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowPnPFlags(), uNumber2Str(ui_->comboBox_pnpFlags->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kMemGenerateIds(), "false"));
|
||||
parameters.insert(ParametersPair(Parameters::kMemRehearsalSimilarity(), "1.0"));
|
||||
parameters.insert(ParametersPair(Parameters::kKpWordsPerImage(), "0"));
|
||||
Memory tmpMemory(parameters);
|
||||
|
||||
Transform t;
|
||||
std::string rejectedMsg;
|
||||
double variance = -1.0;
|
||||
int inliers = -1;
|
||||
if(ui_->groupBox_visual_recomputeFeatures->isChecked())
|
||||
{
|
||||
// create a fake memory to regenerate features
|
||||
ParametersMap parameters;
|
||||
parameters.insert(ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(ui_->comboBox_featureType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNNStrategy(), uNumber2Str(ui_->comboBox_nnType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(ui_->doubleSpinBox_visual_maxCorrespDistance->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpMaxDepth(), uNumber2Str(ui_->doubleSpinBox_visual_maxDepth->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kKpNndrRatio(), uNumber2Str(ui_->doubleSpinBox_visual_nndr->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(ui_->spinBox_visual_iteration->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(ui_->spinBox_visual_minCorrespondences->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowEstimationType(), uNumber2Str(ui_->comboBox_estimationType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowPnPFlags(), uNumber2Str(ui_->comboBox_pnpFlags->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kMemGenerateIds(), "false"));
|
||||
parameters.insert(ParametersPair(Parameters::kMemRehearsalSimilarity(), "1.0"));
|
||||
parameters.insert(ParametersPair(Parameters::kKpWordsPerImage(), "0"));
|
||||
Memory tmpMemory(parameters);
|
||||
|
||||
// Add signatures
|
||||
SensorData dataFrom = memory_->getNodeData(from, true, false);
|
||||
SensorData dataTo = memory_->getNodeData(to, true, false);
|
||||
// Add sensor data to generate features
|
||||
SensorData dataFrom;
|
||||
dbDriver_->getNodeData(from, dataFrom);
|
||||
dataFrom.uncompressData();
|
||||
SensorData dataTo;
|
||||
dbDriver_->getNodeData(to, dataTo);
|
||||
dataTo.uncompressData();
|
||||
|
||||
if(from > to)
|
||||
{
|
||||
@@ -3507,14 +3599,21 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool updateGra
|
||||
}
|
||||
else
|
||||
{
|
||||
ParametersMap parameters;
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(ui_->doubleSpinBox_visual_maxCorrespDistance->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(ui_->spinBox_visual_iteration->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(ui_->spinBox_visual_minCorrespondences->value())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowEstimationType(), uNumber2Str(ui_->comboBox_estimationType->currentIndex())));
|
||||
parameters.insert(ParametersPair(Parameters::kLccBowPnPFlags(), uNumber2Str(ui_->comboBox_pnpFlags->currentIndex())));
|
||||
memory_->parseParameters(parameters);
|
||||
t = memory_->computeVisualTransform(to, from, &rejectedMsg, &inliers, &variance);
|
||||
std::list<int> ids;
|
||||
ids.push_back(to);
|
||||
ids.push_back(from);
|
||||
std::list<Signature*> signatures;
|
||||
dbDriver_->loadSignatures(ids, signatures);
|
||||
|
||||
if(signatures.size() == 2)
|
||||
{
|
||||
t = tmpMemory.computeVisualTransform(*signatures.front(), *signatures.back(), &rejectedMsg, &inliers, &variance);
|
||||
}
|
||||
//cleanup
|
||||
for(std::list<Signature*>::iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
|
||||
{
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
if(!t.isNull())
|
||||
|
||||
@@ -3198,7 +3198,7 @@ void MainWindow::generateGraphDOT()
|
||||
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdGenerateDOTGraph, false, path.toStdString(), id, margin));
|
||||
|
||||
_ui->dockWidget_console->show();
|
||||
_ui->widget_console->appendMsg(QString("Graph saved... Tip:\nneato -Tpdf \"%1\" -o out.pdf").arg(_graphSavingFileName).arg(_graphSavingFileName));
|
||||
_ui->widget_console->appendMsg(QString("Graph saved... Tip:\nneato -Tpdf \"%1\" -o out.pdf").arg(_graphSavingFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user