Skip to content

Commit

Permalink
fix issue BehaviorTree#530: use convertFromString in scripting assign…
Browse files Browse the repository at this point in the history
…ments
  • Loading branch information
facontidavide committed Mar 21, 2023
1 parent 67cb978 commit e54bcb2
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 2 deletions.
30 changes: 28 additions & 2 deletions include/behaviortree_cpp/scripting/operators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ struct ExprAssignment : ExprBase
const auto& key = varname->name;

std::unique_lock entry_lock(env.vars->entryMutex());
auto any_ptr = env.vars->getAny(key);
Any* any_ptr = env.vars->getAny(key);
if( !any_ptr )
{
// variable doesn't exist, create it if using operator assign_create
Expand All @@ -379,7 +379,33 @@ struct ExprAssignment : ExprBase

if( op == assign_create || op == assign_existing )
{
value.copyInto(*any_ptr);
// special case first: string to other type
// check if we can use the StringConverter
if(value.isString() && !any_ptr->isString())
{
auto const str = value.cast<std::string>();
if(auto converter = env.vars->portInfo(key)->converter())
{
*any_ptr = converter(str);
}
else {
auto msg = StrCat("Type mismatch in scripting:",
" can't convert the string '", str,
"' to the type expected by that port.\n"
"Have you implemented the relevant "
"convertFromString<T>() ?");
throw RuntimeError(msg);
}
}
else {
try {
value.copyInto(*any_ptr);
}
catch (std::runtime_error) {
throw RuntimeError("A script failed to convert the given type "
"to the one expected by that port.");
}
}
return *any_ptr;
}

Expand Down
43 changes: 43 additions & 0 deletions tests/gtest_subtree.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include "behaviortree_cpp/bt_factory.h"
#include "../sample_nodes/dummy_nodes.h"
#include "../sample_nodes/movebase_node.h"

using namespace BT;

Expand Down Expand Up @@ -283,3 +284,45 @@ TEST(SubTree, ScriptRemap)
ASSERT_EQ(tree.subtrees[1]->blackboard->get<int>("value"), 1);
ASSERT_EQ(tree.subtrees[0]->blackboard->get<int>("value"), 1);
}

class ModifyPose : public BT::SyncActionNode
{
public:
// Any TreeNode with ports must have a constructor with this signature
ModifyPose(const std::string& name, const BT::NodeConfig& config)
: SyncActionNode(name, config)
{}

static BT::PortsList providedPorts() {
return{ BT::BidirectionalPort<Pose2D>("pose") };
}

BT::NodeStatus tick() override {
Pose2D pose;
getInput("pose", pose);
pose.theta *= 2;
setOutput("pose", pose);
return NodeStatus::SUCCESS;
}
};

TEST(SubTree, StringConversions_Issue530)
{
const char* xml_text = R"(
<root BTCPP_format="4" >
<BehaviorTree ID="MainTree">
<Sequence>
<Script code=" pose:='1;2;3' "/>
<ModifyPose pose="{pose}"/>
<Script code=" pose:='1;2;3' "/>
</Sequence>
</BehaviorTree>
</root>
)";

BT::BehaviorTreeFactory factory;
factory.registerNodeType<ModifyPose>("ModifyPose");
factory.registerBehaviorTreeFromText(xml_text);
Tree tree = factory.createTree("MainTree");
tree.tickOnce();
}

0 comments on commit e54bcb2

Please sign in to comment.