ArduPilot with Linux その1

## Ardupilotについて
1年ほど前に、[ドローンのフライトコントローラ周りのOSSプロジェクトについて](http://qiita.com/akachochin/items/03a16038b3c20176c0a4)という記事を書きました。
その中で、Ardupilotというオープンソースプロダクトについて言及し、以下の図を載せました。

![c57c3ae1-d129-2044-4f55-606ca0b46e01.png](https://qiita-image-store.s3.amazonaws.com/0/19975/5219ffd4-a9d0-2e94-5704-b7a4965056d7.png)

現在でも、ユーザプロセスやライブラリ、HAL、OSといったフレームワークの基本的構造は変わりません。
しかし、変わったことがあります。
それは、HALで抽象化の対象となるOSにLinuxも加わったということです。つまり、Linux + Ardupilotでドローンのフライトコントローラを制御できるようになったことである。
OS好きとして、Linuxをどう使っているのか非常に興味の湧くところです。また、Nuttx以外にもサポートされているOSもあるようです。こちらも興味がありますね。

## Ardupilotの概要が書かれた資料はないの？
まず、[ArdupilotのWeb Page](http://ardupilot.org/copter/docs/introduction.html)を読んでみましょう。OSSのドキュメントとしてはかなりわかりやすい部類です。
その上で、[開発者向けのページ](http://ardupilot.org/dev/index.html)を順に読むと多くを得ることができます。

しかし、それで終わってしまうと、書きたいことにつながらないので、簡単にユーザプロセスの実装について述べていきます。
http://ardupilot.org/dev/docs/learning-ardupilot-the-example-sketches.html

## ソースを読む
よく言われるように、ユーザプロセス実装を理解するための早道はサンプルコードを読むことです。

```
Knowing the library API and conventions used in ArduPilot is essential to understanding the code. So using the library example sketches is a great way to get started. As a start you should read, build and run the example sketches for the following libraries
訳：Ardupilotで使われているLibrary APIとそのお約束事を知ることは、コードを理解する基本です。よってライブラリの実装例を使うことは、取っ掛かりとしてはとてもよい方法です。手始めに以下のライブラリ群の実装例を読んで、実際にビルドして走らせるのは良い考えです。
```

[ここ](https://github.com/ArduPilot/ardupilot)からgit cloneしましょう。
なお、読むソースコードは、「Copter-3.3.2」でタグ付けされているソースです。

あと、いくつか注意。
 - ビルド環境やソースを読む環境はUbuntu14.04です。それ以外の方は適当に読み替えてください。
 - 私も**個人的な興味・趣味**からソースを読んで勉強や調査をしております。なので、スゴいことを期待しないようお願いいたします(笑)。

## 機能追加をするもっとも基本的なやり方
ソースを読む前に、機能追加を行う最も基本的な方法についてみていきます。
[ArdupilotのWeb Page(Learning ArduPilot — The Example Sketches)](http://ardupilot.org/dev/docs/learning-ardupilot-the-example-sketches.html)をざっと読むと色々わかりますが、基本となる部分は以下のとおりです。
 - ユーザが追加するコードはSketchと呼ばれます。このプロジェクトがArduinoの影響を受けていることによります。よって、Arduinoを知っている人はイメージできるかもしれません。
 - Sketchは起動時に一度だけ呼ばれるsetup()とsetup()呼び出し以降繰り返し呼ばれるloop()があります。
 - halと呼ばれる変数があります。「これによってAP_HAL::HALオブジェクトへのアクセスが行える。このオブジェクトはすべてのハードウェア固有の関数にアクセスすることができ、これら関数にはコンソールへの出力関数、sleep、I2CやSPIバスを介した通信をする関数が含まれる。」
 - sketchにはAP_HAL_MAIN()というマクロが必ず含まれます。

文章だけだとイメージしづらいですね。サンプルとなるsketchを書いてみます。
一番簡単なsketchは以下の通りになります。

```c:sketchのスケルトン的なもの(skelton.cpp)
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-

#include <AP_HAL_Linux/AP_HAL_Linux.h>

const AP_HAL::HAL& hal = AP_HAL_BOARD_DRIVER;

void setup(void)
{
    hal.console->printf("setup\n");
}

void loop(void)
{
    hal.console->printf("loop\n");
}

AP_HAL_MAIN();
```

### ビルド手順
とりあえず、以下のようにやってみてください。
 1. libraries/AP_HAL_Linux/examples/ に skeltonというディレクトリを作って、上記のソースをコピペしてskelton.cppという名前で保存してください。
 2. libraries/AP_HAL_Linux/examples/BusTest からMakefileとmake.incを**内容を変更せずに**そのままlibraries/AP_HAL_Linux/examples/ にコピーしてください。
 3. make linux とタイプしてください。すると、ビルドが始まり、skelton.elfという実行形式ファイルが出来上がります。
    - 環境によっては、「gawkがない！」などビルドに必要なツールが不足していることでビルドエラーになるケースがあります。その際はインストール願います。

さて、skelton.elfを実行しましょう。
最初の1回だけsetupと表示され、あとは延々loopという文字列行が表示されます。

```:実行結果
setup
loop
loop
loop
loop
(以後続く)
```

フライトコントローラと呼ばれるハードウェア上で作成したソフトを動かす場合、もうひと手間かけないといけません。しかし、今回はArdupilotとLinuxについてソースを追ってみるのが主となります。よって、今回はフライトコントローラに関する記述は書きません。

### 今回のsketch作成でわかったこと
先に書いたとおりのことがわかりました。
 - setup()は最初の一回だけ呼ばれる。
 - setup()が呼ばれたあとで、loop()が繰り返し呼ばれる。
 - 何か、halというグローバル変数がある。少なくともコンソールへの表示は何かのインスタンス経由で行われるようだ。
 - AP_HAL_MAIN()という謎マクロがソースの一番下にある。

ここで、以下の疑問が湧いてきます。
 - setup()とloop()は誰が呼び出すのか？
 - AP_HAL_MAIN()とは何者か？
 - halの具体的内容は？
 - 一番最初の図には「ユーザプロセス」とある。今書いたsketchとプロセスの関係は？

次回以降、ソースを読んで疑問点を調べていきましょう。