制御のためのリアルタイムOS

# これはなに？
モーションコントロールのためにリアルタイムOSを用意する必要があったので，その時のメモ。
ここでは，RTAIを用いてUbuntu 16.04をリアルタイム化しました。

# 環境
- CPU: Intel pentium 4
- RAM: 1024GB
- HDD: 500GB
- OS: Ubuntu 16.04 LTS (amd64)

# リアルタイムOSって?
指定の時間ごとに処理を実行してくれるようなOSのこと。
厳密に時間を指定することがロボット制御などには必須なので利用されます。
他にも，ART-linux(産総研)などもあるが，古いカーネルしか対応していないので，今回はRTAIを選びました。

# インストール
[こちらのサイト](https://matsuya.tech/rtai-on-ubuntu16-04/)をベースに他のサイトや公式のマニュアルを見て行いました。

## Ubuntu16.04のインストール
テキトーにisoファイルなりをダウンロードしてインストールします。
（インストールは英語でやって，後から日本語をインストールするとディレクトリ名が英語のままにできるのでお勧め）

## 必要なパッケージなどのインストとダウンロード
端末を開いて必要なパッケージをインストールします。

```bash
sudo apt update
sudo apt upgrade
sudo apt install libncurses5-dev libssl-dev libelf-dev ccache
```
次にテキトーにフォルダを作って，ファイルをダウンロードします。
この時，OSが32bitの場合，amd64をi386と書き換えてダウンロードします。

```bash
mkdir ~/RTAI
cd ~/RTAI
wget https://www.rtai.org/userfiles/downloads/RTAI/rtai-5.1.tar.bz2
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.9.80.tar.gz
wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.9.80/linux-image-4.9.80-040980-generic_4.9.80-040980.201802031730_amd64.deb
```

そして，ソースは/usr/src/に展開し，カーネルイメージはその場に展開します。

```bash
sudo tar -xvf rtai-5.1.tar.bz2 -C /usr/src/
sudo tar -xvf linux-4.9.80.tar.gz -C /usr/src/
sudo dpkg-deb -x linux-image-4.9.80-040980-generic_4.9.80-040980.201802031730_amd64.deb linux-image-4.9.80
```
## カーネルの再コンパイルの準備
カーネルをコンパイルする準備をします。
まず，ソースフォルダに移動し，忘れる前にシンボリックリンクを張っておきます。

```bash
cd /usr/src/
sudo ln -s linux-4.9.80/ linux
sudo ln -s rtai-5.1/ rtai
```
次に，カーネルにパッチを当てます。
この時，お手本となるconfigファイルがあったほうが良いので，
先ほどRTAIフォルダに展開したカーネルイメージや現在のカーネルの/boot以下からファイルをコピーしてきます。

```bash
sudo cp ~/RTAI/linux-image-4.9.80/boot/config-4.9.80-040980-generic /usr/src/linux/.config
```
そうしたら，パッチを当てます。(ちなみに64bitも32bitもx86で良いそうです)
ここで，"-p"の後ろは英語の"l"（エル）ではなく，数字の"1"(いち)なので注意してください。（自分はここでしばらく悩みました・・・）

```bash
cd /usr/src/linux
sudo patch -b -p1 < /usr/src/rtai/base/arch/x86/patches/hal-linux-4.9.80-x86-4.patch
```
## カーネルのコンパイル設定
ここがインストールの**最大の難所**です。
なぜなら，個人の環境によって設定が変わるからです。
（どうしてもうまくいかない場合は，make localmodconfigを試してみてください）
以下のコマンドで，設定画面を開いて設定を変更します。
設定後は，SaveしてExitしてください。

```bash
sudo make menuconfig
```
### マニュアルに述べられている必須項目
以下の設定となっているか確認し，なっていなければ変更します。

- Processor type and features
    - Use register arguments => **exclude**
    - Interrupt pipeline => **include**
- Enable Loadable module support
    - Module versioning support => **exclude**

### おそらく必要な項目
- General setup
    - Stack Protector buffer over flow detection => **none**
- Proceccer type and features
    - Symmetric multi-processing support => マルチコアなら**include** / 単コアなら**exclude**
    - Enable maximum number of SMP processors and NUMA nodes => **exclude**
    - Maximum number of CPU's => 実際のコア数に合わせて2~4
    - SMT(Hyperthreading) scheduler support => **exclude**
- Power management and ACPI options
    - ACPI Support => **disable**
    - CPU Frequency scalling => **disable**

## カーネルのコンパイルとインストール
設定が終わったらコンパイルを行います。

```bash
cd /usr/src/linux
sudo make clean
sudo ccache make -j2 LOCALVERSION=-rtai
```
ccacheはコンパイル結果をキャッシュしてくれるコマンド，-jXはマルチスレッドでコンパイルしてくれるオプションらしいです。
LOCALVERSIONにはカーネル選択時に分かりやすい名前を付けておきます。
ここまで来たらいったん休憩です。（数時間のコンパイルになります）

終了したら，インストールします。

```bash
sudo make modules_install
sudo make install
```
また，起動時のGrubでカーネルを選択できるように設定を変えてからリブートします。

```bash
sudo nano /etc/default/grub
  # 以下をコメントアウトして保存
  # GRUB_HIDDEN_TIMEOUT=0
  # GRUB_HIDDEN_TIMEOUT_QUIET=true
sudo update-grub
sudo reboot
```
Grubの画面から，Advanced options for Ubuntuを選び，先ほど付けたLOCALVERSIONのカーネルを選択してブートする。
これで問題なくブートできればカーネルコンパイルは成功です。
念のため，"uname -a"でカーネルを確かめてみてください。
（ブートできない場合は，カーネル設定に戻っていろいろ変えてみてください）

## RTAIのインストール
最後にRTAIのモジュールなどをインストールします。

```bash
cd /usr/src/rtai
sudo make menuconfig
# ここでは設定変更せずExitを選びSaveする
sudo make
sudo make install
```

# 動作確認
インストール後には，レイテンシの確認を行いましょう。
まず，パスにRTAIのディレクトリを追加します。

```bash
export PATH="$PATH:/usr/realtime/bin"
```
次に，モジュールを手動でinsmodして確認してみます。

```bash
sudo insmod /usr/realtime/modules/rtai_hal.ko
sudo insmod /usr/realtime/modules/rtai_sched.ko
sudo insmod /usr/realtime/modules/rtai_lxrt.ko
sudo lsmod
```
正常にinsmodできることを確認したら，カーネルモードとユーザモードでそれぞれレイテンシを確認してみましょう。

```bash
cd /usr/realtime/testsuite/user/latency
sudo ./run
# ユーザーモードのレイテンシを確認し，Ctrl+Cで終了

cd /usr/realtime/testsuite/kern/latency
sudo ./run
# カーネルモードのレイテンシを確認し，Ctrl+Cで終了
```
それぞれのモードでoverrunsが0であれば，問題なく動作しています。
もし，0でない場合は，ACPIをexcludeしているかなどを確認しましょう。

# 後書き
とりあえず，リアルタイムな環境を構築できて一安心でした。
ART-linuxの実験PCもあるので，サンプリング時間をどのくらいまで下げられるかも比較してみたい。
（最も，小細工なしにapt-getが使える点でこちらの方が良い気はします）

当方素人につき，間違いなどあればぜひコメントにて教えてください。

# 参考サイト
[RTAI公式](https://www.rtai.org/) : オフィシャルページ（英語）
[RTAI on Ubuntu16.04](https://matsuya.tech/rtai-on-ubuntu16-04/) : 最も参考にした（日本語）
[User Manual](https://www.rtai.org/userfiles/documentation/documents/RTAI_User_Manual_34_03.pdf) : 少し古いが詳細な情報（英語,pdf）
[RTAI入門シリーズ](http://blog.smooth-works.net/archives/631) : RTAIの仕組みやAPIも含めて解説（日本語）
[RTAI3.9+Fedora17 64bit](http://www.sidewarehouse.net/rtai-inst64bit-3.9.html) : ディストリは違うが動作確認まで記載あり（日本語）