らずぱいで、MPU-9250 - ９軸センサモジュール(３軸加速度＋３軸ジャイロ＋３軸コンパス) 

![RTIMULib-01.png](https://qiita-image-store.s3.amazonaws.com/0/75594/a296863b-fc9e-88d3-c4b5-e1e8b1083c77.png)
ぐるぐる動くよ

## 概要
- `MPU-9250`というセンサーを ラズパイにI2Cで接続してみる。
- 参考: [How to Setup the MPU-9250 on a Raspberry Pi ](https://kingtidesailing.blogspot.com/2016/02/how-to-setup-mpu-9250-on-raspberry-pi_25.html)
- [`RTIMULib2`](https://github.com/RTIMULib/RTIMULib2)というライブラリを使って、そのデモを見る。<br>ちなみに、`Please note that this project is no longer active.`だそうで、開発終了、でしょうかね。
- IMU = Inertial Measurement Unit [(慣性計測装置)](https://ja.wikipedia.org/wiki/%E6%85%A3%E6%80%A7%E8%A8%88%E6%B8%AC%E8%A3%85%E7%BD%AE) ??
 <br> <font color=#FFFFFF>イナーシャルキャンセラー、全開。??</font>


## 環境
- Raspberry Pi 2 Model B
- `2016-05-27-raspbian-jessie.img`
- Invensense MPU-9250 (ebay.comとかでホンコンから、5～6ドルくらい? 忘れたころに届いた)


## 手順
1. MPU-9250を接続。I2Cは、線4本
 `VCC(3.3V)`、`GND`、`SCL`、`SDA`。(ものによっては、CSを3.3Vへ。)

2. デモで、Xを使うようなので、通常のraspbian-jessieを使用。

    ```bash:いつもの
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y byobu htop samba ## お好みで
```
3. 追加パッケージ

    ```bash:追加パッケージ
sudo apt-get install -y i2c-tools cmake git octave python-dev libqt4-dev
```
4. `sudo raspi-config`<br>I2Cを使う設定に。
`9 Advanced Options > A6  I2C > Yes`

5. `sudo vi /boot/config.txt`

    ```txt:/boot/config.txt_追加する
...
dtparam=i2c1_baudrate=400000
```


5. `sudo vi /etc/udev/rules.d/90-i2c.rules`

    ```txt:/etc/udev/rules.d/90-i2c.rules
KERNEL=="i2c-[0-7]",MODE="0666"
```

5. `sudo reboot`<br>再起動
6. `i2cdetect -y 1`<br>デバイスを認識しているか？

    ```shell-session:0x68が出た？
pi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@raspberrypi:~ $ 
```
7. RTIMULib2のビルド

    ```
cd
git clone https://github.com/richards-tech/RTIMULib2.git
mkdir RTIMULib2/Linux/build
cd RTIMULib2/Linux/build
cmake ..
make -j4
```

8. RTIMULibDemoGL デモの実行

    ```bash
cd ~/RTIMULib2/Linux/build/RTIMULibDemoGL
./RTIMULibDemoGL
```

    ![RTIMULib-02.png](https://qiita-image-store.s3.amazonaws.com/0/75594/72415bcc-f929-1a91-5221-0a91d57d1744.png)<br>
    ![RTIMULib-03.png](https://qiita-image-store.s3.amazonaws.com/0/75594/308ef105-a3d6-ecad-9c04-6c2562b3c4aa.png)


### Python バインディング
1. ビルド・インストール

    ```shell-session
cd 
cd ~/RTIMULib2/Linux/python
python setup.py build
sudo python setup.py install
```

2. サンプル

    ```bash:Fusion.pyを実行
cd
cd ~/RTIMULib2/Linux/python/tests 
python Fusion.py
```

    ```py:Fusion.pyのメインループの部分。
...
while True:
  if imu.IMURead():
    # x, y, z = imu.getFusionData()
    # print("%f %f %f" % (x,y,z))
    data = imu.getIMUData()
    fusionPose = data["fusionPose"]
    print("r: %f p: %f y: %f" % (math.degrees(fusionPose[0]), 
        math.degrees(fusionPose[1]), math.degrees(fusionPose[2])))
    time.sleep(poll_interval*1.0/1000.0)
```

3. 表示例

    ```shell-session
pi@raspberrypi:~/RTIMULib2/Linux/python/tests $ python Fusion.py
Using settings file RTIMULib.ini
Settings file does not exist, will be created
IMU Name: MPU-9250
IMU Init Succeeded
Recommended Poll Interval: 4mS
　　　　
r: -13.623389 p: 18.087236 y: -157.539734
r: -15.078542 p: 13.615657 y: -155.698479
r: -17.162211 p: 9.444151 y: -154.067935
r: -20.069331 p: 5.452485 y: -152.632844
r: -24.085829 p: 1.261949 y: -151.502680
r: -29.675574 p: -2.659780 y: -151.203285
r: -36.056415 p: -6.144597 y: -150.940009
r: -42.588142 p: -8.521807 y: -150.505049
r: -47.347961 p: -11.855518 y: -143.940581
r: -53.580303 p: -13.259552 y: -143.910050
r: -59.725537 p: -14.393150 y: -143.855190
r: -65.340165 p: -14.693897 y: -144.329574
r: -70.261821 p: -14.738734 y: -145.301906
r: -74.317014 p: -14.802757 y: -146.801051
r: -77.447959 p: -14.661696 y: -148.575780
r: -78.309102 p: -14.618659 y: -144.192779
r: -79.242762 p: -13.868489 y: -139.769317
r: -79.927195 p: -12.702007 y: -135.382600
r: -80.395718 p: -11.533799 y: -131.017385
r: -80.965821 p: -10.382536 y: -126.841995
r: -83.190119 p: -9.506169 y: -121.918590
^CTraceback (most recent call last):
  File "Fusion.py", line 44, in <module>
    time.sleep(poll_interval*1.0/1000.0)
KeyboardInterrupt
pi@raspberrypi:~/RTIMULib2/Linux/python/tests $ 
```

### キャリブレーション

- `octave`は、キャリブレーションのために、使用される模様。
- サンプルを実行すると、`RTIMULib.ini`というファイルが生成されるので、そいつをいったんコピーして、キャリブレーションして、元のとこにコピーする、、んだとおもう。

```bash
cd
cd RTIMULib2/Linux/RTIMULibCal/ 
make -j4
sudo make install
# sudo make uninstall もあるヨ。
#
cp -r /home/pi/RTIMULib2/RTEllipsoidFit/ /home/pi/
cd /home/pi/RTEllipsoidFit/
#設定をコピーしてきて、あとで、もどす？
# cp ~/RTIMULib2/Linux/build/RTIMULibDemoGL/RTIMULib.ini .
#
RTIMULibCal
```

1. `m`を押して、なにかキーを押して、ぐるぐる回して、数字が変わらなくなったら、`s`でセーブ。(`r`でリセット、`x`で中止。)
2. `s`を押して、なにかキーを押して、自動でとまるまで 、ぐるぐる回す。(`x`で中止。)
3. `a`をおして、
   1. x軸、`e`をおして、ぐるぐる。'` `'(スペース)で次の軸
   2. y軸、`e`をおして、ぐるぐる。'` `'(スペース)で次の軸
   3. z軸、`e`をおして、ぐるぐる。'` `'(スペース)で次の軸
   4. うまいとこで、`s`でセーブ。(`r`でリセット、`x`で中止。)
4. `x`をおしてキャリブレーション終了<br>=> `RTIMULib.ini`が更新されてるはず。


## その他

- 簡単なサンプルみれば使い方わかるね。

    ```shell-session
pi@raspberrypi:~ $ ~/RTIMULib2/Linux/build/RTIMULibDrive/RTIMULibDrive 
Settings file not found. Using defaults and creating settings file
Detected MPU9250 at standard address
Using fusion algorithm RTQF
min/max compass calibration not in use
Ellipsoid compass calibration not in use
Accel calibration not in use
MPU-9250 init complete
Sample rate 84: : roll:59.973343, pitch:83.228676, yaw:-122.156759
```

    - `cat ~/RTIMULib2/Linux/RTIMULibDrive/RTIMULibDrive.cpp`

```cpp:RTIMULibDrive.cpp
////////////////////////////////////////////////////////////////////////////
//
//  This file is part of RTIMULib
//
//  Copyright (c) 2014-2015, richards-tech, LLC
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy of
//  this software and associated documentation files (the "Software"), to deal in
//  the Software without restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
//  Software, and to permit persons to whom the Software is furnished to do so,
//  subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in all
//  copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
//  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
//  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
//  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
//  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


#include "RTIMULib.h"

int main()
{
    int sampleCount = 0;
    int sampleRate = 0;
    uint64_t rateTimer;
    uint64_t displayTimer;
    uint64_t now;

    //  Using RTIMULib here allows it to use the .ini file generated by RTIMULibDemo.
    //  Or, you can create the .ini in some other directory by using:
    //      RTIMUSettings *settings = new RTIMUSettings("<directory path>", "RTIMULib");
    //  where <directory path> is the path to where the .ini file is to be loaded/saved

    RTIMUSettings *settings = new RTIMUSettings("RTIMULib");

    RTIMU *imu = RTIMU::createIMU(settings);

    if ((imu == NULL) || (imu->IMUType() == RTIMU_TYPE_NULL)) {
        printf("No IMU found\n");
        exit(1);
    }

    //  This is an opportunity to manually override any settings before the call IMUInit

    //  set up IMU

    imu->IMUInit();

    //  this is a convenient place to change fusion parameters

    imu->setSlerpPower(0.02);
    imu->setGyroEnable(true);
    imu->setAccelEnable(true);
    imu->setCompassEnable(true);

    //  set up for rate timer

    rateTimer = displayTimer = RTMath::currentUSecsSinceEpoch();

    //  now just process data

    while (1) {
        //  poll at the rate recommended by the IMU

        usleep(imu->IMUGetPollInterval() * 1000);

        while (imu->IMURead()) {
            RTIMU_DATA imuData = imu->getIMUData();
            sampleCount++;

            now = RTMath::currentUSecsSinceEpoch();

            //  display 10 times per second

            if ((now - displayTimer) > 100000) {
                printf("Sample rate %d: %s\r", sampleRate, RTMath::displayDegrees("", imuData.fusionPose));
                fflush(stdout);
                displayTimer = now;
            }

            //  update rate every second

            if ((now - rateTimer) > 1000000) {
                sampleRate = sampleCount;
                sampleCount = 0;
                rateTimer = now;
            }
        }
    }
}
```


***

<font - [InvenSense Developers Corner](https://www.invensense.com/developers/)(要登録)からダウンロードできる、`Embedded MotionDriver 6.12`は、ライブラリがバイナリの配布なので、らずぱいで、使えないっぽい？？></font>