返回顶部

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 代码省略。

posted @ 2019-10-27 14:34  Zcb0812  阅读(501)  评论(0)    收藏  举报