Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
21
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

ROS講座46 ROSでarduinoを使う

環境

この記事は以下の環境で動いています。

項目
CPU Core i5-8250U
Ubuntu 16.04
ROS Kinetic

インストールについてはROS講座02 インストールを参照してください。
またこの記事のプログラムはgithubにアップロードされています。ROS講座11 gitリポジトリを参照してください。

概要

arduinoは便利で使いやすいマイコンシステムです。基本的にはUbuntuが載るような「高レベル」のPCではモーターなどのハードウェアを扱うことはできません。そこでarduinoのような「低レベル」のマイコンを挟むことでROSとモーター等をつなぎます。
この記事では以下の内容について記述します。

  • Arduinoをplatformioを用いてCLIで使う
  • platformioをROSのディレクトリで管理する
  • rosserialを使ってPCと通信する。

platformIOのインストール・使い方

platformIOはarduinoやmbedなどのマイコンの開発環境をCLIで使うためのツールです。公式のarduinoコンパイラはGUIで提供されているのでとっつきやすいのですがROSの環境と合わせるのが難しいです。ROSのプログラムとArduinoのプログラムを別々に管理してもよいのですが、バージョン管理の問題が起こったりするのでできるだけ同じ環境ですべてできることが理想です。そのためにArduinoもCLIのツールで用います。公式にもarduino CLIというCLIツールがありますが、裏でIDEが立ち上がりだいぶ重いみたいなので今回は見送ります。

使用するボード

今回はarduino megaを使用します。一番普及しているのはunoですがこれはピン数や機能が少なくロボットには不足します。megaなら複数のモーターを制御することも可能です。

arduino_mega.jpg
arduinoストアより

インストール

pipでもインストールできますが以下の方法で行うのが一番確実です。

platformioのインストール
python -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/develop/scripts/get-platformio.py)"

使うボードの選択

platform boardsで使えるボード(マイコン)の一覧が出ます。長いので`grep‘するのがおすすめです。例えば今回使うarduino megaは

mega2560
megaatmega2560        ATMEGA2560     16MHz     248KB   8KB    Arduino Mega or Mega 2560 ATmega2560 (Mega 2560)

と表示されるので1番最初に表示されているmegaatmega2560という名前で使えば良いことがわかります。

シリアルポートの権限

標準では一般ユーザーはシリアルポートのアクセス権限がありません。以下のコマンドで永続的に権限が持てます。

シリアルポートへの権限付加
sudo gpasswd --add $USER dialout

ワークスペースの作成

作る場所はどこでもよいですが~/mega_projectにします。後半はplatformio.iniという設定ファイルにボードへの書き込みの設定を追加しています。

workspaceの作成
mkdir ~/mega_project
cd ~/mega_project/
platformio init -b megaatmega2560
echo "upload_port = /dev/ttyACM0" >> platformio.ini 
echo "targets = upload" >> platformio.ini 

プログラムの作成

以下のようなプログラムを~/mega_project/src/main.inoに書きます。

~/mega_project/src/main.ino
void setup(){
  pinMode(13, OUTPUT);
}

void loop(){
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
  delay(500);
}
  • setup()は起動時に1度だけ最初に実行する関数です。
  • loop()setup後に無限に実行される関数です。
  • pinMode(13, OUTPUT);は13番ピンを出力する関数です。
  • digitalWrite(13, HIGH);は13番ピンをHIGH(5V)にする関数です。
  • digitalWrite(13, LOW);は13番ピンをLOW(0V)にする関数です。

コンパイル&アップロード

以下のコマンドでプログラムのコンパイルとアップロードの両方を行います。ArduinoをUSBポートに刺してから実行してください。

コンパイル&アップロード
cd ~/mega_project/
platformio run

arduinoのボードではLEDが点滅しているはずです。

rosパッケージに統合する。

arduinoのプログラムもROSパッケージと統合するのが便利です。統合といっても実際にやるのはcatkin_wsの中にplatformioのファイルを置くこと、起動用の実行ファイルを作るだけです。

ワークスペースの作成

ROSパッケージの中のhard_lecture/platformio/ino01にワークスペースを作ります。

workspaceの作成
roscd hard_lecture
mkdir -p platformio/ino01
cd platformio/ino01
platformio init -b megaatmega2560
echo "upload_port = /dev/ttyACM0" >> platformio.ini 
echo "targets = upload" >> platformio.ini 

ソースコードの作成

hard_lecture/platformio/ino01/main.inoにプログラムを書きます。内容はさっきと同様のLチカで良いでしょう。

コンパイル&アップロード用のスクリプトを作成

先ほどと同様にコマンドを実行してもよいですがあんまりROSっぽくないのでスクリプトを書いてrosrunで実行します。

hard_lecture/scripts/write_ino01.sh
echo "writing arduino"
echo "connect arduino on USB"

cd `dirname ${0}`/../platformio/ino01
platformio run

実行権限を付与します。

roscd hard_lecture
chmod +x scripts/write_ino01.sh

実行

以下のコマンドで実行できます。roscoreを実行している必要はありません。

rosrun hard_lecture write_ino01.sh 

rosserialの使用

マイコンのプログラムの一番面倒な部分は通信です。PCとArduinoの通信を自作のプロトコルで作っていたら、その製作だけでも大変なことになってしまいます。そこでできたのがrosserialです。Arduinoでrosのpublisherやsubscriberが作れます。
今回は説明しませんがparameterの取得もできます。

インストール

sudo apt-get install ros-kinetic-rosserial
sudo apt-get install ros-kinetic-rosserial-arduino

ワークスペースの作成

roscd hard_lecture
mkdir -p platformio/ino02
cd platformio/ino02
platformio init -b megaatmega2560
echo "upload_port = /dev/ttyACM0" >> platformio.ini 
echo "targets = upload" >> platformio.ini 

ros_libのコピー

rosのメッセージヘッダをコピーします。以下のコマンドで現在のワークスペースのメッセージファイルをarduinoで使うために変換できます。arduinoのコンパイルに使うライブラリはhard_lecture/platformio/ino02/libにコピーします。libはplatformioのワークスペースごとの個別に使うlocalなライブラリの保管場所です。
platformioのワークスペースを作るごとに必要な作業です。

roscd hard_lecture/platformio/ino02/lib
rosrun rosserial_arduino make_libraries.py .

ソースコード

以下がrosserialでpublish、subscribeをするためのarduino側のソースコードです。いつものrosのプログラムと見た目は似ていますが、細部はいくらか違うので注意が必要です。

hard_lecture/platformio/ino02/src/main.ino
#include <ros.h>
#include <std_msgs/String.h>
#include <std_msgs/Bool.h>

ros::NodeHandle  nh;
std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);
char hello[13] = "hello world!";

void led_cb(const std_msgs::Bool& msg){
  if(msg.data)digitalWrite(13, HIGH);
  else digitalWrite(13, LOW);
}
ros::Subscriber<std_msgs::Bool> sub0("led", &led_cb);

void setup()
{
  nh.initNode();
  nh.advertise(chatter);
  nh.subscribe(sub0);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(13, OUTPUT);
}

void loop()
{
  str_msg.data = hello;
  chatter.publish( &str_msg );
  nh.spinOnce();
  delay(500);
}

書き込み用のスクリプト

hard_lecture/scripts/write_ino02.sh
echo "writing arduino"
echo "connect arduino on USB"

cd `dirname ${0}`/../platformio/ino02
platformio run

実行

初めに書き込みを行います。

arduinoのコンパイル・書き込み
rosrun hard_lecture write_ino02.sh 

この後実行します。

1つ目のターミナル
roscore
1つ目のターミナル
rosrun rosserial_python serial_node.py _port:=/dev/ttyACM0

この状態でrostopic listをするとarduinoでpublish、subscriveした/chatter/ledのROSトピックが見えます。
rostopic echo /chatterとするとdata: "hello world!"と見えます。
rostopic pub -1 /led std_msgs/Bool "data: true"とするとledが点灯します。

ros_libの必要なディレクトリ

hard_lecture/platformio/ino02/lib/ros_lib以下には多数のディレクトリが生成されます。しかしすべてのディレクトリが必要なわけではありません。特に今回はgitで管理するのであまり多くの無駄なディレクトリを作りたくありません。
ディレクトリのうち常に必須なのはrosrosserial_msgsとros_lib直下のファイルのみです。
これとは別にarduinoのプログラムからリンクしているstd_msgsが必要です。

コメント

Raspberry PiはLinuxが動いて、GPIOが多数あるのでこれだけでロボットが作れるように見えますが、Raspberry Pi上でROSを動かしてかつモーターなどの制御をするという方式はお勧めしません。理由は3つあります。

  • 1つ目はデバッグ性の問題で、Raspberry Piでモーター制御等のハードウェア部分を作ってしまうと、制御プログラムがRaspberry Piありきの物になってしまいます。こうすると例えばハードウェア部分だけを手元のノートPCにつないでテストするということができなくなります。
  • 2つ目はポートの性能の問題です。じつはRaspberry Piでは純粋なハードウェアPWMは1つしかなく、他は精度が劣るソフトウェアPWMです。またGPIOの数も30ピン程度と大規模なロボットを作ろうとすると簡単に不足します。この範囲を超えた場合はRaspberry Piを複数使うことになり面倒です。
  • 3つ目はリアルタイム性の問題です。例えば100usごとに定期的な処理をするというのはArduinoでは簡単ですが、Raspberry PiはLinuxを使っているために難しいです。

参考

platformioのインストール
platformioの使い方
rosserialの使い方

目次ページへのリンク

ROS講座の目次へのリンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
21
Help us understand the problem. What are the problem?