Skip to content

Commit f94a963

Browse files
authored
CID-SIMS support (#1676)
* cid-sims dataset support * Added cli tool to test CID-SIMS dataset * removed debug log
1 parent 5b985f6 commit f94a963

File tree

13 files changed

+1068
-254
lines changed

13 files changed

+1068
-254
lines changed

corelib/include/rtabmap/core/camera/CameraImages.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,11 @@ class RTABMAP_CORE_EXPORT CameraImages :
102102
}
103103

104104
// 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV, 12=rgbd_bonn
105-
void setGroundTruthPath(const std::string & filePath, int format = 0)
105+
void setGroundTruthPath(const std::string & filePath, int format = 0, const Transform & localTransform = Transform::getIdentity())
106106
{
107107
_groundTruthPath = filePath;
108108
_groundTruthFormat = format;
109+
_groundTruthLocalTransform = localTransform;
109110
}
110111

111112
void setMaxPoseTimeDiff(double diff) {_maxPoseTimeDiff = diff;}
@@ -164,6 +165,7 @@ class RTABMAP_CORE_EXPORT CameraImages :
164165
int _odometryFormat;
165166
std::string _groundTruthPath;
166167
int _groundTruthFormat;
168+
Transform _groundTruthLocalTransform;
167169
double _maxPoseTimeDiff;
168170

169171
std::list<double> _stamps;

corelib/src/CameraModel.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,22 @@ bool CameraModel::load(const std::string & filePath)
353353
data[0], data[1], data[2], data[3],
354354
data[4], data[5], data[6], data[7],
355355
data[8], data[9], data[10], data[11]);
356+
Transform detCheck = localTransform_.clone();
357+
localTransform_.normalizeRotation(); /// Normalize by default
358+
float det = detCheck.toEigen3f().linear().determinant();
359+
if(fabs(det - 1.0f) > 0.0001)
360+
{
361+
std::stringstream streamBefore, streamAfter;
362+
streamBefore << detCheck << std::endl;
363+
streamAfter << localTransform_ << std::endl;
364+
UWARN("The camera model's local_transform from \"%s\" doesn't "
365+
"have a normalized rotation matrix (dertminant=%f). We will normalize "
366+
"it for convenience.\nWas:\n%sNow\n%s",
367+
filePath.c_str(),
368+
det,
369+
streamBefore.str().c_str(),
370+
streamAfter.str().c_str());
371+
}
356372
}
357373
else
358374
{

corelib/src/IMUThread.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,20 @@ void IMUThread::mainLoop()
135135
std::stringstream stream(line);
136136
std::string s;
137137
std::getline(stream, s, ',');
138-
std::string nanoseconds = s.substr(s.size() - 9, 9);
139-
std::string seconds = s.substr(0, s.size() - 9);
138+
139+
double stamp = 0.0;
140+
if(s.find('.') != std::string::npos)
141+
{
142+
// Normal [epoch] timestamp
143+
stamp = uStr2Double(s);
144+
}
145+
else
146+
{
147+
// Assume EuRoC format
148+
std::string nanoseconds = s.substr(s.size() - 9, 9);
149+
std::string seconds = s.substr(0, s.size() - 9);
150+
stamp = double(uStr2Int(seconds)) + double(uStr2Int(nanoseconds))*1e-9;
151+
}
140152

141153
cv::Vec3d gyr;
142154
for (int j = 0; j < 3; ++j) {
@@ -150,7 +162,6 @@ void IMUThread::mainLoop()
150162
acc[j] = uStr2Double(s);
151163
}
152164

153-
double stamp = double(uStr2Int(seconds)) + double(uStr2Int(nanoseconds))*1e-9;
154165
if(previousStamp_>0 && stamp > previousStamp_)
155166
{
156167
captureDelay_ = stamp - previousStamp_;

corelib/src/OdometryThread.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ void OdometryThread::addData(const SensorEvent & event)
188188
"(%f), skipping that frame (imu buffer size=%ld). "
189189
"When using async IMU, make sure IMU is published faster "
190190
"than camera/lidar (assuming IMU latency is very small compared to camera/lidar)."
191-
"Current camera/lidar delay is %fs.",
191+
"Current camera/lidar delay with system time is %fs.",
192192
event.data().stamp(), _oldestAsyncImuStamp, _imuBuffer.size(), UTimer::now() - event.data().stamp());
193193
notify = false;
194194
}
@@ -197,7 +197,7 @@ void OdometryThread::addData(const SensorEvent & event)
197197
"(%f), skipping that frame (imu buffer size=%ld). "
198198
"When using async IMU, make sure IMU is published faster "
199199
"than camera/lidar (assuming IMU latency is very small compared to camera/lidar). "
200-
"Current camera/lidar delay is %fs.",
200+
"Current camera/lidar delay with system time is %fs.",
201201
event.data().stamp(), _newestAsyncImuStamp, _imuBuffer.size(), UTimer::now() - event.data().stamp());
202202
notify = false;
203203
}

corelib/src/Transform.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ Transform::Transform(
5252
r11, r12, r13, o14,
5353
r21, r22, r23, o24,
5454
r31, r32, r33, o34);
55+
56+
if( r11>0.0f || r12>0.0f || r13>0.0f ||
57+
r21>0.0f || r22>0.0f || r23>0.0f ||
58+
r31>0.0f || r32>0.0f || r33>0.0f)
59+
{
60+
Eigen::Matrix3f m;
61+
m << r11, r12, r13,
62+
r21, r22, r23,
63+
r31, r32, r33;
64+
float d = m.determinant();
65+
if(fabs(d-1.0f) > 0.0001)
66+
{
67+
UWARN("Created transform doesn't have normalized rotation. Any transformation with this transform can cause unexpected results!"
68+
" Determinant([%f %f %f;%f %f %f;%f %f %f])=%f",
69+
r11, r12, r13,
70+
r21, r22, r23,
71+
r31, r32, r33,
72+
d);
73+
}
74+
}
5575
}
5676

5777
Transform::Transform(const cv::Mat & transformationMatrix)
@@ -509,6 +529,11 @@ Transform Transform::fromString(const std::string & string)
509529
numbers[4], numbers[5], numbers[6], numbers[7],
510530
numbers[8], numbers[9], numbers[10], numbers[11]);
511531
}
532+
// Always normalize
533+
if(!t.isNull())
534+
{
535+
t.normalizeRotation();
536+
}
512537
return t;
513538
}
514539

corelib/src/camera/CameraImages.cpp

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ CameraImages::CameraImages() :
6363
_syncImageRateWithStamps(true),
6464
_odometryFormat(0),
6565
_groundTruthFormat(0),
66+
_groundTruthLocalTransform(Transform::getIdentity()),
6667
_maxPoseTimeDiff(0.02),
6768
_captureDelay(0.0)
6869
{}
@@ -93,6 +94,7 @@ CameraImages::CameraImages(const std::string & path,
9394
_syncImageRateWithStamps(true),
9495
_odometryFormat(0),
9596
_groundTruthFormat(0),
97+
_groundTruthLocalTransform(Transform::getIdentity()),
9698
_maxPoseTimeDiff(0.02),
9799
_captureDelay(0.0)
98100
{
@@ -478,27 +480,43 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
478480
if(success && _odometryPath.size() && odometry_.empty())
479481
{
480482
success = readPoses(odometry_, _stamps, _odometryPath, _odometryFormat, _maxPoseTimeDiff);
483+
if(!success)
484+
{
485+
UERROR("Failed to read odometry poses.");
486+
}
487+
488+
if(success)
489+
{
490+
for(size_t i=0; i<odometry_.size(); ++i)
491+
{
492+
// linear cov = 0.0001
493+
cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1) * (i==0?9999.0:0.0001);
494+
if(i!=0)
495+
{
496+
// angular cov = 0.000001
497+
covariance.at<double>(3,3) *= 0.01;
498+
covariance.at<double>(4,4) *= 0.01;
499+
covariance.at<double>(5,5) *= 0.01;
500+
}
501+
covariances_.push_back(covariance);
502+
}
503+
}
481504
}
482505

483506
if(success && _groundTruthPath.size())
484507
{
485508
success = readPoses(groundTruth_, _stamps, _groundTruthPath, _groundTruthFormat, _maxPoseTimeDiff);
486-
}
487-
488-
if(!odometry_.empty())
489-
{
490-
for(size_t i=0; i<odometry_.size(); ++i)
509+
if(!success)
491510
{
492-
// linear cov = 0.0001
493-
cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1) * (i==0?9999.0:0.0001);
494-
if(i!=0)
511+
UERROR("Failed to read ground truth poses.");
512+
}
513+
else if(!_groundTruthLocalTransform.isIdentity())
514+
{
515+
Transform gtInv = _groundTruthLocalTransform.inverse();
516+
for(auto pose: groundTruth_)
495517
{
496-
// angular cov = 0.000001
497-
covariance.at<double>(3,3) *= 0.01;
498-
covariance.at<double>(4,4) *= 0.01;
499-
covariance.at<double>(5,5) *= 0.01;
518+
pose = pose*gtInv; // pose of base_link, assuming ground truth frame and base frame are rigidly fixed
500519
}
501-
covariances_.push_back(covariance);
502520
}
503521
}
504522
}
@@ -607,7 +625,7 @@ bool CameraImages::readPoses(
607625
}
608626
if(validPoses != (int)inOutStamps.size())
609627
{
610-
UWARN("%d valid poses of %d stamps", validPoses, (int)inOutStamps.size());
628+
UWARN("%d/%ld valid poses of %ld stamps", validPoses, outputPoses.size(), inOutStamps.size());
611629
}
612630
}
613631
else
@@ -756,32 +774,19 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
756774

757775
if(_stamps.size())
758776
{
759-
stamp = _stamps.front();
760-
_stamps.pop_front();
761-
if(_stamps.size())
762-
{
763-
_captureDelay = _stamps.front() - stamp;
764-
}
777+
UERROR("stamps cannot be used when startAt < 0");
765778
}
766779
if(odometry_.size())
767780
{
768-
odometryPose = odometry_.front();
769-
odometry_.pop_front();
770-
if(covariances_.size())
771-
{
772-
covariance = covariances_.front();
773-
covariances_.pop_front();
774-
}
781+
UERROR("odometry cannot be used when startAt < 0");
775782
}
776783
if(groundTruth_.size())
777784
{
778-
groundTruthPose = groundTruth_.front();
779-
groundTruth_.pop_front();
785+
UERROR("groundTruth cannot be used when startAt < 0");
780786
}
781787
if(_models.size() && !model.isValidForProjection())
782788
{
783-
model = _models.front();
784-
_models.pop_front();
789+
UERROR("models cannot be used when startAt < 0");
785790
}
786791
}
787792
else
@@ -792,6 +797,7 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
792797
{
793798
imageFilePath = _path + imageFileName;
794799
scanFilePath = _scanPath + scanFileName;
800+
size_t stampsSize = _stamps.size();
795801
if(_stamps.size())
796802
{
797803
stamp = _stamps.front();
@@ -803,6 +809,8 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
803809
}
804810
if(odometry_.size())
805811
{
812+
UASSERT_MSG(stampsSize==0 || stampsSize == odometry_.size(),
813+
uFormat("Stamps=%ld odometry=%ld", _stamps.size(), odometry_.size()).c_str());
806814
odometryPose = odometry_.front();
807815
odometry_.pop_front();
808816
if(covariances_.size())
@@ -813,11 +821,15 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
813821
}
814822
if(groundTruth_.size())
815823
{
824+
UASSERT_MSG(stampsSize==0 || stampsSize == groundTruth_.size(),
825+
uFormat("Stamps=%ld groundTruth=%ld", _stamps.size(), groundTruth_.size()).c_str());
816826
groundTruthPose = groundTruth_.front();
817827
groundTruth_.pop_front();
818828
}
819829
if(_models.size() && !model.isValidForProjection())
820830
{
831+
UASSERT_MSG(stampsSize==0 || stampsSize == _models.size(),
832+
uFormat("Stamps=%ld models=%ld", _stamps.size(), _models.size()).c_str());
821833
model = _models.front();
822834
_models.pop_front();
823835
}
@@ -834,6 +846,7 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
834846

835847
imageFilePath = _path + imageFileName;
836848
scanFilePath = _scanPath + scanFileName;
849+
size_t stampsSize = _stamps.size();
837850
if(_stamps.size())
838851
{
839852
stamp = _stamps.front();
@@ -845,6 +858,8 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
845858
}
846859
if(odometry_.size())
847860
{
861+
UASSERT_MSG(stampsSize==0 || stampsSize == odometry_.size(),
862+
uFormat("Stamps=%ld odometry=%ld", stampsSize, odometry_.size()).c_str());
848863
odometryPose = odometry_.front();
849864
odometry_.pop_front();
850865
if(covariances_.size())
@@ -855,11 +870,15 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
855870
}
856871
if(groundTruth_.size())
857872
{
873+
UASSERT_MSG(stampsSize==0 || stampsSize == groundTruth_.size(),
874+
uFormat("Stamps=%ld groundTruth=%ld", _stamps.size(), groundTruth_.size()).c_str());
858875
groundTruthPose = groundTruth_.front();
859876
groundTruth_.pop_front();
860877
}
861878
if(_models.size() && !model.isValidForProjection())
862879
{
880+
UASSERT_MSG(stampsSize==0 || stampsSize == _models.size(),
881+
uFormat("Stamps=%ld models=%ld", _stamps.size(), _models.size()).c_str());
863882
model = _models.front();
864883
_models.pop_front();
865884
}

guilib/include/rtabmap/gui/PreferencesDialog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ class RTABMAP_GUI_EXPORT PreferencesDialog : public QDialog
293293
double getSourceScanForceGroundNormalsUp() const;
294294
Transform getSourceLocalTransform() const; //Openni group
295295
Transform getLaserLocalTransform() const; // directory images
296+
Transform getGroundTruthLocalTransform() const; // directory images
296297
Transform getIMULocalTransform() const; // directory images
297298
QString getIMUPath() const;
298299
int getIMURate() const;

guilib/src/MainWindow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3313,7 +3313,7 @@ void MainWindow::updateMapCloud(
33133313
{
33143314
std::string gtFrustumId = uFormat("f_gt_%d", iter->first);
33153315
color = Qt::gray;
3316-
_cloudViewer->addOrUpdateFrustum(gtFrustumId, _currentGTPosesMap.at(iter->first), t, _cloudViewer->getFrustumScale(), color, model.fovX(), model.fovY());
3316+
_cloudViewer->addOrUpdateFrustum(gtFrustumId, mapToGt*_currentGTPosesMap.at(iter->first), t, _cloudViewer->getFrustumScale(), color, model.fovX(), model.fovY());
33173317
}
33183318
}
33193319
}

0 commit comments

Comments
 (0)