2D Inverse Kinematics
Demo coming soon...
Q: What is inverse kinematics?
Inverse Kinematics is having a series of connected links that constitute a limb, where the links are
rotated in order for the limb to reach a specified position with its tip. The (base) position of the
first link is fixed, giving the limb a fixed base position.
Armed with a definition of Inverse Kinematics. I define my link data as follows:
- Position: Location of the link's base (Illustrated below.)
- Orientation: The orthonormal basis vectors which tell you where the link is facing (And in 3d, it's
roll angle--more on this later.)
- Length: Scalar value denoting how long the link is.
As you can imagine there are different possible scenarios:
- The target position is out of reach for the limb.
The target position is in reach of the limb.
If our limb is made of more than one link when the target position is in reach, there is more than one
limb configuration that would work to reach the target position (As illustrated below.)
Defining a goal (and the problems that must be overcome to achieve it):
Let's make a limb that operates on 2D IK to try and reach a target position which we can move around.
This limb will be structured roughly like a mantis's mandible, with the following rules:
- Limb is made of three links.
- Limb has a rest configuration which it starts out in, and returns to when not reaching for a target position.
Each link in the limb has constraints which make it impossible to rotate any given link past a certain
angle either CW or CCW from the angle it's parent link is at. Since the first link does not have a parent
link, it will be constrained from moving a certain amount CW or CW from its rest angle.
- The links, and the limb as a whole, will move in a smooth way at all times while trying to touch the target position.
- The further the limb is from the target position, the faster it will rotate to try and acquire it, the closer the slower.
Whether or not the limb is in range of reaching the target position, it will converge on one configuration,
and not alternate between configurations.
- 1) How to move the links (and thus the limb) to achieve IK?
- 2) How to constrain the rotation of links, such that the limb moves smoothly (without jerking or snapping)?
- 3) How to constrain the rotation of links, such that it only uses one configuration for reaching or trying to
reach the target-position?
Let the following serve as motivation:
As you can see, the result of achieving the goal will awesome.
Solving the problem(s):
There are a number of popular approaches to achieving IK:
I will not be using any of these for the following reasons.
- Close form solution
- Jacobian Matrix Solution
- Jacobian Transpose Solution
- Cyclic-Coordinate Descent Solution
What I will do to simulate 2D IK is use an iterative approach, determining minuscule amounts
Close form solution:
Not immune to kinematic singularities.
Jacobian Matrix Solution:
Complex math, 6x6 matrix computation.
Slower convergence rates when it is close to a solution
Jacobian Transpose Solution:
Not immune to kinematic singularities.
Cyclic-Coordinate Descent Solution:
Not good for animations, interpolation between link rotations and overall limb movement is not smooth.
that each link should rotate then applying those amounts to each link's rotation (angle):
Given this approach, here are two important formulas that will be of use:
Torque = R*F
- R: (Scalar value. Units: m) The distance from the axis of rotation to the point at which a force is applied.
- F: (Scalar value. Units: kg*m/s^2 or N) The force applied.
- Torque is directly proportional to rotational acceleration.
Dot product formula (And variations)
cos(angle) = (v1.v2)/(|v1|*|v2|)
angle = acos( (v1.v2)/(|v1|*|v2|) )
- angle: The angle between the two vectors v1 and v2 in radians. This value is always positive.
- v1: vector#1
- v2: vector#2
- |v1|: length of vector#1
- |v2|: length of vector#2
- (v1.v2): (v1.X*v2.X+v1.Y*v2.Y)
1) How to move the links (and thus the limb) to achieve IK?
- 1. Determine a vector from the end of each link to the target-position.
- 2. Calculate the dot product between that vector and the right angle (orientation) vector.
- 3. Multiply it by a small value, to map the dot product (above) to an acceptably small angle value, which I'll call 'angle_change'.
- 4. Determine which way to rotate the link, CW or CCW, and change the sign of the angle if CW to negative.
- 5. Add the angle_change to the current angle of the link.
2) How to constrain the rotation of links, such that the limb moves smoothly (without jerking or snapping)?
3) How to constrain the rotation of links, such that it only uses one configuration for reaching or trying to reach the target-position?