How to switch from NAOqi to qi Framework

Introduction

This guide will help you switch to qi Framework. It describes how to access the qi world from NAOqi and how to take advantage of qi.

qi Framework main features

The main new features of qi Framework are:

  • Support for map, list, object and structure.
  • Support for signal and property.
  • It is no longer needed to be a module to subscribe to an event.
  • Asynchronous call with result value.

Getting a Session from a proxy

This section explains how to get a qi.Session from NAOqi.

This can be used in NAOqi script or in Choregraphe behaviors.

import naoqi

#imagine you have a NAOqi proxy on almemory
mem = naoqi.ALProxy("ALMemory", "127.0.0.1", 9559)

#get a qi session
ses = mem.session()

#then you can use the session like you want

Subscribe to a memory event

When using qi, you do not have to be a module to subscribe to a memory event, you just have to specify a callback.

Warning

You have to keep the SignalSubscriber returned by ALMemory.Subscriber to keep the callback being called.

Warning

This is working only for ALMemory events and not ALMemory data.

def mycallback(value):
  print "val:", value

mem = session.service("ALMemory")
sub = mem.subscriber("event/name")
sub.signal.connect(mycallback)

If you want to have the key in your callback you can use functools.partial.

import functools

def mycallback2(key, value):
  print "key:", key
  print "val:", value

mem = session.service("ALMemory")
sub = mem.subscriber("event/name")
sub.signal.connect(functools.partial(mycallback2, "event/name"))

PCall vs qi.async

qi modules do not support pCall but they do support a more generic asynchronous mechanism qi.async(). If you want your call to be asynchronous you can use qi.async() which returns a qi.Future. This qi.Future allows you to object the resulting value or error.

However some NAOqi modules really depend on pCall. Most notably tts.say and motion.moveTo. In this case, you can use the pCall method provided by ALModule. It will behave the same as the old way and return a pcallId, usable with the stop and the wait method of ALModule.

Warning

the pCall method is only available on ALModule, not on qi services. So it’s availability depends on the service you are calling.

Let’s see an example with pCall:

tts = session.service("ALTextToSpeech")
pCallId = tts.pCall("say", "I love rock'n'pCall")
tts.stop(pcallId) #oops that was not what I meant
#let's try again
pCallId = tts.pCall("say", "I love rock'n'roll")

Now let’s imagine you want to call a function and do something when the function finishes:

tts = session.service("ALTextToSpeech")
fut = qi.async(tts.say, "I Love rock'n'sync")
#do some work here

#either wait and get the value
print "value:", fut.value()

#or add a callback that will be called when the function returns
def mycb(fut):
  print "value:", fut.value()
fut.addCallback(mycb)
#continue working while tts.say proceeds