Eigen Revision

Dependencies:   mbed LPS25HB_I2C LSM9DS1 PIDcontroller Autopilot_Eigen LoopTicker GPSUBX_UART_Eigen SBUS_without_mainfile MedianFilter Eigen UsaPack solaESKF_Eigen Vector3 CalibrateMagneto FastPWM

setup.cpp

Committer:
NaotoMorita
Date:
2021-07-15
Revision:
73:84ffa0166e6c
Parent:
70:99f974d8960e
Child:
76:7fd3ac1afe3e

File content as of revision 73:84ffa0166e6c:

#include "global.hpp"

void setup()
{
    pitchPID.setSetPoint(0.0);
    pitchratePID.setSetPoint(0.0); 
    rollPID.setSetPoint(0.0); 
    rollratePID.setSetPoint(0.0); 
    pitchPID.setBias(0.0);
    pitchratePID.setBias(0.0); 
    rollPID.setBias(0.0); 
    rollratePID.setBias(0.0); 
    pitchPID.setOutputLimits(-1.0,1.0);
    pitchratePID.setOutputLimits(-1.0,1.0);
    rollPID.setOutputLimits(-1.0,1.0); 
    rollratePID.setOutputLimits(-1.0,1.0);
    pitchPID.setInputLimits(-M_PI,M_PI);
    pitchratePID.setInputLimits(-M_PI,M_PI);
    rollPID.setInputLimits(-M_PI,M_PI); 
    rollratePID.setInputLimits(-M_PI,M_PI);
    
    servoRight.period_us(15000.0);
    servoLeft.period_us(15000.0);
    servoThrust.period_us(15000.0);
    servoRight.pulsewidth_us(1500.0);
    servoLeft.pulsewidth_us(1500.0); 
    servoThrust.pulsewidth_us(1100.0);
    
    accelgyro.initialize();
    //加速度計のフルスケールレンジを設定
    accelgyro.setFullScaleAccelRange(ACCEL_FSR);
    //角速度計のフルスケールレンジを設定
    accelgyro.setFullScaleGyroRange(GYRO_FSR);
    //MPU6050のLPFを設定
    accelgyro.setDLPFMode(MPU6050_LPF);
    //MPU6050のレートを設定
    accelgyro.setRate(MPU6050_SAMPLERATE);
    //地磁気
    mag_sensor.enable();
}

void calibrate()
{
    pc.serial.printf("\r\nEnter to Calibration Mode\r\n");
    wait(5);
    pc.serial.printf("Acc and Gyro Calibration Start\r\n");
    
    int iter_n = 10000;
    
    long axs = 0;
    long ays = 0;
    long azs = 0;
    double axs2 = 0.0f;
    double ays2 = 0.0f;
    double azs2 = 0.0f;    
    long gxs = 0;
    long gys = 0;
    long gzs = 0;
    double gxs2 = 0.0f;
    double gys2 = 0.0f;
    double gzs2 = 0.0f;
    for(int i = 0;i<iter_n ;i++)
    {
        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
        axs += ax;
        ays += ay;
        azs += az;
        axs2 += double(ax*ax)/iter_n;
        ays2 += double(ay*ay)/iter_n;
        azs2 += double(az*az)/iter_n;
        
        gxs += gx;
        gys += gy;
        gzs += gz;
        gxs2 += double(gx*gx)/iter_n;
        gys2 += double(gy*gy)/iter_n;
        gzs2 += double(gz*gz)/iter_n;
        //wait(0.01);
    }
    axs = axs /iter_n; 
    ays = ays /iter_n; 
    azs = azs /iter_n;
    gxs = gxs /iter_n; 
    gys = gys /iter_n; 
    gzs = gzs /iter_n;
    double var_accx = (axs2 - double(axs*axs))/ ACCEL_SSF / ACCEL_SSF;
    double var_accy = (ays2 - double(ays*ays))/ ACCEL_SSF / ACCEL_SSF;
    double var_accz = (azs2 - double(azs*azs))/ ACCEL_SSF / ACCEL_SSF;
    double var_gyrox = (gxs2 - double(gxs*gxs))/ GYRO_SSF * 0.0174533f / GYRO_SSF * 0.0174533f;
    double var_gyroy = (gys2 - double(gys*gys))/ GYRO_SSF * 0.0174533f / GYRO_SSF * 0.0174533f; 
    double var_gyroz = (gzs2 - double(gzs*gzs))/ GYRO_SSF * 0.0174533f / GYRO_SSF * 0.0174533f;
    pc.serial.printf("AccCovariance : %f, %f, %f \r\n",var_accx,var_accy,var_accz); 
    pc.serial.printf("GyroCovariance : %f, %f, %f \r\n",var_gyrox,var_gyroy,var_gyroz);
    
    pc.serial.printf("Gyrooffset : 0, 0, 0, %d, %d, %d \r\n",gxs,gys,gzs);
    
    
    pc.serial.printf("Initial Magbias (Min) : %f, %f, %f\r\n", magbiasMin[0], magbiasMin[1], magbiasMin[2]);
    pc.serial.printf("Initial Magbias (Max) : %f, %f, %f\r\n", magbiasMax[0], magbiasMax[1], magbiasMax[2]);
    
    pc.serial.printf("Acc Scale and Mag Calibration Start\r\n");
    for(int i = 0;i<3;i++){
        accMin[i] = -1.0f;
        accMax[i] = 1.0f;
    }
    
    accMax[2] = accScaleCalibrate(5);
    accMin[0] = accScaleCalibrate(1);
    accMax[0] =accScaleCalibrate(2);
    accMin[1] =accScaleCalibrate(3);
    accMax[1] =accScaleCalibrate(4);
    accMin[2] =accScaleCalibrate(6);
    
    magCalibrator.getExtremes(magbiasMin,magbiasMax);
    pc.serial.printf("Magbias (Min) : %f, %f, %f\r\n", magbiasMin[0], magbiasMin[1], magbiasMin[2]);
    pc.serial.printf("Magbias (Max) : %f, %f, %f\r\n", magbiasMax[0], magbiasMax[1], magbiasMax[2]);
    magCalibrator.setExtremes(magbiasMin,magbiasMax);
    
    pc.serial.printf("accMin : %f, %f, %f\r\n", accMin[0], accMin[1], accMin[2]);
    pc.serial.printf("accMax : %f, %f, %f\r\n", accMax[0], accMax[1], accMax[2]);
    
    pc.serial.printf("Keep Level \r\n"); 
    wait(5);
    
    pc.serial.printf("Calculating pitch/roll Offset \r\n");  
    //姿勢オフセットを計算
    rpy_align.y = 0.0f*M_PI/180.0f;
    rpy_align.x = 0.0f*M_PI/180.0f;
    float ave_pitch = 0.0f;
    float ave_roll = 0.0f;
    ekf.Q(4,4) = 0.00001f;
    ekf.Q(5,5) = 0.00001f;
    ekf.Q(6,6) = 0.00001f;
    ekf.Qab(1,1) = 0.0f;
    ekf.Qab(2,2) = 0.0f;
    ekf.Qab(3,3) = 0.0f;
    getIMUval();
    ekf.triad(acc/acc.Norm(), accref/accref.Norm(), mag/mag.Norm(), magref/magref.Norm());
    Timer _t;
    _t.start();
    for (int i = 0 ; i < 2200; i++)
    {
        float tstart = _t.read();
        //姿勢角を更新
        getIMUval();
        ekf.updateQhat(gyro, att_dt);
        ekf.updateErrState(gyro, att_dt);
        ekf.updateStaticAccMeasures(acc,accref);
        ekf.fuseErr2Qhat();
        ekf.updateMagMeasures(mag);
        ekf.computeAngles(rpy, rpy_align);
        if(i>199)
        {
            ave_pitch += rpy.x;
            ave_roll += rpy.y;
        }
        wait(0.001);
        float tend = _t.read();
        att_dt = (tend-tstart);
    }
    
    pc.serial.printf("aliginment data(rpy.x, rpy.y, rpy.z) : %ff*M_PI/180.0f, %ff*M_PI/180.0f, 0.0f*M_PI/180.0f\r\n",ave_pitch/2000.0f*180.0f/M_PI,ave_roll/2000.0f*180.0f/M_PI);
    
    
    pc.serial.printf("Calibration Complete\r\n");
    
    while(1)
    {
        wait(1000);
    }
}

float accScaleCalibrate(int attNo)
{
    //attNo 1:Right down (acc.x Negative)
    //attNo 2:Left down (acc.x Positive)
    //attNo 3:Nose down (acc.y Negative)
    //attNo 4:Tail down (acc.y Positive)
    //attNo 5:Level (acc.z Positive)
    //attNo 6:upside down (acc.z Negative)
    //acc scale calibration
    switch(attNo){
        case 1:
            pc.serial.printf("Right down (acc.x Negative)\r\n");
            break;
        case 2:
            pc.serial.printf("Left down (acc.x Positive)\r\n");
            break;
        case 3:
            pc.serial.printf("Nose down (acc.y Negative)\r\n");
            break;
        case 4:
            pc.serial.printf("Tail down (acc.y Positive)\r\n");
            break;
        case 5:
            pc.serial.printf("Level (acc.z Positive)\r\n");
            break;
        case 6:
            pc.serial.printf("Upside down (acc.z Negative)\r\n");
            break;
        default : 
            pc.serial.printf("error");
            break;
    }
    
    while(1){
        double accx = 0.0;
        double accy = 0.0;
        double accz = 0.0;
        for(int i = 0;i<100 ;i++)
        {
            accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
            accx += ax/ ACCEL_SSF;
            accy += ay/ ACCEL_SSF;
            accz += az/ ACCEL_SSF;
            wait(0.01);
        } 
        bool breakFlag = false;
        switch(attNo){
            case 1:
                if(abs(accx/100.0+1.0)<0.1){
                    breakFlag = true;
                };
                break;
            case 2:
                if(abs(accx/100.0-1.0)<0.1){
                    breakFlag = true;
                };
                break;
            case 3:
                if(abs(accy/100.0+1.0)<0.1){
                    breakFlag = true;
                };
                break;
            case 4:
                if(abs(accy/100.0-1.0)<0.1){
                    breakFlag = true;
                };
                break;
            case 5:
                if(abs(accz/100.0-1.0)<0.1){
                    breakFlag = true;
                };
                break;
            case 6:
                if(abs(accz/100.0+1.0)<0.1){
                    breakFlag = true;
                };
                break;
        }
        if(breakFlag){break;};    
        pc.serial.printf("acc %f %f %f\r\n", accx/100.0,accy/100.0,accz/100.0);
    }
    pc.serial.printf("Keep it hold\r\n");
    int iter_n = 1000;
    double accx = 0.0;
    double accy = 0.0;
    double accz = 0.0;
    for(int i = 0;i<iter_n ;i++)
    {
        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
        accx += ax/ ACCEL_SSF;
        accy += ay/ ACCEL_SSF;
        accz += az/ ACCEL_SSF;
        
        float inputMag[3];
        float outputMag[3];
        mag_sensor.getAxis(mdata); // flush the magnetmeter
        inputMag[0] = mdata.x;
        inputMag[1] = mdata.y;
        inputMag[2] = mdata.z;
        magCalibrator.run(inputMag,outputMag);
        
        wait(0.001);
    }
    float returnval = 0.0f;
        switch(attNo){
        case 1:
            returnval = accx/1000.0f;
            break;
        case 2:
            returnval = accx/1000.0f;
            break;
        case 3:
            returnval = accy/1000.0f;
            break;
        case 4:
            returnval = accy/1000.0f;
            break;
        case 5:
            returnval = accz/1000.0f;
            break;
        case 6:
            returnval = accz/1000.0f;
            break;
    }
    
    return returnval;
}