当前位置:  开发笔记 > 编程语言 > 正文

二维逆运动学实现

如何解决《二维逆运动学实现》经验,为你挑选了2个好方法。

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

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

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

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

在此先感谢维克拉姆



1> Lars..:

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

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

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

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

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

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



2> antonakos..:

    旋转可以用它的角度或单位圆的复数表示,而不是旋转矩阵,但实际上它是相同的.更重要的是,你需要一个代表性T的刚体变换,让你可以写这样的东西t1 * t2 * t3来计算第三连杆的位置和方向.

    使用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

推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有