current_state_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 
00035 /* Author: Ioan Sucan */
00036 
00037 #include <moveit/planning_scene_monitor/current_state_monitor.h>
00038 #include <tf_conversions/tf_eigen.h>
00039 #include <limits>
00040 
00041 planning_scene_monitor::CurrentStateMonitor::CurrentStateMonitor(const robot_model::RobotModelConstPtr &kmodel, const boost::shared_ptr<tf::Transformer> &tf) :
00042   tf_(tf), kmodel_(kmodel), kstate_(kmodel), root_(kstate_.getJointState(kmodel->getRoot()->getName())), state_monitor_started_(false), error_(std::numeric_limits<float>::epsilon())
00043 {
00044   kstate_.setToDefaultValues();
00045 }
00046 
00047 planning_scene_monitor::CurrentStateMonitor::~CurrentStateMonitor()
00048 {
00049   stopStateMonitor();
00050 }
00051 
00052 robot_state::RobotStatePtr planning_scene_monitor::CurrentStateMonitor::getCurrentState() const
00053 {
00054   boost::mutex::scoped_lock slock(state_update_lock_);
00055   robot_state::RobotState *result = new robot_state::RobotState(kstate_);
00056   return robot_state::RobotStatePtr(result);
00057 }
00058 
00059 ros::Time planning_scene_monitor::CurrentStateMonitor::getCurrentStateTime() const
00060 {
00061   boost::mutex::scoped_lock slock(state_update_lock_);
00062   return current_state_time_;
00063 }
00064 
00065 std::pair<robot_state::RobotStatePtr, ros::Time> planning_scene_monitor::CurrentStateMonitor::getCurrentStateAndTime() const
00066 {
00067   boost::mutex::scoped_lock slock(state_update_lock_);
00068   robot_state::RobotState *result = new robot_state::RobotState(kstate_);
00069   return std::make_pair(robot_state::RobotStatePtr(result), current_state_time_);
00070 }
00071 
00072 std::map<std::string, double> planning_scene_monitor::CurrentStateMonitor::getCurrentStateValues() const
00073 {
00074   std::map<std::string, double> m;
00075   boost::mutex::scoped_lock slock(state_update_lock_);
00076   kstate_.getStateValues(m);
00077   return m;
00078 }
00079 
00080 void planning_scene_monitor::CurrentStateMonitor::addUpdateCallback(const JointStateUpdateCallback &fn)
00081 {
00082   if (fn)
00083     update_callbacks_.push_back(fn);
00084 }
00085 
00086 void planning_scene_monitor::CurrentStateMonitor::clearUpdateCallbacks()
00087 {
00088   update_callbacks_.clear();
00089 }
00090 
00091 void planning_scene_monitor::CurrentStateMonitor::startStateMonitor(const std::string &joint_states_topic)
00092 {
00093   if (!state_monitor_started_ && kmodel_)
00094   {
00095     joint_time_.clear();
00096     if (joint_states_topic.empty())
00097       ROS_ERROR("The joint states topic cannot be an empty string");
00098     else
00099       joint_state_subscriber_ = nh_.subscribe(joint_states_topic, 25, &CurrentStateMonitor::jointStateCallback, this);
00100     state_monitor_started_ = true;
00101     monitor_start_time_ = ros::Time::now();
00102     ROS_DEBUG("Listening to joint states on topic '%s'", joint_states_topic.c_str());
00103   }
00104 }
00105 
00106 bool planning_scene_monitor::CurrentStateMonitor::isActive() const
00107 {
00108   return state_monitor_started_;
00109 }
00110 
00111 void planning_scene_monitor::CurrentStateMonitor::stopStateMonitor()
00112 {
00113   if (state_monitor_started_)
00114   {
00115     joint_state_subscriber_.shutdown();
00116     ROS_DEBUG("No longer listening o joint states");
00117     state_monitor_started_ = false;
00118   }
00119 }
00120 
00121 std::string planning_scene_monitor::CurrentStateMonitor::getMonitoredTopic() const
00122 {
00123   if (joint_state_subscriber_)
00124     return joint_state_subscriber_.getTopic();
00125   else
00126     return "";
00127 }
00128 
00129 bool planning_scene_monitor::CurrentStateMonitor::isPassiveDOF(const std::string &dof) const
00130 {
00131   if (kmodel_->hasJointModel(dof))
00132   {
00133     if (kmodel_->getJointModel(dof)->isPassive())
00134       return true;
00135   }
00136   else
00137   {
00138     // check if this DOF is part of a multi-dof passive joint
00139     std::size_t slash = dof.find_last_of("/");
00140     if (slash != std::string::npos)
00141     {
00142       std::string joint_name = dof.substr(0, slash);
00143       if (kmodel_->hasJointModel(joint_name))
00144         if (kmodel_->getJointModel(joint_name)->isPassive())
00145           return true;
00146     }
00147   }
00148   return false;
00149 }
00150 
00151 bool planning_scene_monitor::CurrentStateMonitor::haveCompleteState() const
00152 {
00153   bool result = true;
00154   const std::vector<std::string> &dof = kmodel_->getVariableNames();
00155   boost::mutex::scoped_lock slock(state_update_lock_);
00156   for (std::size_t i = 0 ; i < dof.size() ; ++i)
00157     if (joint_time_.find(dof[i]) == joint_time_.end())
00158     {
00159       if (!isPassiveDOF(dof[i]))
00160       {
00161         ROS_DEBUG("Joint variable '%s' has never been updated", dof[i].c_str());
00162         result = false;
00163       }
00164     }
00165   return result;
00166 }
00167 
00168 bool planning_scene_monitor::CurrentStateMonitor::haveCompleteState(std::vector<std::string> &missing_states) const
00169 {
00170   bool result = true;
00171   const std::vector<std::string> &dof = kmodel_->getVariableNames();
00172   boost::mutex::scoped_lock slock(state_update_lock_);
00173   for (std::size_t i = 0 ; i < dof.size() ; ++i)
00174     if (joint_time_.find(dof[i]) == joint_time_.end())
00175       if (!isPassiveDOF(dof[i]))
00176       {
00177         ROS_DEBUG("Joint variable '%s' has never been updated", dof[i].c_str());
00178         missing_states.push_back(dof[i]);
00179         result = false;
00180       }
00181   return result;
00182 }
00183 
00184 bool planning_scene_monitor::CurrentStateMonitor::haveCompleteState(const ros::Duration &age) const
00185 {
00186   bool result = true;
00187   const std::vector<std::string> &dof = kmodel_->getVariableNames();
00188   ros::Time now = ros::Time::now();
00189   ros::Time old = now - age;
00190   boost::mutex::scoped_lock slock(state_update_lock_);
00191   for (std::size_t i = 0 ; i < dof.size() ; ++i)
00192   {
00193     if (isPassiveDOF(dof[i]))
00194       continue;
00195     std::map<std::string, ros::Time>::const_iterator it = joint_time_.find(dof[i]);
00196     if (it == joint_time_.end())
00197     {
00198       ROS_DEBUG("Joint variable '%s' has never been updated", dof[i].c_str());
00199       result = false;
00200     }
00201     else
00202       if (it->second < old)
00203       {
00204         ROS_DEBUG("Joint variable '%s' was last updated %0.3lf seconds ago (older than the allowed %0.3lf seconds)",
00205                   dof[i].c_str(), (now - it->second).toSec(), age.toSec());
00206         result = false;
00207       }
00208   }
00209   return result;
00210 }
00211 
00212 bool planning_scene_monitor::CurrentStateMonitor::haveCompleteState(const ros::Duration &age,
00213                                                                     std::vector<std::string> &missing_states) const
00214 {
00215   bool result = true;
00216   const std::vector<std::string> &dof = kmodel_->getVariableNames();
00217   ros::Time now = ros::Time::now();
00218   ros::Time old = now - age;
00219   boost::mutex::scoped_lock slock(state_update_lock_);
00220   for (std::size_t i = 0 ; i < dof.size() ; ++i)
00221   {
00222     if (isPassiveDOF(dof[i]))
00223       continue;
00224     std::map<std::string, ros::Time>::const_iterator it = joint_time_.find(dof[i]);
00225     if (it == joint_time_.end())
00226     {
00227       ROS_DEBUG("Joint variable '%s' has never been updated", dof[i].c_str());
00228       missing_states.push_back(dof[i]);
00229       result = false;
00230     }
00231     else
00232       if (it->second < old)
00233       {
00234         ROS_DEBUG("Joint variable '%s' was last updated %0.3lf seconds ago (older than the allowed %0.3lf seconds)",
00235                   dof[i].c_str(), (now - it->second).toSec(), age.toSec());
00236         missing_states.push_back(dof[i]);
00237         result = false;
00238       }
00239   }
00240   return result;
00241 }
00242 
00243 bool planning_scene_monitor::CurrentStateMonitor::waitForCurrentState(double wait_time) const
00244 {
00245   double slept_time = 0.0;
00246   double sleep_step_s = std::min(0.05, wait_time / 10.0);
00247   ros::Duration sleep_step(sleep_step_s);
00248   while (!haveCompleteState() && slept_time < wait_time)
00249   {
00250     sleep_step.sleep();
00251     slept_time += sleep_step_s;
00252   }
00253   return haveCompleteState();
00254 }
00255 
00256 bool planning_scene_monitor::CurrentStateMonitor::waitForCurrentState(const std::string &group, double wait_time) const
00257 {
00258   if (waitForCurrentState(wait_time))
00259     return true;
00260   bool ok = true;
00261 
00262   // check to see if we have a fully known state for the joints we want to record
00263   std::vector<std::string> missing_joints;
00264   if (!haveCompleteState(missing_joints))
00265   {
00266     const robot_model::JointModelGroup *jmg = kmodel_->getJointModelGroup(group);
00267     if (jmg)
00268     {
00269       std::set<std::string> mj;
00270       mj.insert(missing_joints.begin(), missing_joints.end());
00271       const std::vector<std::string> &names= jmg->getJointModelNames();
00272       bool ok = true;
00273       for (std::size_t i = 0 ; ok && i < names.size() ; ++i)
00274         if (mj.find(names[i]) != mj.end())
00275           ok = false;
00276     }
00277     else
00278       ok = false;
00279   }
00280   return ok;
00281 }
00282 
00283 void planning_scene_monitor::CurrentStateMonitor::jointStateCallback(const sensor_msgs::JointStateConstPtr &joint_state)
00284 {
00285   if (joint_state->name.size() != joint_state->position.size())
00286   {
00287     ROS_ERROR_THROTTLE(1, "State monitor received invalid joint state");
00288     return;
00289   }
00290 
00291   // read the received values, and update their time stamps
00292   std::size_t n = joint_state->name.size();
00293   std::map<std::string, double> joint_state_map;
00294   const std::map<std::string, std::pair<double, double> > &bounds = kmodel_->getAllVariableBounds();
00295   for (std::size_t i = 0 ; i < n ; ++i)
00296   {
00297     joint_state_map[joint_state->name[i]] = joint_state->position[i];
00298     joint_time_[joint_state->name[i]] = joint_state->header.stamp;
00299 
00300     // continuous joints wrap, so we don't modify them (even if they are outside bounds!)
00301     const robot_model::JointModel* jm = kmodel_->getJointModel(joint_state->name[i]);
00302     if (jm && jm->getType() == robot_model::JointModel::REVOLUTE)
00303       if (static_cast<const robot_model::RevoluteJointModel*>(jm)->isContinuous())
00304         continue;
00305 
00306     std::map<std::string, std::pair<double, double> >::const_iterator bi = bounds.find(joint_state->name[i]);
00307     // if the read variable is 'almost' within bounds (up to error_ difference), then consider it to be within bounds
00308     if (bi != bounds.end())
00309     {
00310       if (joint_state->position[i] < bi->second.first && joint_state->position[i] >= bi->second.first - error_)
00311         joint_state_map[joint_state->name[i]] = bi->second.first;
00312       else
00313         if (joint_state->position[i] > bi->second.second && joint_state->position[i] <= bi->second.second + error_)
00314           joint_state_map[joint_state->name[i]] = bi->second.second;
00315     }
00316   }
00317   bool set_map_values = true;
00318 
00319   // read root transform, if needed
00320   if (tf_ && (root_->getType() == robot_model::JointModel::PLANAR ||
00321               root_->getType() == robot_model::JointModel::FLOATING))
00322   {
00323     const std::string &child_frame = root_->getJointModel()->getChildLinkModel()->getName();
00324     const std::string &parent_frame = kmodel_->getModelFrame();
00325 
00326     std::string err;
00327     ros::Time tm;
00328     tf::StampedTransform transf;
00329     bool ok = false;
00330     if (tf_->getLatestCommonTime(parent_frame, child_frame, tm, &err) == tf::NO_ERROR)
00331     {
00332       try
00333       {
00334         tf_->lookupTransform(parent_frame, child_frame, tm, transf);
00335         ok = true;
00336       }
00337       catch(tf::TransformException& ex)
00338       {
00339         ROS_ERROR_THROTTLE(1, "Unable to lookup transform from %s to %s.  Exception: %s", parent_frame.c_str(), child_frame.c_str(), ex.what());
00340       }
00341     }
00342     else
00343       ROS_DEBUG_THROTTLE(1, "Unable to lookup transform from %s to %s: no common time.", parent_frame.c_str(), child_frame.c_str());
00344     if (ok)
00345     {
00346       const std::vector<std::string> &vars = root_->getJointModel()->getVariableNames();
00347       for (std::size_t j = 0; j < vars.size() ; ++j)
00348         joint_time_[vars[j]] = tm;
00349       set_map_values = false;
00350       Eigen::Affine3d eigen_transf;
00351       tf::transformTFToEigen(transf, eigen_transf);
00352       boost::mutex::scoped_lock slock(state_update_lock_);
00353       root_->setVariableValues(eigen_transf);
00354       kstate_.setStateValues(joint_state_map);
00355       current_state_time_ = joint_state->header.stamp;
00356     }
00357   }
00358 
00359   if (set_map_values)
00360   {
00361     boost::mutex::scoped_lock slock(state_update_lock_);
00362     kstate_.setStateValues(joint_state_map);
00363     current_state_time_ = joint_state->header.stamp;
00364   }
00365 
00366   // callbacks, if needed
00367   for (std::size_t i = 0 ; i < update_callbacks_.size() ; ++i)
00368     update_callbacks_[i](joint_state);
00369 }


planning
Author(s): Ioan Sucan , Sachin Chitta
autogenerated on Mon Oct 6 2014 02:31:39