こんにちは。プラスプラスの真山です。気づいたら体重が3キロ増えていました。
今回はROSの基本プログラミングとして実際にパッケージを作成してノードを作りメッセージの送受信を行います。
作業の流れとしては、
- パッケージの作成
- 設定ファイルの修正
- メッセージファイル、送受信ノードの作成
- ビルド
- 実行
というような流れになっております。
パッケージの作成
まずはじめにパッケージを~/catkin_ws/src
フォルダに作成します。パッケージ名はなんでもいいので今回はros_kihon
にします。パッケージを作成するときに依存パッケージを指定します。
今回のパッケージを使うためには、新しくメッセージを生成するときに必要なmessage_generation、ROSの標準メッセージパッケージstd_msgs、ROSでC/C++言語を使うためのクライアントライブラリroscppが必要なのでパッケージ名のあとに記述します。
それではコマンドです。
$ cd ~/catkin_ws/src $ catkin_create_pkg ros_kihon message_generation std_msgs roscpp
タターン!とエンターキーを押すと~/catkin_ws/src
フォルダにros_kihon
パッケージが生成されその中に見覚えのないファイルなどが作られていると思います。なんだこれは?cd移動してlsで確認すると
$ cd ros_kihon $ ls include ← ヘッダーファイルのフォルダ src ← ソースコードフォルダ CMakeLists.txt ← ビルド設定ファイル package.xml ← パッケージ設定ファイル
と出ます。次はこの下のふたつの設定ファイルを修正します。
パッケージ設定ファイル(package.xml)の修正
package.xmlファイルはパッケージの情報を記載したもので、パッケージ名、著作者、ライセンス、依存パッケージなどを定義する重要な設定ファイルです。エディタを使って中身を修正します。
$ gedit package.xml
ずら〜っとよくわかんないことが書かれています。ほとんどはコメントアウトされていますが。
この中身を書き換えて最終的にはこうなります。
<?xml version="1.0"?> <package> <name>ros_kihon</name> <version>0.1.0</version> <description>The ros_kihon package</description> <maintainer email="ros-basic@todo.todo">ros-basic</maintainer> <license>TODO</license> <buildtool_depend>catkin</buildtool_depend> <build_depend>message_generation</build_depend> <build_depend>roscpp</build_depend> <build_depend>std_msgs</build_depend> <run_depend>roscpp</run_depend> <run_depend>std_msgs</run_depend> <run_depend>message_runtime</run_depend> </package>
ビルド設定ファイル(CMakeLists.txt)の修正
このファイルには実行ファイルの生成、依存パッケージ優先のビルド、リンク生成など、ビルドの詳細が記載されています。
こちらもエディタで修正します。
$ gedit CMakeLists.txt
こちらも簡潔にすると
#パッケージの名前です cmake_minimum_required(VERSION 2.8.3) project(ros_kihon) #ビルドをする際に必要なパッケージを記載します。 find_package(catkin REQUIRED COMPONENTS message_generation roscpp std_msgs ) #メッセージを宣言します。 add_message_files( FILES MsgKihon.msg ) #依存するメッセージを設定します。std_msgsが無いとビルドでエラーが出ます。 generate_messages( DEPENDENCIES std_msgs ) #catkinパッケージオプションのライブラリ、catkinビルドの依存性、システム依存パッケージについて記述します。 catkin_package( LIBRARIES ros_kihon CATKIN_DEPENDS roscpp std_msgs ) #インクルードディレクトリを設定します。 include_directories( ${catkin_INCLUDE_DIRS} ) # kihon_publisherノードのビルドオプションです。 #実行ファイル、ターゲットリンクライブラリ、追加依存性などについて記述します。 add_executable(kihon_publisher src/kihon_publisher.cpp) add_dependencies(kihon_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_link_libraries(kihon_publisher ${catkin_LIBRARIES} ) # kihon_subscriberノードも同様に書きます。 add_executable(kihon_subscriber src/kihon_subscriber.cpp) add_dependencies(kihon_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_link_libraries(kihon_subscriber ${catkin_LIBRARIES} )
書くことが多い!!!ここで何かが抜けているとエラーが出てビルドができません。 タイプエラーは危険です。
次にここで定義したメッセージファイルを作ります。
メッセージファイルの作成
CMakeLists.txtファイルで定義した、MsgKihon.msgファイルを作成します。
メッセージファイルはmsgフォルダを新しく作りその中に作ります。
$ roscd ros_kihon ←(今いると思いますが)パッケージフォルダに移動 $ mkdir msg ←パッケージフォルダの中にmsgフォルダを生成 $ cd msg ← magフォルダに移動 $ gedit MsgKihon.msg ← MsgKihon.msgファイルを書く
MsgKihon.msg
time stamp int32 data
パブリッシャノードの作成
ビルド設定ファイルで記述したパブリッシャノードkihon_publisherを作成する。
$ roscd ros_kihon/src $ gedit kihon_publisher.cpp
kihon_publisher
#include "ros/ros.h" #include "ros_kihon/MsgKihon.h" int main (int argc, char **argv) { ros::init(argc, argv, "kihon_publisher"); ros::NodeHandle nh; ros::Publisher ros_kihon_pub = nh.advertise<ros_kihon::MsgKihon> ("ros_kihon_msg", 100); ros::Rate loop_rate(10); ros_kihon::MsgKihon msg; int count = 0; while (ros::ok()) { msg.stamp = ros::Time::now(); msg.data = count; ROS_INFO("send msg = %d", msg.stamp.sec); ROS_INFO("send msg = %d", msg.stamp.nsec); ROS_INFO("send msg = %d", msg.data); ros_kihon_pub.publish(msg); loop_rate.sleep(); ++count; } return 0; }
サブスクライバノードkihon_subscriberの作成
ビルド設定ファイルで記述したサブスクライバノードを作成します。
$ roscd ros_kihon/src $ gedit kihon_subscriber.cpp
kihon_subscriber
#include "ros/ros.h" #include "ros_kihon/MsgKihon.h" void msgCallback(const ros_kihon::MsgKihon::ConstPtr& msg) { ROS_INFO("receive msg = %d", msg->stamp.sec); ROS_INFO("receive msg = %d", msg->stamp.nsec); ROS_INFO("receive msg = %d", msg->data); } int main(int argc, char **argv) { ros::init(argc, argv, "kihon_subscriber"); ros::NodeHandle nh; ros::Subscriber ros_kihon_sub = nh.subscribe("ros_kihon_msg", 100, msgCallback); ros::spin(); return 0; }
ノードをビルド
パッケージ、メッセージ、ノードの作成ができたらcatkin_wsに移動してビルドを行います。
$ cd ~/catkin_ws $ catkin_make
一旦ここで考えるようです。「なにか曲者がいるぞ!」みたいな感じでしょうか。
少し待ってみると・・・
あれれ〜!おかし〜ぞ〜?(すみませんタイプエラー(曲者)です・・・笑)
気を取り直して(書きなおして)もう一度ビルドすると!?
おお〜〜〜!
無事にビルドができました!実行してみましょう。
パブリッシャノードの実行
roscoreコマンドでマスタを呼び出した後、別のターミナルにrosrun コマンドでパブリッシャノードを実行します。
$ rosrun ros_kihon kihon_publisher
画像のようにテキストが出力されます。もう止めるまで永遠と流れ続けます。飽きるまで見ましょう。
kihon_publisherからパブリッシュされるメッセージは、rostopicコマンドで表示できます。
$ rostopic list /ros_kihon_msg /rosout /rosout_agg
トピックリストにros_kihon_msgトピックの確認ができました。 メッセージの内容を確認してみます。
$ rostopic echo /ros_kihon_msg
dataが1ずつ増えて永遠と流れ続けてるのがわかります。
サブスクライバノードの実行
次にサブスクライバのノードを実行してみます。
実行するとパブリッシュされたros_kihon_msgトピックのメッセージを受信して画面に出力します。
$ rosrun ros_kihon kihon_subscriber
実行中のノードの通信状態を確認
実行中のノードの関係性をグラフで確認できます。
$ rqt_graph
今回はROSトピックの連続したデータを送り、またそれを受信するという基本的なプログラミングを行いました。この送受信内容はbagコマンドを使って保存・再生することもできます。
次回からみんなの人気者、Raspberry Piの登場です。