BehaviorTree/BehaviorTree.CPP

HOW-TO: How to use custom convertFromString in Node loaded as Plugin

LUGGGI opened this issue · 3 comments

Hello,

I have a Node that uses a custom type. I've created the template specialization for convertFromString for that type.

When I use the Node directly, meaning registering it in the same file with factory.registerNodeType, everything works and the type gets converted.

But when I use the Node as a plugin I get the error that the specialization is not found:

You didn't implement the template specialization of convertFromString for this type: geometry_msgs::msg::Point_<std::allocator<void> >

I tried adding the template specialization to the file where I load the plugins, but that didn't work (I already thought it wouldn't work, but didn't have any other ideas.

Does anyone know how to do this? I would really appreciate it.

I think that I know how to solve this and why it may happen. Can you create an example?

Hey! I have the same issue.

I have a plugin that uses a std::vector<bool> port:

using BT::NodeStatus;
using BT::SyncActionNode;

namespace BT {
template <>
[[nodiscard]] auto convertFromString<std::vector<bool>>(StringView str) -> std::vector<bool> {
    // We expect bools separated by semicolons
    auto parts = splitString(str, ';');

    std::vector<bool> output;
    for (auto part : parts) {
        output.push_back(convertFromString<bool>(part));
    }
    return output;
}

}  // namespace BT

template <typename T>
class MyNode : public SyncActionNode {
   public:
    MyNode(const std::string& name, const BT::NodeConfig& config) : SyncActionNode(name, config) {}

    static auto providedPorts() -> BT::PortsList {
        return {
            BT::InputPort<T>("input"),
        };
    }

    auto tick() -> NodeStatus override {
        const auto input = getInput<T>("input").value();
    }
};

BT_REGISTER_NODES(factory) {
    factory.registerNodeType<MyNode<bool>>("MyNodeBool");
    factory.registerNodeType<MyNode<std::vector<bool>>>("MyNodeBoolArray");
}

I tried

  • putting also my class declaration/definition into the BT namespace or
  • moving the convertFromString specialization into a header file and including it both in the plugin and my tree-execution executable

yet still it always complains with

You (maybe indirectly) called BT::convertFromString() for type [std::vector<bool, std::allocator<bool> >], but I can't find the template specialization.
Behavior Tree exception:The port with name "input" and value "true;false" can not be converted to std::vector<bool, std::allocator<bool> >

My tree XML is as simple as

<root BTCPP_format="4">
    <BehaviorTree ID="TestMyNodeBoolArray">
        <MyNodeBoolArray input="true;false" />
    </BehaviorTree>
</root>

Any ideas how to solve or what else to try?

I've encountered this issue when I was trying to convert an input port string into a vector of "Vector3". Anyways, the issue (I eventually found out) was that this was because I had another convertFromString() template specialization that calls the Vector3 convertFromString() function. Apparently, I needed to include the Vector3 convertFromString() function in that one. It's especially tricky since this doesn't give any compile time errors.

Not 100% sure if this is related, but I have a working implementation here using BehaviorTree.ROS2 (if that helps anyone else).