Using ALModule-inherited class from external file

303 views Asked by At

I'm experiencing some issues with the naoqi python sdk. I have the following code for a Caresse Detector. My class is inherited from ALModule and registers to events on the head tactile sensors.

# -*- encoding: UTF-8 -*-
import sys
from naoqi import ALProxy
from naoqi import ALModule
from naoqi import ALBroker
import time

class caresseDetector(ALModule):
    def __init__(self,name="caresseDetectorModule"):
        ALModule.__init__(self,name)
        self.tts = ALProxy("ALTextToSpeech")
        self.memory = ALProxy("ALMemory")
        self.memory.subscribeToEvent("FrontTactilTouched",name,"onFrontTouched")
        self.memory.subscribeToEvent("RearTactilTouched",name,"onRearTouched")
        self.memory.subscribeToEvent("MiddleTactilTouched",name,"onMiddleTouched")
        self.touchFlags = [False,False,False]
        self.t0 = 0
        self.gestureDuration = 0.5

    def onFrontTouched(self):
        print self.touchFlags

        if time.time()-self.t0 < self.gestureDuration:
            if self.touchFlags == [False,True,True]:
                self.greet()
        else:
            self.touchFlags = [False,False,False]

        if self.touchFlags == [True,False,False]:
            self.t0 = time.time()

        elif self.touchFlags == [False,False,False]:
            self.t0 = time.time()
            self.touchFlags[0] = True
        # else:
        #     self.touchFlags = [False,False,False]
        #     self.t0 = 0

    def onRearTouched(self):
        # print self.touchFlags
        exec('print ' + str(self.touchFlags))
        if time.time() - self.t0 < self.gestureDuration:
            if self.touchFlags == [True,True,False]:
                self.greet()
        else:
            self.touchFlags = [False,False,False]

        if self.touchFlags == [False,False,True]:
            self.t0 = time.time()

        elif self.touchFlags == [False,False,False]:
            self.t0 = time.time()
            self.touchFlags[2] = True
        # else:
        #     self.touchFlags = [False, False, False]
        #     self.t0 = 0

    def onMiddleTouched(self):
        # print self.touchFlags
        exec ('print ' + str(self.touchFlags))
        self.touchFlags[1] = True

        if self.touchFlags == [True,True,True]:
            self.greet()
        # else:
        #     self.touchFlags = [False,False,False]
        #     self.t0 = 0

    def greet(self):
        # print "-------"
        exec ('print ' + str(self.touchFlags))
        self.t0 = 0
        id = self.tts.post.say("Grazie!")
        self.touchFlags = [False,False,False]
        self.tts.wait(id,0)

    def detect(self,broker):
        # myBroker = ALBroker("myBroker", "0.0.0.0", 0, self.robotIP, self.port)
        try:
            while True:
                time.sleep(1)

        except:
            # print
            # print "Interrupted, shutting down"
            exec ('print')
            exec ('print "Interrupted, shutting down"')
            broker.shutdown()

    def __del__(self):
        self.memory = None
        self.tts = None

    # robotIP = "194.119.214.185"
    #
    # myBroker = ALBroker("myBroker","0.0.0.0",0,robotIP,9559)
    # goofy = caresseDetector("detector")
    # goofy.detect(myBroker)

If I run the last instructions commented at the end of the code the module works well, while if I run THE SAME code in an external file importing my class, I get the following error when an event occurs:

[E] 4099 qitype.dynamicobject:  ALPythonTools::eval
 python object not found detector

The external file to test looks like this:

from naoqi import ALBroker
from caresseDetector import caresseDetector
robotIP = "194.119.214.185"

myBroker = ALBroker("myBroker","0.0.0.0",0,robotIP,9559)
goofy = caresseDetector("detector")
goofy.detect(myBroker)

I have not found anything online, can someone help me?

Thanks in advance

2

There are 2 answers

0
Stefan On BEST ANSWER

The NAOqi callback mechanism tries to find the module instance by looking for a global variable in the top-level scope (i.e., where __main__ is) with the same name as the module name. You pass "detector" to ALModule.__init__(), so NAOqi looks for the global variable named detector and fails to find it because it is named goofy in the code example.

After changing the instance creation code to

myBroker = ALBroker("myBroker","0.0.0.0",0,robotIP,9559)
detector = caresseDetector("detector")
detector.detect(myBroker)

the code works for me both in the same file and in an external file.

This behavior is also mentioned in the official documentation on the NAOqi Python SDK (see the notes below the code example): http://doc.aldebaran.com/2-1/dev/python/reacting_to_events.html

3
Victor Paléologue On

You don't need to use ALModule in your case, because you are simply doing a client. Here is a tutorial for how to write a client. If you really wanted to expose methods, you should write a service, instead of getting around ALModule.

In your case, you want to subscribe to ALMemory events. But you are doing it the old-school way, that requires you to use an ALModule. Since the introduction of ALMemory.subscriber(eventName), you can simply write the following:

def onFrontTactilTouched(value):
    pass # process the event

memory = session.service('ALMemory')
subscriber = memory.subscriber('FrontTactilTouched')
subscriber.signal.connect(onFrontTactilTouched)

Please note that you will have to keep the subscriber alive to maintain the subscription.