@@ -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}
0 commit comments