angles.h
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
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 Willow Garage 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 OWNER 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 
35 #ifndef GEOMETRY_ANGLES_UTILS_H
36 #define GEOMETRY_ANGLES_UTILS_H
37 
38 #include <algorithm>
39 #include <cmath>
40 
41 namespace angles
42 {
43 
48  static inline double from_degrees(double degrees)
49  {
50  return degrees * M_PI / 180.0;
51  }
52 
56  static inline double to_degrees(double radians)
57  {
58  return radians * 180.0 / M_PI;
59  }
60 
61 
68  static inline double normalize_angle_positive(double angle)
69  {
70  const double result = fmod(angle, 2.0*M_PI);
71  if(result < 0) return result + 2.0*M_PI;
72  return result;
73  }
74 
75 
83  static inline double normalize_angle(double angle)
84  {
85  const double result = fmod(angle + M_PI, 2.0*M_PI);
86  if(result <= 0.0) return result + M_PI;
87  return result - M_PI;
88  }
89 
90 
103  static inline double shortest_angular_distance(double from, double to)
104  {
105  return normalize_angle(to-from);
106  }
107 
117  static inline double two_pi_complement(double angle)
118  {
119  //check input conditions
120  if (angle > 2*M_PI || angle < -2.0*M_PI)
121  angle = fmod(angle, 2.0*M_PI);
122  if(angle < 0)
123  return (2*M_PI+angle);
124  else if (angle > 0)
125  return (-2*M_PI+angle);
126 
127  return(2*M_PI);
128  }
129 
141  static bool find_min_max_delta(double from, double left_limit, double right_limit, double &result_min_delta, double &result_max_delta)
142  {
143  double delta[4];
144 
145  delta[0] = shortest_angular_distance(from,left_limit);
146  delta[1] = shortest_angular_distance(from,right_limit);
147 
148  delta[2] = two_pi_complement(delta[0]);
149  delta[3] = two_pi_complement(delta[1]);
150 
151  if(delta[0] == 0)
152  {
153  result_min_delta = delta[0];
154  result_max_delta = std::max<double>(delta[1],delta[3]);
155  return true;
156  }
157 
158  if(delta[1] == 0)
159  {
160  result_max_delta = delta[1];
161  result_min_delta = std::min<double>(delta[0],delta[2]);
162  return true;
163  }
164 
165 
166  double delta_min = delta[0];
167  double delta_min_2pi = delta[2];
168  if(delta[2] < delta_min)
169  {
170  delta_min = delta[2];
171  delta_min_2pi = delta[0];
172  }
173 
174  double delta_max = delta[1];
175  double delta_max_2pi = delta[3];
176  if(delta[3] > delta_max)
177  {
178  delta_max = delta[3];
179  delta_max_2pi = delta[1];
180  }
181 
182 
183  // printf("%f %f %f %f\n",delta_min,delta_min_2pi,delta_max,delta_max_2pi);
184  if((delta_min <= delta_max_2pi) || (delta_max >= delta_min_2pi))
185  {
186  result_min_delta = delta_max_2pi;
187  result_max_delta = delta_min_2pi;
188  if(left_limit == -M_PI && right_limit == M_PI)
189  return true;
190  else
191  return false;
192  }
193  result_min_delta = delta_min;
194  result_max_delta = delta_max;
195  return true;
196  }
197 
198 
222  static inline bool shortest_angular_distance_with_large_limits(double from, double to, double left_limit, double right_limit, double &shortest_angle)
223  {
224  // Shortest steps in the two directions
225  double delta = shortest_angular_distance(from, to);
226  double delta_2pi = two_pi_complement(delta);
227 
228  // "sort" distances so that delta is shorter than delta_2pi
229  if(std::fabs(delta) > std::fabs(delta_2pi))
230  std::swap(delta, delta_2pi);
231 
232  if(left_limit > right_limit) {
233  // If limits are something like [PI/2 , -PI/2] it actually means that we
234  // want rotations to be in the interval [-PI,PI/2] U [PI/2,PI], ie, the
235  // half unit circle not containing the 0. This is already gracefully
236  // handled by shortest_angular_distance_with_limits, and therefore this
237  // function should not be called at all. However, if one has limits that
238  // are larger than PI, the same rationale behind shortest_angular_distance_with_limits
239  // does not hold, ie, M_PI+x should not be directly equal to -M_PI+x.
240  // In this case, the correct way of getting the shortest solution is to
241  // properly set the limits, eg, by saying that the interval is either
242  // [PI/2, 3*PI/2] or [-3*M_PI/2, -M_PI/2]. For this reason, here we
243  // return false by default.
244  shortest_angle = delta;
245  return false;
246  }
247 
248  // Check in which direction we should turn (clockwise or counter-clockwise).
249 
250  // start by trying with the shortest angle (delta).
251  double to2 = from + delta;
252  if(left_limit <= to2 && to2 <= right_limit) {
253  // we can move in this direction: return success if the "from" angle is inside limits
254  shortest_angle = delta;
255  return left_limit <= from && from <= right_limit;
256  }
257 
258  // delta is not ok, try to move in the other direction (using its complement)
259  to2 = from + delta_2pi;
260  if(left_limit <= to2 && to2 <= right_limit) {
261  // we can move in this direction: return success if the "from" angle is inside limits
262  shortest_angle = delta_2pi;
263  return left_limit <= from && from <= right_limit;
264  }
265 
266  // nothing works: we always go outside limits
267  shortest_angle = delta; // at least give some "coherent" result
268  return false;
269  }
270 
271 
289  static inline bool shortest_angular_distance_with_limits(double from, double to, double left_limit, double right_limit, double &shortest_angle)
290  {
291 
292  double min_delta = -2*M_PI;
293  double max_delta = 2*M_PI;
294  double min_delta_to = -2*M_PI;
295  double max_delta_to = 2*M_PI;
296  bool flag = find_min_max_delta(from,left_limit,right_limit,min_delta,max_delta);
297  double delta = shortest_angular_distance(from,to);
298  double delta_mod_2pi = two_pi_complement(delta);
299 
300 
301  if(flag)//from position is within the limits
302  {
303  if(delta >= min_delta && delta <= max_delta)
304  {
305  shortest_angle = delta;
306  return true;
307  }
308  else if(delta_mod_2pi >= min_delta && delta_mod_2pi <= max_delta)
309  {
310  shortest_angle = delta_mod_2pi;
311  return true;
312  }
313  else //to position is outside the limits
314  {
315  find_min_max_delta(to,left_limit,right_limit,min_delta_to,max_delta_to);
316  if(fabs(min_delta_to) < fabs(max_delta_to))
317  shortest_angle = std::max<double>(delta,delta_mod_2pi);
318  else if(fabs(min_delta_to) > fabs(max_delta_to))
319  shortest_angle = std::min<double>(delta,delta_mod_2pi);
320  else
321  {
322  if (fabs(delta) < fabs(delta_mod_2pi))
323  shortest_angle = delta;
324  else
325  shortest_angle = delta_mod_2pi;
326  }
327  return false;
328  }
329  }
330  else // from position is outside the limits
331  {
332  find_min_max_delta(to,left_limit,right_limit,min_delta_to,max_delta_to);
333 
334  if(fabs(min_delta) < fabs(max_delta))
335  shortest_angle = std::min<double>(delta,delta_mod_2pi);
336  else if (fabs(min_delta) > fabs(max_delta))
337  shortest_angle = std::max<double>(delta,delta_mod_2pi);
338  else
339  {
340  if (fabs(delta) < fabs(delta_mod_2pi))
341  shortest_angle = delta;
342  else
343  shortest_angle = delta_mod_2pi;
344  }
345  return false;
346  }
347 
348  shortest_angle = delta;
349  return false;
350  }
351 }
352 
353 #endif
angles::shortest_angular_distance
static double shortest_angular_distance(double from, double to)
shortest_angular_distance
Definition: angles.h:135
angles::normalize_angle
static double normalize_angle(double angle)
normalize
Definition: angles.h:115
angles
Definition: angles.h:41
angles::from_degrees
static double from_degrees(double degrees)
Convert degrees to radians.
Definition: angles.h:80
angles::shortest_angular_distance_with_limits
static bool shortest_angular_distance_with_limits(double from, double to, double left_limit, double right_limit, double &shortest_angle)
Returns the delta from "from_angle" to "to_angle" making sure it does not violate limits specified by...
Definition: angles.h:321
angles::normalize_angle_positive
static double normalize_angle_positive(double angle)
normalize_angle_positive
Definition: angles.h:100
angles::find_min_max_delta
static bool find_min_max_delta(double from, double left_limit, double right_limit, double &result_min_delta, double &result_max_delta)
This function is only intended for internal use and not intended for external use....
Definition: angles.h:173
angles::to_degrees
static double to_degrees(double radians)
Convert radians to degrees.
Definition: angles.h:88
angles::shortest_angular_distance_with_large_limits
static bool shortest_angular_distance_with_large_limits(double from, double to, double left_limit, double right_limit, double &shortest_angle)
Returns the delta from from_angle to to_angle, making sure it does not violate limits specified by le...
Definition: angles.h:254
angles::two_pi_complement
static double two_pi_complement(double angle)
returns the angle in [-2*M_PI, 2*M_PI] going the other way along the unit circle.
Definition: angles.h:149


angles
Author(s): John Hsu , Tully Foote
autogenerated on Tue Mar 1 2022 23:45:04