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;
109 auto t1 = steady_clock::now();
111 auto t2 = steady_clock::now();
114 monitor_tick(*
this, new_status, duration_cast<microseconds>(t2 - t1));
127 auto override_status = post_tick(*
this, new_status);
130 new_status = override_status;
159 "]: you are not allowed to set manually the status to IDLE. "
160 "If you know what you are doing (?) use resetStatus() instead.");
165 std::unique_lock<std::mutex> UniqueLock(
_p->state_mutex);
166 prev_status =
_p->status;
167 _p->status = new_status;
169 if(prev_status != new_status)
171 _p->state_condition_variable.notify_all();
172 _p->state_change_signal.notify(std::chrono::high_resolution_clock::now(), *
this,
173 prev_status, new_status);
179 return _p->pre_parsed;
184 return _p->post_parsed;
194 const auto& parse_executor =
_p->pre_parsed[index];
206 if(parse_executor(env).cast<bool>())
230 if(!parse_executor(env).cast<bool>())
237 return nonstd::make_unexpected(
"");
242 auto ExecuteScript = [
this](
const PostCond& cond) {
243 const auto& parse_executor =
_p->post_parsed[size_t(cond)];
266 std::unique_lock<std::mutex> lock(
_p->state_mutex);
267 prev_status =
_p->status;
273 _p->state_condition_variable.notify_all();
274 _p->state_change_signal.notify(std::chrono::high_resolution_clock::now(), *
this,
281 std::lock_guard<std::mutex> lock(
_p->state_mutex);
287 std::unique_lock<std::mutex> lock(
_p->state_mutex);
291 _p->state_condition_variable.wait(lock);
309 return _p->state_change_signal.subscribe(std::move(
callback));
314 std::unique_lock lk(
_p->callback_injection_mutex);
320 std::unique_lock lk(
_p->callback_injection_mutex);
326 std::unique_lock lk(
_p->callback_injection_mutex);
332 return _p->config.uid;
337 return _p->config.path;
342 return _p->registration_ID;
357 auto remap_it =
_p->config.input_ports.find(key);
358 if(remap_it ==
_p->config.input_ports.end())
360 remap_it =
_p->config.output_ports.find(key);
361 if(remap_it ==
_p->config.output_ports.end())
363 throw std::logic_error(
StrCat(
"[", key,
"] not found"));
366 return remap_it->second;
376 size_t front_index = 0;
377 size_t last_index = str.size() - 1;
378 while(str[front_index] ==
' ' && front_index <= last_index)
382 while(str[last_index] ==
' ' && front_index <= last_index)
386 const auto size = (last_index - front_index) + 1;
387 auto valid =
size >= 3 && str[front_index] ==
'{' && str[last_index] ==
'}';
388 if(valid && stripped_pointer)
408 if(remapped_port ==
"{=}" || remapped_port ==
"=")
410 return { port_name };
417 return nonstd::make_unexpected(
"Not a blackboard pointer");
424 _p->wake_up->emitSignal();
430 return bool(
_p->wake_up);
435 _p->registration_ID.assign(ID.data(), ID.size());
440 _p->wake_up = instance;
445 for(
const auto& new_it : new_remapping)
447 auto it =
_p->config.input_ports.find(new_it.first);
448 if(it !=
_p->config.input_ports.end())
450 it->second = new_it.second;
452 it =
_p->config.output_ports.find(new_it.first);
453 if(it !=
_p->config.output_ports.end())
455 it->second = new_it.second;
500 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...