BehaviorTree
Core Library to create and execute Behavior Trees
Loading...
Searching...
No Matches
pop_from_queue.hpp
1/* Copyright (C) 2022-2025 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/action_node.h"
16#include "behaviortree_cpp/decorator_node.h"
17
18#include <list>
19#include <mutex>
20
21/**
22 * Template Action used in ex04_waypoints.cpp example.
23 *
24 * Its purpose is to do make it easy to create while loops which consume the elements of a queue.
25 *
26 * Note that modifying the queue is not thread safe, therefore the action that creates the queue
27 * or push elements into it, must be Synchronous.
28 *
29 * When ticked, we pop_front from the "queue" and insert that value in "popped_item".
30 * Return FAILURE if the queue is empty, SUCCESS otherwise.
31 */
32namespace BT
33{
34
35template <typename T>
36struct ProtectedQueue
37{
38 std::list<T> items;
39 std::mutex mtx;
40};
41
42/*
43 * Few words about why we represent the queue as std::shared_ptr<ProtectedQueue>:
44 *
45 * Since we will pop from the queue, the fact that the blackboard uses
46 * a value semantic is not very convenient, since it would oblige us to
47 * copy the entire std::list from the BB and than copy again a new one with one less element.
48 *
49 * We avoid this using reference semantic (wrapping the object in a shared_ptr).
50 * Unfortunately, remember that this makes our access to the list not thread-safe!
51 * This is the reason why we add a mutex to be used when modifying the ProtectedQueue::items
52 *
53 * */
54
55template <typename T>
56class PopFromQueue : public SyncActionNode
57{
58public:
59 PopFromQueue(const std::string& name, const NodeConfig& config)
60 : SyncActionNode(name, config)
61 {}
62
63 NodeStatus tick() override
64 {
65 std::shared_ptr<ProtectedQueue<T>> queue;
66 if(getInput("queue", queue) && queue)
67 {
68 std::unique_lock<std::mutex> lk(queue->mtx);
69 auto& items = queue->items;
70
71 if(items.empty())
72 {
73 return NodeStatus::FAILURE;
74 }
75 T val = items.front();
76 items.pop_front();
77 setOutput("popped_item", val);
78 return NodeStatus::SUCCESS;
79 }
80 return NodeStatus::FAILURE;
81 }
82
83 static PortsList providedPorts()
84 {
85 return { InputPort<std::shared_ptr<ProtectedQueue<T>>>("queue"), OutputPort<T>("poppe"
86 "d_"
87 "ite"
88 "m") };
89 }
90};
91
92/**
93 * Get the size of a queue. Useful when you want to write something like:
94 *
95 * <QueueSize queue="{waypoints}" size="{wp_size}" />
96 * <Repeat num_cycles="{wp_size}" >
97 * <Sequence>
98 * <PopFromQueue queue="{waypoints}" popped_item="{wp}" >
99 * <UseWaypoint waypoint="{wp}" />
100 * </Sequence>
101 * </Repeat>
102 */
103template <typename T>
104class QueueSize : public SyncActionNode
105{
106public:
107 QueueSize(const std::string& name, const NodeConfig& config)
108 : SyncActionNode(name, config)
109 {}
110
111 NodeStatus tick() override
112 {
113 std::shared_ptr<ProtectedQueue<T>> queue;
114 if(getInput("queue", queue) && queue)
115 {
116 std::unique_lock<std::mutex> lk(queue->mtx);
117 auto& items = queue->items;
118
119 if(items.empty())
120 {
121 return NodeStatus::FAILURE;
122 }
123 setOutput("size", int(items.size()));
124 return NodeStatus::SUCCESS;
125 }
126 return NodeStatus::FAILURE;
127 }
128
129 static PortsList providedPorts()
130 {
131 return { InputPort<std::shared_ptr<ProtectedQueue<T>>>("queue"),
132 OutputPort<int>("size") };
133 }
134};
135
136} // namespace BT
Definition: pop_from_queue.hpp:57
NodeStatus tick() override
Method to be implemented by the user.
Definition: pop_from_queue.hpp:63
Definition: pop_from_queue.hpp:105
NodeStatus tick() override
Method to be implemented by the user.
Definition: pop_from_queue.hpp:111
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn't require a...
Definition: action_node.h:57
Definition: action_node.h:24
NodeStatus
Definition: basic_types.h:34
Definition: tree_node.h:105
Definition: pop_from_queue.hpp:37