41 #include <boost/math/constants/constants.hpp> 
   50   : JointModel(
name), angular_distance_weight_(1.0), motion_model_(HOLONOMIC), min_translational_distance_(1e-5)
 
   54   local_variable_names_.push_back(
"x");
 
   55   local_variable_names_.push_back(
"y");
 
   56   local_variable_names_.push_back(
"theta");
 
   57   for (
int i = 0; i < 3; ++i)
 
   59     variable_names_.push_back(name_ + 
"/" + local_variable_names_[i]);
 
   60     variable_index_map_[variable_names_.back()] = i;
 
   63   variable_bounds_.resize(3);
 
   64   variable_bounds_[0].position_bounded_ = 
true;
 
   65   variable_bounds_[1].position_bounded_ = 
true;
 
   66   variable_bounds_[2].position_bounded_ = 
false;
 
   68   variable_bounds_[0].min_position_ = -std::numeric_limits<double>::infinity();
 
   69   variable_bounds_[0].max_position_ = std::numeric_limits<double>::infinity();
 
   70   variable_bounds_[1].min_position_ = -std::numeric_limits<double>::infinity();
 
   71   variable_bounds_[1].max_position_ = std::numeric_limits<double>::infinity();
 
   72   variable_bounds_[2].min_position_ = -boost::math::constants::pi<double>();
 
   73   variable_bounds_[2].max_position_ = boost::math::constants::pi<double>();
 
   75   computeVariableBoundsMsg();
 
   78 unsigned int PlanarJointModel::getStateSpaceDimension()
 const 
   83 double PlanarJointModel::getMaximumExtent(
const Bounds& other_bounds)
 const 
   85   double dx = other_bounds[0].max_position_ - other_bounds[0].min_position_;
 
   86   double dy = other_bounds[1].max_position_ - other_bounds[1].min_position_;
 
   87   return sqrt(dx * dx + dy * dy) + boost::math::constants::pi<double>() * angular_distance_weight_;
 
   90 void PlanarJointModel::getVariableDefaultPositions(
double* values, 
const Bounds& bounds)
 const 
   92   for (
unsigned int i = 0; i < 2; ++i)
 
   95     if (bounds[i].min_position_ <= 0.0 && bounds[i].max_position_ >= 0.0)
 
   98       values[i] = (bounds[i].min_position_ + bounds[i].max_position_) / 2.0;
 
  104                                                   const Bounds& bounds)
 const 
  106   if (bounds[0].max_position_ >= std::numeric_limits<double>::infinity() ||
 
  107       bounds[0].min_position_ <= -std::numeric_limits<double>::infinity())
 
  111   if (bounds[1].max_position_ >= std::numeric_limits<double>::infinity() ||
 
  112       bounds[1].min_position_ <= -std::numeric_limits<double>::infinity())
 
  120                                                         const Bounds& bounds, 
const double* seed,
 
  123   if (bounds[0].max_position_ >= std::numeric_limits<double>::infinity() ||
 
  124       bounds[0].min_position_ <= -std::numeric_limits<double>::infinity())
 
  128                                 std::min(bounds[0].max_position_, seed[0] + 
distance));
 
  129   if (bounds[1].max_position_ >= std::numeric_limits<double>::infinity() ||
 
  130       bounds[1].min_position_ <= -std::numeric_limits<double>::infinity())
 
  134                                 std::min(bounds[1].max_position_, seed[1] + 
distance));
 
  136   double da = angular_distance_weight_ * 
distance;
 
  138   if (da > boost::math::constants::pi<double>())
 
  139     da = boost::math::constants::pi<double>();
 
  141   normalizeRotation(
values);
 
  145                                   double& dx, 
double& dy, 
double& initial_turn, 
double& drive_angle, 
double& final_turn)
 
  147   dx = to[0] - from[0];
 
  148   dy = to[1] - from[1];
 
  159   const double angle_straight_diff = std::hypot(dx, dy) > min_translational_distance ?
 
  162   const double angle_backward_diff =
 
  164   const double move_straight_cost =
 
  166   const double move_backward_cost =
 
  168   if (move_straight_cost <= move_backward_cost)
 
  170     initial_turn = angle_straight_diff;
 
  174     initial_turn = angle_backward_diff;
 
  176   drive_angle = from[2] + initial_turn;
 
  180 void PlanarJointModel::interpolate(
const double* from, 
const double* to, 
const double t, 
double* state)
 const 
  182   if (motion_model_ == HOLONOMIC)
 
  185     state[0] = from[0] + (to[0] - from[0]) * t;
 
  186     state[1] = from[1] + (to[1] - from[1]) * t;
 
  189     double diff = to[2] - from[2];
 
  190     if (fabs(diff) <= boost::math::constants::pi<double>())
 
  191       state[2] = from[2] + diff * t;
 
  195         diff = 2.0 * boost::math::constants::pi<double>() - diff;
 
  197         diff = -2.0 * boost::math::constants::pi<double>() - diff;
 
  198       state[2] = from[2] - diff * 
t;
 
  200       if (state[2] > boost::math::constants::pi<double>())
 
  201         state[2] -= 2.0 * boost::math::constants::pi<double>();
 
  202       else if (state[2] < -boost::math::constants::pi<double>())
 
  203         state[2] += 2.0 * boost::math::constants::pi<double>();
 
  206   else if (motion_model_ == DIFF_DRIVE)
 
  208     double dx, dy, initial_turn, drive_angle, final_turn;
 
  212     double initial_d = fabs(initial_turn) * angular_distance_weight_;
 
  214     double drive_d = hypot(dx, dy);
 
  216     double final_d = fabs(final_turn) * angular_distance_weight_;
 
  219     double total_d = initial_d + drive_d + final_d;
 
  224     if (total_d < std::numeric_limits<float>::epsilon())
 
  233     double initial_frac = initial_d / total_d;
 
  234     double drive_frac = drive_d / total_d;
 
  235     double final_frac = final_d / total_d;
 
  240     if (t <= initial_frac)
 
  242       percent = 
t / initial_frac;
 
  245       state[2] = from[2] + initial_turn * percent;
 
  248     else if (t <= initial_frac + drive_frac)
 
  250       percent = (
t - initial_frac) / drive_frac;
 
  251       state[0] = from[0] + dx * percent;
 
  252       state[1] = from[1] + dy * percent;
 
  253       state[2] = drive_angle;
 
  258       percent = (
t - initial_frac - drive_frac) / final_frac;
 
  261       state[2] = drive_angle + final_turn * percent;
 
  268   if (motion_model_ == HOLONOMIC)
 
  270     double dx = values1[0] - values2[0];
 
  271     double dy = values1[1] - values2[1];
 
  273     double d = fabs(values1[2] - values2[2]);
 
  274     d = (
d > boost::math::constants::pi<double>()) ? 2.0 * boost::math::constants::pi<double>() - 
d : 
d;
 
  275     return sqrt(dx * dx + dy * dy) + angular_distance_weight_ * 
d;
 
  277   else if (motion_model_ == DIFF_DRIVE)
 
  279     double dx, dy, initial_turn, drive_angle, final_turn;
 
  282     return hypot(dx, dy) + angular_distance_weight_ * (fabs(initial_turn) + fabs(final_turn));
 
  287 bool PlanarJointModel::satisfiesPositionBounds(
const double* values, 
const Bounds& bounds, 
double margin)
 const 
  289   for (
unsigned int i = 0; i < 3; ++i)
 
  290     if (values[i] < bounds[i].min_position_ - margin || values[i] > bounds[i].max_position_ + margin)
 
  295 bool PlanarJointModel::normalizeRotation(
double* values)
 const 
  298   if (v >= -boost::math::constants::pi<double>() && v <= boost::math::constants::pi<double>())
 
  300   v = fmod(v, 2.0 * boost::math::constants::pi<double>());
 
  301   if (v < -boost::math::constants::pi<double>())
 
  302     v += 2.0 * boost::math::constants::pi<double>();
 
  303   else if (v > boost::math::constants::pi<double>())
 
  304     v -= 2.0 * boost::math::constants::pi<double>();
 
  308 bool PlanarJointModel::enforcePositionBounds(
double* values, 
const Bounds& bounds)
 const 
  310   bool result = normalizeRotation(values);
 
  311   for (
unsigned int i = 0; i < 2; ++i)
 
  313     if (values[i] < bounds[i].min_position_)
 
  315       values[i] = bounds[i].min_position_;
 
  318     else if (values[i] > bounds[i].max_position_)
 
  320       values[i] = bounds[i].max_position_;
 
  327 void PlanarJointModel::computeTransform(
const double* joint_values, Eigen::Isometry3d& transf)
 const 
  329   transf = Eigen::Isometry3d(Eigen::Translation3d(joint_values[0], joint_values[1], 0.0) *
 
  330                              Eigen::AngleAxisd(joint_values[2], Eigen::Vector3d::UnitZ()));
 
  333 void PlanarJointModel::computeVariablePositions(
const Eigen::Isometry3d& transf, 
double* joint_values)
 const 
  335   joint_values[0] = transf.translation().x();
 
  336   joint_values[1] = transf.translation().y();
 
  339   Eigen::Quaterniond q(transf.linear());
 
  341   double s_squared = 1.0 - (q.w() * q.w());
 
  342   if (s_squared < 10.0 * std::numeric_limits<double>::epsilon())
 
  343     joint_values[2] = 0.0;
 
  346     double s = 1.0 / sqrt(s_squared);
 
  347     joint_values[2] = (acos(q.w()) * 2.0f) * (q.z() * 
s);