10

我正在尝试在 2D 手臂(由三根带关节的棍子组成)上实现反向运动学。我能够将最低的手臂旋转到所需的位置。现在,我有一些问题:

  1. 如何使上臂与第三臂一起移动,使手臂的终点到达所需的点。我是否需要对两者都使用旋转矩阵,如果是的话,有人可以给我一些例子或帮助吗?还有其他可能的方法吗?不用旋转矩阵来做到这一点???

  2. 最低的手臂只向一个方向移动。我试过谷歌,他们说两个向量的叉积给出了手臂的方向,但这是针对 3D 的。我正在使用 2D 和两个 2D 向量的叉积给出一个标量。那么,如何确定它的方向???

Plz伙计们任何帮助将不胜感激....

在此先感谢维克拉姆

4

4 回答 4

7

我会试一试,但由于我的机器人技术已经过去了 20 年,所以还是持保留态度。

根据我的学习方式,每个关节都由其自己的旋转矩阵描述,相对于其当前位置和方向定义。然后通过将旋转矩阵组合在一起来计算整个手臂端点的坐标。

这完全达到了您正在寻找的效果:您只能移动一个关节(更改其方向),而所有其他关节自动跟随。

你不会有太多机会在​​这里绕过矩阵 - 事实上,如果你使用齐次坐标,所有联合计算(旋转和平移)都可以用矩阵乘法建模。优点是整个手臂位置可以用单个矩阵(加上手臂的原点)来描述。

使用此变换矩阵,您可以解决逆运动学问题:由于变换矩阵的元素将取决于关节的角度,因此您可以将整个计算“端点 = 起点 x 变换”视为方程组,并带有起点并且端点已知,您可以解决此系统以确定未知角度。这里的困难在于方程可能无法解,或者存在多个解。

不过,我不太明白你的第二个问题——你在找什么?

于 2010-04-12T21:31:18.327 回答
6
  1. 除了旋转矩阵,旋转可以用它的角度或单位圆的复数来表示,但实际上是一回事。更重要的是,您需要一个刚体变换T的表示,这样您就可以编写诸如计算第三个链接的位置和方向之类的东西。t1 * t2 * t3

  2. 用于atan2计算向量之间的角度

如以下 Python 示例所示,这两件事足以构建一个小型 IK 解算器。

from gameobjects.vector2 import Vector2 as V
from matrix33 import Matrix33 as T
from math import sin, cos, atan2, pi
import random

gameobjects库没有2D 转换,所以你必须matrix33自己编写。它的界面就像gameobjects.matrix44.

定义从一个关节到下一个关节的转换的正向运动学函数。我们假设关节旋转angle并跟随一个固定的变换joint

def fk_joint(joint, angle): return T.rotation(angle) * joint

工具的变换是tool == fk(joints, q)固定joints变换,q是关节角度:

def fk(joints, q):
    prev = T.identity()
    for i, joint in enumerate(joints):
        prev = prev * fk_joint(joint, q[i])
    return prev

如果手臂的底部有偏移,请更换T.identity()变换。

OP正在通过循环坐标下降来解决位置的IK问题。这个想法是通过一次调整一个关节变量来使工具更接近目标位置。设q为关节的角度, 为关节prev底面的变换。关节应旋转到工具和目标位置的向量之间的角度:

def ccd_step(q, prev, tool, goal):
    a = tool.get_position() - prev.get_position()
    b = goal - prev.get_position()
    return q + atan2(b.get_y(), b.get_x()) - atan2(a.get_y(), a.get_x())

遍历关节并为关节值的每次变化更新工具配置:

def ccd_sweep(joints, tool, q, goal):
    prev = T.identity()
    for i, joint in enumerate(joints):
        next = prev * fk_joint(joint, q[i])
        q[i] = ccd_step(q[i], prev, tool, goal)
        prev = prev * fk_joint(joint, q[i])
        tool = prev * next.get_inverse() * tool
    return prev

注意fk()ccd_sweep()对于 3D 是一样的;你只需要重写fk_joint()ccd_step().

构造一个具有n相同链接的臂并运行cntCCD 扫描的迭代,从随机臂配置开始q

def ccd_demo(n, cnt):
    q = [random.uniform(-pi, pi) for i in range(n)]
    joints = [T.translation(0, 1)] * n
    tool = fk(joints, q)
    goal = V(0.9, 0.75)  # Some arbitrary goal.
    print "i     Error"
    for i in range(cnt):
        tool = ccd_sweep(joints, tool, q, goal)
        error = (tool.get_position() - goal).get_length()
        print "%d  %e" % (i, error)

我们可以尝试求解器并比较不同数量的链接的收敛速度:

>>> ccd_demo(3, 7)
i     Error
0  1.671521e-03
1  8.849190e-05
2  4.704854e-06
3  2.500868e-07
4  1.329354e-08
5  7.066271e-10
6  3.756145e-11
>>> ccd_demo(20, 7)
i     Error
0  1.504538e-01
1  1.189107e-04
2  8.508951e-08
3  6.089372e-11
4  4.485040e-14
5  2.601336e-15
6  2.504777e-15
于 2010-12-23T00:25:24.193 回答
3

在机器人技术中,我们最常将 DH 参数用于正向和反向运动学。维基百科有一个很好的介绍。

于 2010-04-13T12:13:12.053 回答
3

DH (Denavit-Hartenberg) 表示法是解决方案的一部分。它可以帮助您收集一组简洁的值,这些值描述了您的机器人的机制,例如链接长度和关节类型。

从那里开始计算正向运动学变得更容易。您首先要了解的是如何将坐标系从一个地方转换到另一个坐标系。例如,给定您的机器人(或它的 DH 表),您必须将一组旋转和平移应用于一个坐标系(例如世界)以了解点(或矢量)在机器人手腕坐标系。

您可能已经知道,齐次变换矩阵对于此类变换非常有用。它们是封装旋转和平移的 4x4 矩阵。这些矩阵的另一个非常有用的属性是,如果您有两个通过旋转和平移链接和定义的坐标系,如果您将两个矩阵相乘,那么您只需将变换目标乘以该乘法的乘积。

因此,DH 表将帮助您构建该矩阵。

不过,反向运动学要复杂一些,具体取决于您的应用。复杂性源于对同一问题有多种解决方案。自由度数越大,解的数量就越多。

想想你的手臂。捏紧你周围的固体。您可以将手臂移动到空间中的多个位置,并且仍然保持捏合矢量不变。解决逆运动学问题还包括决定选择哪种解决方案。

于 2010-04-14T16:09:25.793 回答