step_controller_plugin.cpp
Go to the documentation of this file.
00001 #include <vigir_step_control/step_controller_plugin.h>
00002 
00003 
00004 
00005 namespace vigir_step_control
00006 {
00007 std::string toString(const StepControllerState& state)
00008 {
00009   switch (state)
00010   {
00011     case NOT_READY:   return "NOT_READY";
00012     case READY:       return "READY";
00013     case ACTIVE:      return "ACTIVE";
00014     case PAUSED:      return "PAUSED";
00015     case FINISHED:    return "FINISHED";
00016     case FAILED:      return "FAILED";
00017     default:          return "UNKNOWN";
00018   }
00019 }
00020 
00021 StepControllerPlugin::StepControllerPlugin()
00022   : vigir_pluginlib::Plugin("step_controller")
00023   , state_(NOT_READY)
00024 {
00025   step_queue_.reset(new StepQueue());
00026 
00027   reset();
00028 }
00029 
00030 StepControllerPlugin::~StepControllerPlugin()
00031 {
00032 }
00033 
00034 void StepControllerPlugin::setStepPlanMsgPlugin(vigir_footstep_planning::StepPlanMsgPlugin::Ptr plugin)
00035 {
00036   UniqueLock lock(plugin_mutex_);
00037 
00038   if (plugin)
00039     step_plan_msg_plugin_ = plugin;
00040   else
00041     ROS_ERROR("[StepControllerPlugin] Null pointer to StepPlanMsgPlugin rejected! Fix it immediately!");
00042 }
00043 
00044 StepControllerState StepControllerPlugin::getState() const
00045 {
00046   SharedLock lock(plugin_mutex_);
00047   return state_;
00048 }
00049 
00050 int StepControllerPlugin::getNextStepIndexNeeded() const
00051 {
00052   SharedLock lock(plugin_mutex_);
00053   return next_step_index_needed_;
00054 }
00055 
00056 int StepControllerPlugin::getLastStepIndexSent() const
00057 {
00058   SharedLock lock(plugin_mutex_);
00059   return last_step_index_sent_;
00060 }
00061 
00062 const msgs::ExecuteStepPlanFeedback& StepControllerPlugin::getFeedbackState() const
00063 {
00064   SharedLock lock(plugin_mutex_);
00065   return feedback_state_;
00066 }
00067 
00068 void StepControllerPlugin::reset()
00069 {
00070   step_queue_->reset();
00071 
00072   msgs::ExecuteStepPlanFeedback feedback;
00073   feedback.last_performed_step_index = -1;
00074   feedback.currently_executing_step_index = -1;
00075   feedback.first_changeable_step_index = -1;
00076   setFeedbackState(feedback);
00077 
00078   setNextStepIndexNeeded(-1);
00079   setLastStepIndexSent(-1);
00080 
00081   setState(READY);
00082 }
00083 
00084 void StepControllerPlugin::setState(StepControllerState state)
00085 {
00086   UniqueLock lock(plugin_mutex_);
00087   ROS_INFO("[StepControllerPlugin] Switching state from '%s' to '%s'.", toString(this->state_).c_str(), toString(state).c_str());
00088   this->state_ = state;
00089   feedback_state_.controller_state = state;
00090 }
00091 
00092 void StepControllerPlugin::setNextStepIndexNeeded(int index)
00093 {
00094   UniqueLock lock(plugin_mutex_);
00095   next_step_index_needed_ = index;
00096 }
00097 
00098 void StepControllerPlugin::setLastStepIndexSent(int index)
00099 {
00100   UniqueLock lock(plugin_mutex_);
00101   last_step_index_sent_ = index;
00102 }
00103 
00104 void StepControllerPlugin::setFeedbackState(const msgs::ExecuteStepPlanFeedback& feedback)
00105 {
00106   UniqueLock lock(plugin_mutex_);
00107   this->feedback_state_ = feedback;
00108 }
00109 
00110 void StepControllerPlugin::updateQueueFeedback()
00111 {
00112   UniqueLock lock(plugin_mutex_);
00113   feedback_state_.queue_size = static_cast<int>(step_queue_->size());
00114   feedback_state_.first_queued_step_index = step_queue_->firstStepIndex();
00115   feedback_state_.last_queued_step_index = step_queue_->lastStepIndex();
00116 }
00117 
00118 bool StepControllerPlugin::updateStepPlan(const msgs::StepPlan& step_plan)
00119 {
00120   if (step_plan.steps.empty())
00121     return true;
00122 
00123   // Reset controller if previous execution was finished or has failed
00124   StepControllerState state = getState();
00125   if (state == FINISHED || state == FAILED)
00126     reset();
00127 
00128   // Allow step plan updates only in READY and ACTIVE state
00129   state = getState();
00130   if (state == READY || state == ACTIVE)
00131   {
00132     msgs::ExecuteStepPlanFeedback feedback = getFeedbackState();
00133 
00134     if (step_queue_->updateStepPlan(step_plan, feedback.first_changeable_step_index))
00135     {
00136       // resets last_step_index_sent counter to trigger (re)executing steps in process()
00137       if (state == ACTIVE)
00138         setLastStepIndexSent(feedback.first_changeable_step_index-1);
00139 
00140       updateQueueFeedback();
00141 
00142       ROS_INFO("[StepControllerPlugin] Updated step queue from [%i; %i]. Current queue has steps in range [%i; %i].", step_plan.steps.front().step_index, step_plan.steps.back().step_index, step_queue_->firstStepIndex(), step_queue_->lastStepIndex());
00143 
00144       return true;
00145     }
00146   }
00147 
00148   setState(FAILED);
00149   return false;
00150 }
00151 
00152 void StepControllerPlugin::preProcess(const ros::TimerEvent& /*event*/)
00153 {
00154   // check if new walking request has been done
00155   if (getState() == READY && !step_queue_->empty())
00156   {
00157     // check consisty
00158     if (step_queue_->firstStepIndex() != 0)
00159     {
00160       ROS_ERROR("[StepControllerPlugin] Step plan doesn't start with initial step (step_index = 0). Execution aborted!");
00161       setState(FAILED);
00162     }
00163     else
00164     {
00165       initWalk();
00166     }
00167   }
00168 }
00169 
00170 void StepControllerPlugin::process(const ros::TimerEvent& /*event*/)
00171 {
00172   // execute steps
00173   if (getState() == ACTIVE)
00174   {
00175     // spool all requested steps
00176     while (getLastStepIndexSent() < getNextStepIndexNeeded())
00177     {
00178       // check if queue isn't empty
00179       if (step_queue_->empty())
00180       {
00181         ROS_ERROR("[StepControllerPlugin] Step %i required but queue is empty. Execution aborted!", getNextStepIndexNeeded());
00182         setState(FAILED);
00183         return;
00184       }
00185 
00186       // determine next step index
00187       int next_step_index = getLastStepIndexSent()+1;
00188       msgs::Step step;
00189 
00190       // retrieve next step
00191       if (!step_queue_->getStep(step, next_step_index))
00192       {
00193         ROS_ERROR("[StepControllerPlugin] Missing step %i in queue. Execution aborted!", next_step_index);
00194         setState(FAILED);
00195         return;
00196       }
00197 
00198       ROS_ASSERT(next_step_index == step.step_index);
00199 
00200       // send step to walking engine
00201       if (!executeStep(step))
00202       {
00203         ROS_ERROR("[StepControllerPlugin] Error while execution request of step %i. Execution aborted!", next_step_index);
00204         setState(FAILED);
00205         return;
00206       }
00207 
00208       // increment last_step_index_sent
00209       setLastStepIndexSent(next_step_index);
00210     }
00211   }
00212 }
00213 
00214 void StepControllerPlugin::postProcess(const ros::TimerEvent& /*event*/)
00215 {
00216   if (getState() == READY)
00217     return;
00218 
00219   msgs::ExecuteStepPlanFeedback feedback = getFeedbackState();
00220 
00221   // garbage collection: remove already executed steps
00222   if (step_queue_->firstStepIndex() <= feedback.last_performed_step_index)
00223     step_queue_->removeSteps(0, feedback.last_performed_step_index);
00224 
00225   // update feedback
00226   updateQueueFeedback();
00227 }
00228 
00229 void StepControllerPlugin::stop()
00230 {
00231   UniqueLock lock(plugin_mutex_);
00232 
00233   ROS_INFO("[StepControllerPlugin] Stop requested. Resetting walk controller.");
00234   reset();
00235 }
00236 } // namespace


vigir_step_control
Author(s): Alexander Stumpf
autogenerated on Thu Jun 6 2019 21:13:33