Joints
Each joint can be controlled individually, or in parallel with other joints.
Chain and Joint Names
Head | LArm | LLeg | RLeg | RArm |
---|---|---|---|---|
HeadYaw | LShoulderPitch | LHipYawPitch1 | RHipYawPitch1 | RShoulderPitch |
HeadPitch | LShoulderRoll | LHipRoll | RHipRoll | RShoulderRoll |
LElbowYaw | LHipPitch | RHipPitch | RElbowYaw | |
LElbowRoll | LKneePitch | RKneePitch | RElbowRoll | |
LWristYaw2 | LAnklePitch | RAnklePitch | RWristYaw2 | |
LHand2 | RAnkleRoll | LAnkleRoll | RHand2 |
1 LHipYawPitch and RHipYawPitch share the same motor, with LHipYawPitch always taking priority.
2 These joints do not exist in the "RoboCup" version
Programmatic access to Joint Names
Programmatically, you can get the joint names for the body or a chain, using the getJointNames method.
# Example showing how to get joint names > print proxy.getJointNames("Body") ['HeadYaw', 'HeadPitch', 'LShoulderPitch', 'LShoulderRoll', 'LElbowYaw', 'LElbowRoll', 'LHipYawPitch', 'LHipRoll', 'LHipPitch', 'LKneePitch', 'LAnklePitch', 'LAnkleRoll', 'RHipYawPitch', 'RHipRoll', 'RHipPitch', 'RKneePitch', 'RAnklePitch', 'RAnkleRoll', 'RShoulderPitch', 'RShoulderRoll', 'RElbowYaw', 'RElbowRoll'] > print proxy.getJointNames("LArm") ['LShoulderPitch', 'LShoulderRoll', 'LElbowYaw', 'LElbowRoll']
Controlling Joints
To control a joint, you need to specify the name of the joint, the target angle in radians, and how fast you want to go to the target angle.
# Simple command for the HeadYaw joint at 10% max speed names = "HeadYaw" angles = 0.2 fractionMaxSpeed = 0.1 proxy.setAngles(names,angles,fractionMaxSpeed)
Reactive Control
The commands setAngles and changeAngles, do not block the calling thread. This makes them ideal for being called often in reactive control loops, such as head tracking. You can call them often, with contradictory commands, and motion will ensure that the trajectory is smooth in position and continuous in velocity.
# Example simulating reactive control names = "HeadYaw" angles = 0.3 fractionMaxSpeed = 0.1 proxy.setAngles(names,angles,fractionMaxSpeed) # wait half a second time.sleep(0.5) # change target angles = 0.0 proxy.setAngles(names,angles,fractionMaxSpeed) # wait half a second time.sleep(0.5) # change target angles = 0.1 proxy.setAngles(names,angles,fractionMaxSpeed)
Timed Interpolations
When you know in advance the trajectory that you want to follow, the angleInterpolation and angleInterpolationWithSpeed methods can be used to set up an interpolation.
# Example showing a joint trajectory with a single destination names = "HeadYaw" angleLists = 1.0 times = 1.0 isAbsolute = True proxy.angleInterpolation(names, angleLists, times, isAbsolute)
You can command multiple joints in one command, by using a single time, and a number of target angles equal to the number of joints
# Example showing a command for the two joints in the 'Head' alias # 'Head' is expanded to ['HeadYaw','HeadPitch'] names = "Head" angleLists = [-1.0,-1.0] times = 1.0 isAbsolute = True proxy.angleInterpolation(names, angleLists, times, isAbsolute)
The same command can take a list of angles with corresponding times
# Shake the head from side to side names = "HeadYaw" angleLists = [1.0, -1.0, 1.0, -1.0, 0.0] times = [1.0, 2.0, 3.0, 4.0, 5.0] isAbsolute = True proxy.angleInterpolation(names, angleLists, times, isAbsolute)
Similarly, trajectories can be specified for multiple joints
# Two trajectories in one command. Each trajectory must have a # corresponding number of times names = ["HeadYaw", "HeadPitch"] angleLists = [[1.0, -1.0, 1.0, -1.0], [-1.0]] times = [[1.0, 2.0, 3.0, 4.0], [ 5.0]] isAbsolute = True proxy.angleInterpolation(names, angleLists, times, isAbsolute)
Init Pose
This example shows how to place NAO in an init pose. By changing the parameters for kneeAngle, torsoAngle and wideAngle, you can make a variety of stable poses.
# Example showing how to create an init pose import math TO_RAD = math.pi/180 # Feel free to experiment with these values kneeAngle = 40 torsoAngle = 0 wideAngle = 0 #----------------------------- prepare the angles ---------------------------- # Get the Number of Joints NumJoints = len(proxy.getJointNames("Body")) # Define The Initial Position Head = [0, 0] LeftArm = [120, 15, -90, -80] LeftLeg = [0, wideAngle, -kneeAngle/2-torsoAngle, kneeAngle, -kneeAngle/2, -wideAngle] RightLeg = [0, -wideAngle, -kneeAngle/2-torsoAngle, kneeAngle, -kneeAngle/2, wideAngle] RightArm = [120, -15, 90, 80] # If we have hands, we need to add angles for wrist and hand if (NumJoints == 26): LeftArm += [0, 0] RightArm += [0, 0] # Gather the joints together pTargetAngles = Head + LeftArm + LeftLeg + RightLeg + RightArm # Convert to radians pTargetAngles = [ x * TO_RAD for x in pTargetAngles] #------------------------------ send the commands ----------------------------- # Display the starting position print proxy.getSummary() # We use the "Body" name to signify the collection of all joints pNames = "Body" # We set the fraction of max speed pMaxSpeedFraction = 0.2 # Ask motion to do this with a blocking call proxy.angleInterpolationWithSpeed(pNames, pTargetAngles, pMaxSpeedFraction) # Display the end position print proxy.getSummary()