48 OscillationCritic::CommandTrend::CommandTrend()
53 void OscillationCritic::CommandTrend::reset()
56 positive_only_ =
false;
57 negative_only_ =
false;
60 bool OscillationCritic::CommandTrend::update(
double velocity)
62 bool flag_set =
false;
65 if (sign_ == Sign::POSITIVE)
67 negative_only_ =
true;
70 sign_ = Sign::NEGATIVE;
72 else if (velocity > 0.0)
74 if (sign_ == Sign::NEGATIVE)
76 positive_only_ =
true;
79 sign_ = Sign::POSITIVE;
84 bool OscillationCritic::CommandTrend::isOscillating(
double velocity)
86 return (positive_only_ && velocity < 0.0) || (negative_only_ && velocity > 0.0);
89 bool OscillationCritic::CommandTrend::hasSignFlipped()
91 return positive_only_ || negative_only_;
94 void OscillationCritic::onInit()
97 oscillation_reset_dist_sq_ = oscillation_reset_dist_ * oscillation_reset_dist_;
108 std::string resolved_name;
109 if (critic_nh_.hasParam(
"x_only_threshold"))
111 critic_nh_.getParam(
"x_only_threshold", x_only_threshold_);
113 else if (critic_nh_.searchParam(
"min_speed_xy", resolved_name))
115 critic_nh_.getParam(resolved_name, x_only_threshold_);
117 else if (critic_nh_.searchParam(
"min_trans_vel", resolved_name))
119 ROS_WARN_NAMED(
"OscillationCritic",
"Parameter min_trans_vel is deprecated. " 120 "Please use the name min_speed_xy or x_only_threshold instead.");
121 critic_nh_.getParam(resolved_name, x_only_threshold_);
125 x_only_threshold_ = 0.05;
131 bool OscillationCritic::prepare(
const geometry_msgs::Pose2D& pose,
132 const nav_2d_msgs::Twist2D& vel,
133 const geometry_msgs::Pose2D& goal,
134 const nav_2d_msgs::Path2D& global_plan)
140 void OscillationCritic::debrief(
const nav_2d_msgs::Twist2D& cmd_vel)
142 if (setOscillationFlags(cmd_vel))
144 prev_stationary_pose_ = pose_;
149 if (x_trend_.hasSignFlipped() || y_trend_.hasSignFlipped() || theta_trend_.hasSignFlipped())
152 if (resetAvailable())
159 bool OscillationCritic::resetAvailable()
161 if (oscillation_reset_dist_ >= 0.0)
163 double x_diff = pose_.x - prev_stationary_pose_.x;
164 double y_diff = pose_.y - prev_stationary_pose_.y;
165 double sq_dist = x_diff * x_diff + y_diff * y_diff;
166 if (sq_dist > oscillation_reset_dist_sq_)
171 if (oscillation_reset_angle_ >= 0.0)
173 double th_diff = pose_.theta - prev_stationary_pose_.theta;
174 if (fabs(th_diff) > oscillation_reset_angle_)
179 if (oscillation_reset_time_ >= 0.0)
182 if (t_diff > oscillation_reset_time_)
190 void OscillationCritic::reset()
194 theta_trend_.reset();
197 bool OscillationCritic::setOscillationFlags(
const nav_2d_msgs::Twist2D& cmd_vel)
199 bool flag_set =
false;
201 flag_set |= x_trend_.update(cmd_vel.x);
204 if (x_only_threshold_ < 0.0 || fabs(cmd_vel.x) <= x_only_threshold_)
206 flag_set |= y_trend_.update(cmd_vel.y);
207 flag_set |= theta_trend_.update(cmd_vel.theta);
212 double OscillationCritic::scoreTrajectory(
const dwb_msgs::Trajectory2D& traj)
214 if (x_trend_.isOscillating(traj.velocity.x) ||
215 y_trend_.isOscillating(traj.velocity.y) ||
216 theta_trend_.isOscillating(traj.velocity.theta))
#define ROS_WARN_NAMED(name,...)
Checks to see whether the sign of the commanded velocity flips frequently.
param_t searchAndGetParam(const ros::NodeHandle &nh, const std::string ¶m_name, const param_t &default_value)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)