#################################### ##FILL ME IN #################################### ## for a custom note with links: ## note =This tutorial assumes you have completed the writing a tf listener tutorial [[tf/Tutorials/Writing a tf listener (Python)|(Python)]] [[tf/Tutorials/Writing a tf listener (C++)|(C++)]] ## for the canned note of "This tutorial assumes that you have completed the previous tutorials:" just add the links ## note.0= ## descriptive title for the tutorial ## title =フレームを加える (C++) ## multi-line description to be displayed in search ## description = このチュートリアルではどのようにして特別な固定のフレームをtfに加えるかを学びます ## the next tutorial description (optional) ## next = tf and time ## links to next tutorial (optional) ## next.0.link=[[ja/tf/Tutorials/tf and Time (C++)|(C++)]] ## next.1.link= ## what level user is this tutorial for ## level= BeginnerCategory ## keywords = #################################### <<IncludeCSTemplate(TutorialCSHeaderTemplate)>> <<TableOfContents(4)>> <<Buildsystem()>> ##introstart 前回のチュートリアルの中で、tf broadcasterとtf listenerを加えることでturtle のデモを再現しました。今回のチュートリアルでは、どのようにtfツリーに特別なフレームを加えるかについて学んでいきましょう。この過程はtf broadcasterを作ることにとても似ていて、tfの利便さの一端を実感できるでしょう。 == なぜフレームを追加するのか == ほとんどのタスクにおいて、ローカルフレームの中について考えるのは簡単です、例えば、レーザスキャナの中心でのフレームでレーザスキャンを推論するのは簡単です。tfは、それぞれのセンサにローカルフレームを定義し、リンクし、そのほかのこともできるようにしてくれています。そして、tfは導入された特別なフレームのtransformもすべて管理してくれます。 == どこにフレームを追加すべきか == tfはフレームの'''木構造(tree structure)'''を作ります(フレーム構造の中に閉ループができることが許されません)。つまり、フレームは一つの親のみを持つが、子は複数もっているということです。現在、今までのチュートリアルでできたtfツリーは3つのフレームをもっています。ワールド、turtle1、turtle2です。二つのturtleは、worldの子にあたります。もし、新しいtfを加えたいなら、3つのすでにあるフレームが親のフレームになる必要があり、新しいフレームは子フレームになるでしょう。 {{attachment:tree.png||height="282px",width="315px"}} == どのようにフレームを加えるか == turtleの例を用いて、1匹目のturtleに新しいフレームを加えましょう。このフレームは2匹目のturtleにとって、"carrot"になるでしょう。 ソースファイルから作っていきましょう。まずは一つ前のチュートリアルで作ったパッケージのディレクトリに移動してください。: {{{ $ roscd learning_tf }}} ##introend === コード === エディタを立ち上げ、以下のソースコードを`src/frame_tf_broadcaster.cpp`として、コピー&ペーストして保存してください。 {{{ #!cplusplus block=broadcaster #include <ros/ros.h> #include <tf/transform_broadcaster.h> int main(int argc, char** argv){ ros::init(argc, argv, "my_tf_broadcaster"); ros::NodeHandle node; tf::TransformBroadcaster br; tf::Transform transform; ros::Rate rate(10.0); while (node.ok()){ transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) ); transform.setRotation( tf::Quaternion(0, 0, 0) ); br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "turtle1", "carrot1")); rate.sleep(); } return 0; }; }}} コードは[[ja/tf/Tutorials/Writing a tf broadcaster (C++)|tf broadcaster チュートリアル]]の例にとても似ています。 === コード解説 === このコードの中のキーとなる行を部分的に見ていきましょう。: <<CodeRef(broadcaster,13,15)>> ここで新しい親の`turtle1`から新しい子の`carrot1`へのtransformを作成しています。 `carrot1`フレームは、`turtle1`から左にオフセット2メートルのところです。 == frame broadcasterを実行する == コードがこれでできたので、まずコンパイルしてみましょう。CMakeLists.txtを開いて、以下の行をファイルの最後に追加してください。: {{{{{#!wiki buildsystem catkin {{{ add_executable(frame_tf_broadcaster src/frame_tf_broadcaster.cpp) target_link_libraries(frame_tf_broadcaster ${catkin_LIBRARIES}) }}} パッケージをビルドします;(catkinワークスペースのトップディレクトリにて): {{{ $ catkin_make }}} }}}}} {{{{{#!wiki buildsystem rosbuild {{{ rosbuild_add_executable(frame_tf_broadcaster src/frame_tf_broadcaster.cpp) }}} パッケージをビルドします: {{{ $ make }}} ビルドが全て成功すると、binフォルダの中にturtle_tf_broadcasterと呼ばれるバイナリファイルが出来ているはずです。 }}}}} このデモのためのlaunchファイル(start_demo.launch)を編集する段階に入りましょう。以下のものを<launch>タグのブロックの中にnodeブロックとしてマージします。: {{{ <launch> ... <node pkg="learning_tf" type="frame_tf_broadcaster" name="broadcaster_frame" /> </launch> }}} ##checkingstart まず、前回のチュートリアルのlaunchファイルは止めていることを確認してください(ctrl-cを使ってください)。これで、turtleのデモを始める準備ができました。 {{{ $ roslaunch learning_tf start_demo.launch }}} == 結果を確認する == もし一匹目のturtleを動かしたら、新しいフレームを加えたのにもかかわらず、以前のチュートリアルと動きが変わっていないことに気づくと思います。それは、特別なフレームを加えることは他のフレームになんら影響を与えないからで、listenerは今はまだ以前に定義されたフレームを使用しています。それでは、ここでlistenerの振る舞いを変えてみましょう。 ##checkingend `src/turtle_tf_listener.cpp`を開いて、`"/turtle1"`を`"/carrot1"`に26-27行あたりを置き換えてください: {{{ #!cplusplus block=broadcaster listener.lookupTransform("/turtle2", "/carrot1", ros::Time(0), transform); }}} 心強いことに、ただリビルドをして再スタートするだけで、2匹目の亀がcarrotを1匹目の亀の代わりに追いかけているのが見えると思います。carrotは`turtle1`の左2メートルを常に動いていることを覚えていてください。そこには、キャロットに該当する視覚的な表示はそこにありませんが、それを追っかけて2匹目の亀が動いているのが見えると思います。 {{{{{#!wiki buildsystem catkin {{{ $ catkin_make $ roslaunch learning_tf start_demo.launch }}} }}}}} {{{{{#!wiki buildsystem rosbuild {{{ $ make $ roslaunch learning_tf start_demo.launch }}} }}}}} == 動いているフレームをブロードキャストする == このチュートリアルで配信するようにした余分なフレームは、親のフレームに対して時間がたっても位置が変わらないものとなっています。しかし、もし動いているフレームを配信したければ、時間で変化するようにbroadcasterを変えることができます。 `/carrot1`のフレームが`/turtle1`に呼応して、時間が経つにつれて位置が変わるようにframe_tf_broadcaster.cppを修正しましょう。 {{{ #!cplusplus transform.setOrigin( tf::Vector3(2.0*sin(ros::Time::now().toSec()), 2.0*cos(ros::Time::now().toSec()), 0.0) ); transform.setRotation( tf::Quaternion(0, 0, 0) ); }}} 再度turtle demoをリビルドして、再スタートしてください。 {{{{{#!wiki buildsystem catkin {{{ $ catkin_make $ roslaunch learning_tf start_demo.launch }}} }}}}} {{{{{#!wiki buildsystem rosbuild {{{ $ make $ roslaunch learning_tf start_demo.launch }}} }}}}} これで、次のtfと時間についてのチュートリアルに進む準備ができました。[[ja/tf/Tutorials/tf and Time (Python)|(Python)]] [[ja/tf/Tutorials/tf and Time (C++)|(C++)]] ## AUTOGENERATED DO NOT DELETE ## TutorialCategory ## TutorialTurtlesim ## C++Category ## LearningCategory