step_controller_plugin.cpp
Go to the documentation of this file.
2 
3 
4 
5 namespace vigir_step_control
6 {
7 std::string toString(const StepControllerState& state)
8 {
9  switch (state)
10  {
11  case NOT_READY: return "NOT_READY";
12  case READY: return "READY";
13  case ACTIVE: return "ACTIVE";
14  case PAUSED: return "PAUSED";
15  case FINISHED: return "FINISHED";
16  case FAILED: return "FAILED";
17  default: return "UNKNOWN";
18  }
19 }
20 
22  : vigir_pluginlib::Plugin("step_controller")
23  , state_(NOT_READY)
24 {
25  step_queue_.reset(new StepQueue());
26 
27  reset();
28 }
29 
31 {
32 }
33 
34 void StepControllerPlugin::setStepPlanMsgPlugin(vigir_footstep_planning::StepPlanMsgPlugin::Ptr plugin)
35 {
37 
38  if (plugin)
39  step_plan_msg_plugin_ = plugin;
40  else
41  ROS_ERROR("[StepControllerPlugin] Null pointer to StepPlanMsgPlugin rejected! Fix it immediately!");
42 }
43 
45 {
47  return state_;
48 }
49 
51 {
54 }
55 
57 {
59  return last_step_index_sent_;
60 }
61 
62 const msgs::ExecuteStepPlanFeedback& StepControllerPlugin::getFeedbackState() const
63 {
65  return feedback_state_;
66 }
67 
69 {
70  step_queue_->reset();
71 
72  msgs::ExecuteStepPlanFeedback feedback;
73  feedback.last_performed_step_index = -1;
74  feedback.currently_executing_step_index = -1;
75  feedback.first_changeable_step_index = -1;
76  setFeedbackState(feedback);
77 
80 
81  setState(READY);
82 }
83 
85 {
87  ROS_INFO("[StepControllerPlugin] Switching state from '%s' to '%s'.", toString(this->state_).c_str(), toString(state).c_str());
88  this->state_ = state;
89  feedback_state_.controller_state = state;
90 }
91 
93 {
96 }
97 
99 {
101  last_step_index_sent_ = index;
102 }
103 
104 void StepControllerPlugin::setFeedbackState(const msgs::ExecuteStepPlanFeedback& feedback)
105 {
107  this->feedback_state_ = feedback;
108 }
109 
111 {
113  feedback_state_.queue_size = static_cast<int>(step_queue_->size());
114  feedback_state_.first_queued_step_index = step_queue_->firstStepIndex();
115  feedback_state_.last_queued_step_index = step_queue_->lastStepIndex();
116 }
117 
118 bool StepControllerPlugin::updateStepPlan(const msgs::StepPlan& step_plan)
119 {
120  if (step_plan.steps.empty())
121  return true;
122 
123  // Reset controller if previous execution was finished or has failed
124  StepControllerState state = getState();
125  if (state == FINISHED || state == FAILED)
126  reset();
127 
128  // Allow step plan updates only in READY and ACTIVE state
129  state = getState();
130  if (state == READY || state == ACTIVE)
131  {
132  msgs::ExecuteStepPlanFeedback feedback = getFeedbackState();
133 
134  if (step_queue_->updateStepPlan(step_plan, feedback.first_changeable_step_index))
135  {
136  // resets last_step_index_sent counter to trigger (re)executing steps in process()
137  if (state == ACTIVE)
138  setLastStepIndexSent(feedback.first_changeable_step_index-1);
139 
141 
142  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());
143 
144  return true;
145  }
146  }
147 
148  setState(FAILED);
149  return false;
150 }
151 
153 {
154  // check if new walking request has been done
155  if (getState() == READY && !step_queue_->empty())
156  {
157  // check consisty
158  if (step_queue_->firstStepIndex() != 0)
159  {
160  ROS_ERROR("[StepControllerPlugin] Step plan doesn't start with initial step (step_index = 0). Execution aborted!");
161  setState(FAILED);
162  }
163  else
164  {
165  initWalk();
166  }
167  }
168 }
169 
171 {
172  // execute steps
173  if (getState() == ACTIVE)
174  {
175  // spool all requested steps
177  {
178  // check if queue isn't empty
179  if (step_queue_->empty())
180  {
181  ROS_ERROR("[StepControllerPlugin] Step %i required but queue is empty. Execution aborted!", getNextStepIndexNeeded());
182  setState(FAILED);
183  return;
184  }
185 
186  // determine next step index
187  int next_step_index = getLastStepIndexSent()+1;
188  msgs::Step step;
189 
190  // retrieve next step
191  if (!step_queue_->getStep(step, next_step_index))
192  {
193  ROS_ERROR("[StepControllerPlugin] Missing step %i in queue. Execution aborted!", next_step_index);
194  setState(FAILED);
195  return;
196  }
197 
198  ROS_ASSERT(next_step_index == step.step_index);
199 
200  // send step to walking engine
201  if (!executeStep(step))
202  {
203  ROS_ERROR("[StepControllerPlugin] Error while execution request of step %i. Execution aborted!", next_step_index);
204  setState(FAILED);
205  return;
206  }
207 
208  // increment last_step_index_sent
209  setLastStepIndexSent(next_step_index);
210  }
211  }
212 }
213 
215 {
216  if (getState() == READY)
217  return;
218 
219  msgs::ExecuteStepPlanFeedback feedback = getFeedbackState();
220 
221  // garbage collection: remove already executed steps
222  if (step_queue_->firstStepIndex() <= feedback.last_performed_step_index)
223  step_queue_->removeSteps(0, feedback.last_performed_step_index);
224 
225  // update feedback
227 }
228 
230 {
232 
233  ROS_INFO("[StepControllerPlugin] Stop requested. Resetting walk controller.");
234  reset();
235 }
236 } // namespace
virtual void reset()
Resets the plugin (called during construction and by stop()). The default implementation raises the R...
virtual void initWalk()=0
This method is called when new step plan has been enqueued and previously the walk controller state w...
std::string toString(const StepControllerState &state)
void setFeedbackState(const msgs::ExecuteStepPlanFeedback &feedback)
msgs::ExecuteStepPlanFeedback feedback_state_
virtual void preProcess(const ros::TimerEvent &event)
PreProcess Method is called before processing the walk controller, e.g. for precompute/update data or...
int getNextStepIndexNeeded() const
Returns next step index needed by the walking engine.
const msgs::ExecuteStepPlanFeedback & getFeedbackState() const
Returns current feedback information provided by the plugin.
virtual bool executeStep(const msgs::Step &step)=0
This method will be called when the next step should be added to execution pipeline. The call of this function should be triggered by the process(...) method when next_step_index_needed_ has been changed.
void updateQueueFeedback()
Updates feedback information with internal state data.
vigir_footstep_planning::StepPlanMsgPlugin::Ptr step_plan_msg_plugin_
virtual bool updateStepPlan(const msgs::StepPlan &step_plan)
Merges given step plan to the current step queue of steps. Hereby, two cases have to considered: ...
StepControllerState getState() const
Get current state of execution.
virtual void process(const ros::TimerEvent &event)
Overwrite to handle robot specific behavior. The default behavior behaves as followed: ...
#define ROS_INFO(...)
int getLastStepIndexSent() const
Returns last step index which has been sent to walking engine.
boost::unique_lock< Mutex > UniqueLock
Definition: step_queue.h:45
virtual void setStepPlanMsgPlugin(vigir_footstep_planning::StepPlanMsgPlugin::Ptr plugin)
Sets the StepPlanMsgPlugin to be used.
boost::shared_lock< Mutex > SharedLock
Definition: step_queue.h:44
#define ROS_ASSERT(cond)
virtual void postProcess(const ros::TimerEvent &event)
PostProcess Method is called after processing step, in order to sum up the current status and cleanup...
#define ROS_ERROR(...)
virtual void stop()
Will be called when (soft) stop is requested and resets plugin.


vigir_step_control
Author(s): Alexander Stumpf
autogenerated on Mon Jun 10 2019 15:44:47