state_machine.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2016 Shaun Edwards
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  * http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include "packml_sm/state_machine.h"
00020 #include "packml_sm/transitions.h"
00021 #include "packml_sm/events.h"
00022 
00023 namespace packml_sm
00024 {
00025 
00026 
00027 bool StateMachineInterface::start()
00028 {
00029   switch(StatesEnum(getCurrentState())) {
00030   case StatesEnum::IDLE:
00031     _start();
00032     return true;
00033   default:
00034     ROS_WARN_STREAM("Ignoring START command in current state: " << getCurrentState());
00035     return false;
00036   }
00037 }
00038 
00039 bool StateMachineInterface::clear()
00040 {
00041   switch(StatesEnum(getCurrentState())) {
00042   case StatesEnum::ABORTED:
00043     _clear();
00044     return true;
00045   default:
00046     ROS_WARN_STREAM("Ignoring CLEAR command in current state: " << getCurrentState());
00047     return false;
00048   }
00049 }
00050 
00051 bool StateMachineInterface::reset()
00052 {
00053   switch(StatesEnum(getCurrentState())) {
00054   case StatesEnum::COMPLETE:
00055   case StatesEnum::STOPPED:
00056     _reset();
00057     return true;
00058   default:
00059     ROS_WARN_STREAM("Ignoring RESET command in current state: " << getCurrentState());
00060     return false;
00061   }
00062 }
00063 
00064 bool StateMachineInterface::hold()
00065 {
00066   switch(StatesEnum(getCurrentState())) {
00067   case StatesEnum::EXECUTE:
00068     _hold();
00069     return true;
00070   default:
00071     ROS_WARN_STREAM("Ignoring HOLD command in current state: " << getCurrentState());
00072     return false;
00073   }
00074 }
00075 
00076 
00077 bool StateMachineInterface::unhold()
00078 {
00079   switch(StatesEnum(getCurrentState())) {
00080   case StatesEnum::HELD:
00081     _unhold();
00082     return true;
00083   default:
00084     ROS_WARN_STREAM("Ignoring HELD command in current state: " << getCurrentState());
00085     return false;
00086   }
00087 }
00088 
00089 
00090 bool StateMachineInterface::suspend()
00091 {
00092   switch(StatesEnum(getCurrentState())) {
00093   case StatesEnum::EXECUTE:
00094     _suspend();
00095     return true;
00096   default:
00097     ROS_WARN_STREAM("Ignoring SUSPEND command in current state: " << getCurrentState());
00098     return false;
00099   }
00100 }
00101 
00102 bool StateMachineInterface::unsuspend()
00103 {
00104   switch(StatesEnum(getCurrentState())) {
00105   case StatesEnum::SUSPENDED:
00106     _unsuspend();
00107     return true;
00108   default:
00109     ROS_WARN_STREAM("Ignoring UNSUSPEND command in current state: " << getCurrentState());
00110     return false;
00111   }
00112 }
00113 
00114 
00115 bool StateMachineInterface::stop()
00116 {
00117   switch(StatesEnum(getCurrentState())) {
00118   case StatesEnum::STOPPABLE:
00119   case StatesEnum::STARTING:
00120   case StatesEnum::IDLE:
00121   case StatesEnum::SUSPENDED:
00122   case StatesEnum::EXECUTE:
00123   case StatesEnum::HOLDING:
00124   case StatesEnum::HELD:
00125   case StatesEnum::SUSPENDING:
00126   case StatesEnum::UNSUSPENDING:
00127   case StatesEnum::UNHOLDING:
00128   case StatesEnum::COMPLETING:
00129   case StatesEnum::COMPLETE:
00130     _stop();
00131     return true;
00132   default:
00133     ROS_WARN_STREAM("Ignoring STOP command in current state: " << getCurrentState());
00134     return false;
00135   }
00136 }
00137 
00138 bool StateMachineInterface::abort()
00139 {
00140   switch(StatesEnum(getCurrentState())) {
00141   case StatesEnum::ABORTABLE:
00142   case StatesEnum::STOPPED:
00143   case StatesEnum::STARTING:
00144   case StatesEnum::IDLE:
00145   case StatesEnum::SUSPENDED:
00146   case StatesEnum::EXECUTE:
00147   case StatesEnum::HOLDING:
00148   case StatesEnum::HELD:
00149   case StatesEnum::SUSPENDING:
00150   case StatesEnum::UNSUSPENDING:
00151   case StatesEnum::UNHOLDING:
00152   case StatesEnum::COMPLETING:
00153   case StatesEnum::COMPLETE:
00154   case StatesEnum::CLEARING:
00155   case StatesEnum::STOPPING:
00156     _abort();
00157     return true;
00158   default:
00159     ROS_WARN_STREAM("Ignoring ABORT command in current state: " << getCurrentState());
00160     return false;
00161   }
00162 }
00163 
00164 
00165 
00166 
00167 
00168 QCoreApplication *a;
00169 void init(int argc, char *argv[])
00170 {
00171   if( NULL == QCoreApplication::instance() )
00172   {
00173     ROS_INFO_STREAM("Starting QCoreApplication");
00174     a = new QCoreApplication(argc, argv);
00175   }
00176 }
00177 
00178 
00179 
00180 
00181 
00182 
00183 std::shared_ptr<StateMachine> StateMachine::singleCyleSM()
00184 {
00185   return std::shared_ptr<StateMachine>(new SingleCycle());
00186 }
00187 
00188 
00189 std::shared_ptr<StateMachine> StateMachine::continuousCycleSM()
00190 {
00191   return std::shared_ptr<StateMachine>(new ContinuousCycle());
00192 }
00193 
00194 
00195 //NOTES:
00196 // Create factory methods that take std::bind as an argument for
00197 // a custom call back in the "onExit" method.
00198 
00199 // StateMachine will consist of several public SLOTS for each
00200 // PackML command.  The implementations will post events to the SM
00201 // when called.
00202 
00203 // Specializations of StateMachine (like ROS StateMachine) will use
00204 // state entered events to trigger status publishing via SLOTS
00205 
00206 // Mode handling will be achieved using a hiearchy of state machines
00207 // that reference/utilize many of the same transitions/states (maybe)
00208 
00209 
00210 StateMachine::StateMachine()
00211 {
00212 
00213   ROS_DEBUG_STREAM("State machine constructor");
00214 
00215   ROS_DEBUG_STREAM("Constructiong super states");
00216   abortable_ = WaitState::Abortable();
00217   connect(abortable_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00218 
00219   stoppable_ = WaitState::Stoppable(abortable_);
00220   connect(stoppable_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00221 
00222   ROS_DEBUG_STREAM("Constructiong acting/wait states");
00223   unholding_ = ActingState::Unholding(stoppable_);
00224   connect(unholding_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00225 
00226   held_ = WaitState::Held(stoppable_);
00227   connect(held_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00228 
00229   holding_ = ActingState::Holding(stoppable_);
00230   connect(holding_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00231 
00232   idle_ = WaitState::Idle(stoppable_);
00233   connect(idle_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00234 
00235   starting_ = ActingState::Starting(stoppable_);
00236   connect(starting_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00237 
00238   completing_ = ActingState::Completing(stoppable_);
00239   connect(completing_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00240 
00241   complete_ = WaitState::Complete(stoppable_);
00242   connect(complete_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00243 
00244   resetting_ = ActingState::Resetting(stoppable_);
00245   connect(resetting_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00246 
00247   unsuspending_ = ActingState::Unsuspending(stoppable_);
00248   connect(unsuspending_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00249 
00250   suspended_ = WaitState::Suspended(stoppable_);
00251   connect(suspended_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00252 
00253   suspending_ = ActingState::Suspending(stoppable_);
00254   connect(suspending_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00255 
00256   stopped_ = WaitState::Stopped(abortable_);
00257   connect(stopped_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00258 
00259   stopping_ = ActingState::Stopping(abortable_);
00260   connect(stopping_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00261 
00262   clearing_ = ActingState::Clearing(abortable_);
00263   connect(clearing_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00264 
00265   aborted_ = WaitState::Aborted();
00266   connect(aborted_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00267 
00268   aborting_ = ActingState::Aborting();
00269   connect(aborting_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00270 
00271   execute_ = ActingState::Execute(stoppable_);
00272   connect(execute_, SIGNAL(stateEntered(int, QString)), this, SLOT(setState(int,QString)));
00273 
00274   ROS_DEBUG_STREAM("Adding states to state machine");
00275   sm_internal_.addState(abortable_);
00276   sm_internal_.addState(aborted_);
00277   sm_internal_.addState(aborting_);
00278 }
00279 
00280 StateMachine::~StateMachine()
00281 {
00282 }
00283 
00284 
00285 bool StateMachine::activate()
00286 {
00287   ROS_INFO_STREAM("Checking if QCore application is running");
00288   if( NULL == QCoreApplication::instance() )
00289   {
00290     ROS_ERROR_STREAM("QCore application is not running, QCoreApplication must"
00291                     << " be created in main thread for state macine to run");
00292     return false;
00293   }
00294   else
00295   {
00296     ROS_INFO_STREAM("Moving state machine to Qcore thread");
00297     sm_internal_.moveToThread(QCoreApplication::instance()->thread());
00298     this->moveToThread(QCoreApplication::instance()->thread());
00299 
00300     sm_internal_.start();
00301     ROS_INFO_STREAM("State machine thread created and started");
00302 
00303     return true;
00304   }
00305 }
00306 
00307 
00308 bool StateMachine::deactivate()
00309 {
00310   ROS_DEBUG_STREAM("Deactivating state machine");
00311   sm_internal_.stop();
00312 }
00313 
00314 void StateMachine::setState(int value, QString name)
00315 {
00316   ROS_DEBUG_STREAM("State changed(event) to: " << name.toStdString() <<
00317                   "(" << value << ")");
00318   state_value_ = value;
00319   state_name_ = name;
00320   emit stateChanged(value, name);
00321 }
00322 
00323 
00324 bool StateMachine::setStarting(std::function<int ()> state_method)
00325 {
00326   ROS_INFO_STREAM("Initializing state machine with STARTING function pointer");
00327   return starting_->setOperationMethod(state_method);
00328 }
00329 
00330 bool StateMachine::setCompleting(std::function<int ()> state_method)
00331 {
00332   ROS_INFO_STREAM("Initializing state machine with COMPLETING function pointer");
00333   return completing_->setOperationMethod(state_method);
00334 }
00335 
00336 bool StateMachine::setAborting(std::function<int ()> state_method)
00337 {
00338   ROS_INFO_STREAM("Initializing state machine with ABORTING function pointer");
00339   return aborting_->setOperationMethod(state_method);
00340 }
00341 
00342 bool StateMachine::setClearing(std::function<int ()> state_method)
00343 {
00344   ROS_INFO_STREAM("Initializing state machine with CLEARING function pointer");
00345   return clearing_->setOperationMethod(state_method);
00346 }
00347 
00348 bool StateMachine::setStopping(std::function<int ()> state_method)
00349 {
00350   ROS_INFO_STREAM("Initializing state machine with STOPPING function pointer");
00351   return stopping_->setOperationMethod(state_method);
00352 }
00353 
00354 bool StateMachine::setResetting(std::function<int ()> state_method)
00355 {
00356   ROS_INFO_STREAM("Initializing state machine with RESETTING function pointer");
00357   return resetting_->setOperationMethod(state_method);
00358 }
00359 
00360 bool StateMachine::setSuspending(std::function<int ()> state_method)
00361 {
00362   ROS_INFO_STREAM("Initializing state machine with SUSPENDING function pointer");
00363   return suspending_->setOperationMethod(state_method);
00364 }
00365 
00366 bool StateMachine::setUnsuspending(std::function<int ()> state_method)
00367 {
00368   ROS_INFO_STREAM("Initializing state machine with UNSUSPENDING function pointer");
00369   return unsuspending_->setOperationMethod(state_method);
00370 }
00371 
00372 bool StateMachine::setHolding(std::function<int ()> state_method)
00373 {
00374   ROS_INFO_STREAM("Initializing state machine with HOLDING function pointer");
00375   return holding_->setOperationMethod(state_method);
00376 }
00377 
00378 bool StateMachine::setUnholding(std::function<int ()> state_method)
00379 {
00380   ROS_INFO_STREAM("Initializing state machine with UNHOLDING function pointer");
00381   return unholding_->setOperationMethod(state_method);
00382 }
00383 
00384 bool StateMachine::setExecute(std::function<int ()> state_method)
00385 {
00386   ROS_INFO_STREAM("Initializing state machine with EXECUTE function pointer");
00387   return execute_->setOperationMethod(state_method);
00388 }
00389 
00390 void StateMachine::_start() {sm_internal_.postEvent(CmdEvent::start());}
00391 void StateMachine::_clear() {sm_internal_.postEvent(CmdEvent::clear());}
00392 void StateMachine::_reset() {sm_internal_.postEvent(CmdEvent::reset());}
00393 void StateMachine::_hold() {sm_internal_.postEvent(CmdEvent::hold());}
00394 void StateMachine::_unhold() {sm_internal_.postEvent(CmdEvent::unhold());}
00395 void StateMachine::_suspend() {sm_internal_.postEvent(CmdEvent::suspend());}
00396 void StateMachine::_unsuspend() {sm_internal_.postEvent(CmdEvent::unsuspend());}
00397 void StateMachine::_stop() {sm_internal_.postEvent(CmdEvent::stop());}
00398 void StateMachine::_abort() {sm_internal_.postEvent(CmdEvent::abort());}
00399 
00400 
00401 ContinuousCycle::ContinuousCycle()
00402 {
00403 
00404   ROS_INFO_STREAM("Forming CONTINUOUS CYCLE state machine (states + transitions)");
00405 
00406 
00407   //Naming <from state>_<to state>
00408   CmdTransition*                abortable_aborting_on_cmd = CmdTransition::abort(*abortable_, *aborting_);
00409   ErrorTransition*              abortable_aborting_on_error = new ErrorTransition(*abortable_, *aborting_);
00410   StateCompleteTransition*      aborting_aborted = new StateCompleteTransition(*aborting_, *aborted_);
00411   CmdTransition*                aborted_clearing_ = CmdTransition::clear(*aborted_, *clearing_);
00412   StateCompleteTransition*      clearing_stopped_ = new StateCompleteTransition(*clearing_, *stopped_);
00413   CmdTransition*                stoppable_stopping_ = CmdTransition::stop(*stoppable_, *stopping_);
00414   StateCompleteTransition*      stopping_stopped = new StateCompleteTransition(*stopping_, *stopped_);
00415   CmdTransition*                stopped_resetting_ = CmdTransition::reset(*stopped_, *resetting_);
00416   StateCompleteTransition*      unholding_execute_ = new StateCompleteTransition(*unholding_, *execute_);
00417   CmdTransition*                held_unholding_ = CmdTransition::unhold(*held_, *unholding_);
00418   StateCompleteTransition*      holding_held_ = new StateCompleteTransition(*holding_,*held_);
00419   CmdTransition*                idle_starting_ = CmdTransition::start(*idle_, *starting_);
00420   StateCompleteTransition*      starting_execute_ = new StateCompleteTransition(*starting_,*execute_);
00421   CmdTransition*                execute_holding_ = CmdTransition::hold(*execute_,*holding_);
00422   StateCompleteTransition*      execute_execute_ = new StateCompleteTransition(*execute_, *execute_);
00423   StateCompleteTransition*      completing_complete = new StateCompleteTransition(*completing_, *complete_);
00424   CmdTransition*                complete_resetting_ = CmdTransition::reset(*complete_, *resetting_);
00425   StateCompleteTransition*      resetting_idle_ = new StateCompleteTransition(*resetting_, *idle_);
00426   CmdTransition*                execute_suspending_ = CmdTransition::suspend(*execute_,*suspending_);
00427   StateCompleteTransition*      suspending_suspended_ = new StateCompleteTransition(*suspending_,*suspended_);
00428   CmdTransition*                suspended_unsuspending_ = CmdTransition::unsuspend(*suspended_, *unsuspending_);
00429   StateCompleteTransition*      unsuspending_execute_ = new StateCompleteTransition(*unsuspending_, *execute_);
00430 
00431 
00432   abortable_->setInitialState(clearing_);
00433   stoppable_->setInitialState(resetting_);
00434   sm_internal_.setInitialState(aborted_);
00435   ROS_INFO_STREAM("State machine formed");
00436 }
00437 
00438 
00439 SingleCycle::SingleCycle()
00440 {
00441 
00442   ROS_INFO_STREAM("Forming SINGLE CYCLE state machine (states + transitions)");
00443 
00444 
00445   //Naming <from state>_<to state>
00446   CmdTransition*                abortable_aborting_on_cmd = CmdTransition::abort(*abortable_, *aborting_);
00447   ErrorTransition*              abortable_aborting_on_error = new ErrorTransition(*abortable_, *aborting_);
00448   StateCompleteTransition*      aborting_aborted = new StateCompleteTransition(*aborting_, *aborted_);
00449   CmdTransition*                aborted_clearing_ = CmdTransition::clear(*aborted_, *clearing_);
00450   StateCompleteTransition*      clearing_stopped_ = new StateCompleteTransition(*clearing_, *stopped_);
00451   CmdTransition*                stoppable_stopping_ = CmdTransition::stop(*stoppable_, *stopping_);
00452   StateCompleteTransition*      stopping_stopped = new StateCompleteTransition(*stopping_, *stopped_);
00453   CmdTransition*                stopped_resetting_ = CmdTransition::reset(*stopped_, *resetting_);
00454   StateCompleteTransition*      unholding_execute_ = new StateCompleteTransition(*unholding_, *execute_);
00455   CmdTransition*                held_unholding_ = CmdTransition::unhold(*held_, *unholding_);
00456   StateCompleteTransition*      holding_held_ = new StateCompleteTransition(*holding_,*held_);
00457   CmdTransition*                idle_starting_ = CmdTransition::start(*idle_, *starting_);
00458   StateCompleteTransition*      starting_execute_ = new StateCompleteTransition(*starting_,*execute_);
00459   CmdTransition*                execute_holding_ = CmdTransition::hold(*execute_,*holding_);
00460   StateCompleteTransition*      execute_completing_ = new StateCompleteTransition(*execute_,*completing_);
00461   StateCompleteTransition*      completing_complete = new StateCompleteTransition(*completing_, *complete_);
00462   CmdTransition*                complete_resetting_ = CmdTransition::reset(*complete_, *resetting_);
00463   StateCompleteTransition*      resetting_idle_ = new StateCompleteTransition(*resetting_, *idle_);
00464   CmdTransition*                execute_suspending_ = CmdTransition::suspend(*execute_,*suspending_);
00465   StateCompleteTransition*      suspending_suspended_ = new StateCompleteTransition(*suspending_,*suspended_);
00466   CmdTransition*                suspended_unsuspending_ = CmdTransition::unsuspend(*suspended_, *unsuspending_);
00467   StateCompleteTransition*      unsuspending_execute_ = new StateCompleteTransition(*unsuspending_, *execute_);
00468 
00469 
00470   abortable_->setInitialState(clearing_);
00471   stoppable_->setInitialState(resetting_);
00472   sm_internal_.setInitialState(aborted_);
00473   ROS_INFO_STREAM("State machine formed");
00474 }
00475 
00476 
00477 
00478 }//packml_sm


packml_sm
Author(s): Shaun Edwards
autogenerated on Sat Jun 8 2019 20:13:34