[Python] Pepper robot error: A grammar named "modifiable_grammar" already exists

Discussão em 'Python' iniciado por Stack, Julho 24, 2025.

  1. Stack

    Stack Membro Participativo

    i am programming a interaccion script in python 2.7 for the robot Pepper but when i try to set the vocabulary to detect the words i need i get this error

    Traceback (most recent call last):
    File "choice_script.py", line 225, in <module>
    text, value = ask_pepper_question(question2, actions2)
    File "choice_script.py", line 209, in ask_pepper_question
    return handler.ask_question(question, response_actions, timeout)
    File "choice_script.py", line 70, in ask_question
    self._setup_vocabulary(possible_responses)
    File "choice_script.py", line 124, in _setup_vocabulary
    self.asr.setVocabulary(vocabulary, False)
    File "/opt/aldebaran/lib/python2.7/site-packages/naoqi.py", line 194, in __call__
    return self.__wrapped__.method_missing(self.__method__, *args, **kwargs)
    File "/opt/aldebaran/lib/python2.7/site-packages/naoqi.py", line 264, in method_missing
    raise e
    RuntimeError: ALSpeechRecognition::setVocabulary
    NuanceContext::addContext
    A grammar named "modifiable_grammar" already exists.


    At first it worked by simply checking if i had already set the vocabulary so omitting the set line but now i need to change it so that doesnt work.

    This is the code i would like to run, thanks

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    Script para que Pepper reaccione a respuestas personalizables
    Requiere Python 2.7 y NAOqi SDK
    """

    from __future__ import print_function
    from naoqi import ALProxy
    import time

    # Clave de ALMemory para marcar vocab inicializado
    VOCAB_FLAG = "MyApp/VocabInitialized"
    DISTINCT_VOCABS = []

    class PepperInteractionHandler:
    def __init__(self, robot_ip="localhost", robot_port=9559):
    """
    Inicializa el manejador de interacciones de Pepper
    """
    self.robot_ip = robot_ip
    self.robot_port = robot_port
    self.tts = None
    self.asr = None
    self.memory = None
    self._initialize_robot()

    def _initialize_robot(self):
    """
    Inicializa los proxies del robot
    """
    try:
    self.tts = ALProxy("ALTextToSpeech", self.robot_ip, self.robot_port)
    self.asr = ALProxy("ALSpeechRecognition", self.robot_ip, self.robot_port)
    self.memory = ALProxy("ALMemory", self.robot_ip, self.robot_port)

    # Configurar idioma
    self.asr.setLanguage("Spanish")
    print("Robot inicializado correctamente")

    except Exception as e:
    print("Error conectando al robot: {}".format(e))
    print("Asegúrate de que:")
    print("1. El robot esté encendido")
    print("2. La IP sea correcta")
    print("3. Estés en la misma red")
    raise

    def ask_question(self, question, response_actions, timeout=15, confidence_threshold=0.5):
    """
    Hace una pregunta al usuario y procesa la respuesta

    Args:
    question (str): La pregunta que hará el robot
    response_actions (dict): Diccionario que mapea cada respuesta a la acción del robot
    Formato: {"respuesta": {"text": "texto_respuesta", "value": numero}}
    timeout (int): Tiempo límite para esperar respuesta en segundos
    confidence_threshold (float): Umbral de confianza para aceptar la respuesta

    Returns:
    tuple: (texto_respuesta, valor_numerico) o (None, None) si no se reconoció
    """
    if not self.tts or not self.asr or not self.memory:
    print("Error: Robot no inicializado correctamente")
    return (None, None)

    try:
    # Extraer respuestas posibles del diccionario
    possible_responses = list(response_actions.keys())

    # Configurar vocabulario dinámicamente
    self._setup_vocabulary(possible_responses)

    # Hacer la pregunta
    self.tts.say(question)

    # Iniciar reconocimiento de voz
    self.asr.subscribe("Dynamic_ASR")

    print("Robot esperando respuesta...")
    print("Respuestas posibles: {}".format(", ".join(possible_responses)))

    # Limpiar datos anteriores de memoria
    self.memory.insertData("WordRecognized", [])

    # Esperar respuesta del usuario
    recognized_response = self._wait_for_response(timeout, confidence_threshold)

    if recognized_response:
    # Procesar la respuesta y devolver tupla
    return self._process_response(recognized_response, response_actions)
    else:
    self.tts.say("No pude escuchar tu respuesta. Intenta hablar más claro.")
    return (None, None)

    except Exception as e:
    print("Error durante la interacción: {}".format(e))
    print(e)
    return (None, None)
    finally:
    # Asegurar que se detenga el reconocimiento
    try:
    self.asr.unsubscribe("Dynamic_ASR")
    except:
    pass

    def _setup_vocabulary(self, possible_responses):
    """
    Configura el vocabulario dinámicamente basado en las respuestas posibles
    """
    try:
    # Pausar ASR para cambiar vocabulario
    self.asr.pause(True)

    # Crear vocabulario expandido (incluir variaciones)
    vocabulary = []
    for response in possible_responses:
    vocabulary.append(response.lower())
    vocabulary.append(response.upper())
    vocabulary.append(response.capitalize())

    # Eliminar duplicados
    vocabulary = list(set(vocabulary))

    self.asr.setVocabulary(vocabulary, False)

    # Reanudar ASR
    self.asr.pause(False)

    print("Vocabulario configurado: {}".format(vocabulary))

    except Exception as e:
    print("Error configurando vocabulario")
    print(e)
    raise e

    def _wait_for_response(self, timeout, confidence_threshold):
    """
    Espera y procesa la respuesta del usuario
    """
    recognized = False
    start_time = time.time()
    time.sleep(1.0) # Esperar antes de empezar a escuchar

    while not recognized and (time.time() - start_time) < timeout:
    # Verificar si hay una palabra reconocida
    word_recognized = self.memory.getData("WordRecognized")
    if word_recognized and len(word_recognized) > 1:
    recognized_word = word_recognized[0]
    confidence = word_recognized[1]

    print("Palabra detectada: '{}' con confianza: {:.2f}".format(recognized_word, confidence))

    if confidence > confidence_threshold:
    print("Palabra reconocida con suficiente confianza: {}".format(recognized_word))
    # Limpiar memoria después del reconocimiento
    self.memory.insertData("WordRecognized", [])
    return recognized_word
    else:
    print("Confianza insuficiente ({:.2f}), continuando...".format(confidence))
    # Limpiar para evitar re-procesamiento
    self.memory.insertData("WordRecognized", [])

    time.sleep(0.1)

    return None

    def _process_response(self, recognized_word, response_actions):
    """
    Procesa la respuesta reconocida y devuelve la tupla correspondiente

    Returns:
    tuple: (texto_respuesta, valor_numerico) o (None, None) si no se encuentra
    """
    word_lower = recognized_word.lower()

    # Buscar la acción correspondiente
    for response_key, action_data in response_actions.items():
    if word_lower == response_key.lower():
    text = action_data.get("text", "")
    value = action_data.get("value", 0)

    print("Usuario respondió '{}' - Devolviendo: ('{}', {})".format(
    recognized_word, text, value))
    return (text, value)

    # Si no se encuentra una acción específica
    print("Respuesta no reconocida en acciones: '{}'".format(recognized_word))
    return (None, None)


    # Función de conveniencia para usar sin clase
    def ask_pepper_question(question, response_actions, robot_ip="localhost", robot_port=9559, timeout=15):
    """
    Función de conveniencia para hacer una pregunta sin instanciar la clase

    Args:
    question (str): La pregunta que hará el robot
    response_actions (dict): Diccionario que mapea respuestas a acciones del robot
    Formato: {"respuesta": {"text": "texto", "value": numero}}
    robot_ip (str): IP del robot
    robot_port (int): Puerto del robot
    timeout (int): Tiempo límite para respuesta

    Returns:
    tuple: (texto_respuesta, valor_numerico) o (None, None) si no se reconoció
    """
    handler = PepperInteractionHandler(robot_ip, robot_port)
    return handler.ask_question(question, response_actions, timeout)


    # Ejemplo de uso
    if __name__ == "__main__":

    print("\n=== Ejemplo 2: Múltiples opciones ===")
    # Ejemplo 2: Pregunta de múltiples opciones con diferentes valores
    question2 = "¿Qué te gustaría hacer? Puedes decir: bailar, cantar o hablar."
    actions2 = {
    "bailar": {"text": "¡Perfecto! Vamos a bailar juntos.", "value": 1},
    "cantar": {"text": "¡Qué divertido! Me encanta cantar.", "value": 2},
    "hablar": {"text": "Excelente, podemos tener una buena conversación.", "value": 3}
    }

    print("\n=== Ejemplo 2: Múltiples opciones ===")
    text, value = ask_pepper_question(question2, actions2)
    print("Resultado: ('{}', {})".format(text, value))

    # Ejemplo de uso del valor numérico para lógica de control
    if value == 1:
    print("Activando modo baile...")
    elif value == 2:
    print("Activando modo canto...")
    elif value == 3:
    print("Activando modo conversación...")
    else:
    print("No se reconoció la respuesta")

    print("\n=== Ejemplo 1: Múltiples opciones ===")
    # Ejemplo 1: Pregunta Sí/No con valores numéricos
    question1 = "¿Tienes alguna otra pregunta?"
    actions1 = {
    "si": {"text": "¡Vamos!", "value": 1},
    "no": {"text": "Entiendo. Ha sido un placer. No dudes en volver a consultarme.", "value": 0}
    }

    print("=== Ejemplo 1: Pregunta Sí/No ===")
    text, value = ask_pepper_question(question1, actions1)
    print("Resultado: ('{}', {})".format(text, value))

    # Si quieres que el robot diga el texto, lo puedes hacer después:
    if text:
    handler = PepperInteractionHandler()
    handler.tts.say(text)



    I tried running the code with multiple inputs and it should work without the grammar error. The error appeared but randomly, ussualy in the second or so on run.

    This is the code of the naoqi.py file if it were of use:

    import os
    import sys
    import ctypes
    import weakref
    import logging
    import inspect
    from functools import partial

    import qi


    def set_dll_directory():
    this_dir = os.path.abspath(os.path.dirname(__file__))
    bin_dir = os.path.join(this_dir, "..", "bin")
    if os.path.exists(bin_dir):
    ctypes.windll.kernel32.SetDllDirectoryA(bin_dir)

    def load_inaoqi_deps():
    """ Helper to laod _inaoqi.so deps on linux """
    deps = [
    "libboost_python.so",
    "libboost_system.so",
    "libboost_chrono.so",
    "libboost_program_options.so",
    "libboost_thread.so",
    "libboost_filesystem.so",
    "libboost_regex.so",
    "libboost_locale.so",
    "libboost_signals.so",
    "libqi.so",
    "libalerror.so",
    "libalthread.so",
    "libalvalue.so",
    "libalcommon.so",
    "libalproxies.so",
    "libalpythontools.so",
    "libqipython.so",
    "libinaoqi.so"
    ]
    relpaths = [
    # in pynaoqi, this file is /naoqi.py and we search for /libqi.so
    [],
    # in deploys/packages/etc,
    # this file is $PREFIX/lib/python2.7/site-packages/naoqi.py
    # and we need $PREFIX/lib/libqi.so
    ["..", ".."],
    ]
    this_dir = os.path.abspath(os.path.dirname(__file__))
    for dep in deps:
    for relpath in relpaths:
    list_path = [this_dir] + relpath + [dep]
    full_path = os.path.join(*list_path)
    try:
    ctypes.cdll.LoadLibrary(full_path)
    except Exception:
    pass

    if sys.platform.startswith("linux"):
    load_inaoqi_deps()

    if sys.platform.startswith("win"):
    set_dll_directory()

    import inaoqi

    import motion
    import allog

    def _getMethodParamCount(func):
    r = inspect.getargspec(func)
    #normal args
    np = len(r[0])
    #*args (none if non existent)
    if r[1] is not None:
    np = np + 1
    #**kargs (none if non existent)
    if r[2] is not None:
    np = np + 1
    return np

    def autoBind(myClass, bindIfnoDocumented):
    """Show documentation for each
    method of the class"""

    # dir(myClass) is a list of the names of
    # everything in class
    myClass.setModuleDescription(myClass.__doc__)

    for thing in dir(myClass):
    # getattr(x, "y") is exactly: x.y
    function = getattr(myClass, thing)
    if callable(function):
    if (type(function) == type(myClass.__init__)):
    if (bindIfnoDocumented or function.__doc__ != ""):
    if (thing[0] != "_"): # private method
    if (function.__doc__):
    myClass.functionName(thing, myClass.getName(), function.__doc__)
    else:
    myClass.functionName(thing, myClass.getName(), "")

    for param in function.func_code.co_varnames:
    if (param != "self"):
    myClass.addParam(param)
    myClass._bindWithParam(myClass.getName(),thing, _getMethodParamCount(function)-1)



    class ALDocable():
    def __init__(self, bindIfnoDocumented):
    autoBind(self,bindIfnoDocumented)


    # define the log handler to be used by the logging module
    class ALLogHandler(logging.Handler):
    def __init__(self):
    logging.Handler.__init__(self)

    def emit(self, record):
    level_to_function = {
    logging.DEBUG: allog.debug,
    logging.INFO: allog.info,
    logging.WARNING: allog.warning,
    logging.ERROR: allog.error,
    logging.CRITICAL: allog.fatal,
    }
    function = level_to_function.get(record.levelno, allog.debug)
    function(record.getMessage(),
    record.name,
    record.filename,
    record.funcName,
    record.lineno)


    # define a class that will be inherited by both ALModule and ALBehavior, to store instances of modules, so a bound method can be called on them.
    class NaoQiModule():
    _modules = dict()

    @classmethod
    def getModule(cls, name):
    # returns a reference a module, giving its string, if it exists !
    if(name not in cls._modules):
    raise RuntimeError("Module " + str(name) + " does not exist")
    return cls._modules[name]()

    def __init__(self, name, logger=True):
    # keep a weak reference to ourself, so a proxy can be called on this module easily
    self._modules[name] = weakref.ref(self)
    self.loghandler = None
    if logger:
    self.logger = logging.getLogger(name)
    self.loghandler = ALLogHandler()
    self.logger.addHandler(self.loghandler)
    self.logger.setLevel(logging.DEBUG)

    def __del__(self):
    # when object is deleted, clean up dictionnary so we do not keep a weak reference to it
    del self._modules[self.getName()]
    if(self.loghandler != None):
    self.logger.removeHandler(self.loghandler)


    class ALBroker(inaoqi.broker):
    def init(self):
    pass

    class ALModule(inaoqi.module, ALDocable, NaoQiModule):

    def __init__(self,param):
    inaoqi.module.__init__(self, param)
    ALDocable.__init__(self, False)
    NaoQiModule.__init__(self, param)
    self.registerToBroker()

    def __del__(self):
    NaoQiModule.__del__(self)

    def methodtest(self):
    pass

    def pythonChanged(self, param1, param2, param3):
    pass

    class MethodMissingMixin(object):
    """ A Mixin' to implement the 'method_missing' Ruby-like protocol. """
    def __getattribute__(self, attr):
    try:
    return object.__getattribute__(self, attr)
    except:
    class MethodMissing(object):
    def __init__(self, wrapped, method):
    self.__wrapped__ = wrapped
    self.__method__ = method
    def __call__(self, *args, **kwargs):
    return self.__wrapped__.method_missing(self.__method__, *args, **kwargs)

    return MethodMissing(self, attr)

    def method_missing(self, *args, **kwargs):
    """ This method should be overridden in the derived class. """
    raise NotImplementedError(str(self.__wrapped__) + " 'method_missing' method has not been implemented.")


    class postType(MethodMissingMixin):
    def __init__(self):
    ""

    def setProxy(self, proxy):
    self.proxy = weakref.ref(proxy)
    # print name

    def method_missing(self, method, *args, **kwargs):
    list = []
    list.append(method)
    for arg in args:
    list.append(arg)
    result = 0
    try:
    p = self.proxy()
    result = p.pythonPCall(list)
    except RuntimeError,e:
    raise e

    return result



    class ALProxy(inaoqi.proxy,MethodMissingMixin):

    def __init__(self, *args):
    self.post = postType()
    self.post.setProxy(self)
    if (len (args) == 1):
    inaoqi.proxy.__init__(self, args[0])
    elif (len (args) == 2):
    inaoqi.proxy.__init__(self, args[0], args[1])
    else:
    inaoqi.proxy.__init__(self, args[0], args[1], args[2])

    def call(self, *args):
    list = []
    for arg in args:
    list.append(arg)

    return self.pythonCall(list)


    def pCall(self, *args):
    list = []
    for arg in args:
    list.append(arg)

    return self.pythonPCall(list)


    def method_missing(self, method, *args, **kwargs):
    list = []
    list.append(method)
    for arg in args:
    list.append(arg)
    result = 0
    try:
    result = self.pythonCall(list)
    except RuntimeError,e:
    raise e
    #print e.args[0]

    return result

    @staticmethod
    def initProxy(name, fut):
    try:
    proxy = ALProxy(name)
    except:
    print "Error: cannot get proxy to %s even though we waited for it" % name
    return

    globals()[name] = proxy
    print "Got proxy to " + name

    global _initCb
    if _initCb is not None:
    _initCb(name)

    @staticmethod
    def lazyLoad(session, name):
    session.waitForService(name, _async = True).addCallback(partial(ALProxy.initProxy, name))

    @staticmethod
    def initProxies(initCb = None):
    global _initCb
    _initCb = initCb

    #Warning: The use of these default proxies is deprecated.
    global ALLeds
    ALLeds = None

    session = inaoqi._getDefaultSession()

    ALProxy.lazyLoad(session, "ALFrameManager")
    ALProxy.lazyLoad(session, "ALMemory")
    ALProxy.lazyLoad(session, "ALMotion")
    ALProxy.lazyLoad(session, "ALLeds")
    ALProxy.lazyLoad(session, "ALLogger")
    ALProxy.lazyLoad(session, "ALSensors")


    def createModule(name):
    global moduleList
    str = "moduleList.append("+ "module(\"" + name + "\"))"
    exec(str)

    Continue reading...

Compartilhe esta Página