uniform_sample_filter.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright (c) 2013, Southwest Research Institute
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  *      * Redistributions of source code must retain the above copyright
00011  *      notice, this list of conditions and the following disclaimer.
00012  *      * Redistributions in binary form must reproduce the above copyright
00013  *      notice, this list of conditions and the following disclaimer in the
00014  *      documentation and/or other materials provided with the distribution.
00015  *      * Neither the name of the Southwest Research Institute, nor the names
00016  *      of its contributors may be used to endorse or promote products derived
00017  *      from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #include <industrial_trajectory_filters/uniform_sample_filter.h>
00033 #include <kdl/velocityprofile_spline.hpp>
00034 #include <ros/ros.h>
00035 
00036 using namespace industrial_trajectory_filters;
00037 
00038 const double DEFAULT_SAMPLE_DURATION = 0.050; //seconds
00039 
00040 template<typename T>
00041   UniformSampleFilter<T>::UniformSampleFilter() :
00042       industrial_trajectory_filters::FilterBase<T>()
00043   {
00044     ROS_INFO_STREAM("Constructing N point filter");
00045     sample_duration_ = DEFAULT_SAMPLE_DURATION;
00046     this->filter_name_ = "UniformSampleFilter";
00047     this->filter_type_ = "UniformSampleFilter";
00048   }
00049 
00050 template<typename T>
00051   UniformSampleFilter<T>::~UniformSampleFilter()
00052   {
00053   }
00054 
00055 template<typename T>
00056   bool UniformSampleFilter<T>::configure()
00057   {
00058     if (!this->nh_.getParam("sample_duration", sample_duration_))
00059     {
00060       ROS_WARN_STREAM( "UniformSampleFilter, params has no attribute sample_duration.");
00061     }
00062     ROS_INFO_STREAM("Using a sample_duration value of " << sample_duration_);
00063 
00064     return true;
00065   }
00066 
00067 template<typename T>
00068   bool UniformSampleFilter<T>::update(const T& trajectory_in, T& trajectory_out)
00069   {
00070     bool success = false;
00071     size_t size_in = trajectory_in.request.trajectory.points.size();
00072     double duration_in = trajectory_in.request.trajectory.points.back().time_from_start.toSec();
00073     double interpolated_time = 0.0;
00074     size_t index_in = 0;
00075 
00076     trajectory_msgs::JointTrajectoryPoint p1, p2, interp_pt;
00077 
00078     trajectory_out = trajectory_in;
00079 
00080     // Clear out the trajectory points
00081     trajectory_out.request.trajectory.points.clear();
00082 
00083     while (interpolated_time < duration_in)
00084     {
00085       ROS_INFO_STREAM("Interpolated time: " << interpolated_time);
00086       // Increment index until the interpolated time is past the start time.
00087       while (interpolated_time > trajectory_in.request.trajectory.points[index_in + 1].time_from_start.toSec())
00088       {
00089         ROS_INFO_STREAM(
00090             "Interpolated time: " << interpolated_time << ", next point time: " << (trajectory_in.request.trajectory.points[index_in + 1].time_from_start.toSec()));
00091         ROS_INFO_STREAM("Incrementing index");
00092         index_in++;
00093         if (index_in >= size_in)
00094         {
00095           ROS_ERROR_STREAM(
00096               "Programming error, index: " << index_in << ", greater(or equal) to size: " << size_in << " input duration: " << duration_in << " interpolated time:)" << interpolated_time);
00097           return false;
00098         }
00099       }
00100       p1 = trajectory_in.request.trajectory.points[index_in];
00101       p2 = trajectory_in.request.trajectory.points[index_in + 1];
00102       if (!interpolatePt(p1, p2, interpolated_time, interp_pt))
00103       {
00104         ROS_ERROR_STREAM("Failed to interpolate point");
00105         return false;
00106       }
00107       trajectory_out.request.trajectory.points.push_back(interp_pt);
00108       interpolated_time += sample_duration_;
00109 
00110     }
00111 
00112     ROS_INFO_STREAM(
00113         "Interpolated time exceeds original trajectory (quitting), original: " << duration_in << " final interpolated time: " << interpolated_time);
00114     p2 = trajectory_in.request.trajectory.points.back();
00115     p2.time_from_start = ros::Duration(interpolated_time);
00116     // TODO: Really should check that appending the last point doesn't result in
00117     // really slow motion at the end.  This could happen if the sample duration is a
00118     // large percentage of the trajectory duration (not likely).
00119     trajectory_out.request.trajectory.points.push_back(p2);
00120 
00121     ROS_INFO_STREAM(
00122         "Uniform sampling, resample duraction: " << sample_duration_ << " input traj. size: " << trajectory_in.request.trajectory.points.size() << " output traj. size: " << trajectory_out.request.trajectory.points.size());
00123 
00124     success = true;
00125     return success;
00126   }
00127 
00128 template<typename T>
00129   bool UniformSampleFilter<T>::interpolatePt(trajectory_msgs::JointTrajectoryPoint & p1,
00130                                              trajectory_msgs::JointTrajectoryPoint & p2, double time_from_start,
00131                                              trajectory_msgs::JointTrajectoryPoint & interp_pt)
00132   {
00133     bool rtn = false;
00134     double p1_time_from_start = p1.time_from_start.toSec();
00135     double p2_time_from_start = p2.time_from_start.toSec();
00136 
00137     ROS_INFO_STREAM("time from start: " << time_from_start);
00138 
00139     if (time_from_start >= p1_time_from_start && time_from_start <= p2_time_from_start)
00140     {
00141       if (p1.positions.size() == p1.velocities.size() && p1.positions.size() == p1.accelerations.size())
00142       {
00143         if (p1.positions.size() == p2.positions.size() && p1.velocities.size() == p2.velocities.size()
00144             && p1.accelerations.size() == p2.accelerations.size())
00145         {
00146           // Copy p1 to ensure the interp_pt has the correct size vectors
00147           interp_pt = p1;
00148           // TODO: Creating a new spline calculator in this function means that
00149           // it may be created multiple times for the same points (assuming the
00150           // resample duration is less that the actual duration, which it might
00151           // be sometimes)
00152           KDL::VelocityProfile_Spline spline_calc;
00153           ROS_INFO_STREAM( "---------------Begin interpolating joint point---------------");
00154 
00155           for (size_t i = 0; i < p1.positions.size(); ++i)
00156           {
00157             // Calculated relative times for spline calculation
00158             double time_from_p1 = time_from_start - p1.time_from_start.toSec();
00159             double time_from_p1_to_p2 = p2_time_from_start - p1_time_from_start;
00160 
00161             ROS_INFO_STREAM("time from p1: " << time_from_p1);
00162             ROS_INFO_STREAM( "time_from_p1_to_p2: " << time_from_p1_to_p2);
00163 
00164             spline_calc.SetProfileDuration(p1.positions[i], p1.velocities[i], p1.accelerations[i], p2.positions[i],
00165                                            p2.velocities[i], p2.accelerations[i], time_from_p1_to_p2);
00166 
00167             ros::Duration time_from_start_dur(time_from_start);
00168             ROS_INFO_STREAM( "time from start_dur: " << time_from_start_dur);
00169 
00170             interp_pt.time_from_start = time_from_start_dur;
00171             interp_pt.positions[i] = spline_calc.Pos(time_from_p1);
00172             interp_pt.velocities[i] = spline_calc.Vel(time_from_p1);
00173             interp_pt.accelerations[i] = spline_calc.Acc(time_from_p1);
00174 
00175             ROS_INFO_STREAM(
00176                 "p1.pos: " << p1.positions[i] << ", vel: " << p1.velocities[i] << ", acc: " << p1.accelerations[i] << ", tfs: " << p1.time_from_start);
00177 
00178             ROS_INFO_STREAM(
00179                 "p2.pos: " << p2.positions[i] << ", vel: " << p2.velocities[i] << ", acc: " << p2.accelerations[i] << ", tfs: " << p2.time_from_start);
00180 
00181             ROS_INFO_STREAM(
00182                 "interp_pt.pos: " << interp_pt.positions[i] << ", vel: " << interp_pt.velocities[i] << ", acc: " << interp_pt.accelerations[i] << ", tfs: " << interp_pt.time_from_start);
00183           }
00184           ROS_INFO_STREAM( "---------------End interpolating joint point---------------");
00185           rtn = true;
00186         }
00187         else
00188         {
00189           ROS_ERROR_STREAM("Trajectory point size mismatch");
00190           ROS_ERROR_STREAM(
00191               "Trajectory point 1, pos: " << p1.positions.size() << " vel: " << p1.velocities.size() << " acc: " << p1.accelerations.size());
00192           ROS_ERROR_STREAM(
00193               "Trajectory point 2, pos: " << p2.positions.size() << " vel: " << p2.velocities.size() << " acc: " << p2.accelerations.size());
00194           rtn = false;
00195         }
00196 
00197       }
00198       else
00199       {
00200         ROS_ERROR_STREAM(
00201             "Trajectory point not fully defined, pos: " << p1.positions.size() << " vel: " << p1.velocities.size() << " acc: " << p1.accelerations.size());
00202         rtn = false;
00203       }
00204     }
00205     else
00206     {
00207       ROS_ERROR_STREAM(
00208           "Time: " << time_from_start << " not between interpolation point times[" << p1.time_from_start.toSec() << "," << p2.time_from_start.toSec() << "]");
00209       rtn = false;
00210     }
00211 
00212     return rtn;
00213   }
00214 
00215 // registering planner adapter
00216 CLASS_LOADER_REGISTER_CLASS( industrial_trajectory_filters::UniformSampleFilterAdapter,
00217                             planning_request_adapter::PlanningRequestAdapter);
00218 
00219 /*
00220  * Old plugin declaration for arm navigation trajectory filters
00221  PLUGINLIB_DECLARE_CLASS(industrial_trajectory_filters,
00222  IndustrialNPointFilterJointTrajectoryWithConstraints,
00223  industrial_trajectory_filters::NPointFilter<arm_navigation_msgs::FilterJointTrajectoryWithConstraints>,
00224  filters::FilterBase<arm_navigation_msgs::FilterJointTrajectoryWithConstraints>);
00225 
00226  */
00227 


industrial_trajectory_filters
Author(s): Shaun Edwards , Jorge Nicho
autogenerated on Sat Jun 8 2019 20:43:16