Skip to content

Commit ceebb24

Browse files
committed
fixed some edge cases
1 parent 25b687c commit ceebb24

File tree

3 files changed

+90
-49
lines changed

3 files changed

+90
-49
lines changed

corelib/include/rtabmap/core/Memory.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class RTABMAP_CORE_EXPORT Memory
144144
void saveLocationData(int locationId);
145145
void removeLink(int idA, int idB);
146146
void removeRawData(int id, bool image = true, bool scan = true, bool userData = true);
147-
int reduceNode(int id, float maxProximityDistance = 0.0f, bool keepLinkedInDb = false);
147+
int reduceNode(int id, float maxDistance = 0.0f, bool keepLinkedInDb = false);
148148

149149
//getters
150150
const std::map<int, double> & getWorkingMem() const {return _workingMem;}
@@ -278,6 +278,7 @@ class RTABMAP_CORE_EXPORT Memory
278278
void initCountId();
279279
void rehearsal(Signature * signature, Statistics * stats = 0);
280280
bool rehearsalMerge(int oldId, int newId);
281+
std::set<int> reduceNode(int id, float maxDistance, bool keepLinkedInDb, bool propagateNeighborMergedLinks);
281282

282283
const std::map<int, Signature*> & getSignatures() const {return _signatures;}
283284

corelib/src/Memory.cpp

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,47 +1185,57 @@ void Memory::addSignatureToWmFromLTM(Signature * signature)
11851185
}
11861186
}
11871187

1188-
int Memory::reduceNode(int id, float maxProximityDistance, bool keepLinkedInDb)
1188+
int Memory::reduceNode(int id, float maxDistance, bool keepLinkedInDb)
11891189
{
1190+
std::set<int> reducedTo = reduceNode(id, maxDistance, keepLinkedInDb, false);
1191+
return reducedTo.empty()?0:*reducedTo.rbegin();
1192+
}
1193+
1194+
bool canBeReduced(const Link & link, float maxDistance)
1195+
{
1196+
return link.to() != link.from() &&
1197+
link.type() != Link::kNeighbor &&
1198+
link.type() != Link::kNeighborMerged &&
1199+
link.userDataCompressed().empty() &&
1200+
link.type() != Link::kUndef &&
1201+
link.type() != Link::kVirtualClosure &&
1202+
(maxDistance==0 || link.transform().getNormSquared() < maxDistance*maxDistance);
1203+
}
1204+
1205+
std::set<int> Memory::reduceNode(int id, float maxDistance, bool keepLinkedInDb, bool propagateNeighborMergedLinks)
1206+
{
1207+
std::set<int> reducedTo;
11901208
Signature * s = this->_getSignature(id);
1191-
UASSERT(s!=0);
1209+
if(s==0)
1210+
{
1211+
UWARN("Node %d is not in WM/STM, cannot reduce it.", id);
1212+
return reducedTo;
1213+
}
11921214

11931215
if(!s->getLabel().empty())
11941216
{
11951217
// We currently not remove nodes with labels
1196-
return 0;
1218+
return reducedTo;
11971219
}
11981220

1199-
int reducedTo = 0;
1200-
bool merge = false;
12011221
const std::multimap<int, Link> & links = s->getLinks();
12021222
std::map<int, Link> neighbors;
12031223
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
12041224
{
1205-
if(!merge || iter->second.type() == Link::kGlobalClosure) // prioritize reducing to global loop closures
1206-
{
1207-
merge = iter->second.to() != iter->second.from() &&
1208-
iter->second.type() != Link::kNeighbor &&
1209-
iter->second.type() != Link::kNeighborMerged &&
1210-
iter->second.userDataCompressed().empty() &&
1211-
iter->second.type() != Link::kUndef &&
1212-
iter->second.type() != Link::kVirtualClosure &&
1213-
(maxProximityDistance==0 ||
1214-
(iter->second.type() == Link::kLocalSpaceClosure &&
1215-
iter->second.transform().getNormSquared() < maxProximityDistance*maxProximityDistance)); // in case of far lidar proximity links
1216-
if(merge)
1225+
if(canBeReduced(iter->second, maxDistance))
12171226
{
1218-
reducedTo = iter->second.to();
1219-
UDEBUG("Reduce %d to %d", s->id(), reducedTo);
1227+
reducedTo.insert(iter->second.to());
1228+
UDEBUG("Reduce %d to %d (distance=%f)", s->id(), iter->second.to(), iter->second.transform().getNorm());
12201229
}
1221-
}
1230+
12221231
if(iter->second.type() == Link::kNeighbor)
12231232
{
12241233
neighbors.insert(*iter);
12251234
}
12261235
}
1227-
if(merge)
1236+
if(!reducedTo.empty())
12281237
{
1238+
std::vector<int> propagateIds;
12291239
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
12301240
{
12311241
Signature * sTo = this->_getSignature(iter->first);
@@ -1234,20 +1244,21 @@ int Memory::reduceNode(int id, float maxProximityDistance, bool keepLinkedInDb)
12341244
UASSERT_MSG(sTo!=0, uFormat("id=%d", iter->first).c_str());
12351245
sTo->removeLink(s->id());
12361246
if(iter->second.type() != Link::kNeighbor &&
1237-
iter->second.type() != Link::kNeighborMerged &&
1247+
(iter->second.type() != Link::kNeighborMerged || propagateNeighborMergedLinks) &&
12381248
iter->second.type() != Link::kUndef)
12391249
{
12401250
// link to all neighbors
12411251
for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
12421252
{
12431253
if(!sTo->hasLink(jter->second.to()))
12441254
{
1245-
UDEBUG("Merging link %d->%d (type=%d) to link %d->%d (type %d)",
1246-
iter->second.from(), iter->second.to(), iter->second.type(),
1247-
jter->second.from(), jter->second.to(), jter->second.type());
12481255
Link l = iter->second.inverse().merge(
12491256
jter->second,
12501257
iter->second.userDataCompressed().empty() && iter->second.type() != Link::kVirtualClosure?Link::kNeighborMerged:iter->second.type());
1258+
UDEBUG("Merging link %d->%d (type=%d) to with %d->%d (type %d). Adding %d->%d (type %d) to %d and %d",
1259+
iter->second.to(), iter->second.from(), iter->second.type(),
1260+
jter->second.from(), jter->second.to(), jter->second.type(),
1261+
l.from(), l.to(), l.type(), sTo->id(), l.to());
12511262
sTo->addLink(l);
12521263
Signature * sB = this->_getSignature(l.to());
12531264
UASSERT(sB!=0);
@@ -1281,6 +1292,19 @@ int Memory::reduceNode(int id, float maxProximityDistance, bool keepLinkedInDb)
12811292
}
12821293
}
12831294
}
1295+
1296+
// Check if node merged to can also be reduced, if so, we have to propagate the neighbor merged links to the next node
1297+
if(reducedTo.find(sTo->id()) != reducedTo.end())
1298+
{
1299+
for(std::multimap<int, Link>::const_iterator lter=sTo->getLinks().begin(); lter!=sTo->getLinks().end(); ++lter)
1300+
{
1301+
if(canBeReduced(lter->second, maxDistance))
1302+
{
1303+
UDEBUG("Will progagate %d to %d (distance=%f)", sTo->id(), lter->second.to(), lter->second.transform().getNorm());
1304+
propagateIds.push_back(lter->second.to());
1305+
}
1306+
}
1307+
}
12841308
}
12851309
}
12861310

@@ -1300,6 +1324,15 @@ int Memory::reduceNode(int id, float maxProximityDistance, bool keepLinkedInDb)
13001324
s = 0;
13011325
_linksChanged = true;
13021326
_memoryChanged = true;
1327+
1328+
for(auto id: propagateIds)
1329+
{
1330+
//Nodes can be already reduced by other nodes, check if they are still there
1331+
if(getSignature(id) != 0)
1332+
{
1333+
reducedTo = reduceNode(id, maxDistance, keepLinkedInDb, true);
1334+
}
1335+
}
13031336
}
13041337
return reducedTo;
13051338
}

tools/ReduceGraph/main.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ void showUsage(const char * exec)
5454
"Options:\n"
5555
" --keep_latest Merge old nodes to newer nodes, thus keeping only latest nodes.\n"
5656
" --keep_linked Keep reduced nodes linked to graph.\n"
57-
"\n%s", exec, Parameters::showUsage());
57+
" --radius #.# Maximum loop closure distance that can be merged.\n"
58+
"\n", exec);
5859
exit(1);
5960
}
6061

@@ -70,6 +71,7 @@ int main(int argc, char * argv[])
7071

7172
bool keepLatest = false;
7273
bool keepLinked = false;
74+
float radius = 0.0f;
7375
for(int i=1; i<argc-1; ++i)
7476
{
7577
if(std::strcmp(argv[i], "--help") == 0)
@@ -84,10 +86,24 @@ int main(int argc, char * argv[])
8486
{
8587
keepLinked = uStr2Bool(argv[i]);
8688
}
89+
else if(std::strcmp(argv[i], "--radius") == 0)
90+
{
91+
++i;
92+
if(i < argc-1)
93+
{
94+
radius = uStr2Float(argv[i]);
95+
}
96+
else {
97+
showUsage(argv[0]);
98+
}
99+
}
87100
}
88-
ParametersMap inputParams = Parameters::parseArguments(argc, argv);
101+
102+
// Just parse logging options
103+
Parameters::parseArguments(argc, argv);
89104

90-
// Add some optimizations (soft set, can be overriden by arguments)
105+
// Add some optimizations
106+
ParametersMap inputParams;
91107
inputParams.insert(ParametersPair(Parameters::kMemInitWMWithAllNodes(), "true")); // load the whole map in RAM
92108
inputParams.insert(ParametersPair(Parameters::kMemLoadVisualLocalFeaturesOnInit(), "false")); // don't need features already loaded in RAM
93109
inputParams.insert(ParametersPair(Parameters::kKpNNStrategy(), "3")); // don't need flann index
@@ -96,6 +112,7 @@ int main(int argc, char * argv[])
96112
if(!UFile::exists(dbPath))
97113
{
98114
printf("Database %s doesn't exist!\n", dbPath.c_str());
115+
return 1;
99116
}
100117

101118
printf("\nDatabase: %s\n", dbPath.c_str());
@@ -114,11 +131,6 @@ int main(int argc, char * argv[])
114131
}
115132
delete driver;
116133

117-
for(ParametersMap::iterator iter=inputParams.begin(); iter!=inputParams.end(); ++iter)
118-
{
119-
printf(" Using parameter \"%s=%s\" from arguments\n", iter->first.c_str(), iter->second.c_str());
120-
}
121-
122134
Memory memory;
123135
printf("Initialization...\n");
124136
UTimer timer;
@@ -140,30 +152,25 @@ int main(int argc, char * argv[])
140152
Transform lastLocalizationPose;
141153
bool hasOptimizedPoses = !memory.loadOptimizedPoses(&lastLocalizationPose).empty();
142154

143-
float proximityMaxRadius = Parameters::defaultRGBDProximityPathFilteringRadius();
144-
Parameters::parse(parameters, Parameters::kRGBDProximityPathFilteringRadius(), proximityMaxRadius);
145155
int totalNodesReduced = 0;
156+
std::vector<int> vids;
157+
vids.reserve(ids.size());
146158
if(keepLatest)
147159
{
148160
// we process older to newer nodes, merging to new nodes
149-
for(std::set<int>::iterator iter = ids.begin(); iter!=ids.end(); ++iter)
150-
{
151-
int id = *iter;
152-
int reducedId = memory.reduceNode(id, proximityMaxRadius, keepLinked);
153-
if(reducedId > 0)
154-
{
155-
printf("Reduced node %d to node %d!\n", id, reducedId);
156-
++totalNodesReduced;
157-
}
158-
}
161+
vids.insert(vids.end(), ids.begin(), ids.end());
159162
}
160163
else
161164
{
162165
// we process newer to older nodes, merging to old nodes
163-
for(std::set<int>::reverse_iterator iter = ids.rbegin(); iter!=ids.rend(); ++iter)
166+
vids.insert(vids.end(), ids.rbegin(), ids.rend());
167+
}
168+
for(auto id: vids)
169+
{
170+
// Nodes can be already reduced by other nodes, check if they are still there
171+
if(memory.getSignature(id) != 0)
164172
{
165-
int id = *iter;
166-
int reducedId = memory.reduceNode(id, proximityMaxRadius, keepLinked);
173+
int reducedId = memory.reduceNode(id, radius, keepLinked);
167174
if(reducedId > 0)
168175
{
169176
printf("Reduced node %d to node %d!\n", id, reducedId);

0 commit comments

Comments
 (0)