• ROS学习笔记二(TF)基于ubuntu20.04各种bug解决


    一、双海龟跟随实验

    首先安装双海龟的例子。

    在ubuntu20.04下,用的指令是

    sudo apt-get install ros-noetic-turtle-tf

    其他版本把noetic换成melodic或者kinetic

    然后执行

    roslaunch turtle_tf turtle_tf_demo.launch

    这里基本会报错说 “python”: 没有那个文件或目录

    解决方法:sudo apt install python-is-python3

    然后重新执行命令就可以看到两个小乌龟

     再运行海龟的键盘控制节点

    rosrun turtlesim turtle_teleop_key

    就可以控制一只海龟运动了,另一只海龟会追逐它。

    view_frames

    rosrun tf view_frames

    不出意外的话会报错

    解决方法:

    运行 sudo vim /opt/ros/noetic/lib/tf/view_frames
    将第89行代码m = r.search更改为m = r.search(vstr.decode('utf-8'))

    其中进入vim模式后,按i进入编辑模式,修改完代码后按esc退出编辑模式后,输入 :wq 保存并退出。

    再重新执行命令就可以正常运行。等待五秒后会得到一个frame.pdf。可能在主目录下,可能在桌面。

     体现了三个坐标系之间的位置关系。

    可以通过箭头检测坐标系之间是否连通。

    这就是TF树。

    tf_echo

    使用tf_echo可以更直接地查看两个坐标系的相对位置变化关系。

    rosrun tf tf_echo turtle1 turtle2

     

    rviz

    使用rviz可以可视化地看出位置关系。

    rosrun rviz rviz -d `rospack find turtrtle_tf` /rviz/turtle_rviz.rviz

     这里要修改几个地方

    这里改成world

    然后左下角 

     

    最后得到

     中间的就是world,下面那两个就是两个turtle。黄线连接着它们,表示他们之间的位置关系。

    二、tf坐标系广播与监听

    先和之前一样在catkin_ws的src中创建功能包

    catkin_create_pkg learning_tf roscpp rospy tf turtlesim

    在这个功能包的src中再创建两个文件turtle_tf_broadcaster.cppturtle_tf_listener.cpp

    文件源码来自于古月居

    1. /**
    2. * 该例程产生tf数据,并计算、发布turtle2的速度指令
    3. */
    4. #include
    5. #include
    6. #include
    7. std::string turtle_name;
    8. void poseCallback(const turtlesim::PoseConstPtr& msg)
    9. {
    10. // 创建tf的广播器
    11. static tf::TransformBroadcaster br;
    12. // 初始化tf数据
    13. tf::Transform transform;
    14. transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
    15. tf::Quaternion q;
    16. q.setRPY(0, 0, msg->theta);
    17. transform.setRotation(q);
    18. // 广播world与海龟坐标系之间的tf数据
    19. br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
    20. }
    21. int main(int argc, char** argv)
    22. {
    23. // 初始化ROS节点
    24. ros::init(argc, argv, "my_tf_broadcaster");
    25. // 输入参数作为海龟的名字
    26. if (argc != 2)
    27. {
    28. ROS_ERROR("need turtle name as argument");
    29. return -1;
    30. }
    31. turtle_name = argv[1];
    32. // 订阅海龟的位姿话题
    33. ros::NodeHandle node;
    34. ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
    35. // 循环等待回调函数
    36. ros::spin();
    37. return 0;
    38. };
    1. /**
    2. * 该例程监听tf数据,并计算、发布turtle2的速度指令
    3. */
    4. #include
    5. #include
    6. #include
    7. #include
    8. int main(int argc, char** argv)
    9. {
    10. // 初始化ROS节点
    11. ros::init(argc, argv, "my_tf_listener");
    12. // 创建节点句柄
    13. ros::NodeHandle node;
    14. // 请求产生turtle2
    15. ros::service::waitForService("/spawn");
    16. ros::ServiceClient add_turtle = node.serviceClient("/spawn");
    17. turtlesim::Spawn srv;
    18. add_turtle.call(srv);
    19. // 创建发布turtle2速度控制指令的发布者
    20. ros::Publisher turtle_vel = node.advertise("/turtle2/cmd_vel", 10);
    21. // 创建tf的监听器
    22. tf::TransformListener listener;
    23. ros::Rate rate(10.0);
    24. while (node.ok())
    25. {
    26. // 获取turtle1与turtle2坐标系之间的tf数据
    27. tf::StampedTransform transform;
    28. try
    29. {
    30. listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
    31. listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
    32. }
    33. catch (tf::TransformException &ex)
    34. {
    35. ROS_ERROR("%s",ex.what());
    36. ros::Duration(1.0).sleep();
    37. continue;
    38. }
    39. // 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令
    40. geometry_msgs::Twist vel_msg;
    41. vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
    42. transform.getOrigin().x());
    43. vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
    44. pow(transform.getOrigin().y(), 2));
    45. turtle_vel.publish(vel_msg);
    46. rate.sleep();
    47. }
    48. return 0;
    49. };

    在cmakelist中添加编译规则

    1. add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
    2. target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
    3. add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
    4. target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

    回到catkin_ws下catkin_make编译一下

    接着输入一句新打开一个终端,输入以下命令:

    1. roscore
    2. rosrun turtlesim turtlesim_node
    3. rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1
    4. rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
    5. rosrun learning_tf turtle_tf_listener
    6. rosrun turtlesim turtle_teleop_key

    一样会实现两个海龟的控制界面

     

  • 相关阅读:
    SAP ABAP BDC录屏 保姆级教程
    一文讲通物联网&嵌入式
    writev函数的使用测试
    10-DOM节点操作
    SPI机制
    【Python高级编程】Python中Excel表格处理数据
    VScode 调试 linux内核
    SAP 采购发票校验之 后续贷记 MIRO <转载>
    用Unity实现Flat Shading
    浅谈构造函数【Javascript】
  • 原文地址:https://blog.csdn.net/Zero_979/article/details/126884567