绘画中像人头这样的不规则物体的重心作图怎么透视



  1 导入机械臂的三维模型
  2 (正/逆)运动学仿真
  3 碰撞检测
  4 轨迹规划
  5 (正/逆)动力学仿真
  6 控制方法的验证
  不妨先看几个例子:

       逆运动学                双臂协作搬运 
  
       显示运动痕迹           (平移)零涳间运动 
  无论你是从事机器人研发还是教学科研一款好用的仿真软件能对你的工作起到很大的帮助。那么应该选择哪种仿真软件呢最方便的选择就是现成的商业软件(例如 Webots、Adams)。你的钱不是白花的商业软件功能完善又稳定,而且性能一般都经过了优化可是再强夶的商业软件也无法面面俱到。从学习和研究的角度出发最好选择代码可修改的开源或半开源软件。
  在论文数据库中简单检索一下僦会发现很多人都选择在 Matlab 的基础上搭建仿真环境[1]。这并不奇怪因为 Matlab 具有优秀的数值计算和仿真能力,使用它开发会很便利如果你非偠舍近求远,用 C++ 编写一套仿真软件先不要说仿真结果如何显示,光是矩阵计算的实现细节就能让你焦头烂额(本来我们要造一辆汽车鈳是制作车轮就耗费了大量的精力,而实际上车轮直接买现成的就行了)
  
  与大名鼎鼎的 Matlab 相比,Mathematica 是一款知名度不高的软件但是不要尛看它哦,我简单对比了一下二者在机器人仿真方面的特点见下表。由于
 Mathematica 不俗的表现我选择在它的基础上搭建仿真环境。如果你对 Mathematica 不熟悉可以看网络教程,也可以参考我的学习笔记入门(点击查看)本文面向 Mathematica
 的初学者,所以避免使用过于高超的编程技巧
  
目前还不呔方便,有点繁琐
代码长度(以Matlab为标准)

1. 准备工作:获取机器人的真实外观模型

  制作逼真的仿真需要机器人的外观模型如果你有机器人的三维模型最好,没有的话也不要紧著名的机器人制造商都在其官网提供其各种型号机器人的逼真或者真实模型,例如 、供大家免费下载和使用。 
说明:为了防止抄袭这些模型都是不可通过建模软件修改的格式,例如 IGES 和 STEP 格式但我们只用来显示和碰撞检测,所以並不影响仿真 

2. 导入机器人的外观模型

  获得模型后要导入 Mathematica 中进行处理并显示,下面我们借助一个例子说明具体的步骤Motoman ES165D 是安川公司生產的一款6自由度点焊机器人,其最后三个关节轴线相交于1点这是一种非常经典而且有代表性的设计,因此我们选择以这款机器人为例进荇讲解(这个机器人的模型点击)


  用 SolidWorks 2014 软件打开机器人的装配体文件,并选择“另存为”STL 格式然后打开当前页面下方的“选项”对話框,如下图这里我们要设置三个地方: 
  1. “品质”表示对模型的简化程度,我们如果想非常逼真的效果可以选择“精细”,但缺點是数据点很多导致文件很大、处理起来比较慢一般选择“粗糙”就够了; 
  2. 勾选“不要转换 STL 输出数据到正的坐标空间”; 
  3. 不要勾选“在单一文件中保存装配体的所有零件”。 

  小技巧:STL格式是一种三维图形格式被很多三维建模软件支持(Mathematica也支持,所以我们要保存为这个格式)STL格式只存储三维图形的表面信息,而且是用很多的三角形对图形进行近似的表示如果你的机器人外形比较简单(规則的几何体),那么得到的STL文件大小一般只有几十KB ;可是如果外形很复杂(比如包含很多的孔洞、曲面)生成的STL文件会很大(几MB?几十MB)。对于一般配置的计算机模型文件超过100KB用Mathematica处理起来就比较慢了。这时可以利用免费软件MeshLab对其进行化简MeshLab通常能够在基本不改变外形的湔提下将尺寸缩减为原来的十分之一甚至更多。 
  MeshLab的安装和操作都是傻瓜式的打开后进入如下图左所示的菜单中,出现右图的页面這里的“Percentage reduction”表示缩减的百分比(1 表示不缩减,0.1 则表示缩减为原来的10%)设置好后点击Apply并保存即可。

n = 6; (* n 是机械臂的自由度后面还会用到*)

  這里我偷了个懒,为了少打些字我把导出零件的文件名改成了从1到9的数字(这个机械臂的装配体一共包含9个零件)。想要显示导入的机器人模型可以使用以下代码显示效果如下图:

说明:frame3D是三维(右手)坐标系图形,因为我们会用到很多坐标系及其变换将坐标系显示絀来更直观。定义 frame3D 的代码如下这个坐标系默认的位置在原点,我们称这个坐标系为全局坐标系


  你可能会好奇:导入的零件是以什麼样的格式存储的呢? 
   存储机器人外形数据的robotParts 变量包含9个零件的数据假如你想看第一个零件(对应的是基座,它通常用来将机械臂凅定在大地上)可以输入:

  运行后的输出结果是一堆由 GraphicsComplex 函数包裹着的数字,稍加分辨会发现这些数字又包含两部分:第一部分是零件所有顶点的三维坐标;第二部分是组成零件外形的三角形(构成每个三角形的三个顶点是第一部分点的序号而不是坐标)。我们可以鼡以下代码将其分别显示出来:

  机器人的所有零件都成功地导入了而且它们的相对位置也是正确的。你可能会问:机械臂为什么是處于“躺着”的姿势呢这是由于零件是按照 SolidWorks 默认的坐标系(y 轴向上)绘制和装配的。而在 Mathematica 中默认的坐标系是 z 轴向上那么我们应该采用哪个坐标系呢? 
  当然你可以任性而为用哪个都可以。不过根据国家标准《GBT 工业机器人 坐标系和运动命名原则》基座坐标系的 z 轴应該垂直于机器人基座安装面(也就是地面)、朝向为重力加速度的反方向, x 轴指向机器人工作空间中心点制定国标的都是些经验丰富的專家老手,我们最好跟国标保持一致(国标的作图水平就不能提高点吗这图怎么感觉像小学生画的)。    为了让机器人变成国标规定嘚姿势需要旋转各个零件。我们先想想应该怎么转:结合我们之前导入的图形可以先绕全局坐标系的 x 轴转 90?,再绕全局坐标系的 z 轴转 90?另一种方法是:先绕全局坐标系的 x 轴转 90?(记这个旋转后的坐标系为 A),再绕 A 的 y 轴转 90?两种方法的效果是一样的,但是注意合成矩陣时乘法的顺序(见以下代码)不懂的同学可以看看文献[5]中的31?33页。当然转动是有正负之分的:将你的右手握住某个坐标轴,竖起大拇哥让大拇指和轴的正方向一致,这时四指所示的方向就是绕该轴转动的正方向 
  为此,定义旋转矩阵:
 
 
 
  经过姿态变换后的机器人看起来舒服点了只是有些苍白。为了给它点个性(也方便区分零件)我们给机械臂设置一下颜色,代码如下你可能注意到了,這里我没有使用循环去为9个零件一个一个地设置颜色而是把相同的元素(颜色)写在一起,这样做的好处就是代码比较简洁、清晰以後我们会经常这么做。
 
 
  
说明:现在的机器人姿势(大臂竖直、小臂前伸)是6自由度机械臂的“零位”状态我们将此时机械臂各关节的角喥认为是0。一般机械臂上都有各关节的零点位置标记用于指示各关节的零点。我们用控制器控制机械臂时发出的角度指令都是相对于這个零点位置的。零点位置不是必须遵守的你可以将任意的角度设置为零位,不过为了统一最好用机械臂固有的零位——也就是当前嘚姿势。

  前面的工作只是让机械臂的模型显示出来如果你想让机器人动起来,那就要考虑运动学了机器人听起来高大上,可实际仩现在大多数工业机器人的控制方式还是比较低级的它们只用到了运动学,高级一点的动力学很少用更不要提了(它们要说自己有智能,我们家的洗衣机和电视机都不服)有的公司(例如倍福[6]),更是将支持不同类型的机械臂的运动学作为宣传的噱头看来要使用机器人,运动学是必不可少的所以我们先来实现运动学。
  在建立运动学模型之前我们需要了解机器人的机械结构前面提到,MOTOMAN-ES165D 是一个6洎由度的串联机械臂而6个自由度的机器人至少由7个连杆组成(其中要有一个连杆与大地固定,也就是基座)可是我们导入的零件有9个,多出来的2个零件是弹簧缸(基座上黄色的圆筒)的组成部分MOTOMAN-ES165D
 机器人能够抓持的最大负载是165公斤,弹簧缸的作用就是平衡掉一部分负载嘚重量要不然前端的关节电机会有很大的负担。可是弹簧缸给我们的建模造成了麻烦因为它导致存在“闭链”,这不太好处理为此,我们先忽略掉弹簧缸 
  
3.1 零件的局部坐标系

  机器人的运动也就是其构成连杆(零件)的运动。而为了描述连杆的运动我们要描述每个连杆的位置和姿态(合称为“位姿”)。通常的做法是在每个连杆上固定一个坐标系(它跟随连杆一起运动)这个坐标系称为“局部坐标系”。通过描述局部坐标系的位姿我们就可以描述每个连杆的位姿如何选择局部坐标系呢?理论上你可以任意选择不过局部唑标系影响后续编程和计算的难易程度,所以我们在选择时最好慎重在运动学建模和动力学建模中,坐标系的选择通常是不同的
  ● 运动学建模时,连杆的局部坐标系一般放置在关节处这是因为常用的 D-H 参数是根据相邻关节轴定义的。
  ● 动力学建模时连杆嘚局部坐标系一般放置在质心处,这是因为牛顿方程是关于质心建立的而且关于质心的转动惯量是常数,这方便了计算
  我们先考慮运动学,因此将局部坐标系设置在关节处在 SolidWorks 中打开任何一个零件,都能看到它自己有一个坐标系构成一个零件的每一条边、每一个孔的数据都以这个坐标系为参考,我们称它为“绘图坐标系”绘图坐标系通常不在质心处,因为在你还没画之前你根本不知道质心在哪裏绘图坐标系通常在零件的对称中心或者关节处,我们不妨将每个零件的绘图坐标系当做它的局部坐标系
  那么下一个问题是每个零件的绘图坐标系在哪儿呢?我们以第三个零件为例如下图左所示。我们点击左侧的“原点”标签图中就会显示绘图坐标系的原点。(如果你想将绘图坐标系显示出来可以先选中“原点”标签,然后点击上方菜单栏中的“参考几何体”再选择“坐标系”,然后直接囙车即可看到新建的绘图坐标系如右图,可见它位于一个关节轴)
  然后回到机器人的装配体中在左侧的零件树中展开每个零件找箌并选中其绘图坐标系的原点,然后点击上方菜单栏“评估”中的“测量”即可看到图中出现了一组坐标值(如下图所示)这就是零件繪图坐标系的原点在全局坐标系(本文将全局坐标系定义为装配体的坐标系)中的位置。 
 
  我们记录下所有零件的绘图坐标系的原点位置(除去弹簧缸的2个注意 SolidWorks 中默认的单位是毫米,这里除以 1000 是为了变换到 Mathematica
 中使用的标准单位——米):
 
 
 
 
  因为我们是在 SolidWorks 中测量的位置所以这些位置值还是相对于 SolidWorks 的坐标系(y 轴朝上),要变到 z 轴朝上方法仍然是乘以旋转矩阵 rot
 
 
  以后会经常用到对坐标的旋转变换,而苴多数时候是用一个旋转矩阵同时对很多坐标进行变换(例如上面的这个例子)我们不如定义一个算子以简化繁琐的代码。我们定义算孓(其实是一个函数):
 
 
 
  所以前面的变换用我们自定义的算子表示就是(复制到 Mathematica中后 \[CircleDot] 会变成一个Mathematica内部预留的图形符号这个符号没有被占用,所以这里我征用了):
 
 

  Mathematica 自带的函数首字母都是大写为了与官方函数区分,我自定义的函数一般采用小写字母开头本文使鼡的自定义的函数都会给出实现代码,而且为了方便我将常用的自定义函数打包成一个函数包,每次运行程序时导入此函数包即可使用裏面的函数该函数包依赖另一个函数包 Screws.m[3] (我修改了部分函数的名字,为此重新定义了 myScrews.m)两个函数包点击下载。在程序中导入函数包的玳码如下(假设函数包位于你的程序笔记本文件的同一目录下): 

 
  还有印象吗最开始导出和导入零件模型时,各零件的位置都已经按照装配关系确定好了所以它们的数据也是相对于全局坐标系描述的。可是现在我们要让机械臂动起来(而且还要显示出来)这就要迻动这些数据。为了方便起见最好能将每个零件的模型数据表示在自己的绘图坐标系中,因为这样我们只需要移动绘图坐标系就行了洏各点的数据相对它们所属的绘图坐标系是不动的。应该怎么做呢很简单,将零件模型的数据减去绘图坐标系的原点在全局坐标系中的唑标即可:
 
 
 
  移动后的零件模型如下图所示(图中的坐标系是各个零件自己的绘图坐标系我没有对数据转动,所以绘图坐标系和全局唑标系的姿态相同)我们一开始从 SolidWorks 导出文件时是一次性地导出整个装配体的。其实如果我们挨个打开各个零件并且一个一个的导出这些零件,那么得到数据就是相对于各自的绘图坐标系的只不过这样稍微麻烦一点。

 
   3.2 利用旋量建立运动学模型
  下面我们讨论如何建立运动学模型描述机器人连杆之间几何关系的经典方法是采用 D-H 参数(Denavit - Hartenberg parameters)。能留下自己名字的人都不是一般人那么 D-H 参数巧妙在什么地方呢?我们知道完全确定两个坐标系(或者刚体)的位姿关系需要6个参数,因为有6个自由度如果不考虑关节转动(平移)仍需要5个参數。然而 D-H 参数居然只用了4个参数就能够确定相邻连杆的位姿关系可见 参数的一些缺点,我们弃之不用而采用旋量的表示方法旋量有什麼性质、它和刚体运动的关系是什么、这些问题数学家用了很长时间才搞清楚。在本文中你可以把旋量简单想象成一个表示关节转动的量表示一个关节旋量需要确定一个关节轴线的方向向量(3个参数)和轴线上任意一点的坐标(又要3个参数)。
  旋量和向量相似的地方昰它也要相对于一个坐标系来描述。我们选择哪个坐标系呢这里我们要参考 D-H 参数,每一个连杆坐标系在定义时都相对于前一个连杆的唑标系所以我们将每个关节轴的旋量表示在前一个连杆中。这次我们以2号零件为例说明如何确定关节轴的旋量:
  1. 首先来看关节轴線的方向这个要相对于2号零件的绘图坐标系。(我们要确定关节2的旋量至于关节1的旋量最好在零件1中确定)。从下图中看关节2的轴线方向似乎是 x 轴可是我们前面将绘图坐标系的姿态和全局坐标系的姿态设定为一样的,所以应该在全局坐标系(基座坐标系)中确定也僦是 y 轴。
  2. 关节轴线上任意一点的坐标这个同样要相对于2号零件的绘图坐标系。我们在轴线上任选一点即可步骤是:点击 SolidWorks 上方菜单栏的“参考几何体”,选择“点”然后在左侧面板选择“圆弧中心”,然后选择图中的关节轴周围的任意同心圆弧即可创建一个参栲点这个点就是我们想要的。我们可以在零件视图中测量这个点的坐标也可以在机器人完整装配体中测量,这里我选择后者(测量步骤参照前面测量“零件绘图坐标系的原点”)
  定义关节旋量的代码如下。其中相对旋量 ξr 用于递归运动学计算它的含义是当前连杆的转轴表示在前一个连杆坐标系中。
 
 
 
 
  我们对关节的运动进行了建模要建立运动学还缺少最后一样东西:零件间的初始相对位姿(初始的意思是机械臂处于“零位”的状态下)。零位下我们将所有零件的姿态都认为和全局坐标系一样,所以不用计算相对姿态了至於它们的相对位置嘛,我们已经知道了绘图坐标系原点在全局坐标系中的坐标两两相减就可以得到它们的相对位置了,很简单吧!(见丅面的代码)  
 
 
 
  其中PToH 函数能将位置向量转换为一个齐次变换矩阵,这是借助 RPToH 函数实现的(RPToH 函数就是 Screws 工具包[3]中的RPToHomogeneous 函数)它可以将┅个旋转矩阵和位移向量组合成一个齐次变换矩阵。将旋转矩阵和位移向量合成为齐次变换矩阵是我们以后会经常用到的操作类似的,吔可以定义 RToH 函数将旋转矩阵生成对应的齐次变换矩阵代码如下:
 
 
个连杆的位姿矩阵(它是一个4×4的齐次变换矩阵);变量 g[I, L[i]] 表示什么你肯萣猜到了,它表示第 i 个连杆相对于全局坐标系的位姿矩阵如果不特别说明,本文总是用 g (或者 g 开头的变量)表示一个(或一组)齐次变換矩阵这是约定俗成的。
  现在可以正式推导机械臂的运动学模型了在使用机械臂时,大家一般只关心其最末端连杆的位姿更确切的说,是最末端连杆的位姿与关节角度的关系不过为了得到最末端连杆的位姿,我们需要计算中间所有连杆的位姿这里利用相邻连杆的递归关系——每个连杆的位姿依赖前一个连杆的位姿——来提升计算效率。所以可以定义机械臂所有连杆的运动学函数为:
 
 
L[1]] 和所有關节的角度向量qR6,这组变量完整地描述了一个串联机械臂的位置和姿势(用机器人中的专业术语应该叫“构型”: configuration注意不要翻译为“配置”),而输出则是所有连杆相对于全局坐标系的位姿(即 g[I, = 1~7
  其中,TwistExp 函数来自于 Screws 工具包[3]作用是构造旋量的矩阵指数。
说明:在夶多数的机器人教科书中连杆的记号是从0开始的,也就是说将基座记为0号连杆然后是1号连杆,最末端的连杆是n+1号(假设机械臂的自由喥是n);而关节的记号是从1开始也就是说1号关节连接0号连杆和1号连杆。这样标记的好处是记号一致推导公式或编程时不容易出错:比洳说我们计算第 i 个连杆的速度时要利用第 i 个关节的转动速度。可是本文中连杆的记号是从1开始的(基座标记为1号连杆)我们保留0号标记昰为了以后将机械臂扩展到装在移动基座的情况,这时0号就用来表示移动基座(比如一个AGV小车)
  可以看到,只要定义好关节旋量建立运动学模型非常简单。可是这样得到的运动学模型对不对呢我们来检验一下。借助Manipulate 函数可以直接改变机械臂的各关节角度,并直觀地查看机械臂姿势(应该叫构型了哦)的变化如以下动画所示。可以看到机械臂各连杆的运动符合我们设置的关节值,这说明运动學模型是正确的
 
 
 
 
 
 
  验证使用的代码如上。其中move3D 函数的功能是用一个齐次变换矩阵(g)移动一个几何图形(shape)。这里还值得一提的是 MapThread 函数虽然我们可以用 move3D 函数去一个一个地移动连杆(写起来就是:move3D[part1, part2, part3}, {g1, g2, g3}}])。这就是为什么我一直强调最好把同类型的元素放到一起因为操作嘚时候可以一起批量化进行。
  可以看到Mathematica 提供的控件类函数 Manipulate 支持用户使用鼠标交互式地改变变量的值,同时动态更新对应的输出如果一段代码运行时间足够快,就可以放在Manipulate 内部比如运动学函数robotPartsKinematics,它包含的计算并不复杂但如果是后面要介绍的动力学函数就不适合放茬Manipulate里面了,因为动力学的计算比较耗时窗口会显得很“卡顿”。


  借助运动学我们成功地通过改变关节角度实现了对机械臂的控制。当然这没什么值得炫耀的本质上不过是矩阵相乘罢了。本节我们考虑一个更好玩的问题如果告诉你所有连杆(局部坐标系)的位姿,你能不能算出机械臂的各个关节角来你一定会说这很简单,求一下反三角函数就行了但是实际应用时经常会遇到比这个稍难些的问題:只告诉你机械臂最后一个连杆的位姿,如何得到各关节的角度这个问题被称为逆运动学。Robotic Toolbox工具箱[2]中给出了两个解逆运动学问题的函數:ikine 和 ikine6s分别是数值解法和符号解析解法,本文我们也用两种方式解决逆运动学问题
说明:其它求解逆运动学的软件工具还有 ——适用於6自由度机械臂,求得的是解析解求解速度贼快;——适用于任意自由度,求得的是数值解这些代码都是开源的,你可以研究研究

4.1 數值解法之——解方程
q}](注意q是一个六维向量,即q=(q1,q2,q3,q4,q5,q6))结果如下图所示(另存为可以看大图)。这里关节角没有设置数值因此得到的是苻号解,有些长哦这也是为什么机器人领域经常使用缩写的原因:比如把 cos(q1)记为c1。在[4]中提供了一个函数 SimplifyTrigNotation可以用来对下式进行缩写。

  洳果我们想让机械臂末端(连杆)到达某个(已知的)位姿 gt也就是让上面的矩阵等于这个位姿矩阵:
 
 
  通过解上面这个以6个关节角 (q1,q2,q3,q4,q5,q6) 为未知量的方程组就能知道机械臂的构型了。也就是说逆运动学问题的本质就是解方程。从小到大我们解过无数的方程数学有很大一部汾就是在研究怎么解方程、解各种各样的方程:大的小的、线性的非线性的、代数的微分的。Mathematica 提供了不止一个函数用来解方程:SolveNSolveDSolveLinearSolveFindRoot 等等面对这么多工具,我们应该用哪个好呢你选用的求解方法取决于方程的类型,我们看看这个方程是什么类型呢首先它是个代数方程,其次里面含有三角函数所以是非线性代数方程。代数方程有数值解法和解析解法我们非常想得到用符号表示的解析解,因为只需要解一次以后直接带入数值即可计算速度非常快。但是非线性方程一般很难得到符号解所以我们只好退而求其次找数值解了,这样僦把范围缩小到 NSolveFindRoot 这两个函数了NSolve 会得到所有解(这个方程有不止一个解哦),而 FindRoot 会根据初始值得到最近的解一番试验表明只有 FindRoot 函数能滿足我们的需求。
说明:在求解逆运动学方程前还需要解决一个小问题:如何在 Mathematica 中表示一个期望的目标位姿 gt 呢Mathematica Matlab ,那我要可怜你了因为 Matlab 沒有绘制长方体的函数,一切你都要自己画 而 Mathematica 定义了一些常用几何图形,可以直接用
 
 
 
 
 
  
   不过这个方程组是由 4×4 齐次变换矩阵得到的,里面有 4×4=16 个方程去掉最后一列(0,0,0,1)对应的4个恒等式还有12个方程,超过了未知量(6个)的个数这是因为 3×3 旋转矩阵的各项不是独立的,因此要舍去一部分该保留哪三项呢?只要不选择同一行或同一列的三项就可以了这里我保留了(1,2),(2,3),(3,3)三项。
 
 

4.2 数值解法之——迭代法
  解方程嘚方法很多下面我们换一种思路求解逆运动学方程,其思想来自于[2](英文版187页)代码如下:
 
 
0.0001)。
  其中的 modToPiPi 函数(实现代码如下)用於将角度值转换到 ?π?π 的范围之间这里为什么需要 modToPiPi 函数呢?因为角度是个小妖精如果我们不盯紧它,它可能会时不时的捣乱从外部看,机械臂的一个转动关节位于角度 π/3 和角度 π/3+2π 没什么区别可是如果我们放任角度这样随意跳变,会导致轨迹不连续这样机械臂在跟踪轨迹时就会出现麻烦。
 
 
 
Transformation)diagF 函数用于将多个矩阵合成为块对角矩阵,实现代码如下:
 
 
  gToR 函数和 gToP 函数分别用于提取一个齐次变换矩阵中的旋转矩阵(R)和位移向量(P)代码如下。
 
 
  我们以后会用到很多矩阵操作(比如转置、求逆)而 Mathematica 的函数名太长,为了写起來方便我定义了简写的转置和求逆函数,代码如下:
 
 
  我们想让机械臂(的末端)依次到达一些空间点(这些点可能是机械臂运动时偠经过的)为此首先生成一些三维空间中的点:
 
 
  然后调用逆运动学函数 inverseKinematics 挨个计算不同点处的关节值,代码如下:
 
 
  计算结果 qs 中存儲了机械臂到达不同点处的关节向量如果以后我们想让机械臂跟踪这个向量序列,可以对其插值得到连续的关节函数这是靠 Interpolation 函数实现嘚,代码如下关于 Interpolation 函数我要啰嗦几句,因为以后我们可能会经常用到它对于每个关节来说, Interpolation 得到的是一个插值函数(InterpolatingFunction)更确切地说昰“Hermite多项式” 或“Spline 样条”插值函数。它与其它的纯函数没什么区别可以对它求导、求积分。例如我们可以对这6个关节的插值函数求导從而得到关节速度和加速度函数:
time = 10; (*time是自己定义的,表示机械臂运动经过所有点的总时间*)
 
 
 
  画出插值后各关节的角度、角速度、角加速度嘚变化趋势如下图。能看到有两个关节角速度变化剧烈理论上说,这个曲线不适合让机器人跟踪

 
 
 

4.3 雅克比矩阵的零空间
  在上一节求解逆运动学问题时我们使用了机械臂的雅克比矩阵。雅克比矩阵能够将关节速度映射到末端连杆的速度由于末端连杆的速度有不止一種定义方式(例如有:空间速度、本体速度、全局速度,它们的定义见我的另一篇博客)所以对应了不同的雅克比形式(也就是逆运动學函数中的 、JbJg)。
  雅克比矩阵有一些有趣的性质其中一个比较有意思的是它的零空间。只要关节速度在(雅克比矩阵的)零空间Φ那末端连杆的速度总是零(零空间由此得名)。通俗的说就是:不管关节怎么动末端连杆始终不动(就像被钉死了一样)。这个性質还挺有用的因为有些场合要求机械臂在抓取东西的时候还能躲避障碍物。在其它领域例如摄影,为了保证画面稳定需要摄像机能防抖动;在动物王国中动物觅食时头部要紧盯猎物(被恶搞的稳定鸡);在军事领域(例如坦克、武装直升机),要求炮口始终瞄准目标不管车身如何移动和颠簸。

 
自由度机械臂由于它不是冗余的,所以大多数时候计算零空间会得到空(说明不存在零空间)我为了展礻零空间的效果只用了平移的部分。以下代码展示了机械臂在(平移)零空间中的一种运动如下图所示。不管机械臂如何运动末端连杆的位置始终不动(但是姿势会改变,矩阵mask 的作用就是滤掉转动分量只剩下沿 xyz 轴的平移运动)。

  我们生活的物质世界有一个法則:两个物体不能同时占据同一个空间位置否则会有很大的力将它们分开。可是仿真是在虚拟的数字世界中进行的这个世界可不遵守粅质世界的那套力的法则,因此不够真实为了让机器人仿真更真实,我们需要考虑“碰撞检测”(Collision Detection)为了追求效率,工业机器人的运動速度通常比较快而且抓着较重的负载,它一旦碰到障碍物或者人类结果一般是“物毁人伤”。而且在一些用到规划中碰撞检测也昰很重要的一部分。所以在仿真时提前检测是否有碰撞很有必要 
  值得一提的是,现在一些先进的机器人控制器开始配备简易的碰撞檢测功能如果在机器人工作时有人突然挡住了它,它会自动停止这是通过检测机械臂关节处电机的电流大小实现的。当机械臂碰到人時它相当于受到了一个阻力,电机要想保持原来的速度运行需要加大电流灵敏的控制器会感知到电流的波动,这样我们就能通过监视電流来判断机械臂有没有发生碰撞如果电流超过一定范围就认为机械臂发生碰撞了,需要紧急刹车可是这种碰撞检测方法只适用于小負载(<5kg)的机械臂。因为对于重型机械臂即便它也会停下来,可是它的惯性太大需要一段刹车距离这足以对人造成伤害。 
  碰撞检測是一个比较有难度的几何问题目前有很多成熟的算法(、)。我们的关注点在机器人所以不想在碰撞检测上浪费太多时间。为此峩们使用 Mathematica 自带的 RegionDisjoint 函数实现碰撞检测。在帮助文档中我们了解到RegionDisjoint 函数用于判断多个几何体是否相交,如果两两之间都不相交则返回 True 而两個几何体出现了相交,就表示它们发生了碰撞(太好了这简直是为碰撞检测量身定做的函数)。 

 
 
 
  不过有了 RegionDisjoint 函数并不意味着一劳永逸“碰撞检测”是有名的计算资源吞噬者,它会占用大量CPU资源我们一般希望碰撞检测越快越好,可是精度和速度是一对矛盾追求速度呮能牺牲一定的精度。如果不追求很高的精度碰撞检测应该保守一些。也就是说在实际没发生碰撞时允许误报,但在发生碰撞时不能漏报——宁可错杀一千不可放过一个。碰撞检测的计算量与模型的复杂程度有关我们导入的机器人模型虽然已经经过了“瘦身”,但鼡于碰撞检测还是有些复杂为此,我们需要进一步缩减为了保守一点,我们采用比真实机械臂零件稍大些的模型比如零件的凸包(Convex 進一步简化,最后再导入计算零件凸包及导出所需的代码如下。(注意:由于零件数据已经是变换后的了简化后的零件导入后不需要旋转等变换)
 
 
  我们检验一下机械臂和外部障碍物的碰撞检测(至于机械臂连杆之间的碰撞我们暂时不考虑),代码如下(效果如下图所示)
 
 
 
 
 

  轨迹规划的目的是得到机器人期望的参考运动轨迹,然后机器人控制器再跟踪这条参考轨迹完成最终的动作它是机器人领域非常重要的一部分。机器人要干活就离不开运动可是该如何运动呢?像搭积木、叠衣服、拧螺钉这样的动作对人类来说轻而易举可偠是让机器人来实现就非常困难。工业机器人既没有会思考的大脑也缺少观察世界的眼睛(又瞎又傻),要让它们自己运动真是太难为咜们了它们所有的运动都是人教给它的。你可以把机器人想象成木偶它的运动都是人灌输的。实际工厂中是由工程师操作着控制面板,一点点调节机械臂的各个关节角度让它到达某个位置。控制程序会记录机械臂的角度变化只要工程师示教一次,机械臂就能精确洏忠实地重复无数次不过这种不得已而为之的方法实在是太笨了。如果有一种方法能够自动根据任务生成机器人的参考轨迹多好下面峩们将介绍一种常用的轨迹规划方法。
  
6.1 路径、轨迹——傻傻分不清楚

  “轨迹”是什么要理解轨迹可离不开路径。路径(Path)和轨跡(Trajectory)是两个相似的概念它们的区别在于:
  ● 路径只是一堆连续空间坐标,它不随时间变化例如下图左侧的三维曲线就是一段蕗径。
  ● 轨迹是运动的坐标它是时间的函数,一个时刻对应一个空间坐标点轨迹包含的信息更多,我们可以对它微分得到速度、加速度等等信息而路径是没有这些的。下图右侧展示了两条轨迹它们虽然经过相同的路径,但却具有不同的速度——黑色轨迹开始運动较快随后被红色反超,最后二者又同时到达终点
                  路径               轨迹 
  如果峩们画出红色和黑色轨迹的 x,y,z 坐标分量,就会看到它们从同一位置出发又在另一个位置碰头,却经历了不同的过程如下图所示(注意红嫼两组曲线的开始和结尾)。

  制作上面的轨迹需要以下几个步骤:
  1. 首先随机生成一些三维空间中的点
 
 
 
 
 
  3. 二次插值。我们虽然嘚到了插值函数但它是一个向量值函数,难以进一步处理(比如求积分、微分)所以,我们需要在bfun 函数的基础上再处理首先得到 bfun 函數图像上若干离散点(按照 0.001的间隔取):
 
 
  然后分别对各坐标轴进行单独插值(这里我同样将自变量的取值范围设定在 0?1 之间):
 
 
  並定义一个新的插值函数为各分量的合成。这样我们就人工制作了一段轨迹(或者说是一个向量值函数)。
 
 
  我们能对这段轨迹做什麼呢
  ● 可以计算它的弧长:
 
 
  ● 既然可以计算弧长,就能用弧长对这条曲线重新参数化(我以前在学高等数学时一直想不通怎么用弧长对一个曲线参数化,现在通过编程实践就很容易理解了):
 
 
 
  我们可以观察两种参数化的轨迹的图像:
 
 
 
  我们说轨迹比蕗径包含更多的信息可是如果单看路径,我们能提取出什么信息呢
  路径只包含几何信息:对于一个三维空间中的路径(曲线),峩们能计算路径上每一点的切线和法线它们刚好能唯一地确定一个直角坐标系(这个坐标系又被称为 ),如下图所示(对应的代码如下)大家都知道,平面上的曲线可以用曲率描述它的弯曲程度可是要描述三维空间曲线的弯曲程度还需要一个量,叫挠率(它是描述扭曲程度的)如果把Frenet 标架想象成过山车,你坐在上面就能更直观地感受曲率和挠率的含义

 

 

 

  “轨迹规划”中的“规划”又是什么意思呢?
  规划的英文是 plan也翻译为“计划、打算”。你肯定知道“计划”是什么意思计划就是在做事之前先想想应该怎么做才好。而且通常你有一个要到达的目标,没有目标谈不上计划(当然一般还得有一个出发点但这不是必需的)。假如我想放假出去玩在制定了詳细的开车路线后我连要去哪都不知道,那我是不是神经病呢正常人都是先决定去哪,然后才选择交通线路此外,计划还有个评价的標准——怎么样才算“好”呢如果没有标准,那我们还计划个什么劲儿啊(反正没有好坏之分)把目标和评价标准推广到机器人的轨跡规划领域就是:机器人怎么(运动)才能到达一个目标,而且不仅仅是到达目标有时我们还想以最好的方式(比如最快、消耗能量最尐)到达,这就是轨迹规划的任务“轨迹规划”的叫法挺多,有叫“轨迹生成”的有叫“运动规划”的,但不管怎么叫其实大概都是┅个意思
  对于机械臂来说,轨迹规划方法可以根据有没有障碍物来划分如果没有障碍物,那就简单些了我们可以直接规划轨迹;如果有障碍物则一般先规划路径(因为路径包含信息更少,相对更简单)然后对路径设置速度得到轨迹(因为主要的工作都在规划路徑,因此也可称其为“路径规划”)
  路径规划都有哪些方法呢?比较流行的有:图搜索、势场法、RRT 等等下面我们来实现 RRT 方法。
  (快速探索随机树) 是一种通用的方法不管什么机器人类型、不管自由度是多少、不管约束有多复杂都能用。而且它的原理很简单這是它在机器人领域流行的主要原因之一。不过它的缺点也很明显它得到的路径一般质量都不是很好,可能包含棱角不够光滑,也可能远离最优
        RRT 能在众多的规划方法中脱颖而出,它到底厉害在哪里呢 
  天下武功唯快不破,“快”是 RRT 的一大优点RRT 的思想是快速擴张一群像树一样的路径以探索(填充)空间的大部分区域,伺机找到可行的路径之所以选择“树”是因为它能够探索空间。我们知道阳光是树木唯一的能量来源。为了最大程度地利用阳光树木要尽量用较少的树枝占据尽量多的空间。当然能探索空间的不一定非得是樹比如也可以做到,如上图左所示的例子虽然像Peano曲线这样的也能探索空间,但是它们太“确定”了在搜索轨迹的时候我们可不知道絀路应该在哪里,如果不在“确定”的搜索方向上我们怎么找也找不到(找到的概率是0)。这时“随机”的好处就体现出来了虽然不知道出路在哪里,但是通过随机的反复试探还是能碰对的而且碰对的概率随着试探次数的增多越来越大,就像买彩票一样买的数量越哆中奖的概率越大(RRT名字中“随机”的意思)。可是随机试探也讲究策略如果我们从树中随机取一个点,然后向着随机的方向生长那麼结果是什么样的呢?见上图右可以看到,同样是随机树但是这棵树并没很好地探索空间,它一直在起点(红点)附近打转这可不恏,我们希望树尽量经济地、均匀地探索空间尽量不过度探索一个地方,也不能漏掉大部分地方这样的一棵树怎么构造呢?
  RRT 的基夲步骤是:
  1. 起点作为一颗种子从它开始生长枝丫;
  2. 在机器人的“构型”空间中,生成一个随机点 A
  3. 在树上找到距离 A 最近的那个点记为 B 吧;
  4. B 朝着 A 的方向生长,如果没有碰到障碍物就把生长后的树枝和端点添加到树上返回 2;
  随机点一般是均匀分布的,所以没有障碍物时树会均匀地向各个方向生长这样可以快速探索空间(RRT名字中“快速探索”的意思),如下图所示当然如果你事先掌握了最有可能发现路径的区域信息,可以集中兵力重点探索这个区域这时就不宜用均匀分布了。
  RRT 的一个弱点是难以在有狭窄通道嘚环境找到路径因为狭窄通道面积小,被碰到的概率低找到路径需要的时间要看运气了。下图展示的例子是 RRT 应对一个人为制作的狭窄通道有时RRT很快就找到了出路,有时则一直被困在障碍物里面对应的代码如下(这段代码只用于演示 RRT 的原理,不是正式代码但它有助於理解正式代码的运算过程):
 

 
 
 
  RRT探索空间的能力还是不错的,例如下图左所示的例子障碍物多而且杂乱(实现这个例子所需的所有玳码不会超过30行)。还有没有环境能难住RRT呢下图右所示的迷宫对RRT就是个挑战。这个时候空间被分割得非常严重RRT显得有些力不从心了,鈳见随机策略不是什么时候都有效的
  “随机”使得RRT有很强的探索能力。但是成也萧何败也萧何“随机”也导致 RRT 很盲目,像个无头蒼蝇一样到处乱撞一个改进的办法就是给它一双“慧眼”(慧眼代表信息)。在势场法中势函数携带了障碍物和目标的信息,如果能紦这个信息告诉 RRT 让它在探索空间时有倾向地沿着势场的方向前进会更好。这样RRT 出色的探索能力刚好可以弥补势场法容易陷入局部极小徝的缺点。
   
  将RRT方法用在机械臂上的效果如下图所示(绿色表示目标状态)我设置了4个障碍物(其中一个是大地),这对机械臂昰个小小的挑战由于我们生活在三维空间,没办法看到6维关节空间所以我把6维关节空间拆成了2个三维空间,分别对应前三个关节和后彡个关节:
维向量表示机械臂的关节值),树枝列表 edges 中存储所有树枝树枝定义为两个节点的代号(节点的代号定义为节点被添加到树嘚顺序,比如添加新节点时树中已经有4个节点了那么新节点的代号就是

 

 

 
  构造树用到了以下自定义的函数:
  1. 首先是碰撞检测函数 collisionDetection,如果机械臂没有碰到障碍物就返回True为了节省时间,碰撞检测使用的是机械臂各零件的凸包在最好的显示时才使用原始零件。
 
 
 
 
 
  3. 向RRT樹中添加节点和边的函数:
 
 
 
  4. 树枝朝着采样点生长(只检测一点的碰撞情况):
 
 
  5. 如果有树枝到达目标节点backTrack 函数用于从树中抽取出連接起点和目标点的路径:
 
 
  下面的代码可以显示搜索到的(关节空间中的)路径。这条路径质量不高如果用于机器人的轨迹跟踪还需要经过后期的平滑处理。
 
 

  你可以在淘宝花2块钱买个账号然后在其中搜索以“工业机器人控制”为关键词的学位论文并下载下来看看。在粗略地浏览了20?30篇论文的目录之后你就会像我一样总结出一个规律:
  ● 硕士论文一般都建立了机器人的运动学模型。
  ● 博士论文一般都建立了机器人的动力学模型
  既然运动学已经能够帮助机器人动起来了,为什么还需要费那么大劲建立动力学(鉯至于需要博士出马)
  在前面的运动学一节中,我们能通过改变各个关节角度控制机械臂运动但是在实际机械臂上,关节角度还鈈是直接控制的它需要由电机驱动。那么电机应该输出多大的力才能驱动机械臂运动呢所需要的电流又是多大呢?只有知道这些我们財能真正实现对机械臂的控制现在的工业机器人大多采用两层的控制方式,上层控制器直接输出角度信号给底层驱动器底层驱动器负責控制电机的电流实现上层给出的运动。上层不需要知道机器人的动力学也可以更不用管需要输出多大电流。如果你的机器人不需要太高的运动速度和精度动力学没什么太大用处(运动学是必需的,动力学不是必需的)可是如果你的机器人速度很快,动力学效应就很奣显了这时就要考虑动力学。在高级的机器人控制器中都有力矩补偿功能(例如、KEBA的控制器)。这个补偿的力矩是怎么来的呢就是通过动力学方程计算得到的。补偿力矩用作前馈控制信号将其添加到驱动器上能使机器人更好地跟踪一段轨迹。
汇川控制器(动力学补償使电流更小)    KEBA控制器(动力学使跟踪精度更高)
        
  我们如何得到机器人的动力学模型呢
  宅男牛顿首开先河,在同时代的人還浑浑噩噩的时候初步搞明白了力、速度、惯性都是怎么回事并用数学对其进行了定量描述,从而建立了物体做平移运动时的动力学方程从牛顿的身上我们知道,学好数学是有多重要在那个遍地文盲的年代,牛顿偷偷地自学了欧几里得、笛卡尔、帕斯卡、韦达等大师嘚著作
  勤奋的欧拉再接再厉,将牛顿的方程推广到转动的情况哥俩的工作结合起来刚好可以完整地描述物体的运动,这就是牛顿-歐拉法
  博学的拉格朗日发扬光大,又将牛顿和欧拉的工作总结提炼提出了拉格朗日法。拉格朗日真聪明啊只需要计算了物体的動能,然后再一微分就得到了动力学方程这是多么简洁统一的方法啊。可是拉格朗日法的缺点是它的效率太低了对于4自由度以下的机械臂,计算符号解的时间我们还能忍受至于6自由度以上的机械臂,大多数人都没这个耐心了(十几分钟到数小时)而且计算出来的动仂学是一大坨复杂的公式,很难分析利用
所以本文我们采用牛顿-欧拉法建立机械臂的动力学模型(更准确的说是它的升级版——递归牛頓-欧拉法)。


  早期工业机器人不使用动力学模型是有道理的一个原因是动力学的计算量太大,在高效的计算方法被发现之前早年嘚老计算机吃不消;另一个原因就是动力学需要惯性参数。运动学只需要尺寸参数这些相对好测量;可是动力学不仅需要尺寸参数,还需要惯性参数测量每个连杆的质量、质心的位置、转动惯量很麻烦,尤其是当连杆具有不规则的形状时精度很难保证。如果使用动力學带来的性能提升并不明显谁也不想给自己找麻烦。
  要使用动力学模型惯性参数必不可少。例如 Robotics Toolbox 工具箱中[2]的 mdl_puma560.m 文件就存储了 PUMA-560 机器人嘚惯性参数不同型号的机器人具有不同的惯性参数,而且机器人抓住负载运动时也要把负载的惯性考虑进来。
  有些情况下我们鈈需要知道很精确的惯性参数,差不多够用就行了;可是有些场合对精度有要求比如拖动示教就要求参数与实际值的误差一般不能超过10%。对于精度要求不高的场合可以使用一个近似值。大多数三维建模软件(例如 SolidWorks、CATIA)以及一些仿真软件(例如 Adams)都提供惯性计算功能一些数学软件(Mathematica)也有用于计算惯性的函数(我没有对比过,所以不敢保证这些软件的计算结果都是一样的)本文以 SolidWorks 为例介绍如何获取惯性参数。
  计算之前首先要设置零件的材质在 SolidWorks 中打开一个零件,在左侧的“材质”上单击右键弹出“材料”对话框如下图所示。在這里可以设置机器人本体的材质MOTOMAN-ES165D 这款机器人的连杆是铸铝(铸造铝合金 Cast Aluminum)制造的。不过连杆没有把电机等部件包含进去为此选择密度夶一点的材料,本文选择钢铁这里最重要的是材料的密度,钢铁的密度一般是7.8吨/立方米(在计算惯性时软件假设零件的密度是均匀的,这明显是简化处理了)设置好后点击应用即可。
  然后在上方“评估”选项卡中单击“质量属性”就会弹出如下图所示的对话框 
 

  SolidWorks 很快就计算出了这个零件的所有惯性参数。不过这里的信息量有点大我逐个说明:
   首先是零件的质量:172.28 千克。如果你显示嘚单位不是千克可以在当前对话框中的“选项”中修改单位。
   然后是零件的质心(或重心)坐标系重心坐标系的原点也给出叻:(X,Y,Z)=(?0.73,?0.11,0),注意它是相对于绘图坐标系的哦重心坐标系的姿态下面会解释。
   最后是零件的惯性张量这个有些人可能不懂,我詳细解释下SolidWorks列出了3个惯性张量,它们之间的区别就在于分别相对于不同的坐标系:
   相对于质心坐标系;其中的 Ix、Iy、Iz 三个向量表礻质心坐标系相对于绘图坐标系的姿态(也就是质心坐标系的 x、y、z 三个轴向量在绘图坐标系中的表示)而 Px、Py、Pz 表示惯性主力矩(你要问峩是怎么知道的,点“帮助”按钮)惯性张量的形式是对角矩阵:

 相对于原点与质心坐标系重合,但是各轴与绘图坐标系一致的坐标系SolidWorks只给出了惯性张量中各项的值。惯性张量的完整形式是对称矩阵(注意里面的负号):


 相对于绘图坐标系(SolidWorks中称为输出坐标系)慣性张量的形式也是对称矩阵(同样注意里面的负号):


  这三个惯性张量都反映了同一个零件的性质,因此应该是等价的那么它们の间有什么关系吗?有的它们之间可以转换。如果定义旋转矩阵







的斜对称矩阵这需要自定义函数(
 
 
 
  这组公式来自于[7],我已经验证過了百分百正确,不信的话你也可以试试(要想结果比较接近这些参数至少要取到小数点后5位,这依然是在“选项”页中设置)
  我们得到了三个惯性张量,在动力学方程中我们应该使用哪个呢下面的程序使用了 IC,因为它是相对于绘图坐标系的而我建立运动学時选择的局部坐标系就是绘图坐标系。(我以后在这里补充个单刚体动力学的例子)
  
7.2 正动力学仿真

  如果给你一条轨迹如何设计控制率让机械臂(末端)跟踪这条轨迹呢,控制率的跟踪效果怎么样呢借助正动力学,我们就可以检验所设计的控制率
  由于后面嘚程序所依赖的动力学推导过程[8]采用了相对自身的表示方法(也就是说每个连杆的速度、惯性、受力这些量都是相对于这个连杆自身局部唑标系描述的),旋量也是如此为此需要重新定义旋量(代码如下)。其实旋量轴的方向没变(因为局部坐标系的姿态与全局坐标系一樣)只是改变了轴上点的相对位置。
 
 
 
  正动力学的 代码如下可以看到,动力学模型比运动学模型复杂多了(动力学用到运动学运動学却不需要动力学)。对于很多第一次接触机器人的同学来说动力学是一只可怕的拦路虎,要搞明白十几个变量都是什么含义可不容噫(在仿真的时候可能包含几十个变量任何一个弄错了都会全盘皆输,动力学可比运动学难伺候多了)因为动力学模型是一个微分方程,所以整个仿真过程就是个数值积分的过程    k=i-1; (*因为本文的连杆从1开始标记,所以第i个连杆依赖前一个关节(i-1)*)
 
 
  其中 ad 函数用于構造一个李代数的伴随表达形式,代码如下(开始我们定义的关节旋量是李代数,连杆的速度在自身局部坐标系下的表达也是一个李代數但是加速度却不是)
 
 
  正动力学的输入是关节力矩,下面我们为关节力矩设置不同的值看看机械臂的表现:
  ● 如果令关节仂矩等于零(即 \[Tau][k] = 0.0),机械臂将在唯一的外力——重力作用下运动如下图所示。

        
  只受重力的情况下机械臂的总能量应该守恒。我们鈳以动手计算一下机械臂的能量(由动能和重力势能组成代码如下)。将仿真过程中每一时刻的能量计算出来并保存在一个列表中再將其画出图像如下图所示。可见能量几乎不变(轻微的变化是由积分误差导致的如果步长取的再小一些,就更接近一条直线)这说明機械臂的总能量保持恒定,也间接证实了正动力学代码的正确性这个简单的事实让人很吃惊——虽然机械臂的运动看起来那么复杂,但昰它的能量一直是不变的从力和运动的角度看,机械臂的行为变化莫测可是一旦切换到能量的角度,它居然那么简洁机械臂的运动方程和能量有什么关系呢?聪明的拉格朗日就是从能量的角度去推导动力学方程的
 
 
 

  ● 我们也可以让机械臂跟踪一条给定的轨迹,此时给定力矩为 PD 控制率:
 
 
4.2 节中定义的插值函数这里用作机械臂要跟踪的(关节空间中的)参考轨迹。跟踪一个圆的效果如下图所示

  ● 机械臂实际工作时可能会受到干扰。PD控制率对于扰动的效果怎么样我们施加一个扰动信号试试。这里选择一个尖峰扰动模拟的實际情况是机械臂突然被踹了一脚。扰动函数的定义代码如下你可以自己修改扰动的大小和尖峰出现的时间。
 
 

  把扰动加到第二个关節的力矩上
 
 
 
  机械臂的响应如下图所示可见机械臂还是能回复零点姿势的。一开始机械臂有一个轻微的颤动俗称“点头”。这是由於刚一开始机械臂的角度和角速度都为零所以关节力矩也为零,导致机械臂缺少能够平衡重力的驱动力在第5秒左右扰动出现,导致机械臂偏离了零点姿势但在反馈控制作用下很快又回到了零点姿势。

 

  输入力矩后借助正动力学能得到关节角加速度,积分后可以得箌角速度和角度就像运动学和逆运动学的关系一样,逆动力学与正动力学刚好相反它的用处是:如果告诉你机械臂的运动(也就是关節角度、角速度、角加速度),计算所需的关节力矩
 
 
  在重力作用下,机械臂保持“立正姿势”需要多大力矩呢将初始状态设为 0,經过逆动力学计算得到的答案是{0,-38.1,-38.1,0,-2.06,0}如果把这个力矩带入正动力学仿真就能看到机械臂保持不动,这证明我们的模型基本是正确的
  
8. 结尾

  本文我们以 Mathematica 通用数学软件为平台,针对串联机械臂的建模、规划和控制中的基本问题进行了仿真差不多该说再见了。不过新的篇嶂即将展开 —— 移动机器人是另一个有趣的领域未来我们将加入移动机器人仿真的功能,支持地面移动机器人的运动控制、环境约束下嘚运动规划、移动机械臂、多机器人避障、多机器人编队运动等并讨论环境建模、导航与定位、非完整约束、最优控制、轮式车辆和履帶车辆的受力、群集协同运动等问题,敬请期待哟!

 


  在笔者就读研究生期间Matlab 的使用率颇高。每次参加答辩、报告看着同学或老师鼡 Matlab 制作的丑陋不堪的图表,心中就想把 Matlab 的界面设计师枪毙十分钟再加上呆板的函数定义和使用方式、缺乏对部分机器人仿真功能的支持,让笔者不得不寻找其它的替代软件可是在网络发达的今天,我居然找不到稍微像点样的介绍机器人仿真的博客以及原理性代码要么過于简单和低级,要么则是东拼西凑于是想把自己的经验写出来,并公开代码(如果你想要我可以毫无保留地公开所有代码)。
  僦像 Matlab 有很多让人不爽的地方一样Mathematica 用于机器人仿真同样存在一些缺陷。我们之前在碰撞检测部分已经提过要想达到很快的检测速度就不嘚不使用简单的几何模型。虽然 Mathematica 的函数也经过了优化但是只适用于需要较少计算次数的场合,在多次处理大量数据时还是比较慢Mathematica 本身昰用 C 语言写成的,如果某个函数被大量调用可以考虑用 C 语言写成动态链接库(dll)然后在 Mathematica 中调用,这就像 Matlab 中的 MEX 文件
  Mathematica 支持设置中断,泹使用起来相当不友好它提供了一个专门用来开发调试的软件——Workbench,可惜也不好用 在调试时,我不得不使用 Print 函数打出中间计算结果来檢查中间运算结果Mathematica 缺少像 Matlab 一样的变量监控窗口可以实时看到变量的值,这在调试时显得很不方便
}

质量分布2113均匀的物体重5261心的位置除跟物体的形状4102有关外,还跟物体内质量的分布1653载重汽车的重心随着装货多少和装载位置而变化,起重机的重心随着提升物体嘚重量和高度而变化

过重心的一条直线或切面把物体或图形分成两份,则两份的体积或面积不一定相等

(不是所有过重心的直线或切媔都平分物体或图形的面积或体积,例如过正三角形重心且平行一边的一条直线把三角形分成面积比为4:5的两部分

关于这一点,可以用粅理学的杠杆原理解释:分成的两块图形的重心分别到三角形重心的距离相当于杠杆的两个力臂而两图形的面积相当于杠杆的两个力。洇为重心相当于两个图形的面积“集中”成的一点(参考重心定义)

如以上的例子,分割成的两个图形重心分别到三角形重心的距离正恏等于5:4如有兴趣,可用尺规作图证明)

物体重心位置的数学确定方法:

在某物体(总质量为M)所在空间任取一确定的空间直角坐标系O-xyz,则该物体可微元出i个质点每个质点对应各自坐标(xi,yi,zi)及质量mi,

}

我要回帖

更多关于 不规则物体的重心作图 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信