---
# System prepended metadata

title: ahrs
tags: [訊號處理]

---

###### tags: `訊號處理`

# ahrs

校正軌跡的方式？

https://www.itread01.com/content/1545324504.html
上面這篇看懂了

ahrs mahony

https://blog.csdn.net/weixin_40378598/article/details/108133032

![](https://i.imgur.com/wZiplsA.png)

下圖兩圖為等效 一個是用尤拉角做選轉 一個是用四元數做旋轉
![](https://i.imgur.com/BKgIR7I.png)

![](https://i.imgur.com/7yMRYiL.png)

下圖為從四元數那邊擷取過來的圖
注意上圖和下圖的第三個column 會有一些差異 應該是選轉順序不同造成 而最右下角的元素 有兩個平方項的相加會是常數 在有些程式碼還是有計算 沒有當作常數處理
![](https://i.imgur.com/s9NwxUr.png)


下面是pid控制器的圖

![](https://i.imgur.com/4Qz6rCr.png)

x-imu的部份程式碼

注意下方 一些正負號有差別而已 應該都只是選轉順序的問題
![](https://i.imgur.com/T93QrDi.png)

![](https://i.imgur.com/VCvCsqs.png)

霆寬丟到群組的流程圖
![](https://i.imgur.com/RD0V3Ne.jpg)

同樣姿態 但是w可能不同的符號
https://blog.endaq.com/quaternions-for-orientation

模擬時 用自己gen的資料無法產生正常的output 但用順先從感測器上量到的ok

yaw旋轉
![](https://i.imgur.com/mP0ovix.png)
pitch 旋轉
![](https://i.imgur.com/wyhXl4h.png)
roll旋轉
![](https://i.imgur.com/Zavzzgh.png)


# 磁力計部分相關
https://blog.csdn.net/zhiyu_buliang/article/details/89056519

說明磁力計效果不大？
https://blog.csdn.net/qq_39554681/article/details/90931919

知乎
https://zhuanlan.zhihu.com/p/342703398

**磁力計測得的磁場向量在機體坐標系中，該向量還需通過[公式]變換到地理坐標系中，經過一定處理後，再通過[公式]變換回機體坐標系，從而得到理論地磁向量**

![](https://i.imgur.com/xn11pFJ.png)

![](https://i.imgur.com/ikihtMD.png)

![](https://i.imgur.com/feCBrc0.png)
上式的右邊有問題 中間不該為0

基本上 就是要校正四元素 讓其旋轉矩陣的反轉換的x軸對準正北
https://blog.csdn.net/nemol1990/article/details/21870197


# 磁力計 橢圓擬合
https://hackmd.io/gDv4BkYbTUeD3NSS2t6tXg

https://www.fierceelectronics.com/components/compensating-for-tilt-hard-iron-and-soft-iron-effects

https://longnight975551865.wordpress.com/2019/11/23/how-to-calibrate-a-magnetometer/

https://www.vectornav.com/resources/magnetometer-errors-calibration

https://www.fierceelectronics.com/components/compensating-for-tilt-hard-iron-and-soft-iron-effects

source code
https://github.com/kriswiner/MPU9250/blob/master/MPU9250_MS5637_AHRS_t3.ino

========================================

霆寬新版的board

然後創建scene = canvas(...時 把這幾行加上去
scene.forward = vec(-1, 0, 0)
scene.up = vec(0, 0, 1)
scene.camera.pos = vec(-1, 0, 0)


不到400元的線性加速規
https://www.st.com/en/mems-and-sensors/iis3dhhc.html?fbclid=IwAR2VYs_QFGFeWjWc5ZANEVZGv9D7p2ZOoeIMpJNjgmKHWDg9Np8CYkpYRrw#overview

1.找出線性加速度

用最新的q算出v 然後將它從加速規量到的值中減掉？
```
// Estimated direction of gravity and vector perpendicular to magnetic flux
		halfvx = q1 * q3 - q0 * q2;
		halfvy = q0 * q1 + q2 * q3;
		halfvz = q0 * q0 - 0.5f + q3 * q3;
```

2.把物體座標系加速度轉成大地座標系加速度

q.inverse*a*q<--??

# eagle pcb軟體 免費 給linux

```
void magcalMPU9250(float * dest1, float * dest2) 
{
    uint16_t ii = 0, sample_count = 0;
    int32_t mag_bias[3] = {0, 0, 0}, mag_scale[3] = {0, 0, 0};
    int16_t mag_max[3] = {-32767, -32767, -32767}, mag_min[3] = {32767, 32767, 32767}, mag_temp[3] = {0, 0, 0};

    Serial.println("Mag Calibration: Wave device in a figure eight until done!");
    delay(4000);
  
    // shoot for ~fifteen seconds of mag data
    if(Mmode == 0x02) sample_count = 128;  // at 8 Hz ODR, new mag data is available every 125 ms
    if(Mmode == 0x06) sample_count = 1500;  // at 100 Hz ODR, new mag data is available every 10 ms
    for(ii = 0; ii < sample_count; ii++) {
        readMagData(mag_temp);  // Read the mag data   
        for (int jj = 0; jj < 3; jj++) {
            if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj];
            if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj];
        }
        if(Mmode == 0x02) delay(135);  // at 8 Hz ODR, new mag data is available every 125 ms
        if(Mmode == 0x06) delay(12);  // at 100 Hz ODR, new mag data is available every 10 ms
    }

//    Serial.println("mag x min/max:"); Serial.println(mag_max[0]); Serial.println(mag_min[0]);
//    Serial.println("mag y min/max:"); Serial.println(mag_max[1]); Serial.println(mag_min[1]);
//    Serial.println("mag z min/max:"); Serial.println(mag_max[2]); Serial.println(mag_min[2]);

    // Get hard iron correction
    mag_bias[0]  = (mag_max[0] + mag_min[0])/2;  // get average x mag bias in counts
    mag_bias[1]  = (mag_max[1] + mag_min[1])/2;  // get average y mag bias in counts
    mag_bias[2]  = (mag_max[2] + mag_min[2])/2;  // get average z mag bias in counts
    
    dest1[0] = (float) mag_bias[0]*mRes*magCalibration[0];  // save mag biases in G for main program
    dest1[1] = (float) mag_bias[1]*mRes*magCalibration[1];   
    dest1[2] = (float) mag_bias[2]*mRes*magCalibration[2];  
       
    // Get soft iron correction estimate
    mag_scale[0]  = (mag_max[0] - mag_min[0])/2;  // get average x axis max chord length in counts
    mag_scale[1]  = (mag_max[1] - mag_min[1])/2;  // get average y axis max chord length in counts
    mag_scale[2]  = (mag_max[2] - mag_min[2])/2;  // get average z axis max chord length in counts

    float avg_rad = mag_scale[0] + mag_scale[1] + mag_scale[2];
    avg_rad /= 3.0;

    dest2[0] = avg_rad/((float)mag_scale[0]);
    dest2[1] = avg_rad/((float)mag_scale[1]);
    dest2[2] = avg_rad/((float)mag_scale[2]);
  
    Serial.println("Mag Calibration done!");
}
```
Get soft iron correction estimate後面之後是在寫什麼？
```
// Get magnetometer calibration from AK8963 ROM
  initAK8963(magCalibration); Serial.println("AK8963 initialized for active data mode...."); // Initialize device for active mode read of magnetometer
```
上面是啥鬼 9250內部rom的參數？