Working with inverse kinematics

Flash Player 10 and later, Adobe AIR 1.5 and later, requires Flash CS4 or later

Inverse kinematics (IK) is a great technique for creating realistic motion.

IK lets you create coordinated movements within a chain of connected parts called an IK armature, so that the parts move together in a lifelike way. The parts of the armature are its bones and joints. Given the end point of the armature, IK calculates the angles for the joints that are required to reach that end point.

Calculating those angles manually yourself would be challenging. The beauty of this feature is that you can create armatures interactively using Adobe® Flash® Professional. Then animate them using ActionScript. The IK engine included with Flash Professional performs the calculations to describe the movement of the armature. You can limit the movement to certain parameters in your ActionScript code.

New to the Flash Professional CS5 version of IK is the concept of bone spring, typically associated with high-end animation applications. Used with the new dynamic Physics Engine, this feature lets you configure life-like movement. And, this effect is visible both at runtime and during authoring.

To create inverse kinematics armatures, you must have a license for Flash Professional.

Basics of Inverse Kinematics

Inverse kinematics (IK) lets you create life-like animation by linking parts so they move in relation to one another in a realistic manner.

For example, using IK you can move a leg to a certain position by articulating the movements of the joints in the leg required to achieve the desired pose. IK uses a framework of bones chained together in a structure called an IK armature. The fl.ik package helps you create animations resembling natural motion. It lets you animate multiple IK armatures seamlessly without having to know a lot about the physics behind the IK algorithms.

Create the IK armature with its ancillary bones and joints with Flash Professional. Then you can access the IK classes to animate them at runtime.

See the Using inverse kinematics section in Using Flash Professional for detailed instructions on how to create an IK armature.

Important concepts and terms

The following reference list contains important terms that are relevant to this feature:

Armature
A kinematic chain, consisting of bones and joints, used in computer animation to simulate realistic motion.

Bone
A rigid segment in an armature, analogous to a bone in an animal skeleton.

Inverse Kinematics (IK)
Process of determining the parameters of a jointed flexible object called a kinematic chain or armature.

Joint
The location at which two bones make contact, constructed to enable movement of the bones; analogous to a joint in an animal.

Physics Engine
A package of physics-related algorithms used to provide life-like actions to animation.

Spring
The quality of a bone that moves and reacts when the parent bone is moved and then incrementally diminishes over time.

Animating IK Armatures Overview

After creating an IK armature in Flash Professional, use the fl.ik classes to limit its movement, track its events, and animate it at runtime.

The following figure shows a movie clip named Wheel. The axle is an instance of an IKArmature named Axle. The IKMover class moves the armature in synchronization with the rotation of wheel. The IKBone, ikBone2, in the armature is attached to the wheel at its tail joint.

A.
Wheel

B.
Axle

C.
ikBone2

At runtime, the wheel spins in association with the __motion_Wheel motion tween discussed in Describing the animation. An IKMover object initiates and controls the movement of the axle. The following figure shows two snapshots of the axle armature attached to the spinning wheel at different frames in the rotation.

Moving IK armature in two different positions
At runtime, the following ActionScript:
  • Gets information about the armature and its components

  • Instantiates an IKMover object

  • Moves the axle in conjunction with the rotation of the wheel

import fl.ik.* 
 
var tree:IKArmature = IKManager.getArmatureByName("Axle"); 
var bone:IKBone = tree.getBoneByName("ikBone2"); 
var endEffector:IKJoint = bone.tailJoint; 
var pos:Point = endEffector.position; 
 
var ik:IKMover = new IKMover(endEffector, pos); 
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 
 
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); 
 
function frameFunc(event:Event) 
{ 
    if (Wheel != null) 
    { 
        var mat:Matrix = Wheel.transform.matrix; 
        var pt = new Point(90, 0); 
        pt = mat.transformPoint(pt); 
         
        ik.moveTo(pt); 
    } 
}

The IK classes used to move the axle are:

  • IKArmature: describes the armature, a tree structure consisting of bones and joints; must be created with Flash Professional

  • IKManager: container class for all the IK armatures in the document; must be created with Flash Professional

  • IKBone: a segment of an IK armature

  • IKJoint: a connection between two IK bones

  • IKMover: initiates and controls IK movement of armatures

For complete and detailed descriptions of these classes, see the ik package.

Getting information about an IK armature

First, declare variables for the armature, the bone, and the joint that make up the parts that you want to move.

The following code uses the getArmatureByName() method of the IKManager class to assign the value of the Axle armature to the IKArmature variable tree. The Axle armature was previously created with Flash Professional.

var tree:IKArmature = IKManager.getArmatureByName("Axle");

Similarly, the following code uses the getBoneByName() method of the IKArmature class to assign to the IKBone variable the value of the ikBone2 bone.

var bone:IKBone = tree.getBoneByName("ikBone2");

The tail joint of the ikBone2 bone is the part of the armature that attaches to the spinning wheel.

The following line declares the variable endEffector and assigns to it the tailjoint property of the ikBone2 bone:

var endEffector:IKJoint = home.tailjoint;
The variable pos is a point that stores the current position of the endEffector joint.
var pos:Point = endEffector.position;

In this example, pos is the position of the joint at the end of the axle where it connects to the wheel. The original value of this variable is obtained from the position property of the IKJoint.

Instantiating an IK Mover and Limiting Its Movement

An instance of the IKMover class moves the axle.

The following line instantiates the IKMover object ik, passing to its constructor the element to move and the starting point for the movement:
var ik:IKMover = new IKMover(endEffector, pos);

The properties of the IKMover class let you limit the movement of an armature. You can limit movement based on the distance, iterations, and time of the movement.

The following pairs of properties enforce these limits. The pairs consist of a Boolean value that indicates whether the movement is limited and an integer that specifies the limit:

Boolean property

Integer property

Limit set

limitByDistance:Boolean

distanceLimit:int

Sets the maximum distance in pixels that the IK engine moves for each iteration.

limitByIteration:Boolean

iterationLimit:int

Sets the maximum number of iterations the IK engine performs for each movement.

limitByTime:Boolean

timeLimit:int

Sets the maximum time in milliseconds allotted to the IK engine to perform the movement.

By default, all the Boolean values are set to false, so movement is not limited unless you explicitly set a Boolean value to true. To enforce a limit, set the appropriate property to true and then specify a value for the corresponding integer property. If you set the limit to a value without setting its corresponding Boolean property, the limit is ignored. In this case, the IK engine continues to move the object until another limit or the target position of the IKMover is reached.

In the following example, the maximum distance of the armature movement is set to 0.1 pixels per iteration. The maximum number of iterations for every movement is set to ten.
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 

Moving an IK Armature

The IKMover moves the axle inside the event listener for the wheel. On each enterFrame event of the wheel, a new target position for the armature is calculated. Using its moveTo() method, the IKMover moves the tail joint to its target position or as far as it can within the constraints set by its limitByDistance, limitByIteration, and limitByTime properties.
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); 
 
function frameFunc(event:Event) 
{ 
    if (Wheel != null) 
    { 
        var mat:Matrix = Wheel.transform.matrix; 
        var pt = new Point(90,0); 
        pt = mat.transformPoint(pt); 
         
        ik.moveTo(pt); 
    } 
} 

Using Springs

Inverse kinematics in Flash Professional CS5 supports bone spring. Bone spring can be set during authoring, and bone spring attributes can be added or modified at runtime. Spring is a property of a bone and its joints. It has two attributes: IKJoint.springStrength, which sets the amount of spring, and IKJoint.springDamping, which adds resistance to the strength value and changes the rate of decay of the spring.

Spring strength is a percent value from the default 0 (completely rigid) to 100 (very loose and controlled by physics). Bones with spring react to the movement of their joint. If no other translation (rotation, x, or y) is enabled, the spring settings have no effect.

Spring damping is a percent value from the default 0 (no resistance) to 100 (heavily damped). Damping changes the amount of time between a bone’s initial movement and its return to a rest position.

You can check to see if springs are enabled for an IKArmature object by checking its IKArmature.springsEnabled property. The other spring properties and methods belong to individual IKJoint objects. A joint can be enabled for angular rotation and translation along the x- and y-axes. You can position a rotational joint’s spring angle with IKJoint.setSpringAngle and a translational joint’s spring position with IKJoint.setSpringPt.

This example selects a bone by name and identifies its tailJoint. The code tests the parent armature to see if springs are enabled and then sets spring properties for the joint.

var arm:IKArmature = IKManager.getArmatureAt(0); 
var bone:IKBone = arm.getBoneByName("c"); 
var joint:IKJoint = bone.tailJoint; 
if (arm.springsEnabled) { 
    joint.springStrength = 50; //medium spring strength 
    joint.springDamping = 10; //light damping resistance 
    if (joint.hasSpringAngle) { 
        joint.setSpringAngle(30); //set angle for rotational spring 
    } 
}

Using IK Events

The IKEvent class lets you create an event object that contains information about IK Events. IKEvent information describes motion that has terminated because the specified time, distance, or iteration limit was exceeded.

The following code shows an event listener and handler for tracking time limit events. This event handler reports on the time, distance, iteration count, and joint properties of an event that fires when the time limit of the IKMover is exceeded.

var ikmover:IKMover = new IKMover(endjoint, pos); 
ikMover.limitByTime = true; 
ikMover.timeLimit = 1000; 
 
ikmover.addEventListener(IKEvent.TIME_LIMIT, timeLimitFunction); 
 
function timeLimitFunction(evt:IKEvent):void 
{ 
    trace("timeLimit hit"); 
    trace("time is " + evt.time); 
    trace("distance is " + evt.distance); 
    trace("iterationCount is " + evt.iterationCount); 
    trace("IKJoint is " + evt.joint.name); 
}