<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ROS 機(jī)器人技術(shù) - 添加一個 TF 幀

          共 5220字,需瀏覽 11分鐘

           ·

          2020-08-01 22:18

          afefc172348485e29b51c36283b97f07.webp


          登龍

          這是我的第 140 篇原創(chuàng)


          在實(shí)際的機(jī)器人中往往有很多個傳感器,比如我們組目前用的小車上就有相機(jī),雷達(dá),IMU 等,為了能夠在 TF 系統(tǒng)中找到傳感器之間的轉(zhuǎn)換,就需要把每個傳感器的坐標(biāo)系加到系統(tǒng)的 TF 樹中,方法很簡單,下面一起來學(xué)習(xí)下。

          一、TF 樹的注意事項(xiàng)

          在實(shí)際使用和調(diào)試 TF 的時候一定要時刻記?。?strong style="color:#000000;">TF 樹中的一個節(jié)點(diǎn)可以有多個子節(jié)點(diǎn),但是只能有一個父節(jié)點(diǎn),并且 TF 樹中不能出現(xiàn)回環(huán)!

          一個典型的 TF 樹如下:

          5b13399eab8e6f3fb641c28146dc0076.webp


          這個 TF 樹中有 3 個坐標(biāo)系:

          • world:世界坐標(biāo)系
          • turtle1:烏龜 1 的坐標(biāo)系,父節(jié)點(diǎn)是 world
          • turtle2:烏龜 2 的坐標(biāo)系,父節(jié)點(diǎn)時 world

          如果你再發(fā)布一個「xxx -> turtle1」的變換,那 turtle1 就有 2 個父節(jié)點(diǎn),這樣是不可行的,違反了 TF 樹的構(gòu)建規(guī)則,實(shí)際使用是一定要注意了,如果你想查看系統(tǒng)當(dāng)前的 TF 樹,使用下面的命令:

          rosrun rqt_tf_tree rqt_tf_tree

          下面來學(xué)習(xí)如何為一個節(jié)點(diǎn)添加子坐標(biāo)系。

          二、添加子坐標(biāo)系

          同樣進(jìn)入 learning_tf2 包中:

          roscd learning_tf2

          然后在 src 下新建 frame_tf2_broadcaster.cpp 文件,代碼如下:

          #include 
               
          #include 
          #include 

          int main(int argc, char** argv)
          {
              ros::init(argc, argv, "my_tf2_broadcaster");
              ros::NodeHandle node;

              tf2_ros::TransformBroadcaster tfb;
              geometry_msgs::TransformStamped transformStamped;
            // 指定 carrot1 的父節(jié)點(diǎn)時 turtle1 
              // 即添加一個新的 carrot1 子坐標(biāo)系到 turtle1 
              transformStamped.header.frame_id = "turtle1";
              transformStamped.child_frame_id = "carrot1";

              // carrot1 相對于 tutle1 做了 y 軸的偏移
              transformStamped.transform.translation.x = 0.0;
              transformStamped.transform.translation.y = 2.0;
              transformStamped.transform.translation.z = 0.0;

              tf2::Quaternion q;
              q.setRPY(000);

              transformStamped.transform.rotation.x = q.x();
              transformStamped.transform.rotation.y = q.y();
              transformStamped.transform.rotation.z = q.z();
              transformStamped.transform.rotation.w = q.w();

              ros::Rate rate(10.0);
              while (node.ok()) {
                  transformStamped.header.stamp = ros::Time::now();

                  // 這兩行表示讓該 carrot1 參考系隨著時間移動
                  transformStamped.transform.translation.x = 2.0 * sin(ros::Time::now().toSec());
                  transformStamped.transform.translation.y = 2.0 * cos(ros::Time::now().toSec());

                  // 將 carrot1 相對于 tutle1 的坐標(biāo)變換廣播到 TF 系統(tǒng)中
                  tfb.sendTransform(transformStamped);
                  rate.sleep();
                  printf("sending\n");
              }
          };

          代碼中最關(guān)鍵的就是要正確指定發(fā)布轉(zhuǎn)換的 ID:

          • frame_id:父坐標(biāo)系名稱
          • child_frame_id:子坐標(biāo)系名稱

          然后添加編譯規(guī)則:

          add_executable(frame_tf2_broadcaster src/frame_tf2_broadcaster.cpp)
          target_link_libraries(frame_tf2_broadcaster ${catkin_LIBRARIES})

          編譯:

          catkin_make 

          在 launch 中添加啟動:


          <launch>
               
              <node pkg="turtlesim" type="turtlesim_node" name="sim"/>

              
              <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
              
              
              <param name="scale_linear" value="2" type="double"/>
              <param name="scale_angular" value="2" type="double"/>

              
              <node pkg="learning_tf2" type="turtle_tf2_broadcaster" args="/turtle1" name="turtle1_tf2_broadcaster" />
              
               
              <node pkg="learning_tf2" type="turtle_tf2_broadcaster" args="/turtle2" name="turtle2_tf2_broadcaster" />

              
              <node pkg="learning_tf2" type="turtle_tf2_listener" name="listener" />

              
              <node pkg="learning_tf2" type="frame_tf2_broadcaster" name="broadcaster_frame" />
          launch>

          開始啟動節(jié)點(diǎn):

          roslaunch learning_tf2 start_demo.launch

          不過你應(yīng)該發(fā)現(xiàn)小烏龜?shù)母S運(yùn)動跟上一個實(shí)驗(yàn)一模一樣,我們自己添加的坐標(biāo)系沒有產(chǎn)生作用,這是為何呢?這是因?yàn)殡m然我們發(fā)布了新的變換,但是我們并沒有使用它,來修改下 listener 的代碼:

          transformStamped = listener.lookupTransform("/turtle2""/carrot1", ros::Time(0));

          /turtle1 坐標(biāo)系改為 /carrot1,因?yàn)槲覀円褂眯绿砑拥淖鴺?biāo)系,所以尋找變換的坐標(biāo)系參數(shù)就要填寫新添加的坐標(biāo)系名稱,這樣系統(tǒng)才能正確找到新添加的變換,再次編譯重新運(yùn)行:

          catkin_make

          roslaunch learning_tf2 start_demo.launch

          你應(yīng)該會發(fā)現(xiàn)現(xiàn)在的小烏龜產(chǎn)生的跟隨運(yùn)動與之前不一定了,兩者之間的 y 方向有一定的距離,這個距離就是我們發(fā)布變換時指定的坐標(biāo)系的相對位置:

          OK!TF 系統(tǒng)常用的基礎(chǔ)就學(xué)完了,目前因?yàn)轫?xiàng)目有用到 TF,所以寫了幾篇基礎(chǔ)的文章,之前沒有看過的可以再回過頭看下:



          廈大同學(xué),與你分享編程,AI 算法等技術(shù)干貨!精品文章創(chuàng)作不易,謝謝關(guān)注,歡迎在看。


          59495246bb5602781bd89070e3fb315d.webp

          點(diǎn)擊閱讀原文,查看更多精彩文章!

          瀏覽 21
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费视频二区三区 | 亚洲男人69天堂 | 18禁免费看黄 | 青草久久視頻網站 | 成人毛片AV无码 |