Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get blackboard variable from a Subscriber defined in a separate file #222

Open
SyZbidi opened this issue Jun 12, 2024 · 2 comments
Open

Comments

@SyZbidi
Copy link

SyZbidi commented Jun 12, 2024

Hello,

I created an Image subscriber that writes the image it receives on a blackboard, with the intent to add it at the top of the tree so that every behavior that would need it has access to its blackboard.

I defined a small root tree with the image_subscriber in it at first

import sys

import py_trees
import py_trees.console as console
import py_trees_ros.trees
import rclpy

from .behaviors import ImageSubscriber


def root_create_root() -> py_trees.behaviour.Behaviour:
    """
    Create a tree for a 'Scan' work that moves the robot along waypoints and takes images.

    Returns
    -------
        the root of the tree

    """
    root = py_trees.composites.Parallel(
        name="Damage Inspection Process",
        policy=py_trees.common.ParallelPolicy.SuccessOnAll(synchronise=False),
    )
    image_subscriber = ImageSubscriber(
        name="Image Subscriber",
        topic_name="img_topic",
        qos_profile=py_trees_ros.utilities.qos_profile_unlatched(),
    )

    workpiece_info = py_trees.composites.Sequence(name="workpiece_info", memory=True)
    tb_placeholder = py_trees.timers.Timer("TB_info_placeholder", duration=1.0)

    workpiece_info.add_child(tb_placeholder)
    root.add_children([image_subscriber, workpiece_info])

    return root


def main():
    """Entry point for the root script."""
    rclpy.init(args=None)
    root = root_create_root()
    tree = py_trees_ros.trees.BehaviourTree(root=root, unicode_tree_debug=True)
    try:
        tree.setup(node_name="root_tree", timeout=15.0)
    except py_trees_ros.exceptions.TimedOutError as e:
        console.logerror(
            console.red + "failed to setup the tree, aborting [{}]".format(str(e)) + console.reset
        )
        tree.shutdown()
        rclpy.try_shutdown()
        sys.exit(1)
    except KeyboardInterrupt:
        # not a warning, nor error, usually a user-initiated shutdown
        console.logerror("tree setup interrupted")
        tree.shutdown()
        rclpy.try_shutdown()
        sys.exit(1)

    tree.tick_tock(period_ms=1000.0)

    try:
        rclpy.spin(tree.node)
    except (KeyboardInterrupt, rclpy.executors.ExternalShutdownException):
        pass
    finally:
        tree.shutdown()
        rclpy.try_shutdown()


if __name__ == "__main__":
    main()

then I import that root in my subtree and try to get the image_subscriber blackboard variable but it fails there with KeyError: '/camera_feed_image'. Here's how I'm trying to get the value of BB variable in the subtree

current_image = py_trees.blackboard.Blackboard.get(variable_name="camera_feed_image")

To be used in an action client

    get_image = py_trees_ros.actions.ActionClient(
        name="get_image",
        action_type=SaveImage,
        action_name="capture_image",
        action_goal=SaveImage.Goal(block_id=block_id, images_folder=folder, image=current_image),
    )

So I'm guessing maybe I haven't properly created the ImageSubscriber? are the keyboard variables not global in this case?

This is my ImageSubscriber behavior

import py_trees
import py_trees_ros
import rclpy
from sensor_msgs.msg import Image


class ImageSubscriber(py_trees_ros.subscribers.ToBlackboard):
    """
    Subscribe to the Image message and write an Image to the blackboard.

    Blackboard Variables:
    --------------------
        * image (:class:`sensor_msgs.msg.Image`)[w]: the raw image message

    Args:
    ----
        name: name of the behaviour
        topic_name: name of the Image topic
        qos_profile: qos profile for the subscriber

    """

    def __init__(self, name: str, topic_name: str, qos_profile: rclpy.qos.QoSProfile):
        super().__init__(
            name=name,
            topic_name=topic_name,
            topic_type=Image,
            qos_profile=qos_profile,
            blackboard_variables={"camera_feed_image": None},
            clearing_policy=py_trees.common.ClearingPolicy.NEVER,
        )

    def update(self) -> py_trees.common.Status:
        """
        Call the parent to write the Image to the blackboard.

        Returns
        -------
            py_trees.common.Status: SUCCESS if a message is written, RUNNING otherwise.

        """
        self.logger.debug("%s.update()" % self.__class__.__name__)
        status = super(ImageSubscriber, self).update()
        if status != py_trees.common.Status.RUNNING:
            self.feedback_message = "Saved Image to blackboard"
        return status

Thank you in advance for your help

@slyandsmart
Copy link

i have the same problem.

i do not know how to use a blackboard variables.

I have used the subscribers.ToBlackboard Class

    jointstates_to_blackboard = py_trees_ros.subscribers.ToBlackboard(
                                name="jointstates_to_blackboard",
                                topic_type=JointState,
                                topic_name="/joint_states",
                                qos_profile=py_trees_ros.utilities.qos_profile_unlatched(),
                                #blackboard_variables={'jointstate': None}
                                blackboard_variables={'JointStateName': 'name'}
                                )

And i see in the watcher that the variable is there but when i use

        myblackboardvar = py_trees.blackboard.Blackboard.get(variable_name='/JointStateName')

i also get the KeyError

@slyandsmart
Copy link

Here a additional picture of my usage.

image

It can be seen that the key /JointStateName is existing.
By the key method i also can get it from the blackboard but with get i get a keyError

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants