39 #ifndef H_SIGNATURE_H_ 40 #define H_SIGNATURE_H_ 96 template<
typename B
idirIter,
typename Fun>
99 if (obstacles->empty())
110 int m = std::max( (
int)obstacles->size()-1, 5 );
112 int a = (int) std::ceil(
double(m)/2.0);
115 std::advance(path_end, -1);
117 typedef std::complex<long double> cplx;
121 cplx start = fun_cplx_point(*path_start);
122 cplx end = fun_cplx_point(*path_end);
123 cplx delta = end-start;
124 cplx normal(-delta.imag(), delta.real());
125 cplx map_bottom_left;
127 if (std::abs(delta) < 3.0)
129 map_bottom_left = start + cplx(0, -3);
130 map_top_right = start + cplx(3, 3);
134 map_bottom_left = start - normal;
135 map_top_right = start + delta + normal;
140 std::vector<double> imag_proposals(5);
143 while(path_start != path_end)
145 cplx z1 = fun_cplx_point(*path_start);
146 cplx z2 = fun_cplx_point(*boost::next(path_start));
148 for (std::size_t l=0; l<obstacles->size(); ++l)
150 cplx obst_l = obstacles->at(l)->getCentroidCplx();
152 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);
156 for (std::size_t j=0; j<obstacles->size(); ++j)
160 cplx obst_j = obstacles->at(j)->getCentroidCplx();
161 cplx
diff = obst_l - obst_j;
163 if (std::abs(diff)<0.05)
169 double diff2 = std::abs(z2-obst_l);
170 double diff1 = std::abs(z1-obst_l);
171 if (diff2 == 0 || diff1 == 0)
173 double log_real = std::log(diff2)-std::log(diff1);
175 double arg_diff = std::arg(z2-obst_l)-std::arg(z1-obst_l);
176 imag_proposals.at(0) = arg_diff;
177 imag_proposals.at(1) = arg_diff+2*M_PI;
178 imag_proposals.at(2) = arg_diff-2*M_PI;
179 imag_proposals.at(3) = arg_diff+4*M_PI;
180 imag_proposals.at(4) = arg_diff-4*M_PI;
181 double log_imag = *std::min_element(imag_proposals.begin(),imag_proposals.end(),
smaller_than_abs);
182 cplx log_value(log_real,log_imag);
202 if (diff_real<=cfg_->hcp.h_signature_threshold && diff_imag<=cfg_->hcp.h_signature_threshold)
206 ROS_ERROR(
"Cannot compare HSignature equivalence classes with types other than HSignature.");
281 template<
typename B
idirIter,
typename Fun>
283 boost::optional<TimeDiffSequence::iterator> timediff_start, boost::optional<TimeDiffSequence::iterator> timediff_end)
285 hsignature3d_.resize(obstacles->size());
287 std::advance(path_end, -1);
291 for (std::size_t l = 0; l < obstacles->size(); ++l)
294 double transition_time = 0;
295 double next_transition_time = 0;
297 TimeDiffSequence::iterator timediff_iter;
300 for (path_iter = path_start, timediff_iter = timediff_start.get(); path_iter != path_end; ++path_iter, ++timediff_iter)
302 std::complex<long double> z1 = fun_cplx_point(*path_iter);
303 std::complex<long double> z2 = fun_cplx_point(*boost::next(path_iter));
304 Eigen::Vector2d pose (z1.real(), z1.imag());
305 Eigen::Vector2d nextpose (z2.real(), z2.imag());
307 transition_time = next_transition_time;
312 if (std::distance(path_iter, path_end) != std::distance(timediff_iter, timediff_end.get()))
313 ROS_ERROR(
"Size of poses and timediff vectors does not match. This is a bug.");
314 next_transition_time += (*timediff_iter)->dt();
317 Eigen::Vector3d pose_with_time (pose(0), pose(1), transition_time);
318 Eigen::Vector3d next_pose_with_time (nextpose(0), nextpose(1), next_transition_time);
320 Eigen::Vector3d direction_vec = next_pose_with_time - pose_with_time;
321 if(direction_vec.norm() == 0)
323 Eigen::Vector3d dl = 0.1 * direction_vec;
325 for (Eigen::Vector3d position = pose_with_time; (position-pose_with_time).norm() <= direction_vec.norm(); position += dl)
328 Eigen::Vector3d s1 (obstacles->at(l)->getCentroid()(0), obstacles->at(l)->getCentroid()(1), 0);
330 obstacles->at(l)->predictCentroidConstantVelocity(t, s2.head(2));
332 Eigen::Vector3d r = position;
333 Eigen::Vector3d p1 = s1 - r;
334 Eigen::Vector3d p2 = s2 - r;
335 Eigen::Vector3d
d = ((s2 - s1).
cross(p1.cross(p2))) / (s2 - s1).squaredNorm();
336 Eigen::Vector3d phi = 1 / d.squaredNorm() * ((d.cross(p2) / p2.norm()) - (d.cross(p1) / p1.norm()));
338 if (dl.norm() < (next_pose_with_time - position).norm())
341 H += phi.dot(next_pose_with_time - position);
346 hsignature3d_.at(l) = H/(4*M_PI);
367 for(
size_t i = 0; i < hsignature3d_.size(); ++i)
381 ROS_ERROR(
"Cannot compare HSignature3d equivalence classes with types other than HSignature3d.");
392 for(
const double&
value : hsignature3d_)
394 if (!std::isfinite(
value))
406 for(
const double&
value : hsignature3d_)
418 const std::vector<double>&
values()
const {
return hsignature3d_;}
virtual bool isValid() const
Check if the equivalence value is detected correctly.
TFSIMD_FORCE_INLINE Vector3 cross(const Vector3 &v) const
virtual bool isEqual(const EquivalenceClass &other) const
Check if two candidate classes are equivalent.
Config class for the teb_local_planner and its components.
The H-signature in three dimensions (here: x-y-t) defines an equivalence relation based on homology u...
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
struct teb_local_planner::TebConfig::Robot robot
Robot related parameters.
The H-signature defines an equivalence relation based on homology in terms of complex calculus...
virtual bool isValid() const
Check if the equivalence value is detected correctly.
void calculateHSignature(BidirIter path_start, BidirIter path_end, Fun fun_cplx_point, const ObstContainer *obstacles)
Calculate the H-Signature of a path.
std::complex< long double > hsignature_
struct teb_local_planner::TebConfig::HomotopyClasses hcp
virtual bool isReasonable() const
Check if the trajectory is non-looping around any obstacle. Values greater than 1 indicate a looping ...
#define ROS_ASSERT_MSG(cond,...)
std::vector< ObstaclePtr > ObstContainer
Abbrev. for containers storing multiple obstacles.
double h_signature_prescaler
Scale number of obstacle value in order to allow huge number of obstacles. Do not choose it extremly ...
virtual bool isReasonable() const
Check if the trajectory is non-looping around an obstacle.
void calculateHSignature(BidirIter path_start, BidirIter path_end, Fun fun_cplx_point, const ObstContainer *obstacles, boost::optional< TimeDiffSequence::iterator > timediff_start, boost::optional< TimeDiffSequence::iterator > timediff_end)
Calculate the H-Signature of a path.
const std::vector< double > & values() const
Get the current h-signature (read-only)
const std::complex< long double > & value() const
Get the current value of the h-signature (read-only)
HSignature(const TebConfig &cfg)
Constructor accepting a TebConfig.
Abstract class that defines an interface for computing and comparing equivalence classes.
bool smaller_than_abs(double i, double j)
Small helper function: check if |a|<|b|.
HSignature3d(const TebConfig &cfg)
Constructor accepting a TebConfig.
std::vector< double > hsignature3d_
double h_signature_threshold
Two h-signatures are assumed to be equal, if both the difference of real parts and complex parts are ...
virtual bool isEqual(const EquivalenceClass &other) const
Check if two candidate classes are equivalent.
double max_vel_x
Maximum translational velocity of the robot.