概要
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
送信した/cmd_velの値が、rosserialの方で出力されていれば正常にArduino側に値が送られていることになります。
rosserialでエラーが出た場合は下記記事などを参考にしてください。
https://rb-station.com/blogs/article/rosserial-lost-sync-with-device-restarting