2018-11-06 17:19:16 -05:00
|
|
|
/*
|
|
|
|
|
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
* Neither the name of the Universite de Sherbrooke nor the
|
|
|
|
|
names of its contributors may be used to endorse or promote products
|
|
|
|
|
derived from this software without specific prior written permission.
|
|
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
|
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <rtabmap/core/DBDriver.h>
|
|
|
|
|
#include <rtabmap/core/Rtabmap.h>
|
2022-09-30 15:48:09 -07:00
|
|
|
#include <rtabmap/core/Memory.h>
|
2023-12-17 22:44:11 -08:00
|
|
|
#include <rtabmap/core/global_map/OccupancyGrid.h>
|
2018-11-06 17:19:16 -05:00
|
|
|
#include <rtabmap/core/util3d.h>
|
|
|
|
|
#include <rtabmap/core/util3d_filtering.h>
|
|
|
|
|
#include <rtabmap/core/util3d_transforms.h>
|
|
|
|
|
#include <rtabmap/core/util3d_surface.h>
|
|
|
|
|
#include <rtabmap/utilite/UMath.h>
|
|
|
|
|
#include <rtabmap/utilite/UTimer.h>
|
|
|
|
|
#include <rtabmap/utilite/UFile.h>
|
2019-11-03 14:10:02 -05:00
|
|
|
#include <rtabmap/utilite/UStl.h>
|
2018-11-06 17:19:16 -05:00
|
|
|
#include <pcl/filters/filter.h>
|
|
|
|
|
#include <pcl/io/ply_io.h>
|
|
|
|
|
#include <pcl/io/obj_io.h>
|
|
|
|
|
#include <pcl/common/common.h>
|
|
|
|
|
#include <pcl/surface/poisson.h>
|
|
|
|
|
#include <stdio.h>
|
2019-03-27 16:12:49 -04:00
|
|
|
#include <signal.h>
|
2018-11-06 17:19:16 -05:00
|
|
|
|
|
|
|
|
using namespace rtabmap;
|
|
|
|
|
|
|
|
|
|
void showUsage()
|
|
|
|
|
{
|
|
|
|
|
printf("\nUsage:\n"
|
|
|
|
|
"rtabmap-detectMoreLoopClosures [options] database.db\n"
|
|
|
|
|
"Options:\n"
|
|
|
|
|
" -r # Cluster radius (default 1 m).\n"
|
2021-03-13 18:42:13 -05:00
|
|
|
" -rx # Cluster radius min (default 0 m).\n"
|
2018-11-06 17:19:16 -05:00
|
|
|
" -a # Cluster angle (default 30 deg).\n"
|
|
|
|
|
" -i # Iterations (default 1).\n"
|
|
|
|
|
" --intra Add only intra-session loop closures.\n"
|
|
|
|
|
" --inter Add only inter-session loop closures.\n"
|
2026-02-13 10:49:12 -08:00
|
|
|
" --session # Add loop closures only from/to that map session ID (use -1 for last session).\n"
|
2019-11-03 14:10:02 -05:00
|
|
|
"\n%s", Parameters::showUsage());
|
2018-11-06 17:19:16 -05:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 15:39:46 -04:00
|
|
|
bool g_loopForever = true;
|
2018-11-06 17:19:16 -05:00
|
|
|
class PrintProgressState : public ProgressState
|
|
|
|
|
{
|
|
|
|
|
public:
|
2026-02-13 10:49:12 -08:00
|
|
|
PrintProgressState() :
|
|
|
|
|
stamp_(UTimer::now())
|
|
|
|
|
{}
|
2018-11-06 17:19:16 -05:00
|
|
|
virtual bool callback(const std::string & msg) const
|
|
|
|
|
{
|
|
|
|
|
if(!msg.empty())
|
2026-02-13 10:49:12 -08:00
|
|
|
printf("[%f] %s \n", UTimer::now()-stamp_, msg.c_str());
|
2019-03-27 15:39:46 -04:00
|
|
|
return g_loopForever;
|
2018-11-06 17:19:16 -05:00
|
|
|
}
|
2026-02-13 10:49:12 -08:00
|
|
|
private:
|
|
|
|
|
double stamp_;
|
2018-11-06 17:19:16 -05:00
|
|
|
};
|
2026-04-04 19:48:03 -07:00
|
|
|
PrintProgressState progress;
|
|
|
|
|
|
|
|
|
|
// catch ctrl-c
|
|
|
|
|
void sighandler(int sig)
|
|
|
|
|
{
|
|
|
|
|
printf("\nSignal %d caught...\n", sig);
|
|
|
|
|
g_loopForever = false;
|
|
|
|
|
progress.setCanceled(true);
|
|
|
|
|
}
|
2018-11-06 17:19:16 -05:00
|
|
|
|
|
|
|
|
int main(int argc, char * argv[])
|
|
|
|
|
{
|
2019-03-27 15:39:46 -04:00
|
|
|
signal(SIGABRT, &sighandler);
|
|
|
|
|
signal(SIGTERM, &sighandler);
|
|
|
|
|
signal(SIGINT, &sighandler);
|
|
|
|
|
|
2018-11-06 17:19:16 -05:00
|
|
|
ULogger::setType(ULogger::kTypeConsole);
|
2026-04-04 19:48:03 -07:00
|
|
|
ULogger::setLevel(ULogger::kWarning);
|
2018-11-06 17:19:16 -05:00
|
|
|
|
|
|
|
|
if(argc < 2)
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-13 18:42:13 -05:00
|
|
|
float clusterRadiusMin = 0.0f;
|
|
|
|
|
float clusterRadiusMax = 1.0f;
|
2018-11-06 17:19:16 -05:00
|
|
|
float clusterAngle = CV_PI/6.0f;
|
|
|
|
|
int iterations = 1;
|
|
|
|
|
bool intraSession = false;
|
|
|
|
|
bool interSession = false;
|
2026-02-13 10:49:12 -08:00
|
|
|
int fromToMapId = -2;
|
2018-11-06 17:19:16 -05:00
|
|
|
for(int i=1; i<argc-1; ++i)
|
|
|
|
|
{
|
2019-11-03 14:10:02 -05:00
|
|
|
if(std::strcmp(argv[i], "--help") == 0)
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
else if(std::strcmp(argv[i], "--intra") == 0)
|
2018-11-06 17:19:16 -05:00
|
|
|
{
|
|
|
|
|
intraSession = true;
|
|
|
|
|
if(interSession)
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(std::strcmp(argv[i], "--inter") == 0)
|
|
|
|
|
{
|
|
|
|
|
interSession = true;
|
|
|
|
|
if(intraSession)
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(std::strcmp(argv[i], "-r") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if(i<argc-1)
|
|
|
|
|
{
|
2021-03-13 18:42:13 -05:00
|
|
|
clusterRadiusMax = uStr2Float(argv[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(std::strcmp(argv[i], "-rx") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if(i<argc-1)
|
|
|
|
|
{
|
|
|
|
|
clusterRadiusMin = uStr2Float(argv[i]);
|
2018-11-06 17:19:16 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(std::strcmp(argv[i], "-a") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if(i<argc-1)
|
|
|
|
|
{
|
|
|
|
|
clusterAngle = uStr2Float(argv[i])*CV_PI/180.0f;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(std::strcmp(argv[i], "-i") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if(i<argc-1)
|
|
|
|
|
{
|
|
|
|
|
iterations = uStr2Int(argv[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-13 10:49:12 -08:00
|
|
|
else if(std::strcmp(argv[i], "--session") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if(i<argc-1)
|
|
|
|
|
{
|
|
|
|
|
fromToMapId = uStr2Int(argv[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-06 17:19:16 -05:00
|
|
|
}
|
2019-11-03 14:10:02 -05:00
|
|
|
ParametersMap inputParams = Parameters::parseArguments(argc, argv);
|
2018-11-06 17:19:16 -05:00
|
|
|
|
2026-02-13 10:49:12 -08:00
|
|
|
// Add some optimizations (soft set, can be overriden by arguments)
|
|
|
|
|
inputParams.insert(ParametersPair(Parameters::kMemLoadVisualLocalFeaturesOnInit(), "false")); // don't need features already loaded in RAM
|
2026-04-04 19:48:03 -07:00
|
|
|
inputParams.insert(ParametersPair(Parameters::kMemIncrementalMemory(), "true")); // should be incremental to update links
|
2026-02-13 10:49:12 -08:00
|
|
|
|
2018-11-06 17:19:16 -05:00
|
|
|
std::string dbPath = argv[argc-1];
|
2019-04-18 19:50:58 -04:00
|
|
|
if(!UFile::exists(dbPath))
|
|
|
|
|
{
|
|
|
|
|
printf("Database %s doesn't exist!\n", dbPath.c_str());
|
|
|
|
|
}
|
2018-11-06 17:19:16 -05:00
|
|
|
|
|
|
|
|
printf("\nDatabase: %s\n", dbPath.c_str());
|
2021-03-13 18:42:13 -05:00
|
|
|
printf("Cluster radius min = %f m\n", clusterRadiusMin);
|
|
|
|
|
printf("Cluster radius max = %f m\n", clusterRadiusMax);
|
2018-11-06 17:19:16 -05:00
|
|
|
printf("Cluster angle = %f deg\n", clusterAngle*180.0f/CV_PI);
|
|
|
|
|
if(intraSession)
|
|
|
|
|
{
|
|
|
|
|
printf("Intra-session only\n");
|
|
|
|
|
}
|
|
|
|
|
else if(interSession)
|
|
|
|
|
{
|
|
|
|
|
printf("Inter-session only\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!intraSession && !interSession)
|
|
|
|
|
{
|
|
|
|
|
intraSession = true;
|
|
|
|
|
interSession = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get parameters
|
|
|
|
|
ParametersMap parameters;
|
|
|
|
|
DBDriver * driver = DBDriver::create();
|
|
|
|
|
if(driver->openConnection(dbPath))
|
|
|
|
|
{
|
|
|
|
|
parameters = driver->getLastParameters();
|
|
|
|
|
driver->closeConnection(false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UERROR("Cannot open database %s!", dbPath.c_str());
|
|
|
|
|
}
|
|
|
|
|
delete driver;
|
|
|
|
|
|
2021-10-11 13:52:55 -04:00
|
|
|
for(ParametersMap::iterator iter=inputParams.begin(); iter!=inputParams.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
printf(" Using parameter \"%s=%s\" from arguments\n", iter->first.c_str(), iter->second.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 17:19:16 -05:00
|
|
|
// Get the global optimized map
|
|
|
|
|
Rtabmap rtabmap;
|
|
|
|
|
printf("Initialization...\n");
|
2026-02-13 10:49:12 -08:00
|
|
|
UTimer timer;
|
2026-04-04 19:48:03 -07:00
|
|
|
ParametersMap originalParameters = parameters;
|
2019-11-03 14:10:02 -05:00
|
|
|
uInsert(parameters, inputParams);
|
2026-07-29 08:19:13 -07:00
|
|
|
|
|
|
|
|
// This avoids to load original descriptors in the dictionary
|
|
|
|
|
// to save RAM and intialization time (we don't need the dictionary for this tool)
|
|
|
|
|
rtabmap.setDummyDictionary(true); // should be set before Rtabmap::init()
|
|
|
|
|
|
2018-11-06 17:19:16 -05:00
|
|
|
rtabmap.init(parameters, dbPath);
|
2026-02-13 10:49:12 -08:00
|
|
|
printf("Initialization... done! (%f sec)\n", timer.ticks());
|
2018-11-06 17:19:16 -05:00
|
|
|
|
2026-07-29 08:19:13 -07:00
|
|
|
// detectMoreLoopClosures would clear the optimized map if loop closures are detected
|
2022-09-30 15:48:09 -07:00
|
|
|
float xMin, yMin, cellSize;
|
|
|
|
|
bool haveOptimizedMap = !rtabmap.getMemory()->load2DMap(xMin, yMin, cellSize).empty();
|
|
|
|
|
|
2026-02-13 10:49:12 -08:00
|
|
|
if(fromToMapId <= -2)
|
|
|
|
|
{
|
|
|
|
|
fromToMapId = -1; // means all below
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bool last = false;
|
|
|
|
|
if(fromToMapId == -1)
|
|
|
|
|
{
|
|
|
|
|
// get last session ID
|
|
|
|
|
fromToMapId = rtabmap.getMemory()->getMapId(rtabmap.getMemory()->getLastSignatureId(), true);
|
|
|
|
|
}
|
|
|
|
|
printf("From/To Session ID = %d%s\n", fromToMapId, last?" (last session)":"");
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-06 17:19:16 -05:00
|
|
|
printf("Detecting...\n");
|
2026-02-13 10:49:12 -08:00
|
|
|
int detected = rtabmap.detectMoreLoopClosures(clusterRadiusMax, clusterAngle, iterations, intraSession, interSession, &progress, clusterRadiusMin, fromToMapId);
|
2018-11-06 17:19:16 -05:00
|
|
|
if(detected < 0)
|
|
|
|
|
{
|
2019-03-27 15:39:46 -04:00
|
|
|
if(!g_loopForever)
|
|
|
|
|
{
|
|
|
|
|
printf("Detection interrupted. Loop closures found so far (if any) are not saved.\n");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
printf("Loop closure detection failed!\n");
|
|
|
|
|
}
|
2018-11-06 17:19:16 -05:00
|
|
|
}
|
2022-09-30 15:48:09 -07:00
|
|
|
else if(detected > 0 && haveOptimizedMap)
|
|
|
|
|
{
|
|
|
|
|
printf("The database has a global occupancy grid, regenerating one with new optimized graph!\n");
|
2023-12-17 22:44:11 -08:00
|
|
|
LocalGridCache cache;
|
|
|
|
|
OccupancyGrid grid(&cache, parameters);
|
2022-09-30 15:48:09 -07:00
|
|
|
std::map<int, Transform> optimizedPoses = rtabmap.getLocalOptimizedPoses();
|
|
|
|
|
for(std::map<int, Transform>::iterator iter=optimizedPoses.lower_bound(0); iter!=optimizedPoses.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
SensorData data = rtabmap.getMemory()->getNodeData(iter->first, false, false, false, true);
|
|
|
|
|
data.uncompressData();
|
2023-12-17 22:44:11 -08:00
|
|
|
cache.add(iter->first, data.gridGroundCellsRaw(), data.gridObstacleCellsRaw(), data.gridEmptyCellsRaw(), data.gridCellSize(), data.gridViewPoint());
|
2022-09-30 15:48:09 -07:00
|
|
|
}
|
|
|
|
|
grid.update(optimizedPoses);
|
|
|
|
|
cv::Mat map = grid.getMap(xMin, yMin);
|
|
|
|
|
if(map.empty())
|
|
|
|
|
{
|
|
|
|
|
printf("Could not generate the global occupancy grid!\n");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rtabmap.getMemory()->save2DMap(map, xMin, yMin, cellSize);
|
|
|
|
|
printf("Save new global occupancy grid!\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-06 17:19:16 -05:00
|
|
|
|
2026-04-04 19:48:03 -07:00
|
|
|
// Restore original parameters before saving back the database
|
|
|
|
|
rtabmap.parseParameters(originalParameters);
|
|
|
|
|
|
2026-07-29 08:19:13 -07:00
|
|
|
rtabmap.close(detected>0);
|
2018-11-06 17:19:16 -05:00
|
|
|
|
Adding doc and tests (#1492)
* added doc and tests for util2d.h
* updated cmake-ros ci
* Added util3d.h doc and tests
* util3d_transforms.h: Added doc and tests
* util3d_filtering.h: started doc and test
* util3d_filtering.h: more tests and doc
* Added more doc/tests
* finished util3d_filtering doc and tests
* added test for util2d::depthBleedingFiltering
* Added util3d_registration tests
* Added util3d_features.h doc/tests
* added doc/tests for util3d_correspondences.h
* added doc/gtest for util3d_mapping.h (missing hpp functions)
* finished testing util3d_mapping.hpp
* Added util3d_motion_estimation.h tests (2D->3D done)
* finished util3d_motion_estimation.h tests
* minimal util3d_surface.h
* Added Transform and VisualWord tests
* Added doc for CameraModel and StereoCameraModel
* Added more logs in ros ci
* Passing tests on fical
* improved all devcontainer
* added devcontainer kilted, fixed source setup.bash, removed ldconfig in ros-cmake workflow
* cleanup
* source ros
* Added utilite tests
* Added testing to appveyor, github actions cancellable on re-commit on same branch
* appveyor testing without all targets
* appveyor: specifying ALL_BUILD target
* Fixed Util2dTest.NMSImageBoundsRespected test
* Fixing PCL Indices error on old pcl
* Added VWDictionary tests and doc. Fixed LSH not working (fix from https://github.com/flann-lib/flann/pull/472
* fixing some appveyor CI errors, added test to check dictionary serialization against all type
* Added StereoDense, StereoBM and StereoSGBM doc and tests
* Added Stereo tests
* Added CameraModel and StereoCameraModel tests
* Added doc and test for Statistics
* Added doc/tests for Signature
* Added doc/test for SensorEvent, added doc for SensorCaptureInfo
* Added doc to SensorData
* Added SensorData tests
* Added SensorCapture and SensorCaptureThread doc and tests
* fixed sensordata test
* updated SSC test and doc
* Added doc and tests for BayesFilter class
* Enabled testing on mac, updated windows testing like on linux
* added test_link
* fixed unresolved on windows
* fixed ThreadHandle error on macos ci
* Added GPS and GeodeticCoords tests
* Added tests for compression
* Added Odometry tests (base class only)
* Added DBDriver tests
* Added coverage report
* uniformized test names
* fixing concurancy and coverage ci
* dont built tools, examples and app for coverage build
* fixed report tool rebuilt without qt compilation error
* updated coverage option
* updated coverage config
* added doc CI job
* fixing windows and mac ci errors
* Added DBDriverSqlite3 tests
* Added IMU tests
* Added Graph tests
* fixing flaky macos test
* Added IMUThread and IMUFilter tests
* Added Landmarks tests
* Added LASWriter tests
* fixing seed flaky test
* fixing flaky macos timing tests
* Added LocalGrid tests
* Added LocalGridMaker tests
* fixing ci errors
* Added GlobalMap tests
* Added doc for EnvSensor
* Added Features2D tests
* Added Registration tests
* Added RegistrationVis tests
* Added doc for Rtabmap and Memory classes
* Added Memory and Rtabmap tests
* making some tests less flaky
* lcov 1.14 support
* updated compatible tool arguments
* Added integration tests (RGB-D, Stereo, Lidar2d, Lidar3d)
* More octomap checks
* Refactored how/when python interpretor is created to simplify library usage
* Added python tests
* fixed some flaky tests
* suppressed some third party related warnings
* fixed ceres tests
* more flaky fixes
* Fixing tests without libpointmatcher
* Added RANSAC rejection filter to PCL ICP
* fixing multi platform flakiness
* Added test to detect regression
* Fixing windows pcl link error
* fixed some macos flakiness
* bigger 2D2D registration error on opencv 4.6.0
* flakiness
* fixing flaky tests on windows and mac
* flaky thread test on slow mac VM
* windows slow test
* fixing more ci erros
* fxing temp dir on windows
* Added Optimizer tests and discovered some bugs (fixed)
* fixing flaky tests in mac and windows
* Added Optimizer doc
* Added GTSAM BA, updated Ceres to use g2o ba parameters. Renamed g2o's ba related parameters to Optimizer group and used by both gtsam and ceres.
* fixing build without gtsam
* fixing home dir
* fixing python ci isssues
* Added multicam ba tests
* Added Ceres multicam BA support
* Aligned BundleAdjustment parameters with Optimizer/Strategy to avoid confusion in the code
* Added BA integration test
* Added robust graph optimization integration test
* Added loop3it test
* Added stereo20Hz test
* Added smartfactor gtsam
* Fixed bugged check and warn if python didn't return any descriptors
* Fixing gtsam version build issues
* fixing tilt on windows ci
* loosing ceres integration test for ci
* mac ci flakiness
* updating missing param in gui
* updating test bound for mac
* added appearance-based tests, set min gftt quality to quality level
* testing more stuff
* improving features2d tests
* ci flakiness
* fixing flaky ci
* ci fixes
* flaky fixes
* Added RegistrationIcp tests
* Added icp integration test with real-worl corridor like env
* intermediate nodes
* fixing enum
* Updated test to catch #1714
* Fixed 2d corridor failing on pcl
* flaky pnp test
* flaky brisk test
* Set rtabmap_integration test as long
* updating loop closure test
* flaky ci tests
* TEsting roundtrip g2o/toro save/load
* loosing test bound
* fixed cuda capable checks
* flaky tests
* Debugging test hanging
* more debugging stuff
* updating limit
* windows: disabled cuda on ci to avoid incompatible driver issue. Fixing a bad test mem allocation
* trying fixing cuda hanging issue
* fixing ci flakyness
* flaky tests
* Updated BOW flaky tests by checking min precision/recall instead of recall@100precision. Fixed signature test
* CameraModel::load() test initRectificationMap param
* test dbdriver load dictionary idsOnly
* Memory: test keepLinkedInDb param
* added dummyDictionary tests
* test intermediate nodes count
* Added MarkerDetector tests
* reverted breaking change of UMutex and USemaphore
* Features2d: fixed compiltion warnings with clang about override
* clang warnings
* fixing test build with pcl 1.8
* g2o and gtsam build errors on android
* opencv5 test fixes
* disabled testing for ios and android builds
* normalized endline characters for easier diff
* added LF CRLF rule
* bump 0.23.10. fixing doc version
* Publish rtabmap website doc from ci
* fixing MSCVC build error
* macos icp flaky test
* fixing ceres macos test bound
* ficing more flaky tests
* fixing opencv5 related test errors. Also fixed an actual bug in ENU_WGS84ToGeocentric_WGS84()
* added comment about mrpt change
* removed rosdoc2 (will add it for rtabmap_ros later)
* fixing website style
* updated download links
* locally deployable website with api
* sweep doxygen issues
* improved/revised doxygen main pages
* removed examples empty page
* Updated doxygen style
* more concise doxygen groups
* added api link on main readme
* fixing utilite test error
* fixing CommonFilteringGroundNormalsUp test
* updated precisionRecall test bounds for Freak and brief descriptors
* fixing scale check in ba tests
* disabled tests on windows cuda build (missing dlls amd runner cannot test cuda anyway)
* ceres: missing suitesparse dep in windows ci
* adjusting recall thr for fast/freak
* ficing more flaky tests
* fixing flaky tests
* disabled coverage in ros ci
* Enable integration tests for ros ci jobs
* loosing up some threshold for failing tests
* trigger cache
* fixing test data in ros ci. Updated flaky test for mac
* slaking some test limit
* Fixed rtabmap-detectMoreLoopClosures inverted output value
* loosing up sift recall on mac
* optimizer re-ordered distribution for reproducible results (mac g2o)
* macos dump test crash log
* combining all tests to save time on shared library reload. Also fixed Logs with missing arguments.
* Added ENABLE_FORMAT_ERRORS cmake option
* do test only one time
* fixed all format warnings
* format security android build errors
* less verbose tests
* updated ImuUThread test
* fixed a log
* Fixed libpointmatcher 2d normals eigen issue
* Fixing libpointmatcher conversion issues
* fixing libpointmatcher test on windows ci
* cleanup comments, relax some test thr
* disabled sequoia-intel ci build (too flaky, would need extensive testing directly on that machine)
2026-08-06 13:32:20 -07:00
|
|
|
// Only a negative count is a failure (detection failed or was interrupted).
|
|
|
|
|
// Finding zero new loop closures is a valid outcome, so exit 0.
|
|
|
|
|
return detected<0?1:0;
|
2018-11-06 17:19:16 -05:00
|
|
|
}
|