Handling intial odometry pose in all odometry approaches. For VIO approaches, gravity initialization is handled too. (#298)

This commit is contained in:
matlabbe
2018-07-19 14:10:36 -04:00
parent 9ae47b79f9
commit 173bd49a26
12 changed files with 124 additions and 42 deletions

View File

@@ -55,6 +55,8 @@ private:
IMU lastImu_;
ParametersMap parameters_;
Transform flipXY_;
Transform previousPose_;
bool initGravity_;
#endif
};

View File

@@ -54,8 +54,9 @@ private:
#ifdef RTABMAP_ORB_SLAM2
ORBSLAM2System * orbslam2_;
bool firstFrame_;
#endif
Transform originLocalTransform_;
Transform previousPose_;
#endif
};

View File

@@ -59,6 +59,8 @@ private:
ParametersMap okvisParameters_;
IMU lastImu_; // only used for initialization
int imagesProcessed_;
Transform previousPose_;
bool initGravity_;
};
}

View File

@@ -2538,7 +2538,26 @@ Transform Memory::computeTransform(
{
int id = iter->first;
const Signature * s = this->getSignature(id);
CameraModel model = s->sensorData().cameraModels()[0];
CameraModel model;
if(s->sensorData().cameraModels().size() == 1 && s->sensorData().cameraModels().at(0).isValidForProjection())
{
model = s->sensorData().cameraModels()[0];
}
else if(s->sensorData().stereoCameraModel().isValidForProjection())
{
model = s->sensorData().stereoCameraModel().left();
// Set Tx for stereo BA
model = CameraModel(model.fx(),
model.fy(),
model.cx(),
model.cy(),
model.localTransform(),
-s->sensorData().stereoCameraModel().baseline()*model.fx());
}
else
{
UFATAL("no valid camera model to use local bundle adjustment on loop closure!");
}
bundleModels.insert(std::make_pair(id, model));
Transform invLocalTransform = model.localTransform().inverse();
if(iter->second.isValid())

View File

@@ -297,7 +297,7 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
R(0,0), R(0,1), R(0,2), 0,
R(1,0), R(1,1), R(1,2), 0,
R(2,0), R(2,1), R(2,2), coefficients.values.at(3));
_pose *= rotation;
this->reset(rotation);
success = true;
}
}
@@ -316,7 +316,7 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
Transform guess = dt>0.0 && guessFromMotion_ && !previousVelocityTransform_.isNull()?Transform::getIdentity():Transform();
if(!(dt>0.0 || (dt == 0.0 && previousVelocityTransform_.isNull())))
{
if(guessFromMotion_)
if(guessFromMotion_ && !data.imageRaw().empty())
{
UERROR("Guess from motion is set but dt is invalid! Odometry is then computed without guess. (dt=%f previous transform=%s)", dt, previousVelocityTransform_.prettyPrint().c_str());
}

View File

@@ -335,7 +335,7 @@ Transform OdometryF2M::computeTransform(
}
else
{
UFATAL("no valid camera model!");
UFATAL("no valid camera model to do odometry bundle adjustment!");
}
bundleModels.insert(std::make_pair(lastFrame_->id(), model));
Transform invLocalTransform = model.localTransform().inverse();

View File

@@ -747,7 +747,9 @@ OdometryMSCKF::OdometryMSCKF(const ParametersMap & parameters) :
imageProcessor_(0),
msckf_(0),
parameters_(parameters),
flipXY_(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0)
flipXY_(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0),
previousPose_(Transform::getIdentity()),
initGravity_(false)
#endif
{
}
@@ -771,17 +773,22 @@ void OdometryMSCKF::reset(const Transform & initialPose)
{
Odometry::reset(initialPose);
#ifdef RTABMAP_MSCKF_VIO
if(imageProcessor_)
if(!initGravity_)
{
delete imageProcessor_;
imageProcessor_ = 0;
if(imageProcessor_)
{
delete imageProcessor_;
imageProcessor_ = 0;
}
if(msckf_)
{
delete msckf_;
msckf_ = 0;
}
lastImu_ = IMU();
previousPose_.setIdentity();
}
if(msckf_)
{
delete msckf_;
msckf_ = 0;
}
lastImu_ = IMU();
initGravity_ = false;
#endif
}
@@ -898,10 +905,24 @@ Transform OdometryMSCKF::computeTransform(
if(!p.isNull())
{
// make it incremental
// pose in rtabmap/ros coordinates
p = flipXY_*p*lastImu_.localTransform();
Transform invCurrentPose = this->getPose().inverse();
t = invCurrentPose*p;
if(this->getPose().rotation().isIdentity())
{
initGravity_ = true;
this->reset(this->getPose()*p.rotation());
}
if(previousPose_.isIdentity())
{
previousPose_ = p;
}
// make it incremental
Transform previousPoseInv = previousPose_.inverse();
t = previousPoseInv*p;
previousPose_ = p;
if(info)
{
@@ -915,7 +936,7 @@ Transform OdometryMSCKF::computeTransform(
cv::Matx31f covWorldFrame(twistCov.at<double>(0, 0),
twistCov.at<double>(1, 1),
twistCov.at<double>(2, 2));
cv::Matx31f covBaseFrame = cv::Matx33f(invCurrentPose.rotationMatrix()) * covWorldFrame;
cv::Matx31f covBaseFrame = cv::Matx33f(previousPoseInv.rotationMatrix()) * covWorldFrame;
// we set only diagonal values as there is an issue with g2o and off-diagonal values
info->reg.covariance.at<double>(0, 0) = fabs(covBaseFrame.val[0])/10.0;
info->reg.covariance.at<double>(1, 1) = fabs(covBaseFrame.val[1])/10.0;
@@ -928,7 +949,7 @@ Transform OdometryMSCKF::computeTransform(
{
if(localMap.get() && localMap->size())
{
Eigen::Affine3f flip = flipXY_.toEigen3f();
Eigen::Affine3f flip = (this->getPose()*previousPoseInv*flipXY_).toEigen3f();
for(unsigned int i=0; i<localMap->size(); ++i)
{
pcl::PointXYZ pt = pcl::transformPoint(localMap->at(i), flip);
@@ -942,10 +963,12 @@ Transform OdometryMSCKF::computeTransform(
float fy = data.stereoCameraModel().left().fy();
float cx = data.stereoCameraModel().left().cx();
float cy = data.stereoCameraModel().left().cy();
info->reg.inliersIDs.resize(measurements->features.size());
for(unsigned int i=0; i<measurements->features.size(); ++i)
{
info->newCorners[i].x = measurements->features[i].u0*fx+cx;
info->newCorners[i].y = measurements->features[i].v0*fy+cy;
info->reg.inliersIDs[i] = i;
}
}
}

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/UTimer.h"
#include "rtabmap/utilite/UStl.h"
#include "rtabmap/utilite/UDirectory.h"
#include <pcl/common/transforms.h>
#ifdef RTABMAP_ORB_SLAM2
#include <System.h>
@@ -813,7 +814,8 @@ OdometryORBSLAM2::OdometryORBSLAM2(const ParametersMap & parameters) :
#ifdef RTABMAP_ORB_SLAM2
,
orbslam2_(0),
firstFrame_(true)
firstFrame_(true),
previousPose_(Transform::getIdentity())
#endif
{
#ifdef RTABMAP_ORB_SLAM2
@@ -841,6 +843,7 @@ void OdometryORBSLAM2::reset(const Transform & initialPose)
}
firstFrame_ = true;
originLocalTransform_.setNull();
previousPose_.setIdentity();
#endif
}
@@ -908,23 +911,29 @@ Transform OdometryORBSLAM2::computeTransform(
Tcw = ((ORB_SLAM2::Tracker*)orbslam2_->mpTracker)->GrabImageRGBD(data.imageRaw(), depth, data.stamp());
}
Transform previousPoseInv = previousPose_.inverse();
if(orbslam2_->mpTracker->mState == ORB_SLAM2::Tracking::LOST)
{
covariance = cv::Mat::eye(6,6,CV_64FC1)*9999.0f;
}
else if(Tcw.cols == 4 && Tcw.rows == 4)
{
t = Transform(cv::Mat(Tcw, cv::Range(0,3), cv::Range(0,4)));
Transform p = Transform(cv::Mat(Tcw, cv::Range(0,3), cv::Range(0,4)));
if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull())
if(!p.isNull())
{
if(originLocalTransform_.isNull())
if(!localTransform.isNull())
{
originLocalTransform_ = localTransform;
if(originLocalTransform_.isNull())
{
originLocalTransform_ = localTransform;
}
// transform in base frame
p = originLocalTransform_ * p.inverse() * localTransform.inverse();
}
t = originLocalTransform_ * t.inverse() * localTransform.inverse();
t = this->getPose().inverse() * t;
t = previousPoseInv*p;
}
previousPose_ = p;
if(firstFrame_)
{
@@ -1004,10 +1013,12 @@ Transform OdometryORBSLAM2::computeTransform(
info->reg.matches = oi;
std::vector<ORB_SLAM2::MapPoint*> mapPoints = orbslam2_->mpMap->GetAllMapPoints();
Eigen::Affine3f fixRot = (this->getPose()*previousPoseInv*originLocalTransform_).toEigen3f();
for (unsigned int i = 0; i < mapPoints.size(); ++i)
{
cv::Mat pt = mapPoints[i]->GetWorldPos();
info->localMap.insert(std::make_pair(mapPoints[i]->mnId, util3d::transformPoint(cv::Point3f(pt), originLocalTransform_)));
cv::Point3f pt(mapPoints[i]->GetWorldPos());
pcl::PointXYZ ptt = pcl::transformPoint(pcl::PointXYZ(pt.x, pt.y, pt.z), fixRot);
info->localMap.insert(std::make_pair(mapPoints[i]->mnId, cv::Point3f(ptt.x, ptt.y, ptt.z)));
}
}
}

View File

@@ -133,7 +133,9 @@ OdometryOkvis::OdometryOkvis(const ParametersMap & parameters) :
okvisEstimator_(0),
#endif
okvisParameters_(parameters),
imagesProcessed_(0)
imagesProcessed_(0),
previousPose_(Transform::getIdentity()),
initGravity_(false)
{
#ifdef RTABMAP_OKVIS
Parameters::parse(parameters, Parameters::kOdomOKVISConfigPath(), configFilename_);
@@ -160,17 +162,22 @@ void OdometryOkvis::reset(const Transform & initialPose)
{
Odometry::reset(initialPose);
#ifdef RTABMAP_OKVIS
if(okvisEstimator_)
if(!initGravity_)
{
delete okvisEstimator_;
okvisEstimator_ = 0;
}
lastImu_ = IMU();
if(okvisEstimator_)
{
delete okvisEstimator_;
okvisEstimator_ = 0;
}
lastImu_ = IMU();
imagesProcessed_ = 0;
previousPose_.setIdentity();
delete okvisCallbackHandler_;
okvisCallbackHandler_ = new OkvisCallbackHandler();
delete okvisCallbackHandler_;
okvisCallbackHandler_ = new OkvisCallbackHandler();
}
initGravity_ = false;
#endif
imagesProcessed_ = 0;
}
// return not null transform if odometry is correctly computed
@@ -452,8 +459,21 @@ Transform OdometryOkvis::computeTransform(
if(!p.isNull())
{
p = fixPos * p * fixRot;
if(this->getPose().rotation().isIdentity())
{
initGravity_ = true;
this->reset(this->getPose()*p.rotation());
}
if(previousPose_.isIdentity())
{
previousPose_ = p;
}
// make it incremental
t = this->getPose().inverse()*p;
t = previousPose_.inverse()*p;
previousPose_ = p;
if(info)
{

View File

@@ -2361,7 +2361,7 @@ bool Rtabmap::process(
}
if(maxLinearLink)
{
UINFO("Max optimization error = %f m (link %d->%d, var=%f, %f)", maxLinearError, maxLinearLink->from(), maxLinearLink->to(), maxLinearLink->transVariance(), maxLinearError/sqrt(maxLinearLink->transVariance()));
UINFO("Max optimization error = %f m (link %d->%d, var=%f, ratio error/std=%f)", maxLinearError, maxLinearLink->from(), maxLinearLink->to(), maxLinearLink->transVariance(), maxLinearError/sqrt(maxLinearLink->transVariance()));
float stddev = sqrt(maxLinearLink->transVariance());
maxLinearErrorRatio = maxLinearError/stddev;