equivalence_relations.h
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2016,
00006  *  TU Dortmund - Institute of Control Theory and Systems Engineering.
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of the institute nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * Author: Christoph Rösmann
00037  *********************************************************************/
00038 
00039 #ifndef EQUIVALENCE_RELATIONS_H_
00040 #define EQUIVALENCE_RELATIONS_H_
00041 
00042 #include <ros/ros.h>
00043 #include <math.h>
00044 #include <algorithm>
00045 #include <functional>
00046 #include <vector>
00047 #include <iterator>
00048 #include <teb_local_planner/misc.h>
00049 #include <teb_local_planner/obstacles.h>
00050 #include <teb_local_planner/teb_config.h>
00051 
00052 namespace teb_local_planner
00053 {
00054   
00055     
00072 class EquivalenceClass
00073 {
00074 public:
00075     
00079    EquivalenceClass() {}
00080    
00084    virtual ~EquivalenceClass() {}
00085    
00090    virtual bool isEqual(const EquivalenceClass& other) const = 0;
00091    
00096    virtual bool isValid() const = 0;
00097     
00098 };
00099 
00100 using EquivalenceClassPtr = boost::shared_ptr<EquivalenceClass>;
00101 
00102 
00103 
00112 class HSignature : public EquivalenceClass
00113 {
00114 
00115 public:
00116     
00121     HSignature(const TebConfig& cfg) : cfg_(&cfg) {}
00122     
00123     
00142     template<typename BidirIter, typename Fun>
00143     void calculateHSignature(BidirIter path_start, BidirIter path_end, Fun fun_cplx_point, const ObstContainer* obstacles)
00144     {
00145         if (obstacles->empty()) 
00146         {
00147             hsignature_ = std::complex<double>(0,0);
00148             return;
00149         }
00150     
00151     
00152         ROS_ASSERT_MSG(cfg_->hcp.h_signature_prescaler>0.1 && cfg_->hcp.h_signature_prescaler<=1, "Only a prescaler on the interval (0.1,1] ist allowed.");
00153         
00154         // guess values for f0
00155         // paper proposes a+b=N-1 && |a-b|<=1, 1...N obstacles
00156         int m = std::max( (int)obstacles->size()-1, 5 );  // for only a few obstacles we need a min threshold in order to get significantly high H-Signatures
00157         
00158         int a = (int) std::ceil(double(m)/2.0);
00159         int b = m-a;
00160         
00161         std::advance(path_end, -1); // reduce path_end by 1 (since we check line segments between those path points
00162         
00163         typedef std::complex<long double> cplx;
00164         // guess map size (only a really really coarse guess is required
00165         // use distance from start to goal as distance to each direction
00166         // TODO: one could move the map determination outside this function, since it remains constant for the whole planning interval
00167         cplx start = fun_cplx_point(*path_start);
00168         cplx end = fun_cplx_point(*path_end); // path_end points to the last point now after calling std::advance before
00169         cplx delta = end-start;
00170         cplx normal(-delta.imag(), delta.real());
00171         cplx map_bottom_left;
00172         cplx map_top_right;
00173         if (std::abs(delta) < 3.0)
00174         { // set minimum bound on distance (we do not want to have numerical instabilities) and 3.0 performs fine...
00175             map_bottom_left = start + cplx(0, -3);
00176             map_top_right = start + cplx(3, 3);
00177         }
00178         else
00179         {
00180             map_bottom_left = start - normal;
00181             map_top_right = start + delta + normal;
00182         }
00183         
00184         hsignature_ = 0; // reset local signature
00185         
00186         std::vector<double> imag_proposals(5);
00187         
00188         // iterate path
00189         while(path_start != path_end)
00190         {
00191             cplx z1 = fun_cplx_point(*path_start);
00192             cplx z2 = fun_cplx_point(*boost::next(path_start));
00193 
00194             for (std::size_t l=0; l<obstacles->size(); ++l) // iterate all obstacles
00195             {
00196                 cplx obst_l = obstacles->at(l)->getCentroidCplx();
00197                 //cplx f0 = (long double) prescaler * std::pow(obst_l-map_bottom_left,a) * std::pow(obst_l-map_top_right,b);
00198                 cplx f0 = (long double) cfg_->hcp.h_signature_prescaler * (long double)a*(obst_l-map_bottom_left) * (long double)b*(obst_l-map_top_right);
00199                 
00200                 // denum contains product with all obstacles exepct j==l
00201                 cplx Al = f0;
00202                 for (std::size_t j=0; j<obstacles->size(); ++j)
00203                 {
00204                     if (j==l)
00205                         continue;
00206                     cplx obst_j = obstacles->at(j)->getCentroidCplx();
00207                     cplx diff = obst_l - obst_j;
00208                     //if (diff.real()!=0 || diff.imag()!=0)
00209                     if (std::abs(diff)<0.05) // skip really close obstacles
00210                         continue;
00211                     else
00212                         Al /= diff;
00213                 }
00214                 // compute log value
00215                 double diff2 = std::abs(z2-obst_l);
00216                 double diff1 = std::abs(z1-obst_l);
00217                 if (diff2 == 0 || diff1 == 0)
00218                 continue;
00219                 double log_real = std::log(diff2)-std::log(diff1);
00220                 // complex ln has more than one solution -> choose minimum abs angle -> paper
00221                 double arg_diff = std::arg(z2-obst_l)-std::arg(z1-obst_l);
00222                 imag_proposals.at(0) = arg_diff;
00223                 imag_proposals.at(1) = arg_diff+2*M_PI;
00224                 imag_proposals.at(2) = arg_diff-2*M_PI;
00225                 imag_proposals.at(3) = arg_diff+4*M_PI;
00226                 imag_proposals.at(4) = arg_diff-4*M_PI;
00227                 double log_imag = *std::min_element(imag_proposals.begin(),imag_proposals.end(),smaller_than_abs);
00228                 cplx log_value(log_real,log_imag);
00229                 //cplx log_value = std::log(z2-obst_l)-std::log(z1-obst_l); // the principal solution doesn't seem to work
00230                 hsignature_ += Al*log_value;  
00231             }
00232             ++path_start;
00233         }
00234     }
00235     
00236     
00241     virtual bool isEqual(const EquivalenceClass& other) const
00242     {
00243         const HSignature* hother = dynamic_cast<const HSignature*>(&other); // TODO: better architecture without dynamic_cast
00244         if (hother)
00245         {
00246             double diff_real = std::abs(hother->hsignature_.real() - hsignature_.real());
00247             double diff_imag = std::abs(hother->hsignature_.imag() - hsignature_.imag());
00248             if (diff_real<=cfg_->hcp.h_signature_threshold && diff_imag<=cfg_->hcp.h_signature_threshold)
00249                 return true; // Found! Homotopy class already exists, therefore nothing added  
00250         }
00251         else
00252             ROS_ERROR("Cannot compare HSignature equivalence classes with types other than HSignature.");
00253         
00254         return false;
00255     }
00256     
00261     virtual bool isValid() const
00262     {
00263         return std::isfinite(hsignature_.real()) && std::isfinite(hsignature_.imag());
00264     }
00265         
00266     
00267 private:
00268     
00269     const TebConfig* cfg_;
00270     std::complex<long double> hsignature_;
00271 };
00272 
00273 
00274 
00275 } // namespace teb_local_planner
00276 
00277 
00278 #endif /* EQUIVALENCE_RELATIONS_H_ */


teb_local_planner
Author(s): Christoph Rösmann
autogenerated on Sat Jun 8 2019 20:21:34