Go to the documentation of this file.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 #include <nav_2d_utils/parameters.h>
00036 #include <dwb_critics/oscillation.h>
00037 #include <nav_core2/exceptions.h>
00038 #include <pluginlib/class_list_macros.h>
00039 #include <cmath>
00040 #include <string>
00041 #include <vector>
00042
00043 PLUGINLIB_EXPORT_CLASS(dwb_critics::OscillationCritic, dwb_local_planner::TrajectoryCritic)
00044
00045 namespace dwb_critics
00046 {
00047
00048 OscillationCritic::CommandTrend::CommandTrend()
00049 {
00050 reset();
00051 }
00052
00053 void OscillationCritic::CommandTrend::reset()
00054 {
00055 sign_ = Sign::ZERO;
00056 positive_only_ = false;
00057 negative_only_ = false;
00058 }
00059
00060 bool OscillationCritic::CommandTrend::update(double velocity)
00061 {
00062 bool flag_set = false;
00063 if (velocity < 0.0)
00064 {
00065 if (sign_ == Sign::POSITIVE)
00066 {
00067 negative_only_ = true;
00068 flag_set = true;
00069 }
00070 sign_ = Sign::NEGATIVE;
00071 }
00072 else if (velocity > 0.0)
00073 {
00074 if (sign_ == Sign::NEGATIVE)
00075 {
00076 positive_only_ = true;
00077 flag_set = true;
00078 }
00079 sign_ = Sign::POSITIVE;
00080 }
00081 return flag_set;
00082 }
00083
00084 bool OscillationCritic::CommandTrend::isOscillating(double velocity)
00085 {
00086 return (positive_only_ && velocity < 0.0) || (negative_only_ && velocity > 0.0);
00087 }
00088
00089 bool OscillationCritic::CommandTrend::hasSignFlipped()
00090 {
00091 return positive_only_ || negative_only_;
00092 }
00093
00094 void OscillationCritic::onInit()
00095 {
00096 oscillation_reset_dist_ = nav_2d_utils::searchAndGetParam(critic_nh_, "oscillation_reset_dist", 0.05);
00097 oscillation_reset_dist_sq_ = oscillation_reset_dist_ * oscillation_reset_dist_;
00098 oscillation_reset_angle_ = nav_2d_utils::searchAndGetParam(critic_nh_, "oscillation_reset_angle", 0.2);
00099 oscillation_reset_time_ = nav_2d_utils::searchAndGetParam(critic_nh_, "oscillation_reset_time", -1.0);
00100
00108 std::string resolved_name;
00109 if (critic_nh_.hasParam("x_only_threshold"))
00110 {
00111 critic_nh_.getParam("x_only_threshold", x_only_threshold_);
00112 }
00113 else if (critic_nh_.searchParam("min_speed_xy", resolved_name))
00114 {
00115 critic_nh_.getParam(resolved_name, x_only_threshold_);
00116 }
00117 else if (critic_nh_.searchParam("min_trans_vel", resolved_name))
00118 {
00119 ROS_WARN_NAMED("OscillationCritic", "Parameter min_trans_vel is deprecated. "
00120 "Please use the name min_speed_xy or x_only_threshold instead.");
00121 critic_nh_.getParam(resolved_name, x_only_threshold_);
00122 }
00123 else
00124 {
00125 x_only_threshold_ = 0.05;
00126 }
00127
00128 reset();
00129 }
00130
00131 bool OscillationCritic::prepare(const geometry_msgs::Pose2D& pose,
00132 const nav_2d_msgs::Twist2D& vel,
00133 const geometry_msgs::Pose2D& goal,
00134 const nav_2d_msgs::Path2D& global_plan)
00135 {
00136 pose_ = pose;
00137 return true;
00138 }
00139
00140 void OscillationCritic::debrief(const nav_2d_msgs::Twist2D& cmd_vel)
00141 {
00142 if (setOscillationFlags(cmd_vel))
00143 {
00144 prev_stationary_pose_ = pose_;
00145 prev_reset_time_ = ros::Time::now();
00146 }
00147
00148
00149 if (x_trend_.hasSignFlipped() || y_trend_.hasSignFlipped() || theta_trend_.hasSignFlipped())
00150 {
00151
00152 if (resetAvailable())
00153 {
00154 reset();
00155 }
00156 }
00157 }
00158
00159 bool OscillationCritic::resetAvailable()
00160 {
00161 if (oscillation_reset_dist_ >= 0.0)
00162 {
00163 double x_diff = pose_.x - prev_stationary_pose_.x;
00164 double y_diff = pose_.y - prev_stationary_pose_.y;
00165 double sq_dist = x_diff * x_diff + y_diff * y_diff;
00166 if (sq_dist > oscillation_reset_dist_sq_)
00167 {
00168 return true;
00169 }
00170 }
00171 if (oscillation_reset_angle_ >= 0.0)
00172 {
00173 double th_diff = pose_.theta - prev_stationary_pose_.theta;
00174 if (fabs(th_diff) > oscillation_reset_angle_)
00175 {
00176 return true;
00177 }
00178 }
00179 if (oscillation_reset_time_ >= 0.0)
00180 {
00181 double t_diff = (ros::Time::now() - prev_reset_time_).toSec();
00182 if (t_diff > oscillation_reset_time_)
00183 {
00184 return true;
00185 }
00186 }
00187 return false;
00188 }
00189
00190 void OscillationCritic::reset()
00191 {
00192 x_trend_.reset();
00193 y_trend_.reset();
00194 theta_trend_.reset();
00195 }
00196
00197 bool OscillationCritic::setOscillationFlags(const nav_2d_msgs::Twist2D& cmd_vel)
00198 {
00199 bool flag_set = false;
00200
00201 flag_set |= x_trend_.update(cmd_vel.x);
00202
00203
00204 if (x_only_threshold_ < 0.0 || fabs(cmd_vel.x) <= x_only_threshold_)
00205 {
00206 flag_set |= y_trend_.update(cmd_vel.y);
00207 flag_set |= theta_trend_.update(cmd_vel.theta);
00208 }
00209 return flag_set;
00210 }
00211
00212 double OscillationCritic::scoreTrajectory(const dwb_msgs::Trajectory2D& traj)
00213 {
00214 if (x_trend_.isOscillating(traj.velocity.x) ||
00215 y_trend_.isOscillating(traj.velocity.y) ||
00216 theta_trend_.isOscillating(traj.velocity.theta))
00217 {
00218 throw nav_core2::IllegalTrajectoryException(name_, "Trajectory is oscillating.");
00219 }
00220 return 0.0;
00221 }
00222
00223 }