美文网首页
标定eai二维雷达和Imu

标定eai二维雷达和Imu

作者: 送分童子笑嘻嘻 | 来源:发表于2019-10-17 20:23 被阅读0次

    //
    // Created by cai on 19-10-14.
    //
    利用机器人匀速直线运动时,两者的相对位姿不会变,联立多次直线运动的速度方向求解相对位姿
    缺点和不足,imu数据的时间没分配好,手移动机器人,有微小旋转,需要对角速度积分,Imu坐标系有点奇怪

    #include "ros/ros.h"
    #include <iostream>
    #include "std_msgs/String.h"
    #include "sensor_msgs/LaserScan.h"
    #include "sensor_msgs/Imu.h"
    #include <vector>
    #include <string>
    #include <math.h>
    #include <thread>
    using namespace std;
    
    vector<sensor_msgs::LaserScan::ConstPtr> scanMsgList;
    vector<sensor_msgs::Imu::ConstPtr> imuMsgList;
    
    
    //是由laserScan判断当前是直线运动还是由imu判断当前是直线运动,当用激光雷达判断是直线运动的时候,将序列
    //中第一个scanmsg的时间戳和最后scanmsg的时间戳中间的imu的数据的xy值的和取平均值
    //有的激光点扫到的距离为0要去掉,不然影响结果,
    void scanCallback(const sensor_msgs::LaserScan::ConstPtr &msg) {
        scanMsgList.push_back(msg);
    //    uint64_t nsec = msg->header.stamp.toNSec();
    //    uint64_t sec = msg->header.stamp.toSec();
    //    cout << "scanMsgListsec=" << sec << endl;
    //    cout << "scanMsgListnsec=" << nsec << endl;
    //    __pid_t pid = getpid();
    //    cout << "scanpid=" << pid << endl;
        int meglen = 10;
         if (scanMsgList.size() > meglen) {
           // if (false) {
            cout << "-----------------------------------------------"<<endl;
            //判断现在是否在直线运动
            //雷达每转4次取平均值吧
            //找到gap最小的
            float gap_min = 10;
            int i_gap_min = 0;
            float dis_gap_min = 0;
            for (int i = 0; i < 45; ++i) {
                int not0_a = 0,not0_b = 0;
                float dis_sum_a = 0,dis_sum_b  = 0;
                float dis_rev_a = 0,dis_rev_b  = 0;
                for (int j = 0; j < 8; ++j) {
                    //0到360
                    float x_a = scanMsgList[0]->ranges[i * 8 + j];
                    if ( x_a!= 0) {
                        not0_a++;
                        dis_sum_a += x_a;
                    }
                    //360-720
                    float x_b = scanMsgList[0]->ranges[i * 8 + j + 360];
                    if ( x_b!= 0) {
                        not0_b++;
                        dis_sum_b += x_b;
                    }
                    dis_rev_a = dis_sum_a / not0_a;
                    dis_rev_b = dis_sum_b / not0_b;
                }
                //---------------------------------------------------------------
                int not0_a2 = 0,not0_b2 = 0;
                float dis_sum_a2 = 0,dis_sum_b2  = 0;
                float dis_rev_a2 = 0,dis_rev_b2  = 0;
                for (int j = 0; j < 8; ++j) {
                    //0到360
                    float x_a2 = scanMsgList[meglen]->ranges[i * 8 + j];
                    if ( x_a2!= 0) {
                        not0_a2++;
                        dis_sum_a2 += x_a2;
                    }
                    //360-720
                    float x_b2 = scanMsgList[meglen]->ranges[i * 8 + j + 360];
                    if ( x_b2!= 0) {
                        not0_b2++;
                        dis_sum_b2 += x_b2;
                    }
                    dis_rev_a2 = dis_sum_a2 / not0_a2;
                    dis_rev_b2 = dis_sum_b2 / not0_b2;
                }
                float d_increate = abs(dis_rev_a2 - dis_rev_a);
                float d_reduce = abs(dis_rev_b2 - dis_rev_b);
                //在一次运动中检测出不平行的直线运动
                //cout << "d_increate=" << d_increate << endl;
                //cout << "d_reduce=" <<  d_reduce<< endl;
                //距离减少和增加的差值
                float gap = abs(abs(d_increate )- abs(d_reduce));
                if (gap < gap_min) {
                    gap_min = gap;
                    i_gap_min = i;
                    dis_gap_min = d_increate;
                }
            }
    
    
                cout << "gap_min=" << gap_min << endl;
                cout << "i_gap_min=" << i_gap_min << endl;
                cout << "dis_gap_min=" << dis_gap_min << endl;
                if (gap_min < 0.015 && dis_gap_min > 0.15) {
                    //是做直线运动
                    cout << "linear"<<endl;
                    //时间
                    //开始时间
                    uint64_t begin_lidar_nsec = scanMsgList[0]->header.stamp.toNSec();
                    //结束时间 
                    uint64_t end_lidar_nsec = scanMsgList[meglen]->header.stamp.toNSec();
                    cout << "begin_lidar_sec=" << begin_lidar_nsec << endl;
                    cout << "end_lidar_sec=" << end_lidar_nsec << endl;
    
                    //结束时间
                    uint64_t time = end_lidar_nsec-begin_lidar_nsec;
                    int64_t n1time = (int64_t) time;
                    double n2time = (double) n1time;
                    cout << "time=" << time << endl;
                    cout << "n1time=" << n1time << endl;
                    cout << "n2time=" << n2time << endl;
                    //求速度的模
                    float vec = dis_gap_min*1000000000ul/n2time;
    
                    cout << "vec=" << vec << endl;
                    //求速度的
                    float theta = i_gap_min*4*(M_PI/180);
    
                    cout << "cos(theta-180)=" << cos(theta-M_PI) << endl;
                    cout << "sin(theta-180)=" << sin(theta-M_PI) << endl;
                    float x = vec * cos(theta-M_PI);
                    float y = vec * sin(theta-M_PI);
                    cout << "theta=" << theta << endl;
                    cout << "x=" << x << endl;
                    cout << "y=" << y << endl;
                    //得到imu
                    //得到时间在激光雷达运动时间内的
                    int imu_begin_i = -1;
                    int imu_end_i = -1;
                    for (int i = 0; i < imuMsgList.size(); ++i) {
                        cout << "imuMsgList[i]->header.stamp.toNSec()=" << imuMsgList[i]->header.stamp.toNSec() << endl;
                        if ((imuMsgList[i]->header.stamp.toNSec() > begin_lidar_nsec)) {
                            imu_begin_i = i;
                            break;
                        }
                    }
                    for (int j = imuMsgList.size()-1; j >-1; --j) {
                        cout << "imuMsgList[j]->header.stamp.toNSec()=" << imuMsgList[j]->header.stamp.toNSec() << endl;
                        if ((imuMsgList[j]->header.stamp.toNSec() < end_lidar_nsec) ) {
                            imu_end_i = j;
                            break;
                        }
                    }
                    cout << "imu_end_i-imu_begin_i+1=" << imu_end_i-imu_begin_i+1 << endl;
                    //陀螺仪的是加速度,假设每个加速度作用的时间区间一样大,平分时间
                    //累积的速度
                    float accum_vec_x = 0;
                    float accum_vec_y= 0;
                    float accum_vec = 0;
                    //累积的距离
                    float accum_dis_x = 0;
                    float accum_dis_y = 0;
                    float accum_dis = 0;
                    //总时间
                    //开始时间
                    uint64_t begin_imu_nsec = imuMsgList[imu_begin_i]->header.stamp.toNSec();
                    //结束时间
                    uint64_t end_imu_nsec = imuMsgList[imu_end_i]->header.stamp.toNSec();
                    cout << "begin_imu_nsec=" << begin_imu_nsec << endl;
                    cout << "end_imu_nsec=" << end_imu_nsec << endl;
                    //结束时间
                    uint64_t time_imu = end_imu_nsec-begin_imu_nsec;
                    int64_t n1time_imu = (int64_t) time_imu;
                    double imu_sum_time = ((double) n1time_imu)/1000000000ul;
                    cout << "imu_sum_time=" << imu_sum_time << endl;
                    //平均时间
                    float imu_rev_time = imu_sum_time/(imu_end_i-imu_begin_i+1);
                    for (int k = imu_begin_i; k < imu_end_i+1; ++k) {
                        float xa = imuMsgList[k]->linear_acceleration.x;
                        float ya =  imuMsgList[k]->linear_acceleration.y;
                        //cout << "xa=" << xa << endl;
                       // cout << "ya=" << ya << endl;
                        //先分别求x,y,  再结合
                        //累积距离
                        accum_dis_x = accum_dis_x + (accum_vec_x * imu_rev_time )+ (0.5 * xa * pow(imu_rev_time, 2));
                        accum_dis_y = accum_dis_y + (accum_vec_y * imu_rev_time )+ (0.5 * ya * pow(imu_rev_time, 2));
                        //累积速度
                        accum_vec_x = accum_vec_x + xa*imu_rev_time;
                        accum_vec_y = accum_vec_y + ya*imu_rev_time;
                        //z轴方向没怎么分去加速度
                        //cout << "imuMsgList[k]->linear_acceleration.z=" << imuMsgList[k]->linear_acceleration.z << endl;
                    }
                    cout << "accum_dis_x=" << accum_dis_x << endl;
                    cout << "accum_dis_y=" << accum_dis_y << endl;
                    cout << "accum_vec_x=" << accum_vec_x << endl;
                    cout << "accum_vec_y=" << accum_vec_y << endl;
                    //去除静止时的误差
                    //accum_vec_x -= -0.012;
                   // accum_vec_y -= 0.023;
                    //不旋转情况下,两者的模长应该是一致的
                    float movec = sqrt(pow(accum_vec_x, 2)+pow(accum_vec_y,2));
                    float modis = sqrt(pow(accum_dis_x, 2)+pow(accum_dis_y,2));
                    cout << "movec=" << movec << endl;
                    cout << "modis=" << modis << endl;
                    //平均速度
                    float imu_rev_vec = modis / imu_sum_time;
                    cout << "imu_rev_vec=" << imu_rev_vec << endl;
                } else{
                    //cout << "no linear"<<endl;
                }
            scanMsgList.clear();
            imuMsgList.clear();
            }
    
        }
    
    //imu x方向上静止的平均误差,总是负的,-0.012
    float imu_rev_err_x = 0;
    int err_x = 0;
    //imu y方向上的静止平均误差,总是正的,静止时大概是0.023
    float imu_rev_err_y = 0;
    int err_y = 0;
    
    void imuCallback(const sensor_msgs::Imu::ConstPtr &msg) {
    
        imuMsgList.push_back(msg);
    //    uint64_t nsec = msg->header.stamp.toNSec();
    //    uint64_t sec = msg->header.stamp.toSec();
    //    cout << "imuMsgListsec=" << sec << endl;
    //    cout << "imuMsgListnsec=" << nsec << endl;
    //    __pid_t pid = getpid();
    //    cout << "Imupid=" << pid << endl;
         if (imuMsgList.size() > 15) {
             // if (false) {
            //累积的速度
            float accum_vec_x = 0;
            float accum_vec_y= 0;
            float accum_vec = 0;
            //累积的距离
            float accum_dis_x = 0;
            float accum_dis_y = 0;
            float accum_dis = 0;
            //开始时间
            uint64_t begin_imu_nsec = imuMsgList[0]->header.stamp.toNSec();
            //结束时间
            uint64_t end_imu_nsec = imuMsgList[15]->header.stamp.toNSec();
            cout << "begin_imu_nsec=" << begin_imu_nsec << endl;
            cout << "end_imu_nsec=" << end_imu_nsec << endl;
            //结束时间
            uint64_t time_imu = end_imu_nsec - begin_imu_nsec;
            int64_t n1time_imu = (int64_t) time_imu;
            double imu_sum_time = ((double) n1time_imu) / 1000000000ul;
            cout << "imu_sum_time=" << imu_sum_time << endl;
            //平均时间
            float imu_rev_time = imu_sum_time / (16);
            for (int k = 0; k < 16; ++k) {
                float xa = imuMsgList[k]->linear_acceleration.x;
                float ya = imuMsgList[k]->linear_acceleration.y;
                cout << "xa=" << xa << endl;
                cout << "ya=" << ya << endl;
                //先分别求x,y,  再结合
                //累积距离
                accum_dis_x = accum_dis_x + (accum_vec_x * imu_rev_time) + (0.5 * xa * pow(imu_rev_time, 2));
                accum_dis_y = accum_dis_y + (accum_vec_y * imu_rev_time) + (0.5 * ya * pow(imu_rev_time, 2));
                //累积速度
                accum_vec_x = accum_vec_x + xa * imu_rev_time;
                accum_vec_y = accum_vec_y + ya * imu_rev_time;
                //z轴方向没怎么分去加速度
                //cout << "imuMsgList[k]->linear_acceleration.z=" << imuMsgList[k]->linear_acceleration.z << endl;
            }
            err_x++;
            imu_rev_err_x = (imu_rev_err_x*(err_x-1) + accum_vec_x) / err_x;
            err_y++;
            imu_rev_err_y = (imu_rev_err_y *(err_y-1)+ accum_vec_y )/ err_y;
            cout << "accum_dis_x=" << accum_dis_x << endl;
            cout << "accum_dis_y=" << accum_dis_y << endl;
            cout << "accum_vec_x=" << accum_vec_x << endl;
            cout << "accum_vec_y=" << accum_vec_y << endl;
            cout << "imu_rev_err_x=" << imu_rev_err_x << endl;
            cout << "imu_rev_err_y=" << imu_rev_err_y << endl;
            //不旋转情况下,两者的模长应该是一致的
            float movec = sqrt(pow(accum_vec_x, 2) + pow(accum_vec_y, 2));
            float modis = sqrt(pow(accum_dis_x, 2) + pow(accum_dis_y, 2));
            cout << "movec=" << movec << endl;
            cout << "modis=" << modis << endl;
            //平均速度
            float imu_rev_vec = modis / imu_sum_time;
            cout << "imu_rev_vec=" << imu_rev_vec << endl;
            scanMsgList.clear();
            imuMsgList.clear();
        }
    
    }
    
    int main(int argc, char **argv) {
        string nodeName = "getData_node";
        string topicName_scan = "scan";
        string topicName_imu = "imu_data";
    
        //初始化节点
        ros::init(argc, argv, nodeName);
        ros::NodeHandle node;
        //创建订阅者
        const ros::Subscriber &subscriber_imu_data = node.subscribe(topicName_imu, 1000, imuCallback);
        const ros::Subscriber &subscriber_scan = node.subscribe(topicName_scan, 1000, scanCallback);
        // 阻塞线程
        ros::spin();
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:标定eai二维雷达和Imu

          本文链接:https://www.haomeiwen.com/subject/nliumctx.html