• Arduino 接入 MPU9250六轴


    使用MPU9250获得加速,角速度及地磁计数据。

    接线使用Arduino上的SCL接Mpu9250的SCL,SDA接SDA,3.3v或5v供电。

    使用I2C连接,通过MPU9250不同地址,我们可以获得不同的数据,即加速度和角速度地址为0x68。

    而地磁计地址为0x0C。

    下面是代码: 

    #include <Wire.h>
     
    #define    MPU9250_ADDRESS            0x68
    #define    MAG_ADDRESS                0x0C
     
    #define    GYRO_FULL_SCALE_250_DPS    0x00  
    #define    GYRO_FULL_SCALE_500_DPS    0x08
    #define    GYRO_FULL_SCALE_1000_DPS   0x10
    #define    GYRO_FULL_SCALE_2000_DPS   0x18
     
    #define    ACC_FULL_SCALE_2_G        0x00  
    #define    ACC_FULL_SCALE_4_G        0x08
    #define    ACC_FULL_SCALE_8_G        0x10
    #define    ACC_FULL_SCALE_16_G       0x18
     
     
     
    // This function read Nbytes bytes from I2C device at address Address. 
    // Put read bytes starting at register Register in the Data array. 
    void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
    {
      // Set register address
      Wire.beginTransmission(Address);
      Wire.write(Register);
      Wire.endTransmission();
     
      // Read Nbytes
      Wire.requestFrom(Address, Nbytes); 
      uint8_t index=0;
      while (Wire.available())
        Data[index++]=Wire.read();
    }
    void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
    {
      // Set register address
      Wire.beginTransmission(Address);
      Wire.write(Register);
      Wire.write(Data);
      Wire.endTransmission();
    }
     
     
    // Initializations
    void setup()
    {
      // Arduino initializations
      Wire.begin();
      Serial.begin(115200);
     
      // Configure gyroscope range
      I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_2000_DPS);
      // Configure accelerometers range
      I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_16_G);
      // Set by pass mode for the magnetometers
      I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
     
      // Request first magnetometer single measurement
      I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
     
     
    }
    
    
    long int cpt=0;
    // Main loop, read and display data
    void loop()
    {
       // ____________________________________
      // :::  accelerometer and gyroscope ::: 
     
      // Read accelerometer and gyroscope
      uint8_t Buf[14];
      I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
     
      // Create 16 bits values from 8 bits data
     
      // Accelerometer
      int16_t ax=-(Buf[0]<<8 | Buf[1]);
      int16_t ay=-(Buf[2]<<8 | Buf[3]);
      int16_t az=Buf[4]<<8 | Buf[5];
     
      // Gyroscope
      int16_t gx=-(Buf[8]<<8 | Buf[9]);
      int16_t gy=-(Buf[10]<<8 | Buf[11]);
      int16_t gz=Buf[12]<<8 | Buf[13];
     
        // Display values
     
      // Accelerometer
    //  Serial.print (ax,DEC); 
    //  Serial.print ("	");
    //  Serial.print (ay,DEC);
    //  Serial.print ("	");
    //  Serial.print (az,DEC);  
    //  Serial.print ("	");
    // 
    //  // Gyroscope
    //  Serial.print (gx,DEC); 
    //  Serial.print ("	");
    //  Serial.print (gy,DEC);
    //  Serial.print ("	");
    //  Serial.print (gz,DEC);  
    //  Serial.print ("	");
      //delay(100); 
    
    
      
    
    
      // Read magnetometer data  
      I2CwriteByte(MAG_ADDRESS,0x37,0x02);
      uint8_t Mag[7];  
      I2Cread(MAG_ADDRESS,0x03,7,Mag);
      // Magnetometer
      int16_t mx=-(Mag[0]<<8 | Mag[1]);
      int16_t my=-(Mag[2]<<8 | Mag[3]);
      int16_t mz=-(Mag[4]<<8 | Mag[5]);
      
      
      // Magnetometer
      Serial.print (mx,DEC); 
      Serial.print ("	");
      Serial.print (my,DEC);
      Serial.print ("	");
      Serial.print (mz,DEC);  
      Serial.print ("	");
      
      // End of line
      Serial.println("");
      //delay(100);    
    }
    View Code

    使用mahony算法,地磁计融合与不融合地磁计算四元数。

    使用mahony方法进行计算。

     

    只使用acc与gyro计算姿态,主要的计算步骤如下:    

    第一:将acc单位化。

    第二:预测惯性向量,根据现有的四元数作预测,q为四元数,v为预测惯性向量。

     

    第三:误差计算,e为实际测量acc向预测v的叉乘,结果为一个旋转误差。

     

    第四:PI补偿

    即当eInt为,计算eInt为下:

    第五:计算四元数导, w为角速度:

    第六:更新:

    当使用地磁计进行数据融合时,重新计算。    

    第一:单位化acc与mag。

    第二:计算h ,地磁参考方向,其中为q的共轭四元数。

     

    第三:计算重力与地磁估计方向

     

    第四:计算误差

     

    第五:与不使用地磁计相同,计算累计误差,根据PI进行计算Gyro,

    即当eInt为,计算eInt为下:

     

    第五:计算四元数导, w为角速度:

     

    第六:更新:

      #include <Wire.h>
       
      #define    MPU9250_ADDRESS            0x68
      #define    MAG_ADDRESS                0x0C
       
      #define    GYRO_FULL_SCALE_250_DPS    0x00  
      #define    GYRO_FULL_SCALE_500_DPS    0x08
      #define    GYRO_FULL_SCALE_1000_DPS   0x10
      #define    GYRO_FULL_SCALE_2000_DPS   0x18
       
      #define    ACC_FULL_SCALE_2_G        0x00  
      #define    ACC_FULL_SCALE_4_G        0x08
      #define    ACC_FULL_SCALE_8_G        0x10
      #define    ACC_FULL_SCALE_16_G       0x18
      
      float Kp = 1;
      float Ki = 0.0;
      
      double eInt1=0.0;
      double eInt2=0.0;
      double eInt3=0.0;
    
      double q1=1.0;
      double q2=0.0;
      double q3=0.0;
      double q4=0.0;
      
      double delta_t = 1.0/256.0;
      long t_pre;
    
       
      // This function read Nbytes bytes from I2C device at address Address. 
      // Put read bytes starting at register Register in the Data array. 
      void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
      {
        // Set register address
        Wire.beginTransmission(Address);
        Wire.write(Register);
        Wire.endTransmission();
       
        // Read Nbytes
        Wire.requestFrom(Address, Nbytes); 
        uint8_t index=0;
        while (Wire.available())
          Data[index++]=Wire.read();
      }
      void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
      {
        // Set register address
        Wire.beginTransmission(Address);
        Wire.write(Register);
        Wire.write(Data);
        Wire.endTransmission();
      } 
       
      // Initializations
      void setup()
      {
        // Arduino initializations
        Wire.begin();
        Serial.begin(115200);
        // Configure gyroscope range
        I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_2000_DPS);
        // Configure accelerometers range
        I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_16_G);
        // Set by pass mode for the magnetometers
        I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
       
        // Request first magnetometer single measurement
        I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
        
      }
      
      double quaternionProd1(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r1;
      }
    
      double quaternionProd2(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r2;
      }
      double quaternionProd3(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r3;
      }
      double quaternionProd4(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r4;
      }
      
      void MahonyUpDate(double delta_t,double ax, double ay,double az, double gx, double gy, double gz, double mx, double my, double mz)
      {
        double a_norm = sqrt(ax*ax+ay*ay+az*az);
        if(a_norm==0)
        {
              Serial.print ("
    ");
              Serial.print ("Acc errer. 
    ");
              return;
        }
        ax = ax/a_norm;
        ay = ay/a_norm;
        az = az/a_norm;
      
        double m_norm = sqrt(mx*mx+my*my+mz*mz);
        if(m_norm==0)
        {
              Serial.print ("
    ");
              Serial.print ("Mag errer. 
    ");
              return;
        }
        mx = mx/m_norm;
        my = my/m_norm;
        mz = mz/m_norm;
    
    
        double mq1,mq2,mq3,mq4;
        double h1,h2,h3,h4;
        double qdot1,qdot2,qdot3,qdot4;
    
        
        //Magwick mag 
        mq1 = quaternionProd1(q1,q2,q3,q4,0,mx,my,mz);
        mq2 = quaternionProd2(q1,q2,q3,q4,0,mx,my,mz);
        mq3 = quaternionProd3(q1,q2,q3,q4,0,mx,my,mz);
        mq4 = quaternionProd4(q1,q2,q3,q4,0,mx,my,mz);
    
        h1 = quaternionProd1(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        h2 = quaternionProd2(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        h3 = quaternionProd3(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        h4 = quaternionProd4(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        float b2 = sqrt( h2*h2 +h3*h3);
        float b4 = h4;
      
        float v1 = 2*(q2*q4-q1*q3);
        float v2 = 2*(q1*q2+q3*q4);
        float v3 = 2*(q1*q1-q2*q2-q3*q3+q4*q4);
      
        float w1 = 2*b2*(0.5-q3*q3-q4*q4)+2*b4*(q2*q4-q1*q3);
        float w2 = 2*b2*(q2*q3 - q1*q4)+2*b4*(q1*q2+q3*q4);
        float w3 = 2*(q1*q3 + q2*q4)+2*b4*(0.5-q2*q2-q3*q3);
      
        float e1 = ay*v3 - az*v2 + my*w3 - mz*w2;
        float e2 = -ax*v3 + az*v1 - mx*w3 + mz*w1;
        float e3 = ax*v2 - ay*v1 + mx*w2 - my*w1;
    
    
    //    //Magwick acc
    //    float v1 = 2*(q2*q4-q1*q3);
    //    float v2 = 2*(q1*q2+q3*q4);
    //    float v3 = q1*q1-q2*q2-q3*q3+q4*q4;
    //    float e1 = ay*v3 - az*v2;
    //    float e2 = -ax*v3 + az*v1;
    //    float e3 = ax*v2 - ay*v1;
    
    
        //errer 
        eInt1 = eInt1 + e1*delta_t;
        eInt2 = eInt2 + e2*delta_t;
        eInt2 = eInt2 + e2*delta_t;
        //PI
        gx = gx + Kp*e1 +Ki*eInt1;
        gy = gy + Kp*e2 +Ki*eInt2;
        gz = gz + Kp*e3 +Ki*eInt3;
    
        //q dot
        qdot1 = 0.5* quaternionProd1(q1,q2,q3,q4, 0,gx,gy,gz);
        qdot2 = 0.5* quaternionProd2(q1,q2,q3,q4, 0,gx,gy,gz); 
        qdot3 = 0.5* quaternionProd3(q1,q2,q3,q4, 0,gx,gy,gz);   
        qdot4 = 0.5* quaternionProd4(q1,q2,q3,q4, 0,gx,gy,gz);
        //quaternion calculate
        q1 = q1 + qdot1*delta_t;
        q2 = q2 + qdot2*delta_t;
        q3 = q3 + qdot3*delta_t;
        q4 = q4 + qdot4*delta_t;
        //unify
        double norm_q = sqrt(q1*q1+q2*q2+q3*q3+q4*q4);            
        q1 = q1/norm_q;
        q2 = q2/norm_q;
        q3 = q3/norm_q;
        q4 = q4/norm_q;
        
    
        
        Serial.print (q1,DEC); 
        Serial.print ("	");
        Serial.print (q2,DEC);
        Serial.print ("	");
        Serial.print (q3,DEC);  
        Serial.print ("	");
        Serial.print (q4,DEC); 
        Serial.print ("	");
        Serial.println("");
      }
      
      
      void loop()
      {
        // ____________________________________
        // :::  accelerometer and gyroscope ::: 
       
        // Read accelerometer and gyroscope
        uint8_t Buf[14];
        I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
       
        // Create 16 bits values from 8 bits data
       
        // Accelerometer
        int16_t ax=-(Buf[0]<<8 | Buf[1]);
        int16_t ay=-(Buf[2]<<8 | Buf[3]);
        int16_t az=Buf[4]<<8 | Buf[5];
       
        // Gyroscope
        int16_t gx=-(Buf[8]<<8 | Buf[9]);
        int16_t gy=-(Buf[10]<<8 | Buf[11]);
        int16_t gz=Buf[12]<<8 | Buf[13];
    
        double ax1 = ax/2048.0;
        double ay1 = ay/2048.0;
        double az1 = az/2048.0;
    
        double gx1 = gx*3.14/16.4/180;
        double gy1 = gy*3.14/16.4/180;
        double gz1 = gz*3.14/16.4/180;   
        // Display values
        // Accelerometer
        Serial.print (ax1,DEC); 
        Serial.print ("	");
        Serial.print (ay1,DEC);
        Serial.print ("	");
        Serial.print (az1,DEC);  
        Serial.print ("	");
        // Gyroscope
        Serial.print (gx1,DEC); 
        Serial.print ("	");
        Serial.print (gy1,DEC);
        Serial.print ("	");
        Serial.print (gz1,DEC);  
        Serial.print ("	");
      
      
        // Read magnetometer data  
        I2CwriteByte(MAG_ADDRESS,0x37,0x02);
        uint8_t Mag[7];  
        I2Cread(MAG_ADDRESS,0x03,7,Mag);
        // Magnetometer
        int16_t mx=-(Mag[3]<<8 | Mag[2]);
        int16_t my=-(Mag[1]<<8 | Mag[0]);
        int16_t mz=-(Mag[5]<<8 | Mag[4]);  
        
        double mx1 = mx*0.6;
        double my1 = my*0.6;
        double mz1 = mz*0.6;
        // Magnetometer
    //    Serial.print (mx1,DEC); 
    //    Serial.print ("	");
    //    Serial.print (my1,DEC);
    //    Serial.print ("	");
    //    Serial.print (mz1,DEC);  
    //    Serial.print ("	");
    
        //run mahony algrithom
        long time = millis();
        double delta_t = (time - t_pre)/1000.0;
    //    Serial.print (delta_t,DEC);  
    //    Serial.print ("	");
        MahonyUpDate(delta_t,ax1,ay1,az1,gx1,gy1,gz1,mx1,my1,mz1);
        t_pre = time;
        // End of line
    
        //delay(100);    
      }
      

    配合ros,使用arduino。

    #include <Wire.h>
    
      #include <ros.h>
      #include <sensor_msgs/Imu.h> 
    
      ros::NodeHandle  nh;
      sensor_msgs::Imu imu_sensor;
      ros::Publisher imu_sensor_pub("imu", &imu_sensor);
      
      #define    MPU9250_ADDRESS            0x68
      #define    MAG_ADDRESS                0x0C
       
      #define    GYRO_FULL_SCALE_250_DPS    0x00  
      #define    GYRO_FULL_SCALE_500_DPS    0x08
      #define    GYRO_FULL_SCALE_1000_DPS   0x10
      #define    GYRO_FULL_SCALE_2000_DPS   0x18
       
      #define    ACC_FULL_SCALE_2_G        0x00  
      #define    ACC_FULL_SCALE_4_G        0x08
      #define    ACC_FULL_SCALE_8_G        0x10
      #define    ACC_FULL_SCALE_16_G       0x18
      
      float Kp = 5;
      float Ki = 0.0;
      
      double eInt1=0.0;
      double eInt2=0.0;
      double eInt3=0.0;
    
      double q1=1.0;
      double q2=0.0;
      double q3=0.0;
      double q4=0.0;
    
      long t_pre;
    
      
      // This function read Nbytes bytes from I2C device at address Address. 
      // Put read bytes starting at register Register in the Data array. 
      void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
      {
        // Set register address
        Wire.beginTransmission(Address);
        Wire.write(Register);
        Wire.endTransmission();
       
        // Read Nbytes
        Wire.requestFrom(Address, Nbytes); 
        uint8_t index=0;
        while (Wire.available())
          Data[index++]=Wire.read();
      }
      void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
      {
        // Set register address
        Wire.beginTransmission(Address);
        Wire.write(Register);
        Wire.write(Data);
        Wire.endTransmission();
      } 
       
      // Initializations
      void setup()
      {
        // Arduino initializations
        Wire.begin();
        nh.initNode();
        nh.advertise(imu_sensor_pub);
        I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_2000_DPS);
        I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_16_G);
        I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
        I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
        //ros initialize
    
      }
      
      double quaternionProd1(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r1;
      }
    
      double quaternionProd2(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r2;
      }
      double quaternionProd3(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r3;
      }
      double quaternionProd4(double a1,double a2,double a3,double a4,double b1,double b2,double b3,double b4)
      {
        double r1,r2,r3,r4;
        r1 = a1*b1-a2*b2-a3*b3-a4*b4;
        r2 = a1*b2+a2*b1+a3*b4-a4*b3;
        r3 = a1*b3-a2*b4+a3*b1+a4*b2;
        r4 = a1*b4+a2*b3-a3*b2+a4*b1;
    
        return r4;
      }
      
      void MahonyUpDate(double delta_t,double ax, double ay,double az, double gx, double gy, double gz, double mx, double my, double mz)
      {
        double a_norm = sqrt(ax*ax+ay*ay+az*az);
        if(a_norm==0)
        {
              Serial.print ("
    ");
              Serial.print ("Acc errer. 
    ");
              return;
        }
        ax = ax/a_norm;
        ay = ay/a_norm;
        az = az/a_norm;
      
        double m_norm = sqrt(mx*mx+my*my+mz*mz);
        if(m_norm==0)
        {
              Serial.print ("
    ");
              Serial.print ("Mag errer. 
    ");
              return;
        }
        mx = mx/m_norm;
        my = my/m_norm;
        mz = mz/m_norm;
    
    
        double mq1,mq2,mq3,mq4;
        double h1,h2,h3,h4;
        double qdot1,qdot2,qdot3,qdot4;
    
        
        //Magwick mag 
        mq1 = quaternionProd1(q1,q2,q3,q4,0,mx,my,mz);
        mq2 = quaternionProd2(q1,q2,q3,q4,0,mx,my,mz);
        mq3 = quaternionProd3(q1,q2,q3,q4,0,mx,my,mz);
        mq4 = quaternionProd4(q1,q2,q3,q4,0,mx,my,mz);
    
        h1 = quaternionProd1(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        h2 = quaternionProd2(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        h3 = quaternionProd3(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        h4 = quaternionProd4(mq1,mq2,mq3,mq4,q1,-q2,-q3,-q4);
        float b2 = sqrt( h2*h2 +h3*h3);
        float b4 = h4;
      
        float v1 = 2*(q2*q4-q1*q3);
        float v2 = 2*(q1*q2+q3*q4);
        float v3 = 2*(q1*q1-q2*q2-q3*q3+q4*q4);
      
        float w1 = 2*b2*(0.5-q3*q3-q4*q4)+2*b4*(q2*q4-q1*q3);
        float w2 = 2*b2*(q2*q3 - q1*q4)+2*b4*(q1*q2+q3*q4);
        float w3 = 2*(q1*q3 + q2*q4)+2*b4*(0.5-q2*q2-q3*q3);
      
        float e1 = ay*v3 - az*v2 + my*w3 - mz*w2;
        float e2 = -ax*v3 + az*v1 - mx*w3 + mz*w1;
        float e3 = ax*v2 - ay*v1 + mx*w2 - my*w1;
    
    
    //    //Magwick acc
    //    float v1 = 2*(q2*q4-q1*q3);
    //    float v2 = 2*(q1*q2+q3*q4);
    //    float v3 = q1*q1-q2*q2-q3*q3+q4*q4;
    //    float e1 = ay*v3 - az*v2;
    //    float e2 = -ax*v3 + az*v1;
    //    float e3 = ax*v2 - ay*v1;
    
    
        //errer 
        eInt1 = eInt1 + e1*delta_t;
        eInt2 = eInt2 + e2*delta_t;
        eInt2 = eInt2 + e2*delta_t;
        //PI
        gx = gx + Kp*e1 +Ki*eInt1;
        gy = gy + Kp*e2 +Ki*eInt2;
        gz = gz + Kp*e3 +Ki*eInt3;
    
        //q dot
        qdot1 = 0.5* quaternionProd1(q1,q2,q3,q4, 0,gx,gy,gz);
        qdot2 = 0.5* quaternionProd2(q1,q2,q3,q4, 0,gx,gy,gz); 
        qdot3 = 0.5* quaternionProd3(q1,q2,q3,q4, 0,gx,gy,gz);   
        qdot4 = 0.5* quaternionProd4(q1,q2,q3,q4, 0,gx,gy,gz);
        //quaternion calculate
        q1 = q1 + qdot1*delta_t;
        q2 = q2 + qdot2*delta_t;
        q3 = q3 + qdot3*delta_t;
        q4 = q4 + qdot4*delta_t;
        //unify
        double norm_q = sqrt(q1*q1+q2*q2+q3*q3+q4*q4);            
        q1 = q1/norm_q;
        q2 = q2/norm_q;
        q3 = q3/norm_q;
        q4 = q4/norm_q;
    
        imu_sensor.orientation.x = q1;
        imu_sensor.orientation.y = q2;
        imu_sensor.orientation.z = q3;
        imu_sensor.orientation.w = q4;
                    
      }
    
      
      void loop()
      {
        // ____________________________________
        // :::  accelerometer and gyroscope ::: 
       
        // Read accelerometer and gyroscope
        uint8_t Buf[14];
        I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
       
        // Create 16 bits values from 8 bits data
       
        // Accelerometer
        int16_t ax=-(Buf[0]<<8 | Buf[1]);
        int16_t ay=-(Buf[2]<<8 | Buf[3]); 
        int16_t az=Buf[4]<<8 | Buf[5];
       
        // Gyroscope
        int16_t gx=-(Buf[8]<<8 | Buf[9]);
        int16_t gy=-(Buf[10]<<8 | Buf[11]);
        int16_t gz=Buf[12]<<8 | Buf[13];
    
        double ax1 = ax/2048.0;
        double ay1 = ay/2048.0;
        double az1 = az/2048.0;
    
        double gx1 = gx*3.14/16.4/180;
        double gy1 = gy*3.14/16.4/180;
        double gz1 = gz*3.14/16.4/180;   
    
        imu_sensor.header.frame_id = "base_link";
        imu_sensor.angular_velocity.y = gy1;
        imu_sensor.angular_velocity.x = gx1;
        imu_sensor.angular_velocity.z = gz1;
    
        imu_sensor.linear_acceleration.x = ax1;
        imu_sensor.linear_acceleration.y = ay1;
        imu_sensor.linear_acceleration.z = az1;
    
        float angular_vel[9]={1e6, 0, 0, 0, 1e6, 0, 0, 0, 1e-6};
        float orientation[9]={1e6, 0, 0, 0, 1e6, 0, 0, 0, 1e-6};
        for(int i=0; i<9; i++){
          imu_sensor.orientation_covariance[i] = angular_vel[i];
          imu_sensor.angular_velocity_covariance[i] = orientation[i]; 
        }
      
        // Read magnetometer data  
        I2CwriteByte(MAG_ADDRESS,0x37,0x02);
        uint8_t Mag[7];  
        I2Cread(MAG_ADDRESS,0x03,7,Mag);
        // Magnetometer
        int16_t mx=-(Mag[3]<<8 | Mag[2]);
        int16_t my=-(Mag[1]<<8 | Mag[0]);
        int16_t mz=-(Mag[5]<<8 | Mag[4]);  
        
        double mx1 = mx*0.6;
        double my1 = my*0.6;
        double mz1 = mz*0.6;
    
    
        //run mahony algrithom
        long time = millis();
        double delta_t = (time - t_pre)/1000.0;
    
        MahonyUpDate(delta_t,ax1,ay1,az1,gx1,gy1,gz1,mx1,my1,mz1);
        t_pre = time;
        
        // End of line
        imu_sensor_pub.publish(&imu_sensor);
        nh.spinOnce();
        delay(10);    
      }
      
    View Code
  • 相关阅读:
    swift
    swift
    swift
    swift
    swift
    swift
    swift
    swift
    Swift
    Nginx 访问控制
  • 原文地址:https://www.cnblogs.com/TIANHUAHUA/p/8556554.html
Copyright © 2020-2023  润新知