recovery_action.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018, Magazino GmbH, Sebastian Pütz, Jorge Santos Simón
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following
13  * disclaimer in the documentation and/or other materials provided
14  * with the distribution.
15  *
16  * 3. Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * recovery_action.cpp
34  *
35  * authors:
36  * Sebastian Pütz <spuetz@uni-osnabrueck.de>
37  * Jorge Santos Simón <santos@magazino.eu>
38  *
39  */
40 
42 
43 namespace mbf_abstract_nav{
44 
45 RecoveryAction::RecoveryAction(const std::string &name, const RobotInformation &robot_info)
46  : AbstractAction(name, robot_info, boost::bind(&mbf_abstract_nav::RecoveryAction::run, this, _1, _2)){}
47 
49 {
50  ROS_DEBUG_STREAM_NAMED(name_, "Start action " << name_);
51 
52  const mbf_msgs::RecoveryGoal &goal = *(goal_handle.getGoal().get());
53  mbf_msgs::RecoveryResult result;
54  bool recovery_active = true;
55 
56  typename AbstractRecoveryExecution::RecoveryState state_recovery_input;
57 
58  while (recovery_active && ros::ok())
59  {
60  state_recovery_input = execution.getState();
61  switch (state_recovery_input)
62  {
64  break;
66  // Recovery behavior doesn't support or didn't answered to cancel and has been ruthlessly stopped
67  ROS_WARN_STREAM("Recovering \"" << goal.behavior << "\" exceeded the patience time and has been stopped!");
68  recovery_active = false; // stopping the action
69  result.outcome = mbf_msgs::RecoveryResult::CANCELED;
70  result.message = "Recovery \"" + goal.behavior + "\" exceeded the patience time";
71  goal_handle.setSucceeded(result, result.message);
72  break;
73 
75  ROS_DEBUG_STREAM_NAMED(name_, "Recovering \"" << goal.behavior << "\" was started");
76  break;
77 
79 
80  if (execution.isPatienceExceeded())
81  {
82  ROS_INFO_STREAM("Recovery behavior \"" << goal.behavior << "\" patience exceeded! Cancel recovering...");
83  if (!execution.cancel())
84  {
85  ROS_WARN_STREAM("Cancel recovering \"" << goal.behavior << "\" failed or not supported; interrupt it!");
86  execution.stop();
87  //TODO goal_handle.setAborted
88  }
89  }
90 
91  ROS_DEBUG_STREAM_THROTTLE_NAMED(3, name_, "Recovering with: " << goal.behavior);
92  break;
93 
95  // Recovery behavior supports cancel and it worked
96  recovery_active = false; // stopping the action
97  result.outcome = mbf_msgs::RecoveryResult::CANCELED;
98  result.message = "Recovering \"" + goal.behavior + "\" preempted!";
99  goal_handle.setCanceled(result, result.message);
100  ROS_DEBUG_STREAM_NAMED(name_, result.message);
101  break;
102 
104  recovery_active = false; // stopping the action
105  result.outcome = execution.getOutcome();
106  result.message = execution.getMessage();
107  if (result.message.empty())
108  {
109  if (result.outcome < 10)
110  result.message = "Recovery \"" + goal.behavior + "\" done";
111  else
112  result.message = "Recovery \"" + goal.behavior + "\" FAILED";
113  }
114 
115  ROS_DEBUG_STREAM_NAMED(name_, result.message);
116  goal_handle.setSucceeded(result, result.message);
117  break;
118 
120  ROS_FATAL_STREAM_NAMED(name_, "Internal error: Unknown error thrown by the plugin!"); // TODO getMessage from recovery
121  recovery_active = false;
122  result.outcome = mbf_msgs::RecoveryResult::INTERNAL_ERROR;
123  result.message = "Internal error: Unknown error thrown by the plugin!";
124  goal_handle.setAborted(result, result.message);
125  break;
126 
127  default:
128  result.outcome = mbf_msgs::RecoveryResult::INTERNAL_ERROR;
129  std::stringstream ss;
130  ss << "Internal error: Unknown state in a move base flex recovery execution with the number: "
131  << static_cast<int>(state_recovery_input);
132  result.message = ss.str();
133  ROS_FATAL_STREAM_NAMED(name_, result.message);
134  goal_handle.setAborted(result, result.message);
135  recovery_active = false;
136  }
137 
138  if (recovery_active)
139  {
140  // try to sleep a bit
141  // normally the thread should be woken up from the recovery unit
142  // in order to transfer the results to the controller
143  execution.waitForStateUpdate(boost::chrono::milliseconds(500));
144  }
145  } // while (recovery_active && ros::ok())
146 
147  if (!recovery_active)
148  {
149  ROS_DEBUG_STREAM_NAMED(name_, "\"" << name_ << "\" action ended properly.");
150  }
151  else
152  {
153  ROS_ERROR_STREAM_NAMED(name_, "\"" << name_ << "\" action has been stopped!");
154  }
155 }
156 
157 } /* namespace mbf_abstract_nav */
158 
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
void run(GoalHandle &goal_handle, AbstractRecoveryExecution &execution)
boost::shared_ptr< const Goal > getGoal() const
AbstractRecoveryExecution::RecoveryState getState()
Returns the current state, thread-safe communication.
std::string getMessage()
Gets the current plugin execution message.
void setCanceled(const Result &result=Result(), const std::string &text=std::string(""))
void waitForStateUpdate(boost::chrono::microseconds const &duration)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
#define ROS_FATAL_STREAM_NAMED(name, args)
ROSCPP_DECL bool ok()
#define ROS_WARN_STREAM(args)
virtual bool cancel()
Cancel the planner execution. This calls the cancel method of the planner plugin. This could be usefu...
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
The AbstractRecoveryExecution class loads and binds the recovery behavior plugin. It contains a threa...
#define ROS_INFO_STREAM(args)
bool isPatienceExceeded()
Checks whether the patience was exceeded.
The recovery execution thread has been started.
RecoveryAction(const std::string &name, const RobotInformation &robot_info)
uint32_t getOutcome()
Gets the current plugin execution outcome.
#define ROS_DEBUG_STREAM_THROTTLE_NAMED(period, name, args)


mbf_abstract_nav
Author(s): Sebastian Pütz
autogenerated on Tue Jun 18 2019 19:34:34