安装和配置 ROS 环境
workstation 安装流程:here
ros 安装流程:here
在安装 ROS 的过程中我选择的是清华的源,由于在第五步中出现网速的问题,切换 4G 和 Wifi 均无法解决网速问题。由于可以打开网页所以选择如下的方法,解决rosdep init和rosdep update出现的问题:here
链接中最后写到如果最后不行考虑是dns的问题,我最后也不行,但是可以打开网页自行添加文件,我认为这不算是 DNS 的问题,应该是网速的问题。如果无法打开网页版的文件,考虑是DNS 的问题。
并且在安装 ROS 的过程中学到了 linux 的基础指令:
全局返回: cd
上一级目录: cd ..
创建文件夹: mkdir new_folder_name
创建文件: gedit new_doc_name
删除文件夹: rmdir folder_name
删除文件: rm doc_name
此外这三个链接对我也有很大的启发:1,2,3
$ source /opt/ros/noetic/setup.bash
$ echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
这些操作方法只适用于ROS Groovy及更新版本
使用以下代码创建一个 catkin 工作空间,其中 catkin_make 是编译整个工作空间的命令,之后会多次使用这一命令。
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/
$ catkin_make
$ source devel/setup.bash
# make sure ROS_PACKAGE_PATH environment variable includes the directory ur in
$ echo $ROS_PACKAGE_PATH /home/<username>/catkin_ws/src:/opt/ros/<distro>/share
ROS 文件系统导览
ROS 提供了专门的命令工具来简化操作:
# 获取软件包的所在路径
# $ rospack find [package_name]
$ rospack find roscpp
# 切换到某个软件包的路径中
# $ roscd [locationname[/subdir]]
$ roscd roscpp
# 按软件包的名称执行 ls 命令
# $ rosls [locationname[/subdir]]
$ rosls roscpp_tutorials
创建 ROS 软件包
workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin
package_1/
CMakeLists.txt -- CMakeLists.txt file for package_1
package.xml -- Package manifest for package_1
...
package_n/
CMakeLists.txt -- CMakeLists.txt file for package_n
package.xml -- Package manifest for package_n
# 在工作空间的源文件空间目录中创建包
# $ cd ~//src
$ cd ~/catkin_ws/src
# 声明包的依赖
# catkin_create_pkg [depend1] [depend2] [depend3]
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
$ cd ~/catkin_ws
$ catkin_make
# 将工作空间添加到 ROS 环境中
$ . ~/catkin_ws/devel/setup.bash
使用 rospack 查看一级依赖包,同时这些包的依赖关系存储在 package.xml 文件中。此外一个一个软件包可以有间接的依赖关系。
$ rospack depends1 beginner_tutorials
# 查看 package.xml
$ roscd beginner_tutorials
$ cat package.xml
# 查看间接依赖
$ rospack depends1 rospy
# 查看所有依赖
$ rospack depends beginner_tutorials
构建 ROS 软件包
使用 catkin_make 命令编译后,在 catkin 工作空间生成了新的文件夹:
理解 ROS 节点
计算图(Computation Graph)是一个由ROS进程组成的点对点网络,它们能够共同处理数据。
# 运行 roscore
$ roscore
# 查看活跃节点 in a new terminal
$ rosnode list
# 查看指定节点的信息
# $ rosnode info /rosout
# 运行 turtlesim 包中的 turtlesim_node
$ rosrun turtlesim turtlesim_node
理解 ROS 话题
$ roscore
# new terminal
$ rosrun turtlesim turtlesim_node
# new terminal
# 想要移动乌龟需要选中 turtle_teleop_key 的终端窗口
$ rosrun turtlesim turtle_teleop_key
于是得知:turtlesim_node 节点和 turtle_teleop_key 节点之间是通过一个叫 /turtle1/cmd_vel 的 ROS 话题来相互通信的。turtle_teleop_key 在话题上发布键盘按下的消息,turtlesim 则订阅该话题以接收消息。之后使用 rostopic 工具获取 ROS 话题的信息。
# 数据发布在/turtle1/cmd_vel话题上
$ rostopic echo /turtle1/cmd_vel
此时显示 rostopic 命令也 subscribe 了相同的 topic
理解 ROS 服务和参数
ROS 中的服务是节点之间通讯的另一种方式。服务允许节点发送一个请求(request)并获得一个响应(response)。
# 输出活跃服务的信息
$ rosservice list
# 输出服务的类型
# $ rosservice type [service]
$ rosservice type /clear
# 返回 std_srvs/Empty 表示调用这个服务时不需要参数
# 调用服务
# rosservice call [service] [args]
# 清除 turtlesim_node 背景上的轨迹
$ rosservice call /clear
# 查看spawn(产卵)服务的信息
$ rosservice type /spawn | rossrv show
# 返回信息如下:
# float32 x
# float32 y
# float32 theta
# string name
# ---
# string name
# 通过这些信息可以在(x,y)的位置上生成一个偏转角度为 theta 名叫 name 的新乌龟
修改背景的颜色
# rosparam set [param_name]
$ rosparam set /turtlesim/background_r 150
# 调用clear服务使得参数的修改能生效
$ rosservice call /clear
获取背景的绿色通道的值
# rosparam get [param_name]
$ rosparam get /turtlesim/background_g
# output = 86
显示参数服务器上的所有内容
$ rosparam get /
将所有的参数写入params.yaml文件
# rosparam dump [file_name] [namespace]
$ rosparam dump params.yaml
# 可以将yaml文件重载入新的命名空间,例如copy_turtle
$ rosparam load params.yaml copy_turtle
使用 rqt_console 和 roslaunch
rqt_console 连接到了ROS的日志框架,以显示节点的输出信息。rqt_logger_level 允许我们在节点运行时改变输出信息的详细级别,包括 Debug、Info、Warn 和 Error。使用如下命令启动 Console 窗口和 Logger Level 窗口,查看 turtlesim 启动后发布的所有信息。
$ rosrun rqt_console rqt_console
$ rosrun rqt_logger_level rqt_logger_level
在一个大型的机器人项目中,经常涉及到多个节点协同工作,每个节点又有很多的参数。为了避免手动 rosrun 每个节点并传入参数,可以将需要启动的节点和需要设置的参数全部写入一个 launch 文件中,然后用 roslaunch 一次性的启动 launch 文件,这样就可以启动所有的节点。并且 roslaunch 命令会自动去启动 roscore。
<!--所有的描述标签都要写在<launch></launch>之间-->
<launch>
<!--group标签用于将node批量划分到某个命名空间,便于大项目中节点的批量管理-->
<!--node标签里包含了ROS图中节点的名称属性name、该节点所在的包名pkg、节点的类型type、调试属性output-->
<group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<group ns="turtlesim2">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<node pkg="turtlesim" name="mimic" type="mimic">
<!--用于将topic的名称进行重映射,from中填入原来的topic名称,to中填入新的topic名称-->
<remap from="input" to="turtlesim1/turtle1"/>
<remap from="output" to="turtlesim2/turtle1"/>
</node>
</launch>
rosed 可以直接通过软件包名编辑包中的文件,而无需键入完整路径
$ rosed [package_name] [filename]
$ rosed roscpp Logger.msg
配置你的 ROS2 环境
ROS2 安装教程
ROS1 和 ROS2 共存时切换方法
介绍 turtlesim 和 rqt
参见上一章的内容
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
修改节点的名称后会出现仿真节点,仿真节点不会和原来的节点产生冲突,因为新启动的仿真节点叫做“my_turtle”,并不是默认的“turtlesim”
# $ ros2 node info
$ ros2 node info /my_turtle
一个节点可以通过多个话题向外发布数据,也可以同时订阅多个其他节点发布的话题,相当于话题是一个多对多的订阅/发布模型。话题是节点之间实现数据传输的重要途径,也是机器人各个子系统之间交换数据的重要方式
$ ros2 run turtlesim turtlesim_node
$ ros2 run turtlesim turtle_teleop_key
$ rqt_graph
$ ros2 topic list
$ ros2 topic list -t
# $ ros2 topic echo
$ ros2 topic echo /turtle1/cmd_vel
$ ros2 topic info /turtle1/cmd_vel
$ ros2 interface show geometry_msgs/msg/Twist
cmd_vel 就是在 ROS 中常用的标准速度指令,以上内容表示在 geometry_msgs 包的 msg 中有一个数据类型 Twist,Twist 中包含了两个三维向量,分别表示线速度和角速度
# $ ros2 topic pub ''
$ ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
$ ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
$ ros2 topic hz /turtle1/pose
topic 通信方式是基于订阅/发布机制的,无论有没有订阅者,发布者都会周期发布数据,这种模式适合持续数据的收发,比如传感器数据。
机器人系统中还有另外一些配置性质的数据,并不需要周期处理,此时就要用到另外一种ROS通信方式——服务(Service)。 服务是基于客户端/服务器模型的通信机制,服务器端只在接收到客户端请求时才会提供反馈数据。
$ ros2 service list
# $ ros2 service type
$ ros2 service type /clear
查看所有服务的数据类型
$ ros2 service type list -t
ROS2 允许查看所有提供同样数据类型的的服务,比如可以查找所有提供std_srvs/srv/Empty数据类型的服务
# $ ros2 service find
$ ros2 service find std_srvs/srv/Empty
可以通过下面的命令查看数据类型具体的数据结构
# $ ros2 interface show .srv
$ ros2 interface show std_srvs/srv/Empty.srv
$ ros2 interface show turtlesim/srv/Spawn.srv
通过终端可以发送一个服务请求,同样可以生成一个小乌龟
# $ ros2 service call
$ ros2 service call /clear std_srvs/srv/Empty
$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
在 ROS2 中,每个节点都有自己的参数,参数的主要作用是对节点功能的配置,这些参数可以用整型数、浮点数、布尔型数、字符串和列表来描述
$ ros2 param list
# $ ros2 param get
$ ros2 param get /turtlesim background_g
# $ ros2 param set
$ ros2 param set /turtlesim background_r 150
# $ ros2 param dump
$ ros2 param dump /turtlesim
# $ ros2 run --ros-args --params-file
$ ros2 run turtlesim turtlesim_node --ros-args --params-file ./turtlesim.yaml
如果要让机械臂抓取一个物体,我们不仅要发出指令,还需要获取机械臂的实时反馈,如果直接用话题和服务也可以实现,不过一下得上好几个,有点麻烦。
所以针对类似的场景,ROS推出了一个应用级的通信机制——动作(action),主要解决需要运行一段时间的机器人任务。action也并不是一个全新的机制,而是由底层的三个话题和服务组成:任务目标(Goal,服务),执行结果(Result,服务),周期数据反馈(Feedback,话题)。action是可抢占式的,可以随时发送取消指令,动作终止。如果执行过程中发送一个新的action目标,则会直接中断上一个目标开始执行最新的任务目标。总体上来讲,action是一个客户端/服务器的通信模型,客户端发送一个任务目标,服务器端根据收到的目标执行并周期反馈状态,执行完成后反馈一个执行结果。
启动小乌龟后根据第二行信息提示的指令,通过action来控制海龟转动到指定方向的。 按键 G | B | V | C | D | E | R | T 都是围绕 F 的,以 F 为中心,对应方向的按键就表示控制小海龟的转动到的方向,F 用来发送 action 终止命令
$ ros2 node info /turtlesim
ros2 node info /teleop_turtle
由此可以得知,键盘控制节点作为 action 的客户端发送 action 目标,海龟仿真器作为 action 的服务器端执行 action 并反馈,action 名为 /turtle1/rotate_absolute,并且 action 的数据类型为 /turtlesim/action/RotateAbsolute。
除此之外,还可以通过这样的方法查看 action
$ ros2 action list
$ ros2 action list - t
$ ros2 action info /turtle1/rotate_absolute
$ ros2 interface show turtlesim/action/RotateAbsolute.action
其中第一段描述客户端发送的请求目标,第二段描述的是action执行完成后的反馈结果,第三段描述的是action执行过程中的周期反馈
# $ ros2 action send_goal
# $ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
# 想要看到周期性反馈,需要添加 --feedback
$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
在 action 执行完成前,终端中会不断周期刷新类似反馈信息,而且是可以抢占或终止的。
在终端中运行ROS2节点时,节点的日志信息会在终端中显示出来,rqt_console 是专门用于管理日志信息的可视化工具。打开 rqt_console,将小乌龟运行到边界时,终端和 rqt_console 会显示错误信息。
$ ros2 run rqt_console rqt_console
也可以修改允许发布的日志级别,如果只想显示 Warn 级别以上的日志,Info 和 Debug 级别的日志都是看不到的,这样就可以快速找到想要看到的日志,提高调试、测试、开发的效率
ros2 run turtlesim turtlesim_node --ros-args --log-level WARN
ROS2 也专门设计了launch启动文件,可以一起启动多个节点并允许在文件中对节点进行配置
Node(
package='turtlesim',
namespace='turtlesim1',
executable='turtlesim_node',
name='sim'
),
Node(
package='turtlesim',
namespace='turtlesim2',
executable='turtlesim_node',
name='sim'
),
这里是启动了两个海龟仿真器,通过命名空间区分开,不然会有同名节点的问题。
Node(
package='turtlesim',
executable='mimic',
name='mimic',
remappings=[
('/input/pose', '/turtlesim1/turtle1/pose'),
('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
]
)
最后一个节点启动的是 turtlesim 功能包中的 mimic 节点,其中主要是在配置 mimc 的 remapping 重映射参数。mimic 的输入话题从 /input/pose 重映射为 /turtlesim1/turtle1/pose,输出话题从 /output/cmd_vel 重映射为 /turtlesim2/turtle1/cmd_vel。mimic 节点通过订阅 turtle1 的位置,转换成对 turtle2 的速度指令发布出去,最后可以达到让 turtle2 模仿 turtle1 完成同样的运动
# $ ros2 bag record
$ ros2 bag record /turtle1/cmd_vel
$ ros2 bag record -o subset /turtle1/cmd_vel /turtle1/pose
# $ ros2 bag info
$ ros2 bag info subset
$ ros2 bag play subset