NAOqi Motion - Overview | API | Tutorial
NAO only - Do not use on Pepper
Whole Body Balancer is a powerful tool which gives a very natural and safe motion.
The main goal is to generate and stabilize consistent motions and adapt NAO’s behavior to the situation.
It is a Generalized Inverse Kinematics which deals with Cartesian and joint control, balance, redundancy and task priority.
This formulation takes into account all joints of the robot in a single problem. The motion obtained guaranties several specified conditions like balance, keeping a foot fixed ...
Moreover, when asking NAO to reach out his arm, he bends over because arms but also legs joints are taken into account. And he stops before stretching too much in order to keep his balance.
This behavior is automatically managed by Whole Body Balancer. The user only asks NAO to reach out his arm.
HipYawPitch joint coupling is implicitly taken into account in the balancer.
The Generalized Inverse Kinematics problem is written as a quadratic program which is solved every 20 ms using the C++ open source library qpOases1.
The classical form of a quadratic program is:
In our case, the unknown vector is composed of:
The equality constraints are about keeping feet fixed or in a plane.
The inequality constraints are:
Ydes is composed of:
These orders are not necessarily feasible and may even contradict. The solution obtained is feasible (it fulfills all the constraints) and is a compromise between the desired motions.
1 H.J. Ferreau, H.G. Bock and M. Diehl, ”An online active set strategy to overcome the limitation of explicit MPC,” IEEE - International Journal of Robust and Nonlinear Control, pp. 816-830, 2008.
Whole Body Balancer can be used with every joint control (angle interpolation, Choregraphe Timeline) and effector control.
There are two exceptions when Whole Body balancer can not be used:
The Whole Body Motion is by default deactivated on the robot. The following example show how to activate it.
# Example showing how to active Whole Body Balancer.
isEnabled = True
proxy.wbEnable(isEnabled)
Warning
Take care to deactivate Whole Body Balancer at the end of your behavior.
During joint control (Choregraphe Timeline for example), motion can be stabilized by Whole Body balancer. Consequently, initial motion is modified to the closest motion which respects balance and/or foot state.
Whole Body balancer has to be activated to use the following function (ALMotionProxy::wbEnable()).
This api sets the foot state:
# Example showing how to fix the feet.
stateName = "Fixed"
supportLeg = "Legs"
proxy.wbFootState(stateName, supportLeg)
# -*- encoding: UTF-8 -*-
''' Whole Body Motion: Foot State '''
''' This example is only compatible with NAO '''
import argparse
import math
from naoqi import ALProxy
def main(robotIP, PORT=9559):
''' Example of a whole body FootState
Warning: Needs a PoseInit before executing
Whole body balancer must be inactivated at the end of the script
'''
motionProxy = ALProxy("ALMotion", robotIP, PORT)
postureProxy = ALProxy("ALRobotPosture", robotIP, PORT)
# Wake up robot
motionProxy.wakeUp()
# Send robot to Stand Init
postureProxy.goToPosture("StandInit", 0.5)
# Activate Whole Body Balancer.
isEnabled = True
motionProxy.wbEnable(isEnabled)
# Legs are constrained in a plane
stateName = "Plane"
supportLeg = "Legs"
motionProxy.wbFootState(stateName, supportLeg)
# HipYawPitch angleInterpolation
# Without Whole Body balancer, foot will not be keeped plane.
names = "LHipYawPitch"
angleLists = [-45.0, 10.0, 0.0]
timeLists = [3.0, 6.0, 9.0]
isAbsolute = True
angleLists = [angle*math.pi/180.0 for angle in angleLists]
try:
motionProxy.angleInterpolation(names, angleLists, timeLists, isAbsolute)
except Exception, errorMsg:
print str(errorMsg)
print "This example is not allowed on this robot."
exit()
# Deactivate Whole Body Balancer.
isEnabled = False
motionProxy.wbEnable(isEnabled)
# Go to rest position
motionProxy.rest()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--ip", type=str, default="127.0.0.1",
help="Robot ip address")
parser.add_argument("--port", type=int, default=9559,
help="Robot port number")
args = parser.parse_args()
main(args.ip, args.port)
# Example showing how to Constraint Balance Motion.
isEnable = True
supportLeg = "Legs"
proxy.wbEnableBalanceConstraint(isEnable, supportLeg)
At least, a foot has to be constrained. The following combination are allowed:
Warning
almotion_wbEnableBalanceConstraint.py
# -*- encoding: UTF-8 -*-
''' Whole Body Motion: Enable Balance Constraint '''
''' This example is only compatible with NAO '''
import argparse
import math
from naoqi import ALProxy
def main(robotIP, PORT=9559):
''' Example of a whole body Enable Balance Constraint
Warning: Needs a PoseInit before executing
Whole body balancer must be inactivated at the end of the script
'''
motionProxy = ALProxy("ALMotion", robotIP, PORT)
postureProxy = ALProxy("ALRobotPosture", robotIP, PORT)
# Wake up robot
motionProxy.wakeUp()
# Send robot to Stand Init
postureProxy.goToPosture("StandInit", 0.5)
# Activate Whole Body Balancer
isEnabled = True
motionProxy.wbEnable(isEnabled)
# Legs are constrained in a plane
stateName = "Fixed"
supportLeg = "Legs"
motionProxy.wbFootState(stateName, supportLeg)
# Constraint Balance Motion
isEnable = True
supportLeg = "Legs"
motionProxy.wbEnableBalanceConstraint(isEnable, supportLeg)
# KneePitch angleInterpolation
# Without Whole Body balancer, foot will fall down
names = ["LKneePitch", "RKneePitch"]
angleLists = [ [0.0, 40.0*math.pi/180.0], [0.0, 40.0*math.pi/180.0]]
timeLists = [ [5.0, 10.0], [5.0, 10.0]]
isAbsolute = True
try:
motionProxy.angleInterpolation(names, angleLists, timeLists, isAbsolute)
except Exception, errorMsg:
print str(errorMsg)
print "This example is not allowed on this robot."
exit()
# Deactivate Whole Body Balancer
isEnabled = False
motionProxy.wbEnable(isEnabled)
# Go to rest position
motionProxy.rest()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--ip", type=str, default="127.0.0.1",
help="Robot ip address")
parser.add_argument("--port", type=int, default=9559,
help="Robot port number")
args = parser.parse_args()
main(args.ip, args.port)
It is a user friendly API which enables whole body Cartesian control of an effector:
It is useful for reactive behavior. User can update the target (Head Orientation, Arm Position) and motion is safe and smooth using a SE3 Interpolation.
The effector target is reached following the next conditions:
Note
Do an init posture before using this api.
First of all, choose the effector you want to control, with the api wbEnableEffectorControl. It implicitly activates Whole Body Balancer.
# Example showing how to active Head tracking.
effectorName = 'Head'
isEnabled = True
proxy.wbEnableEffectorControl(effectorName, isEnabled)
Update as you want the target with api wbSetEffectorControl:
TargetCoordinate must be absolute and expressed in FRAME_ROBOT.
If the desired position/orientation is unfeasible, target is resized to the nearest feasible motion.
# Example showing how to set orientation target for Head tracking.
effectorName = "Head"
targetCoordinate = [0.1, 0.0, 0.0]
proxy.wbSetEffectorControl(effectorName, targetCoordinate)
At last, think to disable effector control.
# Example showing how to deactivate Head tracking.
effectorName = 'Head'
isEnabled = False
proxy.wbEnableEffectorControl(effectorName, isEnabled)
Head Orientation: almotion_wbEffectorControlHead.py
Arm Position: almotion_wbEffectorControlArm.py