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);