angles.h
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 * 
00004 *  Copyright (c) 2008, Willow Garage, Inc.
00005 *  All rights reserved.
00006 * 
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 * 
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 * 
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 #ifndef GEOMETRY_ANGLES_UTILS_H
00036 #define GEOMETRY_ANGLES_UTILS_H
00037 
00038 #include <algorithm>
00039 #include <cmath>
00040 
00041 namespace angles
00042 {
00043     
00048   static inline double from_degrees(double degrees)
00049   {
00050     return degrees * M_PI / 180.0;   
00051   }
00052     
00056   static inline double to_degrees(double radians)
00057   {
00058     return radians * 180.0 / M_PI;
00059   }
00060     
00061 
00068   static inline double normalize_angle_positive(double angle)
00069   {
00070     return fmod(fmod(angle, 2.0*M_PI) + 2.0*M_PI, 2.0*M_PI);
00071   }
00072 
00073 
00081   static inline double normalize_angle(double angle)
00082   {
00083     double a = normalize_angle_positive(angle);
00084     if (a > M_PI)
00085       a -= 2.0 *M_PI;
00086     return a;
00087   }
00088 
00089     
00102   static inline double shortest_angular_distance(double from, double to)
00103   {
00104     double result = normalize_angle_positive(normalize_angle_positive(to) - normalize_angle_positive(from));
00105         
00106     if (result > M_PI)
00107       // If the result > 180,
00108       // It's shorter the other way.
00109       result = -(2.0*M_PI - result);
00110         
00111     return normalize_angle(result);
00112   }
00113 
00123   static inline double two_pi_complement(double angle)
00124   {
00125     //check input conditions
00126     if (angle > 2*M_PI || angle < -2.0*M_PI)
00127       angle = fmod(angle, 2.0*M_PI);    
00128     if(angle < 0)
00129       return (2*M_PI+angle);
00130     else if (angle > 0)
00131       return (-2*M_PI+angle);
00132 
00133     return(2*M_PI);
00134   }
00135 
00147   static bool find_min_max_delta(double from, double left_limit, double right_limit, double &result_min_delta, double &result_max_delta)
00148   {
00149     double delta[4];
00150 
00151     delta[0] = shortest_angular_distance(from,left_limit);
00152     delta[1] = shortest_angular_distance(from,right_limit);
00153 
00154     delta[2] = two_pi_complement(delta[0]);
00155     delta[3] = two_pi_complement(delta[1]);
00156 
00157     if(delta[0] == 0)
00158     {
00159       result_min_delta = delta[0];
00160       result_max_delta = std::max<double>(delta[1],delta[3]);
00161       return true;
00162     }
00163 
00164     if(delta[1] == 0)
00165     {
00166         result_max_delta = delta[1];
00167         result_min_delta = std::min<double>(delta[0],delta[2]);
00168         return true;
00169     }
00170 
00171 
00172     double delta_min = delta[0];
00173     double delta_min_2pi = delta[2];
00174     if(delta[2] < delta_min)
00175     {
00176       delta_min = delta[2];
00177       delta_min_2pi = delta[0];
00178     }
00179 
00180     double delta_max = delta[1];
00181     double delta_max_2pi = delta[3];
00182     if(delta[3] > delta_max)
00183     {
00184       delta_max = delta[3];
00185       delta_max_2pi = delta[1];
00186     }
00187 
00188 
00189     //    printf("%f %f %f %f\n",delta_min,delta_min_2pi,delta_max,delta_max_2pi);
00190     if((delta_min <= delta_max_2pi) || (delta_max >= delta_min_2pi))
00191     {
00192       result_min_delta = delta_max_2pi;
00193       result_max_delta = delta_min_2pi;
00194       if(left_limit == -M_PI && right_limit == M_PI)
00195         return true;
00196       else
00197         return false;
00198     }
00199     result_min_delta = delta_min;
00200     result_max_delta = delta_max;
00201     return true;
00202   }
00203 
00204 
00222   static inline bool shortest_angular_distance_with_limits(double from, double to, double left_limit, double right_limit, double &shortest_angle)
00223   {
00224 
00225     double min_delta = -2*M_PI;
00226     double max_delta = 2*M_PI;
00227     double min_delta_to = -2*M_PI;
00228     double max_delta_to = 2*M_PI;
00229     bool flag    = find_min_max_delta(from,left_limit,right_limit,min_delta,max_delta);
00230     double delta = shortest_angular_distance(from,to);
00231     double delta_mod_2pi  = two_pi_complement(delta);
00232 
00233 
00234     if(flag)//from position is within the limits
00235     {
00236       if(delta >= min_delta && delta <= max_delta)
00237       {
00238         shortest_angle = delta;
00239         return true;
00240       }
00241       else if(delta_mod_2pi >= min_delta && delta_mod_2pi <= max_delta)
00242       {
00243         shortest_angle = delta_mod_2pi;
00244         return true;
00245       }
00246       else //to position is outside the limits
00247       {
00248         find_min_max_delta(to,left_limit,right_limit,min_delta_to,max_delta_to);
00249           if(fabs(min_delta_to) < fabs(max_delta_to))
00250             shortest_angle = std::max<double>(delta,delta_mod_2pi);
00251           else if(fabs(min_delta_to) > fabs(max_delta_to))
00252             shortest_angle =  std::min<double>(delta,delta_mod_2pi);
00253           else
00254           {
00255             if (fabs(delta) < fabs(delta_mod_2pi))
00256               shortest_angle = delta;
00257             else
00258               shortest_angle = delta_mod_2pi;
00259           }
00260           return false;
00261       }
00262     }
00263     else // from position is outside the limits
00264     {
00265         find_min_max_delta(to,left_limit,right_limit,min_delta_to,max_delta_to);
00266 
00267           if(fabs(min_delta) < fabs(max_delta))
00268             shortest_angle = std::min<double>(delta,delta_mod_2pi);
00269           else if (fabs(min_delta) > fabs(max_delta))
00270             shortest_angle =  std::max<double>(delta,delta_mod_2pi);
00271           else
00272           {
00273             if (fabs(delta) < fabs(delta_mod_2pi))
00274               shortest_angle = delta;
00275             else
00276               shortest_angle = delta_mod_2pi;
00277           }
00278       return false;
00279     }
00280 
00281     shortest_angle = delta;
00282     return false;
00283   }
00284 
00285 
00286     
00287 
00288 
00289 }
00290 
00291 #endif


angles
Author(s): John Hsu
autogenerated on Sun Oct 5 2014 22:13:30