dynamic_window.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2020 Northwestern University
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 are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *********************************************************************/
41 
42 namespace ergodic_exploration
43 {
44 using arma::span;
45 
46 DynamicWindow::DynamicWindow(const Collision& collision, double dt, double horizon,
47  double acc_dt, double acc_lim_x, double acc_lim_y,
48  double acc_lim_th, double max_vel_x, double min_vel_x,
49  double max_vel_y, double min_vel_y, double max_rot_vel,
50  double min_rot_vel, unsigned int vx_samples,
51  unsigned int vy_samples, unsigned int vth_samples)
52  : collision_(collision)
53  , dt_(dt)
54  , horizon_(horizon)
55  , acc_dt_(acc_dt)
56  , acc_lim_x_(acc_lim_x)
57  , acc_lim_y_(acc_lim_y)
58  , acc_lim_th_(acc_lim_th)
59  , max_vel_x_(max_vel_x)
60  , min_vel_x_(min_vel_x)
61  , max_vel_y_(max_vel_y)
62  , min_vel_y_(min_vel_y)
63  , max_rot_vel_(max_rot_vel)
64  , min_rot_vel_(min_rot_vel)
65  , vx_samples_(vx_samples)
66  , vy_samples_(vy_samples)
67  , vth_samples_(vth_samples)
68  , steps_(static_cast<unsigned int>(std::abs(horizon / dt)))
69 {
70  if (vx_samples_ == 0)
71  {
72  std::cout << "vx samples set to 0 but need at least 1... setting this to 1"
73  << std::endl;
74  vx_samples_ = 1;
75  }
76 
77  if (vy_samples_ == 0)
78  {
79  std::cout << "vy samples set to 0 but need at least 1... setting this to 1"
80  << std::endl;
81  vy_samples_ = 1;
82  }
83 
84  if (vth_samples_ == 0)
85  {
86  std::cout << "vth samples set to 0 but need at least 1... setting this to 1"
87  << std::endl;
88  vth_samples_ = 1;
89  }
90 }
91 
92 tuple<bool, vec> DynamicWindow::control(const GridMap& grid, const vec& x0, const vec& vb,
93  const vec& vref) const
94 {
95  // window limits and discretization
96  const std::tuple<vec, vec> window_config = window(vb);
97 
98  // Search velocity space
99  auto min_cost = std::numeric_limits<double>::max();
100 
101  vec u_opt(3, arma::fill::zeros); // optimal twist
102  vec u(3, arma::fill::zeros); // sample twist
103 
104  auto vx = std::get<0>(window_config)(0);
105  for (unsigned int i = 0; i < vx_samples_; i++)
106  {
107  auto vy = std::get<0>(window_config)(1);
108  for (unsigned int j = 0; j < vy_samples_; j++)
109  {
110  auto w = std::get<0>(window_config)(2);
111  for (unsigned int k = 0; k < vth_samples_; k++)
112  {
113  u(0) = vx;
114  u(1) = vy;
115  u(2) = w;
116 
117  const auto cost = objective(grid, x0, vref, u);
118  // minimize cost
119  if (cost < min_cost)
120  {
121  min_cost = cost;
122  u_opt = u;
123  }
124 
125  w += std::get<1>(window_config)(2);
126  } // end w loop
127  vy += std::get<1>(window_config)(1);
128  } // end vy loop
129  vx += std::get<1>(window_config)(0);
130  } // end vx loop
131 
132  if (almost_equal(min_cost, std::numeric_limits<double>::max()))
133  {
134  std::cout << "DWA Failed! Not even 1 solution found" << std::endl;
135  return std::make_tuple(false, u_opt);
136  }
137 
138  return std::make_tuple(true, u_opt);
139 }
140 
141 tuple<bool, vec> DynamicWindow::control(const GridMap& grid, const vec& x0, const vec& vb,
142  const mat& xt_ref, double dt_ref) const
143 {
144  // window limits and discretization
145  const tuple<vec, vec> window_config = window(vb);
146 
147  // Time parameterization of the reference trajectory
148  const double tf = static_cast<double>(xt_ref.n_cols) * dt_ref;
149 
150  // Search velocity space
151  auto min_cost = std::numeric_limits<double>::max();
152 
153  vec u_opt(3, arma::fill::zeros); // optimal twist
154  vec u(3, arma::fill::zeros); // sample twist
155 
156  auto vx = std::get<0>(window_config)(0);
157  for (unsigned int i = 0; i < vx_samples_; i++)
158  {
159  auto vy = std::get<0>(window_config)(1);
160  for (unsigned int j = 0; j < vy_samples_; j++)
161  {
162  auto w = std::get<0>(window_config)(2);
163  for (unsigned int k = 0; k < vth_samples_; k++)
164  {
165  u(0) = vx;
166  u(1) = vy;
167  u(2) = w;
168 
169  const auto cost = objective(grid, x0, u, xt_ref, tf);
170  // minimize cost
171  if (cost < min_cost)
172  {
173  min_cost = cost;
174  u_opt = u;
175  }
176 
177  w += std::get<1>(window_config)(2);
178  } // end w loop
179  vy += std::get<1>(window_config)(1);
180  } // end vy loop
181  vx += std::get<1>(window_config)(0);
182  } // end vx loop
183 
184  if (almost_equal(min_cost, std::numeric_limits<double>::max()))
185  {
186  std::cout << "DWA Failed! Not even 1 solution found" << std::endl;
187  return std::make_tuple(false, u_opt);
188  }
189 
190  return std::make_tuple(true, u_opt);
191 }
192 
193 tuple<vec, vec> DynamicWindow::window(const vec& vb) const
194 {
195  // Window bounds and discretization
196  vec vel_upper(3, arma::fill::zeros); // twist upper limits
197  vec vel_lower(3, arma::fill::zeros); // twist lower limits
198  vec delta_vb(3, arma::fill::zeros); // twist discretization
199 
200  vel_lower(0) = std::max(vb(0) - acc_lim_x_ * acc_dt_, min_vel_x_);
201  vel_upper(0) = std::min(vb(0) + acc_lim_x_ * acc_dt_, max_vel_x_);
202 
203  vel_lower(1) = std::max(vb(1) - acc_lim_y_ * acc_dt_, min_vel_y_);
204  vel_upper(1) = std::min(vb(1) + acc_lim_y_ * acc_dt_, max_vel_y_);
205 
206  vel_lower(2) = std::max(vb(2) - acc_lim_th_ * acc_dt_, min_rot_vel_);
207  vel_upper(2) = std::min(vb(2) + acc_lim_th_ * acc_dt_, max_rot_vel_);
208 
209  // std::cout << "Window " << std::endl;
210  // std::cout << "vx: [ " << vel_lower(0) << ", " << vel_upper(0) << " ] \n" ;
211  // std::cout << "vy: [ " << vel_lower(1) << ", " << vel_upper(1) << " ] \n";
212  // std::cout << "w: [ " << vel_lower(2) << ", " << vel_upper(2) << " ]" << std::endl;
213 
214  if (vx_samples_ > 1)
215  {
216  delta_vb(0) = (vel_upper(0) - vel_lower(0)) / static_cast<double>(vx_samples_ - 1);
217  }
218 
219  if (vy_samples_ > 1)
220  {
221  delta_vb(1) = (vel_upper(1) - vel_lower(1)) / static_cast<double>(vy_samples_ - 1);
222  }
223 
224  if (vth_samples_ > 1)
225  {
226  delta_vb(2) = (vel_upper(2) - vel_lower(2)) / static_cast<double>(vth_samples_ - 1);
227  }
228 
229  // std::cout << "Window discretization " << std::endl;
230  // std::cout << "dvx: " << delta_vb(0) << std::endl;
231  // std::cout << "dvy: " << delta_vb(1) << std::endl;
232  // std::cout << "dw: " << delta_vb(2) << std::endl;
233 
234  return std::make_tuple(vel_lower, delta_vb);
235 }
236 
237 double DynamicWindow::objective(const GridMap& grid, const vec& x0, const vec& vref,
238  const vec& u) const
239 {
240  // follow constant twist
241  vec pose = x0;
242  for (unsigned int i = 0; i < steps_; i++)
243  {
244  pose = integrate_twist(pose, u, dt_);
245  pose(2) = normalize_angle_PI(pose(2));
246 
247  if (collision_.collisionCheck(grid, pose))
248  {
249  return std::numeric_limits<double>::max();
250  }
251  }
252 
253  // control error;
254  const vec cntrl_error = vref - u;
255  return dot(cntrl_error, cntrl_error);
256 }
257 
258 double DynamicWindow::objective(const GridMap& grid, const vec& x0, const vec& u,
259  const mat& xt_ref, double tf) const
260 {
261  vec pose = x0;
262  auto t = 0.0;
263  auto cost = 0.0;
264 
265  // follow constant twist
266  for (unsigned int i = 0; i < steps_; i++)
267  {
268  pose = integrate_twist(pose, u, dt_);
269  pose(2) = normalize_angle_PI(pose(2));
270 
271  if (collision_.collisionCheck(grid, pose))
272  {
273  return std::numeric_limits<double>::max();
274  }
275 
276  // index into reference trajectory
277  const auto j = static_cast<unsigned int>(std::round((xt_ref.n_cols - 1) * t / tf));
278 
279  cost += arma::norm(xt_ref(span(0, 1), span(j, j)) - pose.rows(0, 1));
280  cost += std::abs(normalize_angle_PI(normalize_angle_PI(xt_ref(2, j)) - pose(2)));
281 
282  t += dt_;
283  }
284 
285  return cost;
286 }
287 } // namespace ergodic_exploration
ergodic_exploration::DynamicWindow::acc_lim_th_
double acc_lim_th_
Definition: dynamic_window.hpp:165
ergodic_exploration::DynamicWindow::vy_samples_
unsigned int vy_samples_
Definition: dynamic_window.hpp:170
ergodic_exploration::DynamicWindow::steps_
unsigned int steps_
Definition: dynamic_window.hpp:172
ergodic_exploration::DynamicWindow::acc_lim_y_
double acc_lim_y_
Definition: dynamic_window.hpp:165
ergodic_exploration::DynamicWindow::min_rot_vel_
double min_rot_vel_
Definition: dynamic_window.hpp:168
ergodic_exploration::integrate_twist
vec integrate_twist(const vec &x, const vec &u, double dt)
Integrate a constant twist.
Definition: numerics.hpp:273
ergodic_exploration::DynamicWindow::max_vel_x_
double max_vel_x_
Definition: dynamic_window.hpp:166
ergodic_exploration::DynamicWindow::acc_dt_
double acc_dt_
Definition: dynamic_window.hpp:164
ergodic_exploration::normalize_angle_PI
double normalize_angle_PI(double rad)
Wraps angle between -pi and pi.
Definition: numerics.hpp:77
dot
TFSIMD_FORCE_INLINE tfScalar dot(const Quaternion &q1, const Quaternion &q2)
ergodic_exploration::DynamicWindow::vth_samples_
unsigned int vth_samples_
Definition: dynamic_window.hpp:171
ergodic_exploration
Definition: basis.hpp:43
ergodic_exploration::DynamicWindow::dt_
double dt_
Definition: dynamic_window.hpp:162
ergodic_exploration::GridMap
Constructs an 2D grid.
Definition: grid.hpp:79
ergodic_exploration::DynamicWindow::max_rot_vel_
double max_rot_vel_
Definition: dynamic_window.hpp:168
ergodic_exploration::DynamicWindow::window
tuple< vec, vec > window(const vec &vb) const
Compose window size and discretization.
Definition: dynamic_window.cpp:193
dynamic_window.hpp
Dynamic window control.
ergodic_exploration::almost_equal
bool almost_equal(double d1, double d2, double epsilon=1.0e-12)
approximately compare two floating-point numbers
Definition: numerics.hpp:67
ergodic_exploration::DynamicWindow::control
tuple< bool, vec > control(const GridMap &grid, const vec &x0, const vec &vb, const vec &vref) const
Compose best control.
Definition: dynamic_window.cpp:92
numerics.hpp
Useful numerical utilities.
ergodic_exploration::DynamicWindow::acc_lim_x_
double acc_lim_x_
Definition: dynamic_window.hpp:165
ergodic_exploration::DynamicWindow::max_vel_y_
double max_vel_y_
Definition: dynamic_window.hpp:167
std
ergodic_exploration::DynamicWindow::vx_samples_
unsigned int vx_samples_
Definition: dynamic_window.hpp:169
ergodic_exploration::DynamicWindow::objective
double objective(const GridMap &grid, const vec &x0, const vec &vref, const vec &u) const
Objective function for reference twist.
Definition: dynamic_window.cpp:237
ergodic_exploration::DynamicWindow::min_vel_x_
double min_vel_x_
Definition: dynamic_window.hpp:166
ergodic_exploration::DynamicWindow::min_vel_y_
double min_vel_y_
Definition: dynamic_window.hpp:167
tf
ergodic_exploration::Collision::collisionCheck
bool collisionCheck(const GridMap &grid, const vec &pose) const
Check if the given state is a collision.
Definition: collision.cpp:126
ergodic_exploration::DynamicWindow::collision_
Collision collision_
Definition: dynamic_window.hpp:161
t
geometry_msgs::TransformStamped t
ergodic_exploration::DynamicWindow::DynamicWindow
DynamicWindow(const Collision &collision, double dt, double horizon, double acc_dt, double acc_lim_x, double acc_lim_y, double acc_lim_th, double max_vel_x, double min_vel_x, double max_vel_y, double min_vel_y, double max_rot_vel, double min_rot_vel, unsigned int vx_samples, unsigned int vy_samples, unsigned int vth_samples)
Constructor.
Definition: dynamic_window.cpp:46
ergodic_exploration::Collision
2D collision detection
Definition: collision.hpp:85


ergodic_exploration
Author(s): bostoncleek
autogenerated on Wed Mar 2 2022 00:17:13