【LEGOロボットプログラミング】TOPPERS箱庭/ROS対応版・EV3RTをローカル環境を極力汚さずに開発する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/fb20e33a-f711-68a6-b8c8-dac26db62604.png)

# はじめに
[TOPPERS箱庭/ROS対応版・単体ロボット向けシミュレータ](https://qiita.com/kanetugu2018/items/c63ad5827b23f9e1bf21)では、ETロボコンに準じたライントレースロボットを使ったロボットプログラミングを「実機レス」「シミュレータ内完結」で試すことが出来ます。
本記事では、Dockerを用いることで「環境を汚さずに」かつ、「いつものエディタを使って」プログラミングができるような開発環境を用意する方法について記述します。

# 準備等
[単体ロボット向けシミュレータ導入手順 - Unityのインストール・パッケージのインポート・通信方式の切替方法](https://toppers.github.io/hakoniwa/single-robot-setup-detail/60_unity_install/)の通り、Unityによるシミュレーション環境を構築します。

なお、様々な方法で動かすことが可能ですが、以下の条件で動かすものとします。

- [単体ロボット向けシミュレータ導入手順(v2.0)](https://toppers.github.io/hakoniwa/single-robot-setup-detail/60_unity_install_v2.0/)
- [UDP版](https://toppers.github.io/hakoniwa/single-robot-setup-detail/61_unity_install_udp_v2.0/)
  - [Io Writer]-[Host] を `127.0.0.1`に指定する。
  - 合わせて、``

# 環境構築

今回は`ARMv7-A`をターゲットとします。

## athrillのDockerコンテナをビルドする

単体でも使えるように、スタティックリンクのathrill実行ファイルをビルドして、マルチステージビルドを用いてまっさらな環境にコピーしています。

```dockerfile:Dockerfile
FROM ubuntu:18.04 as athrill-builder

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
        git \
        build-essential

WORKDIR /root
RUN git clone --depth 1 https://github.com/toppers/athrill.git && \
    git clone --depth 1 https://github.com/toppers/athrill-target-ARMv7-A.git
WORKDIR /root/athrill-target-ARMv7-A/build_linux
RUN make timer32=true clean && \
    make timer32=true -f Makefile.static

FROM ubuntu:18.04
COPY --from=athrill-builder /root/athrill/bin/linux/athrill2 /usr/local/bin
```

上記の`Dockerfile`を保存して、`docker build`します。

```bash
$ docker build -t hako/athrill:v1.1.1 -f Dockerfile .
```

athrillのコンテナイメージが作成されたことを確認できます。

```bash
$ docker images
REPOSITORY             TAG                        IMAGE ID            CREATED             SIZE
hako/athrill          v1.1.1                     02a87297b3c2        3 hours ago         69MB
```

## ev3rt-athrill-ARMv7-AのDockerコンテナをビルドする

[ev3rt-athrill-ARMv7-A](https://github.com/toppers/ev3rt-athrill-ARMv7-A)をクローンしてきて、中に以下のDockerfileを配置します。
Dockerfileでは、先程作成した`athrillのDockerコンテナ`を元にマルチステージビルドしています。

```bash
$ cd ${YOUR_WORK_SPACE}
$ git clone https://github.com/toppers/ev3rt-athrill-ARMv7-A.git
$ cd ev3rt-athrill-ARMv7-A
$ vi Dockerfile
```

```dockerfile:Dockerfile
FROM ubuntu:18.04 as ev3rt-builder

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
        git \
        build-essential \
        gcc-arm-none-eabi

WORKDIR /root
RUN git clone --depth 1 https://github.com/toppers/athrill.git && \
    git clone --depth 1 https://github.com/toppers/athrill-target-ARMv7-A.git && \
    git clone --depth 1 https://github.com/toppers/asp-athrill-mbed.git && \
    git clone --depth 1 https://github.com/tlk-emb/mROS.git && \
    sed -i '1i#include "kernel_cfg.h"' mROS/mros-lib/mros-src/api/ros.cpp

COPY . /root/ev3rt-athrill-ARMv7-A

WORKDIR /root/ev3rt-athrill-ARMv7-A
RUN mkdir -p cfg/cfg && \
    cp cfg/cfg-linux-64 cfg/cfg/cfg && \
    chmod +x cfg/cfg/cfg
WORKDIR /root/ev3rt-athrill-ARMv7-A/sdk/mros-obj
RUN make clean; make ATHRILL_BUILD_TARGET=ubuntu18

FROM hako/athrill:v1.1.1
RUN mkdir -p /root/ev3rt
COPY --from=ev3rt-builder /root/ev3rt-athrill-ARMv7-A/sdk/mros-obj/memory.txt /root/ev3rt/memory.txt
COPY --from=ev3rt-builder /root/ev3rt-athrill-ARMv7-A/sdk/mros-obj/device_config.txt /root/ev3rt/device_config.txt
COPY --from=ev3rt-builder /root/ev3rt-athrill-ARMv7-A/sdk/asp /root/ev3rt/asp
CMD ["athrill2", "-c1", "-t", "-1", "-m", "/root/ev3rt/memory.txt", "-d", "/root/ev3rt/device_config.txt", "/root/ev3rt/asp"]
```

```bash
./ev3rt-athrill-ARMv7-A
├── arch
├── cfg
├── configure
├── doc
├── Dockerfile <- プロジェクト直下に配置
├── extension
├── include
├── kernel
├── library
├── LICENSE.md
├── MANIFEST
├── pdic
├── README.md
├── README.txt
├── sdk
├── syssvc
├── target
├── test
└── utils
```

Unityで設定したように、Unity-athrill間通信用のIPアドレス(DEBUG_FUNC_VDEV_TX_IPADDR)が`127.0.0.1`となっていることを`sdk/mros-obj/device_config.txt`で確認して下さい。 

```bash:sdk/mros-obj/device_config.txt
DEBUG_FUNC_RESET_PC             0x18004400
DISABLE_SYMBOL_UNDERSCORE       1
DEVICE_CONFIG_TIMER_FD          400
DEBUG_FUNC_ENABLE_FT            1
DEBUG_FUNC_ENABLE_BT            1
DEBUG_FUNC_ENABLE_PROF          1
DEBUG_FUNC_ENABLE_WATCH         1
DEBUG_FUNC_ENABLE_SKIP_CLOCK    1
DEBUG_FUNC_ENABLE_SYNC_TIME     0
#DEBUG_FUNC_SHOW_SKIP_TIME      1
DEBUG_FUNC_ENABLE_VDEV          1
DEBUG_FUNC_VDEV_TX_PORTNO       54001
DEBUG_FUNC_VDEV_TX_IPADDR       127.0.0.1
DEBUG_FUNC_VDEV_RX_PORTNO       54002
DEBUG_FUNC_DISABLE_DEBUG_DATA_TYPE      1
```

正しく配置されていることを確認して、Dockerコンテナをビルドします。今回は`hako/ev3rt:v1.0.0`としてイメージを作成します。

```bash
$ cd ev3rt-athrill-ARMv7-A
$ docker build -t hako/ev3rt:v1.0.0 -f Dockerfile .
```

ev3rtのコンテナイメージが作成されたことを確認できます。

```bash
$ docker images
REPOSITORY             TAG                        IMAGE ID            CREATED             SIZE
hako/ev3rt            v1.0.0                     84e15941698e        3 hours ago         76.7MB
```

# 実行する

[単体ロボット向けシミュレータ使用手順\(ARM版\)のUnityのシミュレータの起動
](https://toppers.github.io/hakoniwa/single-robot-usage/01_usage_arm_v2.0/)を参考に、Unityでロボットシミュレータを起動します。

次に、roscoreを起動します。roscoreはｍROSで指定したIPアドレス環境（sdk/mros-obj/mros_config/mros_sys_config.h）で実行して下さい。

次に、`ev3rt-athrill-ARMv7-A`のプログラムを起動します。先程ビルドで作ったイメージを指定して下さい。

```bash
$ docker run -it --rm --net host --name ev3rt hako/ev3rt:v1.0.0
```

# 止める
基本的にはCtrl-Cで止まるはずなのですが、たまに止まらない環境もあるようです。その場合は`docker stop`コマンドで止めることが出来ます。

```bash
$ docker stop ev3rt
```

# デバッグする

athrillには優秀なデバッグツールがあります。デバッグしたいときは例えば次のようにDockerコンテナを起動すれば直ぐに使い始めることが出来ます。

```bash
$ docker run -it --rm --net host --name ev3rt hako/ev3rt:v1.0.0 athrill2 -c1 -i -t -1 -m /root/ev3rt/memory.txt -d /root/ev3rt/device_config.txt /root/ev3rt/asp
```

# コードを直す

コード修正は、手元の`ev3rt-athrill-ARMv7-A`ディレクト配下で行うことができます。

例えば、ロボットを動かすためのメインプログラムは`sdk/mros-obj/app.cpp`に記述されています。いろいろイジってロボットの挙動が変化することを観察してみて下さい。

```bash
$ vi sdk/mros-obj/app.cpp
```

`ev3rt-athrill-ARMv7-A`を`Visual Studio Code`などで開くとより開発しやすいかと思います。（エディタはあくまで一例、好みに合わせて選択してください。）

修正後は再度「ビルド」「実行」の手順を踏んで下さい。

```bash
$ cd ev3rt-athrill-ARMv7-A
$ docker build -t hako/ev3rt:v1.0.0 -f Dockerfile .                 # BUILD
$ docker run -it --rm --net host --name ev3rt hako/ev3rt:v1.0.0     # EXECUTE
```

# おわりに
コンテナを活用しながら、手元でソースコードをイジったり、デバッグしたりが違和感無くできる環境が完成しました。
ライントレーサロボットには、ロボットプログラミングの基礎が詰まっていて非常に勉強になります。
ぜひ、みなさんお試して下さい。