mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-03 01:50:24 +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:
@@ -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