LEGO Mindstorms EV3 活用事例

LEGO Mindstorms EV3 は LEGO の Mindstorms シリーズの新しいパッケージです。EV3のメインのコントローラーは、Linux が標準搭載され、様々な言語でロボットの開発が可能になりました。

また、NXT では外部との無線通信が基本的に Bluetooth のみでしたが、EV3 では USBインターフェースが搭載され、無線LAN の USBアダプタを挿すことで無線LANなどで外部と通信することも可能になりました。

搭載される OS が Linux になったことで、これまでよりもさらに柔軟に、かつ高度なロボット開発が可能になりました。

このドキュメントでは、LEGO Mindstorms EV3 上に OpenRTM-aist を搭載し、ロボット制御に活用する方法、コンポーネントの開発方法を紹介します。

仕様

EV3 の外観を以下に示します。

ev3.png
LEGO Mindstorms EV3

EV3のコンピュータは以下の仕様になっています。

LEGO Mindstorms EV3 仕様
プロセッサ ARM9 300MHz
メモリ(ROM) 16MB Flash
メモリ(RAM) 64MB RAM
OS Linuxベース
ディスプレイ 178 x 128 pixels
出力ポート 4個
入力ポート 4個
アナログ
デジタル 460.8kbit/s
USB通信速度 High Speed (480Mbps)
USBインターフェース EV3同士の連結可能 (最大4台)
Wi-Fi通信ドングル利用可能
SDカードスロット Micro SDカード 32GBまでサポート
スマートデバイス接続 iOS, Android, Windows
ユーザーインターフェース 6ボタン, イルミネーション機能
プログラムサイズ (ライントレースの場合) 0.950KB
センサー通信性能 1000 回/秒, 1ms
データロギング 最大 1,000サンプリング/秒
Bluetooth通信 最大7台のスレーブと接続可能
動力 リチャージブルバッテリー または、単3電池 6本

なお、EV3では、リチャージブルバッテリーが同梱されています。スペックは下記のとおりです。

電池の種類 リチウムイオン
容量 2050mAh
NXT DCバッテリとの互換性 なし
NXT DCアダプタでの充電 可能
単三電池で動かした場合との比較 単三電池を利用した場合より充電式 DCバッテリーのほうが長く動く。
充電時間 4時間(フル充電の場合)

このBookの概要

このBookでは OpenRTM-aist で RTコンポーネントを開発・実行するための環境構築方法、便利に使うためのノウハウ、移動ロボットの制御や IO の利用方法などを解説します。


チュートリアル(EV3)

このページでは RTM講習会での EV3 操作手順を説明します。
実習では以下の Educator Vehicle 改を制御します。


/jp/node/6038

LEGO Mindstorms EV3 は LEGO の Mindstorms シリーズの新しいパッケージです。EV3 のメインのコントローラーは、Linux が標準搭載され、様々な言語でロボットの開発が可能になりました。

仕様

LEGO Mindstorms EV3 仕様
プロセッサ ARM9 300MHz
メモリ(ROM) 16MB Flash
メモリ(RAM) 64MB RAM
OS Linuxベース
ディスプレイ 178 x 128 pixels
出力ポート 4個
入力ポート 4個
アナログ
デジタル 460.8kbit/s
USB通信速度 High Speed (480Mbps)
USBインターフェース EV3同士の連結可能 (最大4台)
Wi-Fi通信ドングル利用可能
SDカードスロット Micro SDカード 32GBまでサポート
スマートデバイス接続 iOS、Android、Windows
ユーザーインターフェース 6ボタン, イルミネーション機能
プログラムサイズ (ライントレースの場合) 0.950KB
センサー通信性能 1000 回/秒、1ms
データロギング 最大 1,000サンプリング/秒
Bluetooth通信 最大7台のスレーブと接続可能
動力 リチャージブルバッテリー または、単3電池 6本

デバイス

EV3 には以下のデバイスが付属しています。

ジャイロセンサー
45505_GyroSensor.jpg
確度モード: 精度 +/- 3°
角速度モード: 最大 440 deg/sec
サンプリングレート 1,000 Hz
カラーセンサー
45506_color.jpg
計測: 赤色光の反射光、 周囲の明るさ、色
検出カラー数: 8色 (無色、黒、青、緑、黄、赤、白、茶)
サンプリングレート 1,000 Hz
距離 約1mm~18mm(アフレル調査値)
タッチセンサー
45507_TouchSensor.jpg
オン (1), オフ (0)
スイッチ可動域: 約4mm
超音波センサー
45504_UltrasonicSensor.jpg
距離計測可能範囲: 3cmから250cm
距離計測精度: +/- 1 cm
前面電飾: 点灯:超音波発信中、 点滅:超音波観測中
EV3 Lモーター
45502_LargeMotor.jpg
フィードバック: 1°単位
回転数: 160から170RPM
定格トルク: 0.21 N・m (30oz*in)
停動トルク: 0.42 N・m (60oz*in)
重さ: 76 g
EV3 Mモーター
45503_MediumMotor.jpg
フィードバック 1°単位
回転数: 240から250RPM
定格トルク: 0.08 N・m (11oz*in)
停動トルク: 0.12 N・m (17oz*in)
重さ: 36 g

ダウンロード

最初にPC側で使用する RTC 等をダウンロードしてください。

ZIPファイルを Lhaplus 等で展開してください。

EV3 の組み立て方

EV3 は分解した状態で参加者に配ります。 組み立て方は以下の通りです。

※超音波センサー、カラーセンサー、ジャイロセンサーについては、講習で使用しないため取り付ける必要はありません。 以下の※の作業については、時間が余った人が実施してください。

まずは土台部分を取り出してください。


s_DSC00463.JPG

最初にMモーターにケーブル(25cm)を接続します※。


s_DSC00446.JPG

次に EV3 本体を取り付けます。 Mモーターにケーブルを接続した場合は、ケーブルが左側の隙間から出るようにしてください。


s_DSC00448.JPG s_DSC00450.JPG



右側のタッチセンサーを取り付けてください。


s_DSC00451.JPG s_DSC00452.JPG



超音波センサーを取り付けてください※。


s_DSC00454.JPG

ケーブルを接続してください。 必須なのは車輪駆動用のLモーター右、Lモーター左、タッチセンサーだけです。

Lモーター右 ポート C 25cmケーブル
Lモーター左 ポート B 25cmケーブル
Mモーター※ ポートA 25cmケーブル
タッチセンサー右 ポート 3 35cmケーブル
タッチセンサー左 ポート 1 35cmケーブル
超音波センサー※ ポート 4 50cmケーブル
ジャイロセンサー※ ポート 2 25cmケーブル

ケーブルは EV3 の上下に A~D と 1~4 のポートがあるのでそこにケーブルを接続します。


s_DSC00.JPG s_DSC00471.JPG




s_DSC00455.JPG s_DSC00456.JPG



左右にパーツを取り付けます※。 Lモーター右、Lモーター左、Mモーター、タッチセンサー右、タッチセンサー左のケーブルを挟むようにして取り付けてください※。
Lモーター右、タッチセンサー右のケーブルは右側から、Lモーター左、Mモーター、タッチセンサー左は左側から通してください※。


s_DSC00457.JPG


s_DSC00459.JPG

これでとりあえず完成ですが、余裕のある人はジャイロセンサーを取り付けてみてください※。


s_DSC00460.JPG s_DSC00461.JPG



電源の入れ方/切り方

電源の入れ方

中央のボタンを押せば電源が投入されます。


ev3_on.jpg

電源の切り方

EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。


ev3_off.jpg


s_DSC01033.JPG

再起動

再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。

リセット

ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。


ev3_reset.jpg

EV3 への接続

EV3 へは原則として無線LANで接続するようにしてください

無線LANアクセスポイントへの接続

まずは EV3 の中央のスイッチを押して電源を投入してください。
ここで電源を投入する前に無線LANアダプタを取り付けておいてください。

以下の作業でスクリプトを実行するとアクセスポイントが起動します。

EV3 の操作画面から「File Browser」を上下ボタンで選択して中央のボタンを押してください。

 ------------------------------
 192.168.0.1
 ------------------------------
 [File Browser               > ]
  Device Browser             >
  Wireless and Networks      > 
  Battery                    >
  Open Roberta Lab           >
  About                      >
 ------------------------------

次に scripts を選択して中央ボタンを押してください。

 ------------------------------
 192.168.0.1
 ------------------------------
         File Browser
 ------------------------------
 /home/robot
 ------------------------------
 [scripts                     ]
 ・・
 ・・
 ------------------------------

次の画面から start_ap.sh を選択して中央ボタンを押すとスクリプトが起動します。

 ------------------------------
 192.168.0.1
 ------------------------------
         File Browser
 ------------------------------
 /home/robot/scripts
 ------------------------------
 ../
 Component/
 ・・
 [start_ap.sh                 ]
 ------------------------------

しばらくすると無線LANアクセスポイントが起動するので、指定の SSID のアクセスポイントに接続してください。 SSID、パスワードは EV3 に貼り付けたテープに記載してあります。


tutorial_ev3_irex26.png

アクセスポイントへの接続方法は以下のページを参考にしてください。

まず右下のネットワークアイコンをクリックしてください。


/ja/node/6042

次に一覧から ev3_***を選択してください。


tu_ev3_11.png

パスワードを入力してください。


/ja/node/6042

USBケーブルでの接続

以下の作業は有線で接続する場合の作業なので、無線で接続する場合は不要です。

付属の USBケーブルで EV3 と PC を接続してください。


s_DSC00467.JPG

中央のボタンを押して電源を投入してください。

ここで EV3 の電源を投入する前に無線LANアダプタは取り外しておいてください。
以下の画面が表示されていれば ev3dev の起動に成功していますが、起動途中で停止した場合は この手順 で再起動してください。


s_DSC00470.JPG

デバイスマネージャで「EV3+ev3dev」が「その他のデバイス」の下にある場合は正しく機能していないので、以下の手順でデバイスソフトウェアの更新を行ってください。

まずはコントロールパネルからデバイスマネージャを開いてください。


tu_ev3_17.png


tu_ev3_18.png

開いたら EV3+ev3dev を右クリックして「ドライバソフトウェアの更新」を選択してください。
ここで EV3+ev3dev がネットワークアダプターの下にある場合は正常に認識されているので以下の作業は不要です。


tu_ev3_1.png

「コンピューターを参照してドライバー ソフトウェアを検索します」を選択してください。


tu_ev3_3.png

「コンピューター上のデバイス ドライバーの一覧から選択します」を選択してください。


tu_ev3_4.png

ネットワーク アダプターを選択して次へをクリックしてください。


tu_ev3_5.png

製造元は「Microsoft Corporation」、ネットワークアダプタは「Remote RNDIS Compatible Device」を選択して次へをクリックしてください。


tu_ev3_9.png

ドライバー更新警告が出た場合は「はい」を選択してください。


tu_ev3_7.png

正常に更新されたら閉じるを選択してください。


tu_ev3_8.png

事前準備

このページ の手順に従ってネームサーバー、RTシステムエディタを起動してください。 予めネームサーバーを起動してある場合は再起動してください。

またネットワークインターフェースが2つ以上ある場合に通信に失敗する可能性があるため、有線で接続した場合は他のネットワークデバイスを無効にしてからネームサーバーを起動してください。


/ja/node/6042


/ja/node/6042

ネームサーバー追加

続いて RTシステムエディタのネームサーバー追加ボタンで192.168.0.1(無線LANで接続する場合は192.168.11.1)を追加してください。


/jp/node/6042 tu_ev3_25.png



するとEducatorVehicle0という RTC が見えるようになります。

EducatorVehicle は EV3 の走行速度の入力、センサーのデータの出力等を行うためのコンポーネントです。


 /ja/node/6030

EducatorVehicle
InPort
名前 データ型 説明
velocity2D RTC::TimedVelocity2D 目標速度
angle RTC::TimedDouble Mモーターの角度
lcd RTC::TimedString LCDに表示する画像ファイル名
sound RTC::TimedString 出力する音声
OutPort
名前 データ型 説明
odometry RTC::TimedPose2D 現在の位置・姿勢
ultrasonic RTC::RangeData 超音波センサーで計測した距離
gyro RTC::TimedDouble ジャイロセンサーで計測した角度
color RTC::TimedString カラーセンサーで計測した色
light_reflect RTC::TimedDouble カラーセンサーで計測した反射光の強さ
touch RTC::TimedBoolean タッチセンサーのオンオフ。右側が0番目の要素、左側が1番目の要素
コンフィギュレーションパラメーター
名前 デフォルト値 説明
wheelRadius 0.028 車輪の半径
wheelDistance 0.054 タイヤ間距離の1/2
medium_motor_speed 1.6 Mモーターの速度

TimedVelocity2D型について

TimedVelocity2D型は以下のように定義されています。

     struct Velocity2D
     {
         double vx;
         double vy;
         double va;
     };

     struct TimedVelocity2D
     {
         Time tm;
         Velocity2D data;
     };

vx、vy、va はロボット中心座標系での速度を表しています。


tu_ev3_19.png

vx は X方向の速度、vy は Y方向の速度、va は Z軸周りの角速度です。

Educator Vehicle のように2個の車輪が左右に取り付けられているロボットの場合、横滑りしないと仮定すると vy は0になります。

vx、va を指定することでロボットの操作を行います。

音声の出力

sound による音声の入力には以下のコマンドを利用できます。

  • beep
    beep と入力するとビープ音が鳴ります。
  • tone
    以下のように tone、周波数、時間と入力すると指定周波数の音を指定ミリ秒数だけ鳴らします。

 tone,100,1000

  • それ以外
    それ以外は指定文字列を発音します

LCD に表示する画像について

LCD で表示する画像は付属資料の software/saveBinaryImage/EXE/saveBinaryImage.exeで変換したものを利用してください。
画像ファイルを saveBinaryImage.exe にドラッグ・アンド・ドロップすれば変換できます。

サンプルコンポーネント起動

付属資料のstart_component_ev3.batを起動してください。 ※OpenRTM-aist Python版をインストールしていない場合、もしくはインストールに失敗している場合は個別に実行ファイル入りのUSBメモリーを配布いたしますので、その中のstart_component_ev3_exe.batを利用してください。

すると以下の2つの RTC が起動します。

tu_ev3_24.png

動作確認

まずはジョイスティックで EV3 を操作してみます。

RTシステムエディタで EducatorVehicle、FloatSeqToVelocity、TkJoyStick を以下のように接続します。


tutorial_ev3_16.png

そして RTC をアクティブ化するとジョイスティックで EV3 の操作ができるようになります。


tutorial_ev3_21.png

自作の RTC で制御

まずは FloatSeqToVelocity の out と EducatorVehicle の target_velocity_in のコネクタを切断してください。

tutorial_ev3_17.png

FloatSeqToVelocity と EducatorVehicle の間に自作の RTC を接続して、タッチセンサーがオンになった場合に停止して音を鳴らすようにします。

ひな形コードの作成

RTC ビルダを起動してください。


/jp/node/6038

起動したら新規にプロジェクトを作成します。


/jp/node/6038

プロジェクト名は TestEV3CPP(TestEV3Py)にします。

以下のように設定を行ってください。 C++、もしくは Python で作成します。

基本
モジュール名 TestEV3CPP、もしくはTestEV3Py
アクティビティ
有効アクション onInitialize、onExecute、onActivated、onDeactivated
データポート
InPort
名前 データ型 説明
velocity_in RTC::TimedVelocity2D 入力目標速度
touch RTC::TimedBooleanSeq タッチセンサーのオンオフ
OutPort
名前 データ型 説明
velocity_out RTC::TimedVelocity2D 出力目標速度
sound RTC::TimedString 音声
コンフィギュレーション
名前 説明
sound_output string タッチセンサーが ON の時に発する音声。デフォルト値は beep
言語・環境
言語 C++、もしくはPython

[コード生成] ボタンを押したらコードが生成されます。


tutorial_raspimouse10.png

プロジェクト生成

コードが生成できたら C++ の場合は CMake で Visual Studio のプロジェクト(Ubuntu の場合は Code::Blocks)を生成してください。

まず CMake (cmake-gui) を起動します。

  • Windows 7

/jp/node/6038

  • Windows 8.1


/jp/node/6038

起動したらソースコードのディレクトリー、ビルドを行うディレクトリーに以下を指定します。 括弧内は eclipse の作業ディレクトリーを C:\workspace にした場合の例です。

Where is the source code RTCBuilder で生成したコードのフォルダー(C:\workspace\TestEV3CPP)
Where to build the binaries RTCBuilder で生成したコードのフォルダーの下に作成したbuildフォルダー(C:\workspace\TestEV3CPP\build)


tutorial_ev3_24.png

[Configure] ボタン→ [Generate] ボタンをクリックするとVisual Studioのプロジェクトが生成されます。

ソースコードの編集

build ディレクトリーの TestEV3CPP.sln を開いてください。

次にコードの編集を行います。

Pythonの場合はまず変数の初期化部分を修正してください。

  • TestEV3Py.py

     def __init__(self, manager):
         #self._d_velocity_in = RTC.TimedVelocity2D(*velocity_in_arg)
         self._d_velocity_in = RTC.TimedVelocity2D(RTC.Time(0,0),RTC.Velocity2D(0,0,0))

         #self._d_distance_sensor = RTC.TimedShortSeq(*distance_sensor_arg)
         self._d_distance_sensor = RTC.TimedShortSeq(RTC.Time(0,0),[])

         #self._d_velocity_out = RTC.TimedVelocity2D(*velocity_out_arg)
         self._d_velocity_out = RTC.TimedVelocity2D(RTC.Time(0,0),RTC.Velocity2D(0,0,0))

         #self._d_buzzer = RTC.TimedShort(*buzzer_arg)
         self._d_buzzer = RTC.TimedShort(RTC.Time(0,0),0)

まずは onExecute で入力速度をそのまま出力するコードを書いてみます。
C++の場合は以下のようになります。
isNew関数で新規の入力データが存在するかを確認して、read関数で変数(m_velocity_in)に格納します。 そして m_velocity_out に出力データを格納して write関数を呼び出すとデータが送信されます。

  • src/TestEV3CPP.cpp

     if (m_velocity_inIn.isNew())
     {
         m_velocity_inIn.read();
         //入力速度をそのまま出力
         m_velocity_out.data.vx = m_velocity_in.data.vx;
         m_velocity_out.data.vy = m_velocity_in.data.vy;
         m_velocity_out.data.va = m_velocity_in.data.va;
         setTimestamp(m_velocity_out);
         m_velocity_outOut.write();
 
 
     }

Pythonの場合は以下のようになります。

  • TestEV3Py.py

         if self._velocity_inIn.isNew():
             data = self._velocity_inIn.read()
             #入力速度をそのまま出力する
             self._d_velocity_out.data.vx = data.data.vx
             self._d_velocity_out.data.vy = data.data.vy
             self._d_velocity_out.data.va = data.data.va
             OpenRTM_aist.setTimestamp(self._d_velocity_out)
             self._velocity_outOut.write()

次にタッチセンサーがオンの場合に停止する処理を記述します。
常にタッチセンサーのデータが入力されるとは限らないので、センサーのデータを格納する変数を宣言します。
C++の場合は TestEV3CPP.h に記述します。

  • include/TestEV3CPP/TestEV3CPP.h

  private:
      bool m_last_sensor_data[2];


Pythonの場合はコンストラクタに記述します。

  • TestEV3Py.py

     def __init__(self, manager):
         OpenRTM_aist.DataFlowComponentBase.__init__(self, manager)
 
         self._last_sensor_data = [False, False]

次に onExecute に停止する処理を記述します。
C++の場合は以下のようになっています。
まずインポート touch に isNew 関数で新規にデータが入力されたかを確認して、入力されている場合は read関数で読み込みます。そして変数 m_last_sensor_data に格納します。
そしてインポート velocity_in で受信したデータの vx が 0 以上の場合には前進しているため障害物に接触するかもしれないと判定して、タッチセンサーがオンの場合は停止してブザーを鳴らします。

  • src/TestEV3CPP.cpp

 RTC::ReturnCode_t TestEV3CPP::onExecute(RTC::UniqueId ec_id)
 {
     //データを新規に受信した場合に、データをm_last_sensor_dataを格納する
     if (m_touchIn.isNew())
     {
         m_touchIn.read();
         if (m_touch.data.length() == 2)
         {
             for (int i = 0; i < 2; i++)
             {
                 //タッチセンサがOFFからONになった時に音を鳴らす
                 if (!m_last_sensor_data[i] && m_touch.data[i])
                 {
                     m_sound.data = m_sound_output.c_str();
                     setTimestamp(m_sound);
                     m_soundOut.write();
 
 
                 }
                 m_last_sensor_data[i] = m_touch.data[i];
             }
         }
     }
     if (m_velocity_inIn.isNew())
     {
         m_velocity_inIn.read();
         //vxが0以上(前進)のときのみ停止するか判定する
         if (m_velocity_in.data.vx > 0)
         {
             for (int i = 0; i < 2; i++)
             {
                 //タッチセンサがONの時に停止する
                 if (m_last_sensor_data[i])
                 {
                     //停止する
                     m_velocity_out.data.vx = 0;
                     m_velocity_out.data.vy = 0;
                     m_velocity_out.data.va = 0;
                     setTimestamp(m_velocity_out);
                     m_velocity_outOut.write();
 
 
                     return RTC::RTC_OK;
                 }
             }
         }
         //入力速度をそのまま出力
         m_velocity_out.data.vx = m_velocity_in.data.vx;
         m_velocity_out.data.vy = m_velocity_in.data.vy;
         m_velocity_out.data.va = m_velocity_in.data.va;
         setTimestamp(m_velocity_out);
         m_velocity_outOut.write();

   return RTC::RTC_OK;
 }

Pythonの場合は以下のようになっています。

  • TestEV3Py.py

     def onExecute(self, ec_id):
         #データを新規に受信した場合に、データをm_last_sensor_dataを格納する
         if self._touchIn.isNew():
             data = self._touchIn.read()
             if len(data.data) == 2:
                 for i in range(2):
                     #タッチセンサがOFFからONになった時に音を鳴らす
                     if not self._last_sensor_data[i] and data.data[i]:
                         self._d_sound.data = self._sound_output[0]
                         OpenRTM_aist.setTimestamp(self._d_sound)
                         self._soundOut.write()
                 self._last_sensor_data = data.data[:]
 
         if self._velocity_inIn.isNew():
             data = self._velocity_inIn.read()
             #vxが0以上(前進)のときのみ停止するか判定する
             if data.data.vx > 0:
                 for d in self._last_sensor_data:
                     #タッチセンサーがONの時に停止する
                     if d:
                         #停止する
                         self._d_velocity_out.data.vx = 0
                         self._d_velocity_out.data.vy = 0
                         self._d_velocity_out.data.va = 0
                         OpenRTM_aist.setTimestamp(self._d_velocity_out)
                         self._velocity_outOut.write()
                         
                         return RTC.RTC_OK
 
             #入力速度をそのまま出力する
             self._d_velocity_out.data.vx = data.data.vx
             self._d_velocity_out.data.vy = data.data.vy
             self._d_velocity_out.data.va = data.data.va
             OpenRTM_aist.setTimestamp(self._d_velocity_out)
             self._velocity_outOut.write()
         return RTC.RTC_OK

コードの編集が終わったら C++ の場合はビルドしてください。
ビルドに成功すると build\src\Release(Debug) に TestEV3CPPComp.exe が生成されます。

動作確認

TestEV3CPPComp.exe (TestEV3CPPComp.py) をダブルクリックして起動してください。
TestEV3CPP(TestEV3Py)を以下のように接続してください。


tutorial_ev3_18.png

最後に RTC をアクティブ化して動作確認してください。

RTシステム保存

RTシステムを保存する場合は System Diagram 上で右クリックして Save As... を選択してください。


tutorial_ev3_20.png


/jp/node/6038


RTシステム復元

復元する場合は Open and Restore を選択して、先ほど保存したファイルを選択してください。


/ja/node/6042

RTC 終了

RTC を終了する場合は RTシステムエディタ上で RTC を exit してください。


tutorial_ev3_19.png

補足

スクリプトファイルについて

EV3 のボタン操作で File Brower を選択すると/home/robot以下のディレクトリーの操作ができます。
scripts フォルダー内のシェルスクリプトを実行することで以下の操作ができます。

スクリプトファイル名 内容
run_rtcs.sh RTC を起動する
stop_rtcs.sh RTC を終了する

SD カードの準備

はじめに

ここでは、LEGO Mindstorms EV3 上で OpenRTM-aist とそのコンポーネントを動作させるための実行環境のインストールについて説明します。

ここでは、openrtm.org が提供する OpenRTM-aist 入りの OSイメージをダウンロードし、各種セットアップについて説明します。 EV3上で OpenRTM を使用できるようにするまでの大まかな手順は以下の通りです。

  • SDカードに OSイメージを書き込む
  • OS の基本的なセットアップ
  • コンポーネントの実行テスト

SD カード

EV3 には micro SD カードスロットが一つあり、ここに起動した OS を書き込んだ micro SD カードを差し込むと、任意の OS を起動することができます。

用意する SDカードは 2GB以上 32GB以下のも micro SDカード になります。mini SD や SDカードは刺さりませんのでご注意ください。 また、書き込むイメージは約2GB程度ありますので、最低で2GBの容量が必要となります。EV3 は 32GBより大きい SDXC仕様の SDカードには対応していませんので、注意してください。

  • 用意するSDカード
    • micro SDカード
    • 2GB以上、32GB以下

OSイメージのダウンロード

EV3上 での OpenRTM-aist の実行には ev3dev という OS を使用します。

以下のサイトから ev3-ev3dev-jessie-2015-12-30.img.zip をダウンロードしてください。 名前が似たファイルが多数配布されているので間違えないようにしてください。

ev3dev OSイメージのダウンロード

ev3dev とは EV3 上で Linux のディストリビューションの1つである、Debian GNU Linuxを EV3 に搭載した EV3用の Debian ディストリビューションです。 OpenRTM-aist を動作させるには、この ev3dev を micro SDカードに書き込み、EV3 を SDカードから起動させます。

上記の ev3dev オフィシャルWebページから ev3dev の OSイメージファイルがダウンロードできますが、OpenRTM-aist などはインストールされていません。 基本的には、以下のリンクから OpenRTM-aist (C++、Python) 入りの ev3dev イメージファイルをダウンロードしてください。

サンプルコンポーネント入りのイメージ

Educator Vehicle等のサンプルコンポーネント入りのイメージです。

EV3の無線LANアダプタを交換した場合に、無線LANアクセスポイントモードが正常に動作しない場合があります。 その場合は他のアクセスポイントに接続する等して、以下のコマンドを実行して70-persistent-net.rulesを編集します。 ユーザー名はrobot、パスワードはmakerでログインして操作してください。

 sudo nano /etc/udev/rules.d/70-persistent-net.rules

具体的には70-persistent-net.rulesのSUBSYSTEMから始まる行を全てコメントアウトします。

 # USB device 0x:0x (rtl8192cu)
 SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:22:cf:f6:52:a5", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="wlan*", NAME="wlan1"

イメージの展開

ダウンロードしたファイル YYYY-MM-DD-ev3dev-openrtm.zip を展開してください。 YYYY-MM-DD-ev3dev-openrtm.img という2GB位のファイルが展開されているはずです。

Windows

ファイルを右クリックして「すべて展開」を選択すると、展開できます。

Linux

 $ unzip <イメージファイル>

で展開できます。unzip コマンドがない場合はインストールしてください。

 $ unzip 2015-08-06-ev3dev-openrtm.zip
 Archive:  2015-08-06-ev3dev-openrtm.zip
   inflating: 2015-08-06-ev3dev-openrtm.img
 $ ls -l
 合計 2321300
 -rw-rw-r-- 1 n-ando n-ando 1887436800  8月  4 21:37 2015-08-06-ev3dev-openrtm.img
 -rw-rw-r-- 1 n-ando n-ando  489565916  8月  5 10:13 2015-08-06-ev3dev-openrtm.zip

うまく展開できない場合、ダウンロードに失敗しファイルが壊れている可能性があります。壊れたファイルを削除して、再度ダウンロードしてみてください。

イメージの書き込み

展開された yyyy-mm-dd-ev3dev-openrtm.img はイメージファイルといい、ev3dev が起動するディスクの状態をディスクの最初から最後まで1バイトづつ抜き出したものです。 このファイルを SDカードに単純にコピーしても使用することはできません!!

以下に説明する方法で SDカードに書き込んでください。

イメージの書き込み (Windows)

Windows では Win32DiskImager というツールを使用することでイメージの書き込みができます。 以下のサイトからイメージデータ書き込みツール Win32DiskImager のバイナリをダウンロードします。

ダウンロードしたファイル (win32diskimager-vX.X-binary.zip ) を解凍します。

※Win32DiskImager は、2バイト文字に対応していないため、YYYY-MM-DD-ev3dev-openrtm.zip は途中のパス名に全角文字や空白が含まれていない場所に解凍してください。

Raspberry Pi で使用する SD カードを PCに挿入し、Win32DiskImager を起動します。

※SD カードはドライブとして認識されている必要があるので、事前に FAT32 形式でフォーマットしておいてください。

「Image File」に解凍したRaspbian のイメージファイル (YYYY-MM-DD-wheezy-raspbian.img)、「Drive」にSD カードのドライブを指定し、「Write」ボタンをクリックします。

win32diskimager.png
イメージデータの書き込み

以上で SD カードの準備は終了です。 書き込みが終了したら、SD カードを Raspberry Pi に設置し、電源を投入します。

イメージの書き込み (Linux)

Linux では dd コマンドを利用してイメージの読み書きができます。 dd コマンドは UNIX系の OS なら大抵デフォルトでインストールされています。

SDカードを差し込んでから、 dmesg コマンドでカーネルのメッセージを確認します。

 $ dmesg
   : 中略
 [333478.822170] sd 3:0:0:0: [sdb] Assuming drive cache: write through
 [333478.822174]  sdb: sdb1 sdb2
 [333478.839563] sd 3:0:0:0: [sdb] Assuming drive cache: write through
 [333478.839567] sd 3:0:0:0: [sdb] Attached SCSI removable disk
 [333479.094873] EXT4-fs (sdb2): mounted filesystem with ordered data mode
 [333527.658195] usb 1-1: USB disconnect, address 2

このメッセージから SDカードのデバイス名を確認します。この例では sdb が SDカードのデバイス名のようです。/dev/の下を見てみます。

 ls -al /dev/sd*
 brw-rw---- 1 root disk 8,  0 May  7 17:28 /dev/sda
 brw-rw---- 1 root disk 8,  1 May  7 17:28 /dev/sda1
 brw-rw---- 1 root disk 8,  2 May  7 17:28 /dev/sda2
 brw-rw---- 1 root disk 8,  5 May  7 17:28 /dev/sda5
 brw-rw---- 1 root disk 8, 16 May 18 14:19 /dev/sdb
 brw-rw---- 1 root disk 8, 17 May 18 14:19 /dev/sdb1
 brw-rw---- 1 root disk 8, 32 May 18 14:19 /dev/sdc

sda は大抵システムディスクなので、絶対に触ってはいけません。

ディストリビューションによっては、SDカード内にマウント可能なファイルシステムがある場合自動でマウントするケースもあるようです。 その場合、ディスクをアンマウントしてください。(Ubuntuではデスクトップにマウントしたファイルシステムのフォルダーが現れるので右クリックで取り外してください。 それ以外は umount コマンドでアンマウントします。)

ubuntu_adcard_mount.png
Ubuntu場でマウントされたSDカード(右クリックメニューで取り外すことができる)

dd if=イメージファイル of=SDカードのデバイスファイル bs=1M のようにコマンドを入力し実行します。 ただし、デバイスファイルへの書き込みは管理者(root)権限が必要ですので、sudoを使用してください。

 $ sudo dd if=2015-08-05-ev3dev-openrtm.img of=/dev/sdb bs=1M
 1850+0 records in
 1850+0 records out
 1939865600 bytes (1.9 GB) copied, 201.543 s, 9.6 MB/s

実行中は別のターミナルなどで、iostat コマンドを実行して書き込みが正しく行われているかどうか見ることができます。 (最近のディストリビューションではデフォルトでインストールされていないことがあります。debian/ubuntu では apt-get install sysstat で iostatコマンドが使えるようになります。)

 $ iostat -mx 1
  avg-cpu:  %user   %nice %system %iowait  %steal   %idle
            0.00    0.00    0.00   50.25    0.00   49.75
 
 Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
 sda               0.00     0.00    0.00    1.00     0.00     0.00     8.00     0.00    0.00   0.00   0.00
 sdb               0.00  1856.00    0.00   78.00     0.00     9.14   240.00   143.40 1855.85  12.82 100.00

sdb の項目を見ると 9.14MB/s の書き込み速度が出ていることがわかります。 class 6 のSDカードなら 6MB/sec, class 10 の SDカードなら 10MB/sec 程度の速度が出ていれば、問題なく書き込まれていると考えてよいでしょう。 書き込みが終了すると、ディストリビューションによっては自動でマウントされる場合があります。その場合、アンマウントしてから SDカードを抜いてください。

イメージの書き込み (Mac OS X)

Mac OS X も Linuxと同様 dd コマンドを利用して書き込みます。 ただし、Mac では SDカードを挿入すると自動的にマウントされてしまい、マウント中は dd コマンドで SDカードに書き込むことができないので、アンマウント (OSから取り外す) する必要があります。

SDカードを差し込むとFinderに図のように SDカードのアイコンが現れます。 アンマウントするつもりでイジェクトボタンを押さないよう気を付けてください。

sdcard_mac.png
MacにマウントされたSDカード

SDカードのボリューム名はここでは Untitled です。ボリューム名を覚えておきます。 コマンドプロンプトから df コマンドを入力すると以下のように表示されます。

 $ df -k
 Filesystem                        1024-blocks      Used Available Capacity   iused    ifree %iused  Mounted on
 /dev/disk0s2                        500000000 437664508  62079492    88% 109480125 15519873   88%   /
 devfs                                     194       194         0   100%       679        0  100%   /dev
 map -hosts                                  0         0         0   100%         0        0  100%   /net
 map auto_home                               0         0         0   100%         0        0  100%   /home
 /dev/disk1s1                            57288     18992     38296    34%       512        0  100%   /Volumes/Untitled

 一番下 ''/Volumes/Untitled'' とあるのが先ほどの SDカードのマウントポイントです。一番左の SDカードのデバイス名 /dev/disk1s1 を覚えておきます。
この SDカードを一旦アンマウント します。diskutil というコマンドを使用し diskutil umount <マウントポイント> のように入力します。

 $ diskutil umount /Volumes/Untitled
 Volume (null) on disk1s1 unmounted
 $ df -k
 Filesystem                        1024-blocks      Used Available Capacity   iused    ifree %iused  Mounted on
 /dev/disk0s2                        500000000 437664716  62079284    88% 109480177 15519821   88%   /
 devfs                                     194       194         0   100%       679        0  100%   /dev
 map -hosts                                  0         0         0   100%         0        0  100%   /net
 map auto_home                               0         0         0   100%         0        0  100%   /home

先ほどの /Volumes/Untitled が消えて、SDカードがアンマウントされていることがわかります。 次に dd コマンドを使用してイメージを書き込みます。 dd if=イメージファイル of=/dev/rdisk1 bs=1m のように入力します。 of=/dev/rdisk1 は先ほど覚えたデバイスファイル /dev/disk1s1 のうち後ろの s1 を取り、さらに disk の前に raw deviceであることを示す r を付けたデバイス名です。

このコマンドはデバイスファイルにアクセスするので管理者 (root) でなければ実行できません。sudoを使用して以下のように実行します。

 $ sudo dd if=2015-08-05-ev3dev-openrtm.img of=/dev/rdisk1 bs=1m
 1850+0 records in
 1850+0 records out
 1939865600 bytes transferred in 302.377337 secs (6415380 bytes/sec)
 $

書き込み中は、「アクティビティモニタ」で「ディスクの動作」を見ることで書き込みが正しく行われているかどうかわかります。 class 6 の SDカードなら 6MB/sec, class 10のSDカードなら 10MB/sec 程度の速度が出ていれば、問題なく書き込まれていると考えてよいでしょう。

書き込みが終了すると、自動的に再度マウントされますので、今度は Finder のイジェクトボタンを押して SDカードを抜きます。

EV3 および ev3dev の初期設定

電池・無線LAN・SDカードのセット

電池

EV3 は単3電池6本、または専用のバッテリーパックで動作します。単3電池6本、もしくは専用のバッテリーをセットしてください。

EV3_with_AAAbattery.png
単3電池

EV3_with_battery.png
EV3専用バッテリーパック

無線LAN

USB接続の無線LANインターフェースをを用意します。EV3 は PCと有線接続して、PC経由でインターネットに接続することもできますが、ここでは無線LAN接続を前提として説明します。

最近の無線LANドングルであれば、大抵のものが使用可能なはずですが、一例として以下の無線LANドングルは動作確認ができています。

  • BUFFALO WLI-UC-GNM2 Wireless LAN Adapter
  • BUFFALO WLI-UC-GN Wireless LAN Adapter
  • PLANEX GW-USMicro300
    wlan_dongle.png
    無線LANドングルの例

その他の接続方法に関しては、ev3dev の Webページをご覧ください。

SDカードの挿入

無線LANドングルと共に、EV3 のコントローラの側面に ev3dev イメージを書き込んだ SDカードを以下のように挿入してください。

ev3_wlan_sdcard.png
EV3の側面に、無線LANドングルと SDカードを挿入

ev3dev の起動

SDカードを挿入し、電源ボタン(十字キーボタンの中央の濃いグレーのボタン)を押して EV3 に電源を投入すると、以下のような起動画面が表示され、十字キーのあたりの LED が点滅します。

ev3dev_screen_booting.png
ev3dev 起動画面

暫く(1分前後)して起動が完了すると、以下のような初期画面が表示されます。

ev3dev_screen.png
起動直後の画面

ssh ログイン

ネットワークへの接続

起動直後の EV3 は、まだネットワークにつながっていません。 初期画面の状態から、十字キーで、Wireless and Networks を選択し、決定ボタン(中央の濃いグレーのボタン)を押します。

 ------------------------------
                       V [8.12>
 ------------------------------
  File Brower                >
  Device Browser             >
 [Wireless and Networks      > ]
  Battery                    >
  About                      >
 ------------------------------

選択すると、以下のような画面になります。

 
 ------------------------------
      Wireless and Network
 ------------------------------
        Status: Offline
 ------------------------------
 Bluetooth                    >
 USB                          >
 Wifi                         >
 All Network Connections      >
 Tethering                    >
 Offline Mode                □
 ------------------------------

WiFi を選択すると、以下の画面に遷移します。

 ------------------------------
           WiFi
 ------------------------------
 Powered                      □
 Start Scan
            Networks
 ------------------------------
 [* MyWirelessNetwork   ?? ]
 
 
 ------------------------------

Powered を選択し、電源をONにし、スキャンして現れた SSID のうち接続したい ID を選択します。

 ------------------------------
      MyWirelessNetwork
 ------------------------------
 Status:                 Online
 Signal                     83%
 Security        WPA/2 PSK, WPS
 IP Address:
 [    Connect   ]
 [      Network Connection     ]

Connect を選択し決定ボタンを押すと、KEYを入力するダイアログが現れます。再度、決定ボタンを押すと、以下のようなキーボードが現れるので、KEY を入力します。

 [_                           ]
 [ABC] [abc] [123] [!@# ] [INS]
 [Q][W][E][R][T][Y][U][I][O][P]
 [A][S][D][F][G][H][J][K][L][ ]
 [ ][Z][X][C][V][B][N][M][ ][ ]
 [ Accept ]          [ Cancel ]

KEY を入力後、Accept を選択し決定ボタンを押すと、先どのダイアログに KEY が入力された状態で表示されるので、再度 Accept を押します。 暫くすると、指定した無線LANアクセスポイントにつながるはずです。何度か戻るボタン(画面の左下のボタン)を押すと初期画面に戻ります。 左上に割り当てらえた IPアドレスが表示されているはずです。

 --------------------------
 192.168.11.3          V [8.12>
 --------------------------
  File Brower                >
  Device Browser             >
 [Wireless and Networks      > ]
  Battery                    >
  About                      >
 
  
 --------------------------

USBケーブルでの接続

無線LANが何らかの理由で使用できない場合は USBケーブルで接続することもできます。

EV3 と PCを付属の USBケーブルで接続してください。

/ja/node/6041

ev3dev の初期画面で Wireless and Networks を選択してください。 次に All Network Connections を選択します。

 ------------------------------
      Wireless and Network
 ------------------------------
        Status: Offline
 ------------------------------
 Bluetooth                    >
 Wifi                         >
 All Network Connections      > ]
 Tethering                    >
 Offline Mode                □
 ------------------------------

Wiredを選択します。

 ------------------------------
      All Network Connections
 ------------------------------
 Wired                        ψ ]
 ------------------------------

Connectを選択すると接続します。

 ------------------------------
             Wired
 ------------------------------
        Status: Offline
 ------------------------------
 Connect                        ]
 Connect automatically       □
 IPv4                         >
 DNS                          >
 ENET                         >
 ------------------------------

テザリングの設定

EV3 で USBテザリングの設定を行う手順を説明します。 まず ev3dev の初期画面で Wireless and Networks を選択してください。

次に Tehering を選択します。

 ------------------------------
      Wireless and Network
 ------------------------------
        Status: Offline
 ------------------------------
 Bluetooth                    >
 Wifi                         >
 All Network Connections      >
 Tethering                    > ]
 Offline Mode                □
 ------------------------------

Gadget をオンにすれば完了です。

 ------------------------------
           Tethering
 ------------------------------
 Bluetooth                   □
 Gadget                      ■
 Network Info                 >
 ------------------------------

ログイン

EV3 に割り当てられた IPアドレスに sshで接続します。デフォルトでは、ev3dev は以下の ID とパスワードが設定されています。

ID robot
Password maker

Windows では、TeraTerm などのターミナルソフトウェアを利用します。 Linux などでは、ターミナル画面から、

 $ ssh robot@<IPアドレス>

として、ログインします。ログインすると、以下のような画面が表示されるはずです。

              _____     _
    _____   _|___ /  __| | _____   __
   / _ \ \ / / |_ \ / _` |/ _ \ \ / /
  |  __/\ V / ___) | (_| |  __/\ V /
   \___| \_/ |____/ \__,_|\___| \_/
 
 Debian jessie on LEGO MINDSTORMS EV3!
 
 The programs included with the Debian GNU/Linux system are free software;
 the exact distribution terms for each program are described in the
 individual files in /usr/share/doc/*/copyright.
 
 Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
 permitted by applicable law.
 Last login: Tue Aug  4 01:34:12 2015 from openrtm.org
 root@ev3dev:~#

TeraTerm のインストール(参考)

Windows から EV3 に ssh 経由でログインするためには、ssh クライアントをインストールする必要があります。 Windows で利用可能なクライアントは多数ありますが、ここでは Tera Term を紹介します。

こちらから、TeraTerm をダウンロード、インストールしてください。

teraterm_connect.png
TeraTerm による接続

TeraTerm をインストール後、起動すると接続ダイアログが現れるので、先ほど設定したホスト名+.local を「ホスト」のテキストボックスに入力しOKを押します。

設定

無線LANの設定

上記で行ったEV3 の無線LAN設定は、再起動すると消えてしまいます。起動後に自動で無線LAN に接続するためには、EV3 にログインして無線LANの接続設定を行う必要があります。

/etc/wpa_supplicant/wpa_supplicant.conf の編集

次に、無線LAN の ESSID とキーを登録します。

 # cd /etc/wpa_supplicant
 # wpa_passphrase ESSID pass >> wpa_supplicant.conf

SSID には無線LANの ESSID、pass には無線LANのキーを入力します。リダイレクトの際、> ではなく >> (追記)を使用するよう注意してください。 結果は以下のようになっていると思います。

 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
 update_config=1
 network={
         ssid="OpenRTM"
         #psk="4332221111"
         psk=142914b76be167767055ff945898baaaf83c42b3ad3b99afb0ae531e8fb15e5e
 }

通常は、これだけで接続できるはずです。ただし、無線LANアクセスポイントの設定によっては、追加の設定が必要になるかもしれません。 以下に、一例を示します。

 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
 update_config=1
 network={
         ssid="OpenRTM"
         proto=WPA2
         key_mgmt=WPA-PSK
         pairwise=TKIP CCMP
         group=TKIP CCMP
         #psk="4332221111"
         psk=142914b76be167767055ff945898baaaf83c42b3ad3b99afb0ae531e8fb15e5e
 }

最後に、インターフェースを初期化します。

 # ifdown wlan0 ; ifup wlan0
 Internet Systems Consortium DHCP Client 4.2.2
 Copyright 2004-2011 Internet Systems Consortium.
 All rights reserved.
 For info, please visit https://www.isc.org/software/dhcp/
  : 中略
 DHCPREQUEST on wlan0 to 255.255.255.255 port 67
 DHCPOFFER from 192.168.11.1
 DHCPACK from 192.168.11.1
 bound to 192.168.11.26 -- renewal in 34810 seconds.

実際には、いったん無線LANインターフェースがOFFになるので、このような表示は見えません。また、場合によっては、ssh 接続が切断される可能性があるので、その場合は、再度接続してみてください。

最後に、設定が正しく行われているか確認するため、再起動してみます。

 # reboot

EV3 がシャットダウンされ、再び起動画面が表示されます。しばらくすると、初期画面が表示され、設定が正しく行われていれば、画面の左上に IPアドレスが表示されるはずです。

ホスト名でリモート接続する

EV3 に ssh でリモートログインで操作する場合、上記のように無線LAN接続後、画面左上に表示される IPアドレスにssh接続することができます。 IPアドレスは DHCP で割り当てられているので、接続の度に代わる可能性があり、そのたびに異なる IPアドレスで接続しなければならないので不便です。

ev3dev には avahi という Bonjour互換のサービスがインストールしてあります。 Bonjour は Apple が提唱するネットワーク上のサービスを自動的に検索して利用できるようにするためのサービスです。 avahiを使うと、DHCP で IPアドレスを割り振っている EV3 に対してもホスト名でアクセスすることができるようになります。

ホスト名の設定

ev3dev ではデフォルトで ev3dev というホスト名が設定してあります。他の avahi や Bonjour がインストールしてあるマシンからは、ev3dev.local という .local がついたホスト名でアクセスできます。

EV3 が複数台ネットワーク上にある場合には、他のホスト名と衝突しないホスト名を選び設定する必要があります。

 $ sudo vi /etc/hostname

/etc/hostname の1行目にホスト名を記載します。デフォルトでは ev3dev となっていますので、好みの名前に設定してください。 。

avahi-daemon のインストール

Linux ホストから EV3 へアクセスする場合、avahiというサービスをインストールする必要があります。 最近のLinuxディストリビューションでは、たいていデフォルトでこのサービスがインストールされていますが、もしインストールされていない場合は、以下のように avahi デーモンをインストールします。(debian系のディストリビューションの場合)

 $ sudo apt-get update
 $ sudo apt-get install avahi-daemon

EV に対して ping を打ってみます。ホスト名の後に .local を付けた名前を使います。

 $ ping ev3dev.local

これで ping が返ってくれば、avahi がほぼ正しく設定されていることになります。

Bonjour のインストール (Windowsのみ)

PC から EV3 にアクセスするためには、PC側にも avahi か Bonjour がインストールされている必要があります。

Windows ではデフォルトでは Bonjour はインストールされていません。 最も簡単に Bonjour を導入する方法は iTunes をインストールすることです。

どうしても iTunes をインストールしたくない場合は、アーカイバアプリケーションなどで、ダウンロードした iTunesSetup.exe を展開すると BonjourSetup.exe を抽出することもできます。

また、以下の Apple Bonjour 印刷サービスにも Bonjour が同梱されています。(iTunesに同梱されているものよりバージョンが若干古いようです。)

現在 Applie では Bonjour for Windows 単体としては配布は行なっていませんが、かつて配布していたものを再配布しているサイトも幾つかあります。(ただし、古いバージョンしか入手できないようです。) 以下は Appleサイト以外の Bonjourダウンロードサイトです。自己責任でご利用ください。

Bonjour がうまく機能しない場合

ファイヤウォールが動作している場合、Bonjour がうまく機能しないことがあります。 その場合、UDPポート5353を開放するかファイヤウォールをOFFにしてください。

サンプルコンポーネントの実行

OpenRTM-aistのインストール

上述のリンクから ev3dev のイメージで EV3 を起動した場合、すでに OpenRTM-aist (C++、Python版) がインストールされています。 その場合は、以下の OpenRTM-aist のインストールはスキップして、サンプルコンポーネントの実行から進めてください。

自分で ev3dev.org からイメージをダウンロードした場合は、OpenRTM-aist のパッケージを apt-get 等でインストールします。

sources.list の編集

openrtm.org をパッケージリポジトリとして追加するために、/etc/sources.list を編集します。

 # vi /etc/apt/sources.list

のように、vi で /etc/apt/sources.list を開き、

 deb http://ftp.debian.org/debian jessie main contrib non-free
 deb http://ev3dev.org/debian jessie main
 deb http://openrtm.org/pub/Linux/debian jessie main ← この行を追加

この例のように、最下行に openrtm.org のリポジトリを追加します。

その後、

 # apt-get update
として、パッケージリポジトリのデーターベースを更新します。 EV3は遅いので、パッケージデータベースの更新もかなり時間がかかります。

OpenRTM-aist パッケージのインストール

以上で、openrtm.org のパッケージリポジトリにアクセスできるようになりましたので、以下のようにしてパッケージをインストールします。

 # apt-get install libomniorb4-dev omniidl
 # apt-get install openrtm-aist openrtm-aist-dev openrtm-aist-example python-yaml
 # apt-get install gcc g++ make uuid-dev
 # apt-get install python-omniorb
 # apt-get install openrtm-aist-python openrtm-aist-python-example

パッケージのインストールにもかなりの時間がかかりますので気長に待ちます。途中でバッテリーが切れないように、アダプタに接続したまま作業することをお勧めします。

OpenRTM-aistのサンプルの実行

ConsoleIn-ConsoleOut (C++)

C++のサンプルコンポーネントを動作させて、OpenRTM-aistが正しくインストールできているかどうかを確認します。

EV3上で ConsoleIn を実行したうえで、PC上で ConsoleOut を実行して相互に接続し、PCから入力した数字が EV3上で表示できるかどうかを確認してみます。

ConsoleIn の起動

まず、EV3上で、ネームサービスと ConsoleIn を起動します。 omniorb-nameserver というパッケージがインストールされているはずですので、すでにシステムのサービスとして起動していますが、ネットワークがらみのトラブルを避けるためにも、rtm-naming というコマンドで起動させた方が良いでしょう。

Windows などでは TeraTerm などのターミナルソフトウェア、Linux ではコンソールから EV3 に ssh でログインします。

ログインしたら、まず rtm-naming を起動します。途中で既存のネームサーバを落とすかどうか聞いてきますので y と答えて進みます。

              _____     _
    _____   _|___ /  __| | _____   __
   / _ \ \ / / |_ \ / _` |/ _ \ \ / /
  |  __/\ V / ___) | (_| |  __/\ V /
   \___| \_/ |____/ \__,_|\___| \_/
 
 Debian jessie on LEGO MINDSTORMS EV3!
 :中略
 # rtm-naming
 Starting omniORB omniNames: ev3dev:2809
 omniORB: Failed to bind to address 0.0.0.0 port 2809. Address in use?
 omniORB: Error: Unable to create an endpoint of this description: giop:tcp::2809
 :中略
 and start omniNames by rtm-naming? (y/N)y ← yを入力
 Stopping omniNames by /etc/init.d/omniorb4-nameserver.
 [ ok ] Stopping omniorb4-nameserver (via systemctl): omniorb4-nameserver.servic.
 Starting omniORB omniNames: ev3dev:2809
 
 Wed Aug  5 11:04:01 2015:
 
 Starting omniNames for the first time.
 Wrote initial log file.
 Read log file successfully.
 Root context is IOR:010000002b00000049444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f6e746578744578743a312e30000001000000000000007400000001010200100000003139322e3136382e3132382e31303400f90a00000b0000004e616d6553657276696365000300000000000000080000000100000000545441010000001c000000010000000100010001000000010001050901010001000000090101000354544108000000a1edc1550100028f
 Checkpointing Phase 1: Prepare.
 Checkpointing Phase 2: Commit.
 Checkpointing completed.
 omniNames properly started
 root@ev3dev:~#

次に、ConsoleInComp を起動します。

 root@ev3dev:~# /usr/share/openrtm-1.1/example/ConsoleInComp
 Creating a component: "ConsoleIn"....succeed.
 =================================================
  Component Profile
 -------------------------------------------------
 InstanceID:     ConsoleIn0
 :中略
 port.outport.dataport:
 =================================================
 =================================================
 Port0 (name): ConsoleIn0.out
 -------------------------------------------------
 - properties -
 port.port_type: DataOutPort
 dataport.data_type: IDL:RTC/TimedLong:1.0
 dataport.subscription_type: flush,new,periodic
 dataport.dataflow_type: push,pull
 dataport.interface_type: corba_cdr
 -------------------------------------------------
 
ConsoleIn_cxx.png
EV3上で実行されたConsoleInComp

ConsoleOut の起動

PC上で ConsoleOut を起動します。Windowsであれば、ネームサーバ、RTSystemEditor、ConsoleIn をそれぞれ以下のように起動します。

  • ネームサーバの起動
    • 「スタート」>「OpenRTM-aist x.y」>「Tools」>「Start C++ Naming Service」
  • RTSystemEditorの起動
    • 「スタート」>「OpenRTM-aist x.y」>「Tools」>「RTSystemEditor」
  • ConsoleInの起動
    • 「スタート」>「OpenRTM-aist x.y」>「C++」>「Components」>「Examples」>「ConsoleOutComp.exe」

Linux であれば、ネームサービス、eclipse、ConsoleInComp を以下のように起動します。

 $ rtm-naming
 $ <eclipseの起動> &
 $ /usr/share/openrtm-1.1/example/ConsoleOutComp
 :中略
 naming.names: ubuntu1404.host_cxt/ConsoleOut0.rtc
 config_file:
 port.inport.dataport:
 port.inport.in:
 =================================================
 =================================================
 Port0 (name): ConsoleOut0.in
 -------------------------------------------------
 - properties -
 port.port_type: DataInPort
 dataport.data_type: IDL:RTC/TimedLong:1.0
 dataport.subscription_type: Any
 dataport.dataflow_type: push,pull
 dataport.interface_type: corba_cdr
 -------------------------------------------------

OpenRTP (eclipse) または、RTSystemEditotr (RPC版) から、EV3 で起動したネームサーバと PC で起動したネームサーバーにそれぞれ接続します。

それぞれのネームサーバに ConsoleIn (EV3のネームサーバー) と ConsoleOut (PC側のネームサーバー) が現れるはずので、それぞれエディタにドラッグアンドドロップして、InPort と OutPort を接続、Activate します。

ConsoleInOut_rtse01.png
RTSystemEditor上でConsoleInとConsoleOutを接続

ConsoleIn の方から数値を入力し、ConsoleOut の方で表示されれば、テストは成功です。

ConsoleIn-ConsoleOut (Python)

今度は、上記とは逆に、ConsoleIn を PC で、ConsoleOut を EV3 上で実行し接続してみます。

PC上では、以下のように ConsoleOut を起動します。。

  • ConsoleOutの起動
    • 「スタート」>「OpenRTM-aist x.y」>「Python」>「Components」>「Examples」>「ConsoleOutComp.exe」
      ConsoleIn_py.png
      PC上で実行した ConsoleIn (Python版)

次に、EV3上で、以下のように ConsoleOut.py を起動します。

 # python /usr/share/openrtm-1.1/example/python/SimpleIO/ConsoleOut.py
 ------------------------------
 Listener:        ON_CONNECT
 Profile::name:   ConsoleIn0.out_ConsoleOut0.in
 Profile::id:     246bf2c0-3b68-11e5-91a9-005056c00008
 ------------------------------
ConsoleOut_py.png
EV3 で実行した ConsoleOut (Python版)

RTSystemEditor上で、ConsoleIn と ConsoleOut を接続し、Activate します。 ConsoleIn側で数値を入力し、ConsoleOut側で表示されれば、テストは成功です。

ConsoleInOutpy_rtse01.png
RTSystemEditor上で ConsoleIn と ConsoleOut を接続

その他の組み合わせとして、C++ と Python のコンポーネントを起動して接続してみる、他のサンプルコンポーネントを起動して通信させてみるなど試してみてください。

開発環境の構築

EV3 および ev3dev 上で動作するコンポーネントを開発するには、EV3上で開発する方法と、クロス開発環境で開発する方法があります。

ただし、EV3 はメモリが64MB、CPUクロックが300MHz程度と、今どきの開発環境としてはだいぶ遅いマシンですので、EV3上での開発はかなり大変です。

クロス開発というのは、異なるアーキテクチャ、つまり一般的な PCのアーキテクチャである Intel 系の CPU上で、ARM などの異なる種類で動作する実行ファイルを作成することです。

クロス開発では、コンパイル即実行という形はとれませんが、コンパイル時間が圧倒的に速いので、結果として開発効率は高くなります。

Ubuntu のインストール

開発環境は Linux のディストリビューションの1つである Ubuntu (14.04 LTS) を使用します。

こちらの URL から ISOイメージをダウンロードして OS をインストールしてください。

PC のそのままインストールして使用することもできますし、バーチャルマシンとしてインストールして使用しても構いません。

バーチャルマシン環境としては、主に以下のようなものがあります。

これらの詳細な使用方法については、それぞれの Webサイトもしくは、解説の Webページを検索してみてください。

brickstrap

ここからは、Ubuntu14.04 がインストールされたものとして、話を進めます。 まず、brickstrap というツールをインストールします。brickstrap は上述の ev3dev の OSイメージを作成するためのツールですが、クロス開発を行うためのツールとしても利用可能です。

brickstrap のインストール

brickstap は下記の github 上で開発が行われています。

まずは、brickstrap をインストールします。通常の debian リポジトリには存在しないコマンドですので、パッケージリポジトリに ev3dev.org を追加しています。

 $ sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 2B210565
 $ sudo apt-add-repository "deb http://archive.ev3dev.org/ubuntu trusty main"
 $ sudo apt-get update
 $ sudo apt-get install brickstrap

イメージ作成のための準備

まずは supermin appliance を作成するために以下のコマンドを実行します。

 $ sudo update-guestfs-appliance
 $ sudo usermod -a -G kvm <username>
 $ sudo chmod +r /boot/vmlinuz*

開発環境の作成

ここまでできたら、いよいよ開発環境を作成します。特定のディレクトリーに、EV3 に搭載するシステムのファイルシステムを模擬したものを作成します。 場所としては、自分のホームディレクトリー以下の適当な場所が良いでしょう。ここでは、ホームディレクトリー以下の work ディレクトリーに作成します。

 $ cd ~
 $ mkdir work
 $ cd work

以下のコマンドでファイルシステムの作成~イメージの作成を行います。

 $ brickstrap -b ev3-ev3dev-jessie -d ev3-ev3dev-work all

このコマンドの実行には10分から20分かかります。 実際に行われていることは、ev3dev の Linux システムに必要なコマンド群、パッケージなどを仮想的な root ディレクトリー ev3-ev3dev-work 以下にインストールし、それを SDカードに書き込み可能なイメージファイルとして構成する作業です。

終了後には、ev3-ev3dev-work.tar と ev3-ev3dev-work.img というファイルシステムのアーカイブとイメージファイルが作成されているはずです。 この .img ファイルを SDカードに書き込むと EV3 で ev3dev を起動できます。

proot を入れ替える

ubuntu14.04 x86_64 では、brickstrap 内部で使われている proot のバージョンが古く、一部のユーザーIDやグループIDを扱う関数が実行できないため、apt-get でエラーが発生します。 これを避けるために、バージョン4.0以降の proot を使用します。

ここから、x86_64用バイナリをダウンロードし、当該マシンにコピーします。

 $ wget http://portable.proot.me/proot-x86_64
 $ sudo mv /usr/bin/proot /usr/bin/proot_3.0.2
 & sudo mv proot /usr/bin/
 $ chmod 755 /usr/bin/proot

シェルを起動する

以上で、クロス開発環境ができましたので、OpenRTM-aist をコンパイル・インストールして、さらに RTコンポーネントを開発します。 brickstrap を利用すると、あたかも EV3 上でパッケージのインストールやソースコードのコンパイルをしているように振る舞うモードを利用することができます。

以下のコマンドを入力します。

user@host:~/work$ brickstrap -b ev3-ev3dev-jessie -d ev3-ev3dev-work shell

すると、コマンドプロンプトが # となり、上述のモードとなります。

OpenRTM-aist のコンパイル

OpenRTM を自分でコンパイル・インストールする場合には、以下の手順に従ってください。ビルド済みのパッケージを利用する場合は、次の章へ移動してください。

まず、OpenRTM-aist をコンパイルします。OpenRTM-aist のビルドに必要なパッケージをインストールします。

 # apt-get update
 # apt-get install libomniorb4-dev omniidl
 # apt-get install gcc g++ make uuid-dev libboost-filesystem-dev
 # apt-get install doxygen
 # apt-get install build-essential debhelper devscripts
 # apt-get install subversion texlive texlive-lang-cjk xdvik-ja python-yaml
 # apt-get install wget

次に、OpenRTM-aist のソースコードをダウンロードします。

 # cd /home
 # wget http://tmp.openrtm.org/pub/OpenRTM-aist/cxx/x.y.z/OpenRTM-aist-x.y.z.tar.gz
 # tar xvzf OpenRTM-aist-x.y.z.tar.gz
 # cd OpenRTM-aist
 # ./configure --prefix=/usr
 # cd packages
 # make

これで、packages の下に OpenRTM-aist のパッケージが生成されます。 その後は、

 # dpkg -i openrtm-aist-*

のようにして、パッケージをインストールしてください。 OpenRTM-aist-Python についても同様にソースコードをダウンロードして、コンパイル(正確には、パッケージ作成)します。

 # wget http://tmp.openrtm.org/pub/OpenRTM-aist/python/x.y.z/OpenRTM-aist-Python-x.y.z-RELEASE.zip
 # cd OpenRTM-aist-Python
 # cd packages
 # make

C++版同様に package ディレクトリー以下に作成されたパッケージが作成されます。 インストールは、

 # dpkg -i openrtm-aist-python-*

のように行います。

OpenRTM-aist のインストール

上述のように、OpenRTM-aist を自分でソースからインストールせずに、事前にコンパイル済みのパッケージをインストールしても構いません。 ev3dev に OpenRTM-aist をインストールする方法について述べた、上述の方法とほぼ同様です。

sources.list の編集

openrtm.org をパッケージリポジトリとして追加するために、/etc/sources.list を編集します。

 # vi /etc/apt/sources.list

のように、vi で /etc/apt/sources.list を開き、

 deb http://ftp.debian.org/debian jessie main contrib non-free
 deb http://ev3dev.org/debian jessie main
 deb http://openrtm.org/pub/Linux/debian jessie main ← この行を追加

この例のように、最下行に openrtm.org のリポジトリを追加します。

その後、

 # apt-get update
として、パッケージリポジトリのデーターベースを更新します。 EV3 は遅いので、パッケージデータベースの更新もかなり時間がかかります。

OpenRTM-aist パッケージのインストール

以上で、openrtm.org のパッケージリポジトリにアクセスできるようになりましたので、以下のようにしてパッケージをインストールします。

 # apt-get install openrtm-aist openrtm-aist-dev openrtm-aist-example
 # apt-get install openrtm-aist-python openrtm-aist-python-example

EV3 デバイスの利用

LEGO Mindstorms のセンサーとモーター

LEGO Mindstorms EV3 には標準で、以下のようなモーター・センサーが付属しています。

  • ジャイロセンサー x1
  • カラーセンサー x1
  • タッチセンサー x2
  • 超音波距離センサー x1
  • モーター(L)x2
  • モーター(M)x1

センサー類は、プッシュスイッチは ON/OFF 値を取得可能で、超音波センサー、ジャイロセンサーは連続値を出力可能、カラーセンサーはいくつかの色を認識することもできます。 モーターは2種類(L、M)あり、それぞれ PWM(トルク)制御、速度制御、位置制御が可能で、これらの制御のゲイン等も変更できます。 以下に、EV3 のセンサーとモーターの使用を表示します。

ジャイロセンサー
45505_GyroSensor.jpg
確度モード: 精度 +/- 3°
角速度モード: 最大 440 deg/sec
サンプリングレート 1,000 Hz
カラーセンサー
45506_color.jpg
計測: 赤色光の反射光、周囲の明るさ、色
検出カラー数: 8色 (無色、黒、青、緑、黄、赤、白、茶)
サンプリングレート 1,000 Hz
距離 約1mm~18mm(アフレル調査値)
タッチセンサー
45507_TouchSensor.jpg
オン (1)、オフ (0)
スイッチ可動域: 約4mm
超音波センサー
45504_UltrasonicSensor.jpg
距離計測可能範囲: 3cmから250cm
距離計測精度: +/- 1 cm
前面電飾: 点灯:超音波発信中、点滅:超音波観測中
EV3 Lモーター
45502_LargeMotor.jpg
フィードバック: 1°単位
回転数: 160から170RPM
定格トルク: 0.21 N・m (30oz*in)
停動トルク: 0.42 N・m (60oz*in)
重さ: 76 g
EV3 Mモーター
45503_MediumMotor.jpg
フィードバック 1°単位
回転数: 240から250RPM
定格トルク: 0.08 N・m (11oz*in)
停動トルク: 0.12 N・m (17oz*in)
重さ: 36 g

sysfs 経由でのアクセス

ev3dev からこれらのデバイスにアクセスするには、sysfs という仕組みを経由してアクセスします。 sysfs は /sys 以下にある疑似的なファイルシステムで、ここに存在するファイルに値を書き込んだり読み込んだりすることで、モーターの制御やセンサーデータへのアクセスが可能になります。

sysfs 経由でのデバイスのアクセス方法に関しては、以下の ev3dev のドキュメントに詳細が記載されています。

具体的には、以下のようにアクセスします。

モーターの制御例

モーターを連続回転するには、ポートAにモーター(L/Mどちらでもよい)をコマンドラインから以下のように入力します。

 # echo 50 > /sys/class/tacho-motor/motor0/duty_cycle_sp
 # echo run-forever > /sys/class/tacho-motor/motor0/command

現在の位置を表示させるにはこのように入力します。止めるには Ctrl+C

 # while true; do echo -en "\033[0G$(cat /sys/class/tacho-motor/motor0/speed)   "; done
回転を止めるには、以下のように入力します。

 # echo stop > /sys/class/tacho-motor/motor0/command

センサーの例

センサーなども同様のアクセス法で利用できます。 カラーセンサーをポート1に接続します。カラーセンサーの先1cm位のところに赤いものを置いてください。 以下のようなコマンドを入力すると、5と表示されます。

 # echo "COL-COLOR" > /sys/class/lego-sensor/sensor1/mode
 # cat /sys/class/lego-sensor/sensor1/value1
 5

カラーセンサーには、いくつかのモードがあり、上ではカラー検出モードを使用しました。このモードでは、以下の8つの色 (ただし、0は何もないことを意味する) を認識します。

番号 0 1 2 3 4 5 6 7

コマンドラインからは以上のようにアクセスできますが、プログラムからこれらの操作をしようとすると非常に面倒な手続きが必要になります。

プログラムからデバイスにアクセスためのアクセスライブラリがありますので、これを利用します。

python-ev3dev の利用

ev3dev-lang を利用した EV3 デバイスへのアクセス

ev3dev-lang は EV3 のモーターやセンサーにアクセスするためのライブラリです。以下の4つの言語で利用することができます。

  • C++
  • Python
  • JavaScript
  • Lua

ここでは、Python と C++ でのアクセス例を示します。

python-ev3dev のインストール

ev3dev-lang の Python版 (Pythonバインディング) を (クロス開発環境ではなく) EV3 にインストールします。 以下のコマンドを入力すると、python-ev3dev がシステムにインストールされ、Python から利用できるようになります。

 # cd ~
 # mkdir work
 # d work
 # apt-get install libboost-python1.55.0 python-setuptools python-pil
 # wget https://github.com/rhempel/ev3dev-lang-python/archive/0.6.0.zip
 # unzip 0.6.0.zip
 # cd ev3dev-lang-python-0.6.0/
 # python setup.py install

python-ev3dev からのデバイスアクセス

python-ev3dev を使ってモーターを回してみます。まず、適当なディレクトリーに移動し(先ほどの python-ev3dev をインストールする時のディレクトリーで実行するとエラーになります) python をインタラクティブモードで起動します。

 # cd 
 # python
 Python 2.7.9 (default, Mar  1 2015, 13:52:09)
 [GCC 4.9.2] on linux2
 Type "help", "copyright", "credits" or "license" for more information.
 >>> import ev3dev.ev3 as ev3     (ev3dev モジュールをインポートする)
 >>> m = ev3.LargeMotor() (モーターオブジェクトをインスタンス化)
 >>> m.connected (接続しているかを確認)
 True
 >>> m.run_forever(duty_cycle_sp=50) (デューティー比50%でモータを連続回転)
 >>> m.stop() (モーターを停止)

モーターの停止モードには、'break'、'coast'、'hold' の3種類があります。デフォルトは 'coast' に設定してあり、m.stop() 実行時も、惰性で若干動いたと思います。これを、'hold' にして、stop 実行時にピタッと止めます。

 >>> m.set_attr_string(None, "stop_command", ev3.Motor.STOP_COMMAND_HOLD)
 >>> m.get_attr_string(None, "stop_command")[1]
 >>> m.run_forever(duty_cycle_sp=50)
 >>> m.stop()

以上のように、Python からモータを比較的容易に制御出来ます。

次にセンサーを利用してみます。ポート2に超音波センサーをつなぎます。引き続き Python のインタラクティブモードから以下のように入力します。 for 文で100秒間センサの値(mm)を表示し続けます。途中でやめたいときは Ctrl+C を押してループを抜けます。

 >>> s = ev3.UltrasonicSensor()
 >>> s.distance_centimeters()
 118
 >>> import time
 >>> for i in range(0,100):
 ...     print s.distance_centimeters()
 ...     time.sleep(1)
 ..
 118
 114
 :中略
 2382
 2366
 326
 76
 ^CTraceback (most recent call last):
   File "<stdin>", line 3, in <module>
 KeyboardInterrupt
 >>>

python-ev3dev を知る

python-ev3dev の様々なクラス・関数のチュートリアル、リファレンスマニュアルは以下のページにあります。

また、Python では、モジュールやオブジェクトに対して dir() 関数を呼ぶと、利用可能な変数や関数のリストを見ることができます(変数か関数かの区別は dir() だけではわかりません)。

 >>> dir(ev3)
 ['Button', 'ButtonBase', 'ButtonEVIO', 'ColorSensor', 'DcMotor', 'Device', 'FbMem', 
 'FirgelliL12100Motor', 'FirgelliL1250Motor', 'GyroSensor', 'I2cSensor', 'INPUT_1', 'INPUT_2', 
 'INPUT_3', 'INPUT_4', 'INPUT_AUTO', 'Image', 'ImageDraw', 'InfraredSensor', 'LargeMotor', 
 'Led', 'Leds', 'LegoPort', 'LightSensor', 'MediumMotor', 'Motor', 'NxtMotor', 'OUTPUT_A', 
 'OUTPUT_AUTO', 'OUTPUT_B', 'OUTPUT_C', 'OUTPUT_D', 'Popen', 'PowerSupply', 'RemoteControl', 
 'Screen', 'Sensor', 'ServoMotor', 'Sound', 'SoundSensor', 'TouchSensor', 'UltrasonicSensor', 
 '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', 'abspath', 
 'array', 'ctypes', 'fcntl', 'fnmatch', 'list_device_names', 'list_devices', 'list_motors', 
 'mmap', 'numbers', 'os', 'pack', 're', 'stat', 'unpack']
 >>>

たとえば、ev3dev.ev3 モジュールには Sound という変数か関数があります。 run_forever() という関数があり、Sound() 関数を呼んでインスタンスを生成してみます。以下の例でわかるように、引数は不要だったようです。

 >>> s = ev3.Sound()
 >>> dir(s)
 ['__doc__', '__module__', 'beep', 'play', 'speak', 'tone']

生成したオブジェクト s に対して dir(s) を実行してみます。すると、このオブジェクトで呼び出し可能そうな関数群が分かります。 試しに、speak を呼び出してみます。

 >>> s.speak("Hello RT-Middleware World")

EV3 から声が出るはずです。 実際には、関数の引数に何が必要なのか、どのようなデータ型を渡す必要があるのか、など詳細を知らないと呼び出せない関数もありますが、この方法でおおよその使い方を把握することができます。詳しい関数の呼び出し方を知りたい場合には、リファレンスマニュアルを参照してください。

ev3dev C++ バインディングの利用

ev3dev-lang の利用

ev3dev-lang には C++ や Python、Lua などの EV3 デバイスへのバインディングライブラリが含まれています。 以下では、C++ から利用できる、ev3dev バインディングの導入と使い方について説明します。

ev3dev-lang の取得

以下の作業は、クロス開発環境にて行います。既に、上述の方法でクロス開発環境が導入済みであるとして進めます。

まず、github から ev3dev-lang をクローニングします。クローニング先は、クロス開発環境内の適当な場所 (ここでは /home/openrtm/work の下) にします。

 $ cd ev3-ev3dev-work/home/
 $ mkdir -p openrtm/work
 $ cd openrtm/work
 $ git clone https://github.com/ddemidov/ev3dev-lang-cpp
 Cloning into 'ev3dev-lang-cpp'...
 remote: Counting objects: 1733, done.
 remote: Total 1733 (delta 0), reused 0 (delta 0), pack-reused 1733
 Receiving objects: 100% (1733/1733), 510.41 KiB | 310.00 KiB/s, done.
 Resolving deltas: 100% (1150/1150), done.
 Checking connectivity... done.
 $ ls
 ev3dev-lang-cpp
 $ cd  ev3dev-lang-cpp
 $ git checkout c0829011bf668bb77e55049a7f2f396b0b452f41

ev3dev-lang のビルド

次に、コンパイルを行います。まず、作業ディレクトリー work に入り、brickstrap のクロス開発モードに入ります。

 $ cd ~/work
 $ brickstrap -b ev3-ev3dev-jessie -d ev3-ev3dev-work shell

先ほど github からクローニングしたディレクトリに移動し、make します。

 # cd /home/openrtm/work/ev3dev-lang-cpp/
 # mkdir build
 # cd build
 # cmake .. -DEV3DEV_PLATFORM=EV3
 # make

コンパイルが終了すると build の下にスタティックリンクライブラリ (libev3dev.a)、demos の下にはいくつかのサンプルアプリケーションが生成されます。

サンプルプログラム

サンプルプログラムの内容は以下の通りです。 標準セットの構成で使用できる産プロプログラムは、button-test、ev3dev-lang-demo、ev3dev-lang-test で drive-test、remote_control-test には IRセンサーと IRビーコンが必要になります。

button-test EV3 インテリジェントブロック(本体)のボタン(十字、中央、キャンセル)の ON/OFF を表示するサンプル。
drive-test モード1: IRセンサーを距離センサーとして利用し、障害物がなければ直進、障害物があればターンする自動動作を繰り返す。モード2: IRビーコンを用いた赤外線による遠隔操作モード。(標準セットにはIRセンサー、IRビーコンが付属していません。)
ev3dev-lang-demo メニュー形式で、センサー、モーター、LED、ボタン、サウンド、バッテリー、LCD等のデバイスの様々な機能にアクセスできるでもプログラム。
ev3dev-lang-test libev3dev のテスト用プログラム。センサー、モーター、LEDなどの機能を一通りアクセスし、libev3dev の機能をテストするプログラム。
remote_control-test IRセンサーと IRビーコンを用いたリモートコントロールのでもプログラム。

サンプルロプログラムの EV3 へのコピー

実際に EV3 で動作させるために、サンプルプログラムを EV3 にコピーします。EV3 で ev3dev が起動してネットワークにつながっていることを確認してください。クロス開発環境側から以下のようにしてコピーします。

 # cd demos ← ev3dev-lang-cpp/demos に移動
 # scp * ev3dev.local:/tmp/ ← ファイルを ev3.local (EV3) の /tmp/ にコピー

サンプルプログラムの実行

そのままターミナルから ev3dev.local にログインしてサンプルプログラムを実行します。

 # ssh ev3dev.local
 login: root
 password: r00tme
 # cd /tmp
 # ./ev3dev-lang-demo
 *** main menu ***
 
 (s)ensors
 (m)otors
 (l)eds
 (b)uttons
 s(o)und
 b(a)ttery
 l(c)d
 (q)uit
 
 Choice: 

自作のプログラムのビルド

自作のプログラムをビルドする際は ev3dev.h のインクルードと libev3dev.a とのリンクする必要があります。 以下は CMakeLists.txt の一例です。

 cmake_minimum_required(VERSION 2.8)
 
 set(ev3dev_dir /home/ev3dev-lang-cpp)
 set(ev3dev_lib ${ev3dev_dir}/build/libev3dev.a)
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
 
 project( testEV3 )
 add_executable(testEV3 main.cpp)
 include_directories(${ev3dev_dir})
 target_link_libraries(testEV3 ${ev3dev_lib} pthread)

EV3用RTCの作成 (Python編)

移動ロボットの組み立て

EV3 の標準セットを購入すると、移動ロボット (Educator Vehicle) の作成方法のマニュアルが1冊ついてくるはずです。 なければ、以下の URL からダウンロードすることができます。この移動ロボットを例にとり、移動ロボットRTC を作成してみます。

まずは、このマニュアルに従って、移動ロボット (Educator Vehicle) を組み立てます。

それぞれのモーター、センサーはそれぞれ以下のように取り付けます。

モーター右 ポート C
モーター左 ポート B
モーター(M) ポートA
タッチセンサー右 ポート 3
タッチセンサー左 ポート 1
超音波センサー ポート 4
ジャイロセンサー ポート 2

移動ロボットの運動学

さて、上記のコンポーネントは指令値として2次元速度指令を受け取りますが、実際にモータを制御する際には、モーターの角速度指令値を計算しモーターに命令しなければなりません。

移動ロボットの運動学については、東北学院大学の熊谷先生のページが参考になります。

座標系としては、自律移動機能共通インターフェース仕様書に従って、

ロボット進行方向をX軸とした右手系を想定する。速度指令は座標系にならって、(v_x、v_y、v_a)とする。独立二輪駆動式の移動ロボットなので、v_y は常に0となり、実質的に v_x および v_a を指定することになる。

さて、車輪の角速度を math16.png , math17.png として、車輪の半径を r とすると、各車輪の接地点での速度 v_r、v_l はそれぞれ


math3.png
math4.png

となる。また、回転中心からロボット中心の距離を ρ とすると、以下の式が成り立つ。


math5.png

一方、中心から車輪までの距離(トレッドの1/2)を d とすると、


math0.png
math1.png

となる。以上の式から、速度指令(v_x、v_y、v_a)の時に実際に与えるべき左右のモーターの角速度は以下の通りになります。


math6.png
math7.png

Educator Vehicle の車輪の直径 (2r)、トレッド (2d) はそれぞれ

車輪の直径 2r 56mm (0.056m)
車輪の直径 r 28mm (0.028m)
トレッド幅 2d 118.5mm (0.1185m)
トレッド幅 d 59.25mm (0.05925m)
車輪の幅 28.5mm (0.0285m)

なので、

math8.png
math9.png

となる。

自己位置推定(オドメトリ)

次に、ロボットの自己位置同定の方法について考えます。 ロボットの移動速度・角速度を積分することで任意の時点の位置・姿勢を得ることができます。速度 v_x、角速度 v_a とすると、(x、y、θ) の微小変位と v_x、v_a との関係を直線近似すると、


math10.png
math11.png
math12.png

となる。(より厳密には円弧近似する方法もあるが、ここでは簡単に直線近似とした。) これを実際のロボット制御時に、計算機上で求める場合、サンプリング周期 Δt [s] として、

math13.png
math14.png
math15.png

のように求められる。

RTC のひな形作成

作成する RTC の設計

作成する RTC を設計します。

作成する RTC の仕様をいかに示します。RTCBuilder で必要事項を入力し、ひな形コードを生成します。

基本タブ
プロファイル名 名称・指定
モジュール名 EducatorVehicle
バージョン 任意
ベンダ名 任意
カテゴリ Mobilerobot
アクティビティ
有効アクション onInitialize、onActivated、onDeactivated、onExecute
データポート (InPort)
ポート名 意味
velocity2D RTC::TimedVelocity2D 速度指令 (v_x、v_y、v_θ) [m/s、m/s、rad/s]
angle RTC::TimedDouble
データポート (OutPort)
ポート名 意味
odometry RTC::TimedPose2D 現在の位置・姿勢(角度) (x、y、θ) [m、m、rad]
ultrasonic RTC::RangeData 超音波センサーをレンジセンサーと仮定し、要素1の距離データを格納
gyro RTC::TimedDouble ジャイロセンサーを TimedDouble [rad] にて出力
color RTC::TimedString カラーセンサーの値を色名 (none、black、white、blue、green、red、yellow、brown) で出力
touch RTC::TimedBooleanSeq タッチセンサーの値をBoolean[2] で出力
コンフィギュレーション
ポート名 意味
wheelRadius double タイヤの半径 [m]
wheelDistance double タイヤ間距離の1/2 [m]

EV3 デバイスの操作方法について

モーター

速度制御

速度を制御するためには以下のデバイスファイルに"on"と書き込む必要があります。

 echo on > /sys/class/tacho-motor/motor0/speed_regulation

起動時には off になっているので速度制御はできません。 off の場合は duty_cycle_sp でデューティー比を設定できます。

そして以下のファイルに目標速度を書き込みます。

 echo 50 > /sys/class/tacho-motor/motor0/speed_sp

ここで指定する値は1秒間に何カウント動かすかという値なので、以下のデバイスファイルから取得する値を角速度に掛けて変換してください。 ※モーターM、モーターLの場合は count_per_rot で取得できる値が360なので変換しなくても影響はありません。

 cat /sys/class/tacho-motor/motor0/count_per_rot

後は以下のコマンドを入力すると回転を開始します。

 echo run-forever > /sys/class/tacho-motor/motor0/command

現在の角速度を取得するためには以下のデバイスファイルを使用します。

 cat /sys/class/tacho-motor/motor0/speed

以上の手順を ev3dev-lang-cpp を利用して記述すると以下のようになります。

 ev3dev::large_motor lm = ev3dev::large_motor();
 lm.set_speed_regulation_enabled("on");
 lm.set_speed_sp(50*lm.count_per_rot());
 lm.run_forever();
 std::cout << lm.speed()/lm.count_per_rot() << std::endl;

ev3dev-lang-python を利用して記述すると以下のようになります。

 lm = ev3.LargeMotor()
 lm.set_attr_string("speed_regulation", "on")
 lm.speed_sp = 50*lm.count_per_rot
 lm.run_forever()
 print lm.speed/lm.count_per_rot

一定時間動作させる

モーターを一定時間動作させるには、まず以下のデバイスファイルで時間を設定してください。

 echo 2000 > /sys/class/tacho-motor/motor0/time_sp

そして以下のコマンドで動作を開始します。

 echo run-timed > /sys/class/tacho-motor/motor0/command

位置制御

位置制御を行うためにはまず duty_cycle_sp (speed_regulation が on の場合は speed_sp) を設定しておく必要があります。

 echo 50 > /sys/class/tacho-motor/motor0/speed_sp

次に以下のデバイスファイルで位置を設定します。

 echo 100 > /sys/class/tacho-motor/motor1/position_sp

この位置もカウント数で指定するため、count_per_rot で変換してください。

以下のコマンドで動作を開始します。

 echo run-to-abs-pos > /sys/class/tacho-motor/motor1/command

現在の位置からの相対的な角度を指定したい場合は以下のコマンドを利用します。

 echo run-to-rel-pos > /sys/class/tacho-motor/motor1/command

現在の位置は以下のデバイスファイルから取得できます。

 cat /sys/class/tacho-motor/motor1/position

以上の手順を ev3dev-lang-cpp を利用して記述すると以下のようになります。

 ev3dev::large_motor lm = ev3dev::large_motor();
 lm.set_speed_regulation_enabled("on");
 lm.set_speed_sp(50*lm.count_per_rot());
 lm.set_position_sp(100*lm.count_per_rot());
 lm.run_to_abs_pos(100*lm.count_per_rot());
 #lm.run_to_rel_pos(100*lm.count_per_rot());

ev3dev-lang-python を利用して記述すると以下のようになります。

 lm = ev3.LargeMotor()
 lm.set_attr_string(None, "speed_regulation", "on")
 lm.speed_sp = 50*lm.count_per_rot
 lm.run_to_abs_pos()
 #lm.run_to_rel_pos()

センサーの C++、Python による操作

カラーセンサーで反射光の強さ取得

  • C++
     ev3dev::color_sensor cs = ev3dev::color_sensor();
     std::cout << cs.reflected_light_intensity() << std::endl;
  • Python
     cs = ev3.ColorSensor()
     print cs.reflected_light_intensity()

タッチセンサーのオンオフ取得

  • C++
     ev3dev::touch_sensor ts = ev3dev::touch_sensor();
     std::cout << ts.is_pressed() << std::endl;
  • Python
     cs = ev3.ColorSensor()
     print cs.reflected_light_intensity()

ジャイロセンサーで角度取得

  • C++
     ev3dev::gyro_sensor gs = ev3dev::gyro_sensor();
     std::cout << gs.angle() << std::endl;
  • Python
     gs = ev3.GyroSensor()
     print gs.angle()

LCD の操作

  • C++
     ev3dev::lcd lcd = ev3dev::lcd();
     unsigned char *fb = lcd.frame_buffer();
     for(int i=0;i < 3072;i++)
     {
         if(i%24 < 12)fb[i] = 0x00;
         else fb[i] = 0xff;
     }
  • Python
     lcd = ev3.Screen()
     lcd.mmap.seek(os.SEEK_SET)
     lcd.mmap.write(chr(0xff)*3072)
     for i in range(lcd.fix_info.smem_len):
         if i%24 < 12:
             lcd.mmap.seek(os.SEEK_SET)
             lcd.mmap.seek(i)
             lcd.mmap.write_byte(chr(0xff))

Educator Vehicle用 RTC のインストール (EV3)

このページでは Educator Vehicle を操作するための各RTC のインストール方法について説明します。

EducatorVehicle

EducatorVehicle は EV3 の走行速度の入力、センサーのデータの出力等を行うためのコンポーネントです。

クロス環境で以下のコマンドを入力してください。

 git clone https://github.com/Nobu19800/EducatorVehicle
 cd EducatorVehicle
 cmake .
 make

生成された src/EducatorVehicleComp を EV3 に転送してください。

EducatorVehicle
InPort
名前 データ型 説明
velocity2D RTC::TimedVelocity2D 目標速度
angle RTC::TimedDouble モーターMの角度
lcd RTC::CameraImage LCDに表示する画像データ
sound RTC::TimedString 出力する音声
OutPort
名前 データ型 説明
odometry RTC::TimedPose2D 現在の位置・姿勢
current_vel RTC::TimedVelocity2D 現在の速度・角速度
ultrasonic RTC::RangeData 超音波センサーで計測した距離
gyro RTC::TimedDouble ジャイロセンサーで計測した角度
color RTC::TimedString カラーセンサーで計測した色
light_reflect RTC::TimedDouble カラーセンサーで計測した反射光の強さ
touch RTC::TimedBoolean タッチセンサーのオンオフ。右側が0番目の要素、左側が1番目の要素
コンフィギュレーションパラメーター
名前 デフォルト値 説明
wheelRadius 0.028 車輪の半径
wheelDistance 0.054 タイヤ間距離の1/2
medium_motor_speed 1.6 モーターMの速度

simulator_ev3_2.png

タッチセンサーの出力

touch で入力したデータの0番目が右側(3番ポート)のタッチセンサー、1番目が左側(1番ポート)のタッチセンサーに対応しています。

音声の出力

sound による音声の入力には以下のコマンドを利用できます。

  • beep
    beep と入力するとビープ音が鳴ります。
  • tone
    以下のように tone、周波数、時間と入力すると指定周波数の音を指定ミリ秒数だけ鳴らします。

 tone,100,1000

  • それ以外
    それ以外は指定文字列を発音します

LCD に表示する画像について

画像ファイルを saveBinaryImage.exe にドラッグ・アンド・ドロップすれば変換できます。

LDC で表示する画像データは、以下のコンポーネントで画像データの変換を行えば入力可能です。 Windows で使用する場合は、release フォルダーの ImageConversionLCDComp.exe で起動できます。

ImageConversionLCD
InPort
名前 データ型 説明
out RTC::CameraImage 変換前の画像データ
OutPort
名前 データ型 説明
out RTC::CameraImage 変換後の画像データ

ImageConversionLCD.png

例えば、OpenRTM-aist 付属のサンプルコンポーネント OpenCVCamera と接続すれば、EV3 にカメラ画像を表示させることができます。

system_lcd.png
s_DSC00796.JPG

あるいは、指定の画像を入力するということもできます。

s_DSC00797.JPGs_DSC00798.JPG

ControlEducatorVehicle

ControlEducatorVehicle を用いることによって以下の移動ロボット(Educator Vehicle 改)の制御ができます。組み立て方は このページ を参考にしてください。

  • タッチセンサーに障害物が当たった時に回避する
  • カラーセンサーで地面の反射光を計測して一定以下になったら停止する
  • 超音波センサーで地面までの距離を計測して一定上になったら停止して超音波センサーを回転させて走行可能な地面を探索する

超音波センサーを使用しない場合は Educator Vehicle の制御にも使用できます。

クロス環境で以下のコマンドを入力してください。

 git clone https://github.com/Nobu19800/ControlEducatorVehicle
 cd ControlEducatorVehicle
 cmake .
 make

生成された src/ControlEducatorVehicleComp を EV3 に転送してください。

ControlEducatorVehicle
InPort
名前 データ型 説明
target_velocity_in RTC::TimedVelocity2D 目標速度
current_pose RTC::TimedPose2D 現在位置・姿勢
ultrasonic RTC::TimedRangeData 超音波センサーで計測した距離
light_reflect RTC::TimedDouble カラーセンサーで計測した反射光の強さ
touch TimedBoolean タッチセンサーのオンオフ
OutPort
名前 データ型 説明
target_velocity_out RTC::TimedVelocity2D 補正後の目標速度
angle RTC::TimedDouble モーターMの角度
コンフィギュレーションパラメーター
名前 デフォルト値 説明
sensor_height 0.2 走行できる地面があると判定する超音波センサーの計測値
back_speed 0.1 後退運動をする速さ
back_time 1.0 後退運動する時間
rotate_speed 0.8 回転運動をする速さ
rotate_time 2.0 回転運動する時間
medium_motor_range 1.6 モーターMの動作範囲

ControlEducatorVehicle.png

タッチセンサーの入力による回避運動

ev3_4.png

タッチセンサーがオンになった場合、まず③のように back_speed で指定した速さで back_time で指定した時間だけ後退します。 そして④のように rotate_speed で指定した角速度で rotate_time で指定した時間だけ回転します。 回転する方向はオンになったタッチセンサーと逆方向です。

超音波センサーによる地面までの距離計測

超音波センサーで地面までの距離を計測して停止、超音波センサーを回転させて走行可能な地面を探索する操作を実行するためには、EV3 の Education Vehicle を組み立ててさらに超音波センサーを回転させるように取り付ける必要があります。

動作手順は以下のようになっています。

ev3_sensor.png

机の上などを走行している場合で、②のようぬ机の端まで移動したとします。 超音波センサーで計測した距離が sensor_height 以上になった場合、一旦停止します。 そして③のように超音波センサーを右側に90度回転させて地面までの高さが sensor_height 以下かを判定します。 sensor_height 以上だった場合は④のように左方向に180度回転させて地面までの高さが sensor_height 以下かを判定します。 sensor_height 以下だった場合は、超音波センサーを向けた方向に Education Vehicle を回転させます。

一括インストール

上記の RTC を一括でインストールします。 以下のコマンドを入力してください。

 git clone https://github.com/Nobu19800/EducatorVehicle_script_ev3dev
 cd EducatorVehicle_script_ev3dev
 sh Component/install_rtc.sh

サンプルの RTシステムの実行

事前準備

Windows

RTC のインストール

サンプルの RTシステムの一部で以下の RTC を使用するためインストールしてください。

DirectInputRTC

ジョイスティックで操作するためのRTCです。 以下のサイトからインストーラーをダウンロードして実行してください。

JoystickToVelocity

DirectInputRTC のアウトポートからの pos からの出力 (TimedLongSeq型) を TimedVelocity2D型に変換する RTC です。 以下のサイトからインストーラーをダウンロードして実行してください。

FloatSeqToVelocity

FloatSeqToVelocity は OpenRTM-aist-Python のサンプルTkJoyStick の出力 (TimedFloatSeq型) をTimeVelocity2D型でに変換してアウトポートから出力する RTC です。

ここ からダウンロードしてください。

EducatorVehicle
InPort
名前 データ型 説明
in TimeFloatSeq 変換前のデータ
OutPort
名前 データ型 説明
in TimedVelocity2D 変換後のデータ
コンフィギュレーションパラメーター
名前 デフォルト値 説明
rotation_by_position -0.02 ジョイスティックのX座標に対する回転角速度
velocity_by_position 0.002 ジョイスティックのY座標に対する直進速度

ev3_10.png

スクリプトファイル

RTC の起動、RTシステムの復元を自動化するためのスクリプトファイルです。 ここ からダウンロードしてください。

ネームサーバー、RTシステムエディタの起動

Windows

まず最初に Windows でネームサーバー、RTシステムエディタを起動してください。 詳しい手順は このページ を参考にしてください。

ev3dev

EV3 の 一括インストールの項目 でダウンロードしたファイルの中に rtc.conf があるので、rtc.conf の以下の ppp.pp.pp.ppp の部分を Windows側の IPアドレスに変更してください。

 corba.nameservers: ppp.pp.pp.ppp

これで起動したコンポーネントが Windows のネームサーバーに登録されるようになります。

Windows で IPアドレスを確認するには以下のコマンドを入力します。

 ipconfig

RTC の起動

Windows

Windows側の RTC は スクリプトファイルの項目 でダウンロードしたファイルの中に start_component.bat というバッチファイルがあるのでそれを実行すれば以下の RTC が起動します。 ※64bit版 Windows、32bit版 OpenRTM-aist を対象にしています。32bit版 Windows の場合は start_component_32.bat、64bit版 OpenRTM-aist を利用する場合は start_component_64.bat を起動してください。 ※Python のインストールしたディレクトリーにパスが通っていない場合、TkJoyStick は起動できません。お手数ですが このページ の手順を参考にして手動で起動してください。

ev3dev

一括インストールの項目 でダウンロードしたフォルダーの中の start_rtc.sh を実行することで起動できます。

 cd RaspberryPiMouseRTSystem_script_Raspbian
 sh start_rtc.sh

これで以下の RTC が起動します。

 ControlEducatorVehicle0
 EducatorVehicle0

RTシステムの復元、開始

Windows側でスクリプトファイルの項目 でダウンロードしたファイルの JoystickControlEV3 フォルダー内の JoystickControlEV3_resurrect.bat を実行してください。 これでデータポートの接続、コンフィギュレーションパラメーターの設定などが行われます。 次に JoystickControlEV3_activate.bat を実行すると RTC をアクティブ化します。 JoystickControlEV3 はジョイスティックコンポーネントから EV3 を操作する RTシステムです。

非アクティブにする際は JoystickControlEV3_stop.bat を起動してください。 JoystickControlEV3_teardown.bat を起動するとポートの接続を切断します。

サンプルの詳細

JoystickControlEV3 以外のサンプルも ****_resurrect.bat で RTシステム復元、****_activate.bat でアクティブ化、****_stop.bat で非アクティブ化、****_teardown.bat でポートの切断ができます。

ファイル名 内容
****_resurrect.bat RTシステム復元
****_activate.bat アクティブ化
****_stop.bat 非アクティブ化
****_teardown.bat ポートの切断

GamePadSimpleControlEV3

このサンプルはゲームパッドのアナログスティックで傾けた方向に Educator Vehicle を操作する RTシステムです。 Windows側の PC にゲームパッドを接続してから起動してください。

ev3_9.png

JoystickSimpleControlEV3

このサンプルは OpenRTM-aist-Python のサンプルコンポーネント TkJoyStick で傾けた方向に Educator Vehicle を操作する RTシステムです。

ev3_8.png

GamePadControlEV3

このサンプルはゲームパッドのアナログスティックで傾けた方向に Educator Vehicle を操作することに加えて、タッチセンサー、超音波センサー、カラーセンサーを利用した制御 を行う RTシステムです。

ev3_6.png

JoystickControlEV3

このサンプルは OpenRTM-aist-Python のサンプルコンポーネント TkJoyStick で傾けた方向に Educator Vehicle を操作することに加えて、タッチセンサー、超音波センサー、カラーセンサーを利用した制御 を行う RTシステムです。

ev3_7.png

自作の RTC で制御

初心者用課題

ひな形コードの作成

新規作成した RTC を EducatorVehicle と接続して制御するまでの手順を説明します。

まずは Windows、Ubuntu上で このページ の手順に従って RTC を作成してください。 RTC の仕様は以下のように入力します。

基本
モジュール名 EV3SampleCPP、もしくはEV3SamplePy
アクティビティ
有効アクション onInitialize、onExecute、onActivated、onDeactivated
データポート
InPort
名前 データ型 説明
touch RTC::TimedBooleanSeq タッチセンサーのオンオフ
OutPort
名前 データ型 説明
target_velocity RTC::TimedVelocity2D 目標速度
sound RTC::TimedString 音声
コンフィギュレーション
名前 説明
forward_velocity double 直進速度、デフォルト値は0.0、制約条件に-0.20<=x<=0.20、Widgetはslider、Stepは0.02
rotate_velocity double 回転速度、デフォルト値は0.0、制約条件に-3.1<=x<=3.1、Widgetはslider、Stepは0.2
言語・環境
言語 C++、もしくは Python

この RTC ではコンフィギュレーションパラメーター forward_velocity、rotate_velocity に入力した速度を target_velocity から EducatorVehicle に送信します。 さらに touch でタッチセンサーのオンオフを取得して、オンになった場合は停止して sound から発声する音を指令します。

※RTC は EV3上で動作させることを前提にしていますが、動作確認や講習会での利用には Windows や Ubuntu上で動作させても問題はないので、その場合はコードの編集をする前に CMake で Visual Studio、もしくは Code::Blocks のプロジェクトを生成しておくことをお勧めします。 CMake でプロジェクト生成からビルドまでの手順は以下のページに記載してあります。

コードの編集

まずは onExecute 関数を編集します。

以下はforward_velocity、rotate_velocityの 値を target_velocity から送信するコードです。

C++(src/EV3SampleCPP.cpp)

 RTC::ReturnCode_t EV3SampleCPP::onExecute(RTC::UniqueId ec_id)
 {
     //コンフィギュレーションパラメータで設定した速度を送信する
     m_target_velocity.data.vx = m_forward_velocity;
     m_target_velocity.data.va = m_rotate_velocity;
     setTimestamp(m_target_velocity);
     m_target_velocityOut.write();
   return RTC::RTC_OK;
 }

Python(EV3SamplePy.py)

     def onExecute(self, ec_id):
         #コンフィギュレーションパラメータで設定した速度を送信する
         self._d_target_velocity.data.vx = self._forward_velocity[0]
         self._d_target_velocity.data.vy = 0
         self._d_target_velocity.data.va = self._rotate_velocity[0]
         OpenRTM_aist.setTimestamp(self._d_target_velocity)
         self._target_velocityOut.write()

一応、非アクティブ状態の時は停止するように onDeactivated で速度0を送信するようにします。

C++(src/EV3SampleCPP.cpp)

 RTC::ReturnCode_t EV3SampleCPP::onDeactivated(RTC::UniqueId ec_id)
 {
     //停止する
     m_target_velocity.data.vx = 0;
     m_target_velocity.data.vy = 0;
     m_target_velocity.data.va = 0;
     setTimestamp(m_target_velocity);
     m_target_velocityOut.write();
 
   return RTC::RTC_OK;
 }

Python(EV3SamplePy.py)

     def onDeactivated(self, ec_id):
         #停止する
         self._d_target_velocity.data.vx = 0
         self._d_target_velocity.data.vy = 0
         self._d_target_velocity.data.va = 0
         OpenRTM_aist.setTimestamp(self._d_target_velocity)
         self._target_velocityOut.write()
         return RTC.RTC_OK

共通インターフェース仕様書では進行方向をX軸正方向にしているため、Velocity2D型のvxに直進速度、vaに回転速度を入力します。

Pythonではさらにコンストラクタの以下の部分を修正してください。

Python(EV3SamplePy.py)

         #self._d_target_velocity = RTC.TimedVelocity2D(*target_velocity_arg)
         self._d_target_velocity = RTC.TimedVelocity2D(RTC.Time(0,0),RTC.Velocity2D(0,0,0))

         #self._d_sound = RTC.TimedString(*sound_arg)
         self._d_sound = RTC.TimedString(RTC.Time(0,0),[])

※ここまでの作業だけでも Educator Vehicle の動作は可能なので、面倒ならば以下の手順は飛ばしてもらっても大丈夫です。

次にタッチセンサーが ON になった時に停止する処理を書きます。 ここで touch に onExecute が呼び出された時に新規に受信したデータが必ず存在するとは限らないので、タッチセンサーのデータを一時的に格納しておく変数を宣言しておきます。

C++(include/EV3SampleCPP/EV3SampleCPP.h)

 private:
      bool m_last_sensor_data[2];    /*センサーのデータを格納する変数*/

Python(EV3SamplePy.py)

     def __init__(self, manager):
         OpenRTM_aist.DataFlowComponentBase.__init__(self, manager)
 
         #タッチセンサーのデータを格納する変数
         self._last_sensor_data = [False, False]

次に onExecute にタッチセンサーがオンの場合に停止、音声を出力する処理を追加します。

C++(src/EV3SampleCPP.cpp)

 RTC::ReturnCode_t EV3SampleCPP::onExecute(RTC::UniqueId ec_id)
 {
     //ここから
     //データを新規に受信した場合に、データを m_last_sensor_data を格納する
     if (m_touchIn.isNew())
     {
         m_touchIn.read();
         if (m_touch.data.length() == 2)
         {
             for (int i = 0; i < 2; i++)
             {
                 //タッチセンサーがOFFからONになった時に音を鳴らす
                 if (!m_last_sensor_data[i] && m_touch.data[i])
                 {
                     m_sound.data = "beep";
                     setTimestamp(m_sound);
                     m_soundOut.write();
 
                     
                 }
                 m_last_sensor_data[i] = m_touch.data[i];
             }
         }
     }
     //タッチセンサーがONの時に前進しないようにする
     if (m_forward_velocity > 0)
     {
         for (int i = 0; i < 2; i++)
         {
             if (m_last_sensor_data[i])
             {
                 m_target_velocity.data.vx = 0;
                 m_target_velocity.data.vy = 0;
                 m_target_velocity.data.va = 0;
                 setTimestamp(m_target_velocity);
                 m_target_velocityOut.write();
                 return RTC::RTC_OK;
             }
         }
     }
     //ここまで
     //コンフィギュレーションパラメーターで設定した速度を送信する
     m_target_velocity.data.vx = m_forward_velocity;
  (以下略)

Python(EV3SamplePy.py)

    def onExecute(self, ec_id):
         #ここから
         #データを新規に受信した場合に、データをm_last_sensor_dataを格納する
         if self._touchIn.isNew():
             data = self._touchIn.read()
             if len(data.data) == 2:
                 for i in range(2):
                     #タッチセンサーがOFFからONになった時に音を鳴らす
                     if not self._last_sensor_data[i] and data.data[i]:
                         self._d_sound.data = "beep"
                         OpenRTM_aist.setTimestamp(self._d_sound)
                         self._soundOut.write()
                 self._last_sensor_data = data.data[:]
 
 
         #タッチセンサーが ON の時に前進しないようにする
         if self._forward_velocity[0] > 0:
             for d in self._last_sensor_data:
                 if d:
                     self._d_target_velocity.data.vx = 0
                     self._d_target_velocity.data.vy = 0
                     self._d_target_velocity.data.va = 0
                     OpenRTM_aist.setTimestamp(self._d_target_velocity)
                     self._target_velocityOut.write()
                     return RTC.RTC_OK
 
 
        #ここまで
        #コンフィギュレーションパラメーターで設定した速度を送信する
        self._d_target_velocity.data.vx = self._forward_velocity[0]
 (以下略)

ビルド

ソースコードの編集が終了したらC++の場合はビルドを行います。 EV3上で動作させる場合はクロスコンパイル環境でビルドを行ってください。 ソースコードのあるディレクトリに移動して以下のコマンドを入力すればビルドできます。

 cd EV3SampleCPP
 cmake .
 make

※Visual Studio、もしくは Code::Blocks で編集している場合は GUI上の操作でビルドを行ってください。

生成された src/EV3SampleCPPComp を EV3 に転送してください。 ※Windows、Ubuntu で動作させる場合は転送しないでください。

 sftp robot@<IPアドレス>
 sftp> put EV3SampleCPP/src/EV3SampleCPPComp

Python版もEV3SamplePy.py を転送してください。

 sftp robot@<IPアドレス>
 sftp> put EV3SamplePy/EV3SamplePy.py

cmake がインストールされていない場合は以下のコマンドを入力してください。

 sudo apt-get install cmake

RTC 起動

ビルドが完了したら RTC を起動します。 以下のコマンドで起動できます。

C++

 EV3SampleCPPComp&

Python

 python EV3SamplePy.py&

※Windows上で RTC を起動する場合は EV3SampleCPPComp.exe (EV3SamplePy.py) をダブルクリックしてください。

次に EducatorVehicle を起動させます。 以下のコマンドで起動してください。

 Compomnents/EducatorVehicleComp&

動作確認

まずは動作確認のためにデータポートの接続を行います。 Windows側で RTシステムエディタを起動してください。 最初に EV3 で起動しているネームサーバーを RTシステムエディタのビューに追加します。 ネームサーバー追加ボタンを押下して EV3 の IPアドレスを入力してください。

rpm11.png

ネームサーバーを追加したらデータポートを以下のように接続してください。

ev3_sample.png

ポートの接続
EV3SampleCPP0(EV3SamplePy0) EducatorVehicle0
target_velocity velocity2D
touch touch
sound sound

そして RTC をアクティブ化すると動作を開始します。

まずは EV3SampleCPP(EV3SamplePy) のコンフィギュレーションパラメーターを変更する事で Educator Vehicle を操作してみます。

RTシステムエディタで EV3SampleCPP0(EV3SamplePy0) を選択して、Configuration View の編集を選択してください。

ev3_conf.png

すると以下のウインドウが起動します。

ev3_conf2.png

forward_velocity と rotate_velocity のスライダーによりEV3を操作できます。

次にタッチセンサーがオンになった場合に停止するかを確認してみます。 タッチセンサーに物体を接触させて停止するかを確認してください。 停止した時に音が鳴るかも確認してください。

応用(中級者用課題)

ここからはさらにタッチセンサーがオンになった場合に後退→回転のより障害物を回避する動作を実装します。 タッチセンサーのデータが入力された時に以下の処理を実行することで回避運動を行います。

flowChart_4.png

コンフィギュレーションパラメーター

新たに以下のコンフィギュレーションパラメーターを設定します。

コンフィギュレーション
名前 説明
back_speed double 後退速度、デフォルト値は0.1
back_time double 後退運動の時間、デフォルト値は1.0
rotate_speed double 回転速度、デフォルト値は0.8
rotate_time double 回転運動の時間、デフォルト値は2.0

関数の実装

新たに以下の関数を実装します。

関数名 内容 引数
stop_robot 停止する なし
back_move 後退する なし
rotate_move 回転する dir(回転方向)

stop_robot 関数

stop_robot関数は以下のようになっています。 目標速度を0に設定して送信します。

 void ControlEducatorVehicle::stop_robot()
 {
     m_target_velocity_out.data.vx = 0;
     m_target_velocity_out.data.vy = 0;
     m_target_velocity_out.data.va = 0;
     setTimestamp(m_target_velocity_out);
     m_target_velocity_outOut.write();
 }

back_move 関数

back_move 関数は以下のようになっています。 後退するための速度を出力後、sleep 関数で指定時間だけ待つことによりコンフィギュレーションパラメータ back_speed の 速度でback_time の時間だけ後退する運動を実現しています。

 void ControlEducatorVehicle::back_move()
 {
     //後退運動を指令
     m_target_velocity_out.data.vx = -m_back_speed;
     m_target_velocity_out.data.vy = 0;
     m_target_velocity_out.data.va = 0;
     setTimestamp(m_target_velocity_out);
     m_target_velocity_outOut.write();
     
     //一定時間待つ
     double sec, usec;
     usec = modf(m_back_time, &sec);
     
     coil::TimeValue ts((int)sec, (int)(usec*1000000.0));
     coil::sleep(ts);
 
     //一旦停止
     stop_robot();
 }

※onExecute 関数内で sleep 関数などで待機すると、その間は RTシステムエディタ等による操作ができなくなるためあまり望ましい実装の方法ではありません。 ただ今回の場合は実行コンテキストを止めずに処理を実装すると処理が複雑化するためこのように実装しています。

stop_robot 関数

rotate_move 関数は以下のようになっています。 後退運動と同じく、コンフィギュレーションパラメーター rotate_speed の速度で rotate_time の時間だけ回転運動する処理を実装しています。

 void ControlEducatorVehicle::rotate_move(bool dir)
 {
     //回転運動を指令
     m_target_velocity_out.data.vx = 0;
     m_target_velocity_out.data.vy = 0;
     //左回転
     if (dir)m_target_velocity_out.data.va = m_rotate_speed;
     //右回転
     else m_target_velocity_out.data.va = -m_rotate_speed;
     setTimestamp(m_target_velocity_out);
     m_target_velocity_outOut.write();
     
     //一定時間待つ
     double sec, usec;
     usec = modf(m_rotate_time, &sec);
     coil::TimeValue ts((int)sec, (int)(usec*1000000.0));
     coil::sleep(ts);
 
     //一旦停止
     stop_robot();
 }

onExecute 関数の実装

最後にフローチャートのように、タッチセンサーのデータ入力時に回避運動を行う処理を実装すれば完成です。

 RTC::ReturnCode_t ControlEducatorVehicle::onExecute(RTC::UniqueId ec_id)
 {
     //目標速度を変数に格納
     if (m_target_velocity_inIn.isNew())
     {
         m_target_velocity_inIn.read();
         vx = m_target_velocity_in.data.vx;
         vy = m_target_velocity_in.data.vy;
         va = m_target_velocity_in.data.va;
     }
     //タッチセンサーの処理
     if (m_touchIn.isNew())
     {
         while(m_touchIn.isNew())m_touchIn.read();
         if (m_touch.data.length() >= 2)
         {
             touch_r = m_touch.data[0];
             touch_l = m_touch.data[1];
             //前進しているときのみ
             if (vx > 0)
             {
                 //左タッチセンサー
                 if (m_touch.data[0])
                 {
                     停止→後退→右回転
                     stop_robot();
                     back_move();
                     rotate_move(true);
 
                 }
                 //右タッチセンサー
                 else if (m_touch.data[1])
                 {
                     停止→後退→左回転
                     stop_robot();
                     back_move();
                     rotate_move(false);
 
                 }
 
             }
         }
 
     }
 
     m_target_velocity_out.data.vx = vx;
     m_target_velocity_out.data.vy = vy;
     m_target_velocity_out.data.va = va;
 
     
     
     setTimestamp(m_target_velocity_out);
     //目標速度送信
     m_target_velocity_outOut.write();
     
     return RTC::RTC_OK;
 }

発展(上級者用課題)

ここでは超音波センサーにより地面までの距離を検知して滑落を回避する RTC を作成します。

 /ja/node/6030/

超音波センサーで検知した地面までの高さが一定以上の場合に、以下の処理を実行します。

flowChart2.png

データポート、コンフィギュレーションパラメーター

以下のデータポート、コンフィギュレーションパラメーターを追加してください。

データポート
InPort
名前 データ型 説明
ultrasonic RTC::RangeData 超音波センサーをレンジセンサーと仮定し、要素1の距離データを格納
current_pose RTC::TimedPose2D 現在の位置・姿勢
OutPort
名前 データ型 説明
angle RTC::TimedDouble モーターMの角度
コンフィギュレーション
名前 説明
sensor_height double 接地可能と判定する地面までの高さ、デフォルト値は0.20
medium_motor_range double Mモーターの動作範囲、デフォルト値は1.6

関数の実装

接地可能な地面を超音波センサーで調べる search_ground 関数と、ロボットを指定した角度だけ回転させる turn_move 関数を実装します。

 bool ControlEducatorVehicle::search_ground(double &a)
 {
     //Mモーターを右回転
     m_angle.data = (-1)*m_medium_motor_range;
     setTimestamp(m_angle);
     m_angleOut.write();
     coil::TimeValue ts(2, 0);
     coil::sleep(ts);
    
     //地面までの距離が一定以下かを判定
     if (m_ultrasonicIn.isNew())
     {
         while(m_ultrasonicIn.isNew())m_ultrasonicIn.read();
         if (m_ultrasonic.ranges.length() >= 1)
         {
             
             if (m_ultrasonic.ranges[0] < m_sensor_height)
             {
                 //一定以下の場合は接地可能と判定して、接地可能な地面を検知した方向を変数に格納
                 a = m_medium_motor_range;
                 return true;
             }
         }
     }
     
     //Mモーターを左回転
     m_angle.data = (-1)*-m_medium_motor_range;
     setTimestamp(m_angle);
     m_angleOut.write();
     ts = coil::TimeValue(4, 0);
     coil::sleep(ts);
 
     //地面までの距離が一定以下かを判定
     if (m_ultrasonicIn.isNew())
     {
         while(m_ultrasonicIn.isNew())m_ultrasonicIn.read();
         if (m_ultrasonic.ranges.length() >= 1)
         {
             
             if (m_ultrasonic.ranges[0] < m_sensor_height)
             {
                 //一定以下の場合は接地可能と判定して、接地可能な地面を検知した方向を変数に格納
                 a = -m_medium_motor_range;
                 return true;
             }
                 
         }
     }
     
 
     m_angle.data = 0;
     setTimestamp(m_angle);
     m_angleOut.write();
     
 
     
     return false;
 }

 void ControlEducatorVehicle::turn_move(double a)
 {
 
     int max_count = 100;
     coil::TimeValue ts(0,10000);
 
     //現在の姿勢を取得する
     double spos = 0;
     for (int i = 0; i < max_count; i++)
     {
         if (m_current_poseIn.isNew())
         {
             m_current_poseIn.read();
             spos = m_current_pose.data.heading;
             break;
         }
         coil::sleep(ts);
         //一定時間内にデータを取得できなかった場合は回転運動を中止する
         if (i == max_count - 1)return;
     }
     max_count = 1000;
 
     //回転運動を開始する
     double data_new_count = 0;
     double max_data_new_count = 100;
     for (int i = 0; i < max_count; i++)
     {
         if (m_current_poseIn.isNew())
         {
             while(m_current_poseIn.isNew())m_current_poseIn.read();
 
             //目標姿勢角との差に定数を掛けた値を目標速度とする
             double pos = m_current_pose.data.heading - spos;
             double k = 1;
             m_target_velocity_out.data.vx = 0;
             m_target_velocity_out.data.vy = 0;
 
 
             double diff = (a - pos);
             double vela = k * diff;
             if(vela > m_rotate_speed)vela = m_rotate_speed;
             if(vela < -m_rotate_speed)vela = -m_rotate_speed;
 
             //目標速度出力
             m_target_velocity_out.data.va = vela;
 
             setTimestamp(m_target_velocity_out);
             m_target_velocity_outOut.write();
             
         
             
             
             //目標姿勢角との差が一定以下の場合は停止して処理終了
             if(sqrt(pow(diff,2)) < 0.03)
             {
                 stop_robot();
                 return;
             }
 
             data_new_count = 0;
         }
         else
         {
             //一定時間データが取得できなかった場合は処理終了
             data_new_count += 1;
             if(data_new_count > max_data_new_count)
             {
                 stop_robot();
                 return;
             }
             coil::sleep(ts);
         }
 
 
     }
     stop_robot();
     
 }

onExecute 関数

最後に onExecute 関数を以下のように実装します。

 RTC::ReturnCode_t ControlEducatorVehicle::onExecute(RTC::UniqueId ec_id)
 {
     //目標速度を変数に格納
     if (m_target_velocity_inIn.isNew())
     {
         m_target_velocity_inIn.read();
         vx = m_target_velocity_in.data.vx;
         vy = m_target_velocity_in.data.vy;
         va = m_target_velocity_in.data.va;
     }
     
     //超音波センサーのデータ入力時の処理開始
     if (m_ultrasonicIn.isNew())
     {
         while(m_ultrasonicIn.isNew())m_ultrasonicIn.read();
         if (m_ultrasonic.ranges.length() >= 1)
         {
             range = m_ultrasonic.ranges[0];
             //前進しているかの判定
             if (vx > 0)
             {
                 //超音波センサーで検知した地面までの高さが一定以上かの判定
                 if (m_ultrasonic.ranges[0] > m_sensor_height)
                 {
                     //停止フラグをtrueにする
                     //(次の超音波センサーデータ入力時に距離が一定以下と判定した場合は停止フラグをfalseにする)
                     stop_flag = true;
                     //一旦停止
                     stop_robot();
                     //Mモーターの角度を0に設定
                     m_angle.data = 0;
                     setTimestamp(m_angle);
                     m_angleOut.write();
                      //Mモーターを回転させて接地可能な地面を検知
                     double a = 0;
                     bool ret = search_ground(a);
                     //Mモーターの角度を0に設定
                     m_angle.data = 0;
                     setTimestamp(m_angle);
                     m_angleOut.write();
                     
 
                     
                     //接地可能な地面が見つかった場合は回転運動を行う
                     if (ret)
                     {
                         turn_move(a);
                     }
                     coil::TimeValue ts(2, 0);
                     coil::sleep(ts);
                     
                 }
                 //超音波センサーで検知した地面までの高さが一定以下の場合は停止フラグを false にする
                 else
                 {
                     stop_flag = false;
                 }
 
             }
         }
     }
 
     
     //停止フラグが true の場合は停止する
     if (stop_flag)
     {
         m_target_velocity_out.data.vx = 0;
         m_target_velocity_out.data.vy = 0;
         m_target_velocity_out.data.va = 0;
     }
     //停止フラグがfalseの場合は目標速度をそのまま出力
     else
     {
         m_target_velocity_out.data.vx = vx;
         m_target_velocity_out.data.vy = vy;
         m_target_velocity_out.data.va = va;
     }
     
     
     
     setTimestamp(m_target_velocity_out);
     m_target_velocity_outOut.write();
     
   return RTC::RTC_OK;
 }

RTシステムの保存について

RTシステムの保存については RTシステムエディタ上でもできるのですが、rtshell により RTシステムの復元を自動化することができます。 RTシステムエディタでポートの接続、コンフィギュレーションパラメーターを設定後、rtcryo コマンドを実行してください。

 rtcryo localhost -o testSystem.rtsys

これで、testSystem.rtsys というファイルにRTシステムの情報が保存されます。

ただし今回の課題のように複数のネームサーバーに登録された RTC を使用する場合、以下のように複数のネームサーバーを指定する必要があります。

 rtcryo localhost 192.168.11.1 -o testSystem.rtsys

保存した RTシステムを復元するためには rtresurrect コマンドを使用します。

 rtresurrect testSystem.rtsys

RTCをアクティブ化するには rtstart コマンドを使用します。

 rtstart testSystem.rtsys

RTCの非アクティブ化はrtstopコマンドを使用します。

 rtstop testSystem.rtsys

ポートを切断する場合は rtteardownコマンドを使用します。

 rtteardown testSystem.rtsys

注意点として、RTC はデフォルトの設定だとネームサーバーにはホスト名 .host_cxt 以下に登録されます。 ホスト名は環境によって違うので、この手順で RTシステムを保存しても他の環境では再現できないという事になります。 このため、rtc.conf を編集してネームサーバーの Root 直下に登録するようにすると、他の環境でも RTシステムの復元ができるようになります。

 naming.formats: %n.rtc

EV3 を無線LANアクセスポイントとして動作させるまでの手順

ここでは EV3 をアクセスポイント化するまでの手順を説明します。

Raspberry Pi とほとんど手順は同じなので、詳しいことは以下のサイトなどを参考にしてください。

http://hara.jpn.com/_default/ja/Topics/RasPiE3839EE382A6E382B9E38292E784A1E7B79ALANE382A2E382AFE382BBE382B9E3839DE382A4E383B3E38388E58C96.html

Realtek 製品対応の hostapd のコンパイル

無線LANアダプタは GW-USNANO2A を使います。 まず上記のサイトにもあるように 8192CU は hostapd にはデフォルトで対応していないので、クロス環境で以下のコマンドを入力してコンパイルを行います。

 wget http://12244.wpc.azureedge.net/8012244/drivers/rtdrivers/cn/wlan/0001-RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip
 unzip 0001-RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip
 cd RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/wpa_supplicant_hostapd/
 tar zxvf wpa_supplicant_hostapd-0.8_rtw_r7475.20130812.tar.gz
 cd wpa_supplicant_hostapd-0.8_rtw_r7475.20130812/hostapd/
 make

コンパイルが終了したら、hostapdをEV3 に転送してください。

 sftp robot@<IPアドレス>
 put hostapd

各種設定

固定IPアドレス

/etc/network/interfaces に以下の記述を追加してください。

 auto lo
 
 iface lo inet loopback
 
 iface eth0 inet dhcp
 
 auto wlan0
 iface wlan0 inet static
 address 192.168.11.1
 netmask 255.255.255.0

hostapd のインストール

以下のコマンドで hostapd をインストールしてください。

 sudo apt-get install hostapd

インストールが完了したら、先ほど転送した hostapdを/usr/sbin にコピーしてください。

 cp hostapd /usr/sbin/hostapd

/etc/hostapd/hostapd.conf は以下のように記述します。 ssid、wpa_passphrase は適宜変更してください。

 interface=wlan0
 driver=rtl871xdrv
 ssid=ev3_0
 hw_mode=g
 channel=6
 macaddr_acl=0
 auth_algs=1
 ignore_broadcast_ssid=0
 wpa=2
 wpa_passphrase=ev3atx9fr
 wpa_key_mgmt=WPA-PSK
 wpa_pairwise=TKIP
 rsn_pairwise=CCMP

/etc/default/hostapd を以下のように変更します。

 #DAEMON_CONF=""
 →
 DAEMON_CONF="/etc/hostapd/hostapd.conf"

ネットワークを再起動します。

 sudo /etc/init.d/networking restart

以下のコマンドで hostapd を起動します。

 sudo /usr/sbin/hostapd /etc/hostapd/hostapd.conf -dd

これで他の PC から設定した SSID が見えるようにはなったはずです。

DHCP サーバーの設定

以下のコマンドで DHCP サーバーをインストールします。

 sudo apt-get install isc-dhcp-server

/etc/dhcp/dhcpd.conf を以下のように修正してください。

 # option definitions common to all supported networks...
 #option domain-name "example.org";
 #option domain-name-servers ns1.example.org, ns2.example.org;
 
 ping-check true;
 
 #default-lease-time 600;
 #max-lease-time 7200;
 
 authoritative;
 
 subnet 192.168.11.0 netmask 255.255.255.0 {
 option routers 192.168.11.1;
 option broadcast-address 192.168.11.255;
 option subnet-mask 255.255.255.0;
 option domain-name "local";
 option domain-name-servers 8.8.8.8,8.8.4.4;
 default-lease-time 600;
 max-lease-time 7200;
 range 192.168.11.101 192.168.11.199;
 }

/etc/default/isc-dhcp-server を以下のように修正します。

 INTERFACES="wlan0"

起動スクリプトの設定

最後の rc.local に以下の記述を追加します。

 ifdown wlan0
 ifup wlan0
 service hostapd start
 service isc-dhcp-server start

再起動する前に このページの手順で無線LANを設定している場合は、Wireless and Networks→Wifi→Powered を OFF に設定してください。また Wireless and Networks→Offline Mode を ON にしてください。

これで全ての手順が終了したので、再起動して接続できるかを確認してください。 失敗する場合は有線で EV3 と接続して設定が正しく行われているかを確認してください。

ボタン操作でアクセスポイントを起動する手順

EV3 のボタン操作でアクセスポイントを起動する手順を説明します。

まず /home/robot に以下のスクリプトファイル(ここでは start_ap.sh) を作成してください。

 #!/bin/sh
 sudo ifdown wlan0
 sudo ifup wlan0
 sudo service hostapd start
 sudo service isc-dhcp-server start

以下のコマンドで権限を変更してください。

 chmod +x start_ap.sh

このファイルを EV3 のボタン操作で File Browser→start_ap.sh で起動するのですが、EV3 のボタン操作で sudo 実行時のパスワードが入力できないので sudo をパスワードなしで実行できるように設定します。

以下のコマンドを入力してください。

 sudo visudo

そして以下の記述を追加してください。

 robot ALL=(ALL)     ALL
 %robot ALL=(ALL)     NOPASSWD: ALL

これで準備完了です。EV3 のボタン操作で File Browser→start_ap.sh を起動してください。

TETRIX の利用方法

概要

TETRIX は Pitsco Education が販売している LEGO Mindstroms の拡張製品です。 アルミ製フレーム、高トルクのモーター等がセットに含まれており、本格的なロボットの製作が可能になります。

仕様

  • DCモーター
電圧 12V
静止トルク 2.1N・m
回転数 152rpm
  • RCサーボ
名前 HS-485HB(HITEC)
電圧 6V
静止トルク 0.59N・m
回転数 56rpm

モータードライバ

TETRIX ベースセットには DCモータードライバ (DC Motor Controller for TETRIX)、RCサーボドライバ (Servo Controller for TETRIX) が付属しています。

これらのモータードライバと EV3 を接続することで DCモーター及び RCサーボの制御が可能になります。

接続方法

以下のように接続してください。

s_DSC00776.JPG

接続してモータードライバの電源が ON の状態で EV3 の電源を投入してください。

操作方法

EV3 とモータードライバの通信は I2C により行います。

接続に成功している場合、/dev以下にi2c-3、i2c-4、i2c-5、i2c-6 のいずれかのデバイスファイルが追加されているはずです。 後ろの値がポート番号に2を足した値になっています。例えばポート1に接続した場合は i2c-3 になります。 以下で ev3dev上で C++、及び Python によるモータードライバの制御方法について述べます。

まずは I2C 通信に必要なファイルをインクルードしてください。

  • C++
     #include <fcntl.h>
     #include <sys/ioctl.h>
     #include <linux/i2c-dev.h>
  • Python
     import smbus

I2C の通信を開始します。

  • C++
     int fd; = open("/dev/i2c-3", O_RDWR);
  • Python
     sm = smbus.SMBus(3)

モータードライバのアドレスは 0x01 に設定されますが、デイジーチェインで接続した場合 0x02~0x08 に設定されます。 上記の接続の場合、DCモータードライバは 0x01 で RCサーボドライバは 0x02 に設定されているはずです。 まずは DCモータードライバを操作してみます。

DCモータードライバ

制御モードを設定します。 モーター1 は 0x44、モーター2 は 0x47 のレジスタに以下の値を書き込むことで制御モードが設定可能です。 ※TETRIX ベースセットにはエンコーダーは付属していないので速度制御、位置制御モードを使用する場合は別途購入する必要があります。

入力値 制御モード
0b00 PWM
0b01 速度制御
0b10 位置制御
0b11 エンコーダーリセット

PWM モードに設定します。

  • C++
     ioctl(fd, I2C_SLAVE, 0x01)
     unsigned char buf[2] = {0x44, 0x00};
     write(fd, buf, 2);
  • Python
     sm.write_i2c_block_data(0x01, 0x44, [0x00])

最後に PWM の幅を設定します。 モーター1は 0x45、モーター2 は 0x46 のレジスタに書き込むことにより設定可能です。 PWM は正回転するばあいは 1~127 の値、逆回転する場合は -127~-1 の値で設定できます。 ただし、0 の場合はフロートモードで停止、128 の場合はブレーキモードで停止します。

  • C++
     unsigned char buf[2] = {0x45, 0x30};
     write(fd, buf, 2);
  • Python
     sm.write_i2c_block_data(0x01, 0x45, [0x30])

RCサーボドライバ

RCサーボドライバは最大6個の RCサーボを制御可能であり、0x42~0x47 のレジスタに目標角度を書き込むことで制御できます。 パルス幅は 0.75ms~2.25ms で設定可能です。

  • C++
     ioctl(fd, I2C_SLAVE, 0x02)
     unsigned char buf[2] = {0x42, 0x60};
     write(fd, buf, 2);
  • Python
     sm.write_i2c_block_data(0x02, 0x42, [0x60])

応用例

以下は DCモーターを利用した乗り物の作成例です。

s_DSC00777.JPG

取っ手部分にLモーターが2個取り付けられており、Lモーターを回転させることで車体の制御が可能になっています。

tetrix_device.png

使用した RTC は以下の通りです。

TetrixVehicle

上記の乗り物を制御するためのコンポーネントです。

TetrixVehicle
InPort
名前 データ型 説明
target_velocity RTC::TimedVelocity2D 目標速度
update_position RTC::TimedPose2D 位置の再設定
OutPort
名前 データ型 説明
position RTC::TimedPose2D 現在位置
コンフィギュレーションパラメータ-
名前 デフォルト値 説明
wheelRadius 0.04 車輪の半径
wheelDistance 0.34 車輪間の距離
portNum 1 ポート番号
rot_dir_left_motor 1 左車輪の回転方向
rot_dir_righteft_motor -1 右車輪の回転方向
GearRatio 3.0 ギア比

VehicleController

Lモーターの角度から車体の目標速度を出力するコンポーネントです。

TetrixVehicle
OutPort
名前 データ型 説明
out RTC::TimedVelocity2D 目標速度
コンフィギュレーションパラメーター
名前 デフォルト値 説明
rotation_by_angle -0.6 根元のモーターの角度に対する目標角速度の変化量
velocity_by_angle -0.1 先端のモーターの角度に対する目標速度の変化量

シミュレーター利用方法

このページでは Educator Vehicle 改 のシミュレーター RTC の仕様、利用方法について説明します。

ev32.png

仕様

simulator_ev3_1.png

EV3Simulator
InPort
名前 データ型 説明
velocity2D RTC::TimedVelocity2D 目標速度
angle RTC::TimedDouble Mモーターの角度
pos_update RTC::TimedPose2D 現在位置更新
OutPort
名前 データ型 説明
odometry RTC::TimedPose2D 現在の位置
current_vel RTC::TimedVelocity2D 現在の速度
ultrasonic RTC::RangeData 超音波センサーで計測した距離
gyro RTC::TimedDouble ジャイロセンサーで計測した角度
light_reflect RTC::TimedDouble カラーセンサーで計測した反射光の強さ
touch RTC::TimedBooleanSeq タッチセンサーのオンオフ。右側が0番目の要素、左側が1番目の要素
コンフィギュレーションパラメーター
名前 デフォルト値 説明
medium_motor_speed 1.6 モーターMの速度
blocksConfigFile None 障害物の配置設定ファイルの名前
touchSensorOnLength 0.003 タッチセンサーをオンと判定する押し込んだ距離
lightReflectThreshold 0.1 カラーセンサーから物体までの距離がこの値以下になると255を出力
plane_exist 0 1の時は新たに地面作成
plane_x 0 地面の位置(X)
plane_y 0 地面の位置(Y)
plane_z 0 カラーセンサーから物体までの距離がこの値以下になると255を出力
plane_lx 1.0 地面の長さ
plane_ly 1.0 地面の幅
plane_lz 1.0 地面の高さ
draw_time 0.01 描画の周期
sampling_time -1 シミュレーションの刻み幅。負の値に設定した場合は実行コンテキストの周期で設定

使用方法

以下からダウンロードできます。

展開したフォルダーの EXEフォルダー内に実行ファイル (EV3SimulatorComp.exe) があります。 この EXEファイルを実行すると RTC が起動します。

コンフィギュレーションパラメーター

障害物の設定ファイル

blocksConfigFile というパラメーターで障害物の配置を設定する CSVファイルを指定できます。 サンプルとして test.csv というファイルを用意してあります。

このファイルに位置、角度、サイズを記述してください。

位置(X) 位置(Y) 位置(Z) 長さ(L) 幅(W) 高さ(H) 角度(θ)
0.3 0.0 0.0 0.1 1.0 0.3 0.0

 /ja/node/6198
 /ja/node/6198

ブロックは何個でも設定可能です。

地面の設定

Educator Vehicle 改 は超音波センサーにより設置可能な地面の有無を検知して回避する運動が可能になっています。 この制御シミュレーションのために、地面を新たに作成するコンフィギュレーションパラメーターを用意してあります。

plane_existを1に設定後、地面の位置、サイズを設定してください。

チュートリアル(RTM講習会)

チュートリアル(EV3、Windows、第2部)

はじめに

このページではシミュレーター上の Educator Vehicleを操作するためのコンポーネントの作成手順を説明します。 Educator VehicleはレゴマインドストームEV3の組み立て例の一つです。

ev32_2.png

資料のダウンロード

まずは資料をダウンロードしてください。

ZIPファイルは Lhaplus 等で展開してください。

インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布のUSBメモリーに入れてあります。

付属のシミュレータで以下の Educator Vehicle 改のシミュレーションができます。

/jp/node/6038

Lモーター、Mモーターの制御だけではなく、タッチセンサー、ジャイロセンサー、超音波センサーのシミュレーションも可能になっています。

作成する RTコンポーネント

  • RobotController コンポーネント

EV3Simulator コンポーネントと接続してシミュレーター上のロボットを操作するためのコンポーネントです。

RobotController コンポーネントの作成

GUI(スライダー)によりシミュレーター上のロボットの操作を行い、タッチセンサーがオンの時には自動的に停止するコンポーネントの作成を行います。

tutorial_ev3_irex1.png

作成手順

作成手順は以下の通りです。

  • 開発環境の確認
  • コンポーネントの仕様を決める
  • RTC Builderによるソースコードのひな形の作成
  • ソースコードの編集
  • コンポーネントの動作確認

開発環境の確認

以下の環境を想定しています。

コンポーネントの仕様

RobotController は目標速度を出力するアウトポート、センサー値を入力するインポート、目標速度を設定するコンフィギュレーションパラメーターを持っています。

コンポーネント名称 RobotController
InPort
ポート名 in
TimedBooleanSeq
説明 センサー値
OutPort
ポート名 out
TimedVelocity2D
説明 目標速度
Configuration
パラメーター名 speed_x
double
デフォルト値 0.0
制約 -1.0<x<1.0
Widget slider
Step 0.01
説明 直進速度の設定
Configuration
パラメーター名 speed_r
double
デフォルト値 0.0
制約 -2.0<x<2.0
Widget slider
Step 0.01
説明 回転速度の設定

TimedVelocity2D 型について

2次元平面上の移動ロボットの移動速度を格納するデータ型である TimedVelocity2D 型を使用します。

     struct Velocity2D
     {
           /// Velocity along the x axis in metres per second.
           double vx;
           /// Velocity along the y axis in metres per second.
           double vy;
           /// Yaw velocity in radians per second.
           double va;
     };
 
 
     struct TimedVelocity2D
     {
           Time tm;
           Velocity2D data;
     };

このデータ型にはX軸方向の速度vx、Y軸方向の速度vy、Z軸周りの回転速度vaが格納できます。

vxvyvaはロボット中心座標系での速度を表しています。


tutorial_ev3_irex3.png

vxはX方向の速度、vyはY方向の速度、vaはZ軸周りの角速度です。

Educator Vehicle改のように2個の車輪が左右に取り付けられているロボットの場合、横滑りしないと仮定するとvyは0になります。

直進速度vx、回転速度vaを指定することでロボットの操作を行います。

タッチセンサーについて


tutorial_ev3_irex2.png

RobotController コンポーネントのひな型の生成

RobotController コンポーネントの雛型の生成は、RTCBuilder を用いて行います。

RTCBuilder の起動

Eclipse では、各種作業を行うフォルダーを「ワークスペース」(Work Space)とよび、原則としてすべての生成物はこのフォルダーの下に保存されます。 ワークスペースはアクセスできるフォルダーであれば、どこに作っても構いませんが、このチュートリアルでは以下のワークスペースを仮定します。

  • C:\workspace

まずは Eclipse を起動します。 Windows 8.1の場合は「スタート」>「アプリビュー(右下矢印)」>「OpenRTM-aist 1.1.2」>「OpenRTP」をクリックすると起動できます。

最初にワークスペースの場所を尋ねられますので、上記のワークスペースを指定してください。

/ja/node/6026

すると、以下のようなWelcomeページが表示されます。


/ja/node/6026
Eclipse の初期起動時の画面

Welcomeページはいまは必要ないので左上の「×」ボタンをクリックして閉じてください。

右上の [Open Perspective] ボタンをクリックしてください。

/ja/node/6026
パースペクティブの切り替え

「RTC Builder」を選択することで、RTCBuilder が起動します。メニューバーに「カナヅチとRT」の RTCBuilder のアイコンが表示されます。

/ja/node/6026
パースペクティブの選択

新規プロジェクトの作成

RobotController コンポーネントを作成するために、RTC Builder で新規プロジェクトを作成する必要があります。

左上の [Open New RTCBuilder Editor] のアイコンをクリックしてください。

/ja/node/6057
RTC Builder 用プロジェクトの作成

「プロジェクト名」欄に作成するプロジェクト名 (ここでは RobotController) を入力して [終了] ボタンをクリックします。

RT-Component-BuilderProject_1.png

指定した名称のプロジェクトが生成され、パッケージエクスプローラ内に追加されます。

PackageExplolrer_1.png

生成したプロジェクト内には、デフォルト値が設定された RTC プロファイル XML(RTC.xml) が自動的に生成されます。

RTC プロファイルエディタの起動

RTC.xml が生成された時点で、このプロジェクトに関連付けられているワークスペースとして RTCBuilder のエディタが開くはずです。 もし起動しない場合はパッケージエクスプローラーの RTC.xml をダブルクリックしてください。

/ja/node/6026

プロファイル情報入力とコードの生成

まず、いちばん左の「基本」タブを選択し、基本情報を入力します。先ほど決めた RobotController コンポーネントの仕様(名前)の他に、概要やバージョン等を入力してください。 ラベルが赤字の項目は必須項目です。その他はデフォルトで構いません。

  • モジュール名: RobotController
  • モジュール概要: 任意(Robot Controller component)
  • バージョン: 任意(1.0.0)
  • ベンダ名: 任意
  • モジュールカテゴリ: 任意(Controller)


Basic_1.png
基本情報の入力


次に、「アクティビティ」タブを選択し、使用するアクションコールバックを指定します。

RobotController コンポーネントでは、onActivated()、onDeactivated()、onExecute() コールバックを使用します。下図のように①の onAtivated をクリック後に②のラジオボタンにて [ON] にチェックを入れます。 onDeactivated、onExecute についても同様の手順を行います。


Activity_1.png
アクティビティコールバックの選択


さらに、「データポート」タブを選択し、データポートの情報を入力します。 先ほど決めた仕様を元に以下のように入力します。なお、変数名や表示位置はオプションで、そのままで結構です。


  • InPort Profile:
    • ポート名: in
    • データ型: TimedBooleanSeq

  • OutPort Profile:
    • ポート名: out
    • データ型: TimedVelocity2D


DataPort_1.png
データポート情報の入力


次に、「コンフィギュレーション」タブを選択し、先ほど決めた仕様を元に、Configuration の情報を入力します。 制約条件および Widget とは、RTSystemEditor でコンポーネントのコンフィギュレーションパラメーターを表示する際に、スライダー、スピンボタン、ラジオボタンなど、GUI で値の変更を行うためのものです。

直進速度 speed_x、回転速度 speed_r はスライダーのより操作できるようにします。


  • speed_x
    • 名称: speed_x
    • データ型: double
    • デフォルト値: 0.0
    • 制約条件: -1.0<x<1.0
    • Widget: slider
    • Step: 0.01
  • speed_r
    • 名称: speed_r
    • データ型: double
    • デフォルト値: 0.0
    • 制約条件: -2.0<x<2.0
    • Widget: slider
    • Step: 0.01


Configuration_1.png
コンフィグレーション情報の入力


次に、「言語・環境」タブを選択し、プログラミング言語を選択します。 ここでは、C++(言語)を選択します。なお、言語・環境はデフォルト等が設定されておらず、指定し忘れるとコード生成時にエラーになりますので、必ず言語の指定を行うようにしてください。

Language_1.png
プログラミング言語の選択


最後に、「基本」タブにあ [コード生成] ボタンをクリックし、コンポーネントの雛型を生成します。


Generate_1.png
雛型の生成(Generate)


※ 生成されるコード群は、eclipse 起動時に指定したワークスペースフォルダーの中に生成されます。現在のワークスペースは、[ファイル] > [ワークスペースの切り替え..]で確認することができます。

CMake によるビルドに必要なファイルの生成

RTC Builder で生成したコードの中には CMake でビルドに必要な各種ファイルを生成するための CMakeLists.txt が含まれています。 CMake を利用することにより CMakeLists.txt からVisual Studio のプロジェクトファイル、ソリューションファイル、もしくは Makefile 等を自動生成できます。

CMake(cmake-gui) の操作

CMake を利用してビルド環境の Configure を行います。 まずは CMake(cmake-gui) を起動してください。「スタート」>「アプリビュー(右下矢印)」>「CMake 3.7.2」>「CMake (cmake-gui)」をクリックすると起動できます。

CMakeGUI0_1.png
CMake GUI の起動とディレクトリーの指定

画面上部に以下のようなテキストボックスがありますので、それぞれソースコードの場所 (CMakeList.txtがある場所) と、ビルドディレクトリーを指定します。

  • Where is the soruce code
  • Where to build the binaries

ソースコードの場所は RobotController コンポーネントのソースが生成された場所で CMakeList.txt が存在するディレクトリーです。 デフォルトでは <ワークスペースディレクトリー>/RobotController になります。

このディレクトリーはエクスプローラから cmake-gui にドラックアンドドロップすると手入力しなくても設定されます。

ビルドディレクトリーとは、ビルドするためのプロジェクトファイルやオブジェクトファイル、バイナリを格納する場所のことです。 場所は任意ですが、この場合 <ワークスペースディレクトリー>/RobotController/build のように分かりやすい名前をつけた RobotController のサブディレクトリーを指定することをお勧めします。

Where is the soruce code C:\workspace\RobotController
Where to build the binaries C:\workspace\RobotController\build

指定したら、下の [Configure] ボタンをクリックします。すると下図のようなダイアログが表示されますので、生成したいプロジェクトの種類を指定します。 今回は Visual Studio 15 2017 とします。Visual Studio 2013や Visual Studio 2019を利用している方はそれぞれ変更してください。 またプラットフォームにはx64を設定します。32bit版をインストールしている場合はWin32を選択してください。

/ja/node/6310
生成するプロジェクトの種類の指定

ダイアログで [Finish] ボタンをクリックすると Configure が始まります。 問題がなければ下部のログウインドウに「Configuring done」と出力されますので、続けて [Generate] ボタンをクリックします。 「Generating done」と出ればプロジェクトファイル・ソリューションファイル等の出力が完了します。

なお、CMake は Configure の段階でキャッシュファイルを生成しますので、トラブルなどで設定を変更したり環境を変更した場合は [File] > [Delete Cache] でキャッシュを削除して Configure からやり直してください。

ヘッダ、ソースの編集

次に先ほど指定した build ディレクトリーの中の RobotController.sln をダブルクリックして Visual Studio を起動します。

※cmake-gui の新しいバージョンでは cmake-gui 上のボタンをクリックすることで起動できます。


cmake_gui.png

ヘッダ (include/RobotController/RobotController.h) およびソースコード (src/RobotController.cpp) をそれぞれ編集します。 Visual Studio のソリューションエクスプローラから RobotController.h、RobotController.cpp をクリックすることで編集画面が開きます。
/ja/node/6026

アクティビティ処理の実装

RobotController コンポーネントでは、コンフィギュレーションパラメーター(speed_x、speed_y)をスライダーで操作しその値を目標速度としてアウトポート(out)から出力します。 インポート(in) から入力された値を変数に格納して、その値が一定以上の場合は停止するようにします。


onActivated()、onExecute()、onDeactivated() での処理内容を下図に示します。

RCRTC_State_1.png
アクティビティ処理の概要


ヘッダファイル (RobotController.h) の編集

センサー値を一時的に格納する変数 sensor_data を宣言します。

   private:
     bool sensor_data[2];           //センサー値を一時格納する変数

ソースファイル (RobotController.cpp) の編集

下記のように、onActivated()、onDeactivated()、onExecute() を実装します。

 RTC::ReturnCode_t RobotController::onActivated(RTC::UniqueId ec_id)
 {
     //センサー値初期化
     for (int i = 0; i < 2; i++)
     {
         sensor_data[i] = false;
     }
 
     return RTC::RTC_OK;
 }

 RTC::ReturnCode_t RobotController::onDeactivated(RTC::UniqueId ec_id)
 {
          //ロボットを停止する
          m_out.data.vx = 0;
          m_out.data.va = 0;
          m_outOut.write();
  
          return RTC::RTC_OK;
 }

 RTC::ReturnCode_t RobotController::onExecute(RTC::UniqueId ec_id)
 {
     //入力データの存在確認
     if (m_inIn.isNew())
     {
         //入力データ読み込み
         m_inIn.read();
         for (int i = 0; i < m_in.data.length(); i++)
         {
             //入力データ格納
             if (i < 2)
             {
                 sensor_data[i] = m_in.data[i];
             }
         }
     }
 
     //前進するときのみ停止するかを判定
     if (m_speed_x > 0)
     {
         for (int i = 0; i < 2; i++)
         {
             //タッチセンサのオンオフを判定
             if (sensor_data[i] == true)
             {
                 //タッチセンサがオンの場合は停止
                 m_out.data.vx = 0;
                 m_out.data.va = 0;
                 m_outOut.write();
                 return RTC::RTC_OK;
             }
         }
     }
 
     //すべてのタッチセンサがオフの場合はコンフィギュレーションパラメーターの値で操作
     m_out.data.vx = m_speed_x;
     m_out.data.va = m_speed_r;
     m_outOut.write();
  }

Visual Studio によるビルド

ビルドの実行

Visual Studioの [ビルド] >「ソリューションのビルド」を選択してビルドを行います。


/ja/node/6026
ビルドの実行


RobotController コンポーネントの動作確認

作成した RobotController をシミュレーターコンポーネントと接続して動作確認を行います。

以下より EV3Simulator コンポーネントをダウンロードしてください。

ZIPファイルは Lhaplus 等で展開してください。

インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布のUSBメモリーに入れてあります。

NameService の起動

コンポーネントの参照を登録するためのネームサービスを起動します。


「スタート」>「アプリビュー(右下矢印)」>「OpenRTM-aist 1.1.2」の順に辿り、「Start Naming Service」をクリックしてください。

※ 「Start Naming Service」をクリックしても omniNames が起動されない場合は、フルコンピュータ名が14文字以内に設定されているかを確認してください。

RobotController コンポーネントの起動

RobotController コンポーネントを起動します。

RobotController\build\src\Debug(もしくは、Release)フォルダーの RobotControllerComp.exe ファイルを実行してください。

シミュレーターコンポーネントの起動

このコンポーネントは先ほどダウンロードしたファイル(RTM_Tutorial_iREX2017.zip)を展開したフォルダーの EXE/EV3SimulatorComp.exe を実行すると起動します。

コンポーネントの接続

下図のように、RTSystemEditor にて RobotController コンポーネント、EV3Simulator コンポーネントを接続します。 システムダイアグラムは左上のOpen New System Editorボタンで表示できます。

tutorial_ev3_irex9_2.png
コンポーネントの接続

コンポーネントのActivate

RTSystemEditor の上部にあります [All Activate] というアイコンをクリックし、全てのコンポーネントをアクティブ化します。 正常にアクティベートされた場合、下図のように黄緑色でコンポーネントが表示されます。


tutorial_ev3_irex10.png
コンポーネントのアクティブ化


動作確認

下図のようにコンフィギュレーションビューの [編集] ボタンからコンフィギュレーションを変更することができます。


tutorial_ev3_irex6.png

スライダーを操作してシミュレーター上のEducator Vehicle改の操作ができるかを確認してください。


tutorial_ev3_irex7.png
コンフィギュレーションパラメーターの変更


正常に動作している場合は、開始し位置から直進した場合に壁の前で停止します。


tutorial_ev3_irex18.png


正常に動作していない場合は、壁に接触後にそのまま前進を続けます。


tutorial_ev3_irex17.png


実機での動作確認

講習会で EV3実機を用意している場合は実機での動作確認が可能です。

手順は以下の通りです。

  • Educator Vehicle改の組立て
  • EV3アクセスポイントの起動
  • EV3のアクセスポイントに接続
  • ポートの接続
  • コンポーネントのアクティブ化

Educator Vehicle改の組立て

EV3 は分解した状態で参加者に配ります。 組み立て方は以下の通りです。

ただし、Mモーター、超音波センサー、カラーセンサー、ジャイロセンサーについては、講習で使用しないため取り付ける必要はありません。 以下の※の作業については、時間が余った人が実施してください。

まずは土台部分を取り出してください。


s_DSC00463.JPG

最初にMモーターにケーブル(15cm)を接続します※。


s_DSC00446.JPG

次に EV3 本体を取り付けます。 Mモーターにケーブルを接続した場合は、ケーブルが左側の隙間から出るようにしてください。


s_DSC00448.JPG s_DSC00450.JPG



右側のタッチセンサーを取り付けてください。


s_DSC00451.JPG s_DSC00452.JPG



超音波センサーを取り付けてください※。


s_DSC00454.JPG

ケーブルを接続してください。 必須なのは車輪駆動用のLモーター右、Lモーター左、タッチセンサーだけです。

Lモーター右 ポート C 25cmケーブル
Lモーター左 ポート B 25cmケーブル
Mモーター※ ポートA 25cmケーブル
タッチセンサー右 ポート 3 35cmケーブル
タッチセンサー左 ポート 1 35cmケーブル
超音波センサー※ ポート 4 50cmケーブル
ジャイロセンサー※ ポート 2 25cmケーブル

ケーブルは EV3 の上下に A~D と 1~4 のポートがあるのでそこにケーブルを接続します。


s_DSC00.JPG s_DSC00471.JPG




s_DSC00455.JPG s_DSC00456.JPG



左右にパーツを取り付けます※。 Lモーター右、Lモーター左、Mモーター、タッチセンサー右、タッチセンサー左のケーブルを挟むようにして取り付けてください※。
Lモーター右、タッチセンサー右のケーブルは右側から、Lモーター左、Mモーター、タッチセンサー左は左側から通してください※。


s_DSC00457.JPG


s_DSC00459.JPG

これでとりあえず完成ですが、余裕のある人はジャイロセンサーを取り付けてみてください※。


s_DSC00460.JPG s_DSC00461.JPG



電源の入れ方/切り方

電源の入れ方

中央のボタンを押せば電源が投入されます。


ev3_on.jpg

電源の切り方

EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。


ev3_off.jpg


s_DSC01033.JPG

再起動

再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。

リセット

ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。


ev3_reset.jpg

アクセスポイントの設定

EV3 の操作画面から「File Browser」を上下ボタンで選択して中央のボタンを押してください。

 ------------------------------
 192.168.0.1
 ------------------------------
 [File Browser               > ]
  Device Browser             >
  Wireless and Networks      > 
  Battery                    >
  Open Roberta Lab           >
  About                      >
 ------------------------------

次に scripts を選択して中央ボタンを押してください。

 ------------------------------
 192.168.0.1
 ------------------------------
         File Browser
 ------------------------------
 /home/robot
 ------------------------------
 [scripts                     ]
 ・・
 ・・
 ------------------------------

次の画面から start_ap.sh を選択して中央ボタンを押すとスクリプトが起動します。

 ------------------------------
 192.168.0.1
 ------------------------------
         File Browser
 ------------------------------
 /home/robot/scripts
 ------------------------------
 ../
 Component/
 ・・
 [start_ap.sh                 ]
 ------------------------------

しばらくすると無線LANアクセスポイントが起動するので、指定の SSID のアクセスポイントに接続してください。 SSID、パスワードは EV3 に貼り付けたテープに記載してあります。


tutorial_ev3_irex26.png

アクセスポイントに接続

アクセスポイントへの接続方法は以下のページを参考にしてください。

SSID、パスワードは EV3に貼り付けたシールに記載してあります。

まず右下のネットワークアイコンをクリックしてください。


/ja/node/6042

次に一覧から ev3_*** を選択してください。


/ja/node/6042

パスワードを入力してください。


/ja/node/6042

※ネットワークが切り替わった場合にネームサーバーへのコンポーネントの登録やポートの接続が失敗する場合があるのでネームサーバ、コンポーネントを一旦全て終了してください。 ネットワーク切り替え後に起動した場合には問題ないので、終了させる必要はありません。

ネームサーバー追加

続いてRTシステムエディタの [ネームサーバー追加] ボタンで 192.168.0.1 を追加してください。


tutorial_raspimouse0.png tutorial_ev3_irex12.png



するとEducatorVehicle0という RTC が見えるようになります。

ポートの接続

RTシステムエディタで EducatorVehicle、RobotController コンポーネントを以下のように接続します。

tutorial_ev3_irex11.png

アクティブ化

そして RTC をアクティブ化すると EV3の操作ができるようになります。

チュートリアル(EV3、Ubuntu、第2部)

はじめに

このページではシミュレーター上の Educator Vehicleを操作するためのコンポーネントの作成手順を説明します。 Educator VehicleはレゴマインドストームEV3の組み立て例の一つです。

ev32_2.png

資料のダウンロード

まずは資料をダウンロードしてください。

 git clone https://github.com/OpenRTM/RTM_Tutorial_EV3

付属のシミュレータで以下の Educator Vehicle 改のシミュレーションができます。

/jp/node/6038

Lモーター、Mモーターの制御だけではなく、タッチセンサー、ジャイロセンサー、超音波センサーのシミュレーションも可能になっています。

作成する RTコンポーネント

  • RobotController コンポーネント

EV3Simulator コンポーネントと接続してシミュレーター上のロボットを操作するためのコンポーネントです。

RobotController コンポーネントの作成

GUI(スライダー)によりシミュレーター上のロボットの操作を行い、タッチセンサーがオンの時には自動的に停止するコンポーネントの作成を行います。

tutorial_ev3_irex1.png

作成手順

作成手順は以下の通りです。

  • 開発環境の確認
  • コンポーネントの仕様を決める
  • RTC Builderによるソースコードのひな形の作成
  • ソースコードの編集
  • コンポーネントの動作確認

開発環境の確認

Linux (ここでは Ubuntu 16.04 を仮定) 上に開発環境を構築します。

OpenRTM-aistのインストール

インストールスクリプトでインストールします。

 $ wget http://svn.openrtm.org/OpenRTM-aist/trunk/OpenRTM-aist/build/pkg_install_ubuntu.sh
 $ sudo sh pkg_install_ubuntu.sh

OpenRTP のインストール

こちらのURL から Linux版の OpenRTP (コンポーネント開発ツール、システム開発ツール統合環境) をダウンロード、インストールします。 OepnRTP の実行には Java も必要となりますので default-jre パッケージをインストールします。

 $ apt-get install default-jre
 $ wget http://openrtm.org/pub/openrtp/packages/1.1.2.v20160526/eclipse442-openrtp112v20160526-ja-linux-gtk-x86_64.tar.gz
 $ tar xvzf eclipse442-openrtp112v20160526-ja-linux-gtk-x86_64.tar.gz

eclipse起動後、RTSystemEditor でネームサーバに接続できない場合があります。その場合、/etc/hosts の localhost の行に自ホスト名を追記してください。

 $ hostname
 ubuntu1404 ← ホスト名は ubuntu1404
 $ sudo vi /etc/hosts

 127.0.0.1       localhost
 を以下のように変更
 127.0.0.1       localhost ubuntu1404

CMake のインストール

 $ sudo apt-get install cmake cmake-gui

Code::Blocks のインストール

Code::Blocks は C/C++ に対応した統合開発環境です。 以下のコマンドでインストールできます。

 $ sudo apt-get install codeblocks

最新版を入手したい場合は以下のコマンドを入力します。

 $ sudo add-apt-repository ppa:damien-moore/codeblocks-stable
 $ sudo apt-get update
 $ sudo apt-get install codeblocks

EV3Simulator コンポーネント

シミュレーターコンポーネントについては手動でビルドを行います。 以下のコマンドを入力してください。

 $ wget https://raw.githubusercontent.com/Nobu19800/RTM_Tutorial_iREX2017/master/script/install_ev3_simulator.sh
 $ sudo sh install_ev3_simulator.sh

インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布の USBメモリー内のスクリプトを起動してください。

 $ sudo sh install_ev3_simulator_usb.sh

コンポーネントの仕様

RobotController は目標速度を出力するアウトポート、センサー値を入力するインポート、目標速度を設定するコンフィギュレーションパラメーターを持っています。

コンポーネント名称 RobotController
InPort
ポート名 in
TimedBooleanSeq
説明 センサー値
OutPort
ポート名 out
TimedVelocity2D
説明 目標速度
Configuration
パラメーター名 speed_x
double
デフォルト値 0.0
制約 -1.0<x<1.0
Widget slider
Step 0.01
説明 直進速度の設定
Configuration
パラメーター名 speed_r
double
デフォルト値 0.0
制約 -2.0<x<2.0
Widget slider
Step 0.01
説明 回転速度の設定

TimedVelocity2D 型について

2次元平面上の移動ロボットの移動速度を格納するデータ型である TimedVelocity2D 型を使用します。

     struct Velocity2D
     {
           /// Velocity along the x axis in metres per second.
           double vx;
           /// Velocity along the y axis in metres per second.
           double vy;
           /// Yaw velocity in radians per second.
           double va;
     };
 
 
     struct TimedVelocity2D
     {
           Time tm;
           Velocity2D data;
     };

このデータ型にはX軸方向の速度vx、Y軸方向の速度vy、Z軸周りの回転速度vaが格納できます。

vxvyvaはロボット中心座標系での速度を表しています。


tutorial_ev3_irex3.png

vxはX方向の速度、vyはY方向の速度、vaはZ軸周りの角速度です。

Educator Vehicle改のように2個の車輪が左右に取り付けられているロボットの場合、横滑りしないと仮定するとvyは0になります。

直進速度vx、回転速度vaを指定することでロボットの操作を行います。

タッチセンサーについて


tutorial_ev3_irex2.png

RobotController コンポーネントのひな型の生成

RobotController コンポーネントの雛型の生成は、RTCBuilder を用いて行います。

RTCBuilder の起動

Eclipse では、各種作業を行うフォルダーを「ワークスペース」(Work Space)とよび、原則としてすべての生成物はこのフォルダーの下に保存されます。 ワークスペースはアクセスできるフォルダーであれば、どこに作っても構いませんが、このチュートリアルでは以下のワークスペースを仮定します。

  • /home/ユーザー名/workspace

まずは Eclipse を起動します。 OpenRTP を展開したディレクトリーに移動して以下のコマンドを入力します。

 $ ./openrtp

最初にワークスペースの場所を尋ねられますので、上記のワークスペースを指定してください。

/ja/node/6058

すると、以下のような Welcome ページが表示されます。


/ja/node/6026
Eclipse の初期起動時の画面

Welcome ページはいまは必要ないので左上の「×」ボタンをクリックして閉じてください。

右上の [Open Perspective] ボタンをクリックしてください。

/ja/node/6026
パースペクティブの切り替え

「RTC Builder」を選択することで、RTCBuilderが起動します。メニューバーに「カナヅチとRT」の RTCBuilder のアイコンが現れます。

/ja/node/6026
パースペクティブの選択

新規プロジェクトの作成

RobotController コンポーネントを作成するために、RTC Builder で新規プロジェクトを作成する必要があります。

左上の [Open New RTCBuilder Editor] のアイコンをクリックしてください。

/ja/node/6057
RTC Builder 用プロジェクトの作成

「プロジェクト名」欄に作成するプロジェクト名 (ここでは RobotController) を入力して [終了] をクリックします。

/ja/node/6310

指定した名称のプロジェクトが生成され、パッケージエクスプローラ内に追加されます。

/ja/node/6310

生成したプロジェクト内には、デフォルト値が設定された RTC プロファイル XML(RTC.xml) が自動的に生成されます。

RTC プロファイルエディタの起動

RTC.xmlが生成された時点で、このプロジェクトに関連付けられているワークスペースとして RTCBuilder のエディタが開くはずです。 もし起動しない場合はパッケージエクスプローラーの RTC.xml をダブルクリックしてください。

/ja/node/6026

プロファイル情報入力とコードの生成

まず、いちばん左の「基本」タブを選択し、基本情報を入力します。先ほど決めた RobotController コンポーネントの仕様(名前)の他に、概要やバージョン等を入力してください。 ラベルが赤字の項目は必須項目です。その他はデフォルトで構いません。

  • モジュール名: RobotController
  • モジュール概要: 任意(Robot Controller component)
  • バージョン: 任意(1.0.0)
  • ベンダ名: 任意
  • モジュールカテゴリ: 任意(Controller)


/ja/node/6310
基本情報の入力


次に、「アクティビティ」タブを選択し、使用するアクションコールバックを指定します。

RobotController コンポーネントでは、onActivated()、onDeactivated()、onExecute() コールバックを使用します。下図のように①の onAtivated をクリック後に②のラジオボタンにて [ON] にチェックを入れます。 onDeactivated、onExecute についても同様の手順を行います。


/ja/node/6310
アクティビティコールバックの選択


さらに、「データポート」タブを選択し、データポートの情報を入力します。 先ほど決めた仕様を元に以下のように入力します。なお、変数名や表示位置はオプションで、そのままで結構です。


  • InPort Profile:
    • ポート名: in
    • データ型: TimedBooleanSeq

  • OutPort Profile:
    • ポート名: out
    • データ型: TimedVelocity2D


/ja/node/6310
データポート情報の入力


次に、「コンフィギュレーション」タブを選択し、先ほど決めた仕様を元に、Configuration の情報を入力します。 制約条件および Widget とは、RTSystemEditor でコンポーネントのコンフィギュレーションパラメーターを表示する際に、スライダー、スピンボタン、ラジオボタンなど、GUI で値の変更を行うためのものです。

直進速度 speed_x、回転速度 speed_r はスライダーのより操作できるようにします。


  • speed_x
    • 名称: speed_x
    • データ型: double
    • デフォルト値: 0.0
    • 制約条件: -1.0<x<1.0
    • Widget: slider
    • Step: 0.01
  • speed_r
    • 名称: speed_r
    • データ型: double
    • デフォルト値: 0.0
    • 制約条件: -2.0<x<2.0
    • Widget: slider
    • Step: 0.01


/ja/node/6310
コンフィグレーション情報の入力


次に、「言語・環境」タブを選択し、プログラミング言語を選択します。 ここでは、C++(言語) を選択します。なお、言語・環境はデフォルト等が設定されておらず、指定し忘れるとコード生成時にエラーになりますので、必ず言語の指定を行うようにしてください。

/ja/node/6310
プログラミング言語の選択


最後に、「基本」タブにある [コード生成] ボタンをクリックし、コンポーネントの雛型を生成します。


/ja/node/6310
雛型の生成(Generate)


※ 生成されるコード群は、eclipse起動時に指定したワークスペースフォルダーの中に生成されます。 現在のワークスペースは、[ファイル] > [ワークスペースの切り替え...] で確認することができます。

CMake によるビルドに必要なファイルの生成

RTC Builder で生成したコードの中には CMake でビルドに必要な各種ファイルを生成するための CMakeLists.txt が含まれています。 CMake を利用することにより CMakeLists.txt から Visual Studio のプロジェクトファイル、ソリューションファイル、もしくは Makefile 等を自動生成できます。

CMake(cmake-gui) の操作

CMake を利用してビルド環境の Configure を行います。 まずは CMake(cmake-gui) を起動してください。

 $ cmake-gui
CMakeGUI0_2_ubuntu.png
CMake GUI の起動とディレクトリーの指定

画面上部に以下のようなテキストボックスがありますので、それぞれソースコードの場所 (CMakeList.txt がある場所) と、ビルドディレクトリーを指定します。

  • Where is the soruce code
  • Where to build the binaries

ソースコードの場所は RobotController コンポーネントのソースが生成された場所で CMakeList.txt が存在するディレクトリーです。 デフォルトでは <ワークスペースディレクトリー>/RobotController になります。

このディレクトリーはエクスプローラから cmake-gui にドラックアンドドロップすると手入力しなくても設定されます。

ビルドディレクトリーとは、ビルドするためのプロジェクトファイルやオブジェクトファイル、バイナリを格納する場所のことです。 場所は任意ですが、この場合 <ワークスペースディレクトリー>/RobotController/build のように分かりやすい名前をつけた RobotController のサブディレクトリーを指定することをお勧めします。

Where is the soruce code /home/ユーザー名/RobotController
Where to build the binaries /home/ユーザー名/RobotController\build

指定したら、下の [Configure] ボタンをクリックします。すると下図のようなダイアログが表示されますので、生成したいプロジェクトの種類を指定します。 今回は CodeBlocks - Unix Makefiles を指定します。 Code::Blocks を使わない場合は Unix Makefiles を使ってください。

/ja/node/6026
生成するプロジェクトの種類の指定

また cmake-gui を使用しない場合は以下のコマンドでファイルを生成できます。

 $ mkdir build
 $ cd build
 $ cmake .. -G "CodeBlocks - Unix Makefiles"

ダイアログで [Finish] をクリックすると Configure が始まります。問題がなければ下部のログウインドウに「Configuring done」と出力されますので、続けて [Generate] ボタンをクリックします。 「Generating done」と出ればプロジェクトファイル・ソリューションファイル等の出力が完了します。

なお、CMake は Configure の段階でキャッシュファイルを生成しますので、トラブルなどで設定を変更したり環境を変更した場合は [File] > [Delete Cache] を選択して、キャッシュを削除してから Configure からやり直してください。

ヘッダ、ソースの編集

次に先ほど指定した build ディレクトリーの中の RobotController.cbp をダブルクリックして Visual Studio 2013 を起動します。

ヘッダ (include/RobotController/RobotController.h) およびソースコード (src/RobotController.cpp) をそれぞれ編集します。 Code::BlocksのProjectsからRobotController.h、RobotController.cpp をクリックすることで編集画面が開きます。

codeblocks0_2.png

64bitの環境の場合に Code::Blocks の動作が不安定になることがあります。 その場合は code completion というプラグインを無効化すると動作することがあります。

「Plugins」>「Manage plugins...」を選択します。

/ja/node/6057/

「code completion」を選択して [Disable] ボタンをクリックします。

/ja/node/6057/

動作しないときはこの手順を試してください。

アクティビティ処理の実装

RobotController コンポーネントでは、コンフィギュレーションパラメーター(speed_x、speed_y)をスライダーで操作しその値を目標速度としてアウトポート(out)から出力します。 インポート(in)から入力された値を変数に格納して、その値が一定以上の場合は停止するようにします。


onActivated()、onExecute()、onDeactivated() での処理内容を下図に示します。

/ja/node/6310/
アクティビティ処理の概要


ヘッダファイル (RobotController.h) の編集

センサー値を一時的に格納する変数 sensor_data を宣言します。

   private:
     bool sensor_data[2];           //センサー値を一時格納する変数

ソースファイル (RobotController.cpp) の編集

下記のように、onActivated()、onDeactivated()、onExecute() を実装します。

 RTC::ReturnCode_t RobotController::onActivated(RTC::UniqueId ec_id)
 {
     //センサー値初期化
     for (int i = 0; i < 2; i++)
     {
         sensor_data[i] = false;
     }
 
     return RTC::RTC_OK;
 }

 RTC::ReturnCode_t RobotController::onDeactivated(RTC::UniqueId ec_id)
 {
          //ロボットを停止する
          m_out.data.vx = 0;
          m_out.data.va = 0;
          m_outOut.write();
  
          return RTC::RTC_OK;
 }

 RTC::ReturnCode_t RobotController::onExecute(RTC::UniqueId ec_id)
 {
     //入力データの存在確認
     if (m_inIn.isNew())
     {
         //入力データ読み込み
         m_inIn.read();
         for (int i = 0; i < m_in.data.length(); i++)
         {
             //入力データ格納
             if (i < 2)
             {
                 sensor_data[i] = m_in.data[i];
             }
         }
     }
 
     //前進するときのみ停止するかを判定
     if (m_speed_x > 0)
     {
         for (int i = 0; i < 2; i++)
         {
             //タッチセンサのオンオフを判定
             if (sensor_data[i] == true)
             {
                 //タッチセンサがオンの場合は停止
                 m_out.data.vx = 0;
                 m_out.data.va = 0;
                 m_outOut.write();
                 return RTC::RTC_OK;
             }
         }
     }
 
     //すべてのタッチセンサがオフの場合はコンフィギュレーションパラメーターの値で操作
     m_out.data.vx = m_speed_x;
     m_out.data.va = m_speed_r;
     m_outOut.write();
  }

Code::Blocks によるビルド

ビルドの実行

Code::Blocksの [ビルド] ボタンをクリックしてビルドを行います。


codeblocks_build_2.png
ビルドの実行


RobotController コンポーネントの動作確認

作成した RobotController をシミュレーターコンポーネントと接続して動作確認を行います。

以下より EV3Simulator コンポーネントをダウンロードしてください。

インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布のUSBメモリーに入れてあります。

NameService の起動

コンポーネントの参照を登録するためのネームサービスを起動します。


 $ rtm-naming

RobotController コンポーネントの起動

RobotController コンポーネントを起動します。

RobotController\build\srcフォルダーの RobotControllerComp ファイルを実行してください。

 $ RobotControllerComp

シミュレーターコンポーネントの起動

EV3SimulatorComp コンポーネントをインストールしたディレクトリーに移動後、下記のコマンドにて起動できます。

 $ src/EV3SimulatorComp

コンポーネントの接続

下図のように、RTSystemEditor にて RobotController コンポーネント、EV3Simulator コンポーネントを接続します。 システムダイアグラムは左上のOpen New System Editorボタンで表示できます。

tutorial_ev3_irex9_2.png
コンポーネントの接続

コンポーネントのActivate

RTSystemEditor の上部にあります [All Activate] というアイコンをクリックし、全てのコンポーネントをアクティブ化します。 正常にアクティベートされた場合、下図のように黄緑色でコンポーネントが表示されます。


tutorial_ev3_irex10.png
コンポーネントのアクティブ化


動作確認

下図のようにコンフィギュレーションビューの [編集] ボタンからコンフィギュレーションを変更することができます。


tutorial_ev3_irex6.png

スライダーを操作してシミュレーター上のEducator Vehicle改の操作ができるかを確認してください。


tutorial_ev3_irex7.png
コンフィギュレーションパラメーターの変更


正常に動作している場合は、開始し位置から直進した場合に壁の前で停止します。


tutorial_ev3_irex18.png


正常に動作していない場合は、壁に接触後にそのまま前進を続けます。


tutorial_ev3_irex17.png


実機での動作確認

講習会で EV3実機を用意している場合は実機での動作確認が可能です。

手順は以下の通りです。

  • Educator Vehicle改の組立て
  • EV3アクセスポイントの起動
  • EV3のアクセスポイントに接続
  • ポートの接続
  • コンポーネントのアクティブ化

Educator Vehicle改の組立て

EV3 は分解した状態で参加者に配ります。 組み立て方は以下の通りです。

ただし、超音波センサー、カラーセンサー、ジャイロセンサーについては、講習で使用しないため取り付ける必要はありません。 以下の※の作業については、時間が余った人が実施してください。

まずは土台部分を取り出してください。


s_DSC00463.JPG

最初にMモーターにケーブル(15cm)を接続します※。


s_DSC00446.JPG

次に EV3 本体を取り付けます。 Mモーターにケーブルを接続した場合は、ケーブルが左側の隙間から出るようにしてください。


s_DSC00448.JPG s_DSC00450.JPG



右側のタッチセンサーを取り付けてください。


s_DSC00451.JPG s_DSC00452.JPG



超音波センサーを取り付けてください※。


s_DSC00454.JPG

ケーブルを接続してください。 必須なのは車輪駆動用のLモーター右、Lモーター左、タッチセンサーだけです。

Lモーター右 ポート C 25cmケーブル
Lモーター左 ポート B 25cmケーブル
Mモーター※ ポートA 25cmケーブル
タッチセンサー右 ポート 3 35cmケーブル
タッチセンサー左 ポート 1 35cmケーブル
超音波センサー※ ポート 4 50cmケーブル
ジャイロセンサー※ ポート 2 25cmケーブル

ケーブルは EV3 の上下に A~D と 1~4 のポートがあるのでそこにケーブルを接続します。


s_DSC00.JPG s_DSC00471.JPG




s_DSC00455.JPG s_DSC00456.JPG



左右にパーツを取り付けます※。 Lモーター右、Lモーター左、Mモーター、タッチセンサー右、タッチセンサー左のケーブルを挟むようにして取り付けてください※。
Lモーター右、タッチセンサー右のケーブルは右側から、Lモーター左、Mモーター、タッチセンサー左は左側から通してください※。


s_DSC00457.JPG


s_DSC00459.JPG

これでとりあえず完成ですが、余裕のある人はジャイロセンサーを取り付けてみてください※。


s_DSC00460.JPG s_DSC00461.JPG



電源の入れ方/切り方

電源の入れ方

中央のボタンを押せば電源が投入されます。


ev3_on.jpg

電源の切り方

EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。


ev3_off.jpg


s_DSC01033.JPG

再起動

再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。

リセット

ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。


ev3_reset.jpg

アクセスポイントの設定

EV3 の操作画面から「File Browser」を上下ボタンで選択して中央のボタンを押してください。

 ------------------------------
 192.168.0.1
 ------------------------------
 [File Browser               > ]
  Device Browser             >
  Wireless and Networks      > 
  Battery                    >
  Open Roberta Lab           >
  About                      >
 ------------------------------

次に scripts を選択して中央ボタンを押してください。

 ------------------------------
 192.168.0.1
 ------------------------------
         File Browser
 ------------------------------
 /home/robot
 ------------------------------
 [scripts                     ]
 ・・
 ・・
 ------------------------------

次の画面から start_ap.sh を選択して中央ボタンを押すとスクリプトが起動します。

 ------------------------------
 192.168.0.1
 ------------------------------
         File Browser
 ------------------------------
 /home/robot/scripts
 ------------------------------
 ../
 Component/
 ・・
 [start_ap.sh                 ]
 ------------------------------

しばらくすると無線LANアクセスポイントが起動するので、指定の SSID のアクセスポイントに接続してください。 SSID、パスワードは EV3 に貼り付けたテープに記載してあります。


tutorial_ev3_irex26.png

アクセスポイントに接続

SSID、パスワードは EV3に貼り付けたシールに記載してあります。

※ネットワークが切り替わった場合にネームサーバーへのコンポーネントの登録やポートの接続が失敗する場合があるのでネームサーバ、コンポーネントを一旦全て終了してください。 ネットワーク切り替え後に起動した場合には問題ないので、終了させる必要はありません。

ネームサーバー追加

続いてRTシステムエディタの [ネームサーバー追加] ボタンで 192.168.0.1 を追加してください。


tutorial_raspimouse0.png tutorial_ev3_irex12.png



するとEducatorVehicle0という RTC が見えるようになります。

ポートの接続

RTシステムエディタで EducatorVehicle、RobotController コンポーネントを以下のように接続します。

tutorial_ev3_irex11.png

アクティブ化

そして RTC をアクティブ化すると EV3の操作ができるようになります。

チュートリアル(EV3、第3部)

このページでは2台のEV3を連携したRTシステムの構築を行います。

1台目のEV3をアクセスポイントとして、ノートPCと2台目のEV3をアクセスポイントに接続します。

※EV3(1台目)は奇数番号のものを配布します。EV3のシールに記載された番号を確認してください。 EV3(2台目)はEV3(1台目)の次の番号のものを配布します。(例:EV3(1台目):7、EV3(2台目):8)


tutorial_ev3_irex23.png

EV3(2台目)の組立て

第二部の手順に従って2台目のEducator Vehicleを組み立ててください。

EV3との接続

ノートPCとEV3(1台目)の接続

第二部の、実機での動作確認まで完了してください。 この時点でノートPCとアクセスポイントのEV3が接続されているはずです。


tutorial_ev3_irex24.png

EV3(1台目)とEV3(2台目)の接続

まずはEV3(2台目)の電源を投入してください。 起動後にEV3(1台目)に自動接続します。 自動接続できた場合は、EV3の画面左上にIPアドレスが表示されます。 IPアドレスは192.168.11.yyyが表示されます。


tutorial_ev3_irex25.png

他のIPアドレスが表示されている場合は、配布したEV3の番号が違う可能性があるため確認してください。

ネームサーバー、RTCの起動

EV3(2台目)の画面上の操作でネームサーバーとRTCを起動します。

EV3 の操作画面から「File Browser」→「scripts」を選択してください。

ネームサーバー、RTCはstart_rtcs.shのスクリプトを実行することで起動します。

 ------------------------------
 192.168.11.yyy
 ------------------------------
         File Browser
 ------------------------------
 /home/robot/scripts
 ------------------------------
 ../
 Component/
 ・・
 [start_rtcs.sh                 ]
 ------------------------------


tutorial_ev3_irex32.png

ネームサーバー追加

RTシステムエディタから、192.168.11.yyyのネームサーバーに接続してください。


tutorial_raspimouse0.png tutorial_ev3_irex22.png



この時点でRTシステムエディタのネームサービスビューにはlocalhost、192.168.0.1、192.168.11.yyyのネームサーバーが登録されています。 192.168.11.yyyのネームサーバーに登録されているRTCの名前はEducatorVehicle1となります。


tutorial_ev3_irex30.png

  • localhost
    • RobotController0
  • 192.168.0.1
    • EducatorVehicle0
  • 192.168.11.yyy
    • EducatorVehicle1

動作確認

EducatorVehicle0(192.168.0.1)とEducatorVehicle1(192.168.11.yyy)をシステムダイアグラム上で接続してください。 EducatorVehicle1の現在の速度出力をEducatorVehicle0の目標速度入力に接続することで、EV3(2台目)の動きにEV3(1台目)が追従するようになります。


tutorial_ev3_irex31.png

RTCをアクティベートして2台目のEducator Vehicleの車輪を転がすと、1台目のEducator Vehicleがそれに合わせて動作します。


tutorial_ev3_irex28.png

自由課題

これで実習は一通り終了ですが、時間が余っている場合は以下のような課題に挑戦してみてください。

  • EV3(2台目)のタッチセンサのオンオフでEV3(1台目)を操作

ジョイスティックコンポーネントはOpenRTM-aist Python版のサンプルにあります(TkJoyStickComp.py)。 TkJoyStickComp.pyのアウトポートのデータ型はTimedFloatSeq型であるため、TimedVelocity2D型に変換するRTCを作成する必要があります。

EducatorVehicleRTCのsoundという名前のインポートに文字列(TimedString型)を入力すると、EV3が発声します。

文字列(const char*)をデータポートで出力する際はCORBA::string_dup関数で文字列をコピーする必要があります。

 m_out.data= CORBA::string_dup("abc");

  • 各種センサの利用(カラーセンサ、超音波センサ、ジャイロセンサ)

組み立て方

このページではレゴマインドストーム EV3 で以下の車輪移動ロボット (Educator Vehicle 改) を組み立てる手順を説明します。



s_DSC00443.JPG


s_DSC00440.JPG


Educator Vehicle との共通部分

車輪移動ロボットの組立て

まずは Educator Vehicleの説明書 の最初の車輪移動ロボットを組み立てる章の45番まで組み立ててください。 ただし8番と20番の作業は必要ないので飛ばしてください。

またジャイロセンサーを取り付ける章(98ページ)を参考にしてジャイロセンサーを取り付けてください。



s_DSC00374.JPG


モーターMの取り付け

モーターMにパーツを取り付けます。 Educator Vehicle の説明書のモーターMを取り付ける章(78ページ)の2~5、10番作業を行ってください。



s_DSC00370.JPG


そして18番の作業を行ってモーターMを移動ロボットに取り付けてください。



s_DSC00375.JPG


タッチセンサーへのパーツ取り付け

タッチセンサーにパーツを取り付けます。 Educator Vehicle の説明書のタッチセンサーを取り付ける章(61ページ)の1~3番の作業を行ってください。



s_DSC00372.JPG


独自部分

ここからの作業に必要な部品は以下の通りです。



s_DSC00369.JPG


土台部分組立て



s_DSC00376.JPG




s_DSC00386.JPG




s_DSC00387.JPG




s_DSC00388.JPG




s_DSC00389.JPG




s_DSC00390.JPG s_DSC00391.JPG





s_DSC00393.JPG s_DSC00394.JPG





s_DSC00395.JPG s_DSC00396.JPG





s_DSC00397.JPG




s_DSC00398.JPG




s_DSC00399.JPG




s_DSC00400.JPG




s_DSC00401.JPG s_DSC00402.JPG



タッチセンサーの取り付け



s_DSC00403.JPG s_DSC00404.JPG





s_DSC00405.JPG




s_DSC00406.JPG




s_DSC00407.JPG




s_DSC00408.JPG


超音波センサーの取り付け



s_DSC00409.JPG




s_DSC00410.JPG




s_DSC00411.JPG




s_DSC00412.JPG




s_DSC00415.JPG




s_DSC00416.JPG




s_DSC00417.JPG




s_DSC00418.JPG




s_DSC00419.JPG




s_DSC00422.JPG




s_DSC00424.JPG




カラーセンサの取り付け

s_DSC00425.JPG




s_DSC00426.JPG




s_DSC00427.JPG




s_DSC00428.JPG


ケーブルの接続

モーター右 ポート C 25cmケーブル
モーター左 ポート B 25cmケーブル
モーター(M) ポートA 25cmケーブル
タッチセンサー右 ポート 3 35cmケーブル
タッチセンサー左 ポート 1 35cmケーブル
超音波センサー ポート 4 50cmケーブル
ジャイロセンサー ポート 2 25cmケーブル

※カラーセンサーを利用する際は超音波センサーかタッチセンサーのケーブルを外して使用してください。



s_DSC00432.JPG




s_DSC00433.JPG




s_DSC00434.JPG