ROS入门21讲笔记——古月居

2023-10-09 09:58
文章标签 21 入门 笔记 ros 古月

本文主要是介绍ROS入门21讲笔记——古月居,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:
1、 在 catkin_ws 文件下运行catkin_make
2、 在 catkin_ws 文件下运行source devel/setup.bash
3、 在 catkin_ws 文件下运行rosrun learning_topic pose_subscriber
4、 基本上所有操作都是在自己创建的话题文件夹下进行操作
5、 海归仿真器启动可以在任意文件夹下启动
启动流程:
1、 roscore
2、 rosrun turtlesim turtlesim_node #打开海归仿真器
3、 rosrun turtlesim turtlesim_teleop_key #启动键盘控制海归

CMakeLists.txt文件一般添加

add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})

ROS入门21讲笔记——古月居

  • 1 C++&Python极简基础
    • 1.1 安装编译/解析器
    • 1.2 for循环
    • 1.3 while循环
    • 1.4 面向对象
  • 2. ROS基础
    • 2.1 ROS概念
    • 2.2 创建工作空间与功能包
    • 2.3 发布者Publisher的编程实现
    • 2.4 订阅者Subscriber的编程实现
    • 2.5 话题消息的定义与使用
    • 2.6 客户端Client的编程实现
    • 2.7 服务端Server的编程实现
    • 2.8 服务数据的定义与使用
    • 2.9 参数的使用与编程方法
    • 2.10 tf坐标系广播与监听的编程实现
    • 2.11 launch启动文件的使用方法
    • 2.12 常用可视化工具的使用
      • 2.12.1 rqt
      • 2.12.2 Rviz
      • 2.12.3 Gazebo


番外篇:

  • 101、ROS打开bag文件
  • 102、ROS打开pcap文件

1 C++&Python极简基础

1.1 安装编译/解析器

sudo apt-get install g++
sudo apt-get install python

    1.2 for循环

    • Python
    for a in range(5,10):if a< 10:print 'a = ',aa+=1else:break
    

      使用Python解析器运行py程序

      python fileName.py
      

        • C++

        使用g++编译*.cpp文件

        g++  fileName.cpp  -o  exeFileName
        

          运行编译后的二进制文件

          ./exeFileName
          

            1.3 while循环

            • C++

            • Python

            a = 5
            while a < 10:print 'a = ' , aa += 1 
            

              1.4 面向对象

              • C++
              #include <iostream>
              class A
              {public:int i;void test(){std::cout << i <<std::endl;}
              };
              int main()
              {A a;a.i = 10;a.test();return 0;
              }
              
              • Python
              class A:i = 10def test(self)print self.i
              a = A()
              a.test()
              

                配置ROS软件源时,更新软件包容易出现下载失败的情况,跟使用的网络有关.
                古月大神总结:使用手机热点可以更新成功.


                2. ROS基础

                2.1 ROS概念

                在这里插入图片描述
                在这里插入图片描述
                查看节点列表:rosnode list
                发布话题消息:rostopic pub -r 10 /话题名
                发布服务请求:rosservice call /服务文件 “变量:val”
                话题记录: rosbag record -a -O fileName
                话题复现: rosbag play fileName

                2.2 创建工作空间与功能包

                在这里插入图片描述
                在这里插入图片描述
                建立install空间:catkin_make install 输入catkin_make 出现make -j4 -l4 没有问题

                在这里插入图片描述

                2.3 发布者Publisher的编程实现

                在这里插入图片描述


                • C++
                /*** 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist*/
                #include <ros/ros.h>
                #include <geometry_msgs/Twist.h>
                int main(int argc, char **argv)
                {// ROS节点初始化ros::init(argc, argv, "velocity_publisher");// 创建节点句柄ros::NodeHandle n;// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);// 设置循环的频率ros::Rate loop_rate(10);int count = 0;while (ros::ok()){// 初始化geometry_msgs::Twist类型的消息geometry_msgs::Twist vel_msg;vel_msg.linear.x = 0.5;vel_msg.angular.z = 0.2;// 发布消息turtle_vel_pub.publish(vel_msg);ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z);// 按照循环频率延时loop_rate.sleep();}return 0;
                }
                

                  在这里插入图片描述
                  在这里插入图片描述

                  • Python
                  #!/usr/bin/env python
                  # -*- coding: utf-8 -*-
                  # 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
                  import rospy
                  from geometry_msgs.msg import Twist
                  def velocity_publisher():# ROS节点初始化rospy.init_node('velocity_publisher', anonymous=True)# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)#设置循环的频率rate = rospy.Rate(10) while not rospy.is_shutdown():# 初始化geometry_msgs::Twist类型的消息vel_msg = Twist()vel_msg.linear.x = 0.5vel_msg.angular.z = 0.2# 发布消息turtle_vel_pub.publish(vel_msg)rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z)# 按照循环频率延时rate.sleep()
                  if __name__ == '__main__':try:velocity_publisher()except rospy.ROSInterruptException:pass
                  

                    在这里插入图片描述

                    2.4 订阅者Subscriber的编程实现

                    在这里插入图片描述


                    • C++
                    /*** 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose*/
                    #include <ros/ros.h>
                    #include "turtlesim/Pose.h"
                    // 接收到订阅的消息后,会进入消息回调函数
                    void poseCallback(const turtlesim::Pose::ConstPtr& msg)
                    {// 将接收到的消息打印出来ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
                    }
                    int main(int argc, char **argv)
                    {// 初始化ROS节点ros::init(argc, argv, "pose_subscriber");// 创建节点句柄ros::NodeHandle n;// 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallbackros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);// 循环等待回调函数ros::spin();return 0;
                    }
                    

                      在这里插入图片描述
                      在这里插入图片描述

                      • Python
                      #!/usr/bin/env python
                      # -*- coding: utf-8 -*-
                      # 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
                      import rospy
                      from turtlesim.msg import Pose
                      def poseCallback(msg):rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)
                      def pose_subscriber():# ROS节点初始化rospy.init_node('pose_subscriber', anonymous=True)# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallbackrospy.Subscriber("/turtle1/pose", Pose, poseCallback)# 循环等待回调函数rospy.spin()
                      if __name__ == '__main__':pose_subscriber()
                      

                        在这里插入图片描述

                        2.5 话题消息的定义与使用

                        在这里插入图片描述
                        在这里插入图片描述


                        • C++
                        /*** 该例程将发布/person_info话题,自定义消息类型learning_topic::Person*/
                        #include <ros/ros.h>
                        #include "learning_topic/Person.h"
                        int main(int argc, char **argv)
                        {// ROS节点初始化ros::init(argc, argv, "person_publisher");// 创建节点句柄ros::NodeHandle n;// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);// 设置循环的频率ros::Rate loop_rate(1);int count = 0;while (ros::ok()){// 初始化learning_topic::Person类型的消息learning_topic::Person person_msg;person_msg.name = "Tom";person_msg.age  = 18;person_msg.sex  = learning_topic::Person::male;// 发布消息person_info_pub.publish(person_msg);ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d", person_msg.name.c_str(), person_msg.age, person_msg.sex);// 按照循环频率延时loop_rate.sleep();}return 0;
                        }
                        
                          /*** 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person*/
                          #include <ros/ros.h>
                          #include "learning_topic/Person.h"
                          // 接收到订阅的消息后,会进入消息回调函数
                          void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
                          {// 将接收到的消息打印出来ROS_INFO("Subcribe Person Info: name:%s  age:%d  sex:%d", msg->name.c_str(), msg->age, msg->sex);
                          }
                          int main(int argc, char **argv)
                          {// 初始化ROS节点ros::init(argc, argv, "person_subscriber");// 创建节点句柄ros::NodeHandle n;// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbackros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);// 循环等待回调函数ros::spin();return 0;
                          }
                          

                            在这里插入图片描述
                            在这里插入图片描述

                            • Python
                            #!/usr/bin/env python
                            # -*- coding: utf-8 -*-
                            # 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
                            import rospy
                            from learning_topic.msg import Person
                            def velocity_publisher():# ROS节点初始化rospy.init_node('person_publisher', anonymous=True)# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)#设置循环的频率rate = rospy.Rate(10) while not rospy.is_shutdown():# 初始化learning_topic::Person类型的消息person_msg = Person()person_msg.name = "Tom";person_msg.age  = 18;person_msg.sex  = Person.male;# 发布消息person_info_pub.publish(person_msg)rospy.loginfo("Publsh person message[%s, %d, %d]", person_msg.name, person_msg.age, person_msg.sex)# 按照循环频率延时rate.sleep()
                            if __name__ == '__main__':try:velocity_publisher()except rospy.ROSInterruptException:pass
                            
                              #!/usr/bin/env python
                              # -*- coding: utf-8 -*-
                              # 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
                              import rospy
                              from learning_topic.msg import Person
                              def personInfoCallback(msg):rospy.loginfo("Subcribe Person Info: name:%s  age:%d  sex:%d", msg.name, msg.age, msg.sex)
                              def person_subscriber():# ROS节点初始化rospy.init_node('person_subscriber', anonymous=True)# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbackrospy.Subscriber("/person_info", Person, personInfoCallback)# 循环等待回调函数rospy.spin()
                              if __name__ == '__main__':person_subscriber()
                              

                                2.6 客户端Client的编程实现

                                在这里插入图片描述

                                • C++
                                /*** 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn*/
                                #include <ros/ros.h>
                                #include <turtlesim/Spawn.h>
                                int main(int argc, char** argv)
                                {// 初始化ROS节点ros::init(argc, argv, "turtle_spawn");// 创建节点句柄ros::NodeHandle node;// 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的serviceros::service::waitForService("/spawn");//阻塞型函数ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");// 初始化turtlesim::Spawn的请求数据turtlesim::Spawn srv;srv.request.x = 2.0;srv.request.y = 2.0;srv.request.name = "turtle2";// 请求服务调用ROS_INFO("Call service to spwan turtle[x:%0.6f, y:%0.6f, name:%s]", srv.request.x, srv.request.y, srv.request.name.c_str());add_turtle.call(srv); //阻塞型函数// 显示服务调用结果ROS_INFO("Spwan turtle successfully [name:%s]", srv.response.name.c_str());return 0;
                                };
                                

                                  在这里插入图片描述
                                  在这里插入图片描述

                                  • Python
                                  #!/usr/bin/env python
                                  # -*- coding: utf-8 -*-
                                  # 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
                                  import sys
                                  import rospy
                                  from turtlesim.srv import Spawn
                                  def turtle_spawn():# ROS节点初始化rospy.init_node('turtle_spawn')# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的servicerospy.wait_for_service('/spawn')try:add_turtle = rospy.ServiceProxy('/spawn', Spawn)# 请求服务调用,输入请求数据response = add_turtle(2.0, 2.0, 0.0, "turtle2")return response.nameexcept rospy.ServiceException, e:print "Service call failed: %s"%e
                                  if __name__ == "__main__":#服务调用并显示调用结果print "Spwan turtle successfully [name:%s]" %(turtle_spawn())
                                  

                                    2.7 服务端Server的编程实现

                                    在这里插入图片描述

                                    • C++
                                    /*** 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger*/
                                    #include <ros/ros.h>
                                    #include <geometry_msgs/Twist.h>
                                    #include <std_srvs/Trigger.h>
                                    ros::Publisher turtle_vel_pub;
                                    bool pubCommand = false;
                                    // service回调函数,输入参数req,输出参数res
                                    bool commandCallback(std_srvs::Trigger::Request  &req,std_srvs::Trigger::Response &res)
                                    {pubCommand = !pubCommand;// 显示请求数据ROS_INFO("Publish turtle velocity command [%s]", pubCommand==true?"Yes":"No");// 设置反馈数据res.success = true;res.message = "Change turtle command state!"return true;
                                    }
                                    int main(int argc, char **argv)
                                    {// ROS节点初始化ros::init(argc, argv, "turtle_command_server");// 创建节点句柄ros::NodeHandle n;// 创建一个名为/turtle_command的server,注册回调函数commandCallbackros::ServiceServer command_service = n.advertiseService("/turtle_command", commandCallback);// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);// 循环等待回调函数ROS_INFO("Ready to receive turtle command.");// 设置循环的频率ros::Rate loop_rate(10);while(ros::ok()){// 查看一次回调函数队列ros::spinOnce();// 如果标志为true,则发布速度指令if(pubCommand){geometry_msgs::Twist vel_msg;vel_msg.linear.x = 0.5;vel_msg.angular.z = 0.2;turtle_vel_pub.publish(vel_msg);}//按照循环频率延时loop_rate.sleep();}return 0;
                                    }
                                    

                                      在这里插入图片描述
                                      在这里插入图片描述

                                      • Python

                                      注意,ros在Python中没有spinonce方法,可通过多线程来实现

                                      #!/usr/bin/env python
                                      # -*- coding: utf-8 -*-
                                      # 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
                                      import rospy
                                      import thread,time
                                      from geometry_msgs.msg import Twist
                                      from std_srvs.srv import Trigger, TriggerResponse
                                      pubCommand = False;
                                      turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
                                      def command_thread():	while True:if pubCommand:vel_msg = Twist()vel_msg.linear.x = 0.5vel_msg.angular.z = 0.2turtle_vel_pub.publish(vel_msg)			time.sleep(0.1)
                                      def commandCallback(req):global pubCommandpubCommand = bool(1-pubCommand)# 显示请求数据rospy.loginfo("Publish turtle velocity command![%d]", pubCommand)# 反馈数据return TriggerResponse(1, "Change turtle command state!")
                                      def turtle_command_server():# ROS节点初始化rospy.init_node('turtle_command_server')# 创建一个名为/turtle_command的server,注册回调函数commandCallbacks = rospy.Service('/turtle_command', Trigger, commandCallback)# 循环等待回调函数print "Ready to receive turtle command."thread.start_new_thread(command_thread, ())rospy.spin()
                                      if __name__ == "__main__":turtle_command_server()
                                      

                                        2.8 服务数据的定义与使用

                                        在这里插入图片描述
                                        在这里插入图片描述

                                        • C+
                                        //客户端
                                        
                                        /*** 该例程将请求/show_person服务,服务数据类型learning_service::Person*/#include &lt;ros/ros.h&gt;
                                        #include "learning_service/Person.h"
                                        int main(int argc, char** argv)
                                        {// 初始化ROS节点ros::init(argc, argv, "person_client");// 创建节点句柄ros::NodeHandle node;// 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的serviceros::service::waitForService("/show_person");ros::ServiceClient person_client = node.serviceClient&lt;learning_service::Person&gt;("/show_person");// 初始化learning_service::Person的请求数据learning_service::Person srv; //注意要跟srv的文件名相同srv.request.name = "Tom";srv.request.age  = 20;srv.request.sex  = learning_service::Person::Request::male;// 请求服务调用ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]", srv.request.name.c_str(), srv.request.age, srv.request.sex);person_client.call(srv);// 显示服务调用结果ROS_INFO("Show person result : %s", srv.response.result.c_str());return 0;
                                        };//服务端
                                        /**
                                        / * 该例程将执行/show_person服务,服务数据类型learning_service::Person*/
                                        #include &lt;ros/ros.h&gt;
                                        #include "learning_service/Person.h"// service回调函数,输入参数req,输出参数res
                                        bool personCallback(learning_service::Person::Request  &amp;req,learning_service::Person::Response &amp;res)
                                        {// 显示请求数据ROS_INFO("Person: name:%s  age:%d  sex:%d", req.name.c_str(), req.age, req.sex);// 设置反馈数据res.result = "OK";return true;
                                        }
                                        int main(int argc, char **argv)
                                        {// ROS节点初始化ros::init(argc, argv, "person_server");// 创建节点句柄ros::NodeHandle n;// 创建一个名为/show_person的server,注册回调函数personCallbackros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);// 循环等待回调函数ROS_INFO("Ready to show person informtion.");ros::spin();return 0;
                                        }
                                        
                                          • Python

                                          客户端

                                          #!/usr/bin/env python
                                          # -*- coding: utf-8 -*-
                                          # 该例程将请求/show_person服务,服务数据类型learning_service::Person
                                          import sys
                                          import rospy
                                          from learning_service.srv import Person, PersonRequest
                                          def person_client():# ROS节点初始化rospy.init_node('person_client')# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的servicerospy.wait_for_service('/show_person')try:person_client = rospy.ServiceProxy('/show_person', Person)# 请求服务调用,输入请求数据response = person_client("Tom", 20, PersonRequest.male)return response.resultexcept rospy.ServiceException, e:print "Service call failed: %s"%e
                                          if __name__ == "__main__":#服务调用并显示调用结果print "Show person result : %s" %(person_client())
                                          
                                          服务端
                                          #!/usr/bin/env python
                                          # -*- coding: utf-8 -*-
                                          # 该例程将执行/show_person服务,服务数据类型learning_service::Person
                                          import rospy
                                          from learning_service.srv import Person, PersonResponsedef personCallback(req):# 显示请求数据rospy.loginfo("Person: name:%s  age:%d  sex:%d", req.name, req.age, req.sex)# 反馈数据return PersonResponse("OK")def person_server():# ROS节点初始化rospy.init_node('person_server')# 创建一个名为/show_person的server,注册回调函数personCallbacks = rospy.Service('/show_person', Person, personCallback)# 循环等待回调函数print "Ready to show person informtion."rospy.spin()if __name__ == "__main__":person_server()
                                          

                                            2.9 参数的使用与编程方法

                                            在这里插入图片描述
                                            在这里插入图片描述
                                            在这里插入图片描述
                                            在这里插入图片描述
                                            在这里插入图片描述

                                            • C++
                                            /*** 该例程设置/读取海龟例程中的参数*/
                                            #include <string>
                                            #include <ros/ros.h>
                                            #include <std_srvs/Empty.h>
                                            int main(int argc, char **argv)
                                            {int red, green, blue;// ROS节点初始化ros::init(argc, argv, "parameter_config");// 创建节点句柄ros::NodeHandle node;// 读取背景颜色参数ros::param::get("/background_r", red);ros::param::get("/background_g", green);ros::param::get("/background_b", blue);ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);// 设置背景颜色参数ros::param::set("/background_r", 255);ros::param::set("/background_g", 255);ros::param::set("/background_b", 255);ROS_INFO("Set Backgroud Color[255, 255, 255]");// 读取背景颜色参数ros::param::get("/background_r", red);ros::param::get("/background_g", green);ros::param::get("/background_b", blue);ROS_INFO("Re-get Backgroud Color[%d, %d, %d]", red, green, blue);// 调用服务,刷新背景颜色ros::service::waitForService("/clear");ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear");std_srvs::Empty srv;clear_background.call(srv);sleep(1);return 0;
                                            }
                                            

                                              在这里插入图片描述
                                              在这里插入图片描述

                                              • Python
                                              #!/usr/bin/env python
                                              # -*- coding: utf-8 -*-
                                              # 该例程设置/读取海龟例程中的参数
                                              import sys
                                              import rospy
                                              from std_srvs.srv import Empty
                                              def parameter_config():# ROS节点初始化rospy.init_node('parameter_config', anonymous=True)# 读取背景颜色参数red   = rospy.get_param('/background_r')green = rospy.get_param('/background_g')blue  = rospy.get_param('/background_b')rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)# 设置背景颜色参数rospy.set_param("/background_r", 255);rospy.set_param("/background_g", 255);rospy.set_param("/background_b", 255);rospy.loginfo("Set Backgroud Color[255, 255, 255]");# 读取背景颜色参数red   = rospy.get_param('/background_r')green = rospy.get_param('/background_g')blue  = rospy.get_param('/background_b')rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)#发现/spawn服务后,创建一个服务客户端,连接名为/spawn的servicerospy.wait_for_service('/clear')try:clear_background = rospy.ServiceProxy('/clear', Empty)# 请求服务调用,输入请求数据response = clear_background()return responseexcept rospy.ServiceException, e:print "Service call failed: %s"%e
                                              if __name__ == "__main__":parameter_config()
                                              

                                                2.10 tf坐标系广播与监听的编程实现

                                                在这里插入图片描述
                                                在这里插入图片描述

                                                • C++
                                                  广播器的编写
                                                /*** 该例程产生tf数据,并计算、发布turtle2的速度指令*/
                                                #include <ros/ros.h>
                                                #include <tf/transform_broadcaster.h>
                                                #include <turtlesim/Pose.h>
                                                std::string turtle_name;
                                                void poseCallback(const turtlesim::PoseConstPtr& msg)
                                                {// 创建tf的广播器static tf::TransformBroadcaster br;// 初始化tf数据tf::Transform transform;transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );tf::Quaternion q;q.setRPY(0, 0, msg->theta);transform.setRotation(q);// 广播world与海龟坐标系之间的tf数据br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
                                                }
                                                
                                                int main(int argc, char** argv)
                                                {// 初始化ROS节点ros::init(argc, argv, "my_tf_broadcaster");// 输入参数作为海龟的名字if (argc != 2){ROS_ERROR("need turtle name as argument"); return -1;}turtle_name = argv[1];// 订阅海龟的位姿话题ros::NodeHandle node;ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &amp;poseCallback);// 循环等待回调函数ros::spin();return 0;
                                                };
                                                

                                                  监听器的编写

                                                  /*** 该例程监听tf数据,并计算、发布turtle2的速度指令*/
                                                  #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节点ros::init(argc, argv, "my_tf_listener");// 创建节点句柄ros::NodeHandle node;// 请求产生turtle2ros::service::waitForService("/spawn");ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");turtlesim::Spawn srv;add_turtle.call(srv);// 创建发布turtle2速度控制指令的发布者ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);// 创建tf的监听器tf::TransformListener listener;ros::Rate rate(10.0);while (node.ok()){// 获取turtle1与turtle2坐标系之间的tf数据tf::StampedTransform transform;try{//查询是否有这两个坐标系,查询当前时间,如果超过3s则报错listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);}catch (tf::TransformException &ex) {ROS_ERROR("%s",ex.what());ros::Duration(1.0).sleep();continue;}// 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令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;
                                                  };
                                                  

                                                    在这里插入图片描述
                                                    在这里插入图片描述
                                                    在这里插入图片描述


                                                    • Python

                                                    广播器的编写

                                                    #!/usr/bin/env python
                                                    # -*- coding: utf-8 -*-
                                                    # 该例程将请求/show_person服务,服务数据类型learning_service::Person
                                                    import roslib
                                                    roslib.load_manifest('learning_tf')
                                                    import rospy
                                                    import tf
                                                    import turtlesim.msg
                                                    def handle_turtle_pose(msg, turtlename):br = tf.TransformBroadcaster()br.sendTransform((msg.x, msg.y, 0),tf.transformations.quaternion_from_euler(0, 0, msg.theta),rospy.Time.now(),turtlename,"world")
                                                    if __name__ == '__main__':rospy.init_node('turtle_tf_broadcaster')turtlename = rospy.get_param('~turtle')rospy.Subscriber('/%s/pose' % turtlename,turtlesim.msg.Pose,handle_turtle_pose,turtlename)rospy.spin()
                                                    

                                                      监听器的编写

                                                      #!/usr/bin/env python
                                                      # -*- coding: utf-8 -*-
                                                      # 该例程将请求/show_person服务,服务数据类型learning_service::Person
                                                      import roslib
                                                      roslib.load_manifest('learning_tf')
                                                      import rospy
                                                      import math
                                                      import tf
                                                      import geometry_msgs.msg
                                                      import turtlesim.srv
                                                      if __name__ == '__main__':rospy.init_node('turtle_tf_listener')listener = tf.TransformListener()rospy.wait_for_service('spawn')spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)spawner(4, 2, 0, 'turtle2')turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)rate = rospy.Rate(10.0)while not rospy.is_shutdown():try:(trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):continueangular = 4 * math.atan2(trans[1], trans[0])linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)cmd = geometry_msgs.msg.Twist()cmd.linear.x = linearcmd.angular.z = angularturtle_vel.publish(cmd)rate.sleep()
                                                      

                                                        2.11 launch启动文件的使用方法

                                                        Launch文件 :通过XML文件实现多节点的配置和启动(可自动启动ROS Master)
                                                        Launch文件语法:
                                                        在这里插入图片描述
                                                        在这里插入图片描述
                                                        在这里插入图片描述


                                                        参数设置
                                                        在这里插入图片描述
                                                        在这里插入图片描述


                                                        重映射
                                                        在这里插入图片描述

                                                        注意,映射完后原资源就不复存在了


                                                        嵌套
                                                        在这里插入图片描述


                                                        其他:https://wiki.ros.org/roslaunch/XML

                                                        例1:

                                                        <launch><node pkg="learning_topic" type="person_subscriber" name="talker" output="screen" /><node pkg="learning_topic" type="person_publisher" name="listener" output="screen" /> 
                                                        </launch>
                                                        

                                                          例2:

                                                          <launch><param name="/turtle_number"   value="2"/><node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node"><param name="turtle_name1"   value="Tom"/><param name="turtle_name2"   value="Jerry"/><rosparam file="$(find learning_launch)/config/param.yaml" command="load"/></node><node pkg="turtlesim" type="turtle_teleop_key" name="turtle_teleop_key" output="screen"/>
                                                          </launch>
                                                          

                                                            例3:

                                                             <launch><!-- Turtlesim Node--><node pkg="turtlesim" type="turtlesim_node" name="sim"/><node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/><node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster" /><node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster" /><node pkg="learning_tf" type="turtle_tf_listener" name="listener" /></launch>
                                                            

                                                              例4:

                                                              <launch><!-- Turtlesim Node--><node pkg="turtlesim" type="turtlesim_node" name="sim"/><node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/><node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py"><param name="turtle" type="string" value="turtle1" /></node><node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py"><param name="turtle" type="string" value="turtle2" /> </node><node pkg="learning_tf" type="turtle_tf_listener.py" name="listener" />
                                                              </launch>
                                                              

                                                                例5:

                                                                <launch><include file="$(find learning_launch)/launch/simple.launch" /><node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node"><remap from="/turtle1/cmd_vel" to="/cmd_vel"/></node>
                                                                </launch>
                                                                

                                                                  2.12 常用可视化工具的使用

                                                                  2.12.1 rqt

                                                                  在这里插入图片描述

                                                                  rqt 是一个比较综合的工具,集成了rqt_ploat 等一系列的工具,可用于机器人的上位机调试软件

                                                                  2.12.2 Rviz

                                                                  在这里插入图片描述

                                                                  roscore
                                                                  rosrun rviz rviz
                                                                  

                                                                    2.12.3 Gazebo

                                                                    在这里插入图片描述

                                                                    roslaunch gazebo_ros
                                                                    

                                                                      在这里插入图片描述

                                                                      在这里插入图片描述


                                                                      番外篇续:

                                                                      101.ros打开bag文件

                                                                      rosbag play path to xxx.bag 
                                                                      

                                                                      例如:

                                                                      rosbag play ~/Downloads/velodyne.bag 
                                                                      

                                                                      bag数据保存命令,请参见:传送门

                                                                      102.ros打开pcap文件

                                                                      roslaunch velodyne_pointcloud VLP16_points.launch pcap:="path to xxx.pcap"
                                                                      

                                                                      例如:

                                                                      roslaunch velodyne_pointcloud VLP16_points.launch pcap:="$HOME/Downloads/velodyne.pcap"
                                                                      

                                                                      这篇关于ROS入门21讲笔记——古月居的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



                                                                      http://www.chinasem.cn/article/172034

                                                                      相关文章

                                                                      Spring Security 从入门到进阶系列教程

                                                                      Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

                                                                      数论入门整理(updating)

                                                                      一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

                                                                      【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

                                                                      系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

                                                                      Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

                                                                      概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

                                                                      【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

                                                                      【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

                                                                      系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

                                                                      本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

                                                                      poj 2104 and hdu 2665 划分树模板入门题

                                                                      题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

                                                                      MySQL-CRUD入门1

                                                                      文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

                                                                      论文阅读笔记: Segment Anything

                                                                      文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

                                                                      数学建模笔记—— 非线性规划

                                                                      数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2