二维逆运动学实现

时间:2010-04-12 20:56:36

标签: animation rotation robotics inverse-kinematics

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

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

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

  3. Plz家伙会感激任何帮助....

    提前致谢 维克拉姆

4 个答案:

答案 0 :(得分:7)

我会试一试,但是因为我的机器人技术已经过去了二十年,所以要把它带上一粒盐。

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

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

你在这里找到矩阵的可能性不大 - 实际上,如果使用齐次坐标,所有联合计算(旋转和平移)都可以用矩阵乘法建模。优点是可以用单个矩阵(加上手臂的原点)来描述全臂位置。

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

我不太明白你的第二个问题 - 你在寻找什么?

答案 1 :(得分:6)

  1. 旋转可以用它的角度或complex number of the unit circle来代替旋转矩阵,但实际上它是一样的。更重要的是,您需要T代表t1 * t2 * t3,以便您可以编写atan2之类的内容来计算第三个链接的位置和方向。

  2. 使用from gameobjects.vector2 import Vector2 as V from matrix33 import Matrix33 as T from math import sin, cos, atan2, pi import random 计算rigid body transformations

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

    matrix33

    angle between the vectors库没有2D转换,因此您必须自己编写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()

    如果手臂的基部有偏移,请替换q转换。

    OP正在通过循环坐标下降来解决位置的IK问题。我们的想法是通过一次调整一个关节变量来使工具更接近目标位置。设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()fk_joint()与3D相同;您只需重写ccd_step()n

    构建一个具有cnt个相同链接的手臂,并从随机手臂配置q开始运行CCD扫描的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
    

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

    {{1}}

答案 2 :(得分:3)

在机器人技术中,我们通常使用DH参数来进行正向和反向运动。 Wikipedia有一个很好的介绍。

答案 3 :(得分:3)

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

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

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

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

反向运动虽然有点复杂,但取决于您的应用。复杂性源于针对同一问题提供多种解决方案。 DOF的数量越多,解决方案的数量就越多。

想想你的手臂。在你周围捏一些坚实的东西。您可以将手臂移动到空间中的多个位置,并保持收缩矢量不变。解决逆运动学问题涉及决定选择哪种解决方案。