Go to the documentation of this file.
59 this->_p = std::move(other._p);
64 this->_p = std::move(other._p);
73 auto new_status =
_p->status;
78 std::scoped_lock lk(
_p->callback_injection_mutex);
79 pre_tick =
_p->pre_tick_callback;
80 post_tick =
_p->post_tick_callback;
81 monitor_tick =
_p->tick_monitor_callback;
88 new_status = precond.value();
93 bool substituted =
false;
96 auto override_status = pre_tick(*
this);
101 new_status = override_status;
108 using namespace std::chrono;
110 auto t1 = steady_clock::now();
113 std::shared_ptr<void> execute_later(
nullptr, [&](...) {
114 auto t2 = steady_clock::now();
117 monitor_tick(*
this, new_status, duration_cast<microseconds>(t2 - t1));
133 auto override_status = post_tick(*
this, new_status);
136 new_status = override_status;
165 "]: you are not allowed to set manually the status to IDLE. "
166 "If you know what you are doing (?) use resetStatus() instead.");
171 std::unique_lock<std::mutex> UniqueLock(
_p->state_mutex);
172 prev_status =
_p->status;
173 _p->status = new_status;
175 if(prev_status != new_status)
177 _p->state_condition_variable.notify_all();
178 _p->state_change_signal.notify(std::chrono::high_resolution_clock::now(), *
this,
179 prev_status, new_status);
185 return _p->pre_parsed;
190 return _p->post_parsed;
200 const auto& parse_executor =
_p->pre_parsed[index];
212 if(parse_executor(env).cast<bool>())
236 if(!parse_executor(env).cast<bool>())
243 return nonstd::make_unexpected(
"");
248 auto ExecuteScript = [
this](
const PostCond& cond) {
249 const auto& parse_executor =
_p->post_parsed[size_t(cond)];
272 std::unique_lock<std::mutex> lock(
_p->state_mutex);
273 prev_status =
_p->status;
279 _p->state_condition_variable.notify_all();
280 _p->state_change_signal.notify(std::chrono::high_resolution_clock::now(), *
this,
287 std::lock_guard<std::mutex> lock(
_p->state_mutex);
293 std::unique_lock<std::mutex> lock(
_p->state_mutex);
297 _p->state_condition_variable.wait(lock);
315 return _p->state_change_signal.subscribe(std::move(
callback));
320 std::unique_lock lk(
_p->callback_injection_mutex);
326 std::unique_lock lk(
_p->callback_injection_mutex);
332 std::unique_lock lk(
_p->callback_injection_mutex);
338 return _p->config.uid;
343 return _p->config.path;
348 return _p->registration_ID;
363 auto remap_it =
_p->config.input_ports.find(key);
364 if(remap_it ==
_p->config.input_ports.end())
366 remap_it =
_p->config.output_ports.find(key);
367 if(remap_it ==
_p->config.output_ports.end())
369 throw std::logic_error(
StrCat(
"[", key,
"] not found"));
372 return remap_it->second;
382 size_t front_index = 0;
383 size_t last_index = str.size() - 1;
384 while(str[front_index] ==
' ' && front_index <= last_index)
388 while(str[last_index] ==
' ' && front_index <= last_index)
392 const auto size = (last_index - front_index) + 1;
393 auto valid =
size >= 3 && str[front_index] ==
'{' && str[last_index] ==
'}';
394 if(valid && stripped_pointer)
414 if(remapped_port ==
"{=}" || remapped_port ==
"=")
416 return { port_name };
423 return nonstd::make_unexpected(
"Not a blackboard pointer");
430 _p->wake_up->emitSignal();
436 return bool(
_p->wake_up);
441 _p->registration_ID.assign(ID.data(), ID.size());
446 _p->wake_up = instance;
451 for(
const auto& new_it : new_remapping)
453 auto it =
_p->config.input_ports.find(new_it.first);
454 if(it !=
_p->config.input_ports.end())
456 it->second = new_it.second;
458 it =
_p->config.output_ports.find(new_it.first);
459 if(it !=
_p->config.output_ports.end())
461 it->second = new_it.second;
506 return _p->config.blackboard->getAnyLocked(std::string(*remapped_key));
constexpr auto size(const C &c) -> decltype(c.size())
std::array< ScriptFunction, size_t(PostCond::COUNT_)> post_parsed
PreTickCallback pre_tick_callback
bool requiresWakeUp() const
TickMonitorCallback tick_monitor_callback
const NodeConfig & config() const
void emitWakeUpSignal()
Notify that the tree should be ticked again()
StatusChangeSignal::Subscriber StatusChangeSubscriber
std::function< void(TreeNode &, NodeStatus, std::chrono::microseconds)> TickMonitorCallback
nonstd::expected< T, std::string > Expected
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
std::string_view StringView
std::function< Any(Ast::Environment &env)> ScriptFunction
void setPreTickFunction(PreTickCallback callback)
Abstract base class for Behavior Tree Nodes.
PImpl(std::string name, NodeConfig config)
std::array< ScriptFunction, size_t(PreCond::COUNT_)> pre_parsed
std::condition_variable state_condition_variable
std::function< NodeStatus(TreeNode &)> PreTickCallback
static pthread_mutex_t mutex
const std::string & registrationName() const
registrationName is the ID used by BehaviorTreeFactory to create an instance.
std::array< ScriptFunction, size_t(PostCond::COUNT_)> PostScripts
constexpr auto callback(Fns &&... fns)
Creates a callback.
Blackboard::Ptr blackboard
NodeStatus status() const
void setPostTickFunction(PostTickCallback callback)
BT::NodeStatus waitValidStatus()
void setStatus(NodeStatus new_status)
setStatus changes the status of the node. it will throw if you try to change the status to IDLE,...
void setTickMonitorCallback(TickMonitorCallback callback)
StringView getRawPortValue(const std::string &key) const
std::string registration_ID
std::string toStr< PostCond >(const PostCond &pre)
StatusChangeSignal state_change_signal
PostScripts & postConditionsScripts()
AnyPtrLocked getLockedPortContent(const std::string &key)
getLockedPortContent should be used when:
The LockedPtr class is used to share a pointer to an object and a mutex that protects the read/write ...
void setRegistrationID(StringView ID)
void checkPostConditions(NodeStatus status)
const std::string & name() const
Name of the instance, not the type.
virtual BT::NodeStatus tick()=0
Method to be implemented by the user.
void modifyPortsRemapping(const PortsRemapping &new_remapping)
TreeNode & operator=(const TreeNode &other)=delete
PreScripts & preConditionsScripts()
std::unordered_map< std::string, std::string > PortsRemapping
static Expected< StringView > getRemappedKey(StringView port_name, StringView remapped_port)
void setWakeUpInstance(std::shared_ptr< WakeUpSignal > instance)
StatusChangeSubscriber subscribeToStatusChange(StatusChangeCallback callback)
subscribeToStatusChange is used to attach a callback to a status change. When StatusChangeSubscriber ...
bool isStatusCompleted(const NodeStatus &status)
std::shared_ptr< WakeUpSignal > wake_up
TreeNode(std::string name, NodeConfig config)
TreeNode main constructor.
std::unique_ptr< PImpl > _p
void resetStatus()
Set the status to IDLE.
std::array< ScriptFunction, size_t(PreCond::COUNT_)> PreScripts
const std::string & fullPath() const
Expected< NodeStatus > checkPreConditions()
std::function< NodeStatus(TreeNode &, NodeStatus)> PostTickCallback
std::mutex callback_injection_mutex
std::string toStr< PreCond >(const PreCond &pre)
static bool isBlackboardPointer(StringView str, StringView *stripped_pointer=nullptr)
Check a string and return true if it matches the pattern: {...}.
std::shared_ptr< ScriptingEnumsRegistry > enums
StatusChangeSignal::CallableFunction StatusChangeCallback
PostTickCallback post_tick_callback
static StringView stripBlackboardPointer(StringView str)
The Environment class is used to encapsulate the information and states needed by the scripting langu...