rtabmap: added parameter to keep the old id or to update to new id when merging on rehearsal

git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@758 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
matlabbe
2013-01-27 04:50:49 +00:00
parent 635dd9c177
commit a4ccd6acd6
10 changed files with 156 additions and 111 deletions
+2 -1
View File
@@ -163,7 +163,8 @@ private:
bool _incrementalMemory; bool _incrementalMemory;
int _maxStMemSize; int _maxStMemSize;
float _recentWmRatio; float _recentWmRatio;
bool _dataMergedOnRehearsal; bool _oldDataKeptOnRehearsal;
bool _idUpdatedToNewOneRehearsal;
int _idCount; int _idCount;
Signature * _lastSignature; Signature * _lastSignature;
+2 -1
View File
@@ -144,7 +144,8 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Mem, STMSize, unsigned int, 30); // Short-term memory size RTABMAP_PARAM(Mem, STMSize, unsigned int, 30); // Short-term memory size
RTABMAP_PARAM(Mem, IncrementalMemory, bool, true); RTABMAP_PARAM(Mem, IncrementalMemory, bool, true);
RTABMAP_PARAM(Mem, RecentWmRatio, float, 0.2); // Ratio of locations after the last loop closure in WM that cannot be transferred RTABMAP_PARAM(Mem, RecentWmRatio, float, 0.2); // Ratio of locations after the last loop closure in WM that cannot be transferred
RTABMAP_PARAM(Mem, DataMergedOnRehearsal, bool, true); // Merge data on rehearsal RTABMAP_PARAM(Mem, RehearsalOldDataKept, bool, true); // On merge, keep old data
RTABMAP_PARAM(Mem, RehearsalIdUpdatedToNewOne, bool, true); // On merge, update to new id
// KeypointMemory (Keypoint-based) // KeypointMemory (Keypoint-based)
RTABMAP_PARAM(Kp, PublishKeypoints, bool, true); // Publishing keypoints RTABMAP_PARAM(Kp, PublishKeypoints, bool, true); // Publishing keypoints
+2 -1
View File
@@ -94,8 +94,9 @@ public:
std::map<int, int> getWeights(); std::map<int, int> getWeights();
int getTotalMemSize(); int getTotalMemSize();
double getLastProcessTime() const {return _lastProcessTime;}; double getLastProcessTime() const {return _lastProcessTime;};
std::multimap<int, cv::KeyPoint> getWords(int nodeId); std::multimap<int, cv::KeyPoint> getWords(int locationId);
std::map<int, int> getNeighbors(int nodeId, int margin, bool lookInLTM = false); std::map<int, int> getNeighbors(int nodeId, int margin, bool lookInLTM = false);
bool isInSTM(int locationId);
void setTimeThreshold(float maxTimeAllowed); // in ms void setTimeThreshold(float maxTimeAllowed); // in ms
+2 -1
View File
@@ -1106,6 +1106,7 @@ void DBDriverSqlite3::loadNeighborsQuery(int signatureId, std::set<int> & neighb
query << "SELECT to_id FROM Link " query << "SELECT to_id FROM Link "
<< "WHERE from_id = " << signatureId << "WHERE from_id = " << signatureId
<< " AND type = 0"
<< " ORDER BY to_id"; << " ORDER BY to_id";
rc = sqlite3_prepare_v2(_ppDb, query.str().c_str(), -1, &ppStmt, 0); rc = sqlite3_prepare_v2(_ppDb, query.str().c_str(), -1, &ppStmt, 0);
@@ -1133,7 +1134,7 @@ void DBDriverSqlite3::loadNeighborsQuery(int signatureId, std::set<int> & neighb
if(neighbors.size() == 0) if(neighbors.size() == 0)
{ {
UERROR("No neighbors loaded from signature %d", signatureId); //UERROR("No neighbors loaded from signature %d", signatureId);
} }
} }
} }
+87 -66
View File
@@ -47,7 +47,8 @@ Memory::Memory(const ParametersMap & parameters) :
_incrementalMemory(Parameters::defaultMemIncrementalMemory()), _incrementalMemory(Parameters::defaultMemIncrementalMemory()),
_maxStMemSize(Parameters::defaultMemSTMSize()), _maxStMemSize(Parameters::defaultMemSTMSize()),
_recentWmRatio(Parameters::defaultMemRecentWmRatio()), _recentWmRatio(Parameters::defaultMemRecentWmRatio()),
_dataMergedOnRehearsal(Parameters::defaultMemDataMergedOnRehearsal()), _oldDataKeptOnRehearsal(Parameters::defaultMemRehearsalOldDataKept()),
_idUpdatedToNewOneRehearsal(Parameters::defaultMemRehearsalIdUpdatedToNewOne()),
_idCount(kIdStart), _idCount(kIdStart),
_lastSignature(0), _lastSignature(0),
_lastLoopClosureId(0), _lastLoopClosureId(0),
@@ -259,15 +260,26 @@ void Memory::parseParameters(const ParametersMap & parameters)
{ {
this->setRecentWmRatio(std::atof((*iter).second.c_str())); this->setRecentWmRatio(std::atof((*iter).second.c_str()));
} }
if((iter=parameters.find(Parameters::kMemDataMergedOnRehearsal())) != parameters.end()) if((iter=parameters.find(Parameters::kMemRehearsalOldDataKept())) != parameters.end())
{ {
_dataMergedOnRehearsal = uStr2Bool((*iter).second.c_str()); _oldDataKeptOnRehearsal = uStr2Bool((*iter).second.c_str());
}
if((iter=parameters.find(Parameters::kMemRehearsalIdUpdatedToNewOne())) != parameters.end())
{
_idUpdatedToNewOneRehearsal = uStr2Bool((*iter).second.c_str());
} }
if(_dbDriver) if(_dbDriver)
{ {
_dbDriver->parseParameters(parameters); _dbDriver->parseParameters(parameters);
} }
// verification...
if(!_idUpdatedToNewOneRehearsal && !_rehearsalOnlyWithLast)
{
UWARN("if _idUpdatedToNewOneRehearsal=false, _rehearsalOnlyWithLast must be true");
_rehearsalOnlyWithLast = true;
}
// Keypoint stuff // Keypoint stuff
if(_vwd) if(_vwd)
@@ -1348,13 +1360,10 @@ void Memory::moveToTrash(Signature * s)
// neighbor to s // neighbor to s
if(n) if(n)
{ {
std::set<int>::const_iterator jter = n->getNeighbors().find(s->id()); n->removeNeighbor(s->id());
if(jter != n->getNeighbors().end())
{
n->removeNeighbor(s->id());
}
} }
} }
s->removeNeighbors();
} }
if( _dbDriver && if( _dbDriver &&
@@ -1390,85 +1399,77 @@ bool Memory::addLoopClosureLink(int oldId, int newId)
return true; return true;
} }
// Set loop closure link
oldS->addLoopClosureId(newS->id());
UDEBUG("Add loop closure link between %d and %d", oldS->id(), newS->id()); UDEBUG("Add loop closure link between %d and %d", oldS->id(), newS->id());
bool onRehearsal = this->isInSTM(oldS->id()); bool onRehearsal = this->isInSTM(oldS->id());
if(!onRehearsal) if(!onRehearsal)
{ {
// During loop closure in WM // During loop closure in WM
oldS->addLoopClosureId(newS->id());
newS->addChildLoopClosureId(oldS->id()); newS->addChildLoopClosureId(oldS->id());
_lastLoopClosureId = newS->id(); _lastLoopClosureId = newS->id();
newS->setWeight(newS->getWeight() + oldS->getWeight()); newS->setWeight(newS->getWeight() + oldS->getWeight());
oldS->setWeight(0); oldS->setWeight(0);
return true; return true; // RETURN
} }
else
// During rehearsal in STM
if(_idUpdatedToNewOneRehearsal)
{ {
UDEBUG("On rehearsal"); // update weight
// During rehearsal in STM... newS->setWeight(newS->getWeight() + 1 + oldS->getWeight());
// Here we merge the new location with the old one,
// redirecting all neighbor links to new location. oldS->addLoopClosureId(newS->id()); // to keep track of the merged location
if(_lastLoopClosureId == oldS->id()) if(_lastLoopClosureId == oldS->id())
{ {
_lastLoopClosureId = newS->id(); _lastLoopClosureId = newS->id();
} }
}
else
{
// update weight // update weight
newS->setWeight(newS->getWeight() + 1 + oldS->getWeight()); oldS->setWeight(newS->getWeight() + 1 + oldS->getWeight());
// redirect all baseIds from old id to new id newS->addLoopClosureId(oldS->id()); // to keep track of the merged location
for(std::set<int>::iterator iter=_stMem.begin(); iter!=_stMem.end(); ++iter)
if(_lastSignature == newS)
{ {
Signature * s = _getSignature(*iter); _lastSignature = oldS;
if(s)
{
s->changeNeighborIds(oldS->id(), newS->id());
}
else if(!s)
{
UERROR("Location %d is not in RAM?!?", *iter);
}
} }
} }
UDEBUG(""); if(_idUpdatedToNewOneRehearsal)
// redirect neighbor links
std::set<int> neighbors = oldS->getNeighbors();
for(std::set<int>::const_iterator iter = neighbors.begin(); iter!=neighbors.end(); ++iter)
{ {
int link = *iter; // redirect neighbor links
if(link != newS->id() && link != oldS->id()) std::set<int> neighbors = oldS->getNeighbors();
for(std::set<int>::const_iterator iter = neighbors.begin(); iter!=neighbors.end(); ++iter)
{ {
Signature * s = this->_getSignature(link); int link = *iter;
if(s) if(link != newS->id() && link != oldS->id())
{ {
// modify neighbor "from" Signature * s = this->_getSignature(link);
s->changeNeighborIds(oldS->id(), newS->id()); if(s)
if(!newS->hasNeighbor(link))
{ {
newS->addNeighbor(link); // modify neighbor "from"
s->changeNeighborIds(oldS->id(), newS->id());
if(!newS->hasNeighbor(link))
{
newS->addNeighbor(link);
}
}
else
{
UERROR("Didn't find neighbor %d of %d in RAM...", link, oldS->id());
} }
} }
else
{
UERROR("Didn't find neighbor %d of %d in RAM...", link, oldS->id());
}
} }
oldS->removeNeighbors();
if(link == newS->id())
{
oldS->removeNeighbor(link);
}
}
if(onRehearsal)
{
// redirect child loop closure links // redirect child loop closure links
const std::set<int> & childIds = oldS->getChildLoopClosureIds(); std::set<int> childIds = oldS->getChildLoopClosureIds();
for(std::set<int>::const_iterator iter = childIds.begin(); iter!=childIds.end(); ++iter) for(std::set<int>::iterator iter = childIds.begin(); iter!=childIds.end(); ++iter)
{ {
if(*iter == newS->id()) if(*iter == newS->id())
{ {
@@ -1486,18 +1487,27 @@ bool Memory::addLoopClosureLink(int oldId, int newId)
{ {
UERROR("A location (%d, child of %d) in WM/STM cannot be transferred if its loop closure id is in STM", *iter, oldS->id()); UERROR("A location (%d, child of %d) in WM/STM cannot be transferred if its loop closure id is in STM", *iter, oldS->id());
} }
oldS->removeChildLoopClosureId(*iter);
} }
if(_dataMergedOnRehearsal)
{
this->copyData(oldS, newS);
// Set old image to new signature
}
// remove old location
moveToTrash(oldS);
} }
//remove mutual links
oldS->removeNeighbor(newId);
newS->removeNeighbor(oldId);
if(_oldDataKeptOnRehearsal && _idUpdatedToNewOneRehearsal)
{
// Set old image to new signature
this->copyData(oldS, newS);
}
else if(!_oldDataKeptOnRehearsal && !_idUpdatedToNewOneRehearsal)
{
this->copyData(newS, oldS);
}
// remove location
moveToTrash(_idUpdatedToNewOneRehearsal?oldS:newS);
return true; return true;
} }
else else
@@ -1755,7 +1765,14 @@ void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
if(id!=*iter) if(id!=*iter)
{ {
int weightNeighbor = 0; int weightNeighbor = 0;
_dbDriver->getWeight(*iter, weightNeighbor); if(_signatures.find(*iter) == _signatures.end())
{
_dbDriver->getWeight(*iter, weightNeighbor);
}
else
{
weightNeighbor = _signatures.find(*iter)->second->getWeight();
}
UDEBUG("Add neighbor link from %d to %d", id, *iter); UDEBUG("Add neighbor link from %d to %d", id, *iter);
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\"\n", fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\"\n",
id, id,
@@ -1777,6 +1794,7 @@ void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
{ {
weightNeighbor = _signatures.find(*iter)->second->getWeight(); weightNeighbor = _signatures.find(*iter)->second->getWeight();
} }
UDEBUG("Add loop link from %d to %d", id, *iter);
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n", fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n",
id, id,
weight, weight,
@@ -1795,6 +1813,7 @@ void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
{ {
weightNeighbor = _signatures.find(*iter)->second->getWeight(); weightNeighbor = _signatures.find(*iter)->second->getWeight();
} }
UDEBUG("Add child link from %d to %d", id, *iter);
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n", fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n",
id, id,
weight, weight,
@@ -1850,6 +1869,7 @@ void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
{ {
weightNeighbor = _signatures.find(*iter)->second->getWeight(); weightNeighbor = _signatures.find(*iter)->second->getWeight();
} }
UDEBUG("Add loop link from %d to %d", id, *iter);
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n", fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"L\", fontcolor=%s, fontsize=8];\n",
id, id,
weight, weight,
@@ -1871,6 +1891,7 @@ void Memory::generateGraph(const std::string & fileName, std::set<int> ids)
{ {
weightNeighbor = _signatures.find(*iter)->second->getWeight(); weightNeighbor = _signatures.find(*iter)->second->getWeight();
} }
UDEBUG("Add child link from %d to %d", id, *iter);
fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n", fprintf(fout, " \"%d\\n%d\" -> \"%d\\n%d\" [label=\"C\", fontcolor=%s, fontsize=8];\n",
id, id,
weight, weight,
+19 -18
View File
@@ -468,12 +468,11 @@ std::map<int, int> Rtabmap::getWeights()
std::set<int> Rtabmap::getSTM() std::set<int> Rtabmap::getSTM()
{ {
UScopeMutex s(&_threadMutex); UScopeMutex s(&_threadMutex);
std::set<int> mem;
if(_memory) if(_memory)
{ {
mem = _memory->getStMem(); return _memory->getStMem();
} }
return mem; return std::set<int>();
} }
int Rtabmap::getSTMSize() int Rtabmap::getSTMSize()
@@ -489,47 +488,49 @@ int Rtabmap::getSTMSize()
int Rtabmap::getTotalMemSize() int Rtabmap::getTotalMemSize()
{ {
UScopeMutex s(&_threadMutex); UScopeMutex s(&_threadMutex);
ULOGGER_DEBUG("");
int memSize = 0;
if(_memory) if(_memory)
{ {
const Signature * s =_memory->getLastSignature(); const Signature * s =_memory->getLastSignature();
if(s) if(s)
{ {
memSize = s->id(); return s->id();
} }
} }
return memSize; return 0;
} }
std::multimap<int, cv::KeyPoint> Rtabmap::getWords(int nodeId) std::multimap<int, cv::KeyPoint> Rtabmap::getWords(int locationId)
{ {
UScopeMutex s(&_threadMutex); UScopeMutex s(&_threadMutex);
std::multimap<int, cv::KeyPoint> words;
if(_memory) if(_memory)
{ {
const Signature * s = _memory->getSignature(nodeId); const Signature * s = _memory->getSignature(locationId);
if(s) if(s)
{ {
words = s->getWords(); return s->getWords();
} }
} }
return std::multimap<int, cv::KeyPoint>();
return words;
} }
std::map<int, int> Rtabmap::getNeighbors(int nodeId, int margin, bool lookInLTM) std::map<int, int> Rtabmap::getNeighbors(int nodeId, int margin, bool lookInLTM)
{ {
UScopeMutex s(&_threadMutex); UScopeMutex s(&_threadMutex);
std::map<int, int> ids;
if(_memory) if(_memory)
{ {
ids = _memory->getNeighborsId(nodeId, margin, lookInLTM?-1:0); return _memory->getNeighborsId(nodeId, margin, lookInLTM?-1:0);
} }
return std::map<int, int>();
}
return ids; bool Rtabmap::isInSTM(int locationId)
{
UScopeMutex s(&_threadMutex);
if(_memory)
{
return _memory->isInSTM(locationId);
}
return false;
} }
void Rtabmap::clearBufferedSensors() void Rtabmap::clearBufferedSensors()
+1
View File
@@ -59,6 +59,7 @@ public:
void setLoopClosureIds(const std::set<int> & loopClosureIds) {_loopClosureIds = loopClosureIds;_neighborsModified=true;} void setLoopClosureIds(const std::set<int> & loopClosureIds) {_loopClosureIds = loopClosureIds;_neighborsModified=true;}
void addLoopClosureId(int loopClosureId) {if(loopClosureId && _loopClosureIds.insert(loopClosureId).second)_neighborsModified=true;} void addLoopClosureId(int loopClosureId) {if(loopClosureId && _loopClosureIds.insert(loopClosureId).second)_neighborsModified=true;}
void removeLoopClosureId(int loopClosureId) {if(loopClosureId && _loopClosureIds.erase(loopClosureId))_neighborsModified=true;} void removeLoopClosureId(int loopClosureId) {if(loopClosureId && _loopClosureIds.erase(loopClosureId))_neighborsModified=true;}
void removeChildLoopClosureId(int childLoopClosureId) {if(childLoopClosureId && _childLoopClosureIds.erase(childLoopClosureId))_neighborsModified=true;}
bool hasLoopClosureId(int loopClosureId) const {return _loopClosureIds.find(loopClosureId) != _loopClosureIds.end();} bool hasLoopClosureId(int loopClosureId) const {return _loopClosureIds.find(loopClosureId) != _loopClosureIds.end();}
void setChildLoopClosureIds(std::set<int> & childLoopClosureIds) {_childLoopClosureIds = childLoopClosureIds;_neighborsModified=true;} void setChildLoopClosureIds(std::set<int> & childLoopClosureIds) {_childLoopClosureIds = childLoopClosureIds;_neighborsModified=true;}
void addChildLoopClosureId(int childLoopClosureId) {if(childLoopClosureId && _childLoopClosureIds.insert(childLoopClosureId).second)_neighborsModified=true;} void addChildLoopClosureId(int childLoopClosureId) {if(childLoopClosureId && _childLoopClosureIds.insert(childLoopClosureId).second)_neighborsModified=true;}
+2 -1
View File
@@ -155,7 +155,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->doubleSpinBox_similarityThreshold->setObjectName(Parameters::kMemRehearsalSimilarity().c_str()); _ui->doubleSpinBox_similarityThreshold->setObjectName(Parameters::kMemRehearsalSimilarity().c_str());
_ui->general_checkBox_incrementalMemory->setObjectName(Parameters::kMemIncrementalMemory().c_str()); _ui->general_checkBox_incrementalMemory->setObjectName(Parameters::kMemIncrementalMemory().c_str());
_ui->general_doubleSpinBox_recentWmRatio->setObjectName(Parameters::kMemRecentWmRatio().c_str()); _ui->general_doubleSpinBox_recentWmRatio->setObjectName(Parameters::kMemRecentWmRatio().c_str());
_ui->general_checkBox_dataMergedOnRehearsal->setObjectName(Parameters::kMemDataMergedOnRehearsal().c_str()); _ui->general_checkBox_RehearsalOldDataKept->setObjectName(Parameters::kMemRehearsalOldDataKept().c_str());
_ui->general_checkBox_RehearsalIdUpdatedToNewOne->setObjectName(Parameters::kMemRehearsalIdUpdatedToNewOne().c_str());
// Database // Database
_ui->general_checkBox_imagesCompressed->setObjectName(Parameters::kDbImagesCompressed().c_str()); _ui->general_checkBox_imagesCompressed->setObjectName(Parameters::kDbImagesCompressed().c_str());
+38 -21
View File
@@ -86,7 +86,7 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>4</number> <number>7</number>
</property> </property>
<widget class="QWidget" name="page_22"> <widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29"> <layout class="QVBoxLayout" name="verticalLayout_29">
@@ -1864,9 +1864,9 @@ see Sqlite3 doc 'PRAGMA temp_store'.</string>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_119">
<property name="text"> <property name="text">
<string>Only compare to the last signature in STM, otherwise all signatures in STM are compared.</string> <string>On merging, keep old data. The similarity threshold may be lower than updating to new data.</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@@ -1874,24 +1874,7 @@ see Sqlite3 doc 'PRAGMA temp_store'.</string>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QCheckBox" name="general_checkBox_similarityOnlyLast"> <widget class="QCheckBox" name="general_checkBox_RehearsalOldDataKept">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_119">
<property name="text">
<string>The data of the new location is cleared, then old location's data is copied back to new one. The similarity threshold may be also lower than without data copied.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="general_checkBox_dataMergedOnRehearsal">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@@ -1907,6 +1890,40 @@ see Sqlite3 doc 'PRAGMA temp_store'.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1">
<widget class="QLabel" name="label_19">
<property name="text">
<string>On merging, update to new id.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="general_checkBox_RehearsalIdUpdatedToNewOne">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="general_checkBox_similarityOnlyLast">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Only compare to the last signature in STM, otherwise all signatures in STM are compared.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>