parallel_node.cpp
Go to the documentation of this file.
00001 
00002 /* Copyright (C) 2015-2017 Michele Colledanchise - All Rights Reserved
00003 *
00004 *   Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
00005 *   to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
00006 *   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:
00007 *   The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
00008 *
00009 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00010 *   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,
00011 *   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.
00012 */
00013 
00014 
00015 #include <parallel_node.h>
00016 #include <string>
00017 
00018 BT::ParallelNode::ParallelNode(std::string name, int threshold_M) : ControlNode::ControlNode(name)
00019 {
00020     threshold_M_ = threshold_M;
00021 }
00022 
00023 BT::ParallelNode::~ParallelNode() {}
00024 
00025 BT::ReturnStatus BT::ParallelNode::Tick()
00026 {
00027     success_childred_num_ = 0;
00028     failure_childred_num_ = 0;
00029     // Vector size initialization. N_of_children_ could change at runtime if you edit the tree
00030     N_of_children_ = children_nodes_.size();
00031 
00032     // Routing the tree according to the sequence node's logic:
00033     for (unsigned int i = 0; i < N_of_children_; i++)
00034     {
00035         DEBUG_STDOUT(get_name() << "TICKING " << children_nodes_[i]->get_name());
00036 
00037         if (children_nodes_[i]->get_type() == BT::ACTION_NODE)
00038         {
00039             // 1) If the child i is an action, read its state.
00040             // Action nodes runs in another parallel, hence you cannot retrieve the status just by executing it.
00041             child_i_status_ = children_nodes_[i]->get_status();
00042 
00043             if (child_i_status_ == BT::IDLE || child_i_status_ == BT::HALTED)
00044             {
00045                 // 1.1 If the action status is not running, the sequence node sends a tick to it.
00046                 DEBUG_STDOUT(get_name() << "NEEDS TO TICK " << children_nodes_[i]->get_name());
00047                 children_nodes_[i]->tick_engine.Tick();
00048 
00049                 // waits for the tick to arrive to the child
00050                 do
00051                 {
00052                     child_i_status_ = children_nodes_[i]->get_status();
00053                     std::this_thread::sleep_for(std::chrono::milliseconds(10));
00054                 }
00055                 while (child_i_status_ != BT::RUNNING && child_i_status_ != BT::SUCCESS
00056                        && child_i_status_ != BT::FAILURE);
00057             }
00058         }
00059         else
00060         {
00061             child_i_status_ = children_nodes_[i]->Tick();
00062         }
00063         switch (child_i_status_)
00064         {
00065         case BT::SUCCESS:
00066             children_nodes_[i]->set_status(BT::IDLE);  // the child goes in idle if it has returned success.
00067             if (++success_childred_num_ == threshold_M_)
00068             {
00069                 success_childred_num_ = 0;
00070                 failure_childred_num_ = 0;
00071                 HaltChildren(0);  // halts all running children. The execution is done.
00072                 set_status(child_i_status_);
00073                 return child_i_status_;
00074             }
00075             break;
00076         case BT::FAILURE:
00077             children_nodes_[i]->set_status(BT::IDLE);  // the child goes in idle if it has returned failure.
00078             if (++failure_childred_num_ > N_of_children_- threshold_M_)
00079             {
00080                 DEBUG_STDOUT("*******PARALLEL" << get_name()
00081                              << " FAILED****** failure_childred_num_:" << failure_childred_num_);
00082 
00083                 success_childred_num_ = 0;
00084                 failure_childred_num_ = 0;
00085                 HaltChildren(0);  // halts all running children. The execution is hopeless.
00086                 set_status(child_i_status_);
00087                 return child_i_status_;
00088             }
00089             break;
00090         case BT::RUNNING:
00091             set_status(child_i_status_);
00092             break;
00093         default:
00094             break;
00095         }
00096     }
00097     return BT::RUNNING;
00098 }
00099 
00100 void BT::ParallelNode::Halt()
00101 {
00102     success_childred_num_ = 0;
00103     failure_childred_num_ = 0;
00104     BT::ControlNode::Halt();
00105 }
00106 
00107 int BT::ParallelNode::DrawType()
00108 {
00109     return BT::PARALLEL;
00110 }
00111 
00112 
00113 unsigned int BT::ParallelNode::get_threshold_M()
00114 {
00115     return threshold_M_;
00116 }
00117 
00118 void BT::ParallelNode::set_threshold_M(unsigned int threshold_M)
00119 {
00120     threshold_M_ = threshold_M;
00121 }
00122 
00123 
00124 


behavior_tree_core
Author(s): Michele Colledanchise
autogenerated on Sun Sep 10 2017 02:31:49