Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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
00155
00156 int m = std::max( (int)obstacles->size()-1, 5 );
00157
00158 int a = (int) std::ceil(double(m)/2.0);
00159 int b = m-a;
00160
00161 std::advance(path_end, -1);
00162
00163 typedef std::complex<long double> cplx;
00164
00165
00166
00167 cplx start = fun_cplx_point(*path_start);
00168 cplx end = fun_cplx_point(*path_end);
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 {
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;
00185
00186 std::vector<double> imag_proposals(5);
00187
00188
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)
00195 {
00196 cplx obst_l = obstacles->at(l)->getCentroidCplx();
00197
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
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
00209 if (std::abs(diff)<0.05)
00210 continue;
00211 else
00212 Al /= diff;
00213 }
00214
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
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
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);
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;
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 }
00276
00277
00278 #endif