環境
この記事は以下の環境で動いています。
項目 | 値 |
---|---|
CPU | Core i5-8250U |
Ubuntu | 16.04 |
ROS | Kinetic |
インストールについてはROS講座02 インストールを参照してください。
またこの記事のプログラムはgithubにアップロードされています。ROS講座11 gitリポジトリを参照してください。
概要
意外と面倒なのがロボットの電源を切ることです。「sudo shutdown now」程度のコマンドなら簡単に行えますが、ロボットには通常時はキーボードやモニタがつながっていないのでこんなことも面倒です。
普通はsshで接続して電源を切るのですが
- ssh r_user@robot1
- パスワードを入力
- sudo shutdown now
- パスワードを入力
と意外と手間がかかります。これをroslaunchでリモートlaunchすることでコマンド1つで実行しようというのが今回の趣旨です。今回の記事では以下の2点を説明します。
- c++でbashコマンドを実行する方法
- sudoが必要なコマンドを実行する方法
c++でbashコマンド実行
C++のプログラム中からはsystem()
関数を使うとbashコマンドを実行できます。system()
関数を使うには#include <stdlib.h>
のインクルードをする必要があります。例えば以下のようにするとbashコマンドを実行できます。
#include <stdlib.h>
int main(void){
system(" COMMAND ");
return 0;
}
sudoコマンドの実行
上記の例を踏まえて以下のようなプログラムを実行すると失敗します。これはsudoを打つことによってパスワードを対話的に要求されてしまうためです。
#include <stdlib.h>
int main(void){
system("sudo shutdown now");
return 0;
}
これを解決する方法としてsudo -S
のオプションを使うという方法です。これはパスワードを標準入力から受け取るというオプションです。例えばパスワードがpasswordだった場合はecho 'password' | sudo -S command
とすると実行できてしまいます。パスワードが直書きなのでセキュリティー的には大変よろしくないのですが、一番簡単な解決策です。
結論
最終的な案を以下に示します。
#include <stdlib.h>
int main(void){
system("echo 'password' | sudo -S shutdown now");
return 0;
}
これを普通のROSのC++プログラムと同じようにCMakeList.txtを書いてコンパイルします。ROSのC++プログラムもただのC++プログラムにROSのライブラリを追加しただけのものです。
add_executable(net_shutdown src/net_shutdown.cpp)
target_link_libraries(net_shutdown
${catkin_LIBRARIES}
)
これをshutdownする対象のロボット上でbuildします。
これをlaunchファイルから起動します。
<launch>
<machine name="robot1" address="192.168.1.20" env-loader="/home/r_user/catkin_ws/devel/env.sh" user="r_user" password="password"/>
<node machine="robot1" pkg="adv_lecture" type="robot_shutdown" name="robot_shutdown" required="true"/>
</launch>
<machine>
タグではshutdownをする対象のPC(ロボット)を指定します。このROSノードを起動するとPCがシャットダウンするのでROSノードももちろん落ちます。この時にrequired="true"
を指定しておくとそのROSノードが落ちた時に自動的にlaunchも停止します。
roslaunch net_lecture remote_shutdown.launch
上のコマンドでネットワークでつながっている別のPC(ロボット)の電源を切ることができます。
この時robot_shutdown
はrobot1側で実行されるのでこのプログラムが入っているROSパッケージであるadv_lectureがrobot1に入っている必要があります。