Skip to content

Commit ceb25a7

Browse files
author
Gaël Écorchard
committed
Add the possibility to remove a blackboard entry.
Add a node to use this functionality. Signed-off-by: Gaël Écorchard <[email protected]>
1 parent ae95e68 commit ceb25a7

File tree

7 files changed

+96
-7
lines changed

7 files changed

+96
-7
lines changed

include/behaviortree_cpp/actions/set_blackboard_node.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ namespace BT
2727
*
2828
* Will store the string "42" in the entry with key "the_answer".
2929
*/
30-
class SetBlackboard : public SyncActionNode
30+
class SetBlackboardNode : public SyncActionNode
3131
{
3232
public:
33-
SetBlackboard(const std::string& name, const NodeConfig& config) :
33+
SetBlackboardNode(const std::string& name, const NodeConfig& config) :
3434
SyncActionNode(name, config)
3535
{
3636
setRegistrationID("SetBlackboard");
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* Copyright (C) 2018-2022 Davide Faconti, Eurecat - All Rights Reserved
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4+
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5+
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
10+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11+
*/
12+
13+
#pragma once
14+
15+
#include "behaviortree_cpp/action_node.h"
16+
17+
namespace BT
18+
{
19+
/**
20+
* Action that removes an entry from the blackboard and return SUCCESS.
21+
*/
22+
class UnsetBlackboardNode : public SyncActionNode
23+
{
24+
public:
25+
UnsetBlackboardNode(const std::string& name, const NodeConfig& config) :
26+
SyncActionNode(name, config)
27+
{
28+
setRegistrationID("UnsetBlackboard");
29+
}
30+
31+
static PortsList providedPorts()
32+
{
33+
return { InputPort<std::string>("key", "Key of the entry to remove") };
34+
}
35+
36+
private:
37+
virtual BT::NodeStatus tick() override
38+
{
39+
std::string key;
40+
if (!getInput("key", key))
41+
{
42+
throw RuntimeError("missing input port [key]");
43+
}
44+
removeBlackboardEntry(key);
45+
return NodeStatus::SUCCESS;
46+
}
47+
};
48+
} // namespace BT

include/behaviortree_cpp/behavior_tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "behaviortree_cpp/actions/set_blackboard_node.h"
4242
#include "behaviortree_cpp/actions/test_node.h"
4343
#include "behaviortree_cpp/actions/sleep_node.h"
44+
#include "behaviortree_cpp/actions/unset_blackboard_node.h"
4445

4546
#include "behaviortree_cpp/decorators/force_success_node.h"
4647
#include "behaviortree_cpp/decorators/force_failure_node.h"

include/behaviortree_cpp/blackboard.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,22 @@ class Blackboard
199199
new_value.copyInto(previous_any);
200200
}
201201
}
202-
202+
203+
void unset(const std::string& key)
204+
{
205+
std::unique_lock lock(mutex_);
206+
207+
// check local storage
208+
auto it = storage_.find(key);
209+
if (it == storage_.end())
210+
{
211+
// No entry, nothing to do.
212+
return;
213+
}
214+
215+
storage_.erase(it);
216+
}
217+
203218
[[nodiscard]] const TypeInfo* entryInfo(const std::string& key);
204219

205220
void addSubtreeRemapping(StringView internal, StringView external);

include/behaviortree_cpp/tree_node.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,18 @@ class TreeNode
243243
* @brief setOutput modifies the content of an Output port
244244
* @param key the name of the port.
245245
* @param value new value
246-
* @return valid Result, is succesfull.
246+
* @return valid Result, if succesful.
247247
*/
248248
template <typename T>
249249
Result setOutput(const std::string& key, const T& value);
250250

251+
/**
252+
* @brief removeBlackboardEntry erases an entry from the blackboard
253+
* @param key the name of the entry.
254+
* @return valid Result, if succesful.
255+
*/
256+
Result removeBlackboardEntry(const std::string& key);
257+
251258
/**
252259
* @brief getLockedPortContent should be used when:
253260
*
@@ -501,6 +508,18 @@ inline Result TreeNode::setOutput(const std::string& key, const T& value)
501508
return {};
502509
}
503510

511+
inline Result TreeNode::removeBlackboardEntry(const std::string& key)
512+
{
513+
if (!config().blackboard)
514+
{
515+
return nonstd::make_unexpected("setOutput() failed: trying to access a "
516+
"Blackboard(BB) entry, but BB is invalid");
517+
}
518+
519+
config().blackboard->unset(key);
520+
return {};
521+
}
522+
504523
// Utility function to fill the list of ports using T::providedPorts();
505524
template <typename T>
506525
inline void assignDefaultRemapping(NodeConfig& config)

src/bt_factory.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ BehaviorTreeFactory::BehaviorTreeFactory():
7878
registerNodeType<AlwaysFailureNode>("AlwaysFailure");
7979
registerNodeType<ScriptNode>("Script");
8080
registerNodeType<ScriptCondition>("ScriptCondition");
81-
registerNodeType<SetBlackboard>("SetBlackboard");
81+
registerNodeType<SetBlackboardNode>("SetBlackboard");
8282
registerNodeType<SleepNode>("Sleep");
83+
registerNodeType<UnsetBlackboardNode>("UnsetBlackboard");
8384

8485
registerNodeType<SubTreeNode>("SubTree");
8586

src/xml_parsing.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,13 @@ void VerifyXML(const std::string& xml_text,
437437
{
438438
if (children_count == 0)
439439
{
440-
ThrowError(node->GetLineNum(), "A Control node must have at least 1 "
441-
"child");
440+
std::string name_attr;
441+
if (node->Attribute("name"))
442+
{
443+
name_attr = "(`" + std::string(node->Attribute("name")) + "`)";
444+
}
445+
ThrowError(node->GetLineNum(), std::string("A Control node must have at least 1 "
446+
"child, error in XML node `") + node->Name() + name_attr + "`");
442447
}
443448
}
444449
else if (name == "SubTree")

0 commit comments

Comments
 (0)