oscillation.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017, Locus Robotics
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
37 #include <nav_core2/exceptions.h>
39 #include <cmath>
40 #include <string>
41 #include <vector>
42 
44 
45 namespace dwb_critics
46 {
47 
48 OscillationCritic::CommandTrend::CommandTrend()
49 {
50  reset();
51 }
52 
53 void OscillationCritic::CommandTrend::reset()
54 {
55  sign_ = Sign::ZERO;
56  positive_only_ = false;
57  negative_only_ = false;
58 }
59 
60 bool OscillationCritic::CommandTrend::update(double velocity)
61 {
62  bool flag_set = false;
63  if (velocity < 0.0)
64  {
65  if (sign_ == Sign::POSITIVE)
66  {
67  negative_only_ = true;
68  flag_set = true;
69  }
70  sign_ = Sign::NEGATIVE;
71  }
72  else if (velocity > 0.0)
73  {
74  if (sign_ == Sign::NEGATIVE)
75  {
76  positive_only_ = true;
77  flag_set = true;
78  }
79  sign_ = Sign::POSITIVE;
80  }
81  return flag_set;
82 }
83 
84 bool OscillationCritic::CommandTrend::isOscillating(double velocity)
85 {
86  return (positive_only_ && velocity < 0.0) || (negative_only_ && velocity > 0.0);
87 }
88 
89 bool OscillationCritic::CommandTrend::hasSignFlipped()
90 {
91  return positive_only_ || negative_only_;
92 }
93 
94 void OscillationCritic::onInit()
95 {
96  oscillation_reset_dist_ = nav_2d_utils::searchAndGetParam(critic_nh_, "oscillation_reset_dist", 0.05);
97  oscillation_reset_dist_sq_ = oscillation_reset_dist_ * oscillation_reset_dist_;
98  oscillation_reset_angle_ = nav_2d_utils::searchAndGetParam(critic_nh_, "oscillation_reset_angle", 0.2);
99  oscillation_reset_time_ = nav_2d_utils::searchAndGetParam(critic_nh_, "oscillation_reset_time", -1.0);
100 
108  std::string resolved_name;
109  if (critic_nh_.hasParam("x_only_threshold"))
110  {
111  critic_nh_.getParam("x_only_threshold", x_only_threshold_);
112  }
113  else if (critic_nh_.searchParam("min_speed_xy", resolved_name))
114  {
115  critic_nh_.getParam(resolved_name, x_only_threshold_);
116  }
117  else if (critic_nh_.searchParam("min_trans_vel", resolved_name))
118  {
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_);
122  }
123  else
124  {
125  x_only_threshold_ = 0.05;
126  }
127 
128  reset();
129 }
130 
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)
135 {
136  pose_ = pose;
137  return true;
138 }
139 
140 void OscillationCritic::debrief(const nav_2d_msgs::Twist2D& cmd_vel)
141 {
142  if (setOscillationFlags(cmd_vel))
143  {
144  prev_stationary_pose_ = pose_;
145  prev_reset_time_ = ros::Time::now();
146  }
147 
148  // if we've got restrictions... check if we can reset any oscillation flags
149  if (x_trend_.hasSignFlipped() || y_trend_.hasSignFlipped() || theta_trend_.hasSignFlipped())
150  {
151  // Reset flags if enough time or distance has passed
152  if (resetAvailable())
153  {
154  reset();
155  }
156  }
157 }
158 
159 bool OscillationCritic::resetAvailable()
160 {
161  if (oscillation_reset_dist_ >= 0.0)
162  {
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_)
167  {
168  return true;
169  }
170  }
171  if (oscillation_reset_angle_ >= 0.0)
172  {
173  double th_diff = pose_.theta - prev_stationary_pose_.theta;
174  if (fabs(th_diff) > oscillation_reset_angle_)
175  {
176  return true;
177  }
178  }
179  if (oscillation_reset_time_ >= 0.0)
180  {
181  double t_diff = (ros::Time::now() - prev_reset_time_).toSec();
182  if (t_diff > oscillation_reset_time_)
183  {
184  return true;
185  }
186  }
187  return false;
188 }
189 
190 void OscillationCritic::reset()
191 {
192  x_trend_.reset();
193  y_trend_.reset();
194  theta_trend_.reset();
195 }
196 
197 bool OscillationCritic::setOscillationFlags(const nav_2d_msgs::Twist2D& cmd_vel)
198 {
199  bool flag_set = false;
200  // set oscillation flags for moving forward and backward
201  flag_set |= x_trend_.update(cmd_vel.x);
202 
203  // we'll only set flags for strafing and rotating when we're not moving forward at all
204  if (x_only_threshold_ < 0.0 || fabs(cmd_vel.x) <= x_only_threshold_)
205  {
206  flag_set |= y_trend_.update(cmd_vel.y);
207  flag_set |= theta_trend_.update(cmd_vel.theta);
208  }
209  return flag_set;
210 }
211 
212 double OscillationCritic::scoreTrajectory(const dwb_msgs::Trajectory2D& traj)
213 {
214  if (x_trend_.isOscillating(traj.velocity.x) ||
215  y_trend_.isOscillating(traj.velocity.y) ||
216  theta_trend_.isOscillating(traj.velocity.theta))
217  {
218  throw nav_core2::IllegalTrajectoryException(name_, "Trajectory is oscillating.");
219  }
220  return 0.0;
221 }
222 
223 } // namespace dwb_critics
#define ROS_WARN_NAMED(name,...)
Checks to see whether the sign of the commanded velocity flips frequently.
Definition: oscillation.h:79
param_t searchAndGetParam(const ros::NodeHandle &nh, const std::string &param_name, const param_t &default_value)
static Time now()
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)


dwb_critics
Author(s): David V. Lu!!
autogenerated on Sun Jan 10 2021 04:08:44