2D 逆运动学实现

发布于 2024-08-28 18:51:47 字数 358 浏览 8 评论 0原文

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

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

  2. 最下面的手臂仅向一个方向移动。我尝试用谷歌搜索,他们说两个向量的叉积给出了手臂的方向,但这是针对 3D 的。我使用 2D 和两个 2D 向量的叉积给出一个标量。那么,我怎样才能确定它的方向???

请大家提供任何帮助,我们将不胜感激......

提前致谢 维克拉姆

I am trying to implement Inverse Kinematics on a 2D arm(made up of three sticks with joints). I am able to rotate the lowest arm to the desired position. Now, I have some questions:

  1. How can I make the upper arm move alongwith the third so the end point of the arm reaches the desired point. Do I need to use the rotation matrices for both and if yes can someone give me some example or an help and is there any other possibl;e way to do this without rotation matrices???

  2. The lowest arm only moves in one direction. I tried google it, they are saying that cross product of two vectors give the direction for the arm but this is for 3D. I am using 2D and cross product of two 2D vectors give a scalar. So, how can I determine its direction???

Plz guys any help would be appreciated....

Thanks in advance
Vikram

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤君无依 2024-09-04 18:51:47

我会尝试一下,但由于我的机器人技术已经是二十年前的事了,所以对此持保留态度。

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

这完全达到了您想要的效果:您只能移动一个关节(改变其方向),所有其他关节都会自动跟随。

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

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

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

I'll give it a shot, but since my Robotics are two decades in the past, take it with a grain of salt.

The way I learned it, every joint was described by its own rotation matrix, defined relative to its current position and orientation. The coordinate of the whole arm's endpoint was then calculated by combining the rotation matrices together.

This achieved exactly the effect you are looking for: you could move only one joint (change its orientation), and all the other joints followed automatically.

You won't have much chance in getting around matrices here - in fact, if you use homogeneous coordinates, all joint calculations (rotations as well as translations) can be modeled with matrix multiplications. The advantage is that the full arm position can then be described with a single matrix (plus the arm's origin).

With this transformation matrix, you can tackle the inverse kinematic problem: since the transformation matrix' elements will depend on the angles of the joints, you can treat the whole calculation 'endpoint = startpoint x transformation' as a system of equations, and with startpoint and endpoint known, you can solve this system to determine the unknown angles. The difficulty herein lies that the equation may not be solvable, or that there are multiple solutions.

I don't quite understand your second question, though - what are you looking for?

哽咽笑 2024-09-04 18:51:47
  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

定义从一个关节到下一个关节变换的正向运动学函数。我们假设关节旋转角度,然后进行固定变换joint

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

工具的变换为tool == fk(joints, q) code> 其中 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 个相同链接的臂,并从随机臂配置 q 开始运行 CCD 扫描的 cnt 次迭代:

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. Instead of a rotation matrix, the rotation can be represented by its angle or by a complex number of the unit circle, but it's the same thing really. More importantly, you need a representation T of rigid body transformations, so that you can write stuff like t1 * t2 * t3 to compute the position and orientation of the third link.

  2. Use atan2 to compute the angle between the vectors.

As the following Python example shows, those two things are enough to build a small IK solver.

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

The gameobjects library does not have 2D transformations, so you have to write matrix33 yourself. Its interface is just like gameobjects.matrix44.

Define the forward kinematics function for the transformation from one joint to the next. We assume the joint rotates by angle and is followed by a fixed transformation joint:

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

The transformation of the tool is tool == fk(joints, q) where joints are the fixed transformations and q are the joint angles:

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

If the base of the arm has an offset, replace the T.identity() transformation.

The OP is solving the IK problem for position by cyclic coordinate descent. The idea is to move the tool closer to the goal position by adjusting one joint variable at a time. Let q be the angle of a joint and prev be the transformation of the base of the joint. The joint should be rotated by the angle between the vectors to the tool and goal positions:

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())

Traverse the joints and update the tool configuration for every change of a joint value:

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

Note that fk() and ccd_sweep() are the same for 3D; you just have to rewrite fk_joint() and ccd_step().

Construct an arm with n identical links and run cnt iterations of the CCD sweep, starting from a random arm configuration 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)

We can try out the solver and compare the rate of convergence for different numbers of links:

>>> 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
零度° 2024-09-04 18:51:47

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

In robotics we most often use DH parameters for the forward and reverse kinematics. Wikipedia has a nice introduction.

深海不蓝 2024-09-04 18:51:47

DH (Denavit-Hartenberg) 表示法是解决方案的一部分。它可以帮助您收集一组简洁的值来描述机器人的机械结构,例如连杆长度和关节类型。

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

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

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

不过,逆运动学有点复杂,取决于您的应用程序。复杂性是由于同一问题有多种解决方案而产生的。 DOF 数量越多,解的数量就越多。

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

The DH (Denavit-Hartenberg) notation is part of the solution. It helps you collect a succinct set of values that describe the mechanics of your robot such as link length and joint type.

From there it becomes easier to calculate forward kinematics. The first think you have to understand is how to translate a coordinate frame from one place to another coordinate frame. For example, given your robot (or the DH table of it), what is the set of rotations and translations you have to apply to one coordinate frame (the world for example) to know the location of a point (or vector) in the robot's wrist coordinate frame.

As you may already know, homogeneous transform matrices are very useful for such transformations. They are 4x4 matrices that encapsulate rotation and translation. Another very useful property of those matrices is that if you have two coordinate frames linked and defined by some rotation and translation, if you multiply the two matrices together, then you just need to multiply your transformation target by the product of that multiplication.

So the DH table will help you build that matrix.

Inverse kinematics is a bit more complicated though and depends on your application. The complication arises from having multiple solutions for the same problem. The greater the number of DOF, the greater the number of solutions.

Think about your arm. Pinch something solid around you. You can move your arm to several locations in the space and still keep your pinching vector unchanged. Solving the inverse kinematics problem involves deciding which solution to choose as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文