深蓝slam作业

第二节解决Odom_Calib.cpp中solve函数:中有一个这样的代码

Eigen::Matrix3d OdomCalib::Solve()
{
    Eigen::Matrix3d correct_matrix;
 
    //TODO: 求解线性最小二乘
    // Eigen::Matrix<double, 9, 1> params;
    // // params = (A.transpose() * A).inverse() * A.transpose() * b;
    // params = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
    // std::cout << params.transpose() << std::endl;
    // for (size_t i = 0; i < 3; i++) {
    //     correct_matrix.block<1, 3>(i, 0) = params.block<3, 1>(i * 3, 0).transpose();
    // }
    Eigen::Matrix<double,9,1> X_ = A.colPivHouseholderQr().solve(b);
    correct_matrix << X_(0),X_(1),X_(2),X_(3),X_(4),X_(5),X_(6),X_(7),X_(8);
    //end of TODO
 
    return correct_matrix;
}

此处的Eigen::Matrix<double,9,1> X_ = A.colPivHouseholderQr().solve(b);使用来解方程Ax=b的;函数 A.colPivHouseholderQr().solve(b)。就是一个解这个函数的的函数。

构造最小二乘的函数:

bool OdomCalib::Add_Data(Eigen::Vector3d Odom,Eigen::Vector3d scan)
{

    if(now_len<INT_MAX)
    {
        //TODO: 
        A(now_len%data_len*3,0)=Odom(0);
        A(now_len%data_len*3,1)=Odom(1);
        A(now_len%data_len*3,2)=Odom(2);
        A(now_len%data_len*3+1,3)=Odom(0);
        A(now_len%data_len*3+1,4)=Odom(1);
        A(now_len%data_len*3+1,5)=Odom(2);
        A(now_len%data_len*3+2,6)=Odom(0);
        A(now_len%data_len*3+2,7)=Odom(1);
        A(now_len%data_len*3+2,8)=Odom(2);

        b(now_len%data_len*3)=scan(0);
        b(now_len%data_len*3+1)=scan(1);
        b(now_len%data_len*3+2)=scan(2);

        //end of TODO
        now_len++;
        return true;
    }
    else
    {
        return false;
    }
}

计算位姿差函数:

//求解得到两帧数据之间的位姿差
//即求解当前位姿 在 上一时刻 坐标系中的坐标
Eigen::Vector3d cal_delta_distence(Eigen::Vector3d odom_pose)
{
 
    Eigen::Vector3d d_pos; //return value
    now_pos = odom_pose;
    //TODO:
    //向量旋转的方方式,轴角
    d_pos = now_pos - last_pos;
    Eigen::AngleAxisd temp(last_pos(2),Eigen::Vector3d(0,0,1));
    Eigen::Matrix3d trans=temp.matrix().inverse();
    d_pos = trans*d_pos;
    last_pos = now_pos; 
//方法二矩阵的方式
//    Eigen::Matrix3d trans_temp;
//    trans_temp<< cos(last_pos(2)), -sin(last_pos(2)), 0,
//            sin(last_pos(2)), cos(last_pos(2)),  0,
//            0,                           0,                       1;
//
//    d_pos = now_pos - last_pos;
//    d_pos = trans_temp.transpose()*d_pos;
//    last_pos = now_pos;
 
    //end of TODO:
    return d_pos;
}
----------------------------
Eigen::Vector3d  cal_delta_distence(Eigen::Vector3d odom_pose)
{

    Eigen::Vector3d d_pos;  //return value
    now_pos = odom_pose;

    //TODO:

    Eigen::Matrix3d Tnow,Tprev;

    double theta = last_pos(2);
    double x = last_pos(0);
    double y = last_pos(1);

    Tprev << cos(theta),-sin(theta),x,
             sin(theta), cos(theta),y,
                      0,          0,       1;

   
    x = now_pos(0);
    y = now_pos(1);
    theta = now_pos(2);
    Tnow << cos(theta),-sin(theta),x,
             sin(theta), cos(theta),y,
                      0,          0,       1;

 
    Eigen::Matrix3d T = Tprev.inverse() * Tnow;

    d_pos(0) = T(0,2);
    d_pos(1) = T(1,2);
    d_pos(2) = atan2(T(1,0),T(0,0));

    //end of TODO:

    return d_pos;
}

 svd分解的意思是将矩阵携程由三个部分相乘的形式

 

第三节:运动畸变去除

 void Lidar_MotionCalibration(
        tf::Stamped<tf::Pose> frame_base_pose,
        tf::Stamped<tf::Pose> frame_start_pose,
        tf::Stamped<tf::Pose> frame_end_pose,
        std::vector<double>& ranges,
        std::vector<double>& angles,
        int startIndex,
        int& beam_number)
    {
        //TODO
        // frame_base_pose.inverse;
        tf::Quaternion start_q = frame_start_pose.getRotation();
        tf::Quaternion end_q = frame_end_pose.getRotation();
        tf::Vector3 start_xy(frame_start_pose.getOrigin().getX(), frame_start_pose.getOrigin().getY(), 1);
        tf::Vector3 end_xy(frame_end_pose.getOrigin().getX(), frame_end_pose.getOrigin().getY(), 1);
 
        for (size_t i = startIndex; i < startIndex + beam_number; i++) {
            tf::Vector3 mid_xy = start_xy.lerp(end_xy, (i - startIndex) / (beam_number - 1));
            tf::Quaternion mid_q = start_q.slerp(end_q, (i - startIndex) / (beam_number - 1));
            tf::Transform mid_frame(mid_q, mid_xy);
            double x = ranges[i] * cos(angles[i]);
            double y = ranges[i] * sin(angles[i]);
            tf::Vector3 calib_point = frame_base_pose.inverse() * mid_frame * tf::Vector3(x, y, 1);
            ranges[i] = sqrt(calib_point[0] * calib_point[0] + calib_point[1] * calib_point[1]);
            angles[i] = atan2(calib_point[1], calib_point[0]);
        }
        //end of TODO
    }

原文链接:https://blog.csdn.net/p942005405/article/details/119494918

第六节:图优化:激光SLAM理论与实践 第六次作业(G2o 优化方法)_激光slam从理论到实践 作业-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值