はじめに
本記事は、ubuntu 16.04 の入ったPCに Docker をインストールし、ubuntu 18.04 と ROS melodic の入った image を取得して、 Docker上で rostopic 通信をする ROS のチュートリアルをやってみた時のメモです。
対象読者の方
- ROS を使ったことがある(チュートリアルレベル)、Docker 初心者
- Dockerfile とか難しいこと言わずにコンテナ上で色々やってみたい方
準備
Docker のインストール
以下の記事を参考に、ubuntu 16.04 に Docker をインストールします。
参考記事
[Docker] ubuntu 14.04/16.04にDockerをインストール
[2020/05/01追記]
上の参考記事内でも触れられていますが,2017年に商用と無償版の Docker に分かれていたらしく,無償版は Docker CE という名前で提供されているようです.(詳しくはこちらの記事を参照)
Docker CE は下記の記事を参考にインストールしました.
Ubuntu16.04にDocker CEをインストール
Docker 実行時に sudo
を必要としない設定 (Optional)
参考記事
ユーザをdockerグループに入れる
※このあとは全てこの設定をしたものとして書いています。
※必要であれば docker
コマンド実行時に sudo
を足してください。
ROSの入ったubuntuのimageを取得
今回は ubuntu 18.04 に ROS melodic が入った image を取得します。
$ docker pull ros:melodic
取得した image を確認は
$ docker images
でできます。
REPOSITORY TAG IMAGE ID CREATED SIZE
ros melodic 9ca8b5b3f443 5 weeks ago 1.21GB
Dockerコンテナの作成
$ docker run -it --name work ros:melodic
ここではコンテナの名前を work
にしてみました。
$ docker ps
を実行すると、現在起動しているコンテナ一覧を確認することができます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09b23b1203b4 ros:melodic "/ros_entrypoint.s..." 7 seconds ago Up 6 seconds work
[参考] コンテナの停止、起動
コンテナの停止は起動しているコンテナ上で exit
コマンドでできる。
再びコンテナを起動するときは
$ docker ps -a
で、先ほど停止したコンテナIDか名前を確認し、起動後コンテナに入ります。
$ docker start [コンテナID or 名前]
$ docker attach [コンテナID or 名前]
今回の場合は、コンテナの名前を work
にしたので、
$ docker start work
$ docker attach work
でコンテナに復帰できます。
ROSチュートリアル
基本的には以下の ROS 公式のチュートリアルを Docker上で行いますが、適宜不要な箇所は省いています。
ROSのワークスペースの作成
先ほど作成したコンテナ上で、
$ cd ~
$ mkdir -p catkin_ws/src
packageの作成
$ cd ~/catkin_ws/src
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
c++ で talker と listener の node を書く
$ cd ~/catkin_ws/src/beginner_tutorials
$ mkdir src
beginner_tutorials/src
に以下の talker.cpp
と listener.cpp
をコピペする。(コメントは削除済)
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}
CMakeLists.txtの編集
以下を CMakeLists.txt
の末尾に追加
## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
ソースファイルのビルド
$ apt install python-catkin-tools
$ source /opt/ros/melodic
$ cd ~/catkin_ws
$ catkin build
Docker image の作成
ここまで作成したコンテナを image として保存します。
exit
で現在いるコンテナから抜け、
$ docker commit work ros:melodic-tutorials
を実行すると、先ほどまで作業していた work
コンテナを melodic-tutorials
というタグの image として保存します。
Docker のネットワークの作成
コンテナ間で通信をするためのネットワークを作成します。
$ docker network create rosnet
ROS では同一ネットワークにコンテナを入れるだけでなく、ROS_MASTER_URI
を適切に設定する必要があります。(後述)
talker と listener による topic の通信
roscore の起動
$ docker run -it --rm --net rosnet --name master ros:melodic-tutorials
$ roscore
別の端末で、
$ docker run -it --rm --net rosnet --name talker ros:melodic-tutorials
$ source ~/catkin_ws/devel/setup.bash
$ ROS_MASTER_URI=http://master:11311
$ rosrun beginner_tutorials talker
これで端末上に以下のような表示がされます。
[ INFO] [1539528505.137138966]: hello world 0
[ INFO] [1539528505.237245343]: hello world 1
[ INFO] [1539528505.337358401]: hello world 2
[ INFO] [1539528505.437382734]: hello world 3
[ INFO] [1539528505.537352617]: hello world 4
[ INFO] [1539528505.637456156]: hello world 5
[ INFO] [1539528505.737825399]: hello world 6
さらに別の端末で、
$ docker run -it --rm --net rosnet --name listener ros:melodic-tutorials
$ source ~/catkin_ws/devel/setup.bash
$ ROS_MASTER_URI=http://master:11311
$ rosrun beginner_tutorials listener
これで、talker の publish した topic を subscribe して以下のように端末上に表示します。
[ INFO] [1539528505.438633299]: I heard: [hello world 3]
[ INFO] [1539528505.538363467]: I heard: [hello world 4]
[ INFO] [1539528505.638404233]: I heard: [hello world 5]
[ INFO] [1539528505.739407586]: I heard: [hello world 6]
[参考] コンテナの作成時に node を実行する方法
beginner_tutorials ではないですが、こちらの記事で紹介されていたので、興味のある方は参考にしてみてください。
参考記事
Docker + ROS(kinetic)でチュートリアル
参考文献
Docker
- [Docker] ubuntu 14.04/16.04にDockerをインストール
- ユーザをdockerグループに入れる
- Dockerコンテナの作成、起動〜停止まで
- Dockerの作業済みコンテナからイメージを作って移植を楽にする
- Docker + ROS(kinetic)でチュートリアル
- DockerとDocker-CEの違いについて
- Ubuntu16.04にDocker CEをインストール