mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 09:30:25 +08:00
0.17.0: saving optimized poses and last localization pose to database (https://github.com/introlab/rtabmap_ros/issues/220). Parameters: fixed Icp default parameters when not built with libpointmatcher, added RGBD/SavedLocalizationIgnored (default false). DbViewer: added Export/Import 2D map (https://github.com/introlab/rtabmap_ros/issues/213).
This commit is contained in:
@@ -102,9 +102,12 @@ public:
|
||||
void addStatistics(const Statistics & statistics) const;
|
||||
void savePreviewImage(const cv::Mat & image) const;
|
||||
cv::Mat loadPreviewImage() const;
|
||||
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
||||
std::map<int, Transform> loadOptimizedPoses(Transform * lastlocalizationPose) const;
|
||||
void save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
|
||||
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
|
||||
void saveOptimizedMesh(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
|
||||
@@ -113,7 +116,6 @@ public:
|
||||
#endif
|
||||
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size);
|
||||
cv::Mat loadOptimizedMesh(
|
||||
std::map<int, Transform> * poses = 0,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
|
||||
@@ -230,9 +232,12 @@ private:
|
||||
virtual void addStatisticsQuery(const Statistics & statistics) const = 0;
|
||||
virtual void savePreviewImageQuery(const cv::Mat & image) const = 0;
|
||||
virtual cv::Mat loadPreviewImageQuery() const = 0;
|
||||
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const = 0;
|
||||
virtual std::map<int, Transform> loadOptimizedPosesQuery(Transform * lastlocalizationPose) const = 0;
|
||||
virtual void save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const = 0;
|
||||
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const = 0;
|
||||
virtual void saveOptimizedMeshQuery(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
|
||||
@@ -241,7 +246,6 @@ private:
|
||||
#endif
|
||||
const cv::Mat & textures) const = 0;
|
||||
virtual cv::Mat loadOptimizedMeshQuery(
|
||||
std::map<int, Transform> * poses,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
|
||||
|
||||
@@ -95,9 +95,12 @@ public:
|
||||
void saveStatistics(const Statistics & statistics);
|
||||
void savePreviewImage(const cv::Mat & image) const;
|
||||
cv::Mat loadPreviewImage() const;
|
||||
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
||||
std::map<int, Transform> loadOptimizedPoses(Transform * lastlocalizationPose) const;
|
||||
void save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
|
||||
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
|
||||
void saveOptimizedMesh(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
|
||||
@@ -106,7 +109,6 @@ public:
|
||||
#endif
|
||||
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size)
|
||||
cv::Mat loadOptimizedMesh(
|
||||
std::map<int, Transform> * poses = 0,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
|
||||
|
||||
@@ -42,6 +42,7 @@ class RTABMAP_EXP OccupancyGrid
|
||||
public:
|
||||
OccupancyGrid(const ParametersMap & parameters = ParametersMap());
|
||||
void parseParameters(const ParametersMap & parameters);
|
||||
void setMap(const cv::Mat & map, float xMin, float yMin, float cellSize, const std::map<int, Transform> & poses);
|
||||
void setCellSize(float cellSize);
|
||||
float getCellSize() const {return cellSize_;}
|
||||
void setCloudAssembling(bool enabled);
|
||||
|
||||
@@ -336,6 +336,7 @@ class RTABMAP_EXP Parameters
|
||||
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
|
||||
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest node of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
|
||||
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1.0, uFormat("Reject loop closures if optimization error ratio is greater than this value (0=disabled). Ratio is computed as absolute error over standard deviation of each link. This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"%s\" if enabled.", kOptimizerRobust().c_str()));
|
||||
RTABMAP_PARAM(RGBD, SavedLocalizationIgnored, bool, false, "Ignore last saved localization pose from previous session. If true, RTAB-Map won't assume it is restarting from the same place than where it shut down previously.");
|
||||
RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m).");
|
||||
RTABMAP_PARAM(RGBD, PlanStuckIterations, int, 0, "Mark the current goal node on the path as unreachable if it is not updated after X iterations (0=disabled). If all upcoming nodes on the path are unreachabled, the plan fails.");
|
||||
RTABMAP_PARAM(RGBD, PlanLinearVelocity, float, 0, "Linear velocity (m/sec) used to compute path weights.");
|
||||
@@ -550,11 +551,19 @@ class RTABMAP_EXP Parameters
|
||||
RTABMAP_PARAM(Icp, MaxRotation, float, 0.78, "Maximum ICP rotation correction accepted (rad).");
|
||||
RTABMAP_PARAM(Icp, VoxelSize, float, 0.0, "Uniform sampling voxel size (0=disabled).");
|
||||
RTABMAP_PARAM(Icp, DownsamplingStep, int, 1, "Downsampling step size (1=no sampling). This is done before uniform sampling.");
|
||||
#ifdef RTABMAP_POINTMATCHER
|
||||
RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.1, "Max distance for point correspondences.");
|
||||
#else
|
||||
RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.05, "Max distance for point correspondences.");
|
||||
#endif
|
||||
RTABMAP_PARAM(Icp, Iterations, int, 30, "Max iterations.");
|
||||
RTABMAP_PARAM(Icp, Epsilon, float, 0, "Set the transformation epsilon (maximum allowable difference between two consecutive transformations) in order for an optimization to be considered as having converged to the final solution.");
|
||||
RTABMAP_PARAM(Icp, CorrespondenceRatio, float, 0.1, "Ratio of matching correspondences to accept the transform.");
|
||||
#ifdef RTABMAP_POINTMATCHER
|
||||
RTABMAP_PARAM(Icp, PointToPlane, bool, true, "Use point to plane ICP.");
|
||||
#else
|
||||
RTABMAP_PARAM(Icp, PointToPlane, bool, false, "Use point to plane ICP.");
|
||||
#endif
|
||||
RTABMAP_PARAM(Icp, PointToPlaneK, int, 5, "Number of neighbors to compute normals for point to plane if the cloud doesn't have already normals.");
|
||||
RTABMAP_PARAM(Icp, PointToPlaneRadius, float, 1.0, "Search radius to compute normals for point to plane if the cloud doesn't have already normals.");
|
||||
RTABMAP_PARAM(Icp, PointToPlaneMinComplexity, float, 0.02, "Minimum structural complexity (0.0=low, 1.0=high) of the scan to do point to plane registration, otherwise point to point registration is done instead.");
|
||||
|
||||
@@ -253,6 +253,7 @@ private:
|
||||
int _pathStuckIterations;
|
||||
float _pathLinearVelocity;
|
||||
float _pathAngularVelocity;
|
||||
bool _savedLocalizationIgnored;
|
||||
|
||||
std::pair<int, float> _loopClosureHypothesis;
|
||||
std::pair<int, float> _highestHypothesis;
|
||||
|
||||
@@ -114,7 +114,8 @@ void RTABMAP_EXP rayTrace(const cv::Point2i & start,
|
||||
cv::Mat & grid,
|
||||
bool stopOnObstacle);
|
||||
|
||||
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat & map8S);
|
||||
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat & map8S, bool pgmFormat = false);
|
||||
cv::Mat RTABMAP_EXP convertImage8U2Map(const cv::Mat & map8U, bool pgmFormat = false);
|
||||
|
||||
cv::Mat RTABMAP_EXP erodeMap(const cv::Mat & map);
|
||||
|
||||
|
||||
@@ -1061,9 +1061,37 @@ cv::Mat DBDriver::loadPreviewImage() const
|
||||
return image;
|
||||
}
|
||||
|
||||
void DBDriver::saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
saveOptimizedPosesQuery(optimizedPoses, lastlocalizationPose);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
std::map<int, Transform> DBDriver::loadOptimizedPoses(Transform * lastlocalizationPose) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
std::map<int, Transform> poses = loadOptimizedPosesQuery(lastlocalizationPose);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
return poses;
|
||||
}
|
||||
|
||||
void DBDriver::save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
save2DMapQuery(map, xMin, yMin, cellSize);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
|
||||
cv::Mat DBDriver::load2DMap(float & xMin, float & yMin, float & cellSize) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
cv::Mat map = load2DMapQuery(xMin, yMin, cellSize);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
return map;
|
||||
}
|
||||
|
||||
void DBDriver::saveOptimizedMesh(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
|
||||
@@ -1073,12 +1101,11 @@ void DBDriver::saveOptimizedMesh(
|
||||
const cv::Mat & textures) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
saveOptimizedMeshQuery(cloud, poses, polygons, texCoords, textures);
|
||||
saveOptimizedMeshQuery(cloud, polygons, texCoords, textures);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
|
||||
cv::Mat DBDriver::loadOptimizedMesh(
|
||||
std::map<int, Transform> * poses,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
|
||||
@@ -1088,7 +1115,7 @@ cv::Mat DBDriver::loadOptimizedMesh(
|
||||
cv::Mat * textures) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
cv::Mat cloud = loadOptimizedMeshQuery(poses, polygons, texCoords, textures);
|
||||
cv::Mat cloud = loadOptimizedMeshQuery(polygons, texCoords, textures);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
return cloud;
|
||||
}
|
||||
|
||||
@@ -4277,9 +4277,274 @@ cv::Mat DBDriverSqlite3::loadPreviewImageQuery() const
|
||||
return image;
|
||||
}
|
||||
|
||||
void DBDriverSqlite3::saveOptimizedPosesQuery(const std::map<int, Transform> & poses, const Transform & lastlocalizationPose) const
|
||||
{
|
||||
UDEBUG("");
|
||||
if(_ppDb && uStrNumCmp(_version, "0.17.0") >= 0)
|
||||
{
|
||||
UTimer timer;
|
||||
timer.start();
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
std::string query;
|
||||
|
||||
// Update table Admin
|
||||
query = uFormat("UPDATE Admin SET opt_ids=?, opt_poses=?, opt_last_localization=?, time_enter = DATETIME('NOW') WHERE version='%s';", _version.c_str());
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
int index = 1;
|
||||
|
||||
// opt ids and poses
|
||||
cv::Mat compressedIds;
|
||||
cv::Mat compressedPoses;
|
||||
if(poses.empty())
|
||||
{
|
||||
rc = sqlite3_bind_null(ppStmt, index++);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_null(ppStmt, index++);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<int> serializedIds(poses.size());
|
||||
std::vector<float> serializedPoses(poses.size()*12);
|
||||
int i=0;
|
||||
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
||||
{
|
||||
serializedIds[i] = iter->first;
|
||||
memcpy(serializedPoses.data()+(12*i), iter->second.data(), 12*sizeof(float));
|
||||
++i;
|
||||
}
|
||||
|
||||
compressedIds = compressData2(cv::Mat(1,serializedIds.size(), CV_32SC1, serializedIds.data()));
|
||||
compressedPoses = compressData2(cv::Mat(1,serializedPoses.size(), CV_32FC1, serializedPoses.data()));
|
||||
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, compressedIds.data, compressedIds.cols, SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, compressedPoses.data, compressedPoses.cols, SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
|
||||
if(lastlocalizationPose.isNull())
|
||||
{
|
||||
rc = sqlite3_bind_null(ppStmt, index++);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
UDEBUG("lastlocalizationPose=%s", lastlocalizationPose.prettyPrint().c_str());
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, lastlocalizationPose.data(), lastlocalizationPose.size()*sizeof(float), SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
|
||||
//execute query
|
||||
rc=sqlite3_step(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Finalize (delete) the statement
|
||||
rc = sqlite3_finalize(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
UDEBUG("Time=%fs", timer.ticks());
|
||||
}
|
||||
}
|
||||
|
||||
std::map<int, Transform> DBDriverSqlite3::loadOptimizedPosesQuery(Transform * lastlocalizationPose) const
|
||||
{
|
||||
UDEBUG("");
|
||||
std::map<int, Transform> poses;
|
||||
if(_ppDb && uStrNumCmp(_version, "0.17.0") >= 0)
|
||||
{
|
||||
UTimer timer;
|
||||
timer.start();
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
std::stringstream query;
|
||||
|
||||
query << "SELECT opt_ids, opt_poses, opt_last_localization "
|
||||
<< "FROM Admin "
|
||||
<< "WHERE version='" << _version.c_str()
|
||||
<<"';";
|
||||
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.str().c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Process the result if one
|
||||
rc = sqlite3_step(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_ROW, uFormat("DB error (%s): Not found first Admin row: query=\"%s\"", _version.c_str(), query.str().c_str()).c_str());
|
||||
if(rc == SQLITE_ROW)
|
||||
{
|
||||
const void * data = 0;
|
||||
int dataSize = 0;
|
||||
int index = 0;
|
||||
|
||||
//opt_poses
|
||||
cv::Mat serializedIds;
|
||||
data = sqlite3_column_blob(ppStmt, index);
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
if(dataSize>0 && data)
|
||||
{
|
||||
serializedIds = uncompressData(cv::Mat(1, dataSize, CV_8UC1, (void *)data));
|
||||
UDEBUG("serializedIds=%d", serializedIds.cols);
|
||||
}
|
||||
|
||||
data = sqlite3_column_blob(ppStmt, index);
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
if(dataSize>0 && data)
|
||||
{
|
||||
cv::Mat serializedPoses = uncompressData(cv::Mat(1, dataSize, CV_8UC1, (void *)data));
|
||||
UDEBUG("serializedPoses=%d", serializedPoses.cols);
|
||||
|
||||
UASSERT(serializedIds.cols == serializedPoses.cols/12);
|
||||
UASSERT(serializedPoses.type() == CV_32FC1);
|
||||
UASSERT(serializedIds.type() == CV_32SC1);
|
||||
for(int i=0; i<serializedIds.cols; ++i)
|
||||
{
|
||||
Transform t(serializedPoses.at<float>(i*12), serializedPoses.at<float>(i*12+1), serializedPoses.at<float>(i*12+2), serializedPoses.at<float>(i*12+3),
|
||||
serializedPoses.at<float>(i*12+4), serializedPoses.at<float>(i*12+5), serializedPoses.at<float>(i*12+6), serializedPoses.at<float>(i*12+7),
|
||||
serializedPoses.at<float>(i*12+8), serializedPoses.at<float>(i*12+9), serializedPoses.at<float>(i*12+10), serializedPoses.at<float>(i*12+11));
|
||||
poses.insert(std::make_pair(serializedIds.at<int>(i), t));
|
||||
UDEBUG("Optimized pose %d: %s", serializedIds.at<int>(i), t.prettyPrint().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
data = sqlite3_column_blob(ppStmt, index); // ground_truth_pose
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
if(lastlocalizationPose)
|
||||
{
|
||||
if((unsigned int)dataSize == lastlocalizationPose->size()*sizeof(float) && data)
|
||||
{
|
||||
memcpy(lastlocalizationPose->data(), data, dataSize);
|
||||
}
|
||||
UDEBUG("lastlocalizationPose=%s", lastlocalizationPose->prettyPrint().c_str());
|
||||
}
|
||||
|
||||
rc = sqlite3_step(ppStmt); // next result...
|
||||
}
|
||||
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Finalize (delete) the statement
|
||||
rc = sqlite3_finalize(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
ULOGGER_DEBUG("Time=%fs", timer.ticks());
|
||||
|
||||
}
|
||||
return poses;
|
||||
}
|
||||
|
||||
void DBDriverSqlite3::save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const
|
||||
{
|
||||
UDEBUG("");
|
||||
if(_ppDb && uStrNumCmp(_version, "0.17.0") >= 0)
|
||||
{
|
||||
UTimer timer;
|
||||
timer.start();
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
std::string query;
|
||||
|
||||
// Update table Admin
|
||||
query = uFormat("UPDATE Admin SET opt_map=?, opt_map_x_min=?, opt_map_y_min=?, opt_map_resolution=?, time_enter = DATETIME('NOW') WHERE version='%s';", _version.c_str());
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
int index = 1;
|
||||
|
||||
// opt ids and poses
|
||||
cv::Mat compressedMap;
|
||||
if(map.empty())
|
||||
{
|
||||
rc = sqlite3_bind_null(ppStmt, index++);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
compressedMap = compressData2(map);
|
||||
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, compressedMap.data, compressedMap.cols, SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
|
||||
rc = sqlite3_bind_double(ppStmt, index++, xMin);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_double(ppStmt, index++, yMin);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_double(ppStmt, index++, cellSize);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
//execute query
|
||||
rc=sqlite3_step(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Finalize (delete) the statement
|
||||
rc = sqlite3_finalize(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
UDEBUG("Time=%fs", timer.ticks());
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat DBDriverSqlite3::load2DMapQuery(float & xMin, float & yMin, float & cellSize) const
|
||||
{
|
||||
UDEBUG("");
|
||||
cv::Mat map;
|
||||
if(_ppDb && uStrNumCmp(_version, "0.17.0") >= 0)
|
||||
{
|
||||
UTimer timer;
|
||||
timer.start();
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
std::stringstream query;
|
||||
|
||||
query << "SELECT opt_map, opt_map_x_min, opt_map_y_min, opt_map_resolution "
|
||||
<< "FROM Admin "
|
||||
<< "WHERE version='" << _version.c_str()
|
||||
<<"';";
|
||||
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.str().c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Process the result if one
|
||||
rc = sqlite3_step(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_ROW, uFormat("DB error (%s): Not found first Admin row: query=\"%s\"", _version.c_str(), query.str().c_str()).c_str());
|
||||
if(rc == SQLITE_ROW)
|
||||
{
|
||||
const void * data = 0;
|
||||
int dataSize = 0;
|
||||
int index = 0;
|
||||
|
||||
//opt_map
|
||||
data = sqlite3_column_blob(ppStmt, index);
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
if(dataSize>0 && data)
|
||||
{
|
||||
map = uncompressData(cv::Mat(1, dataSize, CV_8UC1, (void *)data));
|
||||
UDEBUG("map=%d/%d", map.cols, map.rows);
|
||||
}
|
||||
|
||||
xMin = sqlite3_column_double(ppStmt, index++);
|
||||
UDEBUG("xMin=%f", xMin);
|
||||
yMin = sqlite3_column_double(ppStmt, index++);
|
||||
UDEBUG("yMin=%f", yMin);
|
||||
cellSize = sqlite3_column_double(ppStmt, index++);
|
||||
UDEBUG("cellSize=%f", cellSize);
|
||||
|
||||
rc = sqlite3_step(ppStmt); // next result...
|
||||
}
|
||||
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// Finalize (delete) the statement
|
||||
rc = sqlite3_finalize(ppStmt);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
ULOGGER_DEBUG("Time=%fs", timer.ticks());
|
||||
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
void DBDriverSqlite3::saveOptimizedMeshQuery(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
|
||||
@@ -4298,7 +4563,7 @@ void DBDriverSqlite3::saveOptimizedMeshQuery(
|
||||
std::string query;
|
||||
|
||||
// Update table Admin
|
||||
query = uFormat("UPDATE Admin SET opt_cloud=?, opt_ids=?, opt_poses=?, opt_polygons_size=?, opt_polygons=?, opt_tex_coords=?, opt_tex_materials=?, time_enter = DATETIME('NOW') WHERE version='%s';", _version.c_str());
|
||||
query = uFormat("UPDATE Admin SET opt_cloud=?, opt_polygons_size=?, opt_polygons=?, opt_tex_coords=?, opt_tex_materials=?, time_enter = DATETIME('NOW') WHERE version='%s';", _version.c_str());
|
||||
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
@@ -4336,39 +4601,9 @@ void DBDriverSqlite3::saveOptimizedMeshQuery(
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
// opt ids and poses
|
||||
cv::Mat compressedIds;
|
||||
cv::Mat compressedPoses;
|
||||
cv::Mat compressedPolygons;
|
||||
cv::Mat compressedTexCoords;
|
||||
cv::Mat compressedTextures;
|
||||
if(poses.empty())
|
||||
{
|
||||
rc = sqlite3_bind_null(ppStmt, index++);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_null(ppStmt, index++);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<int> serializedIds(poses.size());
|
||||
std::vector<float> serializedPoses(poses.size()*12);
|
||||
int i=0;
|
||||
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
||||
{
|
||||
serializedIds[i] = iter->first;
|
||||
memcpy(serializedPoses.data()+(12*i), iter->second.data(), 12*sizeof(float));
|
||||
++i;
|
||||
}
|
||||
|
||||
compressedIds = compressData2(cv::Mat(1,serializedIds.size(), CV_32SC1, serializedIds.data()));
|
||||
compressedPoses = compressData2(cv::Mat(1,serializedPoses.size(), CV_32FC1, serializedPoses.data()));
|
||||
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, compressedIds.data, compressedIds.cols, SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, compressedPoses.data, compressedPoses.cols, SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||
}
|
||||
|
||||
// polygons
|
||||
if(polygons.empty())
|
||||
{
|
||||
@@ -4505,7 +4740,6 @@ void DBDriverSqlite3::saveOptimizedMeshQuery(
|
||||
}
|
||||
|
||||
cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
|
||||
std::map<int, Transform> * poses,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
|
||||
@@ -4524,7 +4758,7 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
|
||||
sqlite3_stmt * ppStmt = 0;
|
||||
std::stringstream query;
|
||||
|
||||
query << "SELECT opt_cloud, opt_ids, opt_poses, opt_polygons_size, opt_polygons, opt_tex_coords, opt_tex_materials "
|
||||
query << "SELECT opt_cloud, opt_polygons_size, opt_polygons, opt_tex_coords, opt_tex_materials "
|
||||
<< "FROM Admin "
|
||||
<< "WHERE version='" << _version.c_str()
|
||||
<<"';";
|
||||
@@ -4560,29 +4794,6 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
|
||||
UDEBUG("serializedIds=%d", serializedIds.cols);
|
||||
}
|
||||
|
||||
data = sqlite3_column_blob(ppStmt, index);
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
if(dataSize>0 && data)
|
||||
{
|
||||
cv::Mat serializedPoses = uncompressData(cv::Mat(1, dataSize, CV_8UC1, (void *)data));
|
||||
UDEBUG("serializedPoses=%d", serializedPoses.cols);
|
||||
|
||||
if(poses)
|
||||
{
|
||||
UASSERT(serializedIds.cols == serializedPoses.cols/12);
|
||||
UASSERT(serializedPoses.type() == CV_32FC1);
|
||||
UASSERT(serializedIds.type() == CV_32SC1);
|
||||
for(int i=0; i<serializedIds.cols; ++i)
|
||||
{
|
||||
Transform t(serializedPoses.at<float>(i*12), serializedPoses.at<float>(i*12+1), serializedPoses.at<float>(i*12+2), serializedPoses.at<float>(i*12+3),
|
||||
serializedPoses.at<float>(i*12+4), serializedPoses.at<float>(i*12+5), serializedPoses.at<float>(i*12+6), serializedPoses.at<float>(i*12+7),
|
||||
serializedPoses.at<float>(i*12+8), serializedPoses.at<float>(i*12+9), serializedPoses.at<float>(i*12+10), serializedPoses.at<float>(i*12+11));
|
||||
poses->insert(std::make_pair(serializedIds.at<int>(i), t));
|
||||
UDEBUG("Optimized pose %d: %s", serializedIds.at<int>(i), t.prettyPrint().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//opt_polygons_size
|
||||
int polygonSize = sqlite3_column_int(ppStmt, index++);
|
||||
UDEBUG("polygonSize=%d", polygonSize);
|
||||
|
||||
@@ -101,9 +101,12 @@ private:
|
||||
virtual void addStatisticsQuery(const Statistics & statistics) const;
|
||||
virtual void savePreviewImageQuery(const cv::Mat & image) const;
|
||||
virtual cv::Mat loadPreviewImageQuery() const;
|
||||
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
||||
virtual std::map<int, Transform> loadOptimizedPosesQuery(Transform * lastlocalizationPose) const;
|
||||
virtual void save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
|
||||
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const;
|
||||
virtual void saveOptimizedMeshQuery(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
|
||||
@@ -112,7 +115,6 @@ private:
|
||||
#endif
|
||||
const cv::Mat & textures) const;
|
||||
virtual cv::Mat loadOptimizedMeshQuery(
|
||||
std::map<int, Transform> * poses,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
|
||||
|
||||
@@ -361,7 +361,7 @@ void Memory::close(bool databaseSaved, bool postInitClosingEvents, const std::st
|
||||
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(RtabmapEventInit::kClosing));
|
||||
|
||||
bool databaseNameChanged = false;
|
||||
if(databaseSaved)
|
||||
if(databaseSaved && _dbDriver)
|
||||
{
|
||||
databaseNameChanged = ouputDatabasePath.size() && _dbDriver->getUrl().size() && _dbDriver->getUrl().compare(ouputDatabasePath) != 0?true:false;
|
||||
}
|
||||
@@ -1756,9 +1756,42 @@ cv::Mat Memory::loadPreviewImage() const
|
||||
return cv::Mat();
|
||||
}
|
||||
|
||||
void Memory::saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const
|
||||
{
|
||||
if(_dbDriver)
|
||||
{
|
||||
_dbDriver->saveOptimizedPoses(optimizedPoses, lastlocalizationPose);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<int, Transform> Memory::loadOptimizedPoses(Transform * lastlocalizationPose) const
|
||||
{
|
||||
if(_dbDriver)
|
||||
{
|
||||
return _dbDriver->loadOptimizedPoses(lastlocalizationPose);
|
||||
}
|
||||
return std::map<int, Transform>();
|
||||
}
|
||||
|
||||
void Memory::save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const
|
||||
{
|
||||
if(_dbDriver)
|
||||
{
|
||||
_dbDriver->save2DMap(map, xMin, yMin, cellSize);
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat Memory::load2DMap(float & xMin, float & yMin, float & cellSize) const
|
||||
{
|
||||
if(_dbDriver)
|
||||
{
|
||||
return _dbDriver->load2DMap(xMin, yMin, cellSize);
|
||||
}
|
||||
return cv::Mat();
|
||||
}
|
||||
|
||||
void Memory::saveOptimizedMesh(
|
||||
const cv::Mat & cloud,
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
|
||||
@@ -1769,12 +1802,11 @@ void Memory::saveOptimizedMesh(
|
||||
{
|
||||
if(_dbDriver)
|
||||
{
|
||||
_dbDriver->saveOptimizedMesh(cloud, poses, polygons, texCoords, textures);
|
||||
_dbDriver->saveOptimizedMesh(cloud, polygons, texCoords, textures);
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat Memory::loadOptimizedMesh(
|
||||
std::map<int, Transform> * poses,
|
||||
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
|
||||
@@ -1785,7 +1817,7 @@ cv::Mat Memory::loadOptimizedMesh(
|
||||
{
|
||||
if(_dbDriver)
|
||||
{
|
||||
return _dbDriver->loadOptimizedMesh(poses, polygons, texCoords, textures);
|
||||
return _dbDriver->loadOptimizedMesh(polygons, texCoords, textures);
|
||||
}
|
||||
return cv::Mat();
|
||||
}
|
||||
|
||||
@@ -197,6 +197,24 @@ void OccupancyGrid::parseParameters(const ParametersMap & parameters)
|
||||
}
|
||||
}
|
||||
|
||||
void OccupancyGrid::setMap(const cv::Mat & map, float xMin, float yMin, float cellSize, const std::map<int, Transform> & poses)
|
||||
{
|
||||
UDEBUG("map=%d/%d xMin=%f yMin=%f cellSize=%f poses=%d",
|
||||
map.cols, map.rows, xMin, yMin, cellSize, (int)poses.size());
|
||||
this->clear();
|
||||
if(!poses.empty() && !map.empty())
|
||||
{
|
||||
UASSERT(cellSize > 0.0f);
|
||||
UASSERT(map.type() == CV_8SC1);
|
||||
map_ = map.clone();
|
||||
mapInfo_ = cv::Mat::zeros(map.size(), CV_32FC3);
|
||||
xMin_ = xMin;
|
||||
yMin_ = yMin;
|
||||
cellSize_ = cellSize;
|
||||
addedNodes_ = poses;
|
||||
}
|
||||
}
|
||||
|
||||
void OccupancyGrid::setCellSize(float cellSize)
|
||||
{
|
||||
UASSERT_MSG(cellSize > 0.0f, uFormat("Param name is \"%s\"", Parameters::kGridCellSize().c_str()).c_str());
|
||||
|
||||
@@ -423,7 +423,7 @@ void RegistrationIcp::parseParameters(const ParametersMap & parameters)
|
||||
#ifndef RTABMAP_POINTMATCHER
|
||||
if(_libpointmatcher)
|
||||
{
|
||||
UWARN("Parameter %s is set to true but RTAB-MAp has not been built with libpointmatcher support. Setting to false.", Parameters::kIcpPM().c_str());
|
||||
UWARN("Parameter %s is set to true but RTAB-Map has not been built with libpointmatcher support. Setting to false.", Parameters::kIcpPM().c_str());
|
||||
_libpointmatcher = false;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -121,6 +121,7 @@ Rtabmap::Rtabmap() :
|
||||
_pathStuckIterations(Parameters::defaultRGBDPlanStuckIterations()),
|
||||
_pathLinearVelocity(Parameters::defaultRGBDPlanLinearVelocity()),
|
||||
_pathAngularVelocity(Parameters::defaultRGBDPlanAngularVelocity()),
|
||||
_savedLocalizationIgnored(Parameters::defaultRGBDSavedLocalizationIgnored()),
|
||||
_loopClosureHypothesis(0,0.0f),
|
||||
_highestHypothesis(0,0.0f),
|
||||
_lastProcessTime(0.0),
|
||||
@@ -309,6 +310,19 @@ void Rtabmap::init(const ParametersMap & parameters, const std::string & databas
|
||||
// Parse all parameters
|
||||
this->parseParameters(parameters);
|
||||
|
||||
Transform lastPose;
|
||||
_optimizedPoses = _memory->loadOptimizedPoses(&lastPose);
|
||||
if(_optimizedPoses.size())
|
||||
{
|
||||
if(!_savedLocalizationIgnored)
|
||||
{
|
||||
_lastLocalizationPose = lastPose;
|
||||
}
|
||||
std::map<int, Transform> tmp;
|
||||
// Get just the links
|
||||
_memory->getMetricConstraints(uKeysSet(_optimizedPoses), tmp, _constraints, false);
|
||||
}
|
||||
|
||||
if(_databasePath.empty())
|
||||
{
|
||||
_statisticLogged = false;
|
||||
@@ -337,11 +351,10 @@ void Rtabmap::close(bool databaseSaved, const std::string & ouputDatabasePath)
|
||||
_loopClosureHypothesis = std::make_pair(0,0.0f);
|
||||
_lastProcessTime = 0.0;
|
||||
_someNodesHaveBeenTransferred = false;
|
||||
_optimizedPoses.clear();
|
||||
_constraints.clear();
|
||||
_mapCorrection.setIdentity();
|
||||
_mapCorrectionBackup.setNull();
|
||||
_lastLocalizationPose.setNull();
|
||||
|
||||
_lastLocalizationNodeId = 0;
|
||||
_distanceTravelled = 0.0f;
|
||||
this->clearPath(0);
|
||||
@@ -365,10 +378,14 @@ void Rtabmap::close(bool databaseSaved, const std::string & ouputDatabasePath)
|
||||
}
|
||||
if(_memory)
|
||||
{
|
||||
_memory->saveOptimizedPoses(_optimizedPoses, _lastLocalizationPose);
|
||||
_memory->close(databaseSaved, true, ouputDatabasePath);
|
||||
delete _memory;
|
||||
_memory = 0;
|
||||
}
|
||||
_optimizedPoses.clear();
|
||||
_lastLocalizationPose.setNull();
|
||||
|
||||
if(_bayesFilter)
|
||||
{
|
||||
delete _bayesFilter;
|
||||
@@ -444,6 +461,7 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
|
||||
Parameters::parse(parameters, Parameters::kRGBDPlanStuckIterations(), _pathStuckIterations);
|
||||
Parameters::parse(parameters, Parameters::kRGBDPlanLinearVelocity(), _pathLinearVelocity);
|
||||
Parameters::parse(parameters, Parameters::kRGBDPlanAngularVelocity(), _pathAngularVelocity);
|
||||
Parameters::parse(parameters, Parameters::kRGBDSavedLocalizationIgnored(), _savedLocalizationIgnored);
|
||||
|
||||
UASSERT(_rgbdLinearUpdate >= 0.0f);
|
||||
UASSERT(_rgbdAngularUpdate >= 0.0f);
|
||||
@@ -937,10 +955,24 @@ bool Rtabmap::process(
|
||||
bool fakeOdom = false;
|
||||
if(_rgbdSlamMode)
|
||||
{
|
||||
if(!_memory->isIncremental() && !odomPose.isNull() && !_mapCorrectionBackup.isNull())
|
||||
if(!_memory->isIncremental() && !odomPose.isNull())
|
||||
{
|
||||
_mapCorrection = _mapCorrectionBackup;
|
||||
_mapCorrectionBackup.setNull();
|
||||
if(!_mapCorrectionBackup.isNull())
|
||||
{
|
||||
_mapCorrection = _mapCorrectionBackup;
|
||||
_mapCorrectionBackup.setNull();
|
||||
}
|
||||
else if(_optimizedPoses.size() && _mapCorrection.isIdentity() && !_lastLocalizationPose.isNull() && _lastLocalizationNodeId == 0)
|
||||
{
|
||||
// Localization mode, set map->odom so that odom is moved back to last saved localization
|
||||
_mapCorrection = _lastLocalizationPose * odomPose.inverse();
|
||||
_lastLocalizationNodeId = graph::findNearestNode(_optimizedPoses, _lastLocalizationPose);
|
||||
UWARN("Update map correction based on last localization saved in database! correction = %s, nearest id = %d of last pose = %s, odom = %s",
|
||||
_mapCorrection.prettyPrint().c_str(),
|
||||
_lastLocalizationNodeId,
|
||||
_lastLocalizationPose.prettyPrint().c_str(),
|
||||
odomPose.prettyPrint().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(odomPose.isNull())
|
||||
|
||||
@@ -112,6 +112,7 @@ CREATE TABLE Admin (
|
||||
opt_cloud BLOB, -- compressed data
|
||||
opt_ids BLOB, -- Node ids used to generate the optimized cloud/mesh
|
||||
opt_poses BLOB, -- compressed N*3x4 float
|
||||
opt_last_localization BLOB, -- 3x4 float
|
||||
opt_polygons_size INTEGER, -- e.g., 3
|
||||
opt_polygons BLOB, -- compressed data [length_v0, i0,i1,i3, length_v1, i0,i1,i3]
|
||||
opt_tex_coords BLOB, -- compressed data [length_v0, u0,v0,u1,v1,u2,v2, length_v1, u0,v0,u1,v1,u2,v2]
|
||||
@@ -119,6 +120,7 @@ CREATE TABLE Admin (
|
||||
opt_map BLOB, -- compressed CV_8SC1 occupancy grid
|
||||
opt_map_x_min FLOAT,
|
||||
opt_map_y_min FLOAT,
|
||||
opt_map_resolution FLOAT,
|
||||
|
||||
time_enter DATE
|
||||
);
|
||||
|
||||
@@ -849,7 +849,7 @@ void rayTrace(const cv::Point2i & start, const cv::Point2i & end, cv::Mat & grid
|
||||
}
|
||||
|
||||
//convert to gray scaled map
|
||||
cv::Mat convertMap2Image8U(const cv::Mat & map8S)
|
||||
cv::Mat convertMap2Image8U(const cv::Mat & map8S, bool pgmFormat)
|
||||
{
|
||||
UASSERT(map8S.channels() == 1 && map8S.type() == CV_8S);
|
||||
cv::Mat map8U = cv::Mat(map8S.rows, map8S.cols, CV_8U);
|
||||
@@ -857,11 +857,11 @@ cv::Mat convertMap2Image8U(const cv::Mat & map8S)
|
||||
{
|
||||
for (int j = 0; j < map8S.cols; ++j)
|
||||
{
|
||||
char v = map8S.at<char>(i, j);
|
||||
char v = pgmFormat?map8S.at<char>((map8S.rows-1)-i, j):map8S.at<char>(i, j);
|
||||
unsigned char gray;
|
||||
if(v == 0)
|
||||
{
|
||||
gray = 178;
|
||||
gray = pgmFormat?254:178;
|
||||
}
|
||||
else if(v == 100)
|
||||
{
|
||||
@@ -869,11 +869,11 @@ cv::Mat convertMap2Image8U(const cv::Mat & map8S)
|
||||
}
|
||||
else if(v == -2)
|
||||
{
|
||||
gray = 200;
|
||||
gray = pgmFormat?254:200;
|
||||
}
|
||||
else // -1
|
||||
{
|
||||
gray = 89;
|
||||
gray = pgmFormat?205:89;
|
||||
}
|
||||
map8U.at<unsigned char>(i, j) = gray;
|
||||
}
|
||||
@@ -881,6 +881,58 @@ cv::Mat convertMap2Image8U(const cv::Mat & map8S)
|
||||
return map8U;
|
||||
}
|
||||
|
||||
//convert gray scaled image to map
|
||||
cv::Mat convertImage8U2Map(const cv::Mat & map8U, bool pgmFormat)
|
||||
{
|
||||
UASSERT_MSG(map8U.channels() == 1 && map8U.type() == CV_8U, uFormat("map8U.channels()=%d map8U.type()=%d", map8U.channels(), map8U.type()).c_str());
|
||||
cv::Mat map8S = cv::Mat(map8U.rows, map8U.cols, CV_8S);
|
||||
for (int i = 0; i < map8U.rows; ++i)
|
||||
{
|
||||
for (int j = 0; j < map8U.cols; ++j)
|
||||
{
|
||||
unsigned char v = pgmFormat?map8U.at<char>((map8U.rows-1)-i, j):map8U.at<char>(i, j);
|
||||
char occupancy;
|
||||
if(pgmFormat)
|
||||
{
|
||||
if(v >= 254)
|
||||
{
|
||||
occupancy = 0;
|
||||
}
|
||||
else if(v == 0)
|
||||
{
|
||||
occupancy = 100;
|
||||
}
|
||||
else // 205
|
||||
{
|
||||
occupancy = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(v == 178)
|
||||
{
|
||||
occupancy = 0;
|
||||
}
|
||||
else if(v == 0)
|
||||
{
|
||||
occupancy = 100;
|
||||
}
|
||||
else if(v == 200)
|
||||
{
|
||||
occupancy = -2;
|
||||
}
|
||||
else // 89
|
||||
{
|
||||
occupancy = -1;
|
||||
}
|
||||
}
|
||||
|
||||
map8S.at<char>(i, j) = occupancy;
|
||||
}
|
||||
}
|
||||
return map8S;
|
||||
}
|
||||
|
||||
cv::Mat erodeMap(const cv::Mat & map)
|
||||
{
|
||||
UASSERT(map.type() == CV_8SC1);
|
||||
|
||||
Reference in New Issue
Block a user