1. 程式人生 > >TF學習筆記7(除錯)

TF學習筆記7(除錯)

本教程將指導您完成除錯典型tf問題的步驟。

它將使用tf故障排除指南中說明的步驟應用於使用turtlesim的示例,還將使用許多tf除錯工具

1 開始這個例子

在本教程中,我們設定了一個具有許多問題的演示應用程式。

本教程的目標是應用系統方法來發現這些問題。

首先,讓我們舉一個例子,並看看會發生什麼:

  $ roslaunch turtle_tf start_debug_demo.launch

你會看到turtlesim出現了。

如果從啟動Demo的終端,選擇終端視窗,則可以使用箭頭鍵驅動其中一個機器人,並且在左上角有第二個機器人。

如果演示工作正常,則第二個機器人應該跟隨您可以使用箭頭鍵命令的機器人。

顯然,它沒有...因為我們必須首先解決一些問題。您看到的是以下錯誤訊息:

  [ERROR] 1254263539.785016000: Frame id /turtle3 does not exist! When trying to transform between /turtle1 and /turtle3.

2 找到tf請求

所以,如果你看看除錯問題指南,你會發現我們首先需要找出我們要求TF做什麼。

因此,我們進入使用tf的程式碼部分。

在之前的教程中,我們建立了一個tf廣播器,用於將烏龜的姿勢釋出到tf。

在本教程中,我們將建立一個tf監聽器以開始使用tf。

3 如何建立一個tf監聽器

我們先建立原始檔。轉到我們在上一個教程中建立的包:

 $ roscd learning_tf

啟動您喜歡的編輯器並將以下程式碼貼上到名為src / turtle_tf_listener_debug.cpp的新檔案中。

https://raw.github.com/ros/geometry_tutorials/hydro-devel/turtle_tf/src/turtle_tf_listener_debug.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("/turtle3", "/turtle1",
                               ros::Time::now(), 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;
};

看看第25-28行:這裡我們對tf做了實際的請求。前三個引數直接告訴了我們在要求TF做什麼:

從座標系/ turtle3 變換到座標系/ turtle1,在時間“now”。

現在,讓我們來看看為什麼這個請求失敗了。

4 檢查座標

首先,我們想知道tf是否知道/ turtle3和/ turtle1之間的轉換:

  $ rosrun tf tf_echo turtle3 turtle1

輸出告訴我們frame turtle3不存在:

Exception thrown:Frame id /turtle3 does not exist! When trying to transform between /turtle1 and /turtle3.
The current list of frames is:
Frame /turtle1 exists with parent /world.
Frame /world exists with parent NO_PARENT.
Frame /turtle2 exists with parent /world.

上述訊息的最後三行告訴我們確實存在哪些座標系。如果您想獲得此圖形表示,請鍵入:

  $ rosrun tf view_frames
  $ evince frames.pdf

你會得到以下輸出。

frames.png

顯然問題是我們要求turtle3,它不存在。要修復此錯誤,請在第25-28行中將turtle3替換為turtle2:

  try{
    listener.lookupTransform("/turtle2", "/turtle1",
                             ros::Time::now(), transform);
  }

現在停止執行演示(Ctrl-c),構建它,然後再次執行它:

  $ make
  $ roslaunch learning_tf start_debug_demo.launch

然後我們馬上遇到下一個問題:

[ERROR] 1254264620.183142000: You requested a transform that is 0.116 miliseconds in the past,
but the most recent transform in the tf buffer is 3.565 miliseconds old.
 When trying to transform between /turtle1 and /turtle2.

5 檢查時間戳

現在我們解決了座標名稱問題,現在是時候檢視時間戳了。

請記住,我們正試圖在“now”時間在turtle2和turtle1之間進行轉換。要獲得有關時間的統計資訊,請執行:

  $ rosrun tf tf_monitor turtle2 turtle1

結果應如下所示:

RESULTS: for /turtle2 to /turtle1
Chain currently is: /turtle1 -> /turtle2
Net delay     avg = 0.008562: max = 0.05632

Frames:

Broadcasters:
Node: /broadcaster1 40.01641 Hz, Average Delay: 0.0001178 Max Delay: 0.000528
Node: /broadcaster2 40.01641 Hz, Average Delay: 0.0001258 Max Delay: 0.000309

這裡的關鍵部分是:the delay for the chain from turtle2 to turtle1。

輸出顯示平均延遲為8毫秒。

這意味著tf只能在經過8毫秒後才能在海龜之間進行轉換。因此,如果我們要求在8毫秒之前而不是“現在”之間進行海龜之間的轉換,tf would be able to give us an answer sometimes.。讓我們通過將第25-28行改為:

try{
    listener.lookupTransform("/turtle2", "/turtle1",
                             ros::Time::now()-ros::Duration(0.1), transform);
  }

所以在新程式碼中,我們要求100毫秒之前的海龜之間的轉換(為什麼不是8?為了安全......)。

停止演示(Ctrl-c),構建並執行:

在catkin工作區的頂部資料夾中重新構建包:

  $ catkin_make

然後再次執行該示例

  $ roslaunch learning_tf start_debug_demo.launch

你最後應該看到烏龜移動了! turtle_tf_start.png

我們做的最後一個修復並不是你想要做的,只是為了確保這是我們的問題。真正的修復將如下所示:

try{
    listener.lookupTransform("/turtle2", "/turtle1",
                             ros::Time(0), transform);
  }

或者像這樣:

try{
    ros::Time now = ros::Time::now();
    listener.waitForTransform("/turtle2", "/turtle1", 
                              now, ros::Duration(1.0));
    listener.lookupTransform("/turtle2", "/turtle1",
                             now, transform);
  }