Esempio n. 1
0
void RGBDOdometry::getIncrementalTransformation(Eigen::Vector3f & trans,
                                                Eigen::Matrix<float, 3, 3, Eigen::RowMajor> & rot,
                                                const bool & rgbOnly,
                                                const float & icpWeight,
                                                const bool & pyramid,
                                                const bool & fastOdom,
                                                const bool & so3)
{
    bool icp = !rgbOnly && icpWeight > 0;
    bool rgb = rgbOnly || icpWeight < 100;

    Eigen::Matrix<float, 3, 3, Eigen::RowMajor> Rprev = rot;
    Eigen::Vector3f tprev = trans;

    Eigen::Matrix<float, 3, 3, Eigen::RowMajor> Rcurr = Rprev;
    Eigen::Vector3f tcurr = tprev;

    if(rgb)
    {
        for(int i = 0; i < NUM_PYRS; i++)
        {
            computeDerivativeImages(nextImage[i], nextdIdx[i], nextdIdy[i]);
        }
    }

    Eigen::Matrix<double, 3, 3, Eigen::RowMajor> resultR = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>::Identity();

    if(so3)
    {
        int pyramidLevel = 2;

        Eigen::Matrix<float, 3, 3, Eigen::RowMajor> R_lr = Eigen::Matrix<float, 3, 3, Eigen::RowMajor>::Identity();

        Eigen::Matrix<double, 3, 3, Eigen::RowMajor> K = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>::Zero();

        K(0, 0) = intr(pyramidLevel).fx;
        K(1, 1) = intr(pyramidLevel).fy;
        K(0, 2) = intr(pyramidLevel).cx;
        K(1, 2) = intr(pyramidLevel).cy;
        K(2, 2) = 1;

        float lastError = std::numeric_limits<float>::max() / 2;
        float lastCount = std::numeric_limits<float>::max() / 2;

        Eigen::Matrix<double, 3, 3, Eigen::RowMajor> lastResultR = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>::Identity();

        for(int i = 0; i < 10; i++)
        {
            Eigen::Matrix<float, 3, 3, Eigen::RowMajor> jtj;
            Eigen::Matrix<float, 3, 1> jtr;

            Eigen::Matrix<double, 3, 3, Eigen::RowMajor> homography = K * resultR * K.inverse();

            mat33 imageBasis;
            memcpy(&imageBasis.data[0], homography.cast<float>().eval().data(), sizeof(mat33));

            Eigen::Matrix<double, 3, 3, Eigen::RowMajor> K_inv = K.inverse();
            mat33 kinv;
            memcpy(&kinv.data[0], K_inv.cast<float>().eval().data(), sizeof(mat33));

            Eigen::Matrix<double, 3, 3, Eigen::RowMajor> K_R_lr = K * resultR;
            mat33 krlr;
            memcpy(&krlr.data[0], K_R_lr.cast<float>().eval().data(), sizeof(mat33));

            float residual[2];

            TICK("so3Step");
            so3Step(lastNextImage[pyramidLevel],
                    nextImage[pyramidLevel],
                    imageBasis,
                    kinv,
                    krlr,
                    sumDataSO3,
                    outDataSO3,
                    jtj.data(),
                    jtr.data(),
                    &residual[0],
                    GPUConfig::getInstance().so3StepThreads,
                    GPUConfig::getInstance().so3StepBlocks);
            TOCK("so3Step");

            lastSO3Error = sqrt(residual[0]) / residual[1];
            lastSO3Count = residual[1];

            //Converged
            if(lastSO3Error < lastError && lastCount == lastSO3Count)
            {
                break;
            }
            else if(lastSO3Error > lastError + 0.001) //Diverging
            {
                lastSO3Error = lastError;
                lastSO3Count = lastCount;
                resultR = lastResultR;
                break;
            }

            lastError = lastSO3Error;
            lastCount = lastSO3Count;
            lastResultR = resultR;

            Eigen::Vector3f delta = jtj.ldlt().solve(jtr);

            Eigen::Matrix<double, 3, 3, Eigen::RowMajor> rotUpdate = OdometryProvider::rodrigues(delta.cast<double>());

            R_lr = rotUpdate.cast<float>() * R_lr;

            for(int x = 0; x < 3; x++)
            {
                for(int y = 0; y < 3; y++)
                {
                    resultR(x, y) = R_lr(x, y);
                }
            }
        }
    }

    iterations[0] = fastOdom ? 3 : 10;
    iterations[1] = pyramid ? 5 : 0;
    iterations[2] = pyramid ? 4 : 0;

    Eigen::Matrix<float, 3, 3, Eigen::RowMajor> Rprev_inv = Rprev.inverse();
    mat33 device_Rprev_inv = Rprev_inv;
    float3 device_tprev = *reinterpret_cast<float3*>(tprev.data());

    Eigen::Matrix<double, 4, 4, Eigen::RowMajor> resultRt = Eigen::Matrix<double, 4, 4, Eigen::RowMajor>::Identity();

    if(so3)
    {
        for(int x = 0; x < 3; x++)
        {
            for(int y = 0; y < 3; y++)
            {
                resultRt(x, y) = resultR(x, y);
            }
        }
    }

    for(int i = NUM_PYRS - 1; i >= 0; i--)
    {
        if(rgb)
        {
            projectToPointCloud(lastDepth[i], pointClouds[i], intr, i);
        }

        Eigen::Matrix<double, 3, 3, Eigen::RowMajor> K = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>::Zero();

        K(0, 0) = intr(i).fx;
        K(1, 1) = intr(i).fy;
        K(0, 2) = intr(i).cx;
        K(1, 2) = intr(i).cy;
        K(2, 2) = 1;

        lastRGBError = std::numeric_limits<float>::max();

        for(int j = 0; j < iterations[i]; j++)
        {
            Eigen::Matrix<double, 4, 4, Eigen::RowMajor> Rt = resultRt.inverse();

            Eigen::Matrix<double, 3, 3, Eigen::RowMajor> R = Rt.topLeftCorner(3, 3);

            Eigen::Matrix<double, 3, 3, Eigen::RowMajor> KRK_inv = K * R * K.inverse();
            mat33 krkInv;
            memcpy(&krkInv.data[0], KRK_inv.cast<float>().eval().data(), sizeof(mat33));

            Eigen::Vector3d Kt = Rt.topRightCorner(3, 1);
            Kt = K * Kt;
            float3 kt = {(float)Kt(0), (float)Kt(1), (float)Kt(2)};

            int sigma = 0;
            int rgbSize = 0;

            if(rgb)
            {
                TICK("computeRgbResidual");
                computeRgbResidual(pow(minimumGradientMagnitudes[i], 2.0) / pow(sobelScale, 2.0),
                                   nextdIdx[i],
                                   nextdIdy[i],
                                   lastDepth[i],
                                   nextDepth[i],
                                   lastImage[i],
                                   nextImage[i],
                                   corresImg[i],
                                   sumResidualRGB,
                                   maxDepthDeltaRGB,
                                   kt,
                                   krkInv,
                                   sigma,
                                   rgbSize,
                                   GPUConfig::getInstance().rgbResThreads,
                                   GPUConfig::getInstance().rgbResBlocks);
                TOCK("computeRgbResidual");
            }

            float sigmaVal = std::sqrt((float)sigma / rgbSize == 0 ? 1 : rgbSize);
            float rgbError = std::sqrt(sigma) / (rgbSize == 0 ? 1 : rgbSize);

            if(rgbOnly && rgbError > lastRGBError)
            {
                break;
            }

            lastRGBError = rgbError;
            lastRGBCount = rgbSize;

            if(rgbOnly)
            {
                sigmaVal = -1; //Signals the internal optimisation to weight evenly
            }

            Eigen::Matrix<float, 6, 6, Eigen::RowMajor> A_icp;
            Eigen::Matrix<float, 6, 1> b_icp;

            mat33 device_Rcurr = Rcurr;
            float3 device_tcurr = *reinterpret_cast<float3*>(tcurr.data());

            DeviceArray2D<float>& vmap_curr = vmaps_curr_[i];
            DeviceArray2D<float>& nmap_curr = nmaps_curr_[i];

            DeviceArray2D<float>& vmap_g_prev = vmaps_g_prev_[i];
            DeviceArray2D<float>& nmap_g_prev = nmaps_g_prev_[i];

            float residual[2];

            if(icp)
            {
                TICK("icpStep");
                icpStep(device_Rcurr,
                        device_tcurr,
                        vmap_curr,
                        nmap_curr,
                        device_Rprev_inv,
                        device_tprev,
                        intr(i),
                        vmap_g_prev,
                        nmap_g_prev,
                        distThres_,
                        angleThres_,
                        sumDataSE3,
                        outDataSE3,
                        A_icp.data(),
                        b_icp.data(),
                        &residual[0],
                        GPUConfig::getInstance().icpStepThreads,
                        GPUConfig::getInstance().icpStepBlocks);
                TOCK("icpStep");
            }

            lastICPError = sqrt(residual[0]) / residual[1];
            lastICPCount = residual[1];

            Eigen::Matrix<float, 6, 6, Eigen::RowMajor> A_rgbd;
            Eigen::Matrix<float, 6, 1> b_rgbd;

            if(rgb)
            {
                TICK("rgbStep");
                rgbStep(corresImg[i],
                        sigmaVal,
                        pointClouds[i],
                        intr(i).fx,
                        intr(i).fy,
                        nextdIdx[i],
                        nextdIdy[i],
                        sobelScale,
                        sumDataSE3,
                        outDataSE3,
                        A_rgbd.data(),
                        b_rgbd.data(),
                        GPUConfig::getInstance().rgbStepThreads,
                        GPUConfig::getInstance().rgbStepBlocks);
                TOCK("rgbStep");
            }

            Eigen::Matrix<double, 6, 1> result;
            Eigen::Matrix<double, 6, 6, Eigen::RowMajor> dA_rgbd = A_rgbd.cast<double>();
            Eigen::Matrix<double, 6, 6, Eigen::RowMajor> dA_icp = A_icp.cast<double>();
            Eigen::Matrix<double, 6, 1> db_rgbd = b_rgbd.cast<double>();
            Eigen::Matrix<double, 6, 1> db_icp = b_icp.cast<double>();

            if(icp && rgb)
            {
                double w = icpWeight;
                lastA = dA_rgbd + w * w * dA_icp;
                lastb = db_rgbd + w * db_icp;
                result = lastA.ldlt().solve(lastb);
            }
            else if(icp)
            {
                lastA = dA_icp;
                lastb = db_icp;
                result = lastA.ldlt().solve(lastb);
            }
            else if(rgb)
            {
                lastA = dA_rgbd;
                lastb = db_rgbd;
                result = lastA.ldlt().solve(lastb);
            }
            else
            {
                assert(false && "Control shouldn't reach here");
            }

            Eigen::Isometry3f rgbOdom;

            OdometryProvider::computeUpdateSE3(resultRt, result, rgbOdom);

            Eigen::Isometry3f currentT;
            currentT.setIdentity();
            currentT.rotate(Rprev);
            currentT.translation() = tprev;

            currentT = currentT * rgbOdom.inverse();

            tcurr = currentT.translation();
            Rcurr = currentT.rotation();
        }
    }

    if(rgb && (tcurr - tprev).norm() > 0.3)
    {
        Rcurr = Rprev;
        tcurr = tprev;
    }

    if(so3)
    {
        for(int i = 0; i < NUM_PYRS; i++)
        {
            std::swap(lastNextImage[i], nextImage[i]);
        }
    }

    trans = tcurr;
    rot = Rcurr;
}
Esempio n. 2
0
void DuoAvoidance::duoMessageCb(const ait_ros_messages::VioSensorMsg::ConstPtr &msg) {

ait_ros_messages::VioSensorMsg duo_msg_  = *msg;
printf("Received message from Duo3d-Cam. Timestamp: %d.%d\n",duo_msg_.header.stamp.sec,duo_msg_.header.stamp.nsec);

//Use cv_bridge to transform images to cv::Mat
cv::Mat img_l_=cv_bridge::toCvCopy(duo_msg_.left_image,"mono8")->image;
cv::Mat img_r_=cv_bridge::toCvCopy(duo_msg_.right_image,"mono8")->image;


cv::Mat left_disp;
cv::Mat right_disp;
cv::Mat left;
cv::Mat right;
left  = img_l_.clone();
right = img_r_.clone();
cv::Size img_size =img_l_.size();

//Camera Calibration Parameters of left Camera
cv::Mat distortion_cam1(1,5,CV_64FC1,cvScalar(0.));
distortion_cam1.at<double>(0,0)=-0.4186;
distortion_cam1.at<double>(0,1)=0.2771;
distortion_cam1.at<double>(0,4)=-0.1375;

cv::Mat intrinsics_cam1(3,3,CV_64FC1,cvScalar(0.));
intrinsics_cam1.at<double>(0,0)=269.181725;	//fx Focal Length
intrinsics_cam1.at<double>(1,1)=269.9321;	//fy Focal Length
intrinsics_cam1.at<double>(0,2)=156.3816;	//x0 Principal Point
intrinsics_cam1.at<double>(1,2)=113.9369;	//y0 Principal Point
intrinsics_cam1.at<double>(2,2)=1.;

//Camera calibration parameters of right Camera
cv::Mat distortion_cam2(1,5,CV_64FC1,cvScalar(0.));
distortion_cam2.at<double>(0,0)=-0.4233;
distortion_cam2.at<double>(0,1)=0.2967;
distortion_cam2.at<double>(0,4)=-0.1663;

cv::Mat intrinsics_cam2(3,3,CV_64FC1,cvScalar(0.));
intrinsics_cam2.at<double>(0,0)=270.1185;	//fx Focal Length
intrinsics_cam2.at<double>(1,1)=270.7983;	//fy Focal Length
intrinsics_cam2.at<double>(0,2)=163.4106;	//x0 Principal Point
intrinsics_cam2.at<double>(1,2)=120.1803;	//y0 Principal Point
intrinsics_cam2.at<double>(2,2)=1.;

//Rotation Matrix R_lr
cv::Mat R_lr(3,3,CV_64FC1,cvScalar(0.));
R_lr.at<double>(0,0)=1.;	R_lr.at<double>(0,1)=0.0018258;	R_lr.at<double>(0,2)=0.0028920;
R_lr.at<double>(1,0)=-0.0018415;R_lr.at<double>(1,1)=1.;	R_lr.at<double>(1,2)=0.005452;
R_lr.at<double>(2,0)=0.0028820;	R_lr.at<double>(2,1)=-0.0054579;R_lr.at<double>(2,2)=1.;

//Translation r_lr
cv::Mat r_lr(3,1,CV_64FC1,cvScalar(0.));
r_lr.at<double>(0,0)=30.5341;
r_lr.at<double>(1,0)=-0.2507;
r_lr.at<double>(2,0)=-1.6489;



//Define StereoRectify Outputs
cv::Mat R1(3,3,CV_64FC1,cvScalar(0.));
cv::Mat R2(3,3,CV_64FC1,cvScalar(0.));
cv::Mat P1(3,4,CV_64FC1,cvScalar(0.));
cv::Mat P2(3,4,CV_64FC1,cvScalar(0.));
cv::Mat Q(4,4,CV_64FC1,cvScalar(0.));

cv::Rect validRoi[2];

//Calculate the Stereo Rectification
cv::stereoRectify(	intrinsics_cam1,distortion_cam1,
			intrinsics_cam2,distortion_cam2,
			img_size, R_lr.inv(), r_lr, R1, R2, P1, P2, Q,
			cv::CALIB_ZERO_DISPARITY, 1, img_size, &validRoi[0], &validRoi[1]);

//Prepare remapping & remap (undistort)
cv::Mat rmap[2][2];
cv::initUndistortRectifyMap(intrinsics_cam1, distortion_cam1, R1, P1, img_size, CV_16SC2, rmap[0][0], rmap[0][1]);
cv::initUndistortRectifyMap(intrinsics_cam2, distortion_cam2, R2, P2, img_size, CV_16SC2, rmap[1][0], rmap[1][1]);

remap(img_l_,left,rmap[0][0],rmap[0][1],cv::INTER_LINEAR);
remap(img_r_,right,rmap[1][0],rmap[1][1],cv::INTER_LINEAR);

//crop_img to be rectangular again and resize to initial size
cv::Mat cropped_left=left(validRoi[0]);
cv::Mat cropped_right=right(validRoi[1]);
cv::Mat resized_left;
cv::Mat resized_right;
cv::resize(cropped_left,resized_left,img_size,0,0,cv::INTER_AREA);
cv::resize(cropped_right,resized_right,img_size,0,0,cv::INTER_AREA);


//append Image on left side to not get cropped result
cv::Mat img_l_app(img_size.height,img_size.width+90,0,cvScalar(0.));
cv::Mat img_r_app(img_size.height,img_size.width+90,0,cvScalar(0.));
img_l_.copyTo(img_l_app(cv::Rect(90,0,img_l_.cols,img_l_.rows)));
img_r_.copyTo(img_r_app(cv::Rect(90,0,img_r_.cols,img_r_.rows)));

//Calculate disparity
int max_disp=64;
int wsize=25;
cv::StereoBM sbm(cv::StereoBM::BASIC_PRESET,max_disp,wsize);
sbm(resized_left,resized_right,left_disp,CV_16S);
sbm(img_l_app,img_r_app,left_disp,CV_16S);
left_disp=left_disp(cv::Rect(90,0,img_r_.cols,img_r_.rows));

//Alternatively calculation with stereSGBM (Semi Global Block Matching) but 10x more expensive
//cv::StereoSGBM sbm;
//sbm.SADWindowSize = 15;
//sbm.numberOfDisparities = 64;
//sbm.preFilterCap = 63;
//sbm.minDisparity = -2;
//sbm.uniquenessRatio= 30;
//sbm.speckleWindowSize = 100;
//sbm.speckleRange = 32;
//sbm.disp12MaxDiff =1;
//sbm.fullDP=false;
//sbm.P1=100;
//sbm.P2=200;
//sbm(resized_left,resized_right,left_disp);


//Convert to 8bit
left_disp.convertTo(left_disp,0);


// //Debug: Republish left image
 cv_bridge::CvImage cv_out1;
 cv_out1.image=img_l_app;
 cv_out1.encoding="mono8";
 cv_out1.toImageMsg(test_output1_);
 test_pub1_.publish(test_output1_);

 cv_bridge::CvImage cv_out2;
 cv_out2.image=left_disp;
 cv_out2.encoding="mono8";
 cv_out2.toImageMsg(test_output2_);
 test_pub2_.publish(test_output2_);

}