Skip to content

Commit

Permalink
bugfix: string to enum/integer/boolean in scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
facontidavide committed Mar 7, 2024
1 parent 61589d1 commit d974b6b
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
37 changes: 32 additions & 5 deletions include/behaviortree_cpp/scripting/operators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#pragma once

#include <cmath>
#include <cstdio>
#include <unordered_map>
#include <memory>
#include <string>
#include <vector>
Expand All @@ -30,6 +28,27 @@ using SimpleString = SafeAny::SimpleString;

using expr_ptr = std::shared_ptr<struct ExprBase>;

// extended strin to number that consider enums and booleans
double StringToDouble(const Any& value, const Environment& env)
{
const auto str = value.cast<std::string>();
if(str == "true") {
return 1.0;
}
if(str == "false") {
return 0.0;
}
if(env.enums)
{
auto it = env.enums->find(str);
if(it != env.enums->end())
{
return it->second;
}
}
return value.cast<double>();
}

struct ExprBase
{
using Ptr = std::shared_ptr<ExprBase>;
Expand Down Expand Up @@ -380,16 +399,24 @@ struct ExprComparison : ExprBase
return False;
}
}
else if ((lhs_v.isString() && rhs_v.isNumber()) ||
(lhs_v.isNumber() && rhs_v.isString()))
else if (lhs_v.isString() && rhs_v.isNumber())
{
auto lv = lhs_v.cast<double>();
auto lv = StringToDouble(lhs_v, env);
auto rv = rhs_v.cast<double>();
if (!SwitchImpl(lv, rv, ops[i]))
{
return False;
}
}
else if (lhs_v.isNumber() && rhs_v.isString())
{
auto lv = lhs_v.cast<double>();
auto rv = StringToDouble(rhs_v, env);
if (!SwitchImpl(lv, rv, ops[i]))
{
return False;
}
}
else
{
throw RuntimeError(StrCat("Can't mix different types in Comparison. "
Expand Down
33 changes: 29 additions & 4 deletions tests/gtest_preconditions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,22 @@ TEST(Preconditions, Issue615_NoSkipWhenRunning_B)
}


class SimpleOutput : public BT::SyncActionNode
{
public:
SimpleOutput(const std::string& name, const BT::NodeConfig& config) :
BT::SyncActionNode(name, config){}

static BT::PortsList providedPorts() {
return { OutputPort<bool>("output")};
}

BT::NodeStatus tick() override {
setOutput("output", true);
return BT::NodeStatus::SUCCESS;
}

};

TEST(Preconditions, Remapping)
{
Expand All @@ -308,23 +324,32 @@ TEST(Preconditions, Remapping)
<BehaviorTree ID="Main">
<Sequence>
<Script code="value:=1" />
<SimpleOutput output="{param}" />
<Script code="value:=true" />
<SubTree ID="Sub1" param="{param}"/>
<SubTree ID="Sub1" param="{value}"/>
<TestA _skipIf="value!=1" />
<SubTree ID="Sub1" param="true"/>
<TestA/>
</Sequence>
</BehaviorTree>
<BehaviorTree ID="Sub1">
<Sequence>
<TestB _skipIf="param!=1" />
<SubTree ID="Sub2" _skipIf="param != true" />
</Sequence>
</BehaviorTree>
<BehaviorTree ID="Sub2">
<TestB/>
</BehaviorTree>
</root>
)";

BehaviorTreeFactory factory;

std::array<int, 2> counters;
factory.registerNodeType<SimpleOutput>("SimpleOutput");
RegisterTestTick(factory, "Test", counters);

factory.registerBehaviorTreeFromText(xml_text);
Expand All @@ -334,5 +359,5 @@ TEST(Preconditions, Remapping)

ASSERT_EQ(status, BT::NodeStatus::SUCCESS);
ASSERT_EQ( counters[0], 1 );
ASSERT_EQ( counters[1], 1 );
ASSERT_EQ( counters[1], 3 );
}

0 comments on commit d974b6b

Please sign in to comment.