pattern_generator.cpp
Go to the documentation of this file.
2 
4 {
6 {
7  joystick_handler_.reset(new JoystickHandler(nh));
8 
9  nh.param("world_frame_id", world_frame_id_, std::string("/world"));
10  nh.param("pattern_generator/number_of_steps", (int&)number_of_steps_needed_, 5);
11 
12  min_vel_x_ = nh.param("pattern_generator/limits/x/min", -0.1);
13  max_vel_x_ = nh.param("pattern_generator/limits/x/max", 0.1);
14  max_vel_y_ = nh.param("pattern_generator/limits/y", 0.1);
15  max_vel_yaw_ = nh.param("pattern_generator/limits/yaw", 0.1);
16 
17  ros::service::waitForService("step_plan_request");
18 
19  // start service clients: TODO use global footstep planner
20  generate_feet_pose_client_ = nh.serviceClient<msgs::GenerateFeetPoseService>("generate_feet_pose");
21  step_plan_request_client_ = nh.serviceClient<vigir_footstep_planning_msgs::StepPlanRequestService>("step_plan_request");
22 
23  // initialize action clients
25 
26  reset();
27 }
28 
30 {}
31 
32 msgs::ErrorStatus PatternGenerator::generatePattern(const msgs::StepPlanRequest& step_plan_request, msgs::StepPlan& step_plan)
33 {
34  // generate step plan request
35  msgs::StepPlanRequestService step_plan_request_srv;
36  step_plan_request_srv.request.plan_request = step_plan_request;
37 
38  // send request
39  if (!step_plan_request_client_.call(step_plan_request_srv.request, step_plan_request_srv.response))
40  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "[PatternGenerator]", "Can't call footstep planner!");
41 
42  // return new step plan
43  if (step_plan_request_srv.response.status.error == msgs::ErrorStatus::NO_ERROR)
44  step_plan = step_plan_request_srv.response.step_plan;
45 
46  return step_plan_request_srv.response.status;
47 }
48 
50 {
51  joystick_cmd_ = geometry_msgs::Twist();
52 
55 
56  start_feet_pose_.reset();
59  has_new_steps_ = false;
60 
61  clearStepPlan();
62 
63  params_.enable = false;
64 }
65 
66 void PatternGenerator::setParams(const msgs::PatternGeneratorParameters& params)
67 {
68  if (isEnabled() && params.enable)
69  {
70  // trigger replanning
71 // if (!setNextStartStepIndex(first_changeable_step_index_))
72 // {
73 // ROS_ERROR("[PatternGenerator] setParams: Replanning failed due to unknown start step.");
74 // reset();
75 // }
76  }
77  else
78  {
79  // triggers reset when enabling
80  setEnabled(params.enable);
81  }
82 
83  params_ = params;
84 }
85 
87 {
88  // activation
89  if (!isEnabled() && enable)
90  reset();
91  // deactivation
92  else if (isEnabled() && !enable)
93  generateSteps(0);
94 
95  params_.enable = enable;
96 }
97 
99 {
100  return params_.enable;
101 }
102 
104 {
105  return params_.simulation_mode;
106 }
107 
109 {
110  return !last_step_sequence_.steps.empty();
111 }
112 
114 {
115  return !last_step_sequence_.steps.empty() && has_new_steps_;
116 }
117 
118 void PatternGenerator::getCompleteStepPlan(msgs::StepPlan& step_plan) const
119 {
120  step_plan_.toMsg(step_plan);
121 }
122 
123 void PatternGenerator::getLastStepSequence(msgs::StepPlan& step_plan) const
124 {
125  has_new_steps_ = false;
126  step_plan = last_step_sequence_;
127 }
128 
130 {
132 }
133 
135 {
136  step_plan_.clear();
137  last_step_sequence_ = msgs::StepPlan();
138 }
139 
141 {
142  // (timer.current_real - timer.last_real).toSec()
143 
144  // handle joystick input
145  if (joystick_handler_ && params_.joystick_mode)
146  {
147  bool enable;
148  joystick_handler_->getJoystickCommand(joystick_cmd_, enable);
149 
150  setEnabled(enable);
151  }
152 
153  // if not enabled, just do nothing
154  if (!isEnabled())
155  return;
156 
157  // check if more steps are needed
159 
160  if (isSimulationMode())
162 }
163 
164 void PatternGenerator::updateFirstChangeableStepIndex(int first_changeable_step_index)
165 {
166  if (!isEnabled())
167  return;
168 
169  if (first_changeable_step_index < 0)
170  {
171  ROS_ERROR("[PatternGenerator] updateFirstChangeableStepIndex: Stopping due to invalid step index %i", first_changeable_step_index);
172  setEnabled(false);
173  }
174 
175  first_changeable_step_index_ = first_changeable_step_index;
176 
177  msgs::Step step;
179  {
180  if (step_plan_.getStep(step, first_changeable_step_index_-1))
181  updateFeetStartPose(step);
182  else
183  {
184  ROS_ERROR("[PatternGenerator] updateFirstChangeableStepIndex: Internal error; step %i isn't in step plan.", first_changeable_step_index);
185  setEnabled(false);
186  }
187  }
188 
189  if (step_plan_.getStep(step, first_changeable_step_index_))
190  updateFeetStartPose(step);
191  else
192  {
193  ROS_ERROR("[PatternGenerator] updateFirstChangeableStepIndex: Internal error; step %i isn't in step plan.", first_changeable_step_index);
194  setEnabled(false);
195  }
196 }
197 
198 void PatternGenerator::updateFeetStartPose(const msgs::Foot& foot)
199 {
200  if (!start_feet_pose_)
201  {
202  start_feet_pose_.reset(new msgs::Feet());
203  start_feet_pose_->header = foot.header;
204  start_feet_pose_->left.header = foot.header;
205  start_feet_pose_->left.foot_index = msgs::Foot::LEFT;
206  start_feet_pose_->right.header = foot.header;
207  start_feet_pose_->right.foot_index = msgs::Foot::RIGHT;
208  }
209 
210  if (foot.foot_index == msgs::Foot::LEFT)
211  {
212  start_feet_pose_->left.header = foot.header;
213  start_feet_pose_->left = foot;
214  }
215  if (foot.foot_index == msgs::Foot::RIGHT)
216  {
217  start_feet_pose_->right.header = foot.header;
218  start_feet_pose_->right = foot;
219  }
220 }
221 
222 void PatternGenerator::updateFeetStartPose(const msgs::Feet& feet)
223 {
224  updateFeetStartPose(feet.left);
225  updateFeetStartPose(feet.right);
226 
227  start_feet_pose_->header = feet.header;
228 }
229 
230 void PatternGenerator::updateFeetStartPose(const msgs::Step& step)
231 {
232  updateFeetStartPose(step.foot);
233 
234  start_feet_pose_->header = step.header;
235  if (step.foot.foot_index == msgs::Foot::LEFT)
236  foot_start_step_index_left_ = step.step_index;
237  if (step.foot.foot_index == msgs::Foot::RIGHT)
238  foot_start_step_index_right_ = step.step_index;
239 }
240 
242 {
243  msgs::StepPlanRequestService step_plan_request_srv;
244  msgs::StepPlanRequest& req = step_plan_request_srv.request.plan_request;
245 
246  if (!start_feet_pose_)
247  {
248  std_msgs::Header header;
249  header.frame_id = world_frame_id_;
250  header.stamp = ros::Time::now();
251  msgs::Feet start_feet;
252  determineStartFeetPose(start_feet, generate_feet_pose_client_, header);
253  updateFeetStartPose(start_feet);
254  }
255 
256  // check command input
257  geometry_msgs::Twist cmd = params_.joystick_mode ? joystick_cmd_ : params_.cmd;
258 
259  if (cmd.linear.x > 0.0)
260  cmd.linear.x *= max_vel_x_;
261  else
262  cmd.linear.x *= -min_vel_x_;
263 
264  cmd.linear.y *= max_vel_y_;
265  cmd.angular.z *= max_vel_yaw_;
266 
267  // determine which foot has to move first (note: For the planner the start foot is fixed, thus, the first moved foot is start+1)
268  unsigned int next_moving_foot_index = msgs::Foot::LEFT;
269  if (getNextStartStepIndex() == 0 || ((cmd.linear.y != 0.0 || cmd.angular.z != 0.0) && number_of_steps_needed_ > 2))
270  {
271  if (cmd.linear.y < 0.0 || (cmd.linear.y == 0.0 && cmd.angular.z < 0.0))
272  next_moving_foot_index = msgs::Foot::RIGHT;
273  else
274  next_moving_foot_index = msgs::Foot::LEFT;
275  }
276  else
277  {
278  if (foot_start_step_index_left_ < foot_start_step_index_right_) // the higher index is pointing on first changeable index
279  next_moving_foot_index = msgs::Foot::RIGHT;
280  else
281  next_moving_foot_index = msgs::Foot::LEFT;
282  }
283 
284  // generate request message
285  req.header = start_feet_pose_->header;
286  req.start = *start_feet_pose_;
287  switch (next_moving_foot_index)
288  {
289  case msgs::Foot::LEFT:
290  req.start_step_index = foot_start_step_index_right_; // reminder: first moving foot has start_index+1
291  req.start_foot_selection = msgs::StepPlanRequest::LEFT;
292  break;
293  case msgs::Foot::RIGHT:
294  req.start_step_index = foot_start_step_index_left_; // reminder: first moving foot has start_index+1
295  req.start_foot_selection = msgs::StepPlanRequest::RIGHT;
296  break;
297  default:
298  ROS_ERROR("[PatternGenerator] Unknown foot index '%u'", next_moving_foot_index);
299  return;
300  }
301 
302  // special case for n = 0
303  if (n == 0)
304  {
305  if (next_moving_foot_index == msgs::Foot::LEFT)
306  req.pattern_parameters.mode = msgs::PatternParameters::FEET_REALIGN_ON_RIGHT;
307  else
308  req.pattern_parameters.mode = msgs::PatternParameters::FEET_REALIGN_ON_LEFT;
309  }
310  else
311  {
312  req.pattern_parameters.steps = n;
313  req.pattern_parameters.step_distance_forward = cmd.linear.x;
314  req.pattern_parameters.step_distance_sideward = cmd.linear.y;
315  req.pattern_parameters.turn_angle = cmd.angular.z;
316  req.pattern_parameters.close_step = true;
317  req.pattern_parameters.extra_seperation = false;
318  req.pattern_parameters.override = false; // disable here, it will override too much by now
319  req.pattern_parameters.roll = 0.0;
320  req.pattern_parameters.pitch = 0.0;
321  req.pattern_parameters.mode = msgs::PatternParameters::SAMPLING;
322  }
323 
324  //ROS_INFO_STREAM(req);
325 
326  req.planning_mode = msgs::StepPlanRequest::PLANNING_MODE_PATTERN;
327  req.parameter_set_name = params_.parameter_set_name;
328 
329  // send request
330  if (!step_plan_request_client_.call(step_plan_request_srv.request, step_plan_request_srv.response))
331  {
332  ROS_ERROR("[PatternGenerator] Can't call footstep planner!");
333  return;
334  }
335 
336  // handle new step plan
337  if (!step_plan_request_srv.response.step_plan.steps.size())
338  {
339  ROS_ERROR("[PatternGenerator] Received empty plan!");
340  return;
341  }
342 
343  last_step_sequence_ = step_plan_request_srv.response.step_plan;
344  has_new_steps_ = true;
345 
346  if (params_.ignore_invalid_steps)
347  {
348  for (msgs::Step& step : last_step_sequence_.steps)
349  step.valid = true;
350  }
351 
352  step_plan_.updateStepPlan(last_step_sequence_);
353  step_plan_.removeSteps(last_step_sequence_.steps.back().step_index+1);
354 }
355 }
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
void update(const ros::TimerEvent &timer)
void updateFirstChangeableStepIndex(int first_changeable_step_index_)
void setParams(const msgs::PatternGeneratorParameters &params)
msgs::PatternGeneratorParameters params_
bool call(MReq &req, MRes &res)
void updateFeetStartPose(const msgs::Foot &foot)
boost::shared_ptr< actionlib::SimpleActionClient< msgs::ExecuteStepPlanAction > > execute_step_plan_ac_
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void getCompleteStepPlan(msgs::StepPlan &step_plan) const
msgs::ErrorStatus generatePattern(const msgs::StepPlanRequest &step_plan_request, msgs::StepPlan &step_plan)
static Time now()
void getLastStepSequence(msgs::StepPlan &step_plan) const
#define ROS_ERROR(...)
ROSCPP_DECL bool waitForService(const std::string &service_name, int32_t timeout)


vigir_pattern_generator
Author(s): Alexander Stumpf
autogenerated on Sun Nov 17 2019 03:30:06