ROS是一个适用于机器人编程的框架,这个框架把原本松散的零部件耦合在了一起,为它们提供了通信架构。ROS虽然叫做操作系统,但并非Windows、Mac那样通常意义的操作系统,它只是连接了操作系统和你开发的ROS应用程序,所以它也算是一个中间件,基于ROS的应用程序之间建立起了沟通的桥梁,所以也是运行在Linux上的运行时环境,在这个环境上,机器人的感知、决策、控制算法可以更好的组织和运行。
对于关键词(框架、中间件、操作系统、运行时环境)都可以用来描述ROS的特性,作为初学者我们不必深究这些概念,随着你越来越多的使用ROS,就能够体会到它的作用。
Ros作为编程框架,介于应用程序与操作系统的中间件,它主要是把我们写的源代码,进行编译、链接后,方便在系统上运行。 Ros采用的是Catkin编译系统(这里的编译其实包含了编译、链接两个步骤)。
Catkin编译系统的工作原理
使用catkin_make编译
当我们写完代码,执行一次catkin_make进行编译,调用系统自动完成编译和链接过程,构建生成目标文件
把源文件放在文末资料中的color_experiment_ws\src路径下(其中color_experiment_ws为工作空间),那就可以使用下面的命令进行编译:
$ cd ~/color_experiment_ws #回到工作空间,catkin_make必须在工作空间下执行
$ catkin_make #开始编译
$ source ~/color_experiment_ws/devel/setup.bash #刷新坏境
编译后,color_experiment_ws文件夹会自动生成build、devel两个文件(如下图所示)。
本节内容主要介绍了ROS开发时常常使用的工具,分别是RVIZ、URDF、STL(可由外部导入)、TF、Gazebo、Moveit!, 这些是我们开发时经常用到的工具。RViz是可视化工具,是将接收到的信息呈现出来;STL文件可以定义复杂的模型;gazebo是一种最常用的ROS仿真工具,也是目前仿真ROS效果最好的工具;rqt则是非常好用的数据流可视化工具,有了它我们可以直观的看到消息的通信架构和流通路径;moveit!是目前为止应用最广泛的开源操作软件。
在ROS开发中,这是一个常用工具,基本上的调试和开发都离不开这个工具—RViZ(the Robit Visualization tool)机器人可视化工具。可视化的作用是直观的,它极大的方便了监控和调试等操作,这个工具将在后续实验中陆续用到。
urdf文件是机器人模型的描述文件,以.urdf结尾。它定义了机器人的连杆和关节的信息,以及它们之间的位置、角度等信息,通过urdf文件可以将机器人的物理连接信息表示出来,并且可视化调试和仿真中显示,这里简单带大家了解一下URDF文件。
在理解urdf文件之前,我们需要先了解一种表达方式。机器人可以由link和joint进行描述,link可以简单理解为连杆,joint可以简单理解为关节。机器人的表达除了表示link和joint数量之外,还需要对link与joint的关系进行描述。
如下图所示, 机器人由一个根link(link1)向上, 分别出现了两个分支–link2和link3, 分别由joint连接link:
因此,典型的机器人描述如下所示,包含robot、link、joint,利用URDF文件进行模型描述,这里URDF可以简单理解为表达上述机器人表达方式的一种xmal文件。如下所示做一个简单的格式举例:
//命名
//父节点
//子节点
//关节
那么如何表达一个link呢?下面我们来看一下。
下面我们来看一下描述link的属性和子元素:
属性
name(必需)
link的名字
子元素
连杆的惯性特性
定义相对于连杆坐标系的惯性参考系的参考坐标,该坐标必需定义在连杆重心处,其坐标轴可与惯性主轴不平行。
xyz (可选,默认为零向量)
表示 x,y,zx,y,zx,y,z 方向的偏置,单位为米。
rpy(可选: defaults to identity if not specified)
表示坐标轴在RPY方向上的旋转,单位为弧度。
3×3旋转惯性矩阵,由六个独立的量组成:ixx, ixy, ixz, iyy, iyz, izz。
连杆的可视化属性。用于指定连杆显示的形状(矩形、圆柱体等),同一连杆可以存在多个visual元素,连杆的形状为多个元素两个形成。一般情况下模型较为复杂可以通过soildwork绘制后生成stl调用,简单的形状如添加末端执行器等可以直接编写。同时可以在此处可根据理论模型和实际模型差距调整几何形状的位置。
连杆几何形状的名字。
相对于连杆的坐标系的几何形状坐标系。
xyz (optional: defaults to zero vector)
表示x,y,zx,y,zx,y,z 方向的偏置,单位为米。
rpy (optional: defaults to identity if not specified)
表示坐标轴在RPY方向上的旋转,单位为弧度。
可视化对象的形状,可以是下面的其中一种:
矩形,元素包含长、宽、高。原点在中心。
-圆柱体,元素包含半径、长度。原点中心。
球体,元素包含半径。原点在中心。
网格,由文件决定,同时提供 scale ,用于界定其边界。推荐使用 Collada .dae 文件, 也支持.stl文件,但必须为一个本地文件。
可视化组件的材料。可以在link标签外定义,但必需在robot标签内,在link标签外定义时,需引用link的名字。
颜色,由 red/green/blue/alpha 组成,大小范围在 [0,1] 内。
材料属性,由文件定义。
连杆的碰撞属性。碰撞属性和连杆的可视化属性不同,简单的碰撞模型经常用来简化计算。同一个连杆可以有多个碰撞属性标签,连杆的碰撞属性表示由其定义的几何图形集构成。
name (可选)
指定连杆几何形状的名称
碰撞组件的参考坐标系相对于连杆坐标系的参考坐标系。
xyz (可选, 默认零向量)
表示x,y,zx,y,zx,y,z 方向的偏置,单位为米。
rpy (可选, defaults to identity if not specified)
表示坐标轴在RPY方向上的旋转,单位为弧度。
与上述geometry元素描述相同
示例:
Joint
下面我们来看一下描述joint的属性和子元素:
属性
name (必需的)
指定joint的名字(唯一的)
type (必需的)
指定joint的类型,有下列选项:
revolute:可以绕着一个轴旋转的铰链关节,有最大值和最小值限制。
continuous:连续型的铰链关节,可以绕一个轴旋转,没有最大值和最小值限制。
prismatic:滑动关节,可以沿着一个轴滑动,有最大值和最小值限制。
fixed:这不是一个实际的关节,因为它无法运动,所有的自由度都被锁定。这种类型的关节不需要指定轴、动力学特征、标度和最大值最小值限制。
floating:这是一个具有6个自由度的关节。
planar:此关节在一个平面内运动,垂线是运动轴。
子元素
从parent link到child link的变换,joint位于child link的原点,修改该参数可以调整连杆的位置,可用在调整实际模型与理论模型误差,但不建议大幅度修改,因为该参数影响连杆stl的位置,容易影响碰撞检测效果,具体如图所示。
xyz (可选: 默认为零向量)
代表x,y,zx,y,zx,y,z轴方向上的偏移,单位米。
rpy (可选: 默认为零向量)
代表绕着固定轴旋转的角度:roll绕着x轴,pitch绕着y轴,yaw绕着z轴,用弧度表示。
parent link的名字是一个强制的属性。
link
parent link的名字,是这个link在机器人结构树中的名字。
child link的名字是一个强制的属性。
link
child link的名字,是这个link在机器人结构树中的名字。
joint的axis轴在joint的坐标系中。这是旋转轴(revolute joint),prismatic joint移动的轴,是planar joint的标准平面。这个轴在joint坐标系中被指定。修改该参数可以调整关节的旋转所绕着的轴,常用于调整旋转方向,若模型旋向与实际相反,只需乘-1即可。固定(fixed)和浮动(floating)类型的joint不需要用到这个元素。
xyz(必需)
代表轴向量的x,y,zx,y,zx,y,z分量,为标准化的向量。
joint的参考点,用来矫正joint的绝对位置。
rising (可选)
当joint正向运动时,参考点会触发一个上升沿。
falling (可选)
当joint正向运动时,参考点会触发一个下降沿。
该元素用来指定joint的物理性能。它的值被用来描述joint的建模性能,尤其是在仿真的时候。
damping(可选,默认为0)
joint的阻尼值。(移动关节为N⋅sm\frac{N\cdot s}{m}mN⋅s,旋转关节为N⋅m⋅srad\frac{N\cdot m\cdot s}{rad}radN⋅m⋅s)
friction(可选,默认为0)
joint的摩擦力值(移动关节为NNN,旋转关节为N⋅mN \cdot mN⋅m)
该元素为关节运动学约束。
lower (可选, 默认为0)
指定joint运动范围下界的属性(revolute joint的单位为弧度,prismatic joint的单位为米),连续型的joint忽略该属性。
upper (可选, 默认为0)
指定joint运动范围上界的属性(revolute joint的单位为弧度,prismatic joint的单位为米),连续型的joint忽略该属性。
effort (必需)
该属性指定了joint运行时的最大的力。详见安全限制.
velocity (required)
该属性指定了joint运行时的最大的速度。详见安全限制.
这个标签用于指定已定义的joint来模仿已存在的joint。这个joint的值可以用以下公式计算,此元素不在move_group中启用,使用会导致报错。
value = multiplier * other_joint_value + offset.
joint(可选)
需要模仿的joint的名字。
multiplier(可选)
指定上述公式中的乘数因子。
offset(可选)
指定上述公式中的偏移项。默认值为0(revolute joint的单位为弧度,prismatic joint的单位为米)。
该元素为安全控制限制,此元素下数据会读入到move_group中,但实际上时无效,move_group会跳过此处限制直接读取limit下的参数内容,同时设置该元素有几率会导致规划失败。
soft_lower_limit (可选, 默认为0)
该属性指定了joint安全控制边界的下界,是joint安全控制的起始限制点。这个值需要大于上述的limit中的lower值。更多细节详见安全限制。
soft_upper_limit (可选, 默认为0)
该属性指定了joint安全控制边界的上界,是joint安全控制的起始限制点。这个值需要小于上述的limit中的upper值。更多细节详见安全限制。
k_position(可选, 默认为0)
本属性用于说明位置和速度之间的关系。更多细节详见安全限制。
k_velocity(必需)
本属性用于说明力和速度之间的关系。更多细节详见安全限制。
示例:
STL文件是3D模型文件,机器人的URDF或仿真环境通常会引用这类文件,它们描述了机器人的三维模型。相比URDF文件简单定义的型状,STL文件可以定义复杂的模型,可以直接从solidworks或其他建模软件导出机器人装配模型,从而显示出更加精确的外形。
rqt是一个基于qt开发的可视化工具,拥有扩展性好、灵活易用、跨平台等特点,主要作用和RViz一致都是可视化,但是和RViz相比,rqt要高级一个层次。常见的命令有:
rqt_graph:显示通信架构
rqt_plot:绘制曲线
rqt_console:查看日志
TF是ROS世界里一个基本的也很重要的概念,所谓TF(TransForm),就是坐标转换。在现实生活中,我们做出各种行为模式都可以在很短的时间里完成(比如拿起身边的物品),但是在机器人的世界里,则远远没有那么简单。观察下图,我们来分析一下抓取物品需要做到什么?而TF又起到什么样的作用?
当机器人的"眼睛"(如摄像头)获取一组关于物体的坐标方位数据后,但是相对于来说,这个坐标只是相对于安装的摄像头,并不直接适用于机械手爪执行,那么物体相对于头部和手臂之间的坐标转换,就是TF。
坐标变换包括位置和姿态两个方面的变换,ROS中的tf是一个可以让用户随时记录多个坐标系的软件包。tf保持缓存的树形结构中的坐标系之间的关系,并且允许用户可以在任何期望的时间点以及任何两个坐标系之间转换点、矢量等。
Gazebo是一个机器人仿真工具、模拟器,也是一个独立的开源机器人仿真平台,可以进行机器人的运动学、动力学仿真,能够模拟机器人常用的传感器(如激光雷达、摄像头、IMU等),也可以加载自定义的环境和场景。 Gazebo提供高保真度的物理模拟,其提供一整套传感器模型,以及对用户和程序非常友好的交互方式。
通常一些不依赖于具体硬件的算法和场景都可以在Gazebo上仿真,例如图像识别、传感器数据融合处理、路径规划、SLAM等任务完全可以在Gazebo上仿真实现,大大减轻了对硬件的依赖。
Moveit!是目前针对移动操作最先进的软件。它结合了运动规划、操纵、三维感知、运动学、控制和导航的最新进展;它提供了一个易于使用的平台,能开发先进的机器人应用程序,评估新的机器人设计和建筑集成的机器人产品,它广泛应用于工业,商业,研发和其他领域。MOVEit!是最广泛使用的开源软件的操作,并已被用于超过65个机器人。
MOVEit!的使用通过为用户提供接口来调用它,包括C++、Python、GUI三种接口。ROS中的move_group节点充当整合器,整合多个独立组件,提供ROS风格的Action和service。move_group通过ROS topic和action与机器人通讯,获取机器人的位置、节点等状态,获取数据再传递给机器人的控制器。为了便于理解Moveit!,请查看下面的系统架构图(见下图)。
本节实验主要是学会为源代码创建新的Ros工作空间并能进行编译。需要提前准备好硬件、并配置好软件环境(如下表所示)。
配置分类 |
备注 |
硬件环境 |
PC机 |
软件环境 |
Ubuntu18.04操作系统 ROS(melodic) |
第一步:打开终端,创建工作空间。
打开终端:同时按下Crtl+Alt+T ,接着按下Enter,等待终端打开;
新建ros工作空间:在终端中输入mkdir -p ~/myself_ws/src ,接着按下 Enter,(如下图所示)。
知识补充:
释义1:命令中的“myself_ws”即为新创建的ros工作空间名,可根据个人喜好更改。
例如将“myself_ws”改为“yourself_ws”,则此时的命令为:
mkdir -p ~/yourself_ws/src
释义2:命令中的src表示代码空间(Source Space),该名称不能更改,为ros固定
的命名方式。
第二步:编译ros工作空间。
在上述的终端中输入:cd ~/myself_ws,接着按下Enter;
接着在该终端继续输入:catkin_make,接着按下Enter,等待创建的ros工作空间编译完成(大致需要15秒左右)。
编译完成后在终端中输入ls ,接着按下Enter,查看ros工作空间是否编译完成。如果编译完成,myself_ws下会出现三个文件夹分别为:(build编译空间Build Space)、devel(开发空间Development Space)、src(代码空间Source Space),否则检查输入命令是否有误。
第三步:拷贝源代码并编译URDF及moveit文件。
① 复制功能包:将文末资料中的ats_arm02和my_robot_arm两个功能包复制粘贴到PC机的/myself_ws/src 文件夹中。
② 编译: 打开终端,并在终端中输入:cd ~/myself_ws,之后按下Enter;接着在上述终端中输入:catkin_make,接着按下Enter,等待编译完成,该过程大致需要30秒。
在计算机操作系统里面设置环境变量其实就是设置一定的文件路径,让计算机执行命令的时候方便找到。所以ROS中环境变量就是为了让计算机更方便的找到文件所在的路径来执行。这里介绍两种将ros工作空间添加到环境变量的方法,主要介绍其中常见的一种。
永久上传创建的ros工作空间至环境变量中:
知识补充:
临时上传ros工作空间至环境变量:最后在该终端中输入:source devel/setup.bash ,接着按下Enter
释义:此时我们可在该终端中加载urdf模型及moveit,但该方法仅适用于此终端,一旦重新开启新终端后,如果想加载urdf模型及movei,需要再次在终端输入:source devel/setup.bash,故为了方便运行该ros工作空间中的程序,需要使用该方法将创建的ros工作空间永久添加到环境变量中。
本节实验主要是把URDF模型在rviz中显示出来,并通过tf观察建立起坐标系;同时通过改变joint来观察机械臂朝向变化。
知识拓展:
ROS中机器人模型包含大量的部件,这些部件统称之为link,每一个link上面对应着一个frame, 即一个坐标系。link和frame概念是绑定在一起的,像上图pr2模型中我们可以看到有很多的frame,错综复杂的铺置在机器人的各个link上。维护各个坐标系之间的关系,就要靠着tf tree来处理,维护着各个坐标系之间的联通。
机械臂的URDF文件介绍
机械臂的实物图如下,我们将把其拆分为底座、转台、大臂、小臂四大部件,进行建模。
首先构建base_link作为底座的父坐标系,然后在base_link基础上,再构建转台、大臂和小臂的link. 最后不同的link之间通过joint来连接,它们分别是base_spin_joint、pin_first_swing_joint、first_second_swing_joint(生成的文件如下图所示)。
下面主要通过在Ros中加载URDF文件(详细见文末资料中的Source_Urdf_Moveit_File\ats_arm02\urdf),在Rviz中显示并调试。 在终端输入roslaunch ats_arm02 display.launch命令后,启动Rviz,设置3个参数(如下图所示)。
下面是各个link的坐标系图。
输入rosrun rqt_tf_tree rqt_tf_tree,可以看到以下tf 树,观察link之间的关系:
移动joint_state_publisher进度条(见下图),可以临时改变joint的朝向。
为了便于查看各个joint的变化情况,每次都要先点 center,让其保持正中位置,然后调整其中一个joint来观察变化。下面是通过调整进度调条后,改变joint朝向后的状态图。
move_group介绍
move_group是MoveIt的核心部分,可以综合机器人的各独立组件,为用户提供一系列需要的动作指令和服务。从moveit!架构图中我们可以看到,move_group类似于一个积分器,本身并不具备丰富的功能,主要做各功能包、插件的集成。它通过消息或服务的形式接收机器人上传的点云信息、joints的状态消息、还有机器人的tf tree,另外还需要ROS的参数服务器提供机器人的运动学参数,这些参数会在使用 setup assistant的过程中根据机器人的URDF模型文件,创建生成(SRDF和配置文件)。下图是以move_group为中心提供的服务:
用户可以通过以下三种方式之一来访问move_group提供的操作和服务:
在C++中 --使用move_group_interface包,提供一个易于设置C++接口move_group;
在 Python中 --使用moveit_commander包;
通过 GUI -- 使用运动规划插件到Rviz(ROS可视化工具)。
下面我们将采用GUI方式来进行运动规划。在进行运动规划前,需要先利用MoveIt Setup Assistant图形化界面进行配置。
要使用MoveIt控制我们的机器人,需要配置一个ROS的软件包。MoveIt提供了一个图形化工具MoveIt Setup Assistant可以快捷的进行配置。MoveIt Setup Assistant是一个图形界面的工具,帮助配置MoveIt所需的ROS包。Setup Assistant会根据用户导入的机器人的urdf模型,生成SRDF( Semantic Robot Description Format)文件,从而生成一个MoveIt!的功能包,来完成机器人的互动、可视化和仿真。
下面我们将加载上面内容介绍的URDF模型,并完成相应的配置。
首先运行setup assistant,命令如下:roslaunch moveit_setup_assistant setup_assistant.launch
请打开终端(Crtl+Alt+T),启动后输入上面的命令,效果如下图所示:
第一步:加载URDF,请点击Create New MoveIt! Configuration Package。
点浏览后,找到文末资料中的Source_Urdf_Moveit_File\ats_arm02\urdf\ats_arm02.urdf文件即可。
第二步:Self-Collisions自碰撞
默认的碰撞免检矩阵生成器搜索机器人所有关节,这个碰撞免检矩阵是可以安全地关闭检查,从而减少行动规划的处理时间
在某些关节会关闭碰撞检查,比如总是碰撞,从不碰撞,在默认的位置碰撞,或在运动学链条上的相邻处
采样密度指定了多少个随机机器人位置来检查碰撞。更高的密度需要更多的计算时间,而较低的密度就要减少关闭的检查节点
默认值是10000个碰撞检查。碰撞检查是并行完成,以减少处理时间
由于只有三个joint,所以需要去掉第一个对勾。
第三步:virtual joint 虚拟关节。虚拟关节就是定义一个关节将机器人与世界链接起来,针对本实验中来说,假如放在桌子上,那么与桌子的连接就算一个虚拟关节,这个关节类型是fixed(固定)的;而base_link是与这个虚拟关节相连的,作为child_link。明白了原理后,请按照下面三幅图进行虚拟关节的设置。
第四步:planning group规划组。MoveIt通过定义规划组(planning group)来定义机械臂的各个部分(如手臂、末端执行器等)。简单的说就是定义某些关节为一个组合并起一个名字,下面我们将定义一个my_new_arm的组、选择运动学算法、选择规划组的方式。
请点击Planning Groups----Add Group按钮;
请输入组名,在运动学求解器上选择kdl_kinematics_plugin/KDLKinematicsPlugin ,创建规划组有四种方法:Add Joints、Add Links、Add Kin. Chain、Add Subgroups,这里选用Add Kin. Chain。具体见下图:
接下来选择机械臂的底座base_link为BaseLink的second_swing_Link作为TipLink。设置结果如下图:
这样就完成了一个规划组的配置(见下图)。
第五步:Robot Poses机器人姿态设置。下面我们将添加一个预设的姿态并命名为my_new_arm_pose。这里的预设姿态为0(这里是弧度制,0代表90度),当然大家也可以按需进行调整滑动条,进行姿态的预设。
下图为配置好的预设姿态结果。
第六步: End Effectors末端执行器。在大多数情况下,我们会给机械臂安装末端执行器,可以是夹持器,也可以是真空吸盘,甚至可以是3d打印机的挤出头。本实验中的URDF中暂且没有画执行器,就先不用设置了。
第七步:Passive Joints 被动关节。被动关节就是无法主动运动的关节,也可以理解为从动关节,这样moveit在规划运动时,这些关节是无法主动控制的。由于这里没有被动关节,所以这一步也可以跳过。
第八步:选择Ros Control(Ros 控制)。ROS Control是ROS官方提供的针对控制机器人的一套硬件驱动框架,针对不懂得运动执行器提供不同的驱动接口,再这之上又加入了一个硬件抽象层统一接入ROS,包含了一系列ROS包。这里我们可以通过ROS Control面板为关节添加simulation(模拟控制器),就可以通过MoveIt模拟机械臂的运动。
点击Auto Add FollowJointsTrajectory Controllers For Each Planning Group按钮后,会自动添加。生成的Controller如下图所示:
第九步:选择模拟器simulation。点击Generate URDF按钮后,会自动生成URDF文件。
第十步:选择3D Perception(3D感知) 。主要为添加传感器,这里暂且没有用到传感器,可以先跳过。
第十一步:选择Author Information(作者信息),方便后续发布用。
第十二步:选择Configuration Files(配置文件)。请先点击Browse选择一个文件夹,然后点Generate Package按钮即可。
针对项目,我们选择是文末资料中的Source_Urdf_Moveit_File\my_robot_arm文件夹,生成的文件如下图所示。
对于运动规划这部分,我们可以采用随机规划路径、也可以手动规划路径。
第一步:打开终端,输入命令 roslaunch my_robot_arm demo.launch,并等待RVIZ启动。
启动后,利用鼠标来调整视图。鼠标的操作方法,一般常用的就是“shift+鼠标左键”转换视角,“鼠标左键”平移视角,“滚轮”缩放大小。
第二步:接下来我们选择面板Planning---Goal State,选择
第三步:点Plan按钮,就可以看见效果(如下图所示)。
第四步:点Execute按钮,执行效果如下图所示。
如果想停止执行效果,请再次按下Plan按钮。
下面我们将分别对机械臂的转台、大臂、小臂分别进行手动规划,并执行查看其效果。
第一步:打开终端,输入命令 roslaunch my_robot_arm demo.launch,并等待RVIZ启动并调整好视图。
第二步:接下来我们选择面板Planning,选中Allow Approx IK solutions(如下图所示)。
第三步:手动设置转台的路径。
点击蓝色的圆圈,设置转动的目标位置(见下图),点Plan按钮规划路径;然后点面板上的Execute按钮后观察效果;再次点击Plan按钮后停止。
第四步:手动设置大臂的路径。
点击红色的箭头,设置转动的目标位置(见下图),点Plan按钮规划路径;然后点面板上的Execute按钮后观察效果;再次点击Plan按钮后停止。
第五步:手动设置小臂的路径。
点击绿色的圆圈,设置转动的目标位置(见下图),点Plan按钮规划路径;然后点面板上的Execute按钮后观察效果;再次点击Plan按钮后停止。