I'm using Python 3.5.10-slim-buster (Docker) with the Pepper robot from Softbank. The NAOqi version on the robot is 2.5.8 (taken from /var/log/naoqi/servicemanager/system.Naoqi.log
).
I got qi v. 3.0.0 via pip.
I want to subscribe to events with
pepper = qi.Application()
pepper.start()
session = pepper.session
memory = session.service("ALMemory")
def touch_event(*args, **kwargs):
pass
subscriber = memory.subscriber("ALTouch/TouchChanged") # throws RuntimeError: Invalid signature
if subscriber:
subscriber.signal.connect(touch_event)
Creating the session directly like in http://doc.aldebaran.com/libqi/api/python/session.html didn't work either.
Does anyone know how to make this work?
I've referenced this issue in https://github.com/aldebaran/libqi-python/issues/13.
tldr: The issue occurs most likely due to a missmatch between the NaoQi OS and the coresponding libQi library. My workaround for this is to run my code directly on the pepper robot.
Even with the latest version of libqi and the fix from Victor (see https://github.com/victorpaleologue/libqi-python/tree/47df0833c707cfd2a6a4c86765db423f319e029d) it didn't work and resulted in the same error.
There has been a protocol breakage in libQi, that you can only spot on methods that returns QiObjects such as ALMemory.subscriber
.
NAOqi 2.5.x has a libQi version around 1.8.x, and libQi 2.x is already incompatible with that. You are running a libQi 3.x, so you experience the issue too.
It is going to be hard to recompile an old libqi-python
for Python 3, so I recommend that you work around this issue by using the legacy ALMemory.subscribeToEvent
.
To do that with libQi, you will need to register a service hosted on your client machine, and make sure it is accessible to the robot by listening on public addresses on the network:
# Listen to public addresses on a random port,
# so that services registered from here are accessible.
session.listen("tcp://0.0.0.0:0")
# An object that will be registered as a service.
class MySubscriber:
# It needs at least a callback to get ALMemory events.
def onTouched(key, value):
pass
subscriber = MySubscriber()
# Register it with an arbitrary name.
service_name = "MySubscriber"
session.registerService(service_name, subscriber)
# Subscribe and tell exactly which service and method to call back.
memory.subscribeToEvent("TouchChanged", service_name, "onTouched")
Also, note that the right name of the event is TouchedChanged
(no ALTouch/
prefix).