footstep_planner_node.cpp
Go to the documentation of this file.
2 
3 #include <vigir_footstep_planning_lib/helper.h>
4 #include <vigir_footstep_planning_lib/visualization/footstep_planning_vis.h>
5 
6 #include <vigir_footstep_planning_plugins/plugins/state_generator_plugin.h>
7 #include <vigir_footstep_planning_plugins/plugins/robot_model_plugin.h>
8 #include <vigir_footstep_planning_plugins/plugins/step_plan_msg_plugin.h>
9 #include <vigir_footstep_planning_plugins/plugins/collision_check_plugin.h>
10 #include <vigir_footstep_planning_plugins/plugins/terrain_model_plugin.h>
11 
12 
13 
15 {
17 {
18 }
19 
21 {
22  vigir_pluginlib::PluginManager::addPluginClassLoader<StateGeneratorPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::StateGeneratorPlugin");
23  vigir_pluginlib::PluginManager::addPluginClassLoader<StepPlanMsgPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::StepPlanMsgPlugin");
24  vigir_pluginlib::PluginManager::addPluginClassLoader<ReachabilityPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::ReachabilityPlugin");
25  vigir_pluginlib::PluginManager::addPluginClassLoader<StepCostEstimatorPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::StepCostEstimatorPlugin");
26  vigir_pluginlib::PluginManager::addPluginClassLoader<HeuristicPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::HeuristicPlugin");
27  vigir_pluginlib::PluginManager::addPluginClassLoader<PostProcessPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::PostProcessPlugin");
28  vigir_pluginlib::PluginManager::addPluginClassLoader<CollisionCheckPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::CollisionCheckPlugin");
29  vigir_pluginlib::PluginManager::addPluginClassLoader<TerrainModelPlugin>("vigir_footstep_planning_plugins", "vigir_footstep_planning::TerrainModelPlugin");
30 
32  //vigir_pluginlib::PluginManager::addPlugin(new RobotModelPlugin(nh));
33 }
34 
36 {
37  initPlugins(nh);
38 
39  getFootSize(nh, foot_size);
40 
41  // init planner
42  footstep_planner.reset(new FootstepPlanner(nh));
43 
44  // subscribe topics
45  set_active_parameter_set_sub = nh.subscribe<std_msgs::String>("set_active_parameter_set", 1, &FootstepPlannerNode::setParams, this);
46  step_plan_request_sub = nh.subscribe("step_plan_request", 1, &FootstepPlannerNode::stepPlanRequest, this);
48 
49  // publish topics
50  step_plan_pub = nh.advertise<msgs::StepPlan>("step_plan", 1);
51  step_plan_request_vis_pub = nh.advertise<msgs::StepPlanRequest>("vis/step_plan_request", 1);
52  step_plan_vis_pub = nh.advertise<msgs::StepPlan>("vis/step_plan", 1);
53  error_status_pub = nh.advertise<msgs::ErrorStatus>("error_status", 1);
54  temp_step_plan_pub = nh.advertise<msgs::StepPlan>("temp_step_plan", 1);
55  feedback_pub = nh.advertise<msgs::PlanningFeedback>("planning_feedback", 1);
56 
57  // start service clients
58  generate_feet_pose_client = nh.serviceClient<msgs::GenerateFeetPoseService>("generate_feet_pose");
59 
60  // start own services
65 
66  // init action servers
67  step_plan_request_as = SimpleActionServer<msgs::StepPlanRequestAction>::create(nh, "step_plan_request", true, boost::bind(&FootstepPlannerNode::stepPlanRequestAction, this, boost::ref(step_plan_request_as))
68  , boost::bind(&FootstepPlannerNode::stepPlanRequestPreempt, this, boost::ref(step_plan_request_as)));
69  update_foot_as = SimpleActionServer<msgs::UpdateFootAction>::create(nh, "update_foot", true, boost::bind(&FootstepPlannerNode::updateFootAction, this, boost::ref(update_foot_as)));
70  update_feet_as = SimpleActionServer<msgs::UpdateFeetAction>::create(nh, "update_feet", true, boost::bind(&FootstepPlannerNode::updateFeetAction, this, boost::ref(update_feet_as)));
71  update_step_plan_as = SimpleActionServer<msgs::UpdateStepPlanAction>::create(nh, "update_step_plan", true, boost::bind(&FootstepPlannerNode::updateStepPlanAction, this, boost::ref(update_step_plan_as)));
72 }
73 
75 {
76 }
77 
78 // --- Callbacks ---
79 
80 void FootstepPlannerNode::planningResultCallback(const msgs::StepPlanRequestService::Response& resp)
81 {
82  // check result
83  if (hasError(resp.status))
84  {
85  ROS_ERROR("[FootstepPlannerNode] Error while planning steps:\n%s", toString(resp.status).c_str());
86  return;
87  }
88  else if (hasWarning(resp.status))
89  ROS_WARN("[FootstepPlannerNode] Warning occured:\n%s", toString(resp.status).c_str());
90 
91  // publish and visualize plan
92  step_plan_pub.publish(resp.step_plan);
93  temp_step_plan_pub.publish(resp.step_plan);
94  step_plan_vis_pub.publish(resp.step_plan);
95  error_status_pub.publish(resp.status);
96 }
97 
98 void FootstepPlannerNode::planningResultActionCallback(const msgs::StepPlanRequestService::Response& resp, SimpleActionServer<msgs::StepPlanRequestAction>::Ptr& as)
99 {
100  boost::recursive_mutex::scoped_lock lock(step_plan_request_as_mutex);
101 
102  // finish action server
103  msgs::StepPlanRequestResult result;
104 
105  result.step_plan = resp.step_plan;
106  result.status = resp.status;
107  result.final_eps = resp.final_eps;
108  result.planning_time = resp.planning_time;
109 
110  as->finish(result);
111 
112  // check result
113  if (hasError(resp.status))
114  {
115  ROS_ERROR("[FootstepPlannerNode] Error while planning steps:\n%s", toString(resp.status).c_str());
116  return;
117  }
118  else if (hasWarning(resp.status))
119  ROS_WARN("[FootstepPlannerNode] Warning occured:\n%s", toString(resp.status).c_str());
120 
121  // publish and visualize plan
122  temp_step_plan_pub.publish(resp.step_plan);
123  step_plan_vis_pub.publish(resp.step_plan);
124  error_status_pub.publish(resp.status);
125 }
126 
127 void FootstepPlannerNode::planningFeedbackCallback(const msgs::PlanningFeedback& feedback)
128 {
129  feedback_pub.publish(feedback);
130 }
131 
132 void FootstepPlannerNode::planningFeedbackActionCallback(const msgs::PlanningFeedback& feedback, SimpleActionServer<msgs::StepPlanRequestAction>::Ptr& as)
133 {
134  planningFeedbackCallback(feedback);
135 
136  msgs::StepPlanRequestFeedback fb;
137  fb.feedback = feedback;
138  as->publishFeedback(fb);
139 }
140 
141 void FootstepPlannerNode::planningPreemptionActionCallback(SimpleActionServer<msgs::StepPlanRequestAction>::Ptr& as)
142 {
143  boost::recursive_mutex::scoped_lock lock(step_plan_request_as_mutex);
144 
145  if (as->isActive())
146  as->setPreempted();
147 }
148 
149 // --- Subscriber calls ---
150 
151 void FootstepPlannerNode::setParams(const std_msgs::StringConstPtr& params_name)
152 {
153  vigir_generic_params::ParameterSet params;
154 
155  if (!ParameterManager::getParameterSet(params_name->data, params))
156  ROS_ERROR("[FootstepPlannerNode] setParams: Unknown parameter set '%s'!", params_name->data.c_str());
157  else if (!footstep_planner->setParams(params))
158  ROS_ERROR("[FootstepPlannerNode] setParams: Couldn't set parameter set '%s'!", params_name->data.c_str());
159  else
160  ParameterManager::setActive(params_name->data);
161 }
162 
163 void FootstepPlannerNode::stepPlanRequest(const msgs::StepPlanRequestConstPtr &plan_request)
164 {
165  msgs::ErrorStatus status;
166  msgs::StepPlanRequestService::Request step_plan_request;
167  step_plan_request.plan_request = *plan_request;
168 
169  // generate start feet pose if needed
170  if (step_plan_request.plan_request.start.header.frame_id.empty())
171  {
172  status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlannerNode", "stepPlanRequest: No valid frame_id was given as start pose. Try to use current robot pose as start.");
173  status += determineStartFeetPose(step_plan_request.plan_request.start, generate_feet_pose_client, step_plan_request.plan_request.header);
174 
175  if (hasError(status))
176  {
177  ROS_WARN("[FootstepPlannerNode] Can't obtain start feet pose:\n%s", toString(status).c_str());
178  return;
179  }
180  else if (hasWarning(status))
181  ROS_WARN("[FootstepPlannerNode] Warning occured while obtaining start feet pose:\n%s", toString(status).c_str());
182  }
183 
184  step_plan_request_vis_pub.publish(step_plan_request.plan_request);
185 
186  // start planning
187  status = footstep_planner->stepPlanRequest(step_plan_request, boost::bind(&FootstepPlannerNode::planningResultCallback, this, _1)
188  , boost::bind(&FootstepPlannerNode::planningFeedbackCallback, this, _1));
189 
190  if (!isOk(status))
191  ROS_INFO("[FootstepPlannerNode] stepPlanRequest:\n%s", toString(status).c_str());
192 }
193 
194 void FootstepPlannerNode::goalPoseCallback(const geometry_msgs::PoseStampedConstPtr& goal_pose)
195 {
196  // get start feet pose
197  msgs::Feet start_feet_pose;
198  msgs::ErrorStatus status = determineStartFeetPose(start_feet_pose, generate_feet_pose_client, goal_pose->header);
199 
200  //start_feet_pose.left.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0.0, -0.1, -0.05);
201  //start_feet_pose.right.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0.0, -0.1, 0.05);
202 
203  if (hasError(status))
204  {
205  ROS_WARN("[FootstepPlannerNode] Can't obtain start feet pose:\n%s", toString(status).c_str());
206  return;
207  }
208  else if (hasWarning(status))
209  ROS_WARN("[FootstepPlannerNode] Warning occured while obtaining start feet pose:\n%s", toString(status).c_str());
210 
211  // get goal feet pose
212  msgs::Feet goal_feet_pose;
213  goal_feet_pose.left.pose.position.z = goal_feet_pose.right.pose.position.z = start_feet_pose.left.pose.position.z;
214  status = determineGoalFeetPose(goal_feet_pose, generate_feet_pose_client, *goal_pose);
215 
216  if (hasError(status))
217  {
218  ROS_WARN("[FootstepPlannerNode] Can't obtain goal feet pose:\n%s", toString(status).c_str());
219  return;
220  }
221  else if (hasWarning(status))
222  ROS_WARN("[FootstepPlannerNode] Warning occured while obtaining goal feet pose:\n%s", toString(status).c_str());
223 
224  footstep_planner->updateFeet(goal_feet_pose, msgs::UpdateMode::UPDATE_MODE_MOVE_TO_VALID);
225 
226  // request step plan
227  msgs::StepPlanRequestService::Request step_plan_request;
228  step_plan_request.plan_request.header = goal_pose->header;
229  step_plan_request.plan_request.start = start_feet_pose;
230  step_plan_request.plan_request.goal = goal_feet_pose;
231  step_plan_request.plan_request.start_step_index = 0;
232  step_plan_request.plan_request.start_foot_selection = msgs::StepPlanRequest::AUTO;
233  step_plan_request.plan_request.planning_mode = WorldModel::instance().isTerrainModelAvailable() ? static_cast<uint8_t>(msgs::StepPlanRequest::PLANNING_MODE_3D)
234  : static_cast<uint8_t>(msgs::StepPlanRequest::PLANNING_MODE_2D);
235  step_plan_request.plan_request.max_planning_time = 0.0;
236  step_plan_request.plan_request.max_number_steps = 0.0;
237  step_plan_request.plan_request.max_path_length_ratio = 0.0;
238  step_plan_request.plan_request.parameter_set_name.data = std::string();
239 
240  // visualize request
241  step_plan_request_vis_pub.publish(step_plan_request.plan_request);
242 
243  // start planning
244  status = footstep_planner->stepPlanRequest(step_plan_request, boost::bind(&FootstepPlannerNode::planningResultCallback, this, _1)
245  , boost::bind(&FootstepPlannerNode::planningFeedbackCallback, this, _1));
246 
247  if (!isOk(status))
248  ROS_INFO("[FootstepPlannerNode] goalPoseCallback:\n%s", toString(status).c_str());
249 }
250 
251 // --- service calls ---
252 
253 bool FootstepPlannerNode::stepPlanRequestService(msgs::StepPlanRequestService::Request &req, msgs::StepPlanRequestService::Response &resp)
254 {
255  // generate start feet pose if needed
256  if (req.plan_request.start.header.frame_id.empty())
257  {
258  resp.status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlannerNode", "stepPlanRequestService: No valid frame_id was given as start pose. Try to use current robot pose as start.");
259  resp.status += determineStartFeetPose(req.plan_request.start, generate_feet_pose_client, req.plan_request.header);
260  }
261 
262  step_plan_request_vis_pub.publish(req.plan_request);
263 
264  // start planning
265  if (!footstep_planner->stepPlanRequestService(req, resp))
266  resp.status += ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlannerNode", "stepPlanRequestService: Can't call footstep planner service!");
267 
268  temp_step_plan_pub.publish(msgs::StepPlanConstPtr(new msgs::StepPlan(resp.step_plan)));
269  step_plan_vis_pub.publish(msgs::StepPlanConstPtr(new msgs::StepPlan(resp.step_plan)));
270  error_status_pub.publish(msgs::ErrorStatusConstPtr(new msgs::ErrorStatus(resp.status)));
271 
272  return true; // return always true so the message is returned
273 }
274 
275 bool FootstepPlannerNode::updateFootService(msgs::UpdateFootService::Request &req, msgs::UpdateFootService::Response &resp)
276 {
277  resp.foot = req.foot;
278  resp.status = footstep_planner->updateFoot(resp.foot, req.update_mode.mode);
279  return true; // return always true so the message is returned
280 }
281 
282 bool FootstepPlannerNode::updateFeetService(msgs::UpdateFeetService::Request &req, msgs::UpdateFeetService::Response &resp)
283 {
284  resp.feet = req.feet;
285  resp.status = footstep_planner->updateFeet(resp.feet, req.update_mode.mode);
286  return true; // return always true so the message is returned
287 }
288 
289 bool FootstepPlannerNode::updateStepPlanService(msgs::UpdateStepPlanService::Request &req, msgs::UpdateStepPlanService::Response &resp)
290 {
291  resp.step_plan = req.step_plan;
292  resp.status = footstep_planner->updateStepPlan(resp.step_plan, req.update_mode.mode, req.parameter_set_name.data);
293  step_plan_vis_pub.publish(msgs::StepPlanConstPtr(new msgs::StepPlan(resp.step_plan)));
294  return true; // return always true so the message is returned
295 }
296 
297 //--- action server calls ---
298 
299 void FootstepPlannerNode::stepPlanRequestAction(SimpleActionServer<msgs::StepPlanRequestAction>::Ptr& as)
300 {
301  // preempt any previous goal if active due to given callback
302  footstep_planner->preemptPlanning();
303 
304  boost::recursive_mutex::scoped_lock lock(step_plan_request_as_mutex);
305 
306  // accept new goal
307  const msgs::StepPlanRequestGoalConstPtr& goal(as->acceptNewGoal());
308 
309  // check if new goal was preempted in the meantime
310  if (as->isPreemptRequested())
311  {
312  as->setPreempted();
313  return;
314  }
315 
316  msgs::ErrorStatus status;
317  msgs::StepPlanRequestService::Request step_plan_request;
318  step_plan_request.plan_request = goal->plan_request;
319 
320  // generate start feet pose if needed
321  if (step_plan_request.plan_request.start.header.frame_id.empty())
322  {
323  status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlannerNode", "stepPlanRequestAction: No valid frame_id was given as start pose. Try to use current robot pose as start.");
324  status += determineStartFeetPose(step_plan_request.plan_request.start, generate_feet_pose_client, step_plan_request.plan_request.header);
325  }
326 
327  step_plan_request_vis_pub.publish(step_plan_request.plan_request);
328 
329  // start planning
330  status = footstep_planner->stepPlanRequest(step_plan_request, boost::bind(&FootstepPlannerNode::planningResultActionCallback, this, _1, boost::ref(as))
331  , boost::bind(&FootstepPlannerNode::planningFeedbackActionCallback, this, _1, boost::ref(as))
332  , boost::bind(&FootstepPlannerNode::planningPreemptionActionCallback, this, boost::ref(as)));
333 
334  if (!isOk(status))
335  ROS_INFO("[FootstepPlannerNode] stepPlanRequest:\n%s", toString(status).c_str());
336 }
337 
338 void FootstepPlannerNode::stepPlanRequestPreempt(SimpleActionServer<msgs::StepPlanRequestAction>::Ptr& as)
339 {
340  boost::recursive_mutex::scoped_lock lock(step_plan_request_as_mutex);
341 
342  if (as->isActive())
343  {
344  footstep_planner->preemptPlanning();
345  as->setPreempted();
346  }
347 }
348 
349 void FootstepPlannerNode::updateFootAction(SimpleActionServer<msgs::UpdateFootAction>::Ptr& as)
350 {
351  const msgs::UpdateFootGoalConstPtr& goal(as->acceptNewGoal());
352 
353  // check if new goal was preempted in the meantime
354  if (as->isPreemptRequested())
355  {
356  as->setPreempted();
357  return;
358  }
359 
360  msgs::UpdateFootResult result;
361  result.foot = goal->foot;
362  result.status = footstep_planner->updateFoot(result.foot, goal->update_mode.mode);
363 
364  as->finish(result);
365 }
366 
367 void FootstepPlannerNode::updateFeetAction(SimpleActionServer<msgs::UpdateFeetAction>::Ptr& as)
368 {
369  const msgs::UpdateFeetGoalConstPtr& goal(as->acceptNewGoal());
370 
371  // check if new goal was preempted in the meantime
372  if (as->isPreemptRequested())
373  {
374  as->setPreempted();
375  return;
376  }
377 
378  msgs::UpdateFeetResult result;
379  result.feet = goal->feet;
380  result.status = footstep_planner->updateFeet(result.feet, goal->update_mode.mode);
381 
382  as->finish(result);
383 }
384 
385 void FootstepPlannerNode::updateStepPlanAction(SimpleActionServer<msgs::UpdateStepPlanAction>::Ptr& as)
386 {
387  const msgs::UpdateStepPlanGoalConstPtr& goal(as->acceptNewGoal());
388 
389  // check if new goal was preempted in the meantime
390  if (as->isPreemptRequested())
391  {
392  as->setPreempted();
393  return;
394  }
395 
396  msgs::UpdateStepPlanResult result;
397 
398  result.step_plan = goal->step_plan;
399  result.status = footstep_planner->updateStepPlan(result.step_plan, goal->update_mode.mode, goal->parameter_set_name.data);
400  step_plan_vis_pub.publish(msgs::StepPlanConstPtr(new msgs::StepPlan(result.step_plan)));
401 
402  as->finish(result);
403 }
404 }
405 
406 int main(int argc, char** argv)
407 {
408  ros::init(argc, argv, "vigir_footstep_planner");
409 
410  ros::NodeHandle nh;
411 
412  // ensure that node's services are set up in proper namespace
413  if (nh.getNamespace().size() <= 1)
414  nh = ros::NodeHandle("~");
415 
416  // init parameter and plugin manager
417  vigir_generic_params::ParameterManager::initialize(nh);
418  vigir_pluginlib::PluginManager::initialize(nh);
419 
420  // init footstep planner
421  vigir_footstep_planning::FootstepPlannerNode footstep_planner_node;
422  footstep_planner_node.initialize(nh);
423 
424  ros::spin();
425 
426  return 0;
427 }
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
void planningResultActionCallback(const msgs::StepPlanRequestService::Response &resp, SimpleActionServer< msgs::StepPlanRequestAction >::Ptr &as)
void setParams(const std_msgs::StringConstPtr &params_name)
A class to control the interaction between ROS and the footstep planner.
virtual void initPlugins(ros::NodeHandle &nh)
void publish(const boost::shared_ptr< M > &message) const
void updateFeetAction(SimpleActionServer< msgs::UpdateFeetAction >::Ptr &as)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void planningResultCallback(const msgs::StepPlanRequestService::Response &resp)
Wrapper class for FootstepPlanner, providing callbacks for the node functionality.
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void updateFootAction(SimpleActionServer< msgs::UpdateFootAction >::Ptr &as)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
int main(int argc, char **argv)
#define ROS_WARN(...)
void stepPlanRequest(const msgs::StepPlanRequestConstPtr &plan_request)
void planningFeedbackCallback(const msgs::PlanningFeedback &feedback)
ROSCPP_DECL void spin(Spinner &spinner)
void stepPlanRequestAction(SimpleActionServer< msgs::StepPlanRequestAction >::Ptr &as)
void updateStepPlanAction(SimpleActionServer< msgs::UpdateStepPlanAction >::Ptr &as)
bool updateStepPlanService(msgs::UpdateStepPlanService::Request &req, msgs::UpdateStepPlanService::Response &resp)
#define ROS_INFO(...)
void planningFeedbackActionCallback(const msgs::PlanningFeedback &feedback, SimpleActionServer< msgs::StepPlanRequestAction >::Ptr &as)
void stepPlanRequestPreempt(SimpleActionServer< msgs::StepPlanRequestAction >::Ptr &as)
SimpleActionServer< msgs::UpdateStepPlanAction >::Ptr update_step_plan_as
const std::string & getNamespace() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool updateFootService(msgs::UpdateFootService::Request &req, msgs::UpdateFootService::Response &resp)
bool updateFeetService(msgs::UpdateFeetService::Request &req, msgs::UpdateFeetService::Response &resp)
void planningPreemptionActionCallback(SimpleActionServer< msgs::StepPlanRequestAction >::Ptr &as)
bool stepPlanRequestService(msgs::StepPlanRequestService::Request &req, msgs::StepPlanRequestService::Response &resp)
void goalPoseCallback(const geometry_msgs::PoseStampedConstPtr &goal_pose)
SimpleActionServer< msgs::StepPlanRequestAction >::Ptr step_plan_request_as
SimpleActionServer< msgs::UpdateFootAction >::Ptr update_foot_as
#define ROS_ERROR(...)
SimpleActionServer< msgs::UpdateFeetAction >::Ptr update_feet_as
virtual void initialize(ros::NodeHandle &nh)


vigir_footstep_planner
Author(s): Alexander Stumpf
autogenerated on Sun Nov 17 2019 03:29:59