Skip to content

Commit ffbd5f7

Browse files
committed
Fix #974: numeric comparison for string-valued blackboard entries in scripts
1 parent b3dbe30 commit ffbd5f7

2 files changed

Lines changed: 57 additions & 4 deletions

File tree

include/behaviortree_cpp/scripting/operators.hpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "behaviortree_cpp/scripting/script_parser.hpp"
1717

1818
#include <cmath>
19+
#include <cstdlib>
1920
#include <memory>
2021
#include <string>
2122
#include <vector>
@@ -407,11 +408,32 @@ struct ExprComparison : ExprBase
407408
}
408409
else if(lhs_v.isString() && rhs_v.isString())
409410
{
410-
auto lv = lhs_v.cast<SimpleString>();
411-
auto rv = rhs_v.cast<SimpleString>();
412-
if(!SwitchImpl(lv, rv, ops[i]))
411+
// Try numeric comparison when both strings are parseable as numbers.
412+
// This handles values set via blackboard->set(key, "42"). Issue #974.
413+
auto ls = lhs_v.cast<std::string>();
414+
auto rs = rhs_v.cast<std::string>();
415+
char* lend = nullptr;
416+
char* rend = nullptr;
417+
double ld = std::strtod(ls.c_str(), &lend);
418+
double rd = std::strtod(rs.c_str(), &rend);
419+
bool l_numeric = (lend == ls.c_str() + ls.size()) && !ls.empty();
420+
bool r_numeric = (rend == rs.c_str() + rs.size()) && !rs.empty();
421+
422+
if(l_numeric && r_numeric)
413423
{
414-
return False;
424+
if(!SwitchImpl(ld, rd, ops[i]))
425+
{
426+
return False;
427+
}
428+
}
429+
else
430+
{
431+
auto lv = lhs_v.cast<SimpleString>();
432+
auto rv = rhs_v.cast<SimpleString>();
433+
if(!SwitchImpl(lv, rv, ops[i]))
434+
{
435+
return False;
436+
}
415437
}
416438
}
417439
else if(lhs_v.isString() && rhs_v.isNumber())

tests/gtest_blackboard.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,3 +745,34 @@ TEST(BlackboardTest, SetBlackboard_WithPortRemapping)
745745
// Tick till the end with no crashes
746746
ASSERT_NO_THROW(tree.tickWhileRunning(););
747747
}
748+
749+
// Issue #974: blackboard->set(key, "42") stores a string.
750+
// When two string-valued blackboard entries are compared in a script,
751+
// numeric comparison should be used if both strings are parseable as numbers.
752+
// "9" < "10" is false lexicographically but true numerically.
753+
TEST(BlackboardTest, StringSetNumericScriptComparison_Issue974)
754+
{
755+
auto bb = Blackboard::create();
756+
bb->set("a", std::string("9"));
757+
bb->set("b", std::string("10"));
758+
759+
BehaviorTreeFactory factory;
760+
761+
std::string xml_txt = R"(
762+
<root BTCPP_format="4" >
763+
<BehaviorTree ID="Main">
764+
<Sequence>
765+
<Script code=" result := false "/>
766+
<Script code=" result := (a < b) "/>
767+
<AlwaysSuccess _successIf="result"/>
768+
</Sequence>
769+
</BehaviorTree>
770+
</root>)";
771+
772+
auto tree = factory.createTreeFromText(xml_txt, bb);
773+
auto status = tree.tickWhileRunning();
774+
775+
ASSERT_EQ(status, NodeStatus::SUCCESS);
776+
// 9 < 10 is true numerically, even though "9" > "10" lexicographically
777+
ASSERT_TRUE(bb->get<bool>("result"));
778+
}

0 commit comments

Comments
 (0)