Making a Python module - Reacting to events ¶
Here we want the robot say ‘Hello, you’ every time it detects a human face.
To do this, we need to subscribe to the ‘FaceDetected’ event, raised by the ALFacedetection module.
If you read the documentation of ALMemoryProxy::subscribeToEvent(), you will see you need a module name and the name of a callback.
So we need to write a NAOqi module in Python.
To create a module in Python, we also need a broker.
The example can be found below.
# -*- encoding: UTF-8 -*- """ Say 'hello, you' each time a human face is detected """ import sys import time from naoqi import ALProxy from naoqi import ALBroker from naoqi import ALModule from optparse import OptionParser NAO_IP = "nao.local" # Global variable to store the HumanGreeter module instance HumanGreeter = None memory = None class HumanGreeterModule(ALModule): """ A simple module able to react to facedetection events """ def __init__(self, name): ALModule.__init__(self, name) # No need for IP and port here because # we have our Python broker connected to NAOqi broker # Create a proxy to ALTextToSpeech for later use self.tts = ALProxy("ALTextToSpeech") # Subscribe to the FaceDetected event: global memory memory = ALProxy("ALMemory") memory.subscribeToEvent("FaceDetected", "HumanGreeter", "onFaceDetected") def onFaceDetected(self, *_args): """ This will be called each time a face is detected. """ # Unsubscribe to the event when talking, # to avoid repetitions memory.unsubscribeToEvent("FaceDetected", "HumanGreeter") self.tts.say("Hello, you") # Subscribe again to the event memory.subscribeToEvent("FaceDetected", "HumanGreeter", "onFaceDetected") def main(): """ Main entry point """ parser = OptionParser() parser.add_option("--pip", help="Parent broker port. The IP address or your robot", dest="pip") parser.add_option("--pport", help="Parent broker port. The port NAOqi is listening to", dest="pport", type="int") parser.set_defaults( pip=NAO_IP, pport=9559) (opts, args_) = parser.parse_args() pip = opts.pip pport = opts.pport # We need this broker to be able to construct # NAOqi modules and subscribe to other modules # The broker must stay alive until the program exists myBroker = ALBroker("myBroker", "0.0.0.0", # listen to anyone 0, # find a free port and use it pip, # parent broker IP pport) # parent broker port # Warning: HumanGreeter must be a global variable # The name given to the constructor must be the name of the # variable global HumanGreeter HumanGreeter = HumanGreeterModule("HumanGreeter") try: while True: time.sleep(1) except KeyboardInterrupt: print print "Interrupted by user, shutting down" myBroker.shutdown() sys.exit(0) if __name__ == "__main__": main()
- Make sure to use a global variable for the module instance.
- Make sure the name you pass to the constructor of ALModule matches the name of your variable.
- The method of your class are automatically transform into bound methods, providing that you wrote a doc string for this method, and it does not start with an underscore.
class MyModule: # This method will be bound: def myMethod(self): """ does this and that """ pass # This will NOT be bound: def myMethod(self): if foo: pass # This will also NOT be bound def _myMethod(self): pass
- Once you have built a ALBroker object, you need to keep the object alive for the subscribing to work, hence the while(True) loop. You also need the broker object to be alive in order to create proxies without specifying an IP or a port.
- The script must be run with --pip and --pport options to work.
Run the script, and put your face in front of the robot : you should hear ‘Hello, you’.