ActiveBehaviorContainer.cpp
Go to the documentation of this file.
00001 /*
00002  * BehaviorSwitch.cpp
00003  *
00004  *  Created on: Mar 13, 2012
00005  *      Author: mriedel
00006  */
00007 
00008 #include <tk_behavior/ActiveBehaviorContainer.hpp>
00009 #include <tk_behavior/BehaviorContainer.hpp>
00010 
00011 #include <tk_behavior/BehaviorController.hpp>
00012 
00013 namespace TELEKYB_NAMESPACE
00014 {
00015 
00016 ActiveBehaviorContainer::ActiveBehaviorContainer(Behavior* initialActiveBehavior)
00017         : activeBehaviorPtr( initialActiveBehavior ),
00018           options( BehaviorControllerOptions::Instance() ),
00019           seController( StateEstimatorController::Instance() ),
00020           behaviorController( BehaviorController::Instance() )
00021 {
00022 
00023 
00024         // did you get at least one state?
00025         if (! seController.waitForFirstState( Time(options.tInitialStateTimeout->getValue()) ) ) {
00026                 // did not receive State
00027                 ROS_ERROR("BehaviorController: Did not receive initial TKState within Timeout! Using uninitialized! This is dangerous!");
00028         }
00029 
00030         // this should block till state becomes available // old Behavior is itself;
00031         activeBehaviorPtr->willBecomeActive( seController.getLastState(), *activeBehaviorPtr);
00032 
00033         // Post active
00034         activeBehaviorPtr->didBecomeActive( seController.getLastState(), *activeBehaviorPtr);
00035 
00036         // State:
00037         transitionState = TransitionState::Active;
00038 
00039 }
00040 
00041 ActiveBehaviorContainer::~ActiveBehaviorContainer() {
00042         // TODO Auto-generated destructor stub
00043 }
00044 
00045 // Callbacks only come in after constructor is finished (Because of subscription point)
00046 void ActiveBehaviorContainer::trajectoryStep(const TKState& currentState, TKTrajectory& generatedTrajInput)
00047 {
00048         // Cannot Ask for Behaviorchange during this CB. Additionally prevents from calling this in parallel.
00049         boost::mutex::scoped_lock lock(behaviorChangeRequestMutex);
00050 
00051         // Currently changing Behavior?
00052         if (behaviorChangeMutex.try_lock()) {
00053 
00054                 // no Change Thread running
00055                 if (activeBehaviorPtr->isValid(currentState)) {
00056                         // Active
00057                         activeBehaviorPtr->trajectoryStepActive(currentState, generatedTrajInput);
00058 
00059                         // unlock again
00060                         behaviorChangeMutex.unlock();
00061                 } else {
00062                         // InValid -> active in Termination
00063                         activeBehaviorPtr->trajectoryStepTermination(currentState, generatedTrajInput);
00064                         transitionState = TransitionState::Termination;
00065 
00066                         // Start Switch Thread...
00067                         Behavior* next = NULL; // NULL means Normalbrake!
00068                         if (activeBehaviorPtr->hasNextBehavior()) {
00069                                 next = activeBehaviorPtr->getNextBehavior();
00070                         }
00071 
00072                         // null or not ok? -> Ground or Normalbrake
00073                         if (!next || !checkNewBehavior(next)) {
00074                                 if (activeBehaviorPtr->getType() == BehaviorType::Ground) {
00075                                         next =  behaviorController.getSystemBehaviorContainer().getGround();
00076                                 } else {
00077                                         // Liftoff, Land and Air changeerrors
00078                                         next = behaviorController.getSystemBehaviorContainer().getNormalBrake();
00079                                 }
00080                         }
00081 
00082 
00083                         // change Behavior
00084                         behaviorChangeThread = boost::thread(&ActiveBehaviorContainer::switchToBehaviorThread, this, next);
00085 
00086                         // Unlock is done by thread
00087                 }
00088 
00089         } else {
00090 
00091                 // Change Thread Running.
00092                 //ROS_ERROR("Currently Changing Behavior");
00093                 // We have to check what state we are in
00094 
00095                 switch (transitionState.index()) {
00096                 case TransitionState::Active:
00097                         if (activeBehaviorPtr->isValid(currentState)) {
00098                                 activeBehaviorPtr->trajectoryStepActive(currentState, generatedTrajInput);
00099                         } else {
00100                                 // New Behavior is already invalid! But change still in Progress. Call Termination Trajectory Step of
00101                                 // this Behavior until previous Change has finished -> Then it automatically causes Change request.
00102                                 activeBehaviorPtr->trajectoryStepTermination(currentState, generatedTrajInput);
00103                         }
00104                         break;
00105                 case TransitionState::Termination:
00106                         activeBehaviorPtr->trajectoryStepTermination(currentState, generatedTrajInput);
00107                         break;
00108                 case TransitionState::Creation:
00109                         activeBehaviorPtr->trajectoryStepCreation(currentState, generatedTrajInput);
00110                         break;
00111                 default:
00112                         // never happens.
00113                         break;
00114                 }
00115         }
00116 }
00117 
00118 bool ActiveBehaviorContainer::checkNewBehavior(Behavior* newBehavior) const
00119 {
00120         // newBehavior must not be the active one
00121         if (activeBehaviorPtr == newBehavior) {
00122                 ROS_ERROR_STREAM("Prevented Behavior Switch of " << activeBehaviorPtr->getName() << ", because the Behavior is already active!");
00123                 return false;
00124         }
00125 
00126         // Valid Behavior Check
00127         if (!BehaviorContainer::behaviorInstanceExists(newBehavior)) {
00128                 ROS_ERROR_STREAM("Cannot switch Behavior to ID " << (uint64_t)newBehavior << ", because it does not exist.");
00129                 return false;
00130         }
00131 
00132         // is Allowed Transition?
00133         if (!activeBehaviorPtr->canTransitionTo(*newBehavior)) {
00134                 ROS_ERROR_STREAM("Transition from "
00135                                 << activeBehaviorPtr->getName() << " (" <<  activeBehaviorPtr->getType().str() <<")"
00136                                 << " to "
00137                                 << newBehavior->getName() << " (" <<  newBehavior->getType().str() <<")"
00138                                 << " is an unallowed transition.");
00139                 return false;
00140         }
00141 
00142         // Check for Parameter Initalization
00143         if (!newBehavior->isParameterInitialized() ) {
00144                 ROS_ERROR_STREAM("Cannot switch to Behavior " << newBehavior->getName() <<
00145                                 " ID: "<< (uint64_t)newBehavior << ", because it is not Parameter Initalized!");
00146                 return false;
00147         }
00148 
00149         return true;
00150 }
00151 
00152 // Switch to Behavior
00153 bool ActiveBehaviorContainer::switchToBehavior(Behavior* newBehavior)
00154 {
00155         // Only do switch to Behavior if not in TrajectoryStep Callback.
00156         boost::mutex::scoped_lock lock(behaviorChangeRequestMutex);
00157 
00158         // Mutex try_lock.?
00159         if (!behaviorChangeMutex.try_lock()) {
00160                 ROS_ERROR_STREAM("Prevented Behavior Switch of " << activeBehaviorPtr->getName() << ", because a Switch is currently in progess!");
00161                 return false;
00162         }
00163 
00164         if (!checkNewBehavior(newBehavior)) {
00165                 // transition not ok
00166                 behaviorChangeMutex.unlock();
00167                 return false;
00168         }
00169 
00170         transitionState = TransitionState::Termination;
00171 
00172         // has lock - start change Thread
00173         behaviorChangeThread = boost::thread(&ActiveBehaviorContainer::switchToBehaviorThread, this, newBehavior);
00174 
00175         return true;
00176 }
00177 
00178 void ActiveBehaviorContainer::switchToBehaviorThread(Behavior* newBehavior)
00179 {
00180         // Inform Behavior about the switch. If this returns false. The behavior prevents the switch!
00181         if (!newBehavior->willBecomeActive( seController.getLastState(), *activeBehaviorPtr ) ) {
00182                 ROS_ERROR_STREAM("Cannot switch to Behavior " << newBehavior->getName() <<
00183                                 " ID: "<< newBehavior->getIDString() << ", because it denied the switch.");
00184 
00185 
00186                 // Go to Ground or NormalBrake
00187                 if (activeBehaviorPtr->getType() == BehaviorType::Ground) {
00188                         newBehavior =  behaviorController.getSystemBehaviorContainer().getGround();
00189                 } else {
00190                         // Liftoff, Land and Air changeerrors
00191                         newBehavior = behaviorController.getSystemBehaviorContainer().getNormalBrake();
00192                 }
00193 
00194                 // if we are already in Normalbrake or Ground. exit.
00195                 if (newBehavior == activeBehaviorPtr) {
00196                         behaviorChangeMutex.unlock();
00197                         return;
00198                 }
00199 
00200 
00201                 //** Note: These Behaviors must always returns true.
00202                 if (!newBehavior->willBecomeActive( seController.getLastState(), *activeBehaviorPtr )) {
00203                         ROS_FATAL("SytemBehavior %s willBecomeActive returned false. THIS MUST NOT HAPPEN!", newBehavior->getName().c_str());
00204                 }
00205         }
00206 
00207         // Inform old
00208         activeBehaviorPtr->willBecomeInActive( seController.getLastState(), *newBehavior );
00209 
00210         ROS_INFO_STREAM("Behavior: Switching from " << activeBehaviorPtr->getName() << " to " << newBehavior->getName());
00211 
00212         // set to new. TURNING POINT
00213         // ------------------------- //
00214         Behavior* oldBehavior = activeBehaviorPtr;
00215         activeBehaviorPtr = newBehavior;
00216         // ------------------------- //
00217 
00218         transitionState = TransitionState::Creation;
00219         // change was successful.
00220 
00221 
00222         // notify about the change
00223         behaviorController.activeBehaviorChanged();
00224         // Post-Switch Callbacks
00225         activeBehaviorPtr->didBecomeActive( seController.getLastState(), *oldBehavior );
00226 
00227         transitionState = TransitionState::Active;
00228 
00229         oldBehavior->didBecomeInActive( seController.getLastState(), *activeBehaviorPtr );
00230 
00231         // unlock
00232         behaviorChangeMutex.unlock();
00233 }
00234 
00235 Behavior* ActiveBehaviorContainer::getActive() const
00236 {
00237         return activeBehaviorPtr;
00238 }
00239 
00240 
00241 } // namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Defines


tk_behavior
Author(s): Dr. Antonio Franchi and Martin Riedel
autogenerated on Mon Nov 11 2013 11:13:36