天天看點

Odometry的釋出和釋出odom到base_link的tf變換

這裡面我覺得重要的話,而且我還看到了twist,這不正是前陣子普羅米修斯群裡問的T265釋出的帶不帶速度資訊所說到的twist?

Odometry的釋出和釋出odom到base_link的tf變換

導航包使用tf來确定機器人在世界中的位置,并将傳感器資料與靜态地圖相關聯。然而,tf不提供關于機器人的速度的任何資訊。是以,導航包要求任何odometry源通過ROS釋出包含速度資訊的transform和nav_msgs/Odometry消息。

摘自:https://www.cnblogs.com/gary-guo/p/7215284.html

Odometry的釋出和釋出odom到base_link的tf變換

轉載自http://www.ncnynl.com/archives/201702/1328.html

ROS釋出nav_msgs/Odometry消息,以及通過tf從“odom”坐标系到“base_link”坐标系的轉換。

在ROS上釋出Odometry資訊

導航包使用tf來确定機器人在世界中的位置,并将傳感器資料與靜态地圖相關聯。然而,tf不提供關于機器人的速度的任何資訊。是以,導航包要求任何odometry源通過ROS釋出包含速度資訊的transform和nav_msgs/Odometry消息。

nav_msgs/Odometry消息

nav_msgs/Odometry資訊存儲在自由空間的機器人的位置和速度的估計:

Odometry的釋出和釋出odom到base_link的tf變換
# This represents an estimate of a position and velocity in free space.  
# 這表示對自由空間中的位置和速度的估計
# The pose in this message should be specified in the coordinate frame given by header.frame_id.
# 此消息中的姿勢應在由header.frame_id給定的坐标系中指定
# The twist in this message should be specified in the coordinate frame given by the child_frame_id
# 這個消息中的twist應該在由child_frame_id給出的坐标系指定
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
           
Odometry的釋出和釋出odom到base_link的tf變換

下面是更詳細的消息類型

std_msgs/Header header

string child_frame_id

geometry_msgs/PoseWithCovariance pose

geometry_msgs/TwistWithCovariance twist

該消息中的姿勢(pose)對應于機器人在世界坐标系中的估計位置以及該姿勢估計特定的可選協方差。

該消息中的速度(twist)對應于機器人在子坐标系的速度,通常是移動基站的坐标系,以及該速度估計特定的可選協方差。

使用tf釋出Odometry變換

如變換配置教程中所讨論的,“tf”軟體庫負責管理與變換樹中的機器人相關的坐标系之間的關系。

是以,任何odometry(裡程)源都必須釋出其管理的坐标系的相關資訊。

編寫代碼

我們将編寫一些用于通過ROS釋出 nav_msgs/Odometry消息的示例代碼,以及使用tf的虛拟機器人的變換。

catkin_create_pkg Odom tf nav_msgs roscpp rospy

Odometry的釋出和釋出odom到base_link的tf變換
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>

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

  ros::NodeHandle n;
  ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);
  tf::TransformBroadcaster odom_broadcaster;

  double x = 0.0;
  double y = 0.0;
  double th = 0.0;

  double vx = 0.1;
  double vy = -0.1;
  double vth = 0.1;

  ros::Time current_time, last_time;
  current_time = ros::Time::now();
  last_time = ros::Time::now();

  ros::Rate r(1.0);
  while(n.ok()){

    ros::spinOnce();               // check for incoming messages
    current_time = ros::Time::now();

    //compute odometry in a typical way given the velocities of the robot
    double dt = (current_time - last_time).toSec();
    double delta_x = (vx * cos(th) - vy * sin(th)) * dt;
    double delta_y = (vx * sin(th) + vy * cos(th)) * dt;
    double delta_th = vth * dt;

    x += delta_x;
    y += delta_y;
    th += delta_th;

    //since all odometry is 6DOF we'll need a quaternion created from yaw
    geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);

    //first, we'll publish the transform over tf
    geometry_msgs::TransformStamped odom_trans;
    odom_trans.header.stamp = current_time;
    odom_trans.header.frame_id = "odom";
    odom_trans.child_frame_id = "base_link";

    odom_trans.transform.translation.x = x;
    odom_trans.transform.translation.y = y;
    odom_trans.transform.translation.z = 0.0;
    odom_trans.transform.rotation = odom_quat;

    //send the transform
    odom_broadcaster.sendTransform(odom_trans);

    //next, we'll publish the odometry message over ROS
    nav_msgs::Odometry odom;
    odom.header.stamp = current_time;
    odom.header.frame_id = "odom";

    //set the position
    odom.pose.pose.position.x = x;
    odom.pose.pose.position.y = y;
    odom.pose.pose.position.z = 0.0;
    odom.pose.pose.orientation = odom_quat;

    //set the velocity
    odom.child_frame_id = "base_link";
    odom.twist.twist.linear.x = vx;
    odom.twist.twist.linear.y = vy;
    odom.twist.twist.angular.z = vth;

    //publish the message
    odom_pub.publish(odom);

    last_time = current_time;
    r.sleep();
  }
}
           
Odometry的釋出和釋出odom到base_link的tf變換

代碼解釋:

  • 代碼:
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>
           
  • 解釋:我們釋出odom坐标系到base_link坐标系的變換和nav_msgs/Odometry消息。需要包含相關頭檔案
  • 代碼:
ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);
tf::TransformBroadcaster odom_broadcaster;
           
  • 解釋:建立ros::Publisher和tf::TransformBroadcaster執行個體,以便能夠分别使用ROS和tf發送消息。
  • 代碼:
double x = 0.0;
  double y = 0.0;
  double th = 0.0;
           
  • 解釋:我們假設機器人最初從“odom”坐标系的原點開始
  • 代碼:
double vx = 0.1;
 double vy = -0.1;
 double vth = 0.1;
           
  • 解釋:在這裡,我們将設定一些速度,其将導緻“base_link”坐标系相對于“odom”坐标系,在x方向上以0.1m/s,在y方向上以-0.1m/s的速率和在th方向以0.1rad/s角度移動。這讓虛拟機器人走一個圓圈。
  • 代碼:
ros::Rate r(1.0);
           
  • 解釋:我們将在這個例子中以1Hz的速率釋出裡程計資訊,以使自我檢查更容易,大多數系統将希望以更高的速率釋出裡程消息。
  • 代碼:
//compute odometry in a typical way given the velocities of the robot
double dt = (current_time - last_time).toSec();
double delta_x = (vx * cos(th) - vy * sin(th)) * dt;
double delta_y = (vx * sin(th) + vy * cos(th)) * dt;
double delta_th = vth * dt;

x += delta_x;
y += delta_y;
th += delta_th;
           
  • 解釋:
    • 在這裡,我們将根據我們設定的恒定速度更新我們的裡程資訊。
    • 當然,真正的裡程系統将整合計算的速度。
  • 代碼:
//since all odometry is 6DOF we'll need a quaternion created from yaw
geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);
           
  • 解釋:
    • 我們通常嘗試使用我們系統中所有消息的3D版本,以允許2D和3D元件在适當的時候一起工作,并将我們要建立的消息數量保持在最小。
    • 是以,有必要将我們用于裡程的偏航值轉換為四元數而發送出去。
    • 幸運的是,tf提供了允許從偏航值容易地建立四元數并且容易地通路四元數的偏航值的功能。
  • 代碼:
//first, we'll publish the transform over tf
geometry_msgs::TransformStamped odom_trans;
odom_trans.header.stamp = current_time;
odom_trans.header.frame_id = "odom";
odom_trans.child_frame_id = "base_link";
           
  • 解釋:
    • 這裡我們将建立一個TransformStamped消息,我們将通過tf發送。
    • 我們想在“current_time”釋出從“odom”坐标系到“base_link”坐标系的轉換。
    • 是以,我們将相應地設定消息的頭部和child_frame_id,確定使用“odom”作為父坐标系,“base_link”作為子坐标系。
  • 代碼:
odom_trans.transform.translation.x = x;
odom_trans.transform.translation.y = y;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation = odom_quat;

//send the transform
odom_broadcaster.sendTransform(odom_trans);
           
  • 解釋:這裡我們從我們的odometry資料填充變換消息,然後使用我們的TransformBroadcaster發送變換。
  • 代碼:
//next, we'll publish the odometry message over ROS
nav_msgs::Odometry odom;
odom.header.stamp = current_time;
odom.header.frame_id = "odom";
           
  • 解釋:
    • 我們還需要釋出nav_msgs/Odometry消息,以便導航堆棧可以從中擷取速度資訊。
    • 我們将消息的頭部設定為current_time和“odom”坐标系。
  • 代碼:
//set the position
odom.pose.pose.position.x = x;
odom.pose.pose.position.y = y;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation = odom_quat;

//set the velocity
odom.child_frame_id = "base_link";
odom.twist.twist.linear.x = vx;
odom.twist.twist.linear.y = vy;
odom.twist.twist.angular.z = vth;
           
  • 解釋:
    • 這将使用裡程資料填充消息,并通過線路發送。
    • 我們将消息的child_frame_id設定為“base_link”坐标系,因為這是我們發送速度資訊的坐标系。

CMakeLists.txt

 add_executable(Odom_exam src/Odom_exam.cpp)

target_link_libraries(Odom_exam ${catkin_LIBRARIES})

Odometry的釋出和釋出odom到base_link的tf變換
Odometry的釋出和釋出odom到base_link的tf變換
Odometry的釋出和釋出odom到base_link的tf變換

分類: ROS