CS56 Computer Animation: Lab 9

In which, we use inverse kinematics to animate our characters

The goal of this lab is to


Get the source


This assignment has been added to your AnimationFramework repository. To get the source, run

> cd cs56/AnimationToolkit 
> git pull
> cd build
> cmake ..
> make

You should now have a new directory under assignments called a9-ik.


Assignment 9: Reach for your goals

Due December 4




Question 1: Practice two-link chain analytical method (15 points)


In this question, you will work through the calculations needed to perform IK for a two-link chain on paper. Include your answers in your readme for this week. Remember that you can use python, octave, matlab, maple, our basecode or any other method to check your answers!

Suppose we have a 2-link chain as in class.



The root joint p1 is located at the origin.

The next joint p2 is offset from p1 by (2,0,0)T

The next joint p3 is offset from p2 by (5,0,0)T

Solve using the analytic two-link method (Reference: here)

  • Suppose we wish to position p3 at a target position pd = (-4,3,0)T. Let's use the analytic IK method for class to compute rotations for p1 and p2 such that p3 is located at pd.
    1. (1 point) What is the desired distance r between p3 and p1?
    2. (1 point) What is L1?
    3. (1 point) What is L2?
    4. (2 points)What is the angle \( \theta_{2z}\) that achieves the desired length?
    5. (1 points)What is the new global position of joint 3? Verify that setting the rotation of joint 1 to \(\theta_{2z} \) results in the desired distance.

    Using polar coordinates to compute the orientation of joint 1:

    1. (1 points) What is the angle \( \theta_{1z}\) that points the limb along the x axis?
    2. (1 points) What is the new global position of joint 3? Verify that setting \( \theta_{2z} \) and \( \theta_{1z} \) points the limb along the x axis using the kinematic equation for our joints.
    3. (1 points) Compute the heading (beta) and elevation (gamma) that point the limb towards the target \( p_d \).
    4. (1 points)Plug in beta, gamma, \( \theta_{1z} \), and \( \theta_{2z} \) and verify that \( p_3 \) is now at location \( p_d \).

    Using angle/axis to compute the orientation of joint 1:

    1. (1 points)After setting the length, what is the global position of joint 3?
    2. (1 points)What is the direction vector r?
    3. (1 points)What is the error vector e?
    4. (1 points)What is the angle phi and axis of rotation?
    5. (1 points)Plugin in the angle/axis rotation and \(\theta_{2z} \) and verify that \( p_3 \) is now at location \( p_d \)


    Question 2: Implement two-link analytic method from class (5 points)


    In this question, you will implement the analytic IK algorithm from class. Put your work in libsrc/animation/AIKController-basecode.cpp inside the method solveIKTwoLink.

    // ASkeleton will contain a two-link chain
    // Assume joint 0 is the root
    // Assume joint 1 is the middle joint
    // Assume joint 2 is the end effector
    // If your implementation is correct, the end effector should be positioned at goalPos
    bool AIKController::solveIKTwoLink(ASkeleton& skeleton, const AVector3& goalPos) 
    

    To run the demo from the build directory, type

    build> ../bin/a9-iksimple 
    


    Implementation tips:

  • DON'T FORGET: When you change the local rotation of a joint, you must call fk() to update the global rotations and translations.
  • When implementing IKSimple::updateIK(), it is best to approach the task systematically. I strongly recommend the following approach


    The basecode includes a simple interface and 3D viewer. See above for a demo.

    The camera can be controled with the mouse:

    The player control panel on the top left can be used to play/pause, step through keys, and see the simulation time.

    The panel at the bottom left can be used to set the goal position of the end effector. The target position can also be moved with the mouse by holding down the Ctrl key.


    Question 3: Eye on the prize (5 points)


    In this question, you will use the CCD's angle/axis computation (with nudge factor of 1) to make a character's gaze follow a target. Implement your solution in assignments/a9-ik/ALooker.cpp

    Your approach should align the forward direction of the head with the target. The forward direction of the head is the Z axis (0,0,1) in its local coordinates.



    To run the demo from the build directory, type

    build> ../bin/a9-looker
    



    Question 4: Character IK using CCD (10 points)


    In this question, you will implement the CCD algorithm for a full character. Implement you solution in IKController::solveIKCCD() located in libsrc/animation/AIKcontroller-basecode.cpp. Given the joint specified by jointid, make its position match goalPos. The chainsize indicates how many descendents to use for the CCD algorithm. When the function returns, skeleton's pose will have the end effector matching the goalPos (as close as feasible).

    // solveIKCCD positions the joint given by jointid so its global position
    // is located at goalPos
    //
    // param skeleton: the character to modify
    // param jointid: the ID of the end effector
    // param goalPos: the target position for jointid (global pos)
    // param chainSize: the number of joints to "nudge" towards the goal. (e.g. the number of descendants to use)
    // param maxIters: the max number of iterations to try to reach the goal
    // 
    // return true/false based on whether we could reach the goal
    // side effect: skeleton should by posed such that jointid is located at goalPos (or in this direction of 
    // goalPos if the target is out of reach) 
    bool AIKController::solveIKCCD(ASkeleton& skeleton, int jointid,
        const AVector3& goalPos, int chainSize, int maxIters)
    {
        // recompute the chain if the end effector or chain size changes
        if (_selectedJoint != jointid || chainSize != (int) _chain.size())
        {
            computeJointChain(skeleton, jointid, chainSize);
        }
    
        // There are no joints in the IK chain for manipulation
        if (_chain.size() == 0) return true;
    
        // implement CCD algorithm here
    
        return false;
    }
    

    To run the demo from the build directory, type

    build> ../bin/a9-ik 
    


    Implementation Hints

    The basecode comes with a viewer to help yo utest your algorithm.


    User interface overview

    The camera can be controled with the mouse:

    The left frame lets you select joints, reset the pose, and set the goal position maunally.

    The target position can also be moved with the mouse by holding down the Ctrl key.

    The right panel lets you select the algorithm for IK along with IK paramaters. For CCD:


    Question 5: Character IK using analytical method (10 points)


    In this question, implement IKController::solveIKAnalytic() located in libsrc/animation/AIKcontroller-basecode.cpp. In this question, you will combine the techniques of the simple two-link analytic approach with CCD's angle/axis calculation. This work will allow us to animate the legs and arms of the character such that the knees and elbows bend along their natural axis.

    // solveIKAnalytic: positions the joint given by jointid so its global position
    // is located at goalPos. This method computes rotations for the parent and grandparent 
    // of jointid.
    //
    // param skeleton: the character to modify
    // param jointid: the ID of the end effector
    // param goalPos: the target position for jointid (global pos)
    // 
    // return true/false based on whether we could reach the goal
    // side effect: skeleton should by posed such that jointid is located at goalPos (or in this direction of 
    // goalPos if the target is out of reach) 
    bool AIKController::solveIKAnalytic(ASkeleton& skeleton, int jointid, const AVector3& goalPos)
    

    To run the demo from the build directory, type

    build> ../bin/a9-ik 
    
    Set the IK type to Analytic to test your work.


    Implementation hints:


    Question 6: Rythym is a dancer (10 points)


    In this question, you will implement a procedural dancer using solveIKAnalytic (or solveIKCCD if you did not finish the previous question). Implement your solution in assignments/a9-ik/ADancer.cpp. Your solution will modify the motion in idle.bvh to make the hands and hips move differently.



    To run the demo from the build directory, type

    build> ../bin/a9-dancer
    


    Demo requirements

    Suggested approach

    1. Animate the hand targets first.
    2. Then use AIKController to position the hands so that they follow the targets
    3. Then animate the position of the hips
    4. Then pin the feet to their original position using AIKController
    5. Then reset the rotation of the feet to their original global rotation

    Extra Credit


    Option 1 Make you own unique animation based on inverse kinematics, splines, and motions. For example, make a new dance, have the character hold a cup, or wave. Try your procedural dance or look on an other motions.

    Option 2 Procedural walker. Animate walking by using IK to move the feet (to move forward, you will need to move the root too). Experiment with unique characters, such as spiders and robots.

    Be sure to include a video of your demo for full credit!


    Submission Requirements (1 points)