Ejemplo n.º 1
0
 def react_to_feedback(ctx: rs.ContextWrapper):
     if ctx[prop_game_in_progress]:
         rand = random.random()
         if ctx[nlp.prop_yesno].yes():
             ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                 "charades_winning_exclamations")
             if rand < 0.5:
                 emotion = SUNGLASSES_ON_EMOTION
                 ctx[prop_sunglasses_on] = True
             else:
                 emotion = HEARTS_EMOTION
             if ctx.conf(key=USE_EMOTIONS):
                 emo_client(emotion)
             ctx[prop_feedback_received] = True
             logger.info("correct")
         elif ctx[nlp.prop_yesno].no():
             if ctx[prop_guess_attempt_count] < 3:
                 ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                     "charades_new_guess_attempt")
                 ctx[prop_another_attempt] = True
                 logger.info("wrong guess")
             else:
                 ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                     "charades_losing_exclamations")
                 if ctx.conf(key=USE_EMOTIONS):
                     emo_client(SHY_EMOTION)
                 ctx[prop_feedback_received] = True
         else:
             ctx[prop_feedback_received] = False
             return rs.Emit()
     else:
         return rs.Resign()
Ejemplo n.º 2
0
def send_on_telegram(ctx: rs.ContextWrapper, text: str):
    """
    If all telegram chats should be in the same context, sends the text to every currently active chat.
    Otherwise it only sends output using the Pipe if it is a child process
    """
    if not text or not isinstance(text, str):
        return rs.Resign()

    if ctx.conf(key=ALL_IN_ONE_CONTEXT_CONFIG_KEY):
        # TODO don't instantiate the updater every time
        token = ctx.conf(key=TOKEN_CONFIG_KEY)
        if not token:
            logger.error('telegram-token is not set. Shutting down telegramio')
            return rs.Delete()
        updater: Updater = Updater(token)
        for chat_id in active_chats.keys():
            updater.bot.send_message(chat_id=chat_id, text=text)
    else:
        child_conn = ctx.conf(key=CHILD_CONN_CONFIG_KEY)
        if child_conn:
            # Child Process -> write to Pipe
            child_conn.send(text)
        else:
            # Master Process -> State not needed
            return rs.Delete()
Ejemplo n.º 3
0
 def move_head(ctx: rs.ContextWrapper):
     for axis, lower, upper in [(prop_head_axis0, ctx.conf(key=AXIS0_LOWER_LIMIT_KEY), ctx.conf(key=AXIS0_UPPER_LIMIT_KEY)),
                                (prop_head_axis1, ctx.conf(key=AXIS1_LOWER_LIMIT_KEY), ctx.conf(key=AXIS1_UPPER_LIMIT_KEY)),
                                (prop_head_axis2, ctx.conf(key=AXIS2_LOWER_LIMIT_KEY), ctx.conf(key=AXIS2_UPPER_LIMIT_KEY))]:
         data = random.uniform(lower, upper)
         if random.random() < ctx.conf(key=HEAD_MOVEMENT_PROBABILITY_KEY):  # move or don't move axis with probability
             logger.info(f"Publishing {data} to {axis.topic}")
             ctx[axis] = Float32(data=data)
Ejemplo n.º 4
0
 def save_face(ctx: rs.ContextWrapper, id, face_vector):
     try:
         redis_conn = redis.Redis(
             host=ctx.conf(key=REDIS_HOST_CONF),
             port=ctx.conf(key=REDIS_PORT_CONF),
             password=ctx.conf(key=REDIS_PASS_CONF))
         redis_conn.set(id, pickle.dumps(face_vector))
     except redis.exceptions.ConnectionError as e:
         err_msg = "Looks like the redis connection is unavailable :-("
         logger.error(err_msg)
Ejemplo n.º 5
0
 def ping_activity_choice(ctx: rs.ContextWrapper):
     if ctx[prop_game_in_progress]:
         rand = random.random()
         pinged_times = ctx[prop_ping_choice_count]
         if pinged_times < 5:
             if rand < 0.4 and ctx.conf(key=USE_EMOTIONS):
                 emo_client(LOOK_RIGHT_EMOTION)
             elif (rand > 0.4 and rand < 0.8
                   and ctx.conf(key=USE_EMOTIONS)):
                 emo_client(LOOK_LEFT_EMOTION)
             ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                 "charades_ping_activity_choice")
             ctx[prop_ping_choice_count] = pinged_times + 1
             return rs.Emit()
         else:
             ctx[prop_stop_game] = True
Ejemplo n.º 6
0
 def move_eyes(ctx: rs.ContextWrapper):
     if random.random() < ctx.conf(key=EYE_MOVEMENT_PROBABILITY_KEY):
         if random.random() < 0.5:
             logger.info(f"Publishing {LOOK_LEFT_EMOTION} to {prop_move_eyes.topic}")
             ctx[prop_move_eyes] = String(data=LOOK_LEFT_EMOTION)
         else:
             logger.info(f"Publishing {LOOK_RIGHT_EMOTION} to {prop_move_eyes.topic}")
             ctx[prop_move_eyes] = String(data=LOOK_RIGHT_EMOTION)
Ejemplo n.º 7
0
 def react_to_continue_decision(ctx: rs.ContextWrapper):
     rand = random.random()
     if ctx[nlp.prop_yesno].yes():
         ctx[rawio.prop_out] = verbaliser.get_random_phrase(
             "charades_positive_expressions") + " Let's continue then"
         if rand < 0.7 and ctx.conf(key=USE_EMOTIONS):
             emo_client(LUCKY_EMOTION)
         return rs.Emit()
     elif ctx[nlp.prop_yesno].no():
         ctx[rawio.prop_out] = verbaliser.get_random_phrase(
             "charades_no_continuation")
         if ctx.conf(key=USE_EMOTIONS):
             emo_client(KISS_EMOTION)
         ctx[prop_stop_game] = True
     else:
         ctx[rawio.prop_out] = verbaliser.get_random_phrase(
             "charades_misunderstanding")
         ctx[prop_continuation_unclear] = True
Ejemplo n.º 8
0
 def ask_to_continue(ctx: rs.ContextWrapper):
     if ctx[prop_feedback_received]:
         ctx[rawio.prop_out] = verbaliser.get_random_phrase(
             "charades_offer_another_round")
         if ctx[prop_sunglasses_on] and ctx.conf(key=USE_EMOTIONS):
             emo_client(SUNGLASSES_ON_EMOTION)
             ctx[prop_sunglasses_on] = False
         return rs.Emit()
     else:
         return rs.Resign()
Ejemplo n.º 9
0
 def process_play_decision(ctx: rs.ContextWrapper):
     if not ctx[prop_game_in_progress]:
         if ctx[nlp.prop_yesno].yes():
             ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                 "charades_positive_expressions") + \
                 " Do you want to hear the rules?"
             if ctx.conf(key=USE_EMOTIONS):
                 emo_client(SMILEBLINK_EMOTION)
             return rs.Emit()
         elif ctx[nlp.prop_yesno].no():
             if random.random() < 0.5 and ctx.conf(key=USE_EMOTIONS):
                 emo_client(ROLL_EYES_EMOTION)
             ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                 "charades_refuse_offer")
             ctx[prop_stop_game] = True
         else:
             ctx[prop_decision_unclear] = True
             ctx[rawio.prop_out] = verbaliser.get_random_phrase(
                 "charades_misunderstanding")
     else:
         return rs.Resign()
Ejemplo n.º 10
0
    def store_face_and_name(ctx: rs.ContextWrapper):
        tokens = ctx[nlp.prop_tokens]
        triples = ctx[nlp.prop_triples]
        if len(tokens) == 1:
            name = tokens[0]
        elif triples[0].get_object().text and triples[0].match_either_lemma(
                pred={"be"}):
            name = triples[0].get_object().text
        else:
            ctx["rawio:out"] = "Sorry, what was the name?"
            return rs.Emit()
        ctx["rawio:out"] = f"Got it, I'm sure I'll remember {name} next time I see that face!"

        # Create memory entry
        sess: Session = ravestate_ontology.get_session()
        onto: Ontology = ravestate_ontology.get_ontology()
        query = Node(metatype=onto.get_type("Person"))
        query.set_properties({"name": name})
        node_list = sess.retrieve(query)
        if not node_list:
            node = sess.create(query)
            logger.info(f"Created new Node in scientio session: {node}")
        elif len(node_list) == 1:
            node = node_list[0]
        else:
            logger.error(
                f'Failed to create or retrieve Scientio Node for {name}!')
            return
        logger.info(f"Node ID for {name} in picture is {node.get_id()}!")

        # Store face vector with node id in redis
        try:
            redis_conn = redis.Redis(host=ctx.conf(key=REDIS_HOST_CONF),
                                     port=ctx.conf(key=REDIS_PORT_CONF),
                                     password=ctx.conf(key=REDIS_PASS_CONF))
            redis_conn.set(node.get_id(), ctx["sendpics:face_vec"])
        except redis.exceptions.ConnectionError as e:
            err_msg = "Looks like the redis connection is unavailable :-("
            logger.error(err_msg)
            ctx[rawio.prop_out] = err_msg
Ejemplo n.º 11
0
 def stop_game_session(ctx: rs.ContextWrapper):
     '''
     go off the game session so new game can be started
     '''
     if not ctx[prop_game_stopped]:
         if ctx[prop_sunglasses_on] and ctx.conf(key=USE_EMOTIONS):
             emo_client(SUNGLASSES_ON_EMOTION)
             ctx[prop_sunglasses_on] = False
         ctx[prop_game_in_progress] = False
         ctx[prop_waiting_for_label] = False
         ctx[prop_ping_choice_count] = 0
         ctx[prop_game_stopped] = True
         ctx[rawio.prop_out] = "I will stop now but if you want to " \
             "play again just tell me"
Ejemplo n.º 12
0
 def start_recording(ctx: rs.ContextWrapper):
     if ctx.conf(key=USE_EMOTIONS):
         emo_client(HYPNO_EMOTION)
     resp = recognition_client()
     if resp:
         global count_round
         count_round = count_round + 1
         logger.info(f"Round {count_round}")
         ctx[rawio.prop_out] = "Beep! Now let me think a little bit"
         ctx[prop_waiting_for_label] = True
         ctx[prop_guess_attempt_count] = 0
         return rs.Emit()
     else:
         ctx[rawio.prop_out] = BROKEN_MESSAGE
         ctx[prop_stop_game] = True
Ejemplo n.º 13
0
 def gpt3(ctx: rs.ContextWrapper):
     append_to_history(ctx.conf(key=HUMAN_PROMPT_PREFIX_KEY),
                       ctx[rawio.prop_in])
     prompt = ctx.conf(key=PROMPT_KEY) + "\n".join(history + ctx.conf(
         key=ROBOY_PROMPT_PREFIX_KEY))
     logger.info(prompt)
     result = requests.post(
         "https://api.openai.com/v1/engines/davinci/completions",
         json={
             "prompt": prompt,
             "temperature": ctx.conf(key=TEMPERATURE_KEY),
             "max_tokens": ctx.conf(key=MAX_TOKENS_KEY),
             "top_p": ctx.conf(key=MIN_PROB_KEY),
             "stop": ctx.conf(key=STOP_INDICATORS_KEY)
         },
         headers={
             "Authorization": f"Bearer {ctx.conf(key=GPT3_API_KEY)}"
         }).json()
     logger.info(result)
     ctx[rawio.prop_out] = result["choices"][0]["text"]
Ejemplo n.º 14
0
def sync_ros_properties(ctx: rs.ContextWrapper):
    """
    State that creates a ROS2-Node, registers all Ros2SubProperties and Ros2PubProperties in ROS2 and keeps them synced
    """
    global global_prop_set, global_node

    # check for ROS2 availability
    if not ROS2_AVAILABLE:
        logger.error(
            "ROS2 is not available, therefore all ROS2-Properties "
            "will be just normal properties without connection to ROS2!")
        return rs.Delete()

    # get config stuff
    node_name = ctx.conf(key=NODE_NAME_CONFIG_KEY)
    if not node_name:
        logger.error(
            f"{NODE_NAME_CONFIG_KEY} is not set. Shutting down ravestate_ros2")
        return rs.Delete()
    spin_frequency = ctx.conf(key=SPIN_FREQUENCY_CONFIG_KEY)
    if spin_frequency is None or spin_frequency < 0:
        logger.error(
            f"{SPIN_FREQUENCY_CONFIG_KEY} is not set or less than 0. Shutting down ravestate_ros2"
        )
        return rs.Delete()
    if spin_frequency == 0:
        spin_sleep_time = 0
    else:
        spin_sleep_time = 1 / spin_frequency

    # init ROS
    if not rclpy.ok():
        rclpy.init()
    if not global_node:
        global_node = rclpy.create_node(node_name)

    global global_prop_set
    # current_props: hash -> subscription/publisher
    current_props: Dict = dict()

    # ROS-Context Sync Loop
    while not ctx.shutting_down():
        # remove deleted props
        removed_props = current_props.keys() - global_prop_set
        for prop_hash in removed_props:
            item = current_props[prop_hash]
            if isinstance(item, rclpy.subscription.Subscription):
                global_node.destroy_subscription(item)
            elif isinstance(item, rclpy.publisher.Publisher):
                global_node.destroy_publisher(item)
            elif isinstance(item, rclpy.client.Client):
                global_node.destroy_client(item)
            current_props.pop(prop_hash)

        # add new props
        new_props = global_prop_set - current_props.keys()
        for prop in new_props:
            # register subscribers in ROS
            if isinstance(prop, Ros2SubProperty):
                # register in context
                @rs.receptor(ctx_wrap=ctx, write=prop.id())
                def ros_to_ctx_callback(ctx, msg, prop_name: str):
                    ctx[prop_name] = msg

                prop.ros_to_ctx_callback = ros_to_ctx_callback
                prop.subscription = global_node.create_subscription(
                    prop.msg_type, prop.topic, prop.ros_subscription_callback)
                current_props[prop.__hash__()] = prop.subscription
            # register publishers in ROS
            if isinstance(prop, Ros2PubProperty):
                prop.publisher = global_node.create_publisher(
                    prop.msg_type, prop.topic)
                current_props[prop.__hash__()] = prop.publisher
            # register clients in ROS
            if isinstance(prop, Ros2CallProperty):
                prop.client = global_node.create_client(
                    prop.service_type, prop.service_name)
                current_props[prop.__hash__()] = prop.client

            # replace prop with hash in global_props
            global_prop_set.remove(prop)
            global_prop_set.add(prop.__hash__())

        # spin once
        rclpy.spin_once(global_node, timeout_sec=0)
        time.sleep(spin_sleep_time)

    global_node.destroy_node()
    rclpy.shutdown()
Ejemplo n.º 15
0
 def is_happy(ctx: rs.ContextWrapper):
     if random.random() < ctx.conf(key=HAPPY_PROB_KEY):
         logger.debug(f"Emitting {sig_happy.name}")
         return rs.Emit()
     return rs.Resign()
Ejemplo n.º 16
0
def telegram_run(ctx: rs.ContextWrapper):
    """
    Starts up the telegram bot and adds a handler to write incoming messages to rawio:in
    """
    @rs.receptor(ctx_wrap=ctx, write=rawio.prop_in)
    def text_receptor(ctx: rs.ContextWrapper, message_text: str):
        """
        Writes the message_text to rawio:in
        """
        ctx[rawio.prop_in] = message_text

    @rs.receptor(ctx_wrap=ctx, write=rawio.prop_pic_in)
    def photo_receptor(ctx: rs.ContextWrapper, photo_path):
        """
        Handles photo messages, write to rawio:pic_in
        """
        ctx[rawio.prop_pic_in] = photo_path

    @rs.receptor(ctx_wrap=ctx, write=interloc.prop_all)
    def push_telegram_interloc(ctx: rs.ContextWrapper, telegram_node: Node,
                               name: str):
        """
        Push the telegram_node into interloc:all:name
        """
        if ctx.push(parent_property_or_path=interloc.prop_all,
                    child=rs.Property(name=name, default_value=telegram_node)):
            logger.debug(f"Pushed {telegram_node} to interloc:all")

    def make_sure_effective_user_exists(update: Update):
        """
        Retrieves scientio Node of User if it exists, otherwise creates it in the scientio session
        Calls the push_telegram_interloc receptor to push the scientio node into interloc:all
        Adds the User to the set of active_users and the chat to the set of active_chats
        """
        active_chats[update.effective_chat.id] = (Timestamp(), None)
        if update.effective_user.id in active_users:
            active_users[update.effective_user.id].add(
                update.effective_chat.id)
        else:
            # set up scientio
            if ontology.initialized.wait():
                sess: Session = ontology.get_session()
                onto: Ontology = ontology.get_ontology()

                # create scientio Node of type TelegramPerson
                query = Node(metatype=onto.get_type("TelegramPerson"))
                prop_dict = {'telegram_id': update.effective_user.id}
                if update.effective_user.username:
                    prop_dict['name'] = update.effective_user.username
                if update.effective_user.full_name:
                    prop_dict['full_name'] = update.effective_user.full_name
                query.set_properties(prop_dict)

                node_list = sess.retrieve(query)
                if not node_list:
                    telegram_node = sess.create(query)
                    logger.info(
                        f"Created new Node in scientio session: {telegram_node}"
                    )
                elif len(node_list) == 1:
                    telegram_node = node_list[0]
                else:
                    logger.error(
                        f'Found multiple TelegramPersons that matched query: {update.message.chat_id} '
                        f'in scientio session. Cannot push node to interloc:all!'
                    )
                    return

                # push chat-Node
                push_telegram_interloc(telegram_node, update.effective_chat.id)
                active_users[update.effective_user.id] = {
                    update.effective_chat.id
                }

    def handle_text(bot: Bot, update: Update):
        """
        Handle incoming text messages
        """
        make_sure_effective_user_exists(update)
        text_receptor(update.effective_message.text)

    def handle_photo(bot: Bot, update: Update):
        """
        Handle incoming photo messages.
        """
        make_sure_effective_user_exists(update)
        photo_index = 2  # Seems like a good size index. TODO: Make configurable
        while photo_index >= len(update.effective_message.photo):
            photo_index -= 1
            if photo_index < 0:
                logger.error(
                    "Telegram photo handler was called, but no photo received!"
                )
                return
        file_descr = bot.get_file(
            update.effective_message.photo[photo_index].file_id)
        photo = requests.get(file_descr.file_path)
        file_path = mkstemp()[1]
        with open(file_path, 'wb') as file:
            file.write(photo.content)
        photo_receptor(file_path)

    def handle_input_multiprocess(bot: Bot, update: Update):
        """
        Handle incoming messages
        """
        if update.effective_chat.id not in active_chats:
            add_new_child_process(update.effective_chat.id)
        # write (bot, update) to Pipe
        active_chats[update.effective_chat.id][0].update()
        logger.info(f"INPUT: {update.effective_message.text}")
        active_chats[update.effective_chat.id][1].send((bot, update))
        # send typing symbol
        bot.send_chat_action(chat_id=update.effective_chat.id,
                             action=ChatAction.TYPING)

    def add_new_child_process(chat_id):
        """
        Adds the chat of the incoming message to the set of active_chats
        Creates new Ravestate Context in new Process for the new chat and
        sets up a bidirectional Pipe for communication between Master and Child Processes
        """
        # start method has to be 'spawn'
        mp_context = mp.get_context('spawn')
        # Pipe to communicate between Master Process and all children
        parent_conn, child_conn = mp.Pipe()
        # create commandline args for child config file
        args = []
        child_config_paths_list = ctx.conf(key=CHILD_FILES_CONFIG_KEY)
        for child_config_path in child_config_paths_list:
            args += ['-f', child_config_path]
        # set up new Process and override child_conn with the Pipe-Connection
        p = mp_context.Process(target=rs.create_and_run_context,
                               args=(*args, ),
                               kwargs={
                                   'runtime_overrides':
                                   [(MODULE_NAME, CHILD_CONN_CONFIG_KEY,
                                     child_conn)]
                               })
        p.start()
        active_chats[chat_id] = (Timestamp(), parent_conn)

    def error(bot: Bot, update: Update, error: TelegramError):
        """
        Log Errors caused by Updates.
        """
        logger.warning(
            f'Update {update.effective_message} caused error {error.message}')

    def _manage_children(updater):
        """
        Receive messages from children via Pipe and then send them to corresponding Telegram Chat.
        Remove chats when they get older than the chat lifetime.
        :param updater: The Updater of the telegram-Bot
        """
        chat_lifetime = ctx.conf(
            key=CHAT_LIFETIME) * 60  # conversion from minutes to seconds
        while not ctx.shutting_down():
            removable_chats = set()
            removable_users = set()
            # wait for children to write to Pipe and then send message to chat
            tick_interval = 1. / ctx.conf(mod=rs.CORE_MODULE_NAME,
                                          key=rs.TICK_RATE_CONFIG_KEY)
            time.sleep(tick_interval)
            for chat_id, (last_msg_timestamp,
                          parent_pipe) in active_chats.items():
                if parent_pipe.poll():
                    try:
                        msg = parent_pipe.recv()
                        if isinstance(msg, str):
                            logger.info(f"OUTPUT: {msg}")
                            updater.bot.send_message(chat_id=chat_id, text=msg)
                        else:
                            logger.error(
                                f'Tried sending non-str object as telegram message: {str(msg)}'
                            )
                    except EOFError:
                        # Child pipe was closed
                        parent_pipe.close()
                        removable_chats.add(chat_id)
                        continue
                # remove chat from active_chats if inactive for too long
                if last_msg_timestamp.age() > chat_lifetime:
                    parent_pipe.close()
                    removable_chats.add(chat_id)

            for chat_id in removable_chats:
                active_chats.pop(chat_id)
                for user_id, chat_ids in active_users.items():
                    # remove chat from chats that the user is part of
                    chat_ids.discard(chat_id)
                    if len(chat_ids) == 0:
                        # user is no longer part of any active chats
                        removable_users.add(user_id)
            for user_id in removable_users:
                active_users.pop(user_id)

    def _bootstrap_telegram_master():
        """
        Handle TelegramIO as the Master Process.
        Start the bot, and handle incoming telegram messages.
        """
        token = ctx.conf(key=TOKEN_CONFIG_KEY)
        if not token:
            logger.error(
                f'{TOKEN_CONFIG_KEY} is not set. Shutting down telegramio')
            return rs.Delete()
        child_config_paths_list = ctx.conf(key=CHILD_FILES_CONFIG_KEY)
        if not ctx.conf(key=ALL_IN_ONE_CONTEXT_CONFIG_KEY) and (
                not child_config_paths_list
                or not isinstance(child_config_paths_list, list) or not all(
                    os.path.isfile(child_config_path)
                    for child_config_path in child_config_paths_list)):
            logger.error(
                f'{CHILD_FILES_CONFIG_KEY} is not set (correctly). Shutting down telegramio'
            )
            return rs.Delete()

        updater: Updater = Updater(token)
        # Get the dispatcher to register handlers
        dispatcher: Dispatcher = updater.dispatcher
        if ctx.conf(key=ALL_IN_ONE_CONTEXT_CONFIG_KEY):
            # handle noncommand-messages with the matching handler
            dispatcher.add_handler(MessageHandler(Filters.text, handle_text))
            dispatcher.add_handler(MessageHandler(Filters.photo, handle_photo))
        else:
            dispatcher.add_handler(
                MessageHandler(Filters.text | Filters.photo,
                               handle_input_multiprocess))
        # log all errors
        dispatcher.add_error_handler(error)
        # Start the Bot
        updater.start_polling()  # non blocking

        if not ctx.conf(key=ALL_IN_ONE_CONTEXT_CONFIG_KEY):
            _manage_children(updater)

    def _bootstrap_telegram_child():
        """
        Handle TelegramIO as a Child Process.
        Listen to Pipe and handle incoming texts and photos.
        """
        try:
            while not ctx.shutting_down():
                # receive Bot,Update for telegram chat
                bot, update = child_conn.recv()  # blocking
                if update.effective_message.photo:
                    handle_photo(bot, update)
                elif update.effective_message.text:
                    if update.effective_message.text.strip().lower(
                    ) in verbaliser.get_phrase_list("farewells"):
                        send_on_telegram(
                            ctx, verbaliser.get_random_phrase("farewells"))
                        logger.info("Shutting down child process")
                        ctx.shutdown()
                    handle_text(bot, update)
                else:
                    logger.error(
                        f"{MODULE_NAME} received an update it cannot handle.")
        except EOFError:
            # Pipe was closed -> Parent was killed or parent has closed the pipe
            logger.info(
                "Pipe was closed, therefore the telegram-child will shut down."
            )
            ctx.shutdown()

    child_conn = ctx.conf(key=CHILD_CONN_CONFIG_KEY)
    is_master_process = child_conn is None
    if is_master_process:
        return _bootstrap_telegram_master()
    else:
        _bootstrap_telegram_child()
Ejemplo n.º 17
0
 def is_affectionate(ctx: rs.ContextWrapper):
     if any(l in ctx[nlp.prop_lemmas] for l in AFFECTIONATE_LIST) and \
             random.random() < ctx.conf(key=AFFECTIONATE_PROB_KEY):
         logger.debug(f"Emitting {sig_affectionate.name}")
         return rs.Emit()
     return rs.Resign()
Ejemplo n.º 18
0
def sync_ros_properties(ctx: rs.ContextWrapper):
    """
    State that creates a ROS1-Node, registers all Ros1SubProperties and Ros1PubProperties in ROS1 and keeps them synced
    """
    global global_prop_set, global_node

    # check for ROS1 availability
    if not ROS1_AVAILABLE:
        logger.error(
            "ROS1 is not available, therefore all ROS1-Properties "
            "will be just normal properties without connection to ROS1!")
        return rs.Delete()

    # get config stuff
    node_name = ctx.conf(key=NODE_NAME_CONFIG_KEY)
    if not node_name:
        logger.error(
            f"{NODE_NAME_CONFIG_KEY} is not set. Shutting down ravestate_ros1")
        return rs.Delete()
    spin_frequency = ctx.conf(key=SPIN_FREQUENCY_CONFIG_KEY)
    if spin_frequency is None or spin_frequency < 0:
        logger.error(
            f"{SPIN_FREQUENCY_CONFIG_KEY} is not set or less than 0. Shutting down ravestate_ros1"
        )
        return rs.Delete()
    if spin_frequency == 0:
        spin_sleep_time = 0
    else:
        spin_sleep_time = 1 / spin_frequency

    # Use same node_name if ROS1 was already initialized (i.e. by importing pyroboy)
    if rospy.get_name():
        node_name = rospy.get_name()[1:]  # cut off leading /
    # init ROS1
    #rospy.init_node(node_name, disable_signals=True)
    global global_prop_set
    # current_props: hash -> Subscriber/Publisher/ServiceProxy
    current_props: Dict = dict()

    # ROS1-Context Sync Loop
    while not ctx.shutting_down() and not rospy.core.is_shutdown():
        # remove deleted props
        removed_props = current_props.keys() - global_prop_set
        for prop_hash in removed_props:
            item = current_props[prop_hash]
            item.unregister()
            current_props.pop(prop_hash)

        # add new props
        new_props = global_prop_set - current_props.keys()
        for prop in new_props:
            # register subscribers in ROS1
            if isinstance(prop, Ros1SubProperty):
                # register in context
                @rs.receptor(ctx_wrap=ctx, write=prop.id())
                def ros_to_ctx_callback(ctx, msg, prop_name: str):
                    ctx[prop_name] = msg

                prop.ros_to_ctx_callback = ros_to_ctx_callback
                prop.subscriber = rospy.Subscriber(
                    prop.topic, prop.msg_type, prop.ros_subscription_callback)
                current_props[prop.__hash__()] = prop.subscriber
            # register publishers in ROS1
            if isinstance(prop, Ros1PubProperty):
                prop.publisher = rospy.Publisher(prop.topic,
                                                 prop.msg_type,
                                                 queue_size=prop.queue_size)
                current_props[prop.__hash__()] = prop.publisher
            # register clients in ROS1
            if isinstance(prop, Ros1CallProperty):
                prop.client = rospy.ServiceProxy(prop.service_name,
                                                 prop.service_type)
                current_props[prop.__hash__()] = prop.client

            # replace prop with hash in global_props
            global_prop_set.remove(prop)
            global_prop_set.add(prop.__hash__())

        rospy.rostime.wallsleep(spin_sleep_time)

    rospy.signal_shutdown("ravestate_ros1 is shutting down")
Ejemplo n.º 19
0
 def is_surprised(ctx: rs.ContextWrapper):
     if random.random() < ctx.conf(key=SURPRISED_PROB_KEY):
         logger.debug(f"Emitting {sig_surprise.name}")
         return rs.Emit()
     return rs.Resign()