00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "mbf_abstract_nav/abstract_controller_execution.h"
00042 #include <mbf_msgs/ExePathResult.h>
00043
00044 namespace mbf_abstract_nav
00045 {
00046
00047 const double AbstractControllerExecution::DEFAULT_CONTROLLER_FREQUENCY = 100.0;
00048
00049 AbstractControllerExecution::AbstractControllerExecution(
00050 const std::string name,
00051 const mbf_abstract_core::AbstractController::Ptr& controller_ptr,
00052 const ros::Publisher& vel_pub,
00053 const ros::Publisher& goal_pub,
00054 const TFPtr &tf_listener_ptr,
00055 const MoveBaseFlexConfig &config,
00056 boost::function<void()> setup_fn,
00057 boost::function<void()> cleanup_fn) :
00058 AbstractExecutionBase(name, setup_fn, cleanup_fn),
00059 controller_(controller_ptr), tf_listener_ptr(tf_listener_ptr), state_(INITIALIZED),
00060 moving_(false), max_retries_(0), patience_(0), vel_pub_(vel_pub), current_goal_pub_(goal_pub),
00061 calling_duration_(boost::chrono::microseconds(static_cast<int>(1e6 / DEFAULT_CONTROLLER_FREQUENCY)))
00062 {
00063 ros::NodeHandle nh;
00064 ros::NodeHandle private_nh("~");
00065
00066
00067 private_nh.param("robot_frame", robot_frame_, std::string("base_link"));
00068 private_nh.param("map_frame", global_frame_, std::string("map"));
00069 private_nh.param("mbf_tolerance_check", mbf_tolerance_check_, false);
00070 private_nh.param("dist_tolerance", dist_tolerance_, 0.1);
00071 private_nh.param("angle_tolerance", angle_tolerance_, M_PI / 18.0);
00072 private_nh.param("tf_timeout", tf_timeout_, 1.0);
00073
00074
00075 reconfigure(config);
00076 }
00077
00078 AbstractControllerExecution::~AbstractControllerExecution()
00079 {
00080 }
00081
00082 bool AbstractControllerExecution::setControllerFrequency(double frequency)
00083 {
00084
00085 if (frequency <= 0.0)
00086 {
00087 ROS_ERROR("Controller frequency must be greater than 0.0! No change of the frequency!");
00088 return false;
00089 }
00090 calling_duration_ = boost::chrono::microseconds(static_cast<int>(1e6 / frequency));
00091 return true;
00092 }
00093
00094 void AbstractControllerExecution::reconfigure(const MoveBaseFlexConfig &config)
00095 {
00096 boost::lock_guard<boost::mutex> guard(configuration_mutex_);
00097
00098
00099 patience_ = ros::Duration(config.controller_patience);
00100
00101 setControllerFrequency(config.controller_frequency);
00102
00103 max_retries_ = config.controller_max_retries;
00104 }
00105
00106
00107 bool AbstractControllerExecution::start()
00108 {
00109 setState(STARTED);
00110 if (moving_)
00111 {
00112 return false;
00113 }
00114 moving_ = true;
00115 return AbstractExecutionBase::start();
00116 }
00117
00118
00119 void AbstractControllerExecution::setState(ControllerState state)
00120 {
00121 boost::lock_guard<boost::mutex> guard(state_mtx_);
00122 state_ = state;
00123 }
00124
00125
00126 typename AbstractControllerExecution::ControllerState
00127 AbstractControllerExecution::getState()
00128 {
00129 boost::lock_guard<boost::mutex> guard(state_mtx_);
00130 return state_;
00131 }
00132
00133 void AbstractControllerExecution::setNewPlan(const std::vector<geometry_msgs::PoseStamped> &plan)
00134 {
00135 if (moving_)
00136 {
00137
00138 ROS_DEBUG("Setting new plan while moving");
00139 }
00140 boost::lock_guard<boost::mutex> guard(plan_mtx_);
00141 new_plan_ = true;
00142
00143 plan_ = plan;
00144 }
00145
00146
00147 bool AbstractControllerExecution::hasNewPlan()
00148 {
00149 boost::lock_guard<boost::mutex> guard(plan_mtx_);
00150 return new_plan_;
00151 }
00152
00153
00154 std::vector<geometry_msgs::PoseStamped> AbstractControllerExecution::getNewPlan()
00155 {
00156 boost::lock_guard<boost::mutex> guard(plan_mtx_);
00157 new_plan_ = false;
00158 return plan_;
00159 }
00160
00161
00162 bool AbstractControllerExecution::computeRobotPose()
00163 {
00164 bool tf_success = mbf_utility::getRobotPose(*tf_listener_ptr, robot_frame_, global_frame_,
00165 ros::Duration(tf_timeout_), robot_pose_);
00166
00167 robot_pose_.header.stamp = ros::Time::now();
00168 if (!tf_success)
00169 {
00170 ROS_ERROR_STREAM("Could not get the robot pose in the global frame. - robot frame: \""
00171 << robot_frame_ << "\" global frame: \"" << global_frame_ << std::endl);
00172 message_ = "Could not get the robot pose";
00173 outcome_ = mbf_msgs::ExePathResult::TF_ERROR;
00174 return false;
00175 }
00176 return true;
00177 }
00178
00179
00180 uint32_t AbstractControllerExecution::computeVelocityCmd(const geometry_msgs::PoseStamped& robot_pose,
00181 const geometry_msgs::TwistStamped& robot_velocity,
00182 geometry_msgs::TwistStamped& vel_cmd,
00183 std::string& message)
00184 {
00185 return controller_->computeVelocityCommands(robot_pose, robot_velocity, vel_cmd, message);
00186 }
00187
00188
00189 void AbstractControllerExecution::setVelocityCmd(const geometry_msgs::TwistStamped &vel_cmd)
00190 {
00191 boost::lock_guard<boost::mutex> guard(vel_cmd_mtx_);
00192 vel_cmd_stamped_ = vel_cmd;
00193 if (vel_cmd_stamped_.header.stamp.isZero())
00194 vel_cmd_stamped_.header.stamp = ros::Time::now();
00195
00196
00197
00198 }
00199
00200
00201 geometry_msgs::TwistStamped AbstractControllerExecution::getVelocityCmd()
00202 {
00203 boost::lock_guard<boost::mutex> guard(vel_cmd_mtx_);
00204 return vel_cmd_stamped_;
00205 }
00206
00207
00208 ros::Time AbstractControllerExecution::getLastPluginCallTime()
00209 {
00210 boost::lock_guard<boost::mutex> guard(lct_mtx_);
00211 return last_call_time_;
00212 }
00213
00214
00215 bool AbstractControllerExecution::isPatienceExceeded()
00216 {
00217 boost::lock_guard<boost::mutex> guard(lct_mtx_);
00218 return !patience_.isZero() && (ros::Time::now() - last_call_time_ > patience_);
00219 }
00220
00221
00222 bool AbstractControllerExecution::isMoving()
00223 {
00224 return moving_;
00225 }
00226
00227 bool AbstractControllerExecution::reachedGoalCheck()
00228 {
00229
00230 return controller_->isGoalReached(dist_tolerance_, angle_tolerance_) || (mbf_tolerance_check_
00231 && mbf_utility::distance(robot_pose_, plan_.back()) < dist_tolerance_
00232 && mbf_utility::angle(robot_pose_, plan_.back()) < angle_tolerance_);
00233 }
00234
00235 bool AbstractControllerExecution::cancel()
00236 {
00237 cancel_ = true;
00238
00239 if(!controller_->cancel())
00240 {
00241 ROS_WARN_STREAM("Cancel controlling failed or is not supported by the plugin. "
00242 << "Wait until the current control cycle finished!");
00243 return false;
00244 }
00245 return true;
00246 }
00247
00248
00249 void AbstractControllerExecution::run()
00250 {
00251 start_time_ = ros::Time::now();
00252
00253
00254 std::vector<geometry_msgs::PoseStamped> plan;
00255 if (!hasNewPlan())
00256 {
00257 setState(NO_PLAN);
00258 moving_ = false;
00259 ROS_ERROR("robot navigation moving has no plan!");
00260 }
00261
00262 ros::Time last_valid_cmd_time = ros::Time();
00263 int retries = 0;
00264 int seq = 0;
00265
00266 try
00267 {
00268 while (moving_ && ros::ok())
00269 {
00270 boost::chrono::thread_clock::time_point loop_start_time = boost::chrono::thread_clock::now();
00271
00272 if(cancel_){
00273 setState(CANCELED);
00274 condition_.notify_all();
00275 moving_ = false;
00276 return;
00277 }
00278
00279
00280 if (hasNewPlan())
00281 {
00282 plan = getNewPlan();
00283
00284
00285 if (plan.empty())
00286 {
00287 setState(EMPTY_PLAN);
00288 condition_.notify_all();
00289 moving_ = false;
00290 return;
00291 }
00292
00293
00294 if(!controller_->setPlan(plan))
00295 {
00296 setState(INVALID_PLAN);
00297 condition_.notify_all();
00298 moving_ = false;
00299 return;
00300 }
00301 current_goal_pub_.publish(plan.back());
00302 }
00303
00304
00305 computeRobotPose();
00306
00307
00308 if (reachedGoalCheck())
00309 {
00310 ROS_DEBUG_STREAM_NAMED("abstract_controller_execution", "Reached the goal!");
00311 setState(ARRIVED_GOAL);
00312
00313 condition_.notify_all();
00314 moving_ = false;
00315
00316 }
00317 else
00318 {
00319 setState(PLANNING);
00320
00321
00322 lct_mtx_.lock();
00323 last_call_time_ = ros::Time::now();
00324 lct_mtx_.unlock();
00325
00326
00327 geometry_msgs::TwistStamped cmd_vel_stamped;
00328 geometry_msgs::TwistStamped robot_velocity;
00329 outcome_ = computeVelocityCmd(robot_pose_, robot_velocity, cmd_vel_stamped, message_ = "");
00330
00331 if (outcome_ < 10)
00332 {
00333 setState(GOT_LOCAL_CMD);
00334 vel_pub_.publish(cmd_vel_stamped.twist);
00335 last_valid_cmd_time = ros::Time::now();
00336 retries = 0;
00337 }
00338 else
00339 {
00340 boost::lock_guard<boost::mutex> guard(configuration_mutex_);
00341 if (max_retries_ >= 0 && ++retries > max_retries_)
00342 {
00343 setState(MAX_RETRIES);
00344 moving_ = false;
00345 }
00346 else if (!patience_.isZero() && ros::Time::now() - last_valid_cmd_time > patience_
00347 && ros::Time::now() - start_time_ > patience_)
00348 {
00349
00350 setState(PAT_EXCEEDED);
00351 moving_ = false;
00352 }
00353 else
00354 {
00355 setState(NO_LOCAL_CMD);
00356 }
00357
00358 publishZeroVelocity();
00359 }
00360
00361
00362 cmd_vel_stamped.header.seq = seq++;
00363 setVelocityCmd(cmd_vel_stamped);
00364 condition_.notify_all();
00365 }
00366
00367 boost::chrono::thread_clock::time_point end_time = boost::chrono::thread_clock::now();
00368 boost::chrono::microseconds execution_duration =
00369 boost::chrono::duration_cast<boost::chrono::microseconds>(end_time - loop_start_time);
00370 configuration_mutex_.lock();
00371 boost::chrono::microseconds sleep_time = calling_duration_ - execution_duration;
00372 configuration_mutex_.unlock();
00373 if (moving_ && ros::ok())
00374 {
00375 if (sleep_time > boost::chrono::microseconds(0))
00376 {
00377
00378 boost::this_thread::sleep_for(sleep_time);
00379 }
00380 else
00381 {
00382
00383 boost::this_thread::interruption_point();
00384 ROS_WARN_THROTTLE(1.0, "Calculation needs too much time to stay in the moving frequency! (%f > %f)",
00385 execution_duration.count()/1000000.0, calling_duration_.count()/1000000.0);
00386 }
00387 }
00388 }
00389 }
00390 catch (const boost::thread_interrupted &ex)
00391 {
00392
00393
00394 ROS_DEBUG_STREAM("Controller thread interrupted!");
00395 publishZeroVelocity();
00396 setState(STOPPED);
00397 condition_.notify_all();
00398 moving_ = false;
00399 }
00400 catch (...)
00401 {
00402 message_ = "Unknown error occurred: " + boost::current_exception_diagnostic_information();
00403 ROS_FATAL_STREAM(message_);
00404 setState(INTERNAL_ERROR);
00405 }
00406 }
00407
00408
00409 void AbstractControllerExecution::publishZeroVelocity()
00410 {
00411 geometry_msgs::Twist cmd_vel;
00412 cmd_vel.linear.x = 0;
00413 cmd_vel.linear.y = 0;
00414 cmd_vel.linear.z = 0;
00415 cmd_vel.angular.x = 0;
00416 cmd_vel.angular.y = 0;
00417 cmd_vel.angular.z = 0;
00418 vel_pub_.publish(cmd_vel);
00419 }
00420
00421 }