概要

ROSを使って実機でロボット台車を動作させたい時に、Arduinoでシリアル通信経由でROSトピックを受信して、ロボット台車を動作させる方法を説明します。

/cmd_velは、平行移動の速度と回転速度が定義されたgeometry_msgs/Twistという型を用いた、ロボットの動作を指示するトピックです。

ROSがインストールされたデバイス(Jetson Nano等)とモータに繋がったArduinoをシリアルケーブルで繋いで、ROSの/cmd_velトピックをArduinoで受信する部分までの解説をします。Arduinoでモータを制御する方法については本記事では解説はしません。

接続

ROSが入ったマシンの設定

ROS側は、rosserialというパッケージを使います。シリアル通信を使ってROSトピックのやりとりができる非常に便利なパッケージです。

rosserialのパッケージをインストールします。(下記はmelodicの例)

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

続いて、Arduinoとシリアルケーブルで繋いだ後に、デバイスが表示されるかを確認します。大抵は、/dev/ttyACM0、/dev/ttyUSB0のような名前になることが多いです。

ls /dev/tty*

 などのコマンドで確認しましょう。

デバイスの確認 

続いて、Arduinoで使用するライブラリをこのマシンでビルドをします。公式チュートリアルも参考にしましょう。

※ Arduino IDEはインストールされている前提とします。

1つターミナルを立ち上げて、roscoreを起動します。

roscore

もう1つターミナルを立ち上げて下記を実行します。Arduinoのディレクトリ配下にあるlibrariesディレクトリに移動して、make_libraries.pyを実行します。

  cd sketchbook_path/libraries
  rm -rf ros_lib
  rosrun rosserial_arduino make_libraries.py .

 すると、librariesディレクトリ内にros_libディレクトリができると思いますので、Arduino IDEを再起動してExamplesの中にros_libがあれば準備が整った形となります。

尚、このros_libは別のマシンに移動しても使用することができるので、私はROSの入ったJetson Nanoでros_libディレクトリを作った後に、それをMacのlibrariesディレクトリに移してMacでも使っています。(MacだとROSが入れづらいので) 

Arduino側の設定

Arduino側のコード例は次のようになります。
#include <spi.h>
#include <ros.h>
#include <geometry_msgs/Twist.h>

ros::NodeHandle nh;

void messageCb(const geometry_msgs::Twist& twist) {
  // /cmd_vel受信後のコード
  int x = int( twist.linear.x * 100);
  char buf[100];
  sprintf(buf, "x = %d", x);
  nh.loginfo(buf);
}

ros::Subscriber<geometry_msgs::Twist> sub("cmd_vel", &messageCb);

void setup() {
  nh.getHardware()->setBaud(115200);
  nh.initNode();
  nh.subscribe(sub);
}

void loop() {
  nh.spinOnce();
  delay(1);
}

 

ros::Subscriber<geometry_msgs::Twist> sub("cmd_vel", &messageCb);

この部分で、cmd_velというトピックをsubscribeして、データを受信したらmessageCbがコールバック関数として呼ばれます。messageCbで受けた引数はgeometry_msgs::Twist型、つまり、下記のようなオブジェクトになります。

Vector3 linear
    float64 x
    float64 y
    float64 z
Vector3 angular
    float64 x
    float64 y
    float64 z

例えば、x方向の速度を取得したい場合は、 twist.linear.xのように取得できます。例ではtwist.linear.xを100倍した値を出力することだけをしています。

あとはこれらの値に応じてモーターを動作させるコードを追記すれば大丈夫です。今回はモーターを動作させる部分は省略します。

/cmd_velの送信

まず、ROSが入ったマシンとArduinoがケーブルで繋がれていることを確認してください。

ROSが入ったマシン側で1つターミナルを立ち上げてcmd_velを発行できるノードを立ち上げます。例ではturtlebot3のteleopパッケージを使用していますが、詳しいインストール方法は省略します。

roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch

もう1つのターミナルを立ち上げて、rosserialを実行します。 

rosrun rosserial_python serial_node.py /dev/ttyUSB0 _baud:=115200

 rosserial

送信した/cmd_velの値が、rosserialの方で出力されていれば正常にArduino側に値が送られていることになります。

rosserialでエラーが出た場合は下記記事などを参考にしてください。

https://rb-station.com/blogs/article/rosserial-lost-sync-with-device-restarting

ArduinoRosRosserial

Related Posts

ROSのLaserScanデータの一定角度の範囲を無視する方法
ROSのLaserScanデータの一定角度の範囲を無視する方法
ROSでLidarセンサーを使う時、ロボットの車体など一定角度の範囲に常に障害物があり、これを無視したい時があると思いますが、その方法を紹介します。 以下は、得られた/scan_rawトピックのデータの一定角度の範囲を無視して新しい/...
Read More
ROSのmove_baseで、Pythonからコストマップをクリアする方法
ROSのmove_baseで、Pythonからコストマップをクリアする方法
move_baseを使っていると、障害物が無いのにコストマップで障害物判定されてしまうことがあります。そのようなときは、コストマップを一度クリアしましょう。 コマンドから   move_baseノードには、コストマップをクリアする方法...
Read More
roslaunchでrospy.loginfoでの出力が表示されない場合の対応策
roslaunchでrospy.loginfoでの出力が表示されない場合の対応策
roslaunchで起動したときに、rospy.loginfoで出力しても表示されない場合は下記のように--screenオプションをつけましょう。 コマンドラインで実行する場合 roslaunch your_package your_...
Read More