Skip to content

Problems with order of subtrees #168

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

Closed
ninamwa opened this issue Apr 2, 2020 · 12 comments
Closed

Problems with order of subtrees #168

ninamwa opened this issue Apr 2, 2020 · 12 comments
Assignees
Labels
bug Something isn't working

Comments

@ninamwa
Copy link

ninamwa commented Apr 2, 2020

Hi. I am trying to use this library to build and execute my BT, but i have met a problem while creating my tree.
My tree is as following (NB: I omitted the "FindObject" subtree, to limit the amount of code).

`

<BehaviorTree ID="MainTree">
    <Sequence name="main_sequence">
        <SubTree ID="FindObject"/>
        <SubTree ID="HandleObject"/>
    </Sequence>
</BehaviorTree> 

<BehaviorTree ID="HandleObject">
    <Sequence name="handle_object_sequence">
        <Sequence name="pick_object">
            <SubTree ID="MoveToFrame" frame="drive_frame"/>
            <CloseGripper/>
        </Sequence>
        <Sequence name="leave_object">
            <Fallback name="find_empty_frame">
               <Fallback name="check_empty_frame">
                   <FrameEmpty check_frame="frame1"/>
                   <FrameEmpty check_frame="frame2"/>
                   <FrameEmpty check_frame="frame3"/>
               </Fallback>
               <ForceFailure name="force_failure">
                   <OpenGripper/>
               </ForceFailure>
            </Fallback>
            <SubTree ID="MoveToFrame" frame="{empty_frame}"/>
            <OpenGripper/>
            <SubTree ID="MoveToFrame" frame="drive_frame"/>
        </Sequence>
    </Sequence>
</BehaviorTree>

<BehaviorTree ID="MoveToFrame">
    <Sequence name="main_move_to_frame">
        <PlanManipulatorPath plan_to_frame="{frame}"/>
        <MoveManipulator path="{path}" move_to_frame="{move_to_frame}"/>
    </Sequence>
</BehaviorTree>

`

When I try to run this i get the error message:
[behavior_tree_node-1] what(): Blackboard::get() error. Missing key [node]

The problem seems to be the lines:
<SubTree ID="MoveToFrame" frame="drive_frame"/> <CloseGripper/>
in the "Handle Object" subtree.
If I change the order of these two lines, hence: close gripper before the subtree, everything works as expected. I have seen this problem in my other subtrees as well. If the subtree is the first element inside a sequence, it is not working.
For example: my MainTree is not working either (for the same reason I guess). I needed to set main_tree_to_execute to HandleObject to find out the problem described above.

Could anyone tell me why this happens, and if there is something i have misunderstood?
I do not want to change the order of the nodes, as i need the manipulator to "MoveToFrame" before it closes...

Thanks!

@facontidavide
Copy link
Collaborator

https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/include/behaviortree_cpp_v3/blackboard.h#L110

As you can see the error message is clearly telling you that you are trying to access a key called node. Are you absolutely sure that you copied the exact error message?

But I do not see anything in your code called "node". Could the error be in your C++ code?
Are you absolutely sure that you copied the exact error message?

It is also very weird that executing earlier the solves the problem because it is not writing (apparently) in any port.

Something weird that is noticed:

        <PlanManipulatorPath plan_to_frame="{frame}"/>
        <MoveManipulator path="{path}" move_to_frame="{move_to_frame}"/>

I am guessing that plan_to_frame is an OutputPort a,d move_to_frame is an input port.
Is that correct? And I do not see remapped the move_to_frame, neither path... that means that, if, they are input, they are empty.

@facontidavide
Copy link
Collaborator

In general... I can not see all the remapping, I don't expect input ports to work properly.

If is Ok for a port to have an empty input, use the non-throwing version of get() and decide what to do accordingly.

@ninamwa
Copy link
Author

ninamwa commented Apr 17, 2020

Hi. My problems were solved when I put everything into the same tree, and stopped using subtrees (but I would like to use them, as it simplifies my code a lot). I am aware of some problems with the ports, that is fixed now. But to show a simpler example:

<root main_tree_to_execute="TestTree">
    <BehaviorTree ID="TestTree2">
        <Sequence name="sequence">
            <CloseGripper/>
        </Sequence>
    </BehaviorTree> 

    <BehaviorTree ID="TestTree">
        <Sequence name="main_sequence">
            <SubTree ID="TestTree2"/>
            <OpenGripper/>
        </Sequence>
    </BehaviorTree> 
</root>

This gives this output in the terminal:

[INFO] [launch]: All log files can be found below /home/ninamwa/.ros/log/2020-04-17-08-59-31-434150-ninamwa-X550JX-20991
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [gripper_node.py-1]: process started with pid [21009]
[INFO] [behavior_tree_node-2]: process started with pid [21010]
[behavior_tree_node-2] [INFO] [behavior_tree_node]: Initialize node!
[behavior_tree_node-2] [INFO] [behavior_tree_node]: behavior_tree_node
[behavior_tree_node-2] terminate called after throwing an instance of 'BT::RuntimeError'
[behavior_tree_node-2] what(): Blackboard::get() error. Missing key [node]
[ERROR] [behavior_tree_node-2]: process has died [pid 21010, exit code -6, cmd '/home/ninamwa/kuka-ELO/install/kmr_behaviortree/lib/kmr_behaviortree/behavior_tree_node --ros-args -r __node:=behavior_tree_node --params-file /tmp/launch_params_cmrtk511 --params-file /home/ninamwa/kuka-ELO/install/kmr_behaviortree/share/kmr_behaviortree/param/param.yaml'].

As you can see, it is the same error message as previously.
The error might be in the c++ code, but i think that is weird as the tree below works just fine:

<root main_tree_to_execute="TestTree">
   <BehaviorTree ID="TestTree">
        <Sequence name="main_sequence">
            <CloseGripper/>
            <OpenGripper/>
        </Sequence>
    </BehaviorTree> 
</root>

What I said earlier about executing something before the subtree works was wrong. The same problem occurs then as well, only at a later time.
The error seems to occur inside the instantiateTree(blackboard) function (https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/include/behaviortree_cpp_v3/xml_parsing.h)

@facontidavide
Copy link
Collaborator

I just tested it with the dummy implementation here:

https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/sample_nodes/dummy_nodes.h#L72-L73

And I insist that the problem must be in your C++ code... unless you are using an old version of BehaviorTree.CPP.

Which version are you using? Remember that I am not maintaining version 2 anymore.

The best I can offer you is to have a look at your C++ code to see if I spot something weird, but otherwise, I will close this issue.

@ninamwa
Copy link
Author

ninamwa commented Apr 17, 2020

My project folder is named behaviortree_cpp_v3, so i guess it is the correct version.

My code can be found at: https://github.com/ninamwa/kmriiwa_ws/tree/eloquent/kmr_behaviortree
As I am using ROS I have reused some of the implementation from ROS2 Navigation2 (the behavior_tree_engine.cpp and node_utils.cpp)
The behavior tree used is the test.xml, and i am running the launch file bt.launch.py.
The C++ code is found in src/behavior_tree_node.cpp

As I said, the code works for me if I use only one behaviortree, with no subtrees, so there is not a big problem for me if this is not solved, but it would be interesting to know what is wrong :-)

@facontidavide
Copy link
Collaborator

This problem is really bothering me. I will try to look into it more closely in the next days.

@facontidavide facontidavide self-assigned this Apr 17, 2020
@facontidavide facontidavide added the bug Something isn't working label Apr 17, 2020
@yimenghou
Copy link

yimenghou commented May 10, 2020

Hi facontidavide, I don't know if I have the same problem with ninamwa.
I'm using ROS2 eloquent, ubuntu 18.04.
I try to set some variables into blackboard by, for example
blackboard_->set<double>("speed", 1.23);

My bt xml looks like this:

<root main_tree_to_execute = "MainTree" >

<BehaviorTree ID="MainTree">
    <Parallel name="parallel1" threshold="2">
      <Action ID="EatApple" />
      <Action ID="EatBanana" />
    </Parallel>
  </BehaviorTree>

</root>

In this case, the bt works perfectly fine, I can access the 'speed' from both actions.

But if I revise my bt xml like this, where I added a subtree:

<root main_tree_to_execute = "MainTree" >

 <BehaviorTree ID="MainTree">
    <SubTree ID="sub_tree"/>
  </BehaviorTree>

  <BehaviorTree ID="sub_tree">
    <Parallel name="parallel1" threshold="2">
      <Action ID="EatApple" />
      <Action ID="EatBanana" />
    </Parallel>
  </BehaviorTree>

</root>

In this case, I cannot get the 'speed' variable from the blackboard by:
double speed = config().blackboard->get<double>("speed");

It seems like a scope problem.
I don't know if I use it wrong (you make this by design) or this is a bug.

Thanks!!

@facontidavide
Copy link
Collaborator

@yimenghou
This is exactly what it should happen, it is not an error but a feature.

Please read this https://www.behaviortree.dev/tutorial_06_subtree_ports/

Your subtree has its own isolated blavkoboard, separated from the parent.

Furthermore, using the blackboard is strongly discouraged, you shous use Input/Outpu ports instead.

@facontidavide
Copy link
Collaborator

@ninamwa, if you remember, I said that there was something fishy about your error that I could not understand from the information you provided.

Now that I see the example of @yimenghou , I am realizing that maybe you are affected by the same error (using blackboard directly instead of using ports with proper remapping).

Could it be?

@yimenghou
Copy link

I see. Thank you :)@facontidavide facontidavide

In my case,
I have some global variables that may be potentially used by the main tree and all it sub trees. If I use input/output ports, that may be too verbose to write. This is why I want to use a blackboard. In this case. Do you have any suggestions instead of ports?

@facontidavide
Copy link
Collaborator

no, I created ports to prevent users from doing what you are doing.

A "solution" to continue doing what you are doing (the wrong thing) is to have what I call a "transparent Subtree", i.e. a subtree that share the same blackboard of the parent, instead o having its own.

I will add it soon.

@facontidavide
Copy link
Collaborator

facontidavide commented May 13, 2020

UPDATE:

I implemented this:

    <SubTree ID="TheSubTree" __shared_blackboard="true"/>

But please, remember that using the config()->blackboard without the ports is strongly discouraged and it is not the intended way to use the library.

The intended usage is clearly described in the tutorials.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants