LEGO Mindstorms EV3 は LEGO の Mindstorms シリーズの新しいパッケージです。EV3のメインのコントローラーは、Linux が標準搭載され、様々な言語でロボットの開発が可能になりました。
また、NXT では外部との無線通信が基本的に Bluetooth のみでしたが、EV3 では USBインターフェースが搭載され、無線LAN の USBアダプタを挿すことで無線LANなどで外部と通信することも可能になりました。
搭載される OS が Linux になったことで、これまでよりもさらに柔軟に、かつ高度なロボット開発が可能になりました。
このドキュメントでは、LEGO Mindstorms EV3 上に OpenRTM-aist を搭載し、ロボット制御に活用する方法、コンポーネントの開発方法を紹介します。
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では OpenRTM-aist で RTコンポーネントを開発・実行するための環境構築方法、便利に使うためのノウハウ、移動ロボットの制御や IO の利用方法などを解説します。
このページでは RTM講習会での EV3 操作手順を説明します。
実習では以下の Educator Vehicle 改を制御します。
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 には以下のデバイスが付属しています。
最初にPC側で使用する RTC 等をダウンロードしてください。
ZIPファイルを Lhaplus 等で展開してください。
EV3 は分解した状態で参加者に配ります。 組み立て方は以下の通りです。
※超音波センサー、カラーセンサー、ジャイロセンサーについては、講習で使用しないため取り付ける必要はありません。 以下の※の作業については、時間が余った人が実施してください。
まずは土台部分を取り出してください。
右側のタッチセンサーを取り付けてください。
超音波センサーを取り付けてください※。
Lモーター右 | ポート C | 25cmケーブル |
Lモーター左 | ポート B | 25cmケーブル |
Mモーター※ | ポートA | 25cmケーブル |
タッチセンサー右 | ポート 3 | 35cmケーブル |
タッチセンサー左 | ポート 1 | 35cmケーブル |
超音波センサー※ | ポート 4 | 50cmケーブル |
ジャイロセンサー※ | ポート 2 | 25cmケーブル |
ケーブルは EV3 の上下に A~D と 1~4 のポートがあるのでそこにケーブルを接続します。
左右にパーツを取り付けます※。 Lモーター右、Lモーター左、Mモーター、タッチセンサー右、タッチセンサー左のケーブルを挟むようにして取り付けてください※。
Lモーター右、タッチセンサー右のケーブルは右側から、Lモーター左、Mモーター、タッチセンサー左は左側から通してください※。
中央のボタンを押せば電源が投入されます。
EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。
再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。
ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。
EV3 へは原則として無線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 に貼り付けたテープに記載してあります。
まず右下のネットワークアイコンをクリックしてください。
以下の作業は有線で接続する場合の作業なので、無線で接続する場合は不要です。
付属の USBケーブルで EV3 と PC を接続してください。
ここで EV3 の電源を投入する前に無線LANアダプタは取り外しておいてください。
以下の画面が表示されていれば ev3dev の起動に成功していますが、起動途中で停止した場合は この手順 で再起動してください。
まずはコントロールパネルからデバイスマネージャを開いてください。
このページ の手順に従ってネームサーバー、RTシステムエディタを起動してください。 予めネームサーバーを起動してある場合は再起動してください。
またネットワークインターフェースが2つ以上ある場合に通信に失敗する可能性があるため、有線で接続した場合は他のネットワークデバイスを無効にしてからネームサーバーを起動してください。
続いて RTシステムエディタのネームサーバー追加ボタンで192.168.0.1(無線LANで接続する場合は192.168.11.1)を追加してください。
するとEducatorVehicle0という RTC が見えるようになります。
EducatorVehicle は EV3 の走行速度の入力、センサーのデータの出力等を行うためのコンポーネントです。
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型は以下のように定義されています。
struct Velocity2D { double vx; double vy; double va; };
struct TimedVelocity2D { Time tm; Velocity2D data; };
vx、vy、va はロボット中心座標系での速度を表しています。
Educator Vehicle のように2個の車輪が左右に取り付けられているロボットの場合、横滑りしないと仮定すると vy は0になります。
vx、va を指定することでロボットの操作を行います。
sound による音声の入力には以下のコマンドを利用できます。
tone,100,1000
LCD で表示する画像は付属資料の software/saveBinaryImage/EXE/saveBinaryImage.exeで変換したものを利用してください。
画像ファイルを saveBinaryImage.exe にドラッグ・アンド・ドロップすれば変換できます。
付属資料のstart_component_ev3.batを起動してください。 ※OpenRTM-aist Python版をインストールしていない場合、もしくはインストールに失敗している場合は個別に実行ファイル入りのUSBメモリーを配布いたしますので、その中のstart_component_ev3_exe.batを利用してください。
すると以下の2つの RTC が起動します。
まずはジョイスティックで EV3 を操作してみます。
RTシステムエディタで EducatorVehicle、FloatSeqToVelocity、TkJoyStick を以下のように接続します。
まずは FloatSeqToVelocity の out と EducatorVehicle の target_velocity_in のコネクタを切断してください。
FloatSeqToVelocity と EducatorVehicle の間に自作の RTC を接続して、タッチセンサーがオンになった場合に停止して音を鳴らすようにします。
RTC ビルダを起動してください。
以下のように設定を行ってください。 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 |
[コード生成] ボタンを押したらコードが生成されます。
コードが生成できたら C++ の場合は CMake で Visual Studio のプロジェクト(Ubuntu の場合は Code::Blocks)を生成してください。
まず CMake (cmake-gui) を起動します。
Where is the source code | RTCBuilder で生成したコードのフォルダー(C:\workspace\TestEV3CPP) |
Where to build the binaries | RTCBuilder で生成したコードのフォルダーの下に作成したbuildフォルダー(C:\workspace\TestEV3CPP\build) |
build ディレクトリーの TestEV3CPP.sln を開いてください。
次にコードの編集を行います。
Pythonの場合はまず変数の初期化部分を修正してください。
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関数を呼び出すとデータが送信されます。
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の場合は以下のようになります。
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 に記述します。
private: bool m_last_sensor_data[2];
Pythonの場合はコンストラクタに記述します。
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 以上の場合には前進しているため障害物に接触するかもしれないと判定して、タッチセンサーがオンの場合は停止してブザーを鳴らします。
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の場合は以下のようになっています。
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)を以下のように接続してください。
RTシステムを保存する場合は System Diagram 上で右クリックして Save As... を選択してください。
復元する場合は Open and Restore を選択して、先ほど保存したファイルを選択してください。
RTC を終了する場合は RTシステムエディタ上で RTC を exit してください。
EV3 のボタン操作で File Brower を選択すると/home/robot以下のディレクトリーの操作ができます。
scripts フォルダー内のシェルスクリプトを実行することで以下の操作ができます。
スクリプトファイル名 | 内容 |
run_rtcs.sh | RTC を起動する |
stop_rtcs.sh | RTC を終了する |
ここでは、LEGO Mindstorms EV3 上で OpenRTM-aist とそのコンポーネントを動作させるための実行環境のインストールについて説明します。
ここでは、openrtm.org が提供する OpenRTM-aist 入りの OSイメージをダウンロードし、各種セットアップについて説明します。 EV3上で OpenRTM を使用できるようにするまでの大まかな手順は以下の通りです。
EV3 には micro SD カードスロットが一つあり、ここに起動した OS を書き込んだ micro SD カードを差し込むと、任意の OS を起動することができます。
用意する SDカードは 2GB以上 32GB以下のも micro SDカード になります。mini SD や SDカードは刺さりませんのでご注意ください。 また、書き込むイメージは約2GB程度ありますので、最低で2GBの容量が必要となります。EV3 は 32GBより大きい SDXC仕様の SDカードには対応していませんので、注意してください。
EV3上 での OpenRTM-aist の実行には ev3dev という OS を使用します。
以下のサイトから ev3-ev3dev-jessie-2015-12-30.img.zip をダウンロードしてください。 名前が似たファイルが多数配布されているので間違えないようにしてください。
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位のファイルが展開されているはずです。
ファイルを右クリックして「すべて展開」を選択すると、展開できます。
$ 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 では 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」ボタンをクリックします。
以上で SD カードの準備は終了です。 書き込みが終了したら、SD カードを Raspberry Pi に設置し、電源を投入します。
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 コマンドでアンマウントします。)
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 も Linuxと同様 dd コマンドを利用して書き込みます。 ただし、Mac では SDカードを挿入すると自動的にマウントされてしまい、マウント中は dd コマンドで SDカードに書き込むことができないので、アンマウント (OSから取り外す) する必要があります。
SDカードを差し込むとFinderに図のように 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 を覚えておきます。
$ 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 は単3電池6本、または専用のバッテリーパックで動作します。単3電池6本、もしくは専用のバッテリーをセットしてください。
USB接続の無線LANインターフェースをを用意します。EV3 は PCと有線接続して、PC経由でインターネットに接続することもできますが、ここでは無線LAN接続を前提として説明します。
最近の無線LANドングルであれば、大抵のものが使用可能なはずですが、一例として以下の無線LANドングルは動作確認ができています。
その他の接続方法に関しては、ev3dev の Webページをご覧ください。
無線LANドングルと共に、EV3 のコントローラの側面に ev3dev イメージを書き込んだ SDカードを以下のように挿入してください。
SDカードを挿入し、電源ボタン(十字キーボタンの中央の濃いグレーのボタン)を押して EV3 に電源を投入すると、以下のような起動画面が表示され、十字キーのあたりの LED が点滅します。
暫く(1分前後)して起動が完了すると、以下のような初期画面が表示されます。
起動直後の 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 > --------------------------
無線LANが何らかの理由で使用できない場合は USBケーブルで接続することもできます。
EV3 と PCを付属の USBケーブルで接続してください。
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:~#
Windows から EV3 に ssh 経由でログインするためには、ssh クライアントをインストールする必要があります。 Windows で利用可能なクライアントは多数ありますが、ここでは Tera Term を紹介します。
こちらから、TeraTerm をダウンロード、インストールしてください。
TeraTerm をインストール後、起動すると接続ダイアログが現れるので、先ほど設定したホスト名+.local を「ホスト」のテキストボックスに入力しOKを押します。
上記で行ったEV3 の無線LAN設定は、再起動すると消えてしまいます。起動後に自動で無線LAN に接続するためには、EV3 にログインして無線LANの接続設定を行う必要があります。
次に、無線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
Linux ホストから EV3 へアクセスする場合、avahiというサービスをインストールする必要があります。 最近のLinuxディストリビューションでは、たいていデフォルトでこのサービスがインストールされていますが、もしインストールされていない場合は、以下のように avahi デーモンをインストールします。(debian系のディストリビューションの場合)
$ sudo apt-get update $ sudo apt-get install avahi-daemon
EV に対して ping を打ってみます。ホスト名の後に .local を付けた名前を使います。
$ ping ev3dev.local
これで ping が返ってくれば、avahi がほぼ正しく設定されていることになります。
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 がうまく機能しないことがあります。 その場合、UDPポート5353を開放するかファイヤウォールをOFFにしてください。
上述のリンクから ev3dev のイメージで EV3 を起動した場合、すでに OpenRTM-aist (C++、Python版) がインストールされています。 その場合は、以下の OpenRTM-aist のインストールはスキップして、サンプルコンポーネントの実行から進めてください。
自分で ev3dev.org からイメージをダウンロードした場合は、OpenRTM-aist のパッケージを apt-get 等でインストールします。
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
以上で、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
パッケージのインストールにもかなりの時間がかかりますので気長に待ちます。途中でバッテリーが切れないように、アダプタに接続したまま作業することをお勧めします。
C++のサンプルコンポーネントを動作させて、OpenRTM-aistが正しくインストールできているかどうかを確認します。
EV3上で ConsoleIn を実行したうえで、PC上で ConsoleOut を実行して相互に接続し、PCから入力した数字が EV3上で表示できるかどうかを確認してみます。
まず、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 -------------------------------------------------
PC上で ConsoleOut を起動します。Windowsであれば、ネームサーバ、RTSystemEditor、ConsoleIn をそれぞれ以下のように起動します。
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 します。
ConsoleIn の方から数値を入力し、ConsoleOut の方で表示されれば、テストは成功です。
今度は、上記とは逆に、ConsoleIn を PC で、ConsoleOut を EV3 上で実行し接続してみます。
PC上では、以下のように ConsoleOut を起動します。。
次に、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 ------------------------------
RTSystemEditor上で、ConsoleIn と ConsoleOut を接続し、Activate します。 ConsoleIn側で数値を入力し、ConsoleOut側で表示されれば、テストは成功です。
その他の組み合わせとして、C++ と Python のコンポーネントを起動して接続してみる、他のサンプルコンポーネントを起動して通信させてみるなど試してみてください。
EV3 および ev3dev 上で動作するコンポーネントを開発するには、EV3上で開発する方法と、クロス開発環境で開発する方法があります。
ただし、EV3 はメモリが64MB、CPUクロックが300MHz程度と、今どきの開発環境としてはだいぶ遅いマシンですので、EV3上での開発はかなり大変です。
クロス開発というのは、異なるアーキテクチャ、つまり一般的な PCのアーキテクチャである Intel 系の CPU上で、ARM などの異なる種類で動作する実行ファイルを作成することです。
クロス開発では、コンパイル即実行という形はとれませんが、コンパイル時間が圧倒的に速いので、結果として開発効率は高くなります。
開発環境は Linux のディストリビューションの1つである Ubuntu (14.04 LTS) を使用します。
こちらの URL から ISOイメージをダウンロードして OS をインストールしてください。
PC のそのままインストールして使用することもできますし、バーチャルマシンとしてインストールして使用しても構いません。
バーチャルマシン環境としては、主に以下のようなものがあります。
これらの詳細な使用方法については、それぞれの Webサイトもしくは、解説の Webページを検索してみてください。
ここからは、Ubuntu14.04 がインストールされたものとして、話を進めます。 まず、brickstrap というツールをインストールします。brickstrap は上述の ev3dev の OSイメージを作成するためのツールですが、クロス開発を行うためのツールとしても利用可能です。
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 を起動できます。
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 を自分でコンパイル・インストールする場合には、以下の手順に従ってください。ビルド済みのパッケージを利用する場合は、次の章へ移動してください。
まず、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 を自分でソースからインストールせずに、事前にコンパイル済みのパッケージをインストールしても構いません。 ev3dev に OpenRTM-aist をインストールする方法について述べた、上述の方法とほぼ同様です。
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
以上で、openrtm.org のパッケージリポジトリにアクセスできるようになりましたので、以下のようにしてパッケージをインストールします。
# apt-get install openrtm-aist openrtm-aist-dev openrtm-aist-example # apt-get install openrtm-aist-python openrtm-aist-python-example
LEGO Mindstorms EV3 には標準で、以下のようなモーター・センサーが付属しています。
センサー類は、プッシュスイッチは ON/OFF 値を取得可能で、超音波センサー、ジャイロセンサーは連続値を出力可能、カラーセンサーはいくつかの色を認識することもできます。 モーターは2種類(L、M)あり、それぞれ PWM(トルク)制御、速度制御、位置制御が可能で、これらの制御のゲイン等も変更できます。 以下に、EV3 のセンサーとモーターの使用を表示します。
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 |
コマンドラインからは以上のようにアクセスできますが、プログラムからこれらの操作をしようとすると非常に面倒な手続きが必要になります。
プログラムからデバイスにアクセスためのアクセスライブラリがありますので、これを利用します。
ev3dev-lang は EV3 のモーターやセンサーにアクセスするためのライブラリです。以下の4つの言語で利用することができます。
ここでは、Python と C++ でのアクセス例を示します。
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 をインタラクティブモードで起動します。
# 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 では、モジュールやオブジェクトに対して 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-lang には C++ や Python、Lua などの EV3 デバイスへのバインディングライブラリが含まれています。 以下では、C++ から利用できる、ev3dev バインディングの導入と使い方について説明します。
以下の作業は、クロス開発環境にて行います。既に、上述の方法でクロス開発環境が導入済みであるとして進めます。
まず、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
次に、コンパイルを行います。まず、作業ディレクトリー 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 で 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 の標準セットを購入すると、移動ロボット (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 を指定することになる。
さて、車輪の角速度を , として、車輪の半径を r とすると、各車輪の接地点での速度 v_r、v_l はそれぞれ
となる。また、回転中心からロボット中心の距離を ρ とすると、以下の式が成り立つ。
一方、中心から車輪までの距離(トレッドの1/2)を d とすると、
となる。以上の式から、速度指令(v_x、v_y、v_a)の時に実際に与えるべき左右のモーターの角速度は以下の通りになります。
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) |
なので、
となる。
次に、ロボットの自己位置同定の方法について考えます。 ロボットの移動速度・角速度を積分することで任意の時点の位置・姿勢を得ることができます。速度 v_x、角速度 v_a とすると、(x、y、θ) の微小変位と v_x、v_a との関係を直線近似すると、
となる。(より厳密には円弧近似する方法もあるが、ここでは簡単に直線近似とした。) これを実際のロボット制御時に、計算機上で求める場合、サンプリング周期 Δt [s] として、
のように求められる。
作成する 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] |
速度を制御するためには以下のデバイスファイルに"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()
ev3dev::color_sensor cs = ev3dev::color_sensor(); std::cout << cs.reflected_light_intensity() << std::endl;
cs = ev3.ColorSensor() print cs.reflected_light_intensity()
ev3dev::touch_sensor ts = ev3dev::touch_sensor(); std::cout << ts.is_pressed() << std::endl;
cs = ev3.ColorSensor() print cs.reflected_light_intensity()
ev3dev::gyro_sensor gs = ev3dev::gyro_sensor(); std::cout << gs.angle() << std::endl;
gs = ev3.GyroSensor() print gs.angle()
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; }
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 のインストール方法について説明します。
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の速度 |
touch で入力したデータの0番目が右側(3番ポート)のタッチセンサー、1番目が左側(1番ポート)のタッチセンサーに対応しています。
sound による音声の入力には以下のコマンドを利用できます。
tone,100,1000
画像ファイルを saveBinaryImage.exe にドラッグ・アンド・ドロップすれば変換できます。
LDC で表示する画像データは、以下のコンポーネントで画像データの変換を行えば入力可能です。 Windows で使用する場合は、release フォルダーの ImageConversionLCDComp.exe で起動できます。
ImageConversionLCD | ||
InPort | ||
名前 | データ型 | 説明 |
out | RTC::CameraImage | 変換前の画像データ |
OutPort | ||
名前 | データ型 | 説明 |
out | RTC::CameraImage | 変換後の画像データ |
例えば、OpenRTM-aist 付属のサンプルコンポーネント OpenCVCamera と接続すれば、EV3 にカメラ画像を表示させることができます。
あるいは、指定の画像を入力するということもできます。
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の動作範囲 |
タッチセンサーがオンになった場合、まず③のように back_speed で指定した速さで back_time で指定した時間だけ後退します。 そして④のように rotate_speed で指定した角速度で rotate_time で指定した時間だけ回転します。 回転する方向はオンになったタッチセンサーと逆方向です。
超音波センサーで地面までの距離を計測して停止、超音波センサーを回転させて走行可能な地面を探索する操作を実行するためには、EV3 の Education Vehicle を組み立ててさらに超音波センサーを回転させるように取り付ける必要があります。
動作手順は以下のようになっています。
机の上などを走行している場合で、②のようぬ机の端まで移動したとします。 超音波センサーで計測した距離が 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システムの一部で以下の RTC を使用するためインストールしてください。
ジョイスティックで操作するためのRTCです。 以下のサイトからインストーラーをダウンロードして実行してください。
DirectInputRTC のアウトポートからの pos からの出力 (TimedLongSeq型) を TimedVelocity2D型に変換する RTC です。 以下のサイトからインストーラーをダウンロードして実行してください。
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座標に対する直進速度 |
RTC の起動、RTシステムの復元を自動化するためのスクリプトファイルです。 ここ からダウンロードしてください。
まず最初に Windows でネームサーバー、RTシステムエディタを起動してください。 詳しい手順は このページ を参考にしてください。
EV3 の 一括インストールの項目 でダウンロードしたファイルの中に rtc.conf があるので、rtc.conf の以下の ppp.pp.pp.ppp の部分を Windows側の IPアドレスに変更してください。
corba.nameservers: ppp.pp.pp.ppp
これで起動したコンポーネントが Windows のネームサーバーに登録されるようになります。
Windows で IPアドレスを確認するには以下のコマンドを入力します。
ipconfig
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 は起動できません。お手数ですが このページ の手順を参考にして手動で起動してください。
一括インストールの項目 でダウンロードしたフォルダーの中の start_rtc.sh を実行することで起動できます。
cd RaspberryPiMouseRTSystem_script_Raspbian sh start_rtc.sh
これで以下の RTC が起動します。
ControlEducatorVehicle0 EducatorVehicle0
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 | ポートの切断 |
このサンプルはゲームパッドのアナログスティックで傾けた方向に Educator Vehicle を操作する RTシステムです。 Windows側の PC にゲームパッドを接続してから起動してください。
このサンプルは OpenRTM-aist-Python のサンプルコンポーネント TkJoyStick で傾けた方向に Educator Vehicle を操作する RTシステムです。
このサンプルはゲームパッドのアナログスティックで傾けた方向に Educator Vehicle を操作することに加えて、タッチセンサー、超音波センサー、カラーセンサーを利用した制御 を行う RTシステムです。
このサンプルは OpenRTM-aist-Python のサンプルコンポーネント TkJoyStick で傾けた方向に Educator Vehicle を操作することに加えて、タッチセンサー、超音波センサー、カラーセンサーを利用した制御 を行う RTシステムです。
新規作成した 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
EV3SampleCPPComp&
python EV3SamplePy.py&
※Windows上で RTC を起動する場合は EV3SampleCPPComp.exe (EV3SamplePy.py) をダブルクリックしてください。
次に EducatorVehicle を起動させます。 以下のコマンドで起動してください。
Compomnents/EducatorVehicleComp&
まずは動作確認のためにデータポートの接続を行います。 Windows側で RTシステムエディタを起動してください。 最初に EV3 で起動しているネームサーバーを RTシステムエディタのビューに追加します。 ネームサーバー追加ボタンを押下して EV3 の IPアドレスを入力してください。
ネームサーバーを追加したらデータポートを以下のように接続してください。
ポートの接続 | |
EV3SampleCPP0(EV3SamplePy0) | EducatorVehicle0 |
target_velocity | velocity2D |
touch | touch |
sound | sound |
そして RTC をアクティブ化すると動作を開始します。
まずは EV3SampleCPP(EV3SamplePy) のコンフィギュレーションパラメーターを変更する事で Educator Vehicle を操作してみます。
RTシステムエディタで EV3SampleCPP0(EV3SamplePy0) を選択して、Configuration View の編集を選択してください。
すると以下のウインドウが起動します。
forward_velocity と rotate_velocity のスライダーによりEV3を操作できます。
次にタッチセンサーがオンになった場合に停止するかを確認してみます。 タッチセンサーに物体を接触させて停止するかを確認してください。 停止した時に音が鳴るかも確認してください。
ここからはさらにタッチセンサーがオンになった場合に後退→回転のより障害物を回避する動作を実装します。 タッチセンサーのデータが入力された時に以下の処理を実行することで回避運動を行います。
新たに以下のコンフィギュレーションパラメーターを設定します。
コンフィギュレーション | ||
名前 | 型 | 説明 |
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関数は以下のようになっています。 目標速度を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 関数は以下のようになっています。 後退するための速度を出力後、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システムエディタ等による操作ができなくなるためあまり望ましい実装の方法ではありません。 ただ今回の場合は実行コンテキストを止めずに処理を実装すると処理が複雑化するためこのように実装しています。
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(); }
最後にフローチャートのように、タッチセンサーのデータ入力時に回避運動を行う処理を実装すれば完成です。
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 を作成します。
超音波センサーで検知した地面までの高さが一定以上の場合に、以下の処理を実行します。
以下のデータポート、コンフィギュレーションパラメーターを追加してください。
データポート | ||
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 関数を以下のように実装します。
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システムエディタ上でもできるのですが、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 をアクセスポイント化するまでの手順を説明します。
Raspberry Pi とほとんど手順は同じなので、詳しいことは以下のサイトなどを参考にしてください。
無線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
/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 をインストールしてください。
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 サーバーをインストールします。
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 は Pitsco Education が販売している LEGO Mindstroms の拡張製品です。 アルミ製フレーム、高トルクのモーター等がセットに含まれており、本格的なロボットの製作が可能になります。
電圧 | 12V |
静止トルク | 2.1N・m |
回転数 | 152rpm |
名前 | HS-485HB(HITEC) |
電圧 | 6V |
静止トルク | 0.59N・m |
回転数 | 56rpm |
TETRIX ベースセットには DCモータードライバ (DC Motor Controller for TETRIX)、RCサーボドライバ (Servo Controller for TETRIX) が付属しています。
これらのモータードライバと EV3 を接続することで DCモーター及び RCサーボの制御が可能になります。
以下のように接続してください。
接続してモータードライバの電源が ON の状態で EV3 の電源を投入してください。
EV3 とモータードライバの通信は I2C により行います。
接続に成功している場合、/dev以下にi2c-3、i2c-4、i2c-5、i2c-6 のいずれかのデバイスファイルが追加されているはずです。 後ろの値がポート番号に2を足した値になっています。例えばポート1に接続した場合は i2c-3 になります。 以下で ev3dev上で C++、及び Python によるモータードライバの制御方法について述べます。
まずは I2C 通信に必要なファイルをインクルードしてください。
#include <fcntl.h> #include <sys/ioctl.h> #include <linux/i2c-dev.h>
import smbus
I2C の通信を開始します。
int fd; = open("/dev/i2c-3", O_RDWR);
sm = smbus.SMBus(3)
モータードライバのアドレスは 0x01 に設定されますが、デイジーチェインで接続した場合 0x02~0x08 に設定されます。 上記の接続の場合、DCモータードライバは 0x01 で RCサーボドライバは 0x02 に設定されているはずです。 まずは DCモータードライバを操作してみます。
制御モードを設定します。 モーター1 は 0x44、モーター2 は 0x47 のレジスタに以下の値を書き込むことで制御モードが設定可能です。 ※TETRIX ベースセットにはエンコーダーは付属していないので速度制御、位置制御モードを使用する場合は別途購入する必要があります。
入力値 | 制御モード |
0b00 | PWM |
0b01 | 速度制御 |
0b10 | 位置制御 |
0b11 | エンコーダーリセット |
PWM モードに設定します。
ioctl(fd, I2C_SLAVE, 0x01) unsigned char buf[2] = {0x44, 0x00}; write(fd, buf, 2);
sm.write_i2c_block_data(0x01, 0x44, [0x00])
最後に PWM の幅を設定します。 モーター1は 0x45、モーター2 は 0x46 のレジスタに書き込むことにより設定可能です。 PWM は正回転するばあいは 1~127 の値、逆回転する場合は -127~-1 の値で設定できます。 ただし、0 の場合はフロートモードで停止、128 の場合はブレーキモードで停止します。
unsigned char buf[2] = {0x45, 0x30}; write(fd, buf, 2);
sm.write_i2c_block_data(0x01, 0x45, [0x30])
RCサーボドライバは最大6個の RCサーボを制御可能であり、0x42~0x47 のレジスタに目標角度を書き込むことで制御できます。 パルス幅は 0.75ms~2.25ms で設定可能です。
ioctl(fd, I2C_SLAVE, 0x02) unsigned char buf[2] = {0x42, 0x60}; write(fd, buf, 2);
sm.write_i2c_block_data(0x02, 0x42, [0x60])
以下は DCモーターを利用した乗り物の作成例です。
取っ手部分にLモーターが2個取り付けられており、Lモーターを回転させることで車体の制御が可能になっています。
使用した RTC は以下の通りです。
上記の乗り物を制御するためのコンポーネントです。
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 | ギア比 |
Lモーターの角度から車体の目標速度を出力するコンポーネントです。
TetrixVehicle | ||
OutPort | ||
名前 | データ型 | 説明 |
out | RTC::TimedVelocity2D | 目標速度 |
コンフィギュレーションパラメーター | ||
名前 | デフォルト値 | 説明 |
rotation_by_angle | -0.6 | 根元のモーターの角度に対する目標角速度の変化量 |
velocity_by_angle | -0.1 | 先端のモーターの角度に対する目標速度の変化量 |
このページでは Educator Vehicle 改 のシミュレーター RTC の仕様、利用方法について説明します。
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 |
ブロックは何個でも設定可能です。
Educator Vehicle 改 は超音波センサーにより設置可能な地面の有無を検知して回避する運動が可能になっています。 この制御シミュレーションのために、地面を新たに作成するコンフィギュレーションパラメーターを用意してあります。
plane_existを1に設定後、地面の位置、サイズを設定してください。
このページではシミュレーター上の Educator Vehicleを操作するためのコンポーネントの作成手順を説明します。 Educator VehicleはレゴマインドストームEV3の組み立て例の一つです。
まずは資料をダウンロードしてください。
ZIPファイルは Lhaplus 等で展開してください。
インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布のUSBメモリーに入れてあります。
付属のシミュレータで以下の Educator Vehicle 改のシミュレーションができます。
Lモーター、Mモーターの制御だけではなく、タッチセンサー、ジャイロセンサー、超音波センサーのシミュレーションも可能になっています。
EV3Simulator コンポーネントと接続してシミュレーター上のロボットを操作するためのコンポーネントです。
GUI(スライダー)によりシミュレーター上のロボットの操作を行い、タッチセンサーがオンの時には自動的に停止するコンポーネントの作成を行います。
作成手順は以下の通りです。
以下の環境を想定しています。
RobotController は目標速度を出力するアウトポート、センサー値を入力するインポート、目標速度を設定するコンフィギュレーションパラメーターを持っています。
コンポーネント名称 | RobotController |
InPort | |
ポート名 | in |
型 | TimedBooleanSeq |
説明 | センサー値 |
OutPort | |
ポート名 | out |
型 | TimedVelocity2D |
説明 | 目標速度 |
Configuration | |
パラメーター名 | speed_x |
型 | double |
デフォルト値 | 0.0 |
制約 | -1.5<x<1.5 |
Widget | slider |
Step | 0.01 |
説明 | 直進速度の設定 |
Configuration | |
パラメーター名 | speed_r |
型 | double |
デフォルト値 | 0.0 |
制約 | -2.0<x<2.0 |
Widget | slider |
Step | 0.01 |
説明 | 回転速度の設定 |
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が格納できます。
vx、vy、vaはロボット中心座標系での速度を表しています。
Educator Vehicle改のように2個の車輪が左右に取り付けられているロボットの場合、横滑りしないと仮定するとvyは0になります。
直進速度vx、回転速度vaを指定することでロボットの操作を行います。
RobotController コンポーネントのひな型コードの生成は、RTCBuilder を用いて行います。
Eclipse では、各種作業を行うフォルダーを「ワークスペース」(Work Space)とよび、原則としてすべての生成物はこのフォルダーの下に保存されます。 ワークスペースはアクセスできるフォルダーであれば、どこに作っても構いませんが、このチュートリアルでは以下のワークスペースを仮定します。
まずは Eclipse を起動します。 Windows 8.1の場合は「スタート」>「アプリビュー(右下矢印)」>「OpenRTM-aist 1.1.2」>「OpenRTP」をクリックすると起動できます。
最初にワークスペースの場所を尋ねられますので、上記のワークスペースを指定してください。
すると、以下のようなWelcomeページが表示されます。
Welcomeページはいまは必要ないので左上の「×」ボタンをクリックして閉じてください。
右上の [Open Perspective] ボタンをクリックしてください。
「RTC Builder」を選択することで、RTCBuilder が起動します。メニューバーに「カナヅチとRT」の RTCBuilder のアイコンが表示されます。
RobotController コンポーネントを作成するために、RTC Builder で新規プロジェクトを作成する必要があります。
左上の [Open New RTCBuilder Editor] のアイコンをクリックしてください。
「プロジェクト名」欄に作成するプロジェクト名 (ここでは RobotController) を入力して [終了] ボタンをクリックします。
指定した名称のプロジェクトが生成され、パッケージエクスプローラ内に追加されます。
生成したプロジェクト内には、デフォルト値が設定された RTC プロファイル XML(RTC.xml) が自動的に生成されます。
RTC.xml が生成された時点で、このプロジェクトに関連付けられているワークスペースとして RTCBuilder のエディタが開くはずです。 もし起動しない場合はパッケージエクスプローラーの RTC.xml をダブルクリックしてください。
まず、いちばん左の「基本」タブを選択し、基本情報を入力します。先ほど決めた RobotController コンポーネントの仕様(名前)の他に、概要やバージョン等を入力してください。 ラベルが赤字の項目は必須項目です。その他はデフォルトで構いません。
次に、「アクティビティ」タブを選択し、使用するアクションコールバックを指定します。
RobotController コンポーネントでは、onActivated()、onDeactivated()、onExecute() コールバックを使用します。下図のように①の onAtivated をクリック後に②のラジオボタンにて [ON] にチェックを入れます。 onDeactivated、onExecute についても同様の手順を行います。
さらに、「データポート」タブを選択し、データポートの情報を入力します。 先ほど決めた仕様を元に以下のように入力します。なお、変数名や表示位置はオプションで、そのままで結構です。
次に、「コンフィギュレーション」タブを選択し、先ほど決めた仕様を元に、Configuration の情報を入力します。 制約条件および Widget とは、RTSystemEditor でコンポーネントのコンフィギュレーションパラメーターを表示する際に、スライダー、スピンボタン、ラジオボタンなど、GUI で値の変更を行うためのものです。
直進速度 speed_x、回転速度 speed_r はスライダーのより操作できるようにします。
次に、「言語・環境」タブを選択し、プログラミング言語を選択します。 ここでは、C++(言語)を選択します。なお、言語・環境はデフォルト等が設定されておらず、指定し忘れるとコード生成時にエラーになりますので、必ず言語の指定を行うようにしてください。
最後に、「基本」タブにあ [コード生成] ボタンをクリックし、コンポーネントのひな型コードを生成します。
※ 生成されるコード群は、eclipse 起動時に指定したワークスペースフォルダーの中に生成されます。現在のワークスペースは、[ファイル] > [ワークスペースの切り替え..]で確認することができます。
RTC Builder で生成したコードの中には CMake でビルドに必要な各種ファイルを生成するための CMakeLists.txt が含まれています。 CMake を利用することにより CMakeLists.txt からVisual Studio のプロジェクトファイル、ソリューションファイル、もしくは Makefile 等を自動生成できます。
CMake を利用してビルド環境の Configure を行います。 まずは CMake(cmake-gui) を起動してください。「スタート」>「アプリビュー(右下矢印)」>「CMake 3.7.2」>「CMake (cmake-gui)」をクリックすると起動できます。
画面上部に以下のようなテキストボックスがありますので、それぞれソースコードの場所 (CMakeList.txtがある場所) と、ビルドディレクトリーを指定します。
ソースコードの場所は 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を選択してください。
ダイアログで [Finish] ボタンをクリックすると Configure が始まります。 問題がなければ下部のログウインドウに「Configuring done」と出力されますので、続けて [Generate] ボタンをクリックします。 「Generating done」と出ればプロジェクトファイル・ソリューションファイル等の出力が完了します。
なお、CMake は Configure の段階でキャッシュファイルを生成しますので、トラブルなどで設定を変更したり環境を変更した場合は [File] > [Delete Cache] でキャッシュを削除して Configure からやり直してください。
次に先ほど指定した build ディレクトリーの中の RobotController.sln をダブルクリックして Visual Studio を起動します。
※cmake-gui の新しいバージョンでは cmake-gui 上のボタンをクリックすることで起動できます。
RobotController コンポーネントでは、コンフィギュレーションパラメーター(speed_x、speed_y)をスライダーで操作しその値を目標速度としてアウトポート(out)から出力します。 インポート(in) から入力された値を変数に格納して、その値が一定以上の場合は停止するようにします。
onActivated()、onExecute()、onDeactivated() での処理内容を下図に示します。
センサー値を一時的に格納する変数 sensor_data を宣言します。
private: bool sensor_data[2]; //センサー値を一時格納する変数
下記のように、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(); return RTC::RTC_OK; }
Visual Studioの [ビルド] >「ソリューションのビルド」を選択してビルドを行います。
作成した RobotController をシミュレーターコンポーネントと接続して動作確認を行います。
以下より EV3Simulator コンポーネントをダウンロードしてください。
ZIPファイルは Lhaplus 等で展開してください。
インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布のUSBメモリーに入れてあります。
OpenRTPのパースペクティブを開くのウインドウからRT System Editorを選択して起動します。
コンポーネントの参照を登録するためのネームサービスを起動します。
RT System Editorのネームサービス起動ボタンを押すと起動します。
※ 「Start Naming Service」をクリックしても omniNames が起動されない場合は、フルコンピュータ名が14文字以内に設定されているかを確認してください。
RobotController コンポーネントを起動します。
RobotController\build\src\Debug(もしくは、Release)フォルダーの RobotControllerComp.exe ファイルを実行してください。
このコンポーネントは先ほどダウンロードしたファイル(RTM_Tutorial_iREX2017.zip)を展開したフォルダーの EXE/EV3SimulatorComp.exe を実行すると起動します。
下図のように、RTSystemEditor にて RobotController コンポーネント、EV3Simulator コンポーネントを接続します。 システムダイアグラムは左上のOpen New System Editorボタンで表示できます。
RTSystemEditor の上部にあります [All Activate] というアイコンをクリックし、全てのコンポーネントをアクティブ化します。 正常にアクティベートされた場合、下図のように黄緑色でコンポーネントが表示されます。
下図のようにコンフィギュレーションビューの [編集] ボタンからコンフィギュレーションを変更することができます。
正常に動作している場合は、開始し位置から直進した場合に壁の前で停止します。
正常に動作していない場合は、壁に接触後にそのまま前進を続けます。
講習会で EV3実機を用意している場合は実機での動作確認が可能です。
手順は以下の通りです。
EV3 は分解した状態で参加者に配ります。 組み立て方は以下の通りです。
ただし、Mモーター、超音波センサー、カラーセンサー、ジャイロセンサーについては、講習で使用しないため取り付ける必要はありません。 以下の※の作業については、時間が余った人が実施してください。
まずは土台部分を取り出してください。
右側のタッチセンサーを取り付けてください。
超音波センサーを取り付けてください※。
Lモーター右 | ポート C | 25cmケーブル |
Lモーター左 | ポート B | 25cmケーブル |
Mモーター※ | ポートA | 25cmケーブル |
タッチセンサー右 | ポート 3 | 35cmケーブル |
タッチセンサー左 | ポート 1 | 35cmケーブル |
超音波センサー※ | ポート 4 | 50cmケーブル |
ジャイロセンサー※ | ポート 2 | 25cmケーブル |
ケーブルは EV3 の上下に A~D と 1~4 のポートがあるのでそこにケーブルを接続します。
左右にパーツを取り付けます※。 Lモーター右、Lモーター左、Mモーター、タッチセンサー右、タッチセンサー左のケーブルを挟むようにして取り付けてください※。
Lモーター右、タッチセンサー右のケーブルは右側から、Lモーター左、Mモーター、タッチセンサー左は左側から通してください※。
中央のボタンを押せば電源が投入されます。
EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。
再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。
ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。
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 に貼り付けたテープに記載してあります。
アクセスポイントへの接続方法は以下のページを参考にしてください。
SSID、パスワードは EV3に貼り付けたシールに記載してあります。
まず右下のネットワークアイコンをクリックしてください。
OpenRTPを終了するには右上の×を押して終了してください。システムダイアグラムを保存するかどうか聞かれますが、Don't Saveを選択してください。
OpenRTPをデスクトップのショートカットをダブルクリックして起動してください。
RT System Editor上でネームサーバーを再起動するには「ネームサービスを起動」ボタンを再度クリックします。
続いてRTシステムエディタの [ネームサーバー追加] ボタンで 192.168.0.1 を追加してください。
するとEducatorVehicle0という RTC が見えるようになります。
RTシステムエディタで EducatorVehicle、RobotController コンポーネントを以下のように接続します。
そして RTC をアクティブ化すると EV3の操作ができるようになります。
このページではシミュレーター上の Educator Vehicleを操作するためのコンポーネントの作成手順を説明します。 Educator VehicleはレゴマインドストームEV3の組み立て例の一つです。
まずは資料をダウンロードしてください。
付属のシミュレータで以下の Educator Vehicle 改のシミュレーションができます。
Lモーター、Mモーターの制御だけではなく、タッチセンサー、ジャイロセンサー、超音波センサーのシミュレーションも可能になっています。
EV3Simulator コンポーネントと接続してシミュレーター上のロボットを操作するためのコンポーネントです。
GUI(スライダー)によりシミュレーター上のロボットの操作を行い、タッチセンサーがオンの時には自動的に停止するコンポーネントの作成を行います。
作成手順は以下の通りです。
Linux (ここでは Ubuntu 18.04 を仮定) 上に開発環境を構築します。
$ wget https://raw.githubusercontent.com/OpenRTM/OpenRTM-aist/master/scripts/pkg_install_ubuntu.sh $ pkg_install_ubuntu.sh -l all --yes
# Ubuntu 18.04、18.10の場合 $ sudo apt-get install openjdk-8-jdk # Ubuntu 16.04の場合 $ sudo apt-get install default-jdk
Ubuntu 18.04、18.10の場合は以下のコマンドでjava8に切り替えます。
$ sudo update-alternatives --config java
eclipse起動後、RTSystemEditor でネームサーバに接続できない場合があります。その場合、/etc/hosts の localhost の行に自ホスト名を追記してください。
$ hostname ubuntu1404 ← ホスト名は ubuntu1404 $ sudo vi /etc/hosts
127.0.0.1 localhost を以下のように変更 127.0.0.1 localhost ubuntu1404
$ sudo apt-get install git
$ sudo apt-get install cmake-qt-gui
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
ODEのビルドに必要です。
$ sudo apt-get install premake4 freeglut3-dev
シミュレーターコンポーネントについては手動でビルドを行います。 以下のコマンドを入力してください。
$ wget https://raw.githubusercontent.com/OpenRTM/RTM_Tutorial_EV3/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.5<x<1.5 |
Widget | slider |
Step | 0.01 |
説明 | 直進速度の設定 |
Configuration | |
パラメーター名 | speed_r |
型 | double |
デフォルト値 | 0.0 |
制約 | -2.0<x<2.0 |
Widget | slider |
Step | 0.01 |
説明 | 回転速度の設定 |
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が格納できます。
vx、vy、vaはロボット中心座標系での速度を表しています。
Educator Vehicle改のように2個の車輪が左右に取り付けられているロボットの場合、横滑りしないと仮定するとvyは0になります。
直進速度vx、回転速度vaを指定することでロボットの操作を行います。
RobotController コンポーネントのひな型コードの生成は、RTCBuilder を用いて行います。
Eclipse では、各種作業を行うフォルダーを「ワークスペース」(Work Space)とよび、原則としてすべての生成物はこのフォルダーの下に保存されます。 ワークスペースはアクセスできるフォルダーであれば、どこに作っても構いませんが、このチュートリアルでは以下のワークスペースを仮定します。
まずは Eclipse を起動します。 OpenRTP を展開したディレクトリーに移動して以下のコマンドを入力します。
$ openrtp
最初にワークスペースの場所を尋ねられますので、上記のワークスペースを指定してください。
すると、以下のような Welcome ページが表示されます。
Welcome ページはいまは必要ないので左上の「×」ボタンをクリックして閉じてください。
右上の [Open Perspective] ボタンをクリックしてください。
「RTC Builder」を選択することで、RTCBuilderが起動します。メニューバーに「カナヅチとRT」の RTCBuilder のアイコンが現れます。
RobotController コンポーネントを作成するために、RTC Builder で新規プロジェクトを作成する必要があります。
左上の [Open New RTCBuilder Editor] のアイコンをクリックしてください。
「プロジェクト名」欄に作成するプロジェクト名 (ここでは RobotController) を入力して [終了] をクリックします。
指定した名称のプロジェクトが生成され、パッケージエクスプローラ内に追加されます。
生成したプロジェクト内には、デフォルト値が設定された RTC プロファイル XML(RTC.xml) が自動的に生成されます。
RTC.xmlが生成された時点で、このプロジェクトに関連付けられているワークスペースとして RTCBuilder のエディタが開くはずです。 もし起動しない場合はパッケージエクスプローラーの RTC.xml をダブルクリックしてください。
まず、いちばん左の「基本」タブを選択し、基本情報を入力します。先ほど決めた RobotController コンポーネントの仕様(名前)の他に、概要やバージョン等を入力してください。 ラベルが赤字の項目は必須項目です。その他はデフォルトで構いません。
次に、「アクティビティ」タブを選択し、使用するアクションコールバックを指定します。
RobotController コンポーネントでは、onActivated()、onDeactivated()、onExecute() コールバックを使用します。下図のように①の onAtivated をクリック後に②のラジオボタンにて [ON] にチェックを入れます。 onDeactivated、onExecute についても同様の手順を行います。
さらに、「データポート」タブを選択し、データポートの情報を入力します。 先ほど決めた仕様を元に以下のように入力します。なお、変数名や表示位置はオプションで、そのままで結構です。
次に、「コンフィギュレーション」タブを選択し、先ほど決めた仕様を元に、Configuration の情報を入力します。 制約条件および Widget とは、RTSystemEditor でコンポーネントのコンフィギュレーションパラメーターを表示する際に、スライダー、スピンボタン、ラジオボタンなど、GUI で値の変更を行うためのものです。
直進速度 speed_x、回転速度 speed_r はスライダーのより操作できるようにします。
次に、「言語・環境」タブを選択し、プログラミング言語を選択します。 ここでは、C++(言語) を選択します。なお、言語・環境はデフォルト等が設定されておらず、指定し忘れるとコード生成時にエラーになりますので、必ず言語の指定を行うようにしてください。
最後に、「基本」タブにある [コード生成] ボタンをクリックし、コンポーネントのひな型コードを生成します。
※ 生成されるコード群は、eclipse起動時に指定したワークスペースフォルダーの中に生成されます。 現在のワークスペースは、[ファイル] > [ワークスペースの切り替え...] で確認することができます。
RTC Builder で生成したコードの中には CMake でビルドに必要な各種ファイルを生成するための CMakeLists.txt が含まれています。 CMake を利用することにより CMakeLists.txt から Visual Studio のプロジェクトファイル、ソリューションファイル、もしくは Makefile 等を自動生成できます。
CMake を利用してビルド環境の Configure を行います。 まずは CMake(cmake-gui) を起動してください。
$ cmake-gui
画面上部に以下のようなテキストボックスがありますので、それぞれソースコードの場所 (CMakeList.txt がある場所) と、ビルドディレクトリーを指定します。
ソースコードの場所は RobotController コンポーネントのソースが生成された場所で CMakeList.txt が存在するディレクトリーです。 デフォルトでは <ワークスペースディレクトリー>/RobotController になります。
このディレクトリーはエクスプローラから cmake-gui にドラックアンドドロップすると手入力しなくても設定されます。
ビルドディレクトリーとは、ビルドするためのプロジェクトファイルやオブジェクトファイル、バイナリを格納する場所のことです。 場所は任意ですが、この場合 <ワークスペースディレクトリー>/RobotController/build のように分かりやすい名前をつけた RobotController のサブディレクトリーを指定することをお勧めします。
Where is the soruce code | /home/ユーザー名/workspace/RobotController |
Where to build the binaries | /home/ユーザー名/workspace/RobotController/build |
指定したら、下の [Configure] ボタンをクリックします。すると下図のようなダイアログが表示されますので、生成したいプロジェクトの種類を指定します。 今回は CodeBlocks - Unix Makefiles を指定します。 Code::Blocks を使わない場合は Unix Makefiles を使ってください。
また 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 をクリックすることで編集画面が開きます。
64bitの環境の場合に Code::Blocks の動作が不安定になることがあります。 その場合は code completion というプラグインを無効化すると動作することがあります。
「Plugins」>「Manage plugins...」を選択します。
「code completion」を選択して [Disable] ボタンをクリックします。
動作しないときはこの手順を試してください。
RobotController コンポーネントでは、コンフィギュレーションパラメーター(speed_x、speed_y)をスライダーで操作しその値を目標速度としてアウトポート(out)から出力します。 インポート(in)から入力された値を変数に格納して、その値が一定以上の場合は停止するようにします。
onActivated()、onExecute()、onDeactivated() での処理内容を下図に示します。
センサー値を一時的に格納する変数 sensor_data を宣言します。
private: bool sensor_data[2]; //センサー値を一時格納する変数
下記のように、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(); return RTC::RTC_OK; }
Code::Blocksの [ビルド] ボタンをクリックしてビルドを行います。
作成した RobotController をシミュレーターコンポーネントと接続して動作確認を行います。
以下より EV3Simulator コンポーネントをダウンロードしてください。
インターネットに接続できない環境で講習会を実施している場合がありますので、その場合は配布のUSBメモリーに入れてあります。
OpenRTPのパースペクティブを開くのウインドウからRT System Editorを選択して起動します。
コンポーネントの参照を登録するためのネームサービスを起動します。
RT System Editorのネームサービス起動ボタンを押すと起動します。
※ 「Start Naming Service」をクリックしても omniNames が起動されない場合は、フルコンピュータ名が14文字以内に設定されているかを確認してください。
RobotController コンポーネントを起動します。
RobotController\build\srcフォルダーの RobotControllerComp ファイルを実行してください。
$ RobotControllerComp
EV3SimulatorComp コンポーネントをインストールしたディレクトリーに移動後、下記のコマンドにて起動できます。
$ src/EV3SimulatorComp
下図のように、RTSystemEditor にて RobotController コンポーネント、EV3Simulator コンポーネントを接続します。 システムダイアグラムは左上のOpen New System Editorボタンで表示できます。
RTSystemEditor の上部にあります [All Activate] というアイコンをクリックし、全てのコンポーネントをアクティブ化します。 正常にアクティベートされた場合、下図のように黄緑色でコンポーネントが表示されます。
下図のようにコンフィギュレーションビューの [編集] ボタンからコンフィギュレーションを変更することができます。
正常に動作している場合は、開始し位置から直進した場合に壁の前で停止します。
正常に動作していない場合は、壁に接触後にそのまま前進を続けます。
講習会で EV3実機を用意している場合は実機での動作確認が可能です。
手順は以下の通りです。
EV3 は分解した状態で参加者に配ります。 組み立て方は以下の通りです。
ただし、超音波センサー、カラーセンサー、ジャイロセンサーについては、講習で使用しないため取り付ける必要はありません。 以下の※の作業については、時間が余った人が実施してください。
まずは土台部分を取り出してください。
右側のタッチセンサーを取り付けてください。
超音波センサーを取り付けてください※。
Lモーター右 | ポート C | 25cmケーブル |
Lモーター左 | ポート B | 25cmケーブル |
Mモーター※ | ポートA | 25cmケーブル |
タッチセンサー右 | ポート 3 | 35cmケーブル |
タッチセンサー左 | ポート 1 | 35cmケーブル |
超音波センサー※ | ポート 4 | 50cmケーブル |
ジャイロセンサー※ | ポート 2 | 25cmケーブル |
ケーブルは EV3 の上下に A~D と 1~4 のポートがあるのでそこにケーブルを接続します。
左右にパーツを取り付けます※。 Lモーター右、Lモーター左、Mモーター、タッチセンサー右、タッチセンサー左のケーブルを挟むようにして取り付けてください※。
Lモーター右、タッチセンサー右のケーブルは右側から、Lモーター左、Mモーター、タッチセンサー左は左側から通してください※。
中央のボタンを押せば電源が投入されます。
EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。
再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。
ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。
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 に貼り付けたテープに記載してあります。
SSID、パスワードは EV3に貼り付けたシールに記載してあります。
※ネットワークが切り替わった場合にネームサーバーへのコンポーネントの登録やポートの接続が失敗する場合があるのでOpenRTP、ネームサーバ、コンポーネントを一旦全て終了してください。 ネットワーク切り替え後に起動した場合には問題ないので、終了させる必要はありません。
OpenRTPを終了するには右上の×を押して終了してください。システムダイアグラムを保存するかどうか聞かれますが、Don't Saveを選択してください。
openrtpコマンドを実行してOpenRTPを起動してください。
RT System Editor上でネームサーバーを再起動するには「ネームサービスを起動」ボタンを再度クリックします。
続いてRTシステムエディタの [ネームサーバー追加] ボタンで 192.168.0.1 を追加してください。
するとEducatorVehicle0という RTC が見えるようになります。
RTシステムエディタで EducatorVehicle、RobotController コンポーネントを以下のように接続します。
そして RTC をアクティブ化すると EV3の操作ができるようになります。
このページでは2台のEV3を連携したRTシステムの構築を行います。
1台目のEV3をアクセスポイントとして、ノートPCと2台目のEV3をアクセスポイントに接続します。
※EV3(1台目)は奇数番号のものを配布します。EV3のシールに記載された番号を確認してください。 EV3(2台目)はEV3(1台目)の次の番号のものを配布します。(例:EV3(1台目):7、EV3(2台目):8)
第二部の手順に従って2台目のEducator Vehicleを組み立ててください。
第二部の、実機での動作確認まで完了してください。 この時点でノートPCとアクセスポイントのEV3が接続されているはずです。
まずはEV3(2台目)の電源を投入してください。 起動後にEV3(1台目)に自動接続します。 自動接続できた場合は、EV3の画面左上にIPアドレスが表示されます。 IPアドレスは192.168.11.yyyが表示されます。
EV3(2台目)の画面上の操作でネームサーバーとRTCを起動します。
EV3 の操作画面から「File Browser」→「scripts」を選択してください。
ネームサーバー、RTCはstart_rtcs.shのスクリプトを実行することで起動します。
------------------------------ 192.168.11.yyy ------------------------------ File Browser ------------------------------ /home/robot/scripts ------------------------------ ../ Component/ ・・ [start_rtcs.sh ] ------------------------------
RTシステムエディタから、192.168.11.yyyのネームサーバーに接続してください。
この時点でRTシステムエディタのネームサービスビューにはlocalhost、192.168.0.1、192.168.11.yyyのネームサーバーが登録されています。 192.168.11.yyyのネームサーバーに登録されているRTCの名前はEducatorVehicle1となります。
EducatorVehicle0(192.168.0.1)とEducatorVehicle1(192.168.11.yyy)をシステムダイアグラム上で接続してください。 EducatorVehicle1の現在の速度出力をEducatorVehicle0の目標速度入力に接続することで、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");
このページではLibreOffice Calc用RTCによるRTCの動作確認手順について説明します。 Calcのセルの値をInPortに入力、OutPortの出力した値をセルに表示することで対象RTCの挙動を確認できます。
RTM講習会ではUSBメモリでポータブル版LibreOfficeとRTCを配布します。 Windowsで実行できます。 UbuntuはPython3用のomniORBのパッケージがないため実行できません。講習会ではノートPCを貸し出します。
この実習では第2部で作成したRobotControllerコンポーネントを使用します。
表計算、パワーポイント、ワープロ機能等を提供するオフィススイートです。 フリーソフトとして公開されており、今回の講習会では以下のポータブル版を使用します。
配布したUSBメモリ内のポータブル版LibreOffice\run_CalcRTC.batを実行します。
LibreOffice Calcが起動するため、RTC起動ボタンをクリックすることでOOoCalcControlというRTCを起動します。
RobotControllerのOutPortと接続し、Calcで出力データの確認ができるようにします。 Calcの操作ダイアログ起動ボタンをクリックしてください。
まずは出力データを確認するOutPortと接続します。 ツリー表示ボタンを押下してネームサーバーに登録されたRTCのポート一覧を表示後、ツリーからRobotController0のoutを選択します。
次に一部設定を変更します。
列を移動させるのチェックを外してください。 このチェックが有効の場合、データを受信する度にセルの位置が移動するモードで動作します。 グラフに描画する場合は位置が移動するモードを使用しますが、今回は単純に値を確認したいだけのためチェックを外します。
列番号の右のボックスにCと入力してください。 これで2行目のA~C列のセルにOutPortの出力データを表示するようになりました。
設定完了後、作成ボタンを押してください。
RT System Editor上でRTCをアクティブ化して動作を確認してください。
この状態でコンフィギュレーションパラメータを操作してCalcのセルの値が変化するかを確認してください。
RobotControllerのInPortと接続し、Calcからデータの入力を行うようにします。
ツリー表示ボタンを押下してネームサーバーに登録されたRTCのポート一覧を表示後、ツリーからRobotController0のinを選択します。
次に一部設定を変更します。
列を移動させるのチェックを外してください。
列番号の右のボックスにDと入力してください。 これで3行目のA~C列のセルにOutPortの出力データを表示するようになりました。
設定完了後、作成ボタンを押してください。
RT System Editor上でRTCをアクティブ化して動作を確認してください。
この状態でコンフィギュレーションパラメータで前進する速度をOutPortから出力するように操作してください。 その後、Calcの3行目のA、B列のセルに1の値を入力するか、0の値を入力するかで動作が変化するかを確認してください。
このページではレゴマインドストーム EV3 で以下の車輪移動ロボット (Educator Vehicle 改) を組み立てる手順を説明します。
まずは Educator Vehicleの説明書 の最初の車輪移動ロボットを組み立てる章の45番まで組み立ててください。 ただし8番と20番の作業は必要ないので飛ばしてください。
またジャイロセンサーを取り付ける章(98ページ)を参考にしてジャイロセンサーを取り付けてください。
モーターMにパーツを取り付けます。 Educator Vehicle の説明書のモーターMを取り付ける章(78ページ)の2~5、10番作業を行ってください。
タッチセンサーにパーツを取り付けます。 Educator Vehicle の説明書のタッチセンサーを取り付ける章(61ページ)の1~3番の作業を行ってください。
ここからの作業に必要な部品は以下の通りです。
モーター右 | ポート C | 25cmケーブル |
モーター左 | ポート B | 25cmケーブル |
モーター(M) | ポートA | 25cmケーブル |
タッチセンサー右 | ポート 3 | 35cmケーブル |
タッチセンサー左 | ポート 1 | 35cmケーブル |
超音波センサー | ポート 4 | 50cmケーブル |
ジャイロセンサー | ポート 2 | 25cmケーブル |
※カラーセンサーを利用する際は超音波センサーかタッチセンサーのケーブルを外して使用してください。