41 #include <mbf_msgs/ExePathResult.h> 51 const std::string &name,
55 const TFPtr &tf_listener_ptr,
56 const MoveBaseFlexConfig &config) :
58 controller_(controller_ptr), tf_listener_ptr(tf_listener_ptr), state_(INITIALIZED),
59 moving_(false), max_retries_(0), patience_(0), vel_pub_(vel_pub), current_goal_pub_(goal_pub),
60 calling_duration_(
boost::chrono::microseconds(static_cast<int>(1e6 / DEFAULT_CONTROLLER_FREQUENCY)))
88 ROS_ERROR(
"Controller frequency must be greater than 0.0! No change of the frequency!");
91 calling_duration_ = boost::chrono::microseconds(static_cast<int>(1e6 / frequency));
122 boost::lock_guard<boost::mutex> guard(
state_mtx_);
130 boost::lock_guard<boost::mutex> guard(
state_mtx_);
135 const std::vector<geometry_msgs::PoseStamped> &plan,
136 bool tolerance_from_action,
137 double action_dist_tolerance,
138 double action_angle_tolerance)
143 ROS_DEBUG(
"Setting new plan while moving");
145 boost::lock_guard<boost::mutex> guard(
plan_mtx_);
157 boost::lock_guard<boost::mutex> guard(
plan_mtx_);
164 boost::lock_guard<boost::mutex> guard(
plan_mtx_);
175 ROS_ERROR_STREAM(
"Could not get the robot pose in the global frame. - robot frame: \"" 177 message_ =
"Could not get the robot pose";
178 outcome_ = mbf_msgs::ExePathResult::TF_ERROR;
186 const geometry_msgs::TwistStamped &robot_velocity,
187 geometry_msgs::TwistStamped &vel_cmd,
188 std::string &message)
190 return controller_->computeVelocityCommands(robot_pose, robot_velocity, vel_cmd, message);
215 boost::lock_guard<boost::mutex> guard(
lct_mtx_);
222 boost::lock_guard<boost::mutex> guard(
lct_mtx_);
232 ROS_DEBUG_STREAM(
"The controller plugin \"" <<
name_ <<
"\" does not return a success state (outcome < 10) for more than the patience time in multiple runs!");
266 ROS_WARN_STREAM(
"Cancel controlling failed. Wait until the current control cycle finished!");
270 if (
waitForStateUpdate(boost::chrono::milliseconds(500)) == boost::cv_status::timeout)
273 ROS_WARN_STREAM(
"Timeout while waiting for control cycle to stop; immediately sent goals can get stuck");
285 std::vector<geometry_msgs::PoseStamped> plan;
290 ROS_ERROR(
"robot navigation moving has no plan!");
301 boost::chrono::thread_clock::time_point loop_start_time = boost::chrono::thread_clock::now();
382 geometry_msgs::TwistStamped cmd_vel_stamped;
383 geometry_msgs::TwistStamped robot_velocity;
416 cmd_vel_stamped.header.seq = seq++;
421 boost::chrono::thread_clock::time_point end_time = boost::chrono::thread_clock::now();
422 boost::chrono::microseconds execution_duration =
423 boost::chrono::duration_cast<boost::chrono::microseconds>(end_time - loop_start_time);
429 if (sleep_time > boost::chrono::microseconds(0))
432 boost::this_thread::sleep_for(sleep_time);
437 boost::this_thread::interruption_point();
438 ROS_WARN_THROTTLE(1.0,
"Calculation needs too much time to stay in the moving frequency! (%f > %f)",
444 catch (
const boost::thread_interrupted &ex)
456 message_ =
"Unknown error occurred: " + boost::current_exception_diagnostic_information();
465 geometry_msgs::Twist cmd_vel;
466 cmd_vel.linear.x = 0;
467 cmd_vel.linear.y = 0;
468 cmd_vel.linear.z = 0;
469 cmd_vel.angular.x = 0;
470 cmd_vel.angular.y = 0;
471 cmd_vel.angular.z = 0;
boost::mutex plan_mtx_
mutex to handle safe thread communication for the current plan
boost::condition_variable condition_
condition variable to wake up control thread
ControllerState
Internal states.
bool new_plan_
true, if a new plan is available. See hasNewPlan()!
double angle(const geometry_msgs::PoseStamped &pose1, const geometry_msgs::PoseStamped &pose2)
bool tolerance_from_action_
whether check for action specific tolerance
std::string global_frame_
the global frame the robot is controlling in.
virtual ~AbstractControllerExecution()
Destructor.
boost::chrono::microseconds calling_duration_
the duration which corresponds with the controller frequency.
ros::Duration patience_
The time / duration of patience, before changing the state.
#define ROS_WARN_THROTTLE(rate,...)
#define ROS_DEBUG_STREAM_NAMED(name, args)
boost::mutex configuration_mutex_
dynamic reconfigure config mutex, thread safe param reading and writing
void publish(const boost::shared_ptr< M > &message) const
bool computeRobotPose()
Computes the robot pose;.
boost::mutex vel_cmd_mtx_
mutex to handle safe thread communication for the current velocity command
The controller has been stopped!
Exceeded the maximum number of retries without a valid command.
Received no velocity command by the plugin, in the current cycle.
ros::Publisher current_goal_pub_
publisher for the current goal
std::string name_
the plugin name; not the plugin type!
Got a valid velocity command from the plugin.
bool hasNewPlan()
Returns true if a new plan is available, false otherwise! A new plan is set by another thread! ...
void setVelocityCmd(const geometry_msgs::TwistStamped &vel_cmd_stamped)
Sets the velocity command, to make it available for another thread.
double dist_tolerance_
distance tolerance to the given goal pose
The controller has been started without a plan.
bool getRobotPose(const TF &tf, const std::string &robot_frame, const std::string &global_frame, const ros::Duration &timeout, geometry_msgs::PoseStamped &robot_pose)
double action_dist_tolerance_
replaces parameter dist_tolerance_ for the action
void setState(ControllerState state)
Sets the controller state. This method makes the communication of the state thread safe...
boost::cv_status waitForStateUpdate(boost::chrono::microseconds const &duration)
bool cancel_
flag for canceling controlling
ros::Publisher vel_pub_
publisher for the current velocity command
const TFPtr & tf_listener_ptr
shared pointer to the shared tf listener
virtual bool cancel()
Cancel the controller execution. This calls the cancel method of the controller plugin, sets the cancel_ flag to true, and waits for the control loop to stop. Normally called upon aborting the navigation.
std::string message_
the last received plugin execution message
static const double DEFAULT_CONTROLLER_FREQUENCY
virtual void run()
The main run method, a thread will execute this method. It contains the main controller execution loo...
geometry_msgs::TwistStamped vel_cmd_stamped_
the last calculated velocity command
Exceeded the patience time without a valid command.
bool isMoving()
Returns whether the robot should normally move or not. True if the controller seems to work properly...
bool mbf_tolerance_check_
whether move base flex should check for the goal tolerance or not.
AbstractControllerExecution::ControllerState state_
the current controller state
bool moving_
main controller loop variable, true if the controller is running, false otherwise ...
#define ROS_FATAL_STREAM(args)
bool force_stop_at_goal_
whether move base flex should force the robot to stop once the goal is reached.
bool isPatienceExceeded()
Checks whether the patience duration time has been exceeded, ot not.
double angle_tolerance_
angle tolerance to the given goal pose
virtual bool safetyCheck()
Check if its safe to drive. This method gets called at every controller cycle, stopping the robot if ...
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
boost::mutex state_mtx_
mutex to handle safe thread communication for the current value of the state
uint32_t outcome_
the last received plugin execution outcome
bool force_stop_on_cancel_
whether move base flex should force the robot to stop on canceling navigation.
The robot arrived the goal.
ros::Time getLastPluginCallTime()
Returns the time of the last plugin call.
An internal error occurred.
ros::Time start_time_
The time the controller has been started.
AbstractControllerExecution(const std::string &name, const mbf_abstract_core::AbstractController::Ptr &controller_ptr, const ros::Publisher &vel_pub, const ros::Publisher &goal_pub, const TFPtr &tf_listener_ptr, const MoveBaseFlexConfig &config)
Constructor.
std::vector< geometry_msgs::PoseStamped > getNewPlan()
Gets the new available plan. This method is thread safe.
virtual uint32_t computeVelocityCmd(const geometry_msgs::PoseStamped &pose, const geometry_msgs::TwistStamped &velocity, geometry_msgs::TwistStamped &vel_cmd, std::string &message)
Request plugin for a new velocity command, given the current position, orientation, and velocity of the robot. We use this virtual method to give concrete implementations as move_base the chance to override it and do additional stuff, for example locking the costmap.
#define ROS_WARN_STREAM(args)
#define ROS_DEBUG_STREAM(args)
double action_angle_tolerance_
replaces parameter angle_tolerance_ for the action
Received an invalid plan that the controller plugin rejected.
geometry_msgs::TwistStamped getVelocityCmd()
Returns the last velocity command calculated by the plugin. Set by setVelocityCmd method...
void setNewPlan(const std::vector< geometry_msgs::PoseStamped > &plan, bool tolerance_from_action=false, double action_dist_tolerance=1.0, double action_angle_tolerance=3.1415)
Sets a new plan to the controller execution.
double distance(const geometry_msgs::PoseStamped &pose1, const geometry_msgs::PoseStamped &pose2)
#define ROS_WARN_STREAM_THROTTLE(rate, args)
void publishZeroVelocity()
Publishes a velocity command with zero values to stop the robot.
bool reachedGoalCheck()
Checks whether the goal has been reached in the range of tolerance or not.
mbf_abstract_core::AbstractController::Ptr controller_
the local planer to calculate the velocity command
int max_retries_
The maximum number of retries.
ControllerState getState()
Return the current state of the controller execution. Thread communication safe.
boost::mutex lct_mtx_
mutex to handle safe thread communication for the last plugin call time
geometry_msgs::PoseStamped robot_pose_
current robot pose;
std::string robot_frame_
the frame of the robot, which will be used to determine its position.
void reconfigure(const MoveBaseFlexConfig &config)
Is called by the server thread to reconfigure the controller execution, if a user uses dynamic reconf...
virtual bool start()
Starts the controller, a valid plan should be given in advance.
ros::Time last_valid_cmd_time_
The time the controller responded with a success output (output < 10).
double tf_timeout_
time before a timeout used for tf requests
#define ROS_ERROR_STREAM(args)
bool setControllerFrequency(double frequency)
Sets the controller frequency.
Controller has been started.
std::vector< geometry_msgs::PoseStamped > plan_
the last set plan which is currently processed by the controller
ros::Time last_call_time_
The current cycle start time of the last cycle run. Will by updated each cycle.
The controller has been canceled.