Skip to content

Commit b25480c

Browse files
committed
add cast to ENUMS in ports
1 parent 5722dd1 commit b25480c

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

include/behaviortree_cpp/utils/safe_any.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ class Any
120120
_any.type() == typeid(double);
121121
}
122122

123+
bool isIntegral() const
124+
{
125+
return _any.type() == typeid(int64_t) ||
126+
_any.type() == typeid(uint64_t);
127+
}
128+
123129
bool isString() const
124130
{
125131
return _any.type() == typeid(SafeAny::SimpleString);
@@ -176,6 +182,16 @@ class Any
176182
{
177183
static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, can not cast to reference");
178184

185+
if constexpr(std::is_enum_v<T>)
186+
{
187+
if(!isNumber())
188+
{
189+
std::cout << demangle( _any.type() ) << std::endl;
190+
throw std::runtime_error("Any::cast failed to cast to enum type");
191+
}
192+
return static_cast<T>( convert<int>().value() );
193+
}
194+
179195
if( _any.empty() )
180196
{
181197
throw std::runtime_error("Any::cast failed because it is empty");

tests/script_parser_test.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,51 @@ TEST(ParserTest, Enums)
247247
ASSERT_EQ(blackboard->get<int>("color2"), BLUE);
248248
ASSERT_EQ(blackboard->get<int>("color3"), GREEN);
249249
}
250+
251+
enum DeviceType { BATT=1, CONTROLLER=2 };
252+
253+
254+
BT::NodeStatus checkLevel(BT::TreeNode &self)
255+
{
256+
double percent = self.getInput<double>("percentage").value();
257+
DeviceType devType = self.getInput<DeviceType>("deviceType").value();
258+
259+
if(devType == DeviceType::BATT)
260+
{
261+
self.setOutput("isLowBattery", (percent < 25));
262+
}
263+
std::cout << "Device: " << devType << " Level: " << percent << std::endl;
264+
return BT::NodeStatus::SUCCESS;
265+
}
266+
267+
TEST(ParserTest, Enums_Issue_523)
268+
{
269+
BT::BehaviorTreeFactory factory;
270+
271+
const std::string xml_text = R"(
272+
<root BTCPP_format="4" >
273+
<BehaviorTree ID="PowerManagerT">
274+
<Sequence>
275+
<Script code=" deviceA:=BATT; deviceB:=CONTROLLER; LOW_BATT:=20 "/>
276+
<CheckLevel deviceType="{deviceA}" percentage="{LOW_BATT}" isLowBattery="{isLowBattery}"/>
277+
</Sequence>
278+
</BehaviorTree>
279+
</root> )";
280+
281+
factory.registerSimpleCondition("CheckLevel", std::bind(checkLevel, std::placeholders::_1),
282+
{ BT::InputPort("percentage"),
283+
BT::InputPort("deviceType"),
284+
BT::OutputPort("isLowBattery")});
285+
286+
factory.registerScriptingEnums<DeviceType>();
287+
288+
auto tree = factory.createTreeFromText(xml_text);
289+
const auto status = tree.tickWhileRunning();
290+
ASSERT_EQ(status, BT::NodeStatus::SUCCESS);
291+
292+
const auto& blackboard = tree.subtrees.front()->blackboard;
293+
ASSERT_EQ(blackboard->get<int>("deviceA"), BATT);
294+
ASSERT_EQ(blackboard->get<int>("deviceB"), CONTROLLER);
295+
ASSERT_EQ(blackboard->get<bool>("isLowBattery"), true);
296+
}
297+

0 commit comments

Comments
 (0)