trajectory_execution_monitor.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2011, Willow Garage, Inc.
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
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00037 #include <trajectory_execution_monitor/trajectory_execution_monitor.h>
00038 #include <trajectory_execution_monitor/trajectory_stats.h>
00039 
00040 using namespace trajectory_execution_monitor;
00041 
00042 TrajectoryExecutionRequest::TrajectoryExecutionRequest() :
00043   monitor_overshoot_(false),
00044   max_overshoot_velocity_epsilon_(20),
00045   min_overshoot_time_(ros::Duration(0.5)),
00046   max_overshoot_time_(ros::Duration(0.01)),
00047   failure_ok_(false),
00048   test_for_close_enough_(false),
00049   max_joint_distance_(0.01),
00050   failure_time_factor_(1.5)
00051 {}
00052 
00053 void TrajectoryExecutionMonitor::addTrajectoryRecorder(boost::shared_ptr<TrajectoryRecorder>& trajectory_recorder) {
00054   trajectory_recorder_map_[trajectory_recorder->getName()] = trajectory_recorder;
00055 }
00056 
00057 void TrajectoryExecutionMonitor::addTrajectoryControllerHandler(boost::shared_ptr<TrajectoryControllerHandler>& trajectory_controller_handler) {
00058   trajectory_controller_handler_map_[trajectory_controller_handler->getGroupControllerComboName()] = 
00059     trajectory_controller_handler;
00060 }
00061 
00062 void TrajectoryExecutionMonitor::executeTrajectories(const std::vector<TrajectoryExecutionRequest>& to_execute,
00063                                                      const boost::function<bool(TrajectoryExecutionDataVector)>& done_callback) {
00064   
00065   execution_data_ = &to_execute;
00066   execution_result_vector_.reset();
00067   result_callback_ = done_callback;
00068   
00069   current_trajectory_index_ = 0;
00070   
00071   if(!sendTrajectory((*execution_data_)[current_trajectory_index_])) {
00072     result_callback_(execution_result_vector_);
00073   }
00074 };
00075 
00076 bool TrajectoryExecutionMonitor::sendTrajectory(const TrajectoryExecutionRequest& ter) {
00077   
00078   execution_result_vector_.resize(execution_result_vector_.size()+1);
00079   
00080   std::string recorder_name = ter.recorder_name_;
00081   if(trajectory_recorder_map_.size() == 1) {
00082     recorder_name = trajectory_recorder_map_.begin()->second->getName();
00083   }
00084      
00085   if(trajectory_recorder_map_.find(ter.recorder_name_) == trajectory_recorder_map_.end() && 
00086      trajectory_recorder_map_.size() > 1) {
00087     execution_result_vector_.back().result_ = NO_RECORDER;
00088     return false;
00089   } 
00090   
00091   std::string combo_name = TrajectoryControllerHandler::combineGroupAndControllerNames(ter.group_name_,
00092                                                                                        ter.controller_name_);
00093   
00094   if(trajectory_controller_handler_map_.find(combo_name) == trajectory_controller_handler_map_.end()) {
00095     execution_result_vector_.back().result_ = NO_HANDLER;
00096     return false;
00097   }
00098   
00099   boost::shared_ptr<TrajectoryRecorder>& requested_recorder = trajectory_recorder_map_.find(recorder_name)->second;
00100   last_requested_handler_ = trajectory_controller_handler_map_.find(combo_name)->second;
00101 
00102   // Enable overshoot, if required
00103   if(ter.monitor_overshoot_)
00104   {
00105     last_requested_handler_->enableOvershoot(ter.max_overshoot_velocity_epsilon_, ter.min_overshoot_time_, ter.max_overshoot_time_);
00106   }
00107   else
00108   {
00109     last_requested_handler_->disableOvershoot();
00110   }
00111 
00112   // Set the max execution time
00113   trajectory_msgs::JointTrajectory traj = ter.trajectory_;
00114   ros::Duration traj_dur = TrajectoryStats::getDuration(traj);
00115   if( traj_dur > ros::Duration(0.1) )
00116   {
00117     last_requested_handler_->setMaximumExecutionTime(traj_dur * ter.failure_time_factor_);
00118   }
00119 
00120   traj.header.stamp = ros::Time::now();
00121   if(!last_requested_handler_->executeTrajectory(
00122         traj,
00123         requested_recorder,
00124         boost::bind(&TrajectoryExecutionMonitor::trajectoryFinishedCallbackFunction, this, _1))
00125   )
00126   {
00127     execution_result_vector_.back().result_ = HANDLER_FAILED_ENTIRELY;
00128   }
00129   return true;
00130 }
00131 
00132 void TrajectoryExecutionMonitor::trajectoryFinishedCallbackFunction(
00133         TrajectoryControllerState controller_state )
00134 {
00135   //adding this in any case
00136   execution_result_vector_.back().recorded_trajectory_ = last_requested_handler_->getLastRecordedTrajectory();
00137   execution_result_vector_.back().overshoot_trajectory_ = last_requested_handler_->getLastOvershootTrajectory();
00138 
00139   const TrajectoryExecutionRequest& req = (*execution_data_)[current_trajectory_index_];
00140   bool ok = (   controller_state==TrajectoryControllerStates::SUCCESS ||
00141               controller_state==TrajectoryControllerStates::OVERSHOOT_TIMEOUT);
00142   bool continue_execution =
00143             ok ||
00144             req.failure_ok_ ||
00145             (   req.test_for_close_enough_ && closeEnough(req,execution_result_vector_.back()));
00146 
00147   if(   continue_execution )
00148   {
00149     ROS_INFO_STREAM("Trajectory finished");
00150 
00151     // calculate stats
00152     TrajectoryExecutionData & data = execution_result_vector_.back();
00153     data.time_ = TrajectoryStats::getDuration(data.recorded_trajectory_);
00154     data.overshoot_time_ = TrajectoryStats::getDuration(data.overshoot_trajectory_);
00155     data.angular_distance_ = TrajectoryStats::getAngularDistance(data.recorded_trajectory_);
00156 
00157     if(!ok) {
00158       if(req.failure_ok_) {
00159         execution_result_vector_.back().result_ = HANDLER_REPORTS_FAILURE_BUT_OK;
00160       } else {
00161         execution_result_vector_.back().result_ = HANDLER_REPORTS_FAILURE_BUT_CLOSE_ENOUGH;
00162       }
00163     } else {
00164       execution_result_vector_.back().result_ = SUCCEEDED;
00165     }
00166     if(req.callback_function_) {
00167       req.callback_function_(req.group_name_);
00168     }
00169 
00170     current_trajectory_index_++;
00171     if(current_trajectory_index_ >= execution_data_->size()) {
00172       result_callback_(execution_result_vector_);
00173       return;
00174     }
00175     for(int i = (int)current_trajectory_index_-1; i >= 0; i--) {
00176       if((*execution_data_)[i].group_name_ == (*execution_data_)[current_trajectory_index_].group_name_) {
00177         ROS_INFO_STREAM("Last index is " << i << " current is " << current_trajectory_index_);
00178         compareLastRecordedToStart((*execution_data_)[i],
00179                                    (*execution_data_)[current_trajectory_index_],
00180                                    execution_result_vector_[i]);
00181         break;
00182       }
00183     }
00184 
00185     // Start next trajectory
00186     if(!sendTrajectory((*execution_data_)[current_trajectory_index_])) {
00187       result_callback_(execution_result_vector_);
00188     }
00189   } else {
00190     ROS_ERROR_STREAM( "Trajectory finished with failure.  controller_state=" << controller_state <<
00191                       ". Stopping the remaining trajectories" << std::endl );
00192     execution_result_vector_.back().result_ = HANDLER_REPORTS_FAILURE;
00193     result_callback_(execution_result_vector_);
00194   }
00195 };
00196 
00197 bool TrajectoryExecutionMonitor::closeEnough(const TrajectoryExecutionRequest& ter,
00198                                              const TrajectoryExecutionData& ted) {
00199   if(ted.recorded_trajectory_.points.size() == 0) {
00200     ROS_WARN_STREAM("No points in recorded trajectory");
00201     return false;
00202   }
00203   ROS_WARN_STREAM("Comparing trajectories trajectory");
00204   double total_distance = TrajectoryStats::distance(ter.trajectory_.points.back(),ted.recorded_trajectory_.points.back());
00205   if(total_distance < ter.max_joint_distance_) {
00206     ROS_INFO_STREAM("Allowing because max distance low " << total_distance);
00207     return true;
00208   }
00209   for(unsigned int i = 0; i < ter.trajectory_.points.back().positions.size(); i++) {
00210     ROS_INFO_STREAM("Distance for " << ter.trajectory_.joint_names[i] << " is " << fabs(ter.trajectory_.points.back().positions[i]-ted.recorded_trajectory_.points.back().positions[i]));
00211   }
00212 
00213   ROS_INFO_STREAM("Not allowing because max distance high " << total_distance);
00214   return false;
00215 }
00216 
00217 void TrajectoryExecutionMonitor::compareLastRecordedToStart(const TrajectoryExecutionRequest& last_ter,
00218                                                             const TrajectoryExecutionRequest& next_ter,
00219                                                             const TrajectoryExecutionData& ted)
00220 {
00221   if(ted.recorded_trajectory_.points.size() == 0) {
00222     ROS_WARN_STREAM("No points in recorded trajectory for comparison");
00223     return;
00224   }
00225 
00226   planning_models::KinematicState last_recorded_state(cm_.getKinematicModel());
00227   planning_models::KinematicState last_requested_state(cm_.getKinematicModel());
00228   planning_models::KinematicState next_requested_state(cm_.getKinematicModel());
00229   
00230   last_recorded_state.setKinematicStateToDefault();
00231   last_requested_state.setKinematicStateToDefault();
00232   next_requested_state.setKinematicStateToDefault();
00233 
00234   std::map<std::string, double> last_recorded_values;
00235   for(unsigned int i = 0; i < ted.recorded_trajectory_.points.back().positions.size(); i++) {
00236     ROS_INFO_STREAM("Last recorded " << ted.recorded_trajectory_.joint_names[i] << " value " << ted.recorded_trajectory_.points.back().positions[i]);
00237     last_recorded_values[ted.recorded_trajectory_.joint_names[i]] = ted.recorded_trajectory_.points.back().positions[i];
00238   }
00239   
00240   std::map<std::string, double> last_requested_values;
00241   for(unsigned int i = 0; i < last_ter.trajectory_.points.front().positions.size(); i++) {
00242     ROS_INFO_STREAM("Last requested " << last_ter.trajectory_.joint_names[i] << " value " << last_ter.trajectory_.points.back().positions[i]);
00243     last_requested_values[last_ter.trajectory_.joint_names[i]] = last_ter.trajectory_.points.back().positions[i];
00244   }
00245 
00246   std::map<std::string, double> next_requested_values;
00247   for(unsigned int i = 0; i < next_ter.trajectory_.points.front().positions.size(); i++) {
00248     ROS_INFO_STREAM("Next requested " << next_ter.trajectory_.joint_names[i] << " value " << next_ter.trajectory_.points.front().positions[i]);
00249     next_requested_values[next_ter.trajectory_.joint_names[i]] = next_ter.trajectory_.points.front().positions[i];
00250   }
00251 
00252   last_recorded_state.setKinematicState(last_recorded_values);
00253   last_requested_state.setKinematicState(last_requested_values);
00254   next_requested_state.setKinematicState(next_requested_values);
00255 
00256   tf::Transform recorded_pose = last_recorded_state.getLinkState("r_wrist_roll_link")->getGlobalLinkTransform();
00257   tf::Transform last_requested_pose = last_requested_state.getLinkState("r_wrist_roll_link")->getGlobalLinkTransform();
00258   tf::Transform next_requested_pose = next_requested_state.getLinkState("r_wrist_roll_link")->getGlobalLinkTransform();
00259 
00260   ROS_INFO_STREAM("Diff in last requested versus recorded is "  
00261                   << fabs(recorded_pose.getOrigin().x()-last_requested_pose.getOrigin().x()) << " "
00262                   << fabs(recorded_pose.getOrigin().y()-last_requested_pose.getOrigin().y()) << " "
00263                   << fabs(recorded_pose.getOrigin().z()-last_requested_pose.getOrigin().z()));
00264 
00265   ROS_INFO_STREAM("Diff is last requested versus next requested " 
00266                   << fabs(last_requested_pose.getOrigin().x()-next_requested_pose.getOrigin().x()) << " " 
00267                   << fabs(last_requested_pose.getOrigin().y()-next_requested_pose.getOrigin().y()) << " " 
00268                   << fabs(last_requested_pose.getOrigin().z()-next_requested_pose.getOrigin().z())); 
00269 
00270   ROS_INFO_STREAM("Diff is last recorded versus next requested " 
00271                   << fabs(recorded_pose.getOrigin().x()-next_requested_pose.getOrigin().x()) << " " 
00272                   << fabs(recorded_pose.getOrigin().y()-next_requested_pose.getOrigin().y()) << " " 
00273                   << fabs(recorded_pose.getOrigin().z()-next_requested_pose.getOrigin().z())); 
00274 }


trajectory_execution_monitor
Author(s): Gil Jones
autogenerated on Fri Dec 6 2013 21:09:24