ROS tf監聽編寫


博客轉載自:https://www.ncnynl.com/archives/201702/1311.html

ROS與C++入門教程-tf-編寫tf listener(監聽)

說明:

  • 介紹如何使用tf訪問坐標系轉換

創建tf的監聽

$ roscd learning_tf
$ touch src/turtle_tf_listener.cpp
$ vim src/turtle_tf_listener.cpp
  • 代碼如下:
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>

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

  ros::NodeHandle node;

  ros::service::waitForService("spawn");
  ros::ServiceClient add_turtle =
    node.serviceClient<turtlesim::Spawn>("spawn");
  turtlesim::Spawn srv;
  add_turtle.call(srv);

  ros::Publisher turtle_vel =
    node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);

  tf::TransformListener listener;

  ros::Rate rate(10.0);
  while (node.ok()){
    tf::StampedTransform transform;
    try{
      listener.lookupTransform("/turtle2", "/turtle1",
                               ros::Time(0), transform);
    }
    catch (tf::TransformException &ex) {
      ROS_ERROR("%s",ex.what());
      ros::Duration(1.0).sleep();
      continue;
    }

    geometry_msgs::Twist vel_msg;
    vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                    transform.getOrigin().x());
    vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                  pow(transform.getOrigin().y(), 2));
    turtle_vel.publish(vel_msg);

    rate.sleep();
  }
  return 0;
};
  • 如果在運行時遇到錯誤"Lookup would require extrapolation into the past",您可以嘗試此替代代碼來調用偵聽器:
try {
    listener.waitForTransform(destination_frame, original_frame, ros::Time(0), ros::Duration(10.0) );
    listener.lookupTransform(destination_frame, original_frame, ros::Time(0), transform);
} catch (tf::TransformException ex) {
    ROS_ERROR("%s",ex.what());
}

代碼解釋:

  • 代碼: #include <tf/transform_listener.h>
  • 作用:
    • tf包提供了TransformListener的實現,以幫助使接收變換的任務更容易。
    • 要使用TransformListener,我們需要包括tf/transform_listener.h頭文件。
  • 代碼:tf::TransformListener listener;

  • 作用:

    • 這里,我們創建一個TransformListener對象。
    • 一旦監聽器被創建,它開始接收tf轉換,並緩沖它們長達10秒。
    • TransformListener對象應該被限定為持久化,否則它的緩存將無法填充,並且幾乎每個查詢都將失敗。
    • 一個常見的方法是使TransformListener對象成為一個類的成員變量。
  • 代碼:

try{
    listener.lookupTransform("/turtle2", "/turtle1",
                               ros::Time(0), transform);
}
  • 作用:這里,真正的工作完成了,我們查詢監聽器進行特定的轉換。

  • 讓我們來看看四個參數:

  • 1.我們想從/turtle2坐標系開始

  • 2.變換到/turtle1坐標系

  • 3.變換的時間,提供ros::Time(0)即會給出最近的可用的變換。

  • 4.結果存放的變換對象。

  • 這個代碼放在try-catch結構,可以獲取拋出的異常

  • 代碼:

geometry_msgs::Twist vel_msg;
vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                    transform.getOrigin().x());
vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
  • 作用:
    • 這里,變換用於計算龜的新的線性和角速度,基於它與龜的距離和角度。
    • 新的速度發布在話題"turtle2/cmd_vel"中,turtlesim將使用它來更新turtle2的運動。

運行監聽

  • 打開CMakeLists.txt文件,並在底部添加以下行:
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
  • 編譯:
$ cd ~/catkin_ws
$ catkin_make
  • 如果一切順利,你應該在devel/lib/learning_tf文件夾中有一個名為turtle_tf_listener的二進制文件。
  • 之前已經創建start_demo.launch,在 塊,合並代碼:
 <launch>
    ...
    <node pkg="learning_tf" type="turtle_tf_listener"
          name="listener" />
  </launch>
  • 啟動:
 $ roslaunch learning_tf start_demo.launch
  • 你應該看到turtlesim有兩只海龜。

檢查結果:

  • 要查看是否有效,只需使用箭頭鍵(確保您的終端窗口處於活動狀態,而不是模擬器窗口)繞過第一只烏龜,您會在第一只烏龜之后看到第二只烏龜!
  • 當turtlesim啟動時,你可能會看到:
[ERROR] 1253915565.300572000: Frame id /turtle2 does not exist! When trying to transform between /turtle1 and /turtle2.
[ERROR] 1253915565.401172000: Frame id /turtle2 does not exist! When trying to transform between /turtle1 and /turtle2.
  • 這是因為我們的監聽器試圖在接收關於龜2的消息之前計算變換,因為它需要一點時間在turtlesim中生成並開始廣播一個tf坐標系。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM