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 #include <moveit/robot_trajectory/robot_trajectory.h>
00038 #include <moveit/robot_state/conversions.h>
00039 #include <eigen_conversions/eigen_msg.h>
00040 #include <boost/math/constants/constants.hpp>
00041 #include <numeric>
00042
00043 robot_trajectory::RobotTrajectory::RobotTrajectory(const robot_model::RobotModelConstPtr &kmodel, const std::string &group) :
00044 kmodel_(kmodel),
00045 group_(group.empty() ? NULL : kmodel->getJointModelGroup(group))
00046 {
00047 }
00048
00049 void robot_trajectory::RobotTrajectory::setGroupName(const std::string &group_name)
00050 {
00051 group_ = kmodel_->getJointModelGroup(group_name);
00052 }
00053
00054 const std::string& robot_trajectory::RobotTrajectory::getGroupName() const
00055 {
00056 if (group_)
00057 return group_->getName();
00058 static const std::string empty;
00059 return empty;
00060 }
00061
00062 double robot_trajectory::RobotTrajectory::getAverageSegmentDuration() const
00063 {
00064 if (duration_from_previous_.empty())
00065 return 0.0;
00066 else
00067 return std::accumulate(duration_from_previous_.begin(), duration_from_previous_.end(), 0.0) / (double)duration_from_previous_.size();
00068 }
00069
00070 void robot_trajectory::RobotTrajectory::swap(robot_trajectory::RobotTrajectory &other)
00071 {
00072 kmodel_.swap(other.kmodel_);
00073 std::swap(group_, other.group_);
00074 waypoints_.swap(other.waypoints_);
00075 duration_from_previous_.swap(duration_from_previous_);
00076 }
00077
00078 void robot_trajectory::RobotTrajectory::append(const RobotTrajectory &source, double dt)
00079 {
00080 waypoints_.insert(waypoints_.end(), source.waypoints_.begin(),source.waypoints_.end());
00081 std::size_t index = duration_from_previous_.size();
00082 duration_from_previous_.insert(duration_from_previous_.end(), source.duration_from_previous_.begin(),source.duration_from_previous_.end());
00083 if (duration_from_previous_.size() > index)
00084 duration_from_previous_[index] += dt;
00085 }
00086
00087 void robot_trajectory::RobotTrajectory::reverse()
00088 {
00089 std::reverse(waypoints_.begin(), waypoints_.end());
00090 if (!duration_from_previous_.empty())
00091 {
00092 duration_from_previous_.push_back(duration_from_previous_.front());
00093 std::reverse(duration_from_previous_.begin(), duration_from_previous_.end());
00094 duration_from_previous_.pop_back();
00095 }
00096 }
00097
00098 void robot_trajectory::RobotTrajectory::unwind()
00099 {
00100 if (waypoints_.empty())
00101 return;
00102
00103 const std::vector<const robot_model::JointModel*> &cont_joints = group_ ?
00104 group_->getContinuousJointModels() : kmodel_->getContinuousJointModels();
00105
00106 for (std::size_t i = 0 ; i < cont_joints.size() ; ++i)
00107 {
00108
00109 double running_offset = 0.0;
00110 double last_value = waypoints_[0]->getJointState(cont_joints[i])->getVariableValues()[0];
00111
00112 for (std::size_t j = 1 ; j < waypoints_.size() ; ++j)
00113 {
00114 robot_state::JointState *js = waypoints_[j]->getJointState(cont_joints[i]);
00115 std::vector<double> current_value = js->getVariableValues();
00116 if (last_value > current_value[0] + boost::math::constants::pi<double>())
00117 running_offset += 2.0 * boost::math::constants::pi<double>();
00118 else
00119 if (current_value[0] > last_value + boost::math::constants::pi<double>())
00120 running_offset -= 2.0 * boost::math::constants::pi<double>();
00121
00122 last_value = current_value[0];
00123 if (running_offset > std::numeric_limits<double>::epsilon() || running_offset < -std::numeric_limits<double>::epsilon())
00124 {
00125 current_value[0] += running_offset;
00126 js->setVariableValues(current_value);
00127 }
00128 }
00129 }
00130 }
00131
00132 void robot_trajectory::RobotTrajectory::unwind(const robot_state::RobotState &state)
00133 {
00134 if (waypoints_.empty())
00135 return;
00136
00137 const std::vector<const robot_model::JointModel*> &cont_joints = group_ ?
00138 group_->getContinuousJointModels() : kmodel_->getContinuousJointModels();
00139
00140 for (std::size_t i = 0 ; i < cont_joints.size() ; ++i)
00141 {
00142 const robot_state::JointState *jstate = state.getJointState(cont_joints[i]);
00143 std::vector<double> reference_value = jstate->getVariableValues();
00144 jstate->getJointModel()->enforceBounds(reference_value);
00145
00146
00147 double running_offset = jstate->getVariableValues()[0] - reference_value[0];
00148
00149 robot_state::JointState *js0 = waypoints_[0]->getJointState(cont_joints[i]);
00150 double last_value = js0->getVariableValues()[0];
00151 if (running_offset > std::numeric_limits<double>::epsilon() || running_offset < -std::numeric_limits<double>::epsilon())
00152 {
00153 std::vector<double> current_value = js0->getVariableValues();
00154 current_value[0] += running_offset;
00155 js0->setVariableValues(current_value);
00156 }
00157
00158 for (std::size_t j = 1 ; j < waypoints_.size() ; ++j)
00159 {
00160 robot_state::JointState *js = waypoints_[j]->getJointState(cont_joints[i]);
00161 std::vector<double> current_value = js->getVariableValues();
00162 if (last_value > current_value[0] + boost::math::constants::pi<double>())
00163 running_offset += 2.0 * boost::math::constants::pi<double>();
00164 else
00165 if (current_value[0] > last_value + boost::math::constants::pi<double>())
00166 running_offset -= 2.0 * boost::math::constants::pi<double>();
00167
00168 last_value = current_value[0];
00169 if (running_offset > std::numeric_limits<double>::epsilon() || running_offset < -std::numeric_limits<double>::epsilon())
00170 {
00171 current_value[0] += running_offset;
00172 js->setVariableValues(current_value);
00173 }
00174 }
00175 }
00176 }
00177
00178 void robot_trajectory::RobotTrajectory::clear()
00179 {
00180 waypoints_.clear();
00181 duration_from_previous_.clear();
00182 }
00183
00184 void robot_trajectory::RobotTrajectory::getRobotTrajectoryMsg(moveit_msgs::RobotTrajectory &trajectory) const
00185 {
00186 trajectory = moveit_msgs::RobotTrajectory();
00187 if (waypoints_.empty())
00188 return;
00189 const std::vector<const robot_model::JointModel*> &jnt = group_ ? group_->getJointModels() : kmodel_->getJointModels();
00190
00191 std::vector<const robot_model::JointModel*> onedof;
00192 std::vector<const robot_model::JointModel*> mdof;
00193 trajectory.joint_trajectory.joint_names.clear();
00194 trajectory.multi_dof_joint_trajectory.joint_names.clear();
00195
00196 for (std::size_t i = 0 ; i < jnt.size() ; ++i)
00197 if (jnt[i]->getVariableCount() == 1)
00198 {
00199 trajectory.joint_trajectory.joint_names.push_back(jnt[i]->getName());
00200 onedof.push_back(jnt[i]);
00201 }
00202 else
00203 {
00204 trajectory.multi_dof_joint_trajectory.joint_names.push_back(jnt[i]->getName());
00205 mdof.push_back(jnt[i]);
00206 }
00207 if (!onedof.empty())
00208 {
00209 trajectory.joint_trajectory.header.frame_id = kmodel_->getModelFrame();
00210 trajectory.joint_trajectory.header.stamp = ros::Time(0);
00211 trajectory.joint_trajectory.points.resize(waypoints_.size());
00212 }
00213
00214 if (!mdof.empty())
00215 {
00216 trajectory.multi_dof_joint_trajectory.header.frame_id = kmodel_->getModelFrame();
00217 trajectory.multi_dof_joint_trajectory.header.stamp = ros::Time(0);
00218 trajectory.multi_dof_joint_trajectory.points.resize(waypoints_.size());
00219 }
00220
00221 static const ros::Duration zero_duration(0.0);
00222 double total_time = 0.0;
00223 for (std::size_t i = 0 ; i < waypoints_.size() ; ++i)
00224 {
00225 if (duration_from_previous_.size() > i)
00226 total_time += duration_from_previous_[i];
00227
00228 if (!onedof.empty())
00229 {
00230 trajectory.joint_trajectory.points[i].positions.resize(onedof.size());
00231 trajectory.joint_trajectory.points[i].velocities.reserve(onedof.size());
00232 for (std::size_t j = 0 ; j < onedof.size() ; ++j)
00233 {
00234 const robot_state::JointState *js = waypoints_[i]->getJointState(onedof[j]->getName());
00235 trajectory.joint_trajectory.points[i].positions[j] = js->getVariableValues()[0];
00236
00237 if (!js->getVelocities().empty())
00238 trajectory.joint_trajectory.points[i].velocities.push_back(js->getVelocities()[0]);
00239 if (!js->getAccelerations().empty())
00240 trajectory.joint_trajectory.points[i].accelerations.push_back(js->getAccelerations()[0]);
00241 }
00242
00243 if (trajectory.joint_trajectory.points[i].velocities.size() != onedof.size())
00244 trajectory.joint_trajectory.points[i].velocities.clear();
00245
00246 if (duration_from_previous_.size() > i)
00247 trajectory.joint_trajectory.points[i].time_from_start = ros::Duration(total_time);
00248 else
00249 trajectory.joint_trajectory.points[i].time_from_start = zero_duration;
00250 }
00251 if (!mdof.empty())
00252 {
00253 trajectory.multi_dof_joint_trajectory.points[i].transforms.resize(mdof.size());
00254 for (std::size_t j = 0 ; j < mdof.size() ; ++j)
00255 tf::transformEigenToMsg(waypoints_[i]->getJointState(mdof[j]->getName())->getVariableTransform(), trajectory.multi_dof_joint_trajectory.points[i].transforms[j]);
00256 if (duration_from_previous_.size() > i)
00257 trajectory.multi_dof_joint_trajectory.points[i].time_from_start = ros::Duration(total_time);
00258 else
00259 trajectory.multi_dof_joint_trajectory.points[i].time_from_start = zero_duration;
00260 }
00261 }
00262 }
00263
00264 void robot_trajectory::RobotTrajectory::setRobotTrajectoryMsg(const robot_state::RobotState &reference_state,
00265 const moveit_msgs::RobotTrajectory &trajectory)
00266 {
00267
00268 robot_state::RobotState copy = reference_state;
00269 clear();
00270
00271 std::size_t state_count = std::max(trajectory.joint_trajectory.points.size(),
00272 trajectory.multi_dof_joint_trajectory.points.size());
00273 ros::Time last_time_stamp = trajectory.joint_trajectory.points.empty() ? trajectory.multi_dof_joint_trajectory.header.stamp : trajectory.joint_trajectory.header.stamp;
00274 ros::Time this_time_stamp = last_time_stamp;
00275
00276 for (std::size_t i = 0 ; i < state_count ; ++i)
00277 {
00278 moveit_msgs::RobotState rs;
00279 if (trajectory.joint_trajectory.points.size() > i)
00280 {
00281 rs.joint_state.header = trajectory.joint_trajectory.header;
00282 rs.joint_state.header.stamp = rs.joint_state.header.stamp + trajectory.joint_trajectory.points[i].time_from_start;
00283 rs.joint_state.name = trajectory.joint_trajectory.joint_names;
00284 rs.joint_state.position = trajectory.joint_trajectory.points[i].positions;
00285 rs.joint_state.velocity = trajectory.joint_trajectory.points[i].velocities;
00286 this_time_stamp = rs.joint_state.header.stamp;
00287 }
00288 if (trajectory.multi_dof_joint_trajectory.points.size() > i)
00289 {
00290 rs.multi_dof_joint_state.joint_names = trajectory.multi_dof_joint_trajectory.joint_names;
00291 rs.multi_dof_joint_state.header = trajectory.multi_dof_joint_trajectory.header;
00292 rs.multi_dof_joint_state.header.stamp = trajectory.multi_dof_joint_trajectory.header.stamp + trajectory.multi_dof_joint_trajectory.points[i].time_from_start;
00293 rs.multi_dof_joint_state.joint_transforms = trajectory.multi_dof_joint_trajectory.points[i].transforms;
00294 this_time_stamp = rs.multi_dof_joint_state.header.stamp;
00295 }
00296
00297 robot_state::RobotStatePtr st(new robot_state::RobotState(copy));
00298 robot_state::robotStateMsgToRobotState(rs, *st);
00299 addSuffixWayPoint(st, (this_time_stamp - last_time_stamp).toSec());
00300 last_time_stamp = this_time_stamp;
00301 }
00302 }
00303
00304 void robot_trajectory::RobotTrajectory::setRobotTrajectoryMsg(const robot_state::RobotState &reference_state,
00305 const moveit_msgs::RobotState &state, const moveit_msgs::RobotTrajectory &trajectory)
00306 {
00307 robot_state::RobotState st(reference_state);
00308 robot_state::robotStateMsgToRobotState(state, st);
00309 setRobotTrajectoryMsg(st, trajectory);
00310 }
00311
00312 void robot_trajectory::RobotTrajectory::findWayPointIndicesForDurationAfterStart( const double& duration, int& before,
00313 int& after, double &blend ) const
00314 {
00315 if(duration < 0.0)
00316 {
00317 before = 0;
00318 after = 0;
00319 blend = 0;
00320 return;
00321 }
00322
00323
00324 std::size_t index = 0, num_points = waypoints_.size();
00325 double running_duration = 0.0;
00326 for( ; index < num_points; index++)
00327 {
00328 running_duration += duration_from_previous_[index];
00329 if( running_duration >= duration )
00330 break;
00331 }
00332 before = std::max<int>(index - 1, 0);
00333 after = std::min<int>(index, num_points - 1);
00334
00335
00336 double before_time = running_duration - duration_from_previous_[index];
00337 if(after == before)
00338 blend = 1.0;
00339 else
00340 blend = (duration - before_time) / duration_from_previous_[index];
00341 }
00342
00343 double robot_trajectory::RobotTrajectory::getWaypointDurationFromStart(std::size_t index) const
00344 {
00345 if(index >= duration_from_previous_.size())
00346 return -1.0;
00347
00348 double time = 0;
00349 for(std::size_t i = 0; i <= index; ++i)
00350 time += duration_from_previous_[i];
00351 return time;
00352 }
00353
00354 bool robot_trajectory::RobotTrajectory::getStateAtDurationFromStart(const double request_duration,
00355 robot_state::RobotStatePtr& output_state) const
00356 {
00357 if( !getWayPointCount() )
00358 return false;
00359
00360 int before=0, after=0;
00361 double blend = 1.0;
00362 findWayPointIndicesForDurationAfterStart(request_duration, before, after, blend);
00363
00364 waypoints_[before]->interpolate(*waypoints_[after], blend, *output_state);
00365
00366 return true;
00367 }