Skip to content

Commit b926ff7

Browse files
facontidavideclaude
andcommitted
Fix #1065: upgrade weakly-typed blackboard entries from subtree string remapping
When a SubTree passes a constant string literal (e.g., queue="1;2;3") to a child tree's port, the subtree remapping stores it as a plain std::string in the child blackboard without type information. Later, when a strongly-typed node like LoopDouble reads the entry, Any::cast<SharedQueue<double>>() fails because there's no conversion path from string to the expected type. Fix: in createNodeFromXML, when initializing port entries, detect when an existing blackboard entry is weakly typed but the port manifest declares a strong type. In this case, convert the string value using the port's parseString() method and upgrade the entry's type info in place. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fd40532 commit b926ff7

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

src/xml_parsing.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,31 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
929929
demangle(prev_info->type()), "] and, later type [",
930930
demangle(port_info.type()), "] was used somewhere else.");
931931
}
932+
933+
// If the existing entry is not strongly typed (e.g. set as a plain
934+
// string from subtree remapping) but the port IS strongly typed,
935+
// upgrade the entry by converting the string value. Issue #1065.
936+
if(!prev_info->isStronglyTyped() && port_info.isStronglyTyped())
937+
{
938+
auto entry = blackboard->getEntry(port_key);
939+
if(entry)
940+
{
941+
std::scoped_lock lock(entry->entry_mutex);
942+
if(!entry->value.empty() && entry->value.isString())
943+
{
944+
auto str_val = entry->value.tryCast<std::string>();
945+
if(str_val)
946+
{
947+
auto typed_val = port_info.parseString(*str_val);
948+
if(!typed_val.empty())
949+
{
950+
entry->info = port_info;
951+
entry->value = typed_val;
952+
}
953+
}
954+
}
955+
}
956+
}
932957
}
933958
else
934959
{

tests/gtest_ports.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ TEST(PortTest, GetInputDefaultValue_Issue858)
637637
}
638638
}
639639

640-
// Helper class used by Issue #969 test
640+
// Helper class used by Issue #969 and #1065 tests
641641
class CollectDoubleAction : public SyncActionNode
642642
{
643643
public:
@@ -777,3 +777,41 @@ TEST(PortTest, DefaultEmptyVector_Issue982)
777777
<< " element(s). First element: \""
778778
<< (result.empty() ? "" : result[0]) << "\"";
779779
}
780+
781+
// Issue #1065: passing a string literal like "1;2;3" through a SubTree port
782+
// to a LoopDouble node should work, but fails because the subtree remapping
783+
// stores the value as a plain std::string in the blackboard without converting
784+
// it to SharedQueue<double>.
785+
TEST(PortTest, SubtreeStringLiteralToLoopDouble_Issue1065)
786+
{
787+
// The main tree passes a string literal "1;2;3" to the subtree port "queue".
788+
// Inside the subtree, LoopDouble should parse it and iterate over the values.
789+
std::string xml_txt = R"(
790+
<root BTCPP_format="4">
791+
<BehaviorTree ID="MainTree">
792+
<SubTree ID="LoopSubTree" queue="1;2;3" />
793+
</BehaviorTree>
794+
795+
<BehaviorTree ID="LoopSubTree">
796+
<LoopDouble queue="{queue}" value="{number}">
797+
<CollectDouble value="{number}" />
798+
</LoopDouble>
799+
</BehaviorTree>
800+
</root>
801+
)";
802+
803+
std::vector<double> collected;
804+
805+
BehaviorTreeFactory factory;
806+
factory.registerNodeType<CollectDoubleAction>("CollectDouble", &collected);
807+
factory.registerBehaviorTreeFromText(xml_txt);
808+
809+
auto tree = factory.createTree("MainTree");
810+
auto status = tree.tickWhileRunning();
811+
812+
ASSERT_EQ(status, NodeStatus::SUCCESS);
813+
ASSERT_EQ(collected.size(), 3u);
814+
EXPECT_DOUBLE_EQ(collected[0], 1.0);
815+
EXPECT_DOUBLE_EQ(collected[1], 2.0);
816+
EXPECT_DOUBLE_EQ(collected[2], 3.0);
817+
}

0 commit comments

Comments
 (0)