最近看到学弟学妹在学ros,回想我当时学ros的痛苦时光,想着能不能写一个教程
这里官方教程:http://wiki.ros.org/cn/ROS/Tutorials
我刚学的时候竟然没有搜到这个教程,枯了,说的还是很细致的,主要是很全不过感觉略显枯燥(?)
初入Linux也可以先学习一下Linux基本操作:https://mapleroid.github.io/unix_tutorial/index.html
目录
什么是ros
全称是Robot Operating System,中文为机器人操作系统
我认为最主要的是理解话题(topic)这个概念,由此又一个概念叫节点
一个话题可以被订阅,也可以往里发布内容,做这些事的叫节点,这也是我们所说的订阅者和发布者
就像这里有一个正方形的门,它就是一个话题,一边有一人P在往里输入正方形的物体,它就是发布者,也是一个节点,另一边有一人S在收这个正方形的物体,他就是订阅者,也是一个节点。这个正方形就是某种指定的数据类型
下面是一些有关话题的命令行指令,或许你现在还不太清楚,但不要紧
话题名形如/cmd_vel
1 | # 查看当前的所有话题 |
在命令行中进行话题通信
还没有安装ros?跟着官网一步一步做就好了
ubuntu20.04->官网安装教程
先使用小乌龟(经典)操作一下吧
1 | # 打开一个终端(ctrl+alt+T)输入 回车 |
1 | # 再打开一个终端输入 回车 就可以看到小乌龟啦 |
再打开一个终端备用,现在的情况大概如下图
接下来我们先熟悉一下一些基本命令行指令
1 | # 查看当前的所有话题 |
$ rostopic list
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
这里有五个话题在发布(或者订阅)着某种数据类型
1 | # 我们先来查看一下/turtle1/pose的情况 |
$ rostopic info /turtle1/pose
Type: turtlesim/Pose
Publishers:
* /turtlesim (http://magic:36353/)
Subscribers: None
这里的意思是/turtle1/pose
这个话题在被/turtlesim
节点发布(Publisher)没有被人订阅,内容物是一个叫turtlesim/Pose
的数据类型
1 | # 查看这个数据类型的具体内容物 |
可以看到有五个float类型的变量,他们的含义和就是变量名的英文啦,例如xy是小乌龟的坐标,theta是角度
那数据内容到底是什么呢,用下面指令可以查看
1 | # 查看话题具体内容物 |
可以看到数据一直在刷新,这样我们就在命令行实现了话题的订阅(Subscriber)
按下
Ctrl+c
可以终止这个程序
让我们回到话题列表,你会发现有一个/turtle1/cmd_vel
的话题,他就是控制小乌龟移动的话题,仿照上面的rostopic info
操作,可以发现/turtlesim
节点一直在订阅(Subscriber),而没有人发布(Publisher),那我们来发布就好了
1 | # 不建议直接复制 自己打一点然后使用<tab>按键自动补全就好 |
设置线速度是1.0,发现小乌龟往前走了一点距离,如果想控制小乌龟一直移动,可以用-r 参数指定频率
(即1s内发送消息的次数)然后设置一下角速度,就可以走圆了
1 | # 可以一直走一个圆 |
现在应大致如下图
现在你应该明白了,我们可以通过话题通信的方式订阅(Subscriber)到小乌龟的位置信息/turtle1/pose
、向速度话题/turtle1/cmd_vel
里发布(Publisher)速度控制小乌龟移动
接下来我将以c++为例演示如何在代码中实现这部分操作
- 下面是几个可能用到工具
1 | # 图形化查看节点和话题 圆圈住的是节点名,曲线上的是话题名 |
用c++实现话题通信
1、准备工作
1.创建工作空间
1
2
3
4
5
6# 新建文件夹catkin_ws/src 这样的话工作空间就叫catkin_ws
mkdir -p ~/catkin_ws/src
# 进入catkin_ws/src文件夹
cd ~/catkin_ws/src
# 初始化工作空间 会在当前目录生成一个CmakeLists.txt文件
catkin_init_workspace2.编译工作空间
1
2
3
4# 编译时要进入工作空间根目录
cd ~/catkin_ws/
# 编译 每次有新功能包或者修改代码之后都要编译
catkin_make3.设置环境变量
1
2# 这样是让当前终端生效
source ~/catkin_ws/devel/setup.bash如果不想每次打开一个新终端都source一下的话,在用户根目录下找到
.bashrc
文件,把source ~/catkin_ws/devel/setup.bash
写入到最后一行然后保存以
.
开头的文件是默认隐藏的,按下ctrl+h
可以显示隐藏的文件4.创建功能包
1
2
3
4# 进入指定位置
cd ~/catkin_ws/src
# 创建功能包 这句指令应该在src目录下运行
catkin_create_pkg control_tortoise roscpp rospy std_msgs geometry_msgs turtlesimcontrol_tortoise
是功能包的名字,后面都是一些依赖
当前文件夹结构应该如下
1 | catkin_ws --- 工作空间名字,其他名字也是可以的 |
2、源码书写
如上文件结构所示,cpp文件放在src中,先生成一个main.cpp(运行touch main.cpp
即可生成)
建议自己打一打喔~ 最好能理解
1 | //ros语法基本头文件 |
3、编译工作空间
- 编译之前首先要去功能包下的CMakeLists.txt修改一些东西
看到138行152、153、153 (或许在这几行附近)把注释去掉
改为如下样子
1 | # 括号里第一个参数是节点的名字 |
- 编译
1 | # 编译时要进入工作空间根目录 |
没有红色报错的话就算是成功啦
4、运行
还是和之前一样把小乌龟启动起来
1 | # 终端1 |
现在已经准备就绪,接下来的就是把我们的程序运行起来
1 | # rosrun命令可以启动某个节点 第一个参数书是功能包的名字 第二个参数是节点名字 |
如果不出意外的小乌龟就可以正常转圈,控制台输出位置信息了
还可以使用rosrun rqt_plot rqt_plot
图形化查看数据内容
现在的你是否可以自己订阅一个话题或者往一个话题里面发布消息呢
5、launch文件
有些时候使用的是roslaunch而并非rosrun,roslaunch的好处在于可以一次性开很多个节点
在功能包下新建launch文件,并生成一个control_tortoise.launch
填入如下内容
1 | <launch> |
pkg代表功能包的名字 type是节点名 name可以随意取名 output="screen"
意味着结果会输出在控制台
这时候可以输入roslaunch control_tortoise control_tortoise.launch
来代替rosrun control_tortoise control_tortoise_node
此外,当使用launch文件时,可以进行配置文件的读入、话题的重映射、命名空间的书写等等操作
下面是一个launch实例,没有实际意义,只是向你表述launch的各种使用方法,比如arg、remap、node、include、rosparam、group等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<launch>
<arg name="map_frame" default="map"/>
<remap from="/odom" to="/base_link"/>
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="/dev/ttyUSB0:57600"/>
</include>
<node pkg="camera" type="transform_cam_to_10hz" name="transform_cam_to_10hz" output="screen"/>
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find uav_robotcup)/rviz/local.rviz" />
<node pkg="cat" type="cat" name="cat" output="screen"/>
<rosparam file="$(find uav_robotcup)/params/settings.yaml" command="load"/>
<group ns="door">
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true">
<param name="controller_frequency" value="10.0"/>
<rosparam file="$(find nav_2d_door)/params/costmap_common_params.yaml" command="load" ns="global_costmap"/>
<remap from="/laser/scan" to="$(arg laser_topic)"/>
</node>
</group>
<node pkg="tf" type="static_transform_publisher" name="tf_world_to_map_broadcaster" required="true"
args="0 0 0 0 0 0 world map 100"/>
</launch>
tf坐标转换
建议先行阅读ros wiki的tf教程以及发布坐标转换 下文主要向你表述在px4+gazebo11仿真情况下如何连接飞机的坐标系
其他动态tf连接同理,如果你没有安装px4,不需要跟着教程一步一步实现,看明白即可
飞机的定位信息在mavros/local_position/pose
中发布,包含坐标xyz以及四元数xyzw
使用rosrun rqt_tf_tree rqt_tf_tree
中查看tf树可以看到一个游离的map和base_link,我们的目标就是把这两个坐标系正确的连接起来
示例代码如下
1 |
|
然后可以打开一个rviz订阅两个坐标系,接着让飞机起飞,观察是否和现实相符合
在mavros中也提供了一个很方便的接口,在启动gazebo的launch中最后加入下面几行和上面的效果是一样的
1
2
3 <param name="/mavros/local_position/tf/frame_id" type="str" value="map" />
<param name="/mavros/local_position/tf/child_frame_id" type="str" value="base_link" />
<param name="/mavros/local_position/tf/send" type="bool" value="true" />
多机通信
该方法可以实现在一台电脑(从机)上订阅另外一台电脑(主机)里的ros话题(需在局域网下)
输入
ifconfig
查看本机ip地址把下面的内容写入.bashrc中,两台电脑中的
ROS_MASTER_URI
里的ip地址填主机的ip,ROS_IP
就填自己的ip1
2export ROS_MASTER_URI=http://192.168.1.113:11311
export ROS_IP=192.168.1.108