• ros入门


    Ros安装:

    sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
    sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
    
    
    
    
    国内:
    sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list'
    
    sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
    
    sudo apt-get update
    
    sudo apt-get install ros-melodic-desktop-full
    melodic 版本ros安装

    ,参看古月21讲!

    ros是否安装成功测试: 

    第一步: roscore  

    第二步: rosrun turtlesim  turtlesim_node 

    第三步    rosrun turtlesim  turtle_teleop_key

    此时就可以通过键盘的上下左右键控制 小海龟了!

    Ros命令行工具的使用:

    命令rqt_graph :

    它会显示当前全局的节点图

    rosnode 相关的命令:

    rosnode  list :

    它会把所有的节点都列出来。

    rosnode  info :

    它可以查看某个节点的信息:

    例如:

    rosnode info turtlesim

    输出为:

    --------------------------------------------------------------------------------
    Node [/turtlesim]
    Publications: 
    * /rosout [rosgraph_msgs/Log]
    * /turtle1/color_sensor [turtlesim/Color]
    * /turtle1/pose [turtlesim/Pose]
    
    Subscriptions: 
    * /turtle1/cmd_vel [geometry_msgs/Twist]
    
    Services: 
    * /clear
    * /kill
    * /reset
    * /spawn
    * /turtle1/set_pen
    * /turtle1/teleport_absolute
    * /turtle1/teleport_relative
    * /turtlesim/get_loggers
    * /turtlesim/set_logger_level
    
    contacting node http://zcb-vm:35989/ ...
    Pid: 3141
    Connections:
    * topic: /rosout
    * to: /rosout
    * direction: outbound
    * transport: TCPROS
    * topic: /turtle1/cmd_vel
    * to: /teleop_turtle (http://zcb-vm:32913/)
    * direction: inbound
    * transport: TCPROS
    输出内容

    rostopic 相关的命令:

    它是和话题相关的命令

    rostopic  list :

    可以打印出所有的话题列表!

    输出为:

    /rosout
    /rosout_agg
    /turtle1/cmd_vel    (它就是前面用于 操控海龟运动的消息  )
    /turtle1/color_sensor
    /turtle1/pose

    我们可以 给消息传入数据(通过 rostopic pub 发布)  以实现通过命令行 操控海龟,如下:

    通过 -r  参数设置发布频率

    -r 10 就是10HZ 就是1s发布10次 。

    下面查看rosmsg 的结构:

    rosmsg show geometry_msgs/Twist
    geometry_msgs/Vector3 linear
    float64 x
    float64 y
    float64 z
    geometry_msgs/Vector3 angular
    float64 x
    float64 y
    float64 z

    rosservice 相关的命令:

    rostopic  list :

    可以打印出所有的服务列表!

    /clear
    /kill
    /reset
    /rosout/get_loggers
    /rosout/set_logger_level
    /spawn
    /teleop_turtle/get_loggers
    /teleop_turtle/set_logger_level
    /turtle1/set_pen
    /turtle1/teleport_absolute
    /turtle1/teleport_relative
    /turtlesim/get_loggers
    /turtlesim/set_logger_level

    产生一个新的海龟(使用spawn 服务):

    rosservice call call个服务!!!

    话题记录工具 rosbag :

    它就是用来复现 操作的。

     rosbag record   

    -a  选项的意思是记录全部  

    后面的cmd_record 是保存到的压缩文件。

    之后ctrl c   

    数据就自动保存到当前终端的目录下了!

    然后可以使用rosbag play     命令进行复现!

    创建工作空间和功能包:

    建工作空间:

    工作空间,就类似于IDE中创建的工程,

    src是放 功能包 的!

    build 是放置 中间产生的 编译文件的,(基本不用关心它)

    devel 是放置 生成的可执行文件,一些库,一些脚本等等,(最终运行都是在这里的!)

    install 是 安装成功之后,安装的路径,(类似 win 中program files 是默认的路径一样)

    创建功能包:

    注意:一定要在 src空间创建功能包。

    下面看下它们的作用,

    先看package.xml  

    它主要是关于 功能包的一些信息!

    再看CMakeLists.txt 

    它主要是描述功能包中的编译规则。它使用的语法是cmake 的语法,

    总结:

    通过功能包可以完成代码的组织,通过工作空间可以完成功能包中代码的编译和运行!!!

    发布者publisher的编程实现(topic 的学习):

    先创建功能包:

    后面的roscpp rospy std_msgs geometry_msgs turtlesim 都是依赖。

    创建发布者代码(C++)

    C++代码:

     1 #include <ros/ros.h>
     2 #include <geometry_msgs/Twist.h>
     3 
     4 int main(int argc,char **argv){
     5     //ROS节点初始化 
     6     ros:: init(argc,argv,"velocity_publisher"); //注意节点名字不能重复  
     7 
     8     //创建节点句柄  
     9     ros:: NodeHandle n; 
    10 
    11     //创建一个Publisher ,发布名为 /turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist ,队列长度 10   
    12     ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);  //第一个参数是向哪个消息中发布数据, 第二个10是队列长度,因为如果每秒发布10000次,但是底层的以太网不可能来得及响应,就会先放到这个队列中
    13     //注: 如果队列中占满了,它会去除时间戳最老的数据,
    14 
    15 
    16 
    17 
    18     //设置循环频率  
    19     ros:: Rate loop_rate(10); //10HZ  1s 10次
    20 
    21     int count =0;
    22     while(ros::ok()){
    23         //初始化geometry_msgs::Twist 类型的消息 
    24         geometry_msgs:: Twist vel_msg;
    25         vel_msg.liner.x = 0.5;
    26         vel_msg.angular.z = 0.2;
    27 
    28         //发布消息 
    29         turtle_vel_pub.publish(vel_msg);
    30         ROS_INFO("Publish turtle velocity command[%0.2f m/s ,%0.2f rad/s] ",
    31                 vel_msg.liner.x,vel_msg.angular.z); 
    32                 //ROS_INFO 类似于 printf()
    33 
    34         //按照循环频率 延时 
    35         loop_rate.sleep(); //1s 10次 
    36     
    37     }
    38     return 0;
    velocity_publisher.cpp

    下面要配置 上面代码的编译规则(修改cmakelists.txt)

    add_executable () 的作用是将 src/velocity_publisher.cpp 编译成 velocity_publisher 可执行文件。

    target_link_libraries()的作用是将 生成的可执行文件和 ros一些库做链接的(主要是C++ 的一些接口)。

    总结:先做代码的编译,然后再做 链接。

    编译并运行代码:

     

    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 队列长度为10  
        turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel',Twist,queue_size=10)
        #设置循环的频率  
        rate = rospy.Rate(10)  #1s 10次 
    
        while not rospy.is_shutdown():
            #初始化 geometry_msgs:: Twist 类型的消息 
            vel_msg = Twist() 
            vel_msg.linear.x = 0.8
            vel_msg.angular.z = 0.2 
    
            #发布消息 
            turtle_vel_pub.publish(vel_msg)
            rospy.loginfo("Publish turtle velocity command [{:.2f}m/s, {:.2f}rad/s ]".format(vel_msg.linear.x,vel_msg.angular.z))
    
            #按照循环 频率延时  
            rate.sleep()
    if __name__ == '__main__':
        try:
            velocity_publisher()
        except:
            pass 
    view code

    注意要给python 文件加上可执行的权限。Python 的代码不需要进行cmake 编译。

    订阅者subscriber的编程实现(topic 的学习):

    C++代码:

     1 /**
     2 * 该例子将订阅 /turtle1/pose 话题 ,消息类型为 turtlesim::Pose 
     3 */
     4 #include <ros/ros.h>
     5 #include <turtlesim/Pose.h>
     6 
     7 //接收到订阅消息后,会进入消息回调函数  
     8 void poseCallback(const turtlesim::Pose::ConstPtr& msg){
     9     //将 接收到的消息 打印出来 
    10     ROS_INFO("Turtle pose: x:%0.6f ,y:%0.6f",msg->x,msg->y);
    11 }
    12 int main(int argc,char **argv){
    13     //初始化 ROS 节点 
    14     ros::init(argc,argv,"pose_subscriber");
    15 
    16     //创建节点句柄  
    17     ros::NodeHandle n;
    18     
    19     //创建一个Subscriber ,消息名为 turtle1/pose的消息 ,注册回调函数 
    20     ros::Subscriber pose_sub = n.subscribe("/turtle1/pose",10,poseCallback);
    21     
    22     //循环等待回调函数  
    23     ros::spin();
    24 
    25     return 0; 
    26 
    27 }
    pose_subscriber.cpp

    python 版代码:

     1 #!usr/bin/env python
     2 # -*- coding:utf-8 -*- 
     3 #该例子 将订阅 /turtle1/pose 话题,消息类型为 turtlesim::Pose  
     4 
     5 import rospy 
     6 from turtlesim.msg import Pose 
     7 
     8 def poseCallback(msg):
     9     rospy.loginfo("Turtle pose x:{:.6f} y:{:.6f}".format(msg.x,msg.y))
    10 
    11 def pose_subscriber():
    12     #ROS 节点初始化  
    13     rospy.init_node("pose_subscriber",anonymous=True)
    14 
    15     #创建一个 subscriber ,消息名为/turtle1/pose 的topic 注册回调函数poseCallback 
    16     rospy.Subscriber("/turtle1/pose",Pose,poseCallback)
    17 
    18     #循环等待回调函数
    19     rospy.spin() 
    20 if __name__ == "__main__":
    21     pose_subscriber()
    pose_subscriber.py

    这里要注意的是 回调函数中要尽量的快(不能有很多的嵌套)。不然,会有问题出现!

    话题消息的自定义与使用(topic的学习):

    自定义话题消息:

    注:Person.msg 是一个与语言无关的文件。

    之后在工作的空间的根目录下使用catkin_make编译。通过之后会在devel/include/learning_topic/下产生一个Person.h 的C++头文件!!!

    下面创建消息的发布者和订阅者:

    代码:

     1 /*
     2 该例子将发布/person_info 话题 ,自定义消息类型为 learning_topic::Person  
     3 
     4 */
     5 #include <ros/ros.h>
     6 #include "learning_topic/Person.h"
     7 int main(int argc,char **argv){
     8     //ros节点 初始化 
     9     ros:: init(argc,argv,"person_publisher");
    10 
    11     //创建节点句柄
    12     ros::NodeHandle n;
    13 
    14     //创建一个Publisher ,发布名为/person_info 消息类型为 learning_topic::Person,队列长度10 
    15     ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info",10); 
    16 
    17     //设置循环的频率 
    18     ros::Rate loop_rate(1); 
    19 
    20     int count=0;
    21     while(ros::ok()){
    22         //初始化 learning_topic::Person 类型的消息 
    23         learning_topic::Person person_msg;
    24         person_msg.name = "tom";
    25         person_msg.age = 18;
    26         person_msg.sex = learning_topic::Person::male;
    27 
    28         //发布消息 
    29         person_info_pub.publish(person_msg);  
    30 
    31         ROS_INFO("Publish Person Info:name: %s age: %d  sex: %d",person_msg.name.c_str(),person_msg.age,person_msg.sex);
    32 
    33         //按照循环频率延时 
    34         loop_rate.sleep();
    35     }
    36 
    37     return 0;
    38 
    39 }
    person_publisher.cpp
     1 /*
     2 
     3 该例子订阅/person_info 话题  自定义消息类型为 learning_topic::Person  
     4 
     5 */
     6 
     7 #include <ros/ros.h>
     8 #include "learning_topic/Person.h"
     9 
    10 //接收订阅的消息后,会进入到 消息回调函数
    11 void personInfoCallback(const learning_topic::Person::ConstPtr & msg){
    12     //将接收到的消息打印出来 
    13     ROS_INFO("Subscribe Person Info:name:%s age:%d sex:%d",msg->name.c_str(),msg->age,msg->sex); 
    14 }
    15 int main(int argc,char ** argv){
    16 
    17     //初始化ros节点
    18     ros::init(argc,argv,"person_subscriber");
    19 
    20     //创建节点句柄 
    21     ros::NodeHandle n; 
    22 
    23     //创建一个Subscriber,订阅名为 /person_info 的topic 注册回调函数为personInfoCallback() 
    24     ros::Subscriber person_info_sub  = n.subscribe("/person_info",10,personInfoCallback);
    25 
    26     //循环等待回调函数
    27     ros::spin();
    28 
    29     return 0;
    30 }
    person_subscriber.cpp

    然后在CMakeLists.txt 中配置代码的编译规则:

    之后在工作的空间的根目录下使用catkin_make编译!

    下面分别运行:

    roscore 

    rosrun learning_topic person_subscriber 

    rosrun learning_topic person_publisher 

    就能看到收发消息了。

    具体Python 代码省略。

  • 相关阅读:
    BZOJ5302: [Haoi2018]奇怪的背包
    BZOJ5303: [Haoi2018]反色游戏
    UOJ#217. 【UNR #1】奇怪的线段树(广义线段树性质+上下界最小流)
    Codeforces 702F T-Shirts(平衡树+复杂度分析)
    满足决策单调性的 DP 的通用做法
    JZOJ 6754. 2020.07.18【NOI2020】模拟T3 (树链剖分+分治+闵科夫斯基和)
    JZOJ 6756. 2020.07.21【NOI2020】模拟T2 (搜索有用状态+背包dp)
    JZOJ 6757 2020.07.21【NOI2020】模拟T3 (至少容斥+OGF+NTT)
    线性规划转对偶问题
    GDOI 2020 赛前反思
  • 原文地址:https://www.cnblogs.com/zach0812/p/11743604.html
Copyright © 2020-2023  润新知