BehaviorTree.CPP
BehaviorTree.CPP copied to clipboard
Type mismatch in Blackboard::set() function
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.
I should look into this. Thanks for reporting
fix added. thanks!
@facontidavide you mentioned you fixed this, could this ticket be closed?
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.
I will investigate.
@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.
no idea.
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.
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.