Skip to content

Commit 3a9784f

Browse files
committed
new decorators using the entry sequence, added
1 parent 22f1b62 commit 3a9784f

File tree

9 files changed

+237
-5
lines changed

9 files changed

+237
-5
lines changed

CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ list(APPEND BT_SOURCE
103103
src/decorators/repeat_node.cpp
104104
src/decorators/retry_node.cpp
105105
src/decorators/timeout_node.cpp
106+
src/decorators/skip_unless_updated.cpp
106107
src/decorators/subtree_node.cpp
108+
src/decorators/wait_update.cpp
107109

108110
src/controls/if_then_else_node.cpp
109111
src/controls/fallback_node.cpp
@@ -148,7 +150,8 @@ endif()
148150

149151
if (BTCPP_SHARED_LIBS)
150152
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
151-
add_library(${BTCPP_LIBRARY} SHARED ${BT_SOURCE})
153+
add_library(${BTCPP_LIBRARY} SHARED ${BT_SOURCE}
154+
src/decorators/wait_update.cpp)
152155
else()
153156
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
154157
add_library(${BTCPP_LIBRARY} STATIC ${BT_SOURCE})

include/behaviortree_cpp/behavior_tree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "behaviortree_cpp/decorators/run_once_node.h"
3434
#include "behaviortree_cpp/decorators/subtree_node.h"
3535
#include "behaviortree_cpp/decorators/loop_node.h"
36+
#include "behaviortree_cpp/decorators/skip_unless_updated.h"
37+
#include "behaviortree_cpp/decorators/wait_update.h"
3638

3739
#include "behaviortree_cpp/actions/always_success_node.h"
3840
#include "behaviortree_cpp/actions/always_failure_node.h"

include/behaviortree_cpp/bt_factory.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@
1414
#ifndef BT_FACTORY_H
1515
#define BT_FACTORY_H
1616

17-
#include <algorithm>
18-
#include <cstring>
1917
#include <filesystem>
2018
#include <functional>
2119
#include <memory>
2220
#include <unordered_map>
2321
#include <set>
24-
#include <utility>
2522
#include <vector>
2623

2724
#include "behaviortree_cpp/contrib/magic_enum.hpp"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* Copyright (C) 2024 Davide Faconti - 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/decorator_node.h"
16+
17+
namespace BT
18+
{
19+
20+
/**
21+
* @brief The SkipUnlessUpdated checks the Timestamp in an entry
22+
* to determine if the value was updated since the last time (true,
23+
* the first time).
24+
*
25+
* If it is, the child will be executed, otherwise SKIPPED is returned.
26+
*/
27+
class SkipUnlessUpdated : public DecoratorNode
28+
{
29+
public:
30+
SkipUnlessUpdated(const std::string& name, const NodeConfig& config);
31+
32+
~SkipUnlessUpdated() override = default;
33+
34+
static PortsList providedPorts()
35+
{
36+
return { InputPort<BT::Any>("entry", "Skip this branch unless the blackboard value "
37+
"was updated") };
38+
}
39+
40+
private:
41+
int64_t sequence_id_ = -1;
42+
std::string entry_key_;
43+
bool still_executing_child_ = false;
44+
45+
NodeStatus tick() override;
46+
47+
void halt() override;
48+
};
49+
50+
} // namespace BT
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* Copyright (C) 2024 Davide Faconti - 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/decorator_node.h"
16+
17+
namespace BT
18+
{
19+
/**
20+
* @brief The WaitValueUpdate checks the Timestamp in an entry
21+
* to determine if the value was updated since the last time (true,
22+
* the first time).
23+
*
24+
* If it is, the child will be executed, otherwise RUNNING is returned.
25+
*/
26+
class WaitValueUpdate : public DecoratorNode
27+
{
28+
public:
29+
WaitValueUpdate(const std::string& name, const NodeConfig& config);
30+
31+
~WaitValueUpdate() override = default;
32+
33+
static PortsList providedPorts()
34+
{
35+
return { InputPort<BT::Any>("entry", "Sleep until the entry in the blackboard is "
36+
"updated") };
37+
}
38+
39+
private:
40+
int64_t sequence_id_ = -1;
41+
std::string entry_key_;
42+
bool still_executing_child_ = false;
43+
44+
NodeStatus tick() override;
45+
46+
void halt() override;
47+
};
48+
49+
} // namespace BT

include/behaviortree_cpp/tree_node.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ inline ResultStamped TreeNode::getInputStamped(const std::string& key,
467467
if constexpr(std::is_same_v<T, Any>)
468468
{
469469
destination = any_value;
470-
return {};
470+
return Timestamp{ entry->sequence_id, entry->stamp };
471471
}
472472

473473
if(!entry->value.empty())

src/bt_factory.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ BehaviorTreeFactory::BehaviorTreeFactory() : _p(new PImpl)
9595
registerNodeType<LoopNode<double>>("LoopDouble");
9696
registerNodeType<LoopNode<std::string>>("LoopString");
9797

98+
registerNodeType<SkipUnlessUpdated>("SkipUnlessUpdated");
99+
registerNodeType<WaitValueUpdate>("WaitValueUpdate");
100+
98101
for(const auto& it : _p->builders)
99102
{
100103
_p->builtin_IDs.insert(it.first);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* Copyright (C) 2024 Davide Faconti - 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/decorators/skip_unless_updated.h"
16+
17+
namespace BT
18+
{
19+
20+
SkipUnlessUpdated::SkipUnlessUpdated(const std::string& name, const NodeConfig& config)
21+
: DecoratorNode(name, config)
22+
{
23+
const auto entry_str = config.input_ports.at("entry");
24+
StringView stripped_key;
25+
if(isBlackboardPointer(entry_str, &stripped_key))
26+
{
27+
entry_key_ = stripped_key;
28+
}
29+
else
30+
{
31+
entry_key_ = entry_str;
32+
}
33+
}
34+
35+
NodeStatus SkipUnlessUpdated::tick()
36+
{
37+
// continue executing an asynchronous child
38+
if(still_executing_child_)
39+
{
40+
auto status = child()->executeTick();
41+
still_executing_child_ = (status == NodeStatus::RUNNING);
42+
return status;
43+
}
44+
45+
auto entry = config().blackboard->getEntry(entry_key_);
46+
std::unique_lock lk(entry->entry_mutex);
47+
auto seq = static_cast<int64_t>(entry->sequence_id);
48+
if(seq == sequence_id_)
49+
{
50+
return NodeStatus::SKIPPED;
51+
}
52+
sequence_id_ = seq;
53+
54+
auto status = child()->executeTick();
55+
still_executing_child_ = (status == NodeStatus::RUNNING);
56+
return status;
57+
}
58+
59+
void SkipUnlessUpdated::halt()
60+
{
61+
still_executing_child_ = false;
62+
}
63+
64+
} // namespace BT

src/decorators/wait_update.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* Copyright (C) 2024 Davide Faconti - 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/decorators/wait_update.h"
16+
17+
namespace BT
18+
{
19+
20+
WaitValueUpdate::WaitValueUpdate(const std::string& name, const NodeConfig& config)
21+
: DecoratorNode(name, config)
22+
{
23+
const auto entry_str = config.input_ports.at("entry");
24+
StringView stripped_key;
25+
if(isBlackboardPointer(entry_str, &stripped_key))
26+
{
27+
entry_key_ = stripped_key;
28+
}
29+
else
30+
{
31+
entry_key_ = entry_str;
32+
}
33+
}
34+
35+
NodeStatus WaitValueUpdate::tick()
36+
{
37+
// continue executing an asynchronous child
38+
if(still_executing_child_)
39+
{
40+
auto status = child()->executeTick();
41+
still_executing_child_ = (status == NodeStatus::RUNNING);
42+
return status;
43+
}
44+
45+
auto entry = config().blackboard->getEntry(entry_key_);
46+
std::unique_lock lk(entry->entry_mutex);
47+
auto seq = static_cast<int64_t>(entry->sequence_id);
48+
if(seq == sequence_id_)
49+
{
50+
return NodeStatus::RUNNING;
51+
}
52+
sequence_id_ = seq;
53+
54+
auto status = child()->executeTick();
55+
still_executing_child_ = (status == NodeStatus::RUNNING);
56+
return status;
57+
}
58+
59+
void WaitValueUpdate::halt()
60+
{
61+
still_executing_child_ = false;
62+
}
63+
64+
} // namespace BT

0 commit comments

Comments
 (0)