BehaviorTree.CPP icon indicating copy to clipboard operation
BehaviorTree.CPP copied to clipboard

Type mismatch in Blackboard::set() function

Open ozgudum opened this issue 3 years ago • 8 comments

I am getting this error when I try to set navigation goal in ROS2 navigation2 stack:

Action server failed while executing action callback: "Blackboard::set() failed: once declared, the type of a port shall not change. Declared type [geometry_msgs::msg::PoseStamped_<std::_1::allocator >] != current type [geometry_msgs::msg::PoseStamped<std::__1::allocator >]"

It was weird because it's complaining about port type mismatch but demangled types seems to be identical. Then, I traced the error and it seems to occur in the line below in set() function in blackboard.h

if( locked_type && locked_type != &typeid(T) && locked_type != &temp.type() )

I found out that both returned types are same as locked_type:

demangle(locked_type) -> geometry_msgs::msg::PoseStamped_<std::_1::allocator > demangle(typeid(T)) -> geometry_msgs::msg::PoseStamped<std::_1::allocator > demangle(temp.type()) -> geometry_msgs::msg::PoseStamped<std::__1::allocator >

but pointers to types are different:

locked_type -> 0x101489060 &typeid(T) -> 0x120fdc3a0 &temp.type()-> 0x120fdc3a0

Interestingly, address mismatch doesn't occur for all types. I wonder why comparison of type addresses was preferred over comparison of type values directly?

If I change the line as below to compare type values directly, I no longer get type mismatch error.

if( locked_type && *locked_type != typeid(T) && *locked_type != temp.type() )

If this change makes sense, I can create a pull request for this fix.

ozgudum avatar Sep 09 '20 16:09 ozgudum

I should look into this. Thanks for reporting

facontidavide avatar Sep 16 '20 10:09 facontidavide

fix added. thanks!

facontidavide avatar Feb 03 '21 21:02 facontidavide

@facontidavide you mentioned you fixed this, could this ticket be closed?

SteveMacenski avatar Mar 24 '21 22:03 SteveMacenski

Hi, it looks like that I have a very similar problem. I'm using BehaviorTree.cpp 3.7.0 Interestingly, this only happens when subtrees are involved.

See this example XML.

    <BehaviorTree ID="TestTree">
        <Control ID="Sequence">
            <Action ID="DriveToPose" in_goal="{to_pose}"/>
        </Control ID="Sequence">
    </BehaviorTree>

    <BehaviorTree ID="Main">
        <Control ID="Sequence">
            <Action ID="GetPose" out_pose="{pose}"/>
            <Action ID="DriveToPose" in_goal="{pose}"/>
        </Control ID="Sequence">
    </BehaviorTree>

    <BehaviorTree ID="MainWithSubtree">
        <Control ID="Sequence">
            <Action ID="GetPose" out_pose="{pose}"/>
            <SubTree ID="TestTree" to_pose="pose"/>
        </Control ID="Sequence">
    </BehaviorTree>

All variables are of type geometry_msgs::msg::PoseStamped. The trees Main and MainWithSubtree are supposed to be equivalent. However, although Main works fine, MainWithSubtree produces the error mentioned in the first post.

The same problem also happens if I use a SubTreePlus node.

alsora avatar Sep 14 '22 12:09 alsora

I will investigate.

facontidavide avatar Sep 14 '22 13:09 facontidavide

@facontidavide FYI, I think I found why this happens in my code. I'm using a custom routine to load plugins rather than calling registerFromPlugin() method.

  • If I use this (which is equivalent to what registerFromPlugin() does) IT WORKS
    BT::SharedLibrary loader;
    loader.load(library_name);
    using register_func_t = void (*)(BT::BehaviorTreeFactory&);
    auto func = reinterpret_cast<register_func_t>(loader.getSymbol(BT::PLUGIN_SYMBOL));
    func(factory);
  • If I use this version IT DOES NOT WORK
    auto library = std::make_shared<rcpputils::SharedLibrary>(library_name);
    using register_func_t = void (*)(BT::BehaviorTreeFactory&);
    auto func = reinterpret_cast<register_func_t>(library->get_symbol(BT::PLUGIN_SYMBOL));
    func(factory);

Note how in one case I use the BT::SharedLibrary class, while in the other I'm using the ROS 2 rcpputils::SharedLibrary class. I have no idea why this happens, but from the tests I did so far, doing this change seems to fix the problem.

alsora avatar Sep 14 '22 16:09 alsora

no idea.

facontidavide avatar Sep 14 '22 19:09 facontidavide

Thanks to @matt-cross, we think that we know what causes the problem. Citing his words: the commit https://github.com/BehaviorTree/BehaviorTree.CPP/commit/4428f00ec6315a71b53fdf2cfc9c596bfa7a04c3 fixed one of the two comparisons between port types present in the codebase. There's another instance that still compares using addresses: https://github.com/BehaviorTree/BehaviorTree.CPP/blob/3.7.0/src/blackboard.cpp#L25

The reason why it works with the BT::SharedLibrary but not with the rcpputils::SharedLibrary is because the former uses the RTLD_GLOBAL flag https://github.com/BehaviorTree/BehaviorTree.CPP/blob/3.7.0/src/shared_library_UNIX.cpp#L23 which appears to solve the issue in some situations (like the one I posted above).

Is there a reason why the fix mentioned above was not applied to all types comparisons? This should be the correct approach, regardless of the flags used to load the library.

alsora avatar Sep 23 '22 18:09 alsora

branch v3.8 fixed (master should be ok) ! @alsora thanks for finding the solution and sorry if it took me so long to come back to you.

facontidavide avatar Nov 22 '22 22:11 facontidavide