40 #include <boost/math/constants/constants.hpp>
50 RobotTrajectory::RobotTrajectory(
const moveit::core::RobotModelConstPtr&
robot_model,
56 RobotTrajectory::RobotTrajectory(
const RobotTrajectory& other,
bool deepcopy)
61 this->waypoints_.clear();
62 for (
const auto& waypoint : other.waypoints_)
64 this->waypoints_.emplace_back(std::make_shared<moveit::core::RobotState>(*waypoint));
69 void RobotTrajectory::setGroupName(
const std::string& group_name)
71 group_ = robot_model_->getJointModelGroup(group_name);
74 const std::string& RobotTrajectory::getGroupName()
const
77 return group_->getName();
78 static const std::string EMPTY;
82 double RobotTrajectory::getDuration()
const
84 return std::accumulate(duration_from_previous_.begin(), duration_from_previous_.end(), 0.0);
87 double RobotTrajectory::getAverageSegmentDuration()
const
89 if (duration_from_previous_.empty())
92 return getDuration() /
static_cast<double>(duration_from_previous_.size());
98 std::swap(group_, other.
group_);
103 void RobotTrajectory::append(
const RobotTrajectory& source,
double dt,
size_t start_index,
size_t end_index)
105 end_index = std::min(end_index, source.
waypoints_.size());
106 if (start_index >= end_index)
108 waypoints_.insert(waypoints_.end(), std::next(source.
waypoints_.begin(), start_index),
109 std::next(source.
waypoints_.begin(), end_index));
110 std::size_t
index = duration_from_previous_.size();
111 duration_from_previous_.insert(duration_from_previous_.end(),
114 if (duration_from_previous_.size() > index)
115 duration_from_previous_[
index] += dt;
118 void RobotTrajectory::reverse()
120 std::reverse(waypoints_.begin(), waypoints_.end());
121 for (moveit::core::RobotStatePtr& waypoint : waypoints_)
124 waypoint->invertVelocity();
126 if (!duration_from_previous_.empty())
128 duration_from_previous_.push_back(duration_from_previous_.front());
129 std::reverse(duration_from_previous_.begin(), duration_from_previous_.end());
130 duration_from_previous_.pop_back();
134 void RobotTrajectory::unwind()
136 if (waypoints_.empty())
139 const std::vector<const moveit::core::JointModel*>& cont_joints =
140 group_ ? group_->getContinuousJointModels() : robot_model_->getContinuousJointModels();
145 double running_offset = 0.0;
146 double last_value = waypoints_[0]->getJointPositions(cont_joint)[0];
148 for (std::size_t j = 1; j < waypoints_.size(); ++j)
150 double current_value = waypoints_[j]->getJointPositions(cont_joint)[0];
151 if (last_value > current_value + boost::math::constants::pi<double>())
152 running_offset += 2.0 * boost::math::constants::pi<double>();
153 else if (current_value > last_value + boost::math::constants::pi<double>())
154 running_offset -= 2.0 * boost::math::constants::pi<double>();
156 last_value = current_value;
157 if (running_offset > std::numeric_limits<double>::epsilon() ||
158 running_offset < -std::numeric_limits<double>::epsilon())
160 current_value += running_offset;
161 waypoints_[j]->setJointPositions(cont_joint, ¤t_value);
165 for (moveit::core::RobotStatePtr& waypoint : waypoints_)
171 if (waypoints_.empty())
174 const std::vector<const moveit::core::JointModel*>& cont_joints =
175 group_ ? group_->getContinuousJointModels() : robot_model_->getContinuousJointModels();
180 double reference_value = reference_value0;
181 cont_joint->enforcePositionBounds(&reference_value);
184 double running_offset = reference_value0 - reference_value;
186 double last_value = waypoints_[0]->getJointPositions(cont_joint)[0];
187 if (running_offset > std::numeric_limits<double>::epsilon() ||
188 running_offset < -std::numeric_limits<double>::epsilon())
190 double current_value = last_value + running_offset;
191 waypoints_[0]->setJointPositions(cont_joint, ¤t_value);
194 for (std::size_t j = 1; j < waypoints_.size(); ++j)
196 double current_value = waypoints_[j]->getJointPositions(cont_joint)[0];
197 if (last_value > current_value + boost::math::constants::pi<double>())
198 running_offset += 2.0 * boost::math::constants::pi<double>();
199 else if (current_value > last_value + boost::math::constants::pi<double>())
200 running_offset -= 2.0 * boost::math::constants::pi<double>();
202 last_value = current_value;
203 if (running_offset > std::numeric_limits<double>::epsilon() ||
204 running_offset < -std::numeric_limits<double>::epsilon())
206 current_value += running_offset;
207 waypoints_[j]->setJointPositions(cont_joint, ¤t_value);
211 for (moveit::core::RobotStatePtr& waypoint : waypoints_)
215 void RobotTrajectory::clear()
218 duration_from_previous_.clear();
221 void RobotTrajectory::getRobotTrajectoryMsg(moveit_msgs::RobotTrajectory& trajectory,
222 const std::vector<std::string>& joint_filter)
const
224 trajectory = moveit_msgs::RobotTrajectory();
225 if (waypoints_.empty())
227 const std::vector<const moveit::core::JointModel*>& jnts =
228 group_ ? group_->getActiveJointModels() : robot_model_->getActiveJointModels();
230 std::vector<const moveit::core::JointModel*> onedof;
231 std::vector<const moveit::core::JointModel*> mdof;
232 trajectory.joint_trajectory.joint_names.clear();
233 trajectory.multi_dof_joint_trajectory.joint_names.clear();
238 if (!joint_filter.empty() &&
239 std::find(joint_filter.begin(), joint_filter.end(), active_joint->getName()) == joint_filter.end())
242 if (active_joint->getVariableCount() == 1)
244 trajectory.joint_trajectory.joint_names.push_back(active_joint->getName());
245 onedof.push_back(active_joint);
249 trajectory.multi_dof_joint_trajectory.joint_names.push_back(active_joint->getName());
250 mdof.push_back(active_joint);
256 trajectory.joint_trajectory.header.frame_id = robot_model_->getModelFrame();
257 trajectory.joint_trajectory.header.stamp =
ros::Time(0);
258 trajectory.joint_trajectory.points.resize(waypoints_.size());
263 trajectory.multi_dof_joint_trajectory.header.frame_id = robot_model_->getModelFrame();
264 trajectory.multi_dof_joint_trajectory.header.stamp =
ros::Time(0);
265 trajectory.multi_dof_joint_trajectory.points.resize(waypoints_.size());
269 double total_time = 0.0;
270 for (std::size_t i = 0; i < waypoints_.size(); ++i)
272 if (duration_from_previous_.size() > i)
273 total_time += duration_from_previous_[i];
277 trajectory.joint_trajectory.points[i].positions.resize(onedof.size());
278 trajectory.joint_trajectory.points[i].velocities.reserve(onedof.size());
280 for (std::size_t j = 0; j < onedof.size(); ++j)
282 trajectory.joint_trajectory.points[i].positions[j] =
283 waypoints_[i]->getVariablePosition(onedof[j]->getFirstVariableIndex());
285 if (waypoints_[i]->hasVelocities())
286 trajectory.joint_trajectory.points[i].velocities.push_back(
287 waypoints_[i]->getVariableVelocity(onedof[j]->getFirstVariableIndex()));
288 if (waypoints_[i]->hasAccelerations())
289 trajectory.joint_trajectory.points[i].accelerations.push_back(
290 waypoints_[i]->getVariableAcceleration(onedof[j]->getFirstVariableIndex()));
291 if (waypoints_[i]->hasEffort())
292 trajectory.joint_trajectory.points[i].effort.push_back(
293 waypoints_[i]->getVariableEffort(onedof[j]->getFirstVariableIndex()));
296 if (trajectory.joint_trajectory.points[i].velocities.size() != onedof.size())
297 trajectory.joint_trajectory.points[i].velocities.clear();
299 if (trajectory.joint_trajectory.points[i].accelerations.size() != onedof.size())
300 trajectory.joint_trajectory.points[i].accelerations.clear();
302 if (trajectory.joint_trajectory.points[i].effort.size() != onedof.size())
303 trajectory.joint_trajectory.points[i].effort.clear();
305 if (duration_from_previous_.size() > i)
306 trajectory.joint_trajectory.points[i].time_from_start =
ros::Duration(total_time);
308 trajectory.joint_trajectory.points[i].time_from_start = ZERO_DURATION;
312 trajectory.multi_dof_joint_trajectory.points[i].transforms.resize(mdof.size());
313 for (std::size_t j = 0; j < mdof.size(); ++j)
315 geometry_msgs::TransformStamped ts =
tf2::eigenToTransform(waypoints_[i]->getJointTransform(mdof[j]));
316 trajectory.multi_dof_joint_trajectory.points[i].transforms[j] = ts.transform;
318 if (waypoints_[i]->hasVelocities() && (mdof[j]->getType() == moveit::core::JointModel::JointType::PLANAR))
320 const std::vector<std::string> names = mdof[j]->getVariableNames();
321 const double* velocities = waypoints_[i]->getJointVelocities(mdof[j]);
323 geometry_msgs::Twist point_velocity;
325 for (std::size_t k = 0; k < names.size(); ++k)
327 if (names[k].find(
"/x") != std::string::npos)
329 point_velocity.linear.x = velocities[k];
331 else if (names[k].find(
"/y") != std::string::npos)
333 point_velocity.linear.y = velocities[k];
335 else if (names[k].find(
"/z") != std::string::npos)
337 point_velocity.linear.z = velocities[k];
339 else if (names[k].find(
"/theta") != std::string::npos)
341 point_velocity.angular.z = velocities[k];
344 trajectory.multi_dof_joint_trajectory.points[i].velocities.push_back(point_velocity);
347 if (duration_from_previous_.size() > i)
348 trajectory.multi_dof_joint_trajectory.points[i].time_from_start =
ros::Duration(total_time);
350 trajectory.multi_dof_joint_trajectory.points[i].time_from_start = ZERO_DURATION;
356 const trajectory_msgs::JointTrajectory& trajectory)
361 std::size_t state_count = trajectory.points.size();
362 ros::Time last_time_stamp = trajectory.header.stamp;
363 ros::Time this_time_stamp = last_time_stamp;
365 for (std::size_t i = 0; i < state_count; ++i)
367 this_time_stamp = trajectory.header.stamp + trajectory.points[i].time_from_start;
369 st->setVariablePositions(trajectory.joint_names, trajectory.points[i].positions);
370 if (!trajectory.points[i].velocities.empty())
371 st->setVariableVelocities(trajectory.joint_names, trajectory.points[i].velocities);
372 if (!trajectory.points[i].accelerations.empty())
373 st->setVariableAccelerations(trajectory.joint_names, trajectory.points[i].accelerations);
374 if (!trajectory.points[i].effort.empty())
375 st->setVariableEffort(trajectory.joint_names, trajectory.points[i].effort);
376 addSuffixWayPoint(st, (this_time_stamp - last_time_stamp).toSec());
377 last_time_stamp = this_time_stamp;
382 const moveit_msgs::RobotTrajectory& trajectory)
388 std::size_t state_count =
389 std::max(trajectory.joint_trajectory.points.size(), trajectory.multi_dof_joint_trajectory.points.size());
390 ros::Time last_time_stamp = trajectory.joint_trajectory.points.empty() ?
391 trajectory.multi_dof_joint_trajectory.header.stamp :
392 trajectory.joint_trajectory.header.stamp;
393 ros::Time this_time_stamp = last_time_stamp;
395 for (std::size_t i = 0; i < state_count; ++i)
398 if (trajectory.joint_trajectory.points.size() > i)
400 st->setVariablePositions(trajectory.joint_trajectory.joint_names, trajectory.joint_trajectory.points[i].positions);
401 if (!trajectory.joint_trajectory.points[i].velocities.empty())
402 st->setVariableVelocities(trajectory.joint_trajectory.joint_names,
403 trajectory.joint_trajectory.points[i].velocities);
404 if (!trajectory.joint_trajectory.points[i].accelerations.empty())
405 st->setVariableAccelerations(trajectory.joint_trajectory.joint_names,
406 trajectory.joint_trajectory.points[i].accelerations);
407 if (!trajectory.joint_trajectory.points[i].effort.empty())
408 st->setVariableEffort(trajectory.joint_trajectory.joint_names, trajectory.joint_trajectory.points[i].effort);
410 trajectory.joint_trajectory.header.stamp + trajectory.joint_trajectory.points[i].time_from_start;
412 if (trajectory.multi_dof_joint_trajectory.points.size() > i)
414 for (std::size_t j = 0; j < trajectory.multi_dof_joint_trajectory.joint_names.size(); ++j)
416 Eigen::Isometry3d
t =
tf2::transformToEigen(trajectory.multi_dof_joint_trajectory.points[i].transforms[j]);
417 st->setJointPositions(trajectory.multi_dof_joint_trajectory.joint_names[j],
t);
419 this_time_stamp = trajectory.multi_dof_joint_trajectory.header.stamp +
420 trajectory.multi_dof_joint_trajectory.points[i].time_from_start;
423 addSuffixWayPoint(st, (this_time_stamp - last_time_stamp).toSec());
424 last_time_stamp = this_time_stamp;
429 const moveit_msgs::RobotState& state,
430 const moveit_msgs::RobotTrajectory& trajectory)
434 setRobotTrajectoryMsg(st, trajectory);
437 void RobotTrajectory::findWayPointIndicesForDurationAfterStart(
const double&
duration,
int& before,
int& after,
449 std::size_t
index = 0, num_points = waypoints_.size();
450 double running_duration = 0.0;
453 running_duration += duration_from_previous_[
index];
457 before = std::max<int>(index - 1, 0);
458 after = std::min<int>(index, num_points - 1);
461 double before_time = running_duration - duration_from_previous_[
index];
465 blend = (
duration - before_time) / duration_from_previous_[index];
468 double RobotTrajectory::getWayPointDurationFromStart(std::size_t index)
const
470 if (duration_from_previous_.empty())
472 if (
index >= duration_from_previous_.size())
473 index = duration_from_previous_.size() - 1;
476 for (std::size_t i = 0; i <=
index; ++i)
477 time += duration_from_previous_[i];
481 double RobotTrajectory::getWaypointDurationFromStart(std::size_t index)
const
483 return getWayPointDurationFromStart(index);
486 bool RobotTrajectory::getStateAtDurationFromStart(
const double request_duration,
487 moveit::core::RobotStatePtr& output_state)
const
490 if (getWayPointCount() == 0)
493 int before = 0, after = 0;
495 findWayPointIndicesForDurationAfterStart(request_duration, before, after, blend);
498 waypoints_[before]->interpolate(*waypoints_[after], blend, *output_state);