從零搭建一輛ROS小車(二)發布里程計數據在rviz中顯示


在上一篇文章中介紹了ros和單片機的通訊,這一篇將介紹如何發布里程計信息,並在rviz中顯示。

本文全部代碼:網盤


 

 

創建功能包

創建odom_tf_package功能包

cd ~/catkin_ws/src
catkin_create_pkg odom_tf_package std_msgs rospy roscpp

 

創建odom_tf_pub節點

  在src文件夾下新建odom_tf_pub.cpp,代碼如下 :

(注意第四行的頭文件,是上一篇文章所提到的自定義消息編譯生成的,所以在編譯這個功能包的時候一定先編譯上一篇文章的)

#include "ros/ros.h"
 #include <tf/transform_broadcaster.h>
 #include <nav_msgs/Odometry.h>
 #include </home/max/catkin_ws/devel/include/serial_port/header.h>


    double x = 0.0;
    double y = 0.0;
    double th = 0.0;
//默認機器人的起始位置是odom參考系下的0點
    double vx = 0;
    double vy = 0;
    double vth = 0;
    double dt ;

void messageCallback(const serial_port::header::ConstPtr& msg) //獲取上篇文章串口功能包發來的數據
{
    //ROS_INFO("I heard: [%d] [%d] [%d]", msg->num1, msg->num2, msg->num3);
    vx = double(msg->num1)/1000;
    vy = double(msg->num2)/100;
    vth = double(msg->num3)/1000;
    ROS_INFO("Vx = [%f] Vth = [%f]", vx,  vth);
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "odom_pub");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("serial_data_odom", 1, messageCallback);//訂閱上篇文章串口功能包的話題
    ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odom", 1);
    tf::TransformBroadcaster odom_broadcaster;

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


    ros::Rate r(20);//以20Hz的速率發布里程信息,
    while(n.ok())
    {
        ros::spinOnce();            
        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)) * dt;
        double delta_y = (vx * sin(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組件在適當的情況下協同工作,
        //並將消息數量保持在最低限度。因此,有必要將我們的yaw(偏航值)變為四元數。 
        //tf提供的功能允許從yaw(偏航值)容易地創建四元數,並且可以方便地獲取四元數的偏航值。
        
        //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);
//將我們的里程數據中填入變換消息中,然后使用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消息,以便導航包可以從中獲取速度信息。
//將消息的header設置為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”坐標系,
//因為我們要發送速度信息到這個坐標系。

        //publish the message
        odom_pub.publish(odom);
        last_time = current_time;
        
        r.sleep();
        }
 // return 0;
}

修改package.xml和CMakeLists.txt

  參考我分享的功能包里的 鏈接

  修改完成后就可以編譯了。

 

運行並在rviz顯示

運行

roscore
rosrun serial_port keybord.py 
rosrun serial_port port_SubAndPub.py 
rosrun odom_tf_package om_tf_pub
rviz

  這里需要運行上一篇的功能包,如果沒有arduino的話就請自行修改代碼,直接訂閱鍵盤/cmd_vel,后續會更新在gazebo中仿真阿克曼車型的機器人。

 

打開rviz后 點擊右下角add 添加tf

  這時可以看到odom和base_link重合。

 

 

 

把右邊第一個Global Options的Frame改成odom

  修改后在鍵盤控制界面使用 U I O 控制 就可以看到移動了。

 

 

 

到此完成了在rviz中的顯示。


免責聲明!

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



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