FPGA×ROSでFPGAをプラットフォームとしたロボットを実現するプロジェクトOpenReroc

#はじめに

##自律ロボットの発展

最近はロボットに対する注目がかなり高まっているように思います。
特に、産業用ロボットのようなものではなく、ロボット自身が周囲の状況を把握し動作するような「自律ロボット」の発展が目覚しいように思えます。（完全に主観的笑）
流行りのロボットといえば、おそらく皆さんご存知のお掃除ロボットの[ルンバ](https://www.irobot-jp.com/)があると思います。また、教育用の自律走行ロボットとしてはこのルンバを応用した、[Turtlebot](http://www.nihonbinary.co.jp/Products/Robot/TurtleBot.html)というものがあります(下の写真)。 
実はこのロボットはバッテリ駆動ですが、PC1台を搭載していて電力もそれなりに消費するため、連続駆動時間はそれほどありません。PCを搭載するのにもいろいろ理由がありますが、一番はロボットの性能の問題です。ロボットが自律的に行動するためにはさまざまな知的情報処理（おもに画像処理）が必要で、たいていその処理のどれもが非常に膨大な処理量です。つまりPCほど高性能なCPUを搭載しないと、処理しきれないというわけですね。

<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/7fa73599-cc5d-ddfd-e953-baec8256b9c0.png" height="150"></img>

画像引用：http://www.nihonbinary.co.jp/Products/Robot/TurtleBot.html

##低い電力のなかでも高い処理性能のためにFPGAを･･･！

電力性能比が一般的に高いといわれている**FPGA**であれば、バッテリ駆動で限られた電力制約のなかでも性能を発揮しうるプラットフォームです。
ただ、このFPGAは開発がとても大変。ロボットを開発するということは、ロボットを動かすための物理的な原理だとか、電気的な知識のほかに、自律行動させるためのアルゴリズムや制御構造を考慮しなければなりません。とてもではありませんが、FPGAを導入する余裕がないというのが現状であると思います。せっかくFPGAを使えばいいことがあるのに使わないのはもったいない。

##OpenRerocとは

[OpenReroc (Open source Reconfigurable Robot Component)](https://github.com/Kumikomi/OpenReroc)はFPGAの回路をロボットのためのコンポーネントとして開発するための研究プロジェクトです（ちなみに筆者も開発メンバー）。もう少し具体的にすると、ロボット向けのソフトウェアプラットフォームである[ROS](http://www.ros.org/)で使用できるFPGAの回路を含めたパッケージをリリースします。***ROSを用いてFPGAの回路をコンポーネント化をすることで、ロボットシステムへのFPGA導入を容易にするというモチベーションです。***図に示しているのはSoC(FPGA+CPU)上に構築したシステム例です。破線で囲まれた四角1つ1つがFPGAの回路を含むコンポーネントで、CPUサイドではROSとUbuntuが動作します。FPGAの回路を含むコンポーネントは他のROSノードと同等に通信ができますのでユーザはFPGAを意識することなくFPGAを導入できます。

<center>
<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/074052fc-9ed8-dc88-7a3d-8da659eaf26b.png" height="400"></img>
</center>

今回はこのプロジェクトのROSパッケージである***openreroc_pwm***を紹介します。

#openreroc_pwmの導入

##openreroc_pwmとは
openreroc_pwmはモータのPWM制御を行うためのコンポーネントです。
openreroc_pwmは以下のサイトから入手可能です。

- [ROSのwiki](http://www.ros.org/browse/details.php?distro=indigo&name=openreroc_pwm)：http://www.ros.org/browse/details.php?distro=indigo&name=openreroc_pwm
- [Github](https://github.com/Kumikomi/openreroc_pwm)：https://github.com/Kumikomi/openreroc_pwm

##openreroc_pwmのシステム構成

<center>
<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/ce16eceb-1fb6-8c9a-d497-7a8e251995a9.png" height="200"></img>
</center>

openreroc_pwmでは**”openreroc_pwm”**というトピックにモータへのパラメータを入力することによってモータの回転方向と回転速度を設定することができます。
このコンポーネントはROSにおいて**sample_input**、**openreroc_pwm**の2つのノードを起動することで動作検証が可能です。
また、コンポーネントのより詳細な要素は以下のとおりです。

- mortor_ctl.v : CPUとFPGAのデータ通信を行なうためのインターフェイス
- pwm_ctl.v : PWMのアルゴリズムの実装
- openreroc_pwm.cpp : 他のノードと通信するためのROSノードを記述したcpp

##準備するもの

openreroc_pwmを導入する際の要求環境です。なお、ここから説明することは、下記に示した要求環境が整っていることを前提とします。

###ハードウェア

- [Xilinx Zynq-7000 series -- Zedboard](http://zedboard.org/product/zedboard)
- [PmodHB3](http://japan.xilinx.com/products/boards-and-kits/1-bapx63.html)(モータドライバ) × 2
<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/8795b280-42ba-c901-6d9c-0db269759d6c.jpeg" height="150"></img>

- PWM制御に対応したモータ × 2

###ソフトウェア

- [xillinux-1.3c](http://xillybus.com/xillinux)
	- [Xillybus](http://xillybus.com/)社からリリースされているFPGA-ARM間の通信が可能な、Zedboard用のディストリビューション
	- XillinuxのZedboardへの導入はこちらをご参照ください。[XillinuxをつかってFPGA－ARMプロセッサのデータ通信をしよう](http://qiita.com/kazuyamashi/items/b49df82dc8d868364d53)
- [ROS](http://wiki.ros.org/ja)　(groovy以上のバージョン)  
	- xillinux上でインストールしてください。
	- 詳細なインストール方法はそのうち記事にしたいと思います。それまでの参考記事 → [Ubuntu ARM install of ROS Groovy](http://wiki.ros.org/groovy/Installation/UbuntuARM)
	- ROSにおける基本的な概念の勉強、開発方法はこちらをご覧ください。[ROSの基本的な開発をしよう](http://qiita.com/kazuyamashi/items/53104e2174d2df751868)
- ssh

###その他開発環境
- 母艦PC（FPGA回路の合成のため）
- Zedboardへのログインのためのターミナルソフト(任意)
- FPGAの回路の合成ツール
	- 今回はISE

##openreroc_pwmのクローンとディレクトリ構造
Zedboard上のXillinuxにおいて
以下のコマンドでopenreroc_pwmのリポジトリをROSのワークスペースにクローンしてください。

```
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone https://github.com/Kumikomi/openreroc_pwm.git 
```

クローンした中身は以下のようになっているかと思います。

```
openreroc_pwm 
|-include/ 
|-msg/ 
|-hardware
    |-src/
    |-image/
|-src/ 
|-CMakeLists.txt 
|-package.xml  
|-LICENSE.txt
```

また、各ディレクトリの中身は以下のとおりです。

- include：ヘッダファイル
- msg：openreorc_pwmで使用するメッセージ型の定義ファイル
- hardware
	- src：モータ制御のためのverilogファイル
	- image：bit stream
- src：ROSノードのcpp

##ハードウェアのビルド（母艦PC上でのビルド）
パッケージの中にはbitファイルも含まれていますが、今回はハードウェアのビルド方法を紹介します。
[Xillinuxの導入](http://qiita.com/kazuyamashi/items/b49df82dc8d868364d53)では回路データ[(xillinux-eval-zedboard-1.3c)](http://xillybus.com/downloads/xillinux-eval-zedboard-1.3c.zip)をダウンロードし、合成したかと思います。
このとき用いたプロジェクトを開いていください。なお、プロジェクトは`xillinux-eval-zedboard-1.3c/verilog`内の**xillydemo.xise**をWクリックです。  

###ソースの追加とインスタンスの追加
プロジェクトを開いたら上のメニューバーから***project → Add source***でプロジェクトに
`openreroc_pwm/hardware/src`の**mortor_ctl.v**と**pwm_ctl.v**を追加してください。
ソースを追加した後は、トップモジュールへインスタンスを作ります。
**xillydemo.v**を以下ように編集してください。

```verilog
//xillydemo.v
//267行目あたり
   // 32-bit loopback
//   fifo_32x512 fifo_32
//     (
//      .clk(bus_clk),
//      .srst(!user_w_write_32_open && !user_r_read_32_open),
//      .din(user_w_write_32_data),
//      .wr_en(user_w_write_32_wren),
//      .rd_en(user_r_read_32_rden),
//      .dout(user_r_read_32_data),
//      .full(user_w_write_32_full),
//      .empty(user_r_read_32_empty)
//      );

motor_ctl motor_ctl
(
.clk(bus_clk),
.rst_32(!user_w_write_32_open && !user_r_read_32_open),
.din_32(user_w_write_32_data),
.wr_en_32(user_w_write_32_wren),
.rd_en_32(user_r_read_32_rden),
.dout_32(user_r_read_32_data),
.full_32(user_w_write_32_full),
.empty_32(user_r_read_32_empty),

 .dir_out_r(dir_out_r),
 .dir_out_l(dir_out_l),
 .en_out_r(en_out_r),
 .en_out_l(en_out_l)
);
```

インスタンスを作成したあとにセーブするとプロジェクトの階層構造は以下のようになります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/9fa0dd06-02ca-aba7-4303-7a4e48846c80.png"></img>




###トップモジュールへのポートの追加

**xillydemo.v**のIOポート宣言に以下のポートを追加してください。

```verilog
output dir_out_r,
output dir_out_l,
output en_out_r,
output en_out_l,
input [3:0] sub_port
```

###配線の設定

Zedboardとモータの接続にはPmodのインターフェイスを使いますが
現段階ではPmodの口となるポートが使えません。
したがって、ポートを使用できるようにします。今回Pmodで使用するのは**写真に示したJBのポートです。**
Zedboardの配線を設定するためucfファイル編集します。**xillydemo.ucf**を以下のように編集してください。

<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/c7887513-d81d-1cc5-c9e3-c6a3b3315568.png" height=300></img>

```verilog
# "xillydemo.ucf"
# "86行あたり"
# Pmod JB
NET  dir_out_r  LOC = W12 | IOSTANDARD = LVCMOS33;
NET  en_out_r   LOC = W11 | IOSTANDARD = LVCMOS33;
NET  dir_out_l LOC = V12 | IOSTANDARD = LVCMOS33;
NET  en_out_l  LOC = W10 | IOSTANDARD = LVCMOS33;
NET sub_port[0] LOC = V10 | IOSTANDARD = LVCMOS33;
NET sub_port[1] LOC = W8 | IOSTANDARD = LVCMOS33;
NET sub_port[2] LOC = V9 | IOSTANDARD = LVCMOS33;
NET sub_port[3] LOC = V8 | IOSTANDARD = LVCMOS33;

NET PS_GPIO[32] LOC = M20  | IOSTANDARD=LVCMOS33;  # "FMC-LA00_CC_N"
NET PS_GPIO[33] LOC = M19  | IOSTANDARD=LVCMOS33;  # "FMC-LA00_CC_P"
NET PS_GPIO[34] LOC = N20  | IOSTANDARD=LVCMOS33;  # "FMC-LA01_CC_N"
NET PS_GPIO[35] LOC = N19  | IOSTANDARD=LVCMOS33;  # "FMC-LA01_CC_P"
NET PS_GPIO[36] LOC = P18  | IOSTANDARD=LVCMOS33;  # "FMC-LA02_N"
NET PS_GPIO[37] LOC = P17  | IOSTANDARD=LVCMOS33;  # "FMC-LA02_P"
NET PS_GPIO[38] LOC = P22  | IOSTANDARD=LVCMOS33;  # "FMC-LA03_N"
NET PS_GPIO[39] LOC = N22  | IOSTANDARD=LVCMOS33;  # "FMC-LA03_P"
```

###回路の合成と回路の導入

***Generate Programming File***をダブルクリックして論理合成を開始します。
論理合成が終わったら、生成されたbitファイル(xillydemo.bit)をブートSDにコピーします。
なお、パッケージ内のbitファイルを使用する際は**openreorc_pwm.bit**をもとあるbitファイルと差し替えてください。

##ソフトウェアのビルド(ZedboardのXillinux上におけるビルド)

以下のコマンドでopenreroc_pwmをビルドします。

```
cd ~/catkin_ws
source devel/setup.bash
catkin_make 
```
##Zedboardとモータの接続

***注意：Zedboardとモータの接続はZedboardの電源が落ちた状態で行ってください。***

###PmodHB3について
PmodHB3はPmodのモータドライバです。各ピンは以下の役割があります。左のピンはFPGAのPmodの口にそのまま接続できます。
また、右のポートはモータの＋、－と直流電源のVcc、GNDへそれぞれつなぎます。  
なお、モータの制御はDIR、ENピンにたいしてPWM制御をすることで行います。

<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/7968bb29-c62c-c600-f59e-7287b055774c.png" height="250"></img>

今回使うピンは、SA、SB以外のピンを使います。FPGA側のPmodのポートアサインは以下のようになっています。

<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/ab814dd4-3f1f-3d49-e2fc-558e2e59069a.png" height="300"></img>

<img src="https://qiita-image-store.s3.amazonaws.com/0/57052/d4e90e2e-e5fb-c541-c703-62ee0815cd85.jpeg" height="300"></img>


**モータドライバとFPGAを接続した様子**

##テスト実行

テスト実行は以下のコマンドで行ってください。

**ターミナル1**

```
cd ~/catkin_ws/
source devel/setup.bash
roscore &
rosrun openreroc_pwm openreroc_pwm
```
**ターミナル 2**

```
cd ~/catkin_ws/
source devel/setup.bash
rosrun openreroc_pwm sample_input
```

**sample_input**ではコマンドラインにおいて以下の入力形式でモータの速度や回転方向を決めることができます。

```
type parameter [dir_left] [para_left] [dir_right] [para_right]
1 6000 1 6000
0 10000 1 10000
.
.
.

```

入力形式は左から
`左モータの回転方向 左モータの回転速度　右モータの回転方向のパラメータ 右モータの回転速度のパラメータ`
です。現時点での**回転方向に対するパラメータは 0 or 1、回転速度に対するパラメータの値域は 0 ~ 19999**であり、
**値を大きくすればするほど回転速度が下がります。**入力してモータの挙動が変わったら正常に動作しています。
(なお、回転速度に対するパラメータを小さい値にするとシステム全体の電圧が低い場合、
Zedboardの電源が落ちてしまう場合がありますので6000~程度から検証することをお勧めします。)
(PS：そのうち直します。)

実際のロボットシステムへ活用する場合はたとえば**sample_input**が、制御計画が記述されたノードと交換されるというケースを想定しています。

#おわりに

いかがだったでしょうか。今回はFPGA×ROSでFPGAをプラットフォームとしたロボットを実現するプロジェクト**OpenReroc**の紹介と
そのパッケージの1つである**openreroc_pwm**を紹介しました。  
FPGA×ROS、FPGA×ロボットの一大旋風を起こすためにも私自身、がんばっていこうと思います。
ご質問、ご意見ございましたら、コメントしていただけると幸いです。

###連絡先と筆者のwebサイト
Email：kazushi_at_virgo.is.utsunomiya-u.ac.jp
HP : [Kazushi Yamashina](https://kazuyamashi.github.io/)

###関連リンクまとめ
- [OpenReroc (Open source Reconfigurable Robot Component)](https://github.com/Kumikomi/OpenReroc)
- [openreroc_pwm](https://github.com/Kumikomi/openreroc_pwm)
- [Xilinx Zynq-7000 series -- Zedboard](http://zedboard.org/product/zedboard)
- [PmodHB3](http://japan.xilinx.com/products/boards-and-kits/1-bapx63.html)(モータドライバ)
- [xillinux-1.3c](http://xillybus.com/xillinux)
- [Xillybus](http://xillybus.com/)
- [ROS](http://www.ros.org/)
- [ROS wiki](http://wiki.ros.org/ja)
- [Ubuntu ARM install of ROS Groovy](http://wiki.ros.org/groovy/Installation/UbuntuARM)
- [ROSの基本的な開発をしよう](http://qiita.com/kazuyamashi/items/53104e2174d2df751868)
- [XillinuxをつかってFPGA－ARMプロセッサのデータ通信をしよう](http://qiita.com/kazuyamashi/items/b49df82dc8d868364d53)
- [ルンバ](https://www.irobot-jp.com/)
- [Turtlebot](http://www.nihonbinary.co.jp/Products/Robot/TurtleBot.html)