ROSを使用したCRANE+の動かし方 その11(完結)

こんにちは!長谷川です。
前回はCRANE+の状態をモデルに反映させる方法について説明しましたが、今回は、CRANE+の状態をrviz上でモニタリングしつつ、CRANE+を自動で動かす方法について説明したいと思います。

使用するプログラム

実は、今回やろうとしていることは、すでに勉強したことの組み合わせで実現できます。
CRANE+を自動で動かすプログラムは第6回目の記事で作成済みですし、CRANE+の状態をrvizに反映させるプログラムも第10回目の記事で作成済みです。それぞれのプログラムで立ち上げられるノード名、関係するトピックは異なっているので、これら2つのプログラムを同時に起動できれば、目的を達成できることになります。

launchファイルの利便性

今まで勉強してきたことを組み合わせると、今回は以下のような手続きをすればいいことになります。

1: CRANE+とPCを接続
2: 「sudo chmod 6666 /dev/ttyUSB0」と端末に入力
3: 「roslaunch my_dynamixel_tutorial controller_manager.launch」と入力
4: 新しい端末を開き、「roslaunch roslaunch my_dynamixel_tutorial start_tilt_controller.launch」と入力
5: crane_urdf/srcに移動し、「roslaunch crane_urdf display.launch model:=crane.urdf」と入力
6: 新しい端末を開き、「rosrun crane_urdf reflect_crane_in_rviz」と入力
7: 新しい端末を開き、「rosrun turtlebot_arm turtlebot_arm」と入力

・・・面倒ですね。この面倒な作業を軽減するため、新たなlaunchファイルを作ることにします。これにより、少なくとも5〜7までの手順をコマンド1回で行うことができるようになります。プログラムの方に多少手を加えれば、3〜7までの作業をコマンド1回でできるようになります。

ROSのlaunchファイルについて

前回、display.launchというlaunchファイルを作りましたが、この時にはlaunchファイルについて詳しく説明しませんでした。今回は、display.launchについても詳しく説明しつつ、新しいlaunchファイルを作っていこうと思います。
launchファイルとは、様々なプログラムを組み合わせ、複数のノードを同時に立ち上げることができるファイルです。「roslaunch」というコマンドは、このlaunchファイルを起動するためのものだった、というわけです。このファイルに書いておけば、立ち上げたい全てのノードを1回のコマンドで立ち上げることができます。いちいち「rosrun」する必要がなくなるのです。しかもこのlaunchファイル、内部で他のlaunchファイルも実行することができます。また、それぞれのプログラムに対するパラメータも、ファイル内で決めておくことができるのです。このような機能により、操作がとても楽になります。それだけでなく、プログラムを別個の処理ごとに分けることが容易になるので、モジュール化と再利用性の向上を図ることができるのです。今回の場合では、CRANE+を動かすプログラムとCRANE+の状態をrvizに反映させるプログラムは独立に動いているので、CRANE+の動かし方を変えたいときは、CRANE+を動かすプログラムのみ変更すればいいという事になります。

新しいlaunchファイルの作成

例のごとく解説は後回しにして、まずはlaunchファイルを作ってしまいましょう。
端末に、
[php]
$ roscd crane_urdf/src
$ vi auto_crane_rviz.launch
[/php]
と入力します。以下を貼り付けます。
[xml]
<launch>
<param name="robot_description" textfile="$(find crane_urdf)/src/crane.urdf" />
<param name="use_gui" value="False"/>
<rosparam param="source_list">["joint_states_source"]</rosparam>

<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" required="true" />
<node name="reflect_crane_in_rviz" pkg="crane_urdf" type="reflect_crane_in_rviz" />
<node name="turtlebot_arm" pkg="turtlebot_arm" type="turtlebot_arm" />
</launch>
[/xml]
貼り付けたら、保存してviを終了してください。これで、新しいlaunchファイルが完成です。

実行

早速、新しいlaunchファイルを実行してみましょう。
第5回目の記事にしたがって、CRANE+とPCを接続し、「roslaunch my_dynamixel_tutorial start_tilt_controller.launch」まで入力してください。これで、1〜4までの手続きが終わりました。その後、端末に、
[php]roslaunch crane_urdf auto_crane_rviz.launch[/php]
と入力します。これで、CRANE+も動き始め、rvizも起動すると思います。天板上で動くので、天板にPC等を置くのは危険です。

launchファイルの解説

auto_crane_rviz.launchを見ながら、launchファイルの書き方について学びましょう。
[xml firstline=”1″]<launch>[/xml]
[xml firstline=”11″]</launch>[/xml]
この2つで囲まれた部分が、launchファイルとして認識されます。
[xml firstline=”2″]<param name="robot_description" textfile="$(find crane_urdf)/src/crane.urdf" />[/xml]
ここでは、robot_descriptionというパラメータに、crane_urdfパッケージのsrcディレクトリ内にあるcrane.urdfファイルを設定します。パラメータというのは、変数のことです。パラメータサーバというパラメータを共有できる仕組みがあって、ノードがそこで定義されたパラメータを読み込んで動作に反映させています。このパラメータをノードの外から変更することで、ノードの設定を変えることができます。
こちらこちらを読むと、robot_descriptionというのは、joint_state_publisherとrobot_state_publisherにおいて、ロボットのURDFデータを格納するパラメータのようです。ここに、第8回目の記事で作成したcrane.urdfを設定することで、モデルを読み込ませます。
[xml firstline=”3″]<param name="use_gui" value="False"/>[/xml]
先ほど紹介したページを読むと、use_guiというのは、joint_state_publisherにおいて、各関節の値をスライドバーで変更できるウィンドウを出すかどうかを決めるパラメータのようです。ここにFalseという値を設定することで、ウィンドウを出さない設定にします。なお、前の行ではパラメータ名を指定した後、「textfile=」と書いていましたが、これはファイルの中身をパラメータに設定するためのコマンドです。この行では、値を直接設定するため、「value=」と書いています。
[xml firstline=”4″]<rosparam param="source_list">["joint_states_source"]</rosparam>[/xml]
rosparamタグは、先ほど使ったparamタグに似ています。paramは主にひとつずつパラメータを設定しますが、rosparamはyamlファイルという、パラメータをまとめてあるファイルを読み込んで、複数のパラメータを一度に設定することが可能です。この行では、yamlファイルを読み込んでいるわけではなく、source_listという一つのパラメータしか設定していません。ですが、source_listには文字列のリスト型を設定しなくてはならず、paramタグではリスト型を設定できるのかよくわからないため、rosparamタグを使用しました。なおリスト型というのは、例えば[3, 4]のように値を並べたものです。source_listパラメータの働きについては、前回説明しましたので、割愛します。
[xml firstline=”6″]<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />[/xml]
ここではノードを立ち上げています。「name=”joint_state_publisher”」で、立ち上げるノード名をjoint_state_publisherとし、「pkg=”joint_state_publisher”」でノードの動作が書かれた実行ファイルはjoint_state_publisherパッケージにあると宣言します。次に、「type=”joint_state_publisher”」で、joint_state_publisherが実行するファイルであると宣言します。以上の項目が、ノードを立ち上げるために必要な最低限の宣言です。
[xml firstline=”8″]<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" required="true" />[/xml]
ここもノードを立ち上げる文ですが、いくつかオプションが付け加えられています。「args」というのは、ノードに渡す引数です。端末上でプログラムを起動するとき、コマンドライン上で引数を渡すことができますが、あれと同じようなものですね。「required」というのは、ノードが停止した時にroslaunchを停止させるかどうかを設定できます。ここに「true」を設定しているので、rvizノードが停止すると、roslaunch全体が停止します。

これで、auto_crane_rviz.launchで何が行われていたかは大体説明できたと思います。launchファイルについてもっと詳しく勉強したい方は、こちらをご覧ください。で、読んでいくと、includeタグなるものがあります。これは、launchファイル内で他のlaunchファイルを実行するためのタグです。これを使うと、「roslaunch my_dynamixel_tutorial controller_manager.launch」と「roslaunch roslaunch my_dynamixel_tutorial start_tilt_controller.launch」もauto_crane_rviz.launch内で実行することができます。この場合、以下のように書けばOKです。
[xml]
<launch>
<param name="robot_description" textfile="$(find crane_urdf)/src/crane.urdf" />
<param name="use_gui" value="False"/>
<rosparam param="source_list">["joint_states_source"]</rosparam>

<include file="$(find my_dynamixel_tutorial)/controller_manager.launch" />
<include file="$(find my_dynamixel_tutorial)/start_tilt_controller.launch" />
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" required="true" />
<node name="reflect_crane_in_rviz" pkg="crane_urdf" type="reflect_crane_in_rviz" />
<node name="turtlebot_arm" pkg="turtlebot_arm" type="turtlebot_arm" />
</launch>
[/xml]
ところが、これだと起動当初にCRANE+が暴走します。なぜかというと、controller_manager.launchやstart_tilt_controller.launchの処理が終わっていない状態、つまり初期設定ができていない状態で他のプログラムが走りだすからです。これを解決するためには、reflect_crane_in_rviz.cppやturtlebot_arm.cppの最初にwaitを入れてやればいいです。または、ROSだけに頼らず、シェルスクリプトを使うという手もありますが、今回は割愛したいと思います。

以上、CRANE+の状態をrviz上でモニタリングしつつ、CRANE+を自動で動かす方法について説明しました。
とりあえず、CRANE+とROSの組み合わせでできることの基本は解説できたと思いますので、今回でCRANE+の連載は終わりにしたいと思います。ここまでお読み下さり、ありがとうございました。

ROSを使用したCRANE+の動かし方 その10

こんにちは!長谷川です。
この連載も、ついに10回目に突入しました。ここまで見てくださった皆様、本当にありがとうございます!
前回は、前々回作ったモデルと実物のCRANE+の連動のさせ方について説明しましたが、今回は、CRANE+の状態をモデルに反映させる方法について説明したいと思います。

依存関係の追加

今回書くプログラムを、前々回に作ったcrane_urdfパッケージ上で動かすためには、crane_urdfパッケージの依存パッケージが不足していると思います。そこで、依存関係を追加しましょう。端末を開いて、
[php]
$ roscd crane_urdf
$ vi CMakeLists.txt
[/php]
と入力します。前回はこの末尾に3文貼り付けましたが、今回は違う場所を編集します。
[php firstline=”7″]
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
sensor_msgs
std_msgs
)
[/php]
などと書かれているところがあると思います。roscpp,rospy,sensor_msgs,std_msgsの順番は、パッケージを作った際に記述した順番などにもよると思うので、あまり気にしないでください。この依存パッケージ群の中に、dynamixel_msgsを追加します。具体的には、以下のように修正します。
[php firstline=”7″]
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
sensor_msgs
dynamixel_msgs
std_msgs
)
[/php]
ここを書き直し終わったら、保存してviを終了してください。
次に、[php]vi package.xml[/php]と入力して、package.xmlを開きましょう。
[xml firstline=”42″]
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>std_msgs</run_depend>
[/xml]
などと書かれているところがあると思います。他の依存パッケージの例にならって、dynamixel_msgsも追加します。具体的には、以下のように修正します。
[xml firstline=”42″]
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>dynamixel_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>dynamixel_msgs</run_depend>
<run_depend>std_msgs</run_depend>
[/xml]
修正し終わったら、保存してviを終了してください。これで、依存関係の追加は完了しました。

新しいdisplay.launchの作成

前回、
[php]roslaunch urdf_tutorial display.launch model:=crane.urdf gui:=True[/php]
なる命令を実行していました。この際、urdf_tutorialというパッケージ内のdisplay.launchを立ち上げていましたが、このdisplay.launchのままだと、今回実行したいプログラムが実行できません。そこで、新たなdisplay.launchをcrane_urdf内に作ることにしました。端末に、
[php]
$ roscd crane_urdf/src
$ vi display.launch
[/php]
と入力します。以下を貼り付けます。
[xml]
<launch>
<arg name="model" />
<arg name="gui" default="False" />
<param name="robot_description" textfile="$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>
<rosparam param="source_list">["joint_states_source"]</rosparam>
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" required="true" />
</launch>
[/xml]
貼り付けたら、保存してviを終了してください。これで、新しいdisplay.launchが完成しました。完成しましたが、何やってるのかさっぱりな方も多いと思います。基本的には、urdf_tutorialパッケージのdisplay.launchの真似ですが、
[xml firstline=”6″] <rosparam param="source_list">["joint_states_source"]</rosparam>[/xml]
の一文を書き加えています。この後出てくるプログラムでは、joint_state_publisherノード(Joint State Publisherウィンドウを管理しているノード)に各関節の関節角データを送り、それをjoint_state_publisherノードがrvizに送ることにより、モデルを動かしているのですが、ここをよく読むとわかる通り、それをするためには、joint_state_publisherが購読するトピックを指定してあげなければなりません。指定方法は、source_listというパラメータに、トピックの名前を書き込んであげればいいようです。付け加えた文では、このsource_listに/joint_states_sourceというトピック名を書き込んでいます。これにより、display.launchが実行されると、/joint_states_sourceを購読しながら、その値に応じたメッセージを/joint_statesに配信してくれるjoint_state_publisherが起動することになります。なお、この際、/joint_states_sourceトピックが存在していない場合は、自動で生成されるようです。

プログラムの作成

次に、プログラムを作成しましょう。
crane_urdf/srcにいる状態で、[php]vi reflect_crane_in_rviz.cpp[/php]と入力します。以下を貼り付けます。
[cpp]
#include "ros/ros.h"

#include "std_msgs/Float64.h"
#include "sensor_msgs/JointState.h"
#include "dynamixel_msgs/MotorStateList.h"

#include <sstream>

#define PI 3.14159265
#define MIDDLE_VAL 512
#define CHANGE_TO_DEG (300.0/1024.0)
#define CHANGE_TO_RAD (PI/180.0)

sensor_msgs::JointState jointstate;
char renew = 0;

void reflect_jointstate(const dynamixel_msgs::MotorStateList::ConstPtr& motorstates);

int main(int argc, char **argv)
{
ros::init(argc, argv, "reflect_crane_in_rviz");

ros::NodeHandle n;

ros::Publisher joint_states_pub = n.advertise<sensor_msgs::JointState>("/joint_states_source", 10);

ros::Subscriber sub = n.subscribe("/motor_states/pan_tilt_port", 10, reflect_jointstate);

ros::Rate loop_rate(100);

jointstate.name.push_back("joint1");
jointstate.name.push_back("joint2");
jointstate.name.push_back("joint3");
jointstate.name.push_back("joint4");
jointstate.name.push_back("joint5");
jointstate.position.push_back(0.0);
jointstate.position.push_back(0.0);
jointstate.position.push_back(0.0);
jointstate.position.push_back(0.0);
jointstate.position.push_back(0.0);

while (ros::ok())
{
while(ros::ok() && renew==0){
ros::spinOnce();
loop_rate.sleep();
}
jointstate.header.stamp = ros::Time::now();
joint_states_pub.publish(jointstate);
renew = 0;

ros::spinOnce();
loop_rate.sleep();
}
return 0;
}

void reflect_jointstate(const dynamixel_msgs::MotorStateList::ConstPtr& motorstates)
{
int id;
for(id=1;id<=5;id++){
jointstate.position[id-1] = ((double)(motorstates->motor_states[id-1].position)-MIDDLE_VAL)*CHANGE_TO_DEG*CHANGE_TO_RAD;
}
renew = 1;
}
[/cpp]
貼り付けたら、保存してviを終了してください。これがソースコードになります。今まで、ファイルを実行可能にする処理をしてきましたが、あれは別にいらなかったようなので、今回は飛ばします。
次に、
[php]
$ roscd crane_urdf
$ vi CMakeLists.txt
[/php]
と入力します。末尾に以下の3文を貼り付けます。
[php]
add_executable(reflect_crane_in_rviz src/reflect_crane_in_rviz.cpp)
target_link_libraries(reflect_crane_in_rviz ${catkin_LIBRARIES})
add_dependencies(reflect_crane_in_rviz crane_urdf_generate_messages_cpp)
[/php]
これで保存してviを終了してください。
次に、crane_urdfパッケージをビルドしましょう。
[php]
$ cd ~/catkin_ws/
$ catkin_make
[/php]
と入力します。「「100%」 Built target reflect_crane_in_rviz」と出てきていたら、ビルドが成功していると思います。

CRANE+とモデルの連動

以上で準備は整いました。第5回目の記事にしたがって、CRANE+とPCを接続し、今回は「roslaunch my_dynamixel_tutorial controller_manager.launch」
まで入力してください。「roslaunch my_dynamixel_tutorial start_tilt_controller.launch」まで入力してしまうと、CRANE+の関節角が固定されてしまい、手で動かせなくなるのでご注意ください。もしそうなった場合は、一回Ctrl-cを押してROSを終了してから、CRANE+の電源を切り、その後再度電源をいれ、操作をやり直してください。
その後、新しい端末を開いて、
[php]
$ roscd crane_urdf/src
$ roslaunch crane_urdf display.launch model:=crane.urdf
[/php]
と入力して、rvizを表示します。新しい端末を開き、
[php]rosrun crane_urdf reflect_crane_in_rviz[/php]
と入力すれば、rviz内のモデルが実物のCRANE+の状態を反映するようになります。けがやCRANE+の破壊に注意しながら、CRANE+の各関節を手で動かしてみてください。モデルとCRANE+が同じように動くと思います。なお、モデルに定義された回転角の限界以上まで関節を回すと、変な動きをしてしまいますが、ご容赦ください。

以上、CRANE+の状態をモデルに反映させる方法について説明しました。
次回は、CRANE+の状態をrviz上でモニタリングしつつ、CRANE+を自動で動かすプログラムを作ってみたいと思います。

ROSを使用したCRANE+の動かし方 その9

こんにちは!長谷川です。
前回はCRANE+のURDFモデルの作り方について説明しましたが、今回は、前回作ったモデルと実物のCRANE+の連動のさせ方について説明したいと思います。

プログラムの作成

まずは、モデルとCRANE+を連動させるプログラムを作成しましょう。端末を起動し、
[php]
$ roscd crane_urdf/src
$ vi reflect_rviz_in_crane.cpp
[/php]
と入力してviを起動します。以下を貼りつけます。
[cpp]
#include "ros/ros.h"

#include "std_msgs/Float64.h"
#include "sensor_msgs/JointState.h"

#include <sstream>

std_msgs::Float64 pos1;
std_msgs::Float64 pos2;
std_msgs::Float64 pos3;
std_msgs::Float64 pos4;
std_msgs::Float64 pos5;
char renew = 0;

void reflect_jointstate(const sensor_msgs::JointState::ConstPtr& jointstate);

int main(int argc, char **argv)
{
ros::init(argc, argv, "reflect_rviz_in_crane");

ros::NodeHandle n;

//publish command message to joints/servos of arm
ros::Publisher joint1_pub = n.advertise<std_msgs::Float64>("/tilt1_controller/command", 1000);
ros::Publisher joint2_pub = n.advertise<std_msgs::Float64>("/tilt2_controller/command", 1000);
ros::Publisher joint3_pub = n.advertise<std_msgs::Float64>("/tilt3_controller/command", 1000);
ros::Publisher joint4_pub = n.advertise<std_msgs::Float64>("/tilt4_controller/command", 1000);
ros::Publisher joint5_pub = n.advertise<std_msgs::Float64>("/tilt5_controller/command", 1000);

ros::Subscriber sub = n.subscribe("/joint_states", 10, reflect_jointstate);

ros::Rate loop_rate(100);
while (ros::ok())
{
while(ros::ok() && renew==0){
ros::spinOnce();
loop_rate.sleep();
}
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);
renew = 0;

ros::spinOnce();
loop_rate.sleep();
}
return 0;
}

void reflect_jointstate(const sensor_msgs::JointState::ConstPtr& jointstate)
{
pos1.data = jointstate->position[0];
pos2.data = jointstate->position[1];
pos3.data = jointstate->position[2];
pos4.data = jointstate->position[3];
pos5.data = jointstate->position[4];

renew = 1;
}
[/cpp]
これが、C++言語で書かれたソースコードになります。貼りつけたら、保存してviを終了してください。その後、
[php]chmod +x reflect_rviz_in_crane.cpp[/php]
と入力して、ファイルを実行可能にしておきましょう。
次に、
[php]
$ roscd crane_urdf
$ vi CMakeLists.txt
[/php]
と入力します。末尾に以下の3文を貼りつけます。
[php]
add_executable(reflect_rviz_in_crane src/reflect_rviz_in_crane.cpp)
target_link_libraries(reflect_rviz_in_crane ${catkin_LIBRARIES})
add_dependencies(reflect_rviz_in_crane crane_urdf_generate_messages_cpp)
[/php]
これで保存してviを終了してください。
次に、crane_urdfパッケージをビルドしましょう。
[php]
$ cd ~/catkin_ws/
$ catkin_make
[/php]
と入力します。「Linking ~」と書かれた一文の後に、「「100%」 Built target reflect_rviz_in_crane」と出てきていたら、ビルドが成功していると思います。

CRANE+とモデルの連動

これで準備は整ったので、CRANE+を実際に動かしてみましょう。第5回目の記事にしたがって、CRANE+とPCを接続し、「roslaunch my_dynamixel_tutorial start_tilt_controller.launch 」まで入力してください。
その後、
[php]
$ roscd crane_urdf/src
$ roslaunch urdf_tutorial display.launch model:=crane.urdf gui:=True
[/php]
と入力して、rvizとJoint State Publisherウィンドウを表示します。新しい端末を開き、
[php]rosrun crane_urdf reflect_rviz_in_crane[/php]
と入力すれば、実物のCRANE+がモデルの状態を反映するようになります。けがやCRANE+の破壊に注意しながら、Joint State Publisherウィンドウのバーを動かしてみてください。モデルとCRANE+が同じように動くと思います。
※天板上で動くので、天板にPC等を置くのは危険です。
※関節の可動範囲は最低限しか制限していないので、アームの先端が天板に当たったり、リンク同士がぶつかる可能性があります。CRANE+を破壊したり、けがをすることがないよう、無理のない速度と範囲で動かしてください。
※関節に指を挟まないよう注意してください。

プログラムの解説

今回のプログラムには、第7回目の記事で解説していない部分があるので、そこを説明したいと思います。
[cpp firstline=”32″]ros::Subscriber sub = n.subscribe("/joint_states", 10, reflect_jointstate);[/cpp]
ここで、/joint_statesというトピックを購読することを宣言しています。このトピックに新しいメッセージが来ると、reflect_jointstate()が呼び出されます。10というのは蓄えることのできるデータの最大数で、第7回で説明したものと同じ意味です。
なお、この/joint_statesには、Joint State Publisherが関節角を配信しており、そのトピックをrvizが購読して、取得した関節角をモデルに反映させることで、GUIでモデルを動かせるようになっています。このプログラムは、その仕組みを利用し、関節角をrvizとは独立して取得してCRANE+に反映させることで、CRANE+をrviz内のモデルと同じように動かしています。
[cpp firstline=”54″]void reflect_jointstate(const sensor_msgs::JointState::ConstPtr& jointstate)[/cpp]
この関数が呼び出された際、自動的に引数に新しいメッセージの内容が引き渡されます。つまり、sensor_msgs::JointState型のポインタjointstateの指し示すインスタンスには、新しいメッセージの内容が格納されています。
[cpp firstline=”56″]pos1.data = jointstate->position[0];[/cpp]
jointstate->position[0]には、モデルのjoint1の関節角が格納されています。それをpos1.dataに格納し、メイン文でpos1を/tilt1_controller/commandに配信することで、CRANE+のjoint1の関節角に反映します。

以上、前回作ったモデルと実物のCRANE+の連動のさせ方について説明しました。
次回は、CRANE+の状態をモデルに反映させる方法について説明したいと思います。

ROSを使用したCRANE+の動かし方 その8

こんにちは!長谷川です。
前回はROSのプログラムの書き方について説明しましたが、今回はCRANE+のURDFモデルの作り方について説明したいと思います。

URDFモデルとは

URDFとはUnified Robot Description Formatの略で、ロボットの形状や関節軸構成などのハードウェア情報を、XMLという形式で記録したものです。パッケージそのものの説明はこちらにあります。モデルの作り方についてのWikiはこちらにあるので、これをもとに説明を進めて行きたいと思います。

CRANE+のモデルについて

CRANE+の関節軸構成を以下のように分析し、名前付けします。
ROS_CRANE_8_0
これに基づき、モデルを構成していきます。なお、座標系は右手系です。

パッケージ、ファイルの作成

解説は後回しにして、まずは実際にモデルを作ってみましょう。端末を起動して、
[php]
$ cd ~/catkin_ws/src
$ catkin_create_pkg crane_urdf std_msgs rospy roscpp sensor_msgs
[/php]
と入力し、crane_urdfパッケージを作ります。この作業は今回のURDFモデル作成自体とは関係ありません。以前作成したturtlebot_armパッケージなどの上でモデルを作ることも可能ですが、次回紹介するプログラムを動かすためにはsensor_msgsに依存したパッケージを作らなければならないので、今回することにしました。
次に、
[php]
$ cd crane_urdf/src
$ vi crane.urdf
[/php]
と入力してviを起動します。編集モードに入り、以下を貼り付けます。
[xml]
<?xml version="1.0"?>
<robot name="crane">

<link name="base_link">
<visual>
<origin xyz="0 0 0.0227" rpy="0 0 0" />
<geometry>
<box size="0.0499 0.032 0.0454" />
</geometry>
<material name="red">
<color rgba=".8 0 0 1" />
</material>
</visual>
</link>

<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0.0145 0 0.0454" rpy="0 0 0" />
<axis xyz="0 0 1" />
<limit lower="-2.61" upper="2.61" effort="0.5" velocity="6.0" />
</joint>

<link name="link1">
<visual>
<origin xyz="0 0 0.013" rpy="0 0 0" />
<geometry>
<box size="0.024 0.0475 0.026" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0 0.026" rpy="1.57079632675 0 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>
</link>

<joint name="joint2" type="revolute">
<parent link="link1"/>
<child link="link2"/>
<origin xyz="0 0 0.026" rpy="0 0 0" />
<axis xyz="0 1 0" />
<limit lower="-1.75" upper="1.75" effort="0.5" velocity="6.0" />
</joint>

<link name="link2">
<visual>
<origin xyz="0 0 0" rpy="1.57079632675 0 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0 0.0415" rpy="0 0 0" />
<geometry>
<box size="0.024 0.0475 0.083" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0 0.083" rpy="1.57079632675 0 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>
</link>

<joint name="joint3" type="revolute">
<parent link="link2"/>
<child link="link3"/>
<origin xyz="0 0 0.083" rpy="0 0 0" />
<axis xyz="0 -1 0" />
<limit lower="-2.55" upper="2.55" effort="0.5" velocity="6.0" />
</joint>

<link name="link3">
<visual>
<origin xyz="0 0 0" rpy="1.57079632675 0 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0 0.04675" rpy="0 0 0" />
<geometry>
<box size="0.024 0.0475 0.0935" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0 0.0935" rpy="1.57079632675 0 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>
</link>

<joint name="joint4" type="revolute">
<parent link="link3"/>
<child link="link4"/>
<origin xyz="0 0 0.0935" rpy="0 0 0" />
<axis xyz="0 -1 0" />
<limit lower="-1.80" upper="1.80" effort="0.5" velocity="6.0" />
</joint>

<link name="link4">
<visual>
<origin xyz="0 0 0" rpy="1.57079632675 0 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0 0.0227" rpy="0 0 0" />
<geometry>
<box size="0.024 0.0475 0.061" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0.03295 0.065727241" rpy="-0.52359878 0 0" />
<geometry>
<box size="0.034 0.0014 0.019" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 0.0377 0.09665" rpy="0 0 0" />
<geometry>
<box size="0.034 0.0014 0.0454" />
</geometry>
<material name="red" />
</visual>
</link>

<joint name="joint5" type="revolute">
<parent link="link4"/>
<child link="link5"/>
<origin xyz="0 -0.0145 0.045" rpy="0 0 0" />
<axis xyz="-1 0 0" />
<limit lower="-0.69" upper="0.69" effort="0.5" velocity="6.0" />
</joint>

<link name="link5">
<visual>
<origin xyz="0 0 0" rpy="0 1.57079632675 0" />
<geometry>
<cylinder radius="0.012" length="0.0475" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 -0.013 0" rpy="0 0 0" />
<geometry>
<box size="0.0475 0.026 0.024" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 -0.0267 0.023" rpy="0 0 0" />
<geometry>
<box size="0.034 0.0014 0.070" />
</geometry>
<material name="red" />
</visual>

<visual>
<origin xyz="0 -0.0166252378 0.07545" rpy="-0.52359878 0 0" />
<geometry>
<box size="0.034 0.0014 0.040299" />
</geometry>
<material name="red" />
</visual>
</link>

</robot>
[/xml]
これがURDFモデルを記述した内容になります。貼りつけたら、保存してviを終了してください。これでモデル作成は完了です。

モデルの確認

次に、作成したURDFファイルが正しいフォーマットになっているか確認してみましょう。まず、
[php]sudo apt-get install liburdfdom-tools[/php]
と入力し、チェックのためのコマンドをインストールします。次に、
[php]check_urdf crane.urdf[/php]
と入力すると、以下のように表示されました。
ROS_CRANE_8_2
これで、正しいフォーマットになっていることが確かめられました。
そこで、
[php]roslaunch urdf_tutorial display.launch model:=crane.urdf[/php]
と入力すると、rviz(ROSのビジュアライザ)が起動し、何やら表示されます。
ROS_CRANE_8_3
拡大すると、以下のようにロボットモデルができていることがわかります。
ROS_CRANE_8_4
赤と緑と青の棒は、各関節のx,y,z軸を表しています。白い文字でlinkの名前も書かれていますね。ですが、これでは見にくいので、「Displays」欄内の「TF」に入っているチェックを外します。すると、以下のように、CRANE+を模したモデルができていることがわかります。
ROS_CRANE_8_5
あまりCRANE+に似ていないモデルですみません・・・。色も赤一色ですし・・・。このモデルは、私がURDFファイルの書き方の練習用に作ったものなので、書きやすい直方体と円筒のみで構成され、なんとなく外形を似せている状態です。あくまで練習用なので、ご容赦ください。
端末にCtrl-Cを打ち込んででrvizを終了し、今度は
[php]roslaunch urdf_tutorial display.launch model:=crane.urdf gui:=True[/php]
と入力してみてください。
ROS_CRANE_8_6
今までのrvizの他に、Joint State Publisherなるウィンドウが表示されたと思います。ここに表示されたバーを動かすことで、モデルの各関節を動かすことができます。
ROS_CRANE_8_7

URDFファイルのデータ構造

モデルの表記の仕方について、crane.urdfを見つつ学びましょう。
[xml firstline=”2″]<robot name="crane">[/xml]
[xml firstline=”194″]</robot>[/xml]
この二つに囲まれた部分で、一体のロボットが宣言されます。「crane」の所には他の名前を入れても機能します。
[xml firstline=”4″]<link name="base_link">[/xml]
[xml firstline=”14″]</link>[/xml]
リンク名「base_link」を定義したのち、この二つに囲まれた部分でリンクの状態を定義しています。リンク名はロボット内で唯一のものでなければなりません。なお、base_linkはロボット全体の中心となるリンクであり、必須のリンクとなっています。
[xml firstline=”5″]<visual>[/xml]
[xml firstline=”13″]</visual>[/xml]
この中で、リンク(この行ではbase_link)内の一つの物体についてのビジュアルを定義しています。
[xml firstline=”6″]<origin xyz="0 0 0.0227" rpy="0 0 0" />[/xml]
「xyz=”」の右には、根元のジョイントを原点とした時の、記述している物体の中心のxyz座標[m]を記入します。「rpy=”」の右には、物体を回転させる角度を記入します。
[xml firstline=”7″]<geometry>[/xml]
[xml firstline=”9″]</geometry>[/xml]
この中で、物体の形状を定義します。
[xml firstline=”8″]<box size="0.0499 0.032 0.0454" />[/xml]
記述している物体が、x方向に0.0499[m],y方向に0.032[m],z方向に0.0454[m]の厚みを持つ直方体であると定義しています。
[xml firstline=”10″]<material name="red">[/xml]
[xml firstline=”12″]</material>[/xml]
materialタグは、物体の表面の見栄えを定義するタグです。ここでは、この中で宣言された見栄えを「red」と定義することも同時に宣言しています。
[xml firstline=”11″]<color rgba=".8 0 0 1" />[/xml]
ここで、表面の色を定義しています。この数字だと赤色になるようです。
[xml firstline=”16″]<joint name="joint1" type="revolute">[/xml]
[xml firstline=”22″]</joint>[/xml]
ジョイント名「joint1」を定義したのち、この二つに囲まれた部分でジョイントの状態を定義しています。ジョイント名はロボット内で唯一のものでなければなりません。「type=”」の右には、ジョイントの種類を記入します。ジョイントの種類は以下のように定義されています。
revolute・・・ヒンジ機構
continuous・・・無限回転機構
prismatic・・・直動機構
fixed・・・固定関節
floating・・・自由関節
planar・・・水平移動機構
今回はrevolute、つまりヒンジ機構としています。
[xml firstline=”17″]<parent link="base_link"/>[/xml]
ジョイントの根元にあるリンク(親リンク)がbase_linkであると定義しています。
[xml firstline=”18″]<child link="link1"/>[/xml]
ジョイントの先にあるリンク(子リンク)がlink1であると定義しています。
[xml firstline=”19″]<origin xyz="0.0145 0 0.0454" rpy="0 0 0" />[/xml]
「xyz=”」の右には、親リンクの原点を基準とした、記述しているジョイントのxyz座標[m]を記入します。ここで、親リンクの原点とは、親リンクが最初のリンク(今回はbase_link)の場合はロボットモデル全体の原点、それ以外の場合は親リンクの根元のジョイントの位置を指します。「rpy=”」の右には、ジョイントを最初から回転させる角度を記入します。
[xml firstline=”20″]<axis xyz="0 0 1" />[/xml]
「xyz=”」の右には、回転関節の場合の回転軸の方向を記入します。回転軸の方向に進む右ねじが回る向きを正として、関節が回ることになります。
[xml firstline=”21″]<limit lower="-2.61" upper="2.61" effort="0.5" velocity="6.0" />[/xml]
ここでは、関節のリミットを設定しています。関節がrevoluteやprismaticの場合は、下限値にあたるlowerと、上限値にあたるupperを設定する必要があります。単位は、revoluteの場合は[rad]、prismaticの場合は[m]となっています。
effortとは、ジョイントが発揮できるトルク[Nm]または力[N]の絶対値の最大値のことです。今回は、0.5Nm以上のトルクを発揮できないよう制限されているということになります。
velocityとは、ジョイントの動く速度[m/s]または角速度[rad/s]の絶対値の最大値のことです。今回は、6.0rad/s以上の角速度で動かないよう制限されているということになります。
[xml firstline=”30″]<material name="red" />[/xml]
これは、先ほど定義した「red」という見栄えを物体の見栄えとすることを宣言しています。
[xml firstline=”36″]<cylinder radius="0.012" length="0.0475" />[/xml]
これは、記述している物体が半径0.012[m]、長さ0.0475[m]の円筒であると定義しています。ちなみに、
[xml]<sphere radius="1"/>[/xml]
と書くと、半径1[m]の球となります。また、
[xml]<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae" scale="1."/>[/xml]
などと、ファイルに記述された形状を反映させることも可能です。ファイル形式は、Colladaの.dae形式(推奨)と、.stl形式がサポートされています。

以上で、データ構造の基本は説明できたと思います。これ以上はこの記事では扱わないことにします。
その他の物理パラメータの設定方法や、拡張形式xacroの話については、チュートリアルの続きをご覧になってください。
また、シュミレータGazeboにモデルを読み込ませるためには、ファイルを変更しなければなりません。こちらをご覧になってください。

以上、CRANE+のURDFモデルの作り方について説明しました。
次回は、今回作ったモデルと実物のCRANE+の連動のさせ方について説明したいと思います。

ROSを使用したCRANE+の動かし方 その7

こんにちは!長谷川です。
前回はCRANE+の全ての関節を同時に、かつ自動で動かす方法について説明しましたが、今回はその時出てきたソースコードの解説を通して、ROSのプログラムの書き方について説明したいと思います。

プログラムについてのチュートリアル

ここにC++でのプログラムの書き方が載っていまして、ここ
に実行の仕方が載っています。以上二つに基づいて解説を進めていきます。

ROSで使えるプログラミング言語

ROSでは、PythonとC++の二種類の言語を使うことができます。これは便利なことに思えますが、実はいろいろとめんどくさいです。例えば、C++で書かれたノードがトピックを介してPythonで書かれたノードにデータを送るとしましょう。もしトピックのデータ型を、ノードを起動するプログラム内でfloatとして定義できるとしたら、そのデータ型をPythonにそのまま引き継げるでしょうか?言語が違えばデータ型の定義も違うので、難しいことになります。そこで、トピックのデータ型などは言語によらず共通に定義されています。今の例でいえば、トピックのデータ型をstd_msgs::Float64と定義します。std_msgs::Float64はROS内でPythonでも使えるデータ型になっているので、データを正確に受け渡しできるというわけです。

プログラムの解読

それでは、前回のプログラムを解読していきましょう。
[cpp firstline=”1″]#include "ros/ros.h"[/cpp]
お馴染みのヘッダーのインクルードですが、ros/ros.hをインクルードすると、ROS のシステムでよく用いる部分を使うのに必要なヘッダーをすべてインクルードできます。
[cpp firstline=”6″]#include "std_msgs/Float64.h"[/cpp]
このヘッダーのインクルードにより、先ほど出てきたデータ型、std_msgs::Float64が使えるようになります。今回、CRANE+を動かすために用意したトピックのデータ型はすべてこれなので、インクルードが必要です。
[cpp firstline=”8″]#include <sstream>[/cpp]
文字列ストリームを使うためのヘッダーです。今回は使わないのでいらないのですが、チュートリアル見ながらプログラムを作っていたときに入れてしまいました。
[cpp firstline=”13″]ros::init(argc, argv, "turtlebot_arm");[/cpp]
ROSの初期化をして、このプログラムで起動するノードの名前を指定します。今回は「turtlebot_arm」です。名前には、/を含んではいけないみたいです。
[cpp firstline=”15″]ros::NodeHandle n;[/cpp]
ノードへのハンドラなるものを作成します。ここではnという名前で作成しました。ハンドラとは名前空間を管理するものです。ちなみに、ここでノードの初期化が行われ、最後のハンドラが破棄されるとノードの終了処理に入ります。
[cpp firstline=”18″]
ros::Publisher joint1_pub = n.advertise<std_msgs::Float64>("/tilt1_controller/command", 1000);
[/cpp]
ここで、std_msgs::Float64型のトピック/tilt1_controller/commandに、データの配信を行うことを宣言します。テンプレートを使った宣言です。1000というのは、蓄えることのできるデータの最大数です。トピックにデータが配信されると、そのトピックが購読されるまでデータが保持されなければなりませんが、トピックが購読される前に次の配信が行われてしまう可能性があります。この時、前のデータがすぐ消えないように、キューで値を保持します。このキューの個数が1000個ということです。joint1_pubというros::Publisher型インスタンス(メモリを確保したクラス)が定義されていますが、これは後ですぐに使います。
[cpp firstline=”23″]std_msgs::Float64 pos1;[/cpp]
std_msgs::Float64型のインスタンスpos1を宣言します。これを経由してデータの配信を行います。
[cpp firstline=”29″]pos1.data = 0.0;[/cpp]
pos1のメンバ変数dataに、0.0という値を代入します。
[cpp firstline=”34″]joint1_pub.publish(pos1);[/cpp]
18行目で宣言したjoint1_pubのpublishメソッドを用いることで、トピックへのデータの配信が行えます。この場合は、引数をpos1に設定しているので、pos1がトピックへ配信されます。実質的には、トピック/tilt1_controller/commandに、0.0という値を配信しているようなものです。この値がID1のサーボモータの回転角になることは前回述べた通りなので、サーボモータに回転角を指示していることになります。
[cpp firstline=”40″]ros::Rate loop_rate(0.5);[/cpp]
これで、ループ頻度を設定することができます。この場合は、0.5Hzで駆動するということです。具体的には、loop_rate.sleep()を呼び出してからどれだけ時間が経過したかを常に管理し、次にloop_rate.sleep()が呼び出された際、前回のスリープが終わってから2秒たつまでスリープします。
[cpp firstline=”42″]while (ros::ok())[/cpp]
ros::ok()というのは、以下のような場合にfalseを返す関数です。
・Ctrl-Cが押され、SIGINTシグナルを受け取った時。
・同じ名前のノードができたために,ネットワークから外された時。
・アプリケーションの他の部分でros::shutdown()が呼ばれた時。
・全ての ros::NodeHandles が破棄された時。
以上の場合、falseが返されてwhile文から抜けるため、プログラムが終了します。
[cpp firstline=”184″]ros::spinOnce();[/cpp]
トピックを購読する場合は必須の処理です。これがないとコールバックが呼ばれず、トピックを購読することができません。トピックを購読しようと思っている場所では、必ず繰り返し呼び出すようにしてください。

以上で、ROSのプログラムの書き方の基本は説明できたと思います。次回は、CRANE+のURDFモデルの作り方について説明したいと思います。

ROSを使用したCRANE+の動かし方 その6

こんにちは!長谷川です。
前回はCRANE+を動かすための環境の構築について説明しましたが、今回はCRANE+の全ての関節を同時に、かつ自動で動かす方法について説明したいと思います。

ROSのノードとトピックについて

CRANE+を動かす前に、ROSのシステムの一つ、ノードとトピックについて勉強しなければなりません。
ノードとは、ROSパッケージ内の実行ファイルです。ROSでは多くの場合、複数のノードが起動していて、それぞれの処理のために情報をやりとりしています。例えば、あるノードが常にロボットの位置を計測していて、そのノードからロボットの位置情報を受け取った別のノードが、目的の位置にロボットを動かす、といった具合です。このノード間の情報のやりとりに使われるのがトピックです。各ノードは、やりとりする情報をメッセージとしてトピックに配信し、配信されたメッセージをトピックを購読することで受け取ることができます。上の例で言えば、ロボットの位置情報についてのトピックがあって、位置計測を行うノードはそのトピックに位置情報を配信し、ロボットを動かすノードはそのトピックを購読して位置情報を受け取る、というわけです。
ROS_CRANE_6_1
前回の最後に、
[php]rostopic pub -1 /tilt_controller/command std_msgs/Float64 — 1.5[/php]
というコマンドをご紹介しましたが、このコマンドは、「/tilt_controller/commandというトピックに、std_msgs/Float64というデータ型で1.5という値を配信する」という意味です。/tilt_controller/commandというトピックは、モーターを動かすノードに購読されていまして、そのノードがモーターに設定されている中心位置からこのトピックに入った値(単位はラジアン)だけずれた位置を目標にしてサーボを動かします。3.1415…ラジアン=180度です。
つまり、上のコマンドで、tilt.yamlに記述されたIDのサーボモーターが基準位置から1.5ラジアンだけずれた位置まで動くように指令を送ったというわけです。なので、最後の数字を-1.5とした命令を入力すると、モーターは左右対称な位置まで動きます。

環境の構築

前回は、tilt.yamlなるファイルを作りましたが、今回はこのようなyamlファイルを各モーターに1個ずつ、計5個作ることになります。ID1~5のモーターに、tilt1.yaml~tilt5.yamlをそれぞれ対応させます。まずは、tilt1.yamlを作りましょう。端末に
[php]
$ roscd my_dynamixel_tutorial
$ vi tilt1.yaml
[/php]
と入力してviを起動します。編集モードに入り、以下の内容を貼り付けます。
[php]
tilt1_controller:
controller:
package: dynamixel_controllers
module: joint_position_controller
type: JointPositionController
joint_name: tilt_joint
joint_speed: 1.17
motor:
id: 1
init: 512
min: 0
max: 1023
[/php]
貼り付けたらEscapeを押してコマンドモードに戻り、「:wq」と打ち込んで、tilt1.yamlを保存してviを終了します。同様に、tilt2.yaml~tilt5.yamlを作ります。一行目のtilt1_controllerの1の代わりに各モーターのIDを書き、9行目の「id:」の右側に各モーターのIDを書いてください。

次に、チュートリアルで作ったstart_tilt_controller.launchを、5個のモーターを動かせるように書き換えます。新しいファイルを作ってもいいですが、その場合は、以降の「start_tilt_controller.launch」を自分の設定したファイル名に読み替えてください。端末に[php]vi start_tilt_controller.launch[/php]と入力し、viを起動します。前回書いたものは邪魔になるので、コマンドモードのままddを押していき、何もなくなった所でiを押して編集モードに入ります。以下を貼り付けます。
[php]
<launch>
<!– Start tilt joint controller –>
<rosparam file="$(find my_dynamixel_tutorial)/tilt1.yaml" command="load"/>
<node name="tilt1_controller_spawner" pkg="dynamixel_controllers" type="controller_spawner.py"
args="–manager=dxl_manager
–port pan_tilt_port
tilt1_controller"
output="screen"/>

<!– Start tilt joint controller –>
<rosparam file="$(find my_dynamixel_tutorial)/tilt2.yaml" command="load"/>
<node name="tilt2_controller_spawner" pkg="dynamixel_controllers" type="controller_spawner.py"
args="–manager=dxl_manager
–port pan_tilt_port
tilt2_controller"
output="screen"/>

<!– Start tilt joint controller –>
<rosparam file="$(find my_dynamixel_tutorial)/tilt3.yaml" command="load"/>
<node name="tilt3_controller_spawner" pkg="dynamixel_controllers" type="controller_spawner.py"
args="–manager=dxl_manager
–port pan_tilt_port
tilt3_controller"
output="screen"/>

<!– Start tilt joint controller –>
<rosparam file="$(find my_dynamixel_tutorial)/tilt4.yaml" command="load"/>
<node name="tilt4_controller_spawner" pkg="dynamixel_controllers" type="controller_spawner.py"
args="–manager=dxl_manager
–port pan_tilt_port
tilt4_controller"
output="screen"/>

<!– Start tilt joint controller –>
<rosparam file="$(find my_dynamixel_tutorial)/tilt5.yaml" command="load"/>
<node name="tilt5_controller_spawner" pkg="dynamixel_controllers" type="controller_spawner.py"
args="–manager=dxl_manager
–port pan_tilt_port
tilt5_controller"
output="screen"/>
</launch>
[/php]
貼り付けたらEscapeを押してコマンドモードに戻り、「:wq」と打ち込んで、start_tilt_controller.launchを保存してviを終了します。
これで、チュートリアルと同じように「roslaunch my_dynamixel_tutorial start_tilt_controller.launch」まで入力し、「rostopic pub -1 /tilt(動かしたいモーターのID)_controller/command std_msgs/Float64 — 1.5」と入力すると、該当するモーターが動きます。例えば、[php]rostopic pub -1 /tilt1_controller/command std_msgs/Float64 — 1.5[/php]と入力すると、根元のモーターが動きます。これで、コマンドを手打ちすることによりCRANE+を動かすことができるようになりました。

プログラムによる自動駆動

次は、プログラムにより、あらかじめ決めておいた動きを自動でCRANE+にさせてみましょう。少し長くなるので、CRANE+との接続は一旦切っておいた方がいいと思います。まず、端末に
[php]
$ cd ~/catkin_ws/src
$ catkin_create_pkg turtlebot_arm std_msgs rospy roscpp
[/php]
と入力して、catkin_wsのソースディレクトリに移動してからturtlebot_armパッケージを作成します。(この作業は、ここの「4. catkin形式のパッケージを作る」に基づいています。)そして、
[php]
$ cd turtlebot_arm/src
$ vi turtlebot_arm.cpp
[/php]
と入力してviを起動します。編集モードに入り、以下を貼り付けます。
[cpp]
#include "ros/ros.h"
/**
* turtlebot_arm.cpp – move turtlebot arm according to predefined gestures
*/

#include "std_msgs/Float64.h"

#include <sstream>

int main(int argc, char **argv)
{

ros::init(argc, argv, "turtlebot_arm");

ros::NodeHandle n;

//publish command message to joints/servos of arm
ros::Publisher joint1_pub = n.advertise<std_msgs::Float64>("/tilt1_controller/command", 1000);
ros::Publisher joint2_pub = n.advertise<std_msgs::Float64>("/tilt2_controller/command", 1000);
ros::Publisher joint3_pub = n.advertise<std_msgs::Float64>("/tilt3_controller/command", 1000);
ros::Publisher joint4_pub = n.advertise<std_msgs::Float64>("/tilt4_controller/command", 1000);
ros::Publisher joint5_pub = n.advertise<std_msgs::Float64>("/tilt5_controller/command", 1000);
std_msgs::Float64 pos1;
std_msgs::Float64 pos2;
std_msgs::Float64 pos3;
std_msgs::Float64 pos4;
std_msgs::Float64 pos5;
//Initial gesture of robot arm
pos1.data = 0.0;
pos2.data = 0.0;
pos3.data = 0.0;
pos4.data = 0.0;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

ros::Rate loop_rate(0.5);

while (ros::ok())
{
//gesture 1
pos1.data = -0.9;
pos2.data = 0.0;
pos3.data = 0.0;
pos4.data = 0.0;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 2
pos1.data = -0.9;
pos2.data = 0.9;
pos3.data = 1.8;
pos4.data = 1.0;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 3
pos1.data = -0.9;
pos2.data = 0.9;
pos3.data = 1.8;
pos4.data = 1.0;
pos5.data = 0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 4
pos1.data = -0.9;
pos2.data = 0.0;
pos3.data = 0.0;
pos4.data = 0.0;
pos5.data = 0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 5
pos1.data = 0.95;
pos2.data = 0.0;
pos3.data = 0.0;
pos4.data = 0.0;
pos5.data = 0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 6
pos1.data = 0.95;
pos2.data = 0.3;
pos3.data = 2.0;
pos4.data = -0.2;
pos5.data = 0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 7
pos1.data = 0.95;
pos2.data = 0.3;
pos3.data = 2.0;
pos4.data = -0.2;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 8
pos1.data = 0.95;
pos2.data = 0.4;
pos3.data = 0.0;
pos4.data = -0.2;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//gesture 9
pos1.data = 0.95;
pos2.data = 0.0;
pos3.data = 0.0;
pos4.data = 0.0;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

//Initial gesture of robot arm
pos1.data = 0.0;
pos2.data = 0.0;
pos3.data = 0.0;
pos4.data = 0.0;
pos5.data = -0.3;
joint1_pub.publish(pos1);
joint2_pub.publish(pos2);
joint3_pub.publish(pos3);
joint4_pub.publish(pos4);
joint5_pub.publish(pos5);

loop_rate.sleep();

ros::spinOnce();
}

return 0;
}
[/cpp]
これがC++言語で書かれたソースコードになります。このソースコードについての解説は、次回行いたいと思います。貼り付けたらEscapeを押してコマンドモードに戻り、「:wq」と打ち込んで、turtlebot_arm.cppを保存してviを終了します。その後、[php]chmod +x turtlebot_arm.cpp[/php]と入力して、ファイルを実行可能にしておきましょう。

次に、
[php]
$ roscd turtlebot_arm
$ vi CMakeLists.txt
[/php]
と入力します。色々出てきますが、末尾に以下の3文を貼り付けます。
[php]
add_executable(turtlebot_arm src/turtlebot_arm.cpp)
target_link_libraries(turtlebot_arm ${catkin_LIBRARIES})
add_dependencies(turtlebot_arm turtlebot_arm_generate_messages_cpp)
[/php]
これで保存してviを終了してください。
次に、このturtlebot_armパッケージをビルドしましょう。
[php]
$ cd ~/catkin_ws/
$ catkin_make
[/php]
と入力します。「Linking ~」と書かれた一文の後に、「「100%」 Built target turtlebot_arm」と出てきていたら、ビルドが成功していると思います。

ここまで実行したら、CRANE+とPCを接続し、チュートリアルと同じ手順で「roslaunch my_dynamixel_tutorial start_tilt_controller.launch」まで入力してください。端末に
[php]
rosrun turtlebot_arm turtlebot_arm
[/php]
と入力すると、CRANE+が自動で動きだすと思います。天板上で動くので、天板にPC等を置くのは危険です。物をつかんで運ぶ動きをすると思うので、ペットボトルをつかませて遊んでみましょう。

以上、CRANE+の全ての関節を同時に、かつ自動で動かす方法について説明しました。
次回は、今回出てきたソースコードの解説を通して、ROSのプログラムの書き方について説明したいと思います。

ROSを使用したCRANE+の動かし方 その5

こんにちは!長谷川です。
前回はROSのパッケージの作成とビルドについて説明しましたが、今回はCRANE+を動かすための環境の構築について説明したいと思います。

CRANE+を動かすためのチュートリアル

ここを見ていただくとわかりますが、「CRANE+」はROBOTIS社製のサーボモーターDynamixelシリーズの一つ、AX-12Aを使用しております。ROSには、このDynamixelシリーズを動かすパッケージがすでに用意されていまして、ここにインストールの方法が書かれています。また、ここにチュートリアルがあるので、基本的にはこれに従えばCRANE+のモーターを動かすことができます。チュートリアルは、Connecting to Dynamixel busCreating a joint controllerの順になります。

通信環境の構築

まず、パッケージをインストールしましょう。端末(Terminal)を開き、
[php]sudo apt-get install ros-indigo-dynamixel-motor[/php]
と入力します。
パスワードを要求された場合は入力します。これで、必要なパッケージはインストールされました。

次に、チュートリアルに従って作業していきましょう。最初に、今回使用するパッケージを作成しなければならないのですが、ROS_PACKAGE_PATHに登録されたディレクトリに作らないとroscdとかが使えなくなっちゃいます。
試しに、ROS_PACKAGE_PATHに登録されているディレクトリを表示してみましょう。
端末に
[php]echo $ROS_PACKAGE_PATH[/php]
と入力します。すると、この連載の通りにインストールを行っていた場合は、3個のディレクトリが:で区切られて表示されると思います。このうち、/opt/ros/indigo/shareと/opt/ros/indigo/stacksはroot権限でしかアクセスできないので、ここに作ってしまうと後々困ったことになります。そして、(ホーム・ディレクトリ)/catkin_ws/srcは、catkin workspace内なので、ここに作るとビルドに巻き込まれる可能性があり、めんどくさいところです。
そこで今回は、新たなディレクトリを作って、そのディレクトリをROS_PACKAGE_PATHに登録しましょう。ディレクトリ名は、(ホーム・ディレクトリ)/ros_craneにします。私の環境でのホーム・ディレクトリは/home/turtlebotなので、/home/turtlebot/ros_craneになりますね。
ご自分のディレクトリにしたい場合は、そのディレクトリ名に読み替えてやっていただいて構いませんが、root権限のディレクトリにしてしまうと不具合が起きるので、気を付けてください。

それでは、実際に作業していきましょう。
[php]mkdir /home/turtlebot/ros_crane[/php]
と入力して、/home/turtlebot/ros_craneを作ります。
次に、ROS_PACKAGE_PATHに登録します。恒久的に登録しておいたままにするために、~/.bashrcに設定を追記しておきましょう。
[php]vi ~/.bashrc[/php]
と入力し、エディタviで~/.bashrcを開くなどして、次の2行を最終行に追加して保存します。
[php]
PATH=$PATH:/home/turtlebot/ros_crane
ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:/home/turtlebot/ros_crane
[/php]
端末でのエディタviの使い方については、ここでは省略させていただきます。慣れていないと混乱するので、必ず調べてください。
その後、端末に、
[php]source ~/.bashrc[/php]
と入力します。
これで~/.bashrcに書いた環境が設定されます。

次に、今回使用するパッケージを作成しましょう。
[php]cd /home/turtlebot/ros_crane[/php]
と入力してディレクトリを移動します。
その後、
[php]
$ catkin_create_pkg my_dynamixel_tutorial dynamixel_controllers
$ roscd my_dynamixel_tutorial
[/php]
と入力してパッケージを作成し、そのパッケージに移動します。なお、チュートリアルではroscreate-pkgを使っていますが、これはcatkin導入以前のパッケージ作成命令なので、catkin_create_pkgを使うべきだと思われます。

さて、次に実行ファイルを作成していくわけなのですが、そのファイル上ではCRANE+がパソコンのどのUSBポートに刺さっているのかが重要になります。それを調べましょう。
まず、CRANE+のアームから出ている信号線が電源供給用の基板(SMPS2DYNAMIXEL)につながっていることと、そこから出た信号線がUSBコネクタのついたデバイス(USB2DYNAMIXEL)につながっていることをご確認ください。
ROS_CRANE_5_1
次に、SMPS2DYNAMIXELから出た電源ケーブルが、kobukiの「12V 5A」と書かれたコネクタに接続されていることをご確認ください。
ROS_CRANE_5_2
以上が確認できれば、CRANE+を動かすためのハードウェアの準備は整っています。次に、USB2DYNAMIXELの側面にあるスイッチをTTLモードに切り替えます。
ROS_CRANE_5_3
これを忘れると、全く接続できないので、ご注意ください。最後に、USB2DYNAMIXELをパソコンに接続します。これで接続は完了です。
パソコンにつながっているUSBデバイスをUSB2DYNAMIXELだけにしてから、新しい端末を開き、そこに[php]ls /dev/ttyUSB*[/php]と入力します。すると、「/dev/ttyUSB0」とか「/dev/ttyUSB1」などと表示されます。これが、CRANE+が接続されているUSBポート名になります。
私の場合は、/dev/ttyUSB0と表示されたので、これを前提に以下の操作を進めます。ここで一旦USB2DYNAMIXELをパソコンから抜くと、ポート名が変わる恐れがあります。多くの場合では接続した順番でttyUSB0、ttyUSB1、・・・と命名されていくと思われますが、USB2DYNAMIXELを抜く場合は、再接続の際にポート名を再確認するなどした方が無難です。

ポートの情報が確認できたので、これをもとに実行ファイルを作成していきましょう。前に使っていた端末に[php]vi controller_manager.launch[/php]と入力し、エディタviを起動します。なぜ前に使っていた端末に入力するのかというと、controller_manager.launch ファイルはmy_dynamixel_tutorialの中に作らなければならないからです。viの画面が開いたら、iを押して編集モードに入ってから、以下の内容を貼り付けます。
[php]
<!– -*- mode: XML -*- –>

<launch>
<node name="dynamixel_manager" pkg="dynamixel_controllers" type="controller_manager.py" required="true" output="screen">
<rosparam>
namespace: dxl_manager
serial_ports:
pan_tilt_port:
port_name: "/dev/ttyUSB0"
baud_rate: 1000000
min_motor_id: 1
max_motor_id: 25
update_rate: 20
</rosparam>
</node>
</launch>
[/php]
なお、「port_name:」の右側には、CRANE+がつながっているUSBポート名を入力してください。また、チュートリアルにはbaud rate(ボーレート)をきちんと気にしろみたいなことが書いてありますが、ここをご覧になるとわかります通り、AX-12Aの通信速度の初期設定は1Mbps、つまり1000000bpsなので、上に書いてあるbaud rateのままで大丈夫です。
貼り付けたらEscapeを押してコマンドモードに戻り、「:wq」と打ち込んで、controller_manager.launchを保存してviを終了します。

チュートリアルでは、次に、[php]roslaunch my_dynamixel_tutorial controller_manager.launch[/php]と入力するように指示されています。モーターとの通信を開始する命令のようなので、Turtlebotの電源を入れ、USB2DYNAMIXELをパソコンに接続してから新しい方の端末に入力してみると、エラーが出てきてしまいます。
ROS_CRANE_5_4
エラー文の赤文字の少し上に、「could not open port /dev/ttyUSB0: [Errno 13] Permission denied: ‘/dev/ttyUSB0’」と書かれていました。つまり、USBポートに接続できないみたいです。これは、ユーザーがUSBポートを読み書きできる権限を持たないというLinuxの初期設定によるもののようです。これを解決するため、全てのユーザーに/dev/ttyUSB0の読み書きを認めてしまうことにします。端末に[php]sudo chmod 6666 /dev/ttyUSB0[/php]と入力し、パスワードを求められた場合は入力します。これで、全てのユーザーに/dev/ttyUSB0の読み書きが認められました。この状態で[php]roslaunch my_dynamixel_tutorial controller_manager.launch[/php]と入力してみます。
すると、何やら処理が行われました。
ROS_CRANE_5_5
「pan_tilt_port: Found 5 motors」と端末に出力されたので、CRANE+を構成する5つのモーターをきちんと認識したことがわかります。これで接続は成功です。なお、USB2DYNAMIXELをパソコンから抜くと、USBポートのアクセス権限も初期値にリセットされてしまうので、USB2DYNAMIXELをパソコンにさすたびに全てのユーザーに/dev/ttyUSB0の読み書きを認めなくてはなりません。

さて、次はモーターからの信号を見てみましょう。新しい端末を開いて[php]rostopic list[/php]と入力すると、存在しているトピックが表示されます。トピックとは何かについてまだ何も解説していませんが、今回の記事でCRANE+を動かすところまで行きたいので、説明は次回に回します。今はデータのようなものだと思っておいてください。存在しているトピックのうち、「/motor_states/pan_tilt_port」がモーターの状態についてのトピックです。これの内容を、[php]rostopic echo /motor_states/pan_tilt_port[/php]と入力して、見てみましょう。
ROS_CRANE_5_6
この画面には、IDが4と5のモーターの状態が表示されているようです。CRANE+のモーターのIDは、Turtlebotに一番近い根元のサーボモーターから順に1,2,3,4,5と設定されているので、4と5にあたるモーターを手で動かしてみると、errorやpositionなどが変化することが分かります。

モーターの駆動

ここまででCRANE+とパソコンとの通信はできるようになったので、次はモーターを実際に動かしてみましょう。USB2DYNAMIXELを一旦抜く場合は、その前に処理中の2つの端末それぞれでCtrlを押しながらcを押し、処理を終わらせて下さい。
最初に開いた端末に
[php]vi tilt.yaml[/php]
と入力します。最初に開いた端末を閉じてしまっていた場合は、新しい端末を開いて[php]roscd my_dynamixel_tutorial[/php]と入力し、my_dynamixel_tutorialに移動してからviを起動してください。
編集モードに入り、以下の内容を貼り付けます。
[php]
tilt_controller:
controller:
package: dynamixel_controllers
module: joint_position_controller
type: JointPositionController
joint_name: tilt_joint
joint_speed: 1.17
motor:
id: 4
init: 512
min: 0
max: 1023
[/php]
なお、「id:」の右側には、今回操作するモーターのIDを入力します。貼り付けたらEscapeを押してコマンドモードに戻り、「:wq」と打ち込んで、tilt.yamlを保存してviを終了します。
次に、同じ端末に[php]vi start_tilt_controller.launch[/php]と入力し、viを起動します。編集モードに入り、以下の内容を貼り付けます。
[php]
<launch>
<!– Start tilt joint controller –>
<rosparam file="$(find my_dynamixel_tutorial)/tilt.yaml" command="load"/>
<node name="tilt_controller_spawner" pkg="dynamixel_controllers" type="controller_spawner.py"
args="–manager=dxl_manager
–port pan_tilt_port
tilt_controller"
output="screen"/>
</launch>
[/php]
貼り付けたらEscapeを押してコマンドモードに戻り、「:wq」と打ち込んで、start_tilt_controller.launchを保存してviを終了します。
そこまでできたら、CRANE+とパソコンを接続し、USBポートのアクセス権限を変更し、[php]roslaunch my_dynamixel_tutorial controller_manager.launch[/php]を入力する、という先ほどやったのと同じ操作を行います。先ほどUSB2DYNAMIXELを抜かず、処理も終了していなかった場合は、やらなくても大丈夫です。その後、新しい端末が必要な場合は開いて、[php]roslaunch my_dynamixel_tutorial start_tilt_controller.launch[/php]と入力します。すると、以下のように表示されるはずです。
ROS_CRANE_5_7
「Controller tilt_controller successfully started」と表示されているので、大丈夫でしょう。
最後に、[php]rostopic pub -1 /tilt_controller/command std_msgs/Float64 — 1.5[/php]と入力すると、IDが4のサーボモーターが一定の位置に固定されるはずです。モーターが動けば当然アームが動くので、アーム可動範囲にモノを置かないようにして行ってください。
動くサーボモーターはtilt.yamlに記述するIDを変更することで変えられます。このコマンド自体の意味は、次回で解説したいと思います。

以上、CRANE+を動かすための環境の構築について説明しました。
次回は、CRANE+の全ての関節を同時に、かつ自動で動かす方法について説明したいと思います。

※(2015/3/26追記)
上では、デバイスをUSBポートに接続し直すたびに、
[php]sudo chmod 6666 /dev/ttyUSB0[/php]
と書いて権限付与を行っていますが、これをいちいち書かなくてもよくなる方法があるそうです。以下でその方法を述べますが、当方では動作確認をしておりませんので、実行は自己責任でお願いします。
/dev/ttyUSB0などはdialoutグループだそうです。そして、グループ内からはポートを読み書きできる権限があります。つまり、ユーザをdialoutに追加してやれば、ポートを読み書きできるようになるということだそうです。例えば、turtlebotというユーザをdialoutグループに追加したい場合は、
[php]sudo usermod -a -G dialout turtlebot[/php]
と入力します。ここで、-aを忘れてしまうと、既に設定されていた他のグループの設定が全て飛んでしまい、sudoが効かなくなるなど大変なことになるので注意してください。リカバリーモードに頼らなければいけなくなってしまいます。
ともかく、これが成功すれば、いちいち権限付与しなくても接続できるようになります。

ROSを使用したCRANE+の動かし方 その4

こんにちは!長谷川です。
前回はROSの環境のセットアップとROSのファイルシステムについて説明しましたが、今回はROSのパッケージの作成とビルドについて説明したいと思います。
今回も前回同様、主に英語版Wikiのチュートリアルに従って進みます。日本語版Wikiのチュートリアルは情報が古いですが、英語版がわかりにくい場合、適宜参照すると理解の助けになると思います。

パッケージの作成

前回、パッケージとは何かをお話しましたが、パッケージはpackage.xmlとCMakeLists.txtを含んでいる必要があります。逆に言えば、最低限これらを含んでいれば、パッケージとして認められます。パッケージ作成においては、これらのひな形を自動で生成させ、それらを後から編集します。また、前回作ったようなcatkin workspaceを利用しながらパッケージを編集するのが推奨みたいですが、パッケージを単独でビルドすることも可能らしいです。以下では、チュートリアル通り、catkin workspaceを利用してパッケージを作成、ビルドします。

まず、端末(Terminal)を開き、
[php]
$ cd ~/catkin_ws/src
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
[/php]
と入力します。
ROS_CRANE_4_1
何か表示されましたね。どうやら、~/catkin_ws/srcの中に、beginner_tutorialsというパッケージが作成されたようです。
この場合、すでに一部のパッケージの依存関係が定められています。なぜかというと、「catkin_create_pkg」という命令は、[php]catkin_create_pkg <package_name> [depend1] [depend2] [depend3][/php]のように使用した場合、パッケージ[depend1],[depend2],[depend3]に依存するようなパッケージを作るからです。このことを、前回紹介したrospackを用いて確かめてみましょう。前回はrospackにfindというオプションをつけて使いましたが、今回はdepends1というオプションをつけます。これで依存関係を確認できるというわけです。[php]rospack depends1 beginner_tutorials[/php]と入力すると、roscpp,rospy,std_msgsが表示されました。これは、先にcatkin_create_pkgで指定した依存関係と同じですね。
さて、上の依存関係は当然package.xmlに記録されているはずです。確認してみましょう。
[php]
$ roscd beginner_tutorials
$ cat package.xml
[/php]
と入力します。
ROS_CRANE_4_2
[php]<build_depend>[/php]の後ろと、[php]<run_depend>[/php]の後ろに、roscpp,rospy,std_msgsが確認できますね。

次に、beginner_tutorialsが依存しているパッケージの依存関係(間接的な依存関係)を調べてみましょう。例えばrospyについては、先ほどと同じように
[php]rospack depends1 rospy[/php]
と入力するとわかります。
このような間接的な依存関係も含めて、指定したパッケージが依存するパッケージを全て列挙するのが、rospackにdependsというオプションをつけたものです。
[php]rospack depends beginner_tutorials[/php]
と入力すると、以下のようになります。
ROS_CRANE_4_3
要は、依存関係というのはかなり複雑だ、ということですね・・・。

次に、package.xmlを編集してみましょう。例として、
[php]
$ cd ~/catkin_ws/src/beginner_tutorials
$ vi package.xml
[/php]
と入力して、エディタviでpackage.xmlを開きます。
ROS_CRANE_4_4
チュートリアルによると、色々変えなきゃならないところがあるようですが、とりあえず例として、ライセンス部分を変えてみたいと思います。
[php]<license>[/php]
の後に書かれているTODOを、BSDと書き換えます。
ROS_CRANE_4_5
このようなライセンスの明記や、チュートリアルで指示される作成者の名前、連絡先のタグへの記入は、作成したパッケージが他の人に共有される際の障害を取り払うためのものです。それゆえ、作成したパッケージをアップロードする場合には必ず記入しておきましょう。

パッケージのビルド

次に、自分の作ったパッケージをビルドしてみましょう。ビルドというのは、ソースコードファイルを実行ファイルに変換することです。
[php]
$ cd ~/catkin_ws
$ ls src
[/php]
と入力して、CMakeLists.txt beginner_tutorialsが出てきたら、今までの作業がうまくいっているようです。
[php]catkin_make[/php]と入力します。すると、色々表示されて、ビルドが進行します。終わったら、[php]$ ls[/php]と入力してみます。
ROS_CRANE_4_6
buildとdevel、srcというフォルダがあることがわかります。これでビルドができていることが確認できました。

以上、ROSのパッケージの作成とビルドについて説明しました。
次回は、CRANE+を動かすための環境の構築について説明したいと思います。

ROSを使用したCRANE+の動かし方 その3

こんにちは!長谷川です。
前回はROSのインストールについて説明しましたが、今回はROSの環境のセットアップとROSのファイルシステムについて説明したいと思います。
今回は、主に英語版Wikiのチュートリアルに従って進みます。日本語版Wikiのチュートリアルは情報が古いですが、英語版がわかりにくい場合、適宜参照すると理解の助けになると思います。

環境の確認

まず、端末(Terminal)を開き、[php]export | grep ROS[/php]と入力します。すると、以下のように表示されました。
ROS_CRANE_3_1
これはROSの環境変数を表示させる機能のようで、表示されたということはセットアップがきちんと行われたということみたいです。もしも何も表示されない場合は、ROSの環境変数が宣言されていないということで、[php]source /opt/ros/indigo/setup.bash[/php]と打ち込まねばなりません。前回「~/.bashrc」を編集したのは、これを毎回打ち込む手間を省くためのものだったみたいです。

ワークスペースの作成

次に、ROSのワークスペースを作成します。
今回使うROSはROS Indigo Iglooなので、ROS Groovyより後に出たバージョンです。よって、catkinというビルドシステムを採用しているみたいです。catkinの方の説明に従って進めていきます。以下のように入力していってください。
[php]
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ catkin_init_workspace
[/php]
ここで、「$」というのは、コマンドプロンプトのことです。つまり、「$ 」より右の一文を打ち込んだらEnterを押すことを繰り返してください。次に、[php]cd ~/catkin_ws/[/php]と入力し、作ったワークスペースに移動してから、[php]catkin_make[/php]と打ち込みます。
Enterを押すと、処理が実行されます。これは、ワークスペースをビルドしろという命令のようです。最後に、[php]source devel/setup.bash[/php]と入力します。
最後の命令は、ビルドの結果生まれたsetupファイルを読み込むためのものです。この命令により、環境がセットアップされます。逆に言えば、この命令をしておかないと、ROSの機能の一部が使えません。端末(Terminal)を開き直した際は、
[php]
$ cd ~/catkin_ws/
$ source devel/setup.bash
[/php]
という処理をしておかねばならないことがあります。毎回これを打ち込む手間を省きたい場合は、前回と同じように、
[php]echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc[/php]
と入力して、「~/.bashrc」を編集しておきましょう。

ROSのファイルシステムについて

ROSのソフトウェアは、パッケージという構成単位から作られています。パッケージは結構自由になんでも入れられるものらしく、ライブラリやツール、実行ファイルなどを入れることができます。パッケージを入れられる、メタパッケージというものもあります。そして、package.xmlという名前がついたマニフェストというものにパッケージの説明が書かれています。この説明の中でパッケージ間の依存関係も宣言されています。
ROSのソフトウェアにおいては、大量のパッケージが複雑に絡み合うことになります。そのパッケージごとの作業の際は、端末(Terminal)の階層をいちいち移動しないといけません。よく使う命令は「cd」だと思いますが、これの後ろにパスを入れるのがメンドクサイ。この他にも、初期設定されてるコマンドだけでは、色々とやりづらいことが出てくるみたいです。そこで、ROSにはファイルシステムに関するツールが色々用意されています。以下では、それらを実際に使ってみましょう。

まずは、「rospack」という命令を使ってみましょう。
端末(Terminal)に、[php]rospack find roscpp[/php]と入力すると、「/opt/ros/indigo/share/roscpp」と表示されます。
「rospack」に「find」というオプションをつけると、パッケージのパスを表示してくれる機能になるみたいです。あのパッケージどこにあったっけ?ってなっても、いちいちパソコン全体の検索をすることなく、ROSのファイルシステム内部に絞って検索してくれるので、便利ですね。

次に、「roscd」という命令を使ってみましょう。
[php]
$ roscd roscpp
$ pwd
[/php]
と入力します。
ROS_CRANE_3_2
roscdは、指定したパッケージのディレクトリへ移動できる命令です。何がいいかというと、パッケージを名前で指定できるのがすばらしい。「pwd」というのはUnixのコマンドで、現在のディレクトリの場所を表示させる命令なので、「/opt/ros/indigo/share/roscpp」と表示されるということは、きちんと目標のroscppディレクトリに移動出来ていることになります。

なお、roscdもrospackも、$ROS_PACKAGE_PATHの中のディレクトリ以下にあるROSのパッケージのみを探し出します。ここに何が登録されてるのか知りたいときは、[php]echo $ROS_PACKAGE_PATH[/php]と入力します。
ROS_CRANE_3_3
「/home/turtlebot/catkin_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks」と表示されました。「:」は区切り文字です。つまり、「/home/turtlebot/catkin_ws/src」と「/opt/ros/indigo/share」と「/opt/ros/indigo/stacks」が登録されているということになります。このディレクトリ以下にあるものなら、名前だけで検索してくれるようですね。

roscdのお話に戻りましょう。roscdはパッケージのサブディレクトリ(パッケージに含まれているディレクトリ)に移動することもできます。
[php]
$ roscd roscpp/cmake
$ pwd
[/php]
と入力してみましょう。「/opt/ros/indigo/share/roscpp/cmake」と出てくるので、roscppのサブディレクトリcmakeに移動できたことがわかります。
ちなみに、roscdを引数なしで実行すると、$ROS_WORKSPACEに登録されているディレクトリに移動します。
ROS_CRANE_3_4
ここでは、「/home/turtlebot/catkin_ws/devel」に移動したことがわかります。
また、[php]roscd log[/php]と入力するとROS のログファイル保管フォルダへ移動しますが、まだROSプログラムを一つも実行していないので、ここには何もないみたいです。

次に、「rosls」という命令を使ってみましょう。
[php]rosls roscpp_tutorials[/php]と入力すると、「cmake package.xml srv」と表示されました。roslsという命令は、Unixコマンドのlsと同じように、指定したディレクトリのファイルの一覧を表示させるものです。lsと違うところは、後ろにパスではなく、ファイル名をそのまま入れられることです。今回は、roscpp_tutorialsというパッケージの中に含まれるファイルの一覧を表示させたということですね。

最後に、タブ補完という機能をご紹介します。
タブ補完とは、パッケージ名を書きかけの状態でTabを押すと、自動で可能な限り不足分を補ってくれる機能です。その書き出しから始まるパッケージがいくつかある場合は、それらに共通する部分だけを埋めます。その場合はもう一度Tabを押すと、該当するパッケージの一覧を表示させることもできるので、その一覧を参照して不足分を埋めることが可能です。

以上、ROSの環境のセットアップとROSのファイルシステムについて説明しました。
次回は、ROSのパッケージの作成とビルドについて説明したいと思います。

ROSを使用したCRANE+の動かし方 その2

こんにちは!長谷川です。
前回はROSそのものについての解説をしましたが、今回はROSを実際にインストールしてみましょう。
長くなると思いますが、環境が整わないとCRANE+を動かすこともできないので、ご辛抱ください。

使用PCの環境

この連載で使用するPCのOSはUbuntu 14.04 64bit版(日本語環境)です。インストールの仕方については、ここでは割愛させていただきます。一つ注意点を述べておきますと、他OSの仮想マシン上でUbuntuを走らせている場合、インターネット接続やUSBポートとの接続などに影響が出ることがあります。そのため、チュートリアル通りの作業でROSを動かしたい場合は、仮想マシンを使わず、直接Ubuntuをインストールすることをお勧めします。元々入っていたOSを残したい場合は、デュアルブート環境にするとよいでしょう。

ROSのインストール

ROSのインストールは、ROSのWikiとその日本語版に従って行います。どんどん更新されていくページなので、英語版と日本語版で違いが出ることがありますが、英語版が最新なので、それに従ってください。日本語版は理解の助けにしてください。
まず、「Install」のリンクを押します。現時点では「ROS Indigo installation instructions」のページに飛ぶので、「Select Your Platform」でUbuntuを選択します。すると、インストールの仕方が書かれたページに移動します。
なお、これはROS Indigo Iglooのインストールページです。Indigo IglooというのはROSのバージョンの名前で、Ubuntu 14.04に対応したROSになります。この一つ前のバージョンはROS Hydroというのですが、Ubuntu 14.04に対応していません。対応しているかいないかは、「1.2 Setup your sources.list」の所にバージョン名が上がっているかどうかで確認できます。今回は「Ubuntu 14.04 (Trusty) 」と書かれているため、大丈夫です。
ROS_CRANE_2_1
さて、「1.1 Configure your Ubuntu repositories」からやっていきましょう。貼られてるリンクをクリックして出てきたページを読んで、レポジトリの構成を行いました。コマンド打ち込みでもできるんでしょうが、私にそこまでの能力はないので、GUIを活用させてもらいましょう。デスクトップの左のプログラムバーから「システム設定」を開き、「ソフトウェアとアップデート」を開きます。
ROS_CRANE_2_2
この、main, universe, restricted, multiverseに全てチェック入れろってことみたいですね。ダウンロード元は「日本のサーバー」でも「メインサーバー」でも大丈夫だと思います。

次に、[Ctrl]+[Alt]+[T]キーで端末(Terminal)を開きます。そこに、
[php]sudo sh -c ‘echo "deb http://packages.ros.org/ros/ubuntu trusty main" > /etc/apt/sources.list.d/ros-latest.list'[/php]
と打ち込みます。Enterを押すと、パスワードを聞かれるので、打ち込みます。この時、端末には打ち込んだパスワードが表示されません。何文字打ち込んだかも表示されないので、打ち込んでも表示されない!とかあわてなくても大丈夫です。打ち終わったらEnterを押します。パスワードが間違っているともう一回聞いてくるので、入力し直しましょう。次に、
[php]wget https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -O – | sudo apt-key add -[/php]
と打ち込みます。Enterを押すと、色々表示されます。「OK」と表示されて、コマンドプロンプトが表示されたら、[php]sudo apt-get update[/php]と打ち込みます。
ROS_CRANE_2_3
Enterを押すとパッケージの更新作業が始まります。途中でパスワードを要求されたら入力し、コマンドプロンプトが表示されるまで待ちます。
ここまででインストールの下準備は完了して、次はいよいよインストールです。「Recommended」って書いてあるものをやるのが無難なので、[php]sudo apt-get install ros-indigo-desktop-full[/php]と入力します。途中でパスワードを要求されたら入力してください。コマンドプロンプトが表示されたら、[php]sudo rosdep init[/php]と入力します。次に、[php]rosdep update[/php]と入力します。この処理が終わると、ROSが使用可能になります。

次に環境設定を行います。[php]echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc[/php]と入力した後、[php]source ~/.bashrc[/php]と入力します。
一文目は、bashのセッションが新しいシェルを起動する度に、ROSの環境変数が自動的に追加されるよう、設定を書きかえるためのコマンドです。つまり、端末を起動するたびにROSの設定が自動的に行われ、すぐにROSが使えるようにするためのコマンドみたいです。コマンド自体がやっていることは、「~/.bashrc」というファイルの末尾に「source /opt/ros/indigo/setup.bash」という文を付け加えているだけなので、間違った文を付け加えてしまった場合は、~/.bashrcをエディタで開いて修正することができます。
二文目は、設定の変更を今開いている端末に反映させるためのコマンドです。
最後に、[php]sudo apt-get install python-rosinstall[/php]と入力します。これでROSのインストールの全作業が完了です。お疲れ様でした。

以上、ROSのインストールについてお話してきました。
次回は、ROSの環境のセットアップとROSのファイルシステムについて説明したいと思います。