Herman.Bruyninckx[at]mech.kuleuven.ac.be, 20 SEP 2004
This chapter will guide you through the process of animating a robot, i.e., a device with rigid links and (mostly) revolute joints, driven by motors on each joint. In order to simulate a robot in Blender, one must first “rig” it (i.e., give it a skeleton (“armature”) of bones and joints), and then animate that armature (i.e., provide functions that move the bones).
We assume that you have read the Interface Chapter and the Quickstart Chapter, and that you understand the conventions used throughout this book.
Relevant to Blender v2.31
In order to be able to animate a robot model, you must know the lengths of the bones (or, equivalently, the distances between the axes of all joints in the model) as well as the rotation or translation axes of the joints. And you have to add Empties (i.e., rigid references on specific parts of the bones) that you can “grab” later on to position these specific parts of the armature.
First we'll reposition the object center. We will put the object center in middle of the ground plane of the base. Switch to Object Mode and select the vertices on the ground plane of the base. Press SHIFT-S and select Cursor to Selection from the pop-up menu (Figure 1-1). Your cursor will now be in the center of the ground plane of the base. This works if you select points that are positioned symmetrically with relation to the ground plane center. Now go to Object Mode by pressing TAB and press the Centre Cursor button in the Mesh panel (Figure 1-2). The object center has now moved to the cursor.
Now put your cursor in the origin of the coordinate system. You can do this by putting the cursor on the origin in two orthogonal views: press NUM1, NUM3 or NUM7 to switch to orthogonal views and click the origin with LMB in at least two views. Now your cursor is approximately in the origin. Press SHIFT-S and select Cursor to Grid from the pop-up menu. Now your cursor is in the origin. Select you robot model with RMB and press SHIFT-S and select Selection to Cursor from the pop-up menu (Figure 1-3). Your model's object center is now in the coordinate system origin. You may still want to rotate your model to align it with the correct axes. Press RKEY to rotate and then XKEY, YKEY or ZKEY to rotate around the x, y or z axis. You can also enter a numeric value and confirm with ENTER.
We will now add an Armature and Bones. But first, we'll add Empties. Empties are just empty objects, but can be useful to position the cursor precisely. If your cursor is not in the object center anymore, select your model in Object Mode, press SHIFT-S and select Cursor to Selection. Repeat the following twice: Press SPACE and select Add and then Empty from the pop-up menu. When you're done, switch to an appropriate view with NUM1, NUM3 or NUM7. We'll move the second Empty to the rotational center of the first degree of freedom. Actually you can put the Empty anywhere on the rotation axis of the first degree of freedom, but we will put it in the middle of the robot on the axis. The second Empty is still selected, so press GKEY to move it and enter the appropriate vector to move the Empty to the rotational center of the first DOF (Figure 1-4). Press SHIFT-S and select Cursor to Selection to move the cursor to the new location of the Empty. Add a new Empty and move it the rotational center of the second DOF. Repeat this procedure for all DOF's and perhaps you can add an extra Empty for the end-effector-bone as well (Figure 1-4).
Select the first Empty that you created and press SHIFT-S and select Cursor to Selection. Our cursor is now in the origin. Now press SPACE and select Add and then Armature. Place second endpoint of the first Bone near the second Empty that you created and press ESC after you placed the first Bone. Press TAB to go to Object Mode (you were editing the Armature). We will now precisely position the end-point of the second bone. First we'll move the cursor to the correct location. Select the second Empty, press SHIFT-S and select Cursor to Selection. Now we will move the endpoint of the first bone to the correct location. Select the Armature and switch to Edit Mode. Select the endpoint of the Bone press SHIFT-S and select Selection to Cursor (Figure 1-6). Good. The first bone is now in place. Let's add a second bone. Now press SPACE and select Add and then Bones. Position the endpoint of the second Bone near the third Empty and repeat the above procedure for all bones. You may also wish to add a Bone for the end-effector. Notice that we added a bone for the base too.
![]() | It's probably wise to add all your Bones in the same view (NUM1, NUM3 or NUM7), otherwise the local axes of the Bones may not be consistently defined. This is important! It doesn't matter that your Bones are outside of the members. But it is necessary that one of the local axes of the Bones is the same as the rotation axis in the first point of the Bone. It is not necessary that all your Bones are connected! Although this is the case for our model (Figure 1-7). |
Now we need to connect our Mesh to our Armature. Select the robot model in Object Mode and select the Armature with SHIFT-RMB. The model will be magenta and the Armature will be light pink (Figure 1-8). Then press CTRL-P, select Use Armature from the pop-up menu and then Don't Create Groups. We will manually create vertex groups and give them the same names as the bones.
Now we will name our bones. Select the Armature and switch to Edit Mode. Select a bone by selecting both ends with SHIFT-RMB. When a Bone is selected, you will be able to see and edit some options in the Armature Bones panel. Give each bone an appropriate name, and select the appropriate parent (Figure 1-10). We'll name our base bone q0, the member1 bone q1 etc. q0 is the parent of q1. When a parent bone moves, all it children will move along as if they are all rigidly connected to the parent bone.
Now we need to define vertex groups with the same names as the bones in order to connect them. Select the robot model and switch to Edit Mode. Create new vertex groups q0, q1, q2 etc. and assign the vertices (or vertex groups) that should move along with bone q0, q1, q2 etc. We originally made vertex groups for all our parts of the model. You can quickly select all the appropriate vertices by selecting the vertex groups of the composing parts. If the vertex groups q0, q1 etc. only include the members of the robot, we could simply rename the old vertex groups. But sometimes one member consists of multiple parts and so we can select the member vertex group and the vertex groups for the other parts (e.g. a motor) and group it into a vertex group e.g. q1.
![]() | We do not need the Empties anymore. You can delete them if you want to, or move them to another layer. |
Relevant to Blender v2.31
Once you have a rigged and skinned robot model, you can start moving it manually: moving the bones and viewing the results.
1. Select the armature only, then select Pose Mode from the "Mode" Menu (Figure 1-11). This option only appears if an armature is selected.
2. The armature will turn blue. You are in Pose Mode. If you now select a bone it will turn cyan, not pink, and if you move it (GKEY), or rotate it (RKEY), the body will deform!
![]() | Original position |
|---|---|
Blender remembers the original position of the bones. You can set your armature back by pressing the Rest Pos button in the Armature Edit Buttons (Figure 1-13). |
![]() | Forward and Inverse Kinematics |
|---|---|
While handling bones in pose mode you will notice that they act as rigid, inextensible bodies with spherical joints at the end. You can actually grab only the first bone of a chain and all the other will follow it. All subsequent bones in the chain cannot be grabbed and moved, you can only rotate them, so that the selected bone rotates with respect to the previous bone in the chain while all the subsequent bones of the chain follow its rotation. This procedure, called Forward Kinematics (FK) is easy to follow, but it makes precise location of the last bone of the chain difficult. We can use another method, Inverse Kinematics (IK) where you actually define the position of the last bone in the chain, and all the other assume a position, automatically computed by Blender, to keep the chain without gaps. Hence precise positioning of hands and feet is much easier. |
Now we'll create a simple animation.
1. First, verify that you are at frame 1 of the timeline. The frame number appears in a NumButton on the right of the Buttons Window Toolbar (Figure 1-14). If it is not set to 1, set it to 1 now.
2. First, select all bones with AKEY in Pose Mode. Now, press IKEY and select LocRot (Figure 1-15) to insert a keyframe at frame 1.
3. Now go to frame 25 by entering the number in the NumButton or by pressing UPARROW. Select one of the bones in Pose Mode and rotate it around its rotation axis by pressing RKEY and XKEY, YKEY or ZKEY for rotating it around the x, y or z axis (Figure 1-16). Then press AKEY twice to select all bones. We'll insert a keyframe here as well. Press IKEY and select LocRot from the pop-up menu. This will get the position and orientation of all bones and store it in a pose at frame 25.
4. Now move back to frame 1. You'll notice that our robot moves! If you are on frame 1, press ALT-A to automatically changes frames (press ESC to stop). We can't render anything just yet because our camera and lamps are not in place (or we deleted them). You can add other keyframes and define further rotations to see more action.
![]() | Checking the animation |
|---|---|
To preview your Animation, set the current frame to 1 and press ALT-A in the 3D window. |
Relevant to Blender v2.31
Remember that we had a lamp and a camera and moved it to layer 10? If you deleted them, you can add them back in object mode by pressing SPACE and select Add and Camera or Lamp. If you moved them to layer 10, click on layer 10 with SHIFT-LMB (Figure 1-17) in the layer visibility controls. If the cube is now visible as well, you can safely delete it now. Select it in Object Mode with RMB and press XKEY to remove the cube (and confirm when you see a pop-up menu).
Switch to an appropriate view (e.g. NUM1) and select the camera. Press GKEY to move it to an appropriate position. Instead of moving it relatively, you can also enter absolute coordinates. If you press NKEY, a small window will pop-up. You can change the absolute coordinates (LocX, LocY, LocZ) by clicking the left or right arrow buttons or by clicking on the coordinate with SHIFT-LMB and entering a number (Figure 1-17). You can close the window by click on the left X button. Do the same for the lamp.
Now we'll make the camera track the robot. Select the camera and select the robot model with SHIFT-RMB and press CTRL-T and select Old Track from the pop-up menu (Figure 1-19). Next, select only the camera and press ALT-R to remove any object rotation (Figure 1-20). Pressing NUM0 switches to camera view. Your model should be visible (Figure 1-21).
![]() | If your model is not visible, it's possible that it's still to large for the Blender coordinate system. If this is the case, you can scale it down some more. |
Now make the lamp track the robot model as well, by following the same procedure as above. When you're done, select the lamp and press the Shading button or F5. Make the lamp a Hemi with an energy of 0.6 (Figure 1-22).
We're ready to render the animation now. Select Render Animation from the Render menu (Figure 1-23). If all went well, you should now see your basic animation rendered.
Relevant to Blender v2.31
Now we'll use python to animate our robot model. Click on the upper right window border (Figure 1-24) with RMB and select Split Area (Figure 1-25) from the menu. You can now drag to adjust the size of the second window. Click with LMB to confirm the chosen windows size.
Click on the button in the lower left corner of the newly created area and select Text Editor (Figure 1-26).
Now download this script and open it in the text editor (Figure 1-27) or copy and paste the code below. Careful: some browsers convert tabs to spaces and the Python code will be invalid, if it was incorrectly copied. Tabs are part of the Python syntax! The code assumes that you are a bit familiar with Python and is pretty straight-forward. You shouldn't pay a lot of attention to the clearAllkeys(). The important things are happening in move(). You may need to adjust the script to your needs. If you have a robot with less than 6 DOF's, you need to change qInitial and qEnd. They should contain as many elements as the number of DOF's of your robot. Changing merely this should be enough to produce motion, however, it may be incorrect motion. The next thing you need to adapt is are the following lines:
# q1, q4 and q6 turn about the y axis of the bone if k == 0 or k == 3 or k == 5: # Get the correct rotation matrix and convert it to a quat quatData[k] = RotationMatrix(q[k], 4, 'y').toQuat() # q2, q3 and q4 turn about the z axis of the bone elif k == 1 or k == 2 or k == 4: # Get the correct rotation matrix and convert it to a quat quatData[k] = RotationMatrix(q[k], 4, 'z').toQuat()In our robot model, q1, q4 and q6 rotate about the local y axis of the bones (the axis along the length of the bones) and q2, q3 and q5 rotate about the local z axis of the bones. So, you may need to adjust the values in the comparison lines (e.g. when checking for q1, use if k == 0) and possibly adjust the 'y' or the 'z' parameter in the RotationMatrix(...) call.
# Written by Diederik Verscheure
# Script to display a basic robot motion
import Blender
from Blender import *
from Blender.Armature import *
from Blender.Armature.Bone import *
from Blender.Mathutils import *
from Blender.Window import *
def clearAllKeys():
actions = NLA.GetActions()
actionkeys = actions.keys()
for i in range(len(actionkeys)):
channels = actions[actionkeys[i]].getAllChannelIpos()
channelkeys = channels.keys()
for j in range(len(channelkeys)):
actions[actionkeys[i]].removeChannel(channelkeys[j])
def move():
# The initial angles of the DOF's of the robot
qInitial = [0, 0, 0, 0, 0, 0]
# The end angles of the DOF's of the robot
qEnd = [90, 90, -90, 90, -90, 90]
q = qInitial
# Every movement takes 40 frames
addFrames = 40
# Set current frame to 1
Blender.Set("curframe", 1)
currentFrame = 1
# Get the armatures (we have only one)
armature = Armature.Get()
# Get the bones
bones = armature[0].bones
# We have (len(qInitial) + 1) keyframes
# The first keyframe is the initial position
# In the second keyframe, q1 has turned 90 degrees about its rotion axis
# In the third keyframe, q1 is still in the previous position
# and q2 has turned 90 degrees about its rotation axis etc.
for i in range(len(qInitial)+1):
# Initialisation
quatData = range(len(qInitial))
# The first frame is the initial q
if i != 0:
q[i-1] = qEnd[i-1]
# Calculate the quats of each bone
for k in range(len(qInitial)):
# q1, q4 and q6 turn about the y axis of the bone
if k == 0 or k == 3 or k == 5:
# Get the correct rotation matrix and convert it to a quat
quatData[k] = RotationMatrix(q[k], 4, 'y').toQuat()
# q2, q3 and q4 turn about the z axis of the bone
elif k == 1 or k == 2 or k == 4:
# Get the correct rotation matrix and convert it to a quat
quatData[k] = RotationMatrix(q[k], 4, 'z').toQuat()
# Now set each bone
k = 0
for bone in bones:
# q0 and q7 are not used. q7 is the end-effector (not present) bone
# and q0 is the bone in the base of the robot
if bone.getName() != "q0" and bone.getName() != "q7":
# Set the calculated quat
bone.setQuat(quatData[k])
# Set the pose (inserts a keyframe)
bone.setPose([ROT])
k = k + 1
# Go to the next keyframe
currentFrame = currentFrame + addFrames
Blender.Set("curframe", currentFrame)
# Redraw the 3D view
Window.Redraw(Types["VIEW3D"])
def main():
print "Starting..."
# Clear all previous keyframes (NLA-editor)
clearAllKeys()
# Move the robot
move()
print "Done..."
if __name__ == "__main__":
main()
You can execute the script by pressing ALT-P, or select Run Python script from the File menu (Figure 1-27). Select Render Animation from the Render menu (Figure 1-23).