Skip to content

Commit 7d0219e

Browse files
committed
Convert vector to vector<Any> before placing on the blackboard
Also update checks to allow mismatch when a port was declared as a vector<T> and we have an input port that takes it in as a vector<Any>
1 parent e3b0cd7 commit 7d0219e

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

include/behaviortree_cpp/blackboard.h

+21-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <memory>
55
#include <unordered_map>
66
#include <mutex>
7+
#include <regex>
78

89
#include "behaviortree_cpp/basic_types.h"
910
#include "behaviortree_cpp/contrib/json.hpp"
@@ -25,6 +26,19 @@ struct StampedValue
2526
Timestamp stamp;
2627
};
2728

29+
// Helper trait to check if templated type is a std::vector
30+
template <typename T>
31+
struct is_vector : std::false_type {};
32+
33+
template <typename T, typename A>
34+
struct is_vector<std::vector<T, A>> : std::true_type {};
35+
36+
// Helper function to check if BT::Any object holds a std::vector
37+
inline bool isVector(std::string type_name)
38+
{
39+
return std::regex_match(type_name, std::regex(R"(^std::vector<.*>$)"));
40+
}
41+
2842
/**
2943
* @brief The Blackboard is the mechanism used by BehaviorTrees to exchange
3044
* typed data.
@@ -257,8 +271,14 @@ inline void Blackboard::set(const std::string& key, const T& value)
257271

258272
std::type_index previous_type = entry.info.type();
259273

274+
// Allow mismatch if going from vector -> vector<Any>.
275+
auto prev_type_demangled = BT::demangle(entry.value.type());
276+
bool previous_is_vector = BT::isVector(prev_type_demangled);
277+
bool new_is_vector_any = new_value.type() == typeid(std::vector<Any>);
278+
260279
// check type mismatch
261-
if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
280+
if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type() &&
281+
!(previous_is_vector && new_is_vector_any))
262282
{
263283
bool mismatching = true;
264284
if(std::is_constructible<StringView, T>::value)

include/behaviortree_cpp/tree_node.h

+13-8
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@
3030

3131
namespace BT
3232
{
33-
// Helper trait to check if a type is a std::vector
34-
template <typename T>
35-
struct is_vector : std::false_type {};
36-
37-
template <typename T, typename A>
38-
struct is_vector<std::vector<T, A>> : std::true_type {};
39-
4033
/// This information is used mostly by the XMLParser.
4134
struct TreeNodeManifest
4235
{
@@ -619,7 +612,19 @@ inline Result TreeNode::setOutput(const std::string& key, const T& value)
619612
}
620613

621614
remapped_key = stripBlackboardPointer(remapped_key);
622-
config().blackboard->set(static_cast<std::string>(remapped_key), value);
615+
616+
if constexpr(is_vector<T>::value && !std::is_same_v<T, std::vector<Any>>)
617+
{
618+
// If the object is a vector but not a vector<Any>, convert it to vector<Any> before placing it on the blackboard.
619+
auto any_vec = std::vector<Any>();
620+
std::transform(value.begin(), value.end(), std::back_inserter(any_vec),
621+
[](const auto &element) { return BT::Any(element); });
622+
config().blackboard->set(static_cast<std::string>(remapped_key), any_vec);
623+
}
624+
else
625+
{
626+
config().blackboard->set(static_cast<std::string>(remapped_key), value);
627+
}
623628

624629
return {};
625630
}

src/blackboard.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,18 @@ std::shared_ptr<Blackboard::Entry> Blackboard::createEntryImpl(const std::string
217217
if(storage_it != storage_.end())
218218
{
219219
const auto& prev_info = storage_it->second->info;
220+
auto prev_type_demangled = BT::demangle(prev_info.type());
221+
// Allow mismatch if going from vector -> vector<Any>.
222+
bool previous_is_vector = BT::isVector(prev_type_demangled);
223+
bool new_is_vector_any = info.type() == typeid(std::vector<Any>);
224+
220225
if(prev_info.type() != info.type() && prev_info.isStronglyTyped() &&
221-
info.isStronglyTyped())
226+
info.isStronglyTyped() && !(previous_is_vector && new_is_vector_any))
222227
{
223228
auto msg = StrCat("Blackboard entry [", key,
224229
"]: once declared, the type of a port"
225230
" shall not change. Previously declared type [",
226-
BT::demangle(prev_info.type()), "], current type [",
231+
prev_type_demangled, "], current type [",
227232
BT::demangle(info.type()), "]");
228233

229234
throw LogicError(msg);

src/xml_parsing.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -786,10 +786,15 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
786786

787787
// special case related to convertFromString
788788
bool const string_input = (prev_info->type() == typeid(std::string));
789-
// special case related to unwrapping vector<Any> objects.
789+
// special case related to unwrapping vector<Any> -> vector<T> objects.
790790
bool const vec_any_input = (prev_info->type() == typeid(std::vector<Any>));
791+
// special case related to wrapping vector<T> -> vector<Any> objects.
792+
auto prev_type_demangled = demangle(prev_info->type());
793+
bool previous_is_vector = BT::isVector(prev_type_demangled);
794+
bool new_is_vector_any = port_info.type() == typeid(std::vector<Any>);
791795

792-
if(port_type_mismatch && !string_input && !vec_any_input)
796+
if(port_type_mismatch && !string_input &&
797+
!vec_any_input & !(previous_is_vector && new_is_vector_any))
793798
{
794799
blackboard->debugMessage();
795800

0 commit comments

Comments
 (0)