0. ROSの基本
# 2018-04-12 YMD
正確な情報はhttp://wiki.ros.org/ja/ROS/Tutorialsを参照すること.
ワークスペース
ROSはcatkinというビルドシステムを使っている.
catkinを使うことによって,パッケージの依存関係などの管理が簡単になる.
ワークスペースの作成
以下のコマンドでワークスペースを作成する.(一度だけ行う.端末を立ち上げ直しても再び行う必要はない)
mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace
~/.bashrcの一番下に下記を追加する。
source ~/catkin_ws/devel/setup.bash
一度端末を閉じて,開き直して,.bashrcの変更を反映する.
cd ~/catkin_ws/ catkin_make
環境変数
ROSは環境変数をパッケージの検索などに使っているので, 環境変数を操作できるとデバッグなどで便利なことがある.
環境変数の表示
env # 全ての環境変数を表示 env | grep ROS # ROS関連の環境変数を表示 echo $PATH # 環境変数PATHを表示
ROS_PACKAGE_PATHの中に/home/USERNAME/catkin_ws/srcと/opt/ros/kinetic/shareが表示されていて,PATHの中に/opt/ros/kinetic/binが含まれていれば,正しくセットアップできている.
パッケージ(catkin形式)
パッケージを作る
例として,ros_studyというパッケージを作る.
cd ~/catkin_ws/src catkin_create_pkg ros_study std_msgs sensor_msgs nav_msgs geometry_msgs roscpp
std_msgs以降の引数は依存パッケージを指定している.
roscore
roscore
(ROSを使うときに最初に実行するコマンド,rosout,rosmaster,ros parameter serverが起動する)
roscore
roscoreを行っている間はその端末では他のコマンドが実行できないので,別の端末を起動する.
(terminatorを使っている場合にはCtrl+Shift+eやCtrl+Shift+oを使う)
ノード
rosにおけるプロセスのこと
ノードを作る
~/catkin_ws/src/ros_study/src/にros_study_node.cppを作成する
/**
* inから読み取った最新のメッセージを1回~/outに出力するノード.
* パラメータ~/nameで指定された名前を最初に付与する.
*/
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <iostream>
#include <sstream>
#include <deque>
static std_msgs::String::ConstPtr latest_listened_msg_ptr = nullptr;
void listenCallback(const std_msgs::String::ConstPtr& msg)
{
latest_listened_msg_ptr = msg;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "ros_study_node");
ros::NodeHandle private_nh("~");
ros::NodeHandle nh;
ros::Duration loop_duration(0.1);
std::string name;
ros::Publisher out_pub(private_nh.advertise<std_msgs::String>("out", 1000)); // "~/out"
ros::Subscriber in_sub = nh.subscribe("in", 1000, listenCallback); // "/in"
private_nh.param<std::string>("name", name, "anonymous"); // "~/name"
while (ros::ok())
{
if (latest_listened_msg_ptr)
{
std_msgs::String out_msg;
std::stringstream out_ss;
out_ss << name << ": "; // set name name
out_ss << latest_listened_msg_ptr->data; // append listened string
latest_listened_msg_ptr = nullptr; // delete message
out_msg.data = out_ss.str(); // set data
out_pub.publish(out_msg); // send message
}
ros::spinOnce(); // check topic
loop_duration.sleep(); // sleep for 0.1 sec
}
return 0;
}
ビルド設定を編集する
CMakeLists.txtから以下の行を探してコメント(# )を解除する.
# add_compile_options(-std=c++11)
# add_executable(${PROJECT_NAME}_node src/ros_study_node.cpp)
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
ビルド
cd ~/catkin_ws catkin_make
rosrun
rosrun ros_study ros_study_node # 実行しても何も表示はされない
でros_studyという名前のパッケージにあるros_study_nodeという名前のノードを実行する.
後で使うので実行したまま,別の端末を起動する.
実行中のノード一覧表示
rosnode list
topic
ノード間で非同期的にやり取りされるデータをメッセージと呼ぶ.
メッセージの送信先の指定はtopicによって行われる.
topicはwebサービスにおけるアドレスに似ている.
topic一覧の表示
rostopic list
topicに送られたデータの表示
例としてros_study_node/outのデータを表示する
rostopic echo ros_study_node/out # 現時点では何も表示されない
後で使うので実行したまま,別の端末を起動する.
topicにメッセージを配信する
例としてstd_msgs/String型の“hello”というデータをトピック“in”に配信する
rostopic pub in std_msgs/String "hello"
rostopic echoを行った端末に,data: “anonymous: hello”と表示される.
グラフの表示
インストール
sudo apt-get install ros-kinetic-rqt-graph
実行
rosrun rqt_graph rqt_graph
パラメータ
パラメータ一覧を表示する
rosparam list
パラメータを取得・設定する
例としてros_study_node/nameというパラメータを取得・設定する
rosparam get ros_study_node/name # setしていない場合には存在しないのでエラーメッセージが出る rosparam set ros_study_node/name john
セットした後で
rosrun ros_study ros_study_node
すると,パラメータros_study_node/nameを読み込ませることができる.
(ノード内部の値を動的に更新したいときにはdynamic_reconfigureを使う必要がある)
このとき
rostopic pub in std_msgs/String "hello"
を実行すると,rostopic echoを行った端末に,data: “john: hello”と表示される.
roslaunch
ノードをまとめて実行するときに使う
launchファイル
例えば,以下のようなファイルを作る.
~/catkin_ws/src/ros_study/launch/apple.launchに配置する.
<launch>
<node pkg="ros_study" type="ros_study_node" name="john_node">
<param name="name" value="john"/>
<remap from="/in" to="~/in"/>
<remap from="~/out" to="/paul_node/in"/>
</node>
<node pkg="ros_study" type="ros_study_node" name="paul_node">
<param name="name" value="paul"/>
<remap from="/in" to="~/in"/>
<remap from="~/out" to="/george_node/in"/>
</node>
<node pkg="ros_study" type="ros_study_node" name="george_node">
<param name="name" value="george"/>
<remap from="/in" to="~/in"/>
<remap from="~/out" to="/ringo_node/in"/>
</node>
<node pkg="ros_study" type="ros_study_node" name="ringo_node">
<param name="name" value="ringo"/>
<remap from="/in" to="~/in"/>
</node>
</launch>
pkgにはパッケージ名,
nameには適当に理解しやすい固有名(ノード名と同じでも可),
typeにはノード名を指定する.
paramタグを使ってパラメータを指定する.
remapタグを使ってトピック名を変更する.
launchファイルを実行する
roslaunch ros_study apple.launch
別の端末で
rostopic echo ringo_node/out
さらに別の端末で
rostopic pub john_node/in std_msgs/String "hello"
すると,data: “ringo: george: paul: john: hello”と表示される.
rosrun rqt_graph rqt_graph
すると,メッセージが受け渡される流れを確認できる.