Motion task

NAOqi Motion - Overview | API


What it does

In ALMotion, every time you call an API to request a motion, a “motion task” is created to handle the job. At each ALMotion cycle, the task will compute the elementary commands (changes in motor angles and stiffnesses) to perform the motion.

Examples of motion tasks include the walk, the fall manager, the joint-space interpolator.

How it works

Several motion tasks can coexist. For instance, a task may handle the walk while another controls the arms motion. To prevent several concurrent tasks from sending inconsistent motion commands to the same motors, the tasks are required to declare and book the resources they will control, such as a motor angle or stiffness.

If some resources needed for its execution are unavailable, the task manager will refuse to start a task. It is however possible to free the resources by killing the tasks that are using them.

Note

The resources mentioned here are for ALMotion use only and are different from the ones that are used in Choregraphe and managed by ALResourceManager.

Use Cases

Case 1: Resource unavailable: tasks get postponed

In the following example, two motions tasks attempt to control the same joint. As the corresponding resource is owned by the first task, the second one is postponed until the resource is freed.

almotion_taskManagement1.py

# -*- encoding: UTF-8 -*-

'''Task management: the second motion is postponed'''

import argparse
import math
import time
from naoqi import ALProxy

def main(robotIP, PORT=9559):

    motionProxy = ALProxy("ALMotion", robotIP, PORT)

    # Wake up robot
    motionProxy.wakeUp()

    # go to an init head pose.
    names  = ["HeadYaw", "HeadPitch"]
    angles = [0.0, 0.0]
    times  = [1.0, 1.0]
    isAbsolute = True
    motionProxy.angleInterpolation(names, angles, times, isAbsolute)

    # move slowly the head to look in the left direction. The motion will
    # take 4 seconds
    names  = "HeadYaw"
    angles = math.pi/2.0
    times  = 4.0
    isAbsolute = True
    motionProxy.post.angleInterpolation(names, angles, times, isAbsolute)

    time.sleep(1.0)

    # one second after having started motion1, check the resources use.
    # As expected the "HeadYaw" resource is busy
    isAvailable = motionProxy.areResourcesAvailable([names])
    print("areResourcesAvailable({0}): {1}".format([names], isAvailable))

    time.sleep(1.0)

    # try to look in the right direction. As the "HeadYaw" joint is busy,
    # this motion is postponed until the resource is freed
    angles = -math.pi/2.0
    times  = 2.0
    isAbsolute = True
    motionProxy.post.angleInterpolation(names, angles, times, isAbsolute)

    time.sleep(3.0)
    # 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)

Case 2: Moving a joint without delay

In this example, motions are required using the setAngles method, which does not lock the resource. The target can be changed without delay.

almotion_taskManagement2.py

# -*- encoding: UTF-8 -*-

''' Task management: the second motion is not postponed '''

import argparse
import math
import time
from naoqi import ALProxy

def main(robotIP, PORT=9559):

    motionProxy = ALProxy("ALMotion", robotIP, PORT)

    # Wake up robot
    motionProxy.wakeUp()

    # go to an init head pose.
    names  = ["HeadYaw", "HeadPitch"]
    angles = [0., 0.]
    times  = [1.0, 1.0]
    isAbsolute = True
    motionProxy.angleInterpolation(names, angles, times, isAbsolute)

    # move slowly the head to look in the left direction
    names  = "HeadYaw"
    angles = math.pi/2
    fractionMaxSpeed = .1
    motionProxy.setAngles(names, angles, fractionMaxSpeed)

    time.sleep(1.)

    # while the previous motion is still running, update the angle
    angles  = -math.pi/6
    fractionMaxSpeed  = 1.
    motionProxy.setAngles(names, angles, fractionMaxSpeed)

    time.sleep(2.0)
    # 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)