cartesian_twist.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *  Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2014, Fetch Robotics Inc.
00005  *  Copyright (c) 2013, Unbounded Robotics Inc.
00006  *  Copyright (c) 2008, Willow Garage, Inc.
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Unbounded Robotics nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *********************************************************************/
00036 
00037 /*
00038  * Derived a bit from pr2_controllers/cartesian_pose_controller.cpp
00039  * Author: Michael Ferguson, Wim Meeussen, Hanjun Song
00040  */
00041 
00042 #include <pluginlib/class_list_macros.h>
00043 #include <robot_controllers/cartesian_twist.h>
00044 
00045 #include <urdf/model.h>
00046 #include <kdl_parser/kdl_parser.hpp>
00047 
00048 #include <tf_conversions/tf_kdl.h>
00049 
00050 PLUGINLIB_EXPORT_CLASS(robot_controllers::CartesianTwistController, robot_controllers::Controller)
00051 
00052 namespace robot_controllers
00053 {
00054 CartesianTwistController::CartesianTwistController() :
00055   initialized_(false),
00056   is_active_(false)
00057 {
00058 }
00059 
00060 int CartesianTwistController::init(ros::NodeHandle& nh, ControllerManager* manager)
00061 {
00062   // We absolutely need access to the controller manager
00063   if (!manager)
00064   {
00065     initialized_ = false;
00066     return -1;
00067   }
00068 
00069   Controller::init(nh, manager);
00070   manager_ = manager;
00071 
00072   // Initialize KDL structures
00073   std::string tip_link, root_link;
00074   nh.param<std::string>("root_name", root_link, "torso_lift_link");
00075   nh.param<std::string>("tip_name", tip_link, "wrist_roll_link");
00076 
00077   // Load URDF
00078   urdf::Model model;
00079   if (!model.initParam("robot_description"))
00080   {
00081     ROS_ERROR("Failed to parse URDF");
00082     return -1;
00083   }
00084 
00085   // Load the tree
00086   KDL::Tree kdl_tree;
00087   if (!kdl_parser::treeFromUrdfModel(model, kdl_tree))
00088   {
00089     ROS_ERROR("Could not construct tree from URDF");
00090     return -1;
00091   }
00092 
00093   // Populate the Chain
00094   if (!kdl_tree.getChain(root_link, tip_link, kdl_chain_))
00095   {
00096     ROS_ERROR("Could not construct chain from URDF");
00097     return -1;
00098   }
00099 
00100   solver_.reset(new KDL::ChainIkSolverVel_wdls(kdl_chain_));
00101   fksolver_.reset(new KDL::ChainFkSolverPos_recursive(kdl_chain_));
00102   unsigned num_joints = kdl_chain_.getNrOfJoints();
00103   tgt_jnt_pos_.resize(num_joints);
00104   tgt_jnt_vel_.resize(num_joints);
00105   last_tgt_jnt_vel_.resize(num_joints);
00106 
00107   // Init Joint Handles
00108   joints_.clear();
00109   for (size_t i = 0; i < kdl_chain_.getNrOfSegments(); ++i)
00110     if (kdl_chain_.getSegment(i).getJoint().getType() != KDL::Joint::None)
00111       joints_.push_back(manager_->getJointHandle(kdl_chain_.getSegment(i).getJoint().getName()));
00112 
00113   if (joints_.size() != num_joints)
00114   {
00115     ROS_ERROR("Inconsistant joint count %d, %d", num_joints, int(joints_.size()));
00116     return -1;
00117   }
00118 
00119   for (unsigned ii = 0; ii < num_joints; ++ii)
00120   {
00121     last_tgt_jnt_vel_(ii) = 0.0;
00122   }
00123 
00124   // Subscribe to command
00125   command_sub_ = nh.subscribe<geometry_msgs::TwistStamped>("command", 1,
00126                     boost::bind(&CartesianTwistController::command, this, _1));
00127   last_command_time_ = ros::Time(0);
00128 
00129   initialized_ = true;
00130   return 0;
00131 }
00132 
00133 bool CartesianTwistController::start()
00134 {
00135   if (!initialized_)
00136   {
00137     ROS_ERROR_NAMED("CartesianTwistController",
00138                     "Unable to start, not initialized.");
00139     is_active_ = false;
00140     return false;
00141   }
00142 
00143   for (unsigned ii = 0; ii < joints_.size(); ++ii)
00144   {
00145     last_tgt_jnt_vel_(ii) = joints_[ii]->getVelocity();
00146     tgt_jnt_pos_(ii) = joints_[ii]->getPosition();
00147   }
00148   is_active_ = true;
00149   return true;
00150 }
00151 
00152 bool CartesianTwistController::stop(bool force)
00153 {
00154   is_active_ = false;
00155   return true;
00156 }
00157 
00158 bool CartesianTwistController::reset()
00159 {
00160   // Simply stop
00161   return (manager_->requestStop(getName()) == 0);
00162 }
00163 
00164 void CartesianTwistController::update(const ros::Time& now, const ros::Duration& dt)
00165 {
00166   // Need to initialize KDL structs
00167   if (!initialized_)
00168     return;  // Should never really hit this
00169 
00170   KDL::Frame cart_pose;
00171   // Copy desired twist and update time to local var to reduce lock contention
00172   KDL::Twist twist;
00173   ros::Time last_command_time;
00174   {
00175     boost::mutex::scoped_lock lock(mutex_);
00176     // FK is used to transform the twist command seen from end-effector frame to the one seen from body frame.
00177     if (fksolver_->JntToCart(tgt_jnt_pos_, cart_pose) < 0)
00178     {
00179       twist.Zero();
00180       ROS_ERROR_THROTTLE(1.0, "FKsolver solver failed");
00181     }
00182     else
00183     {
00184       if (twist_command_frame_ == "end_effector_frame")
00185       {
00186         twist = cart_pose.M*twist_command_;
00187       }
00188       else
00189       {
00190         twist = twist_command_;
00191       }
00192     }
00193     last_command_time = last_command_time_;
00194   }
00195 
00196   unsigned num_joints = joints_.size();
00197 
00198   if ((now - last_command_time) > ros::Duration(0.5))
00199   {
00200     manager_->requestStop(getName());
00201   }
00202 
00203   // change the twist here
00204   if (solver_->CartToJnt(tgt_jnt_pos_, twist, tgt_jnt_vel_) < 0)
00205   {
00206     for (unsigned ii = 0; ii < num_joints; ++ii)
00207     {
00208       tgt_jnt_vel_(ii) = 0.0;
00209     }
00210   }
00211 
00212   // Limit joint velocities by scaling all target velocities equally so resulting movement is in same direction
00213   double max_vel = 0.0;
00214   for (unsigned ii = 0; ii < num_joints; ++ii)
00215   {
00216     max_vel = std::max(std::abs(tgt_jnt_vel_(ii)), max_vel);
00217   }
00218 
00219   double joint_velocity_limit = 0.5;
00220   double scale = 1.0;
00221   if (max_vel > joint_velocity_limit)
00222   {
00223     double scale = joint_velocity_limit / max_vel;
00224     for (unsigned ii = 0; ii < num_joints; ++ii)
00225     {
00226       tgt_jnt_vel_(ii) *= scale;
00227     }
00228     ROS_DEBUG_THROTTLE(1.0, "Joint velocity limit reached.");
00229   }
00230 
00231   // Make sure solver didn't generate any NaNs. 
00232   for (unsigned ii = 0; ii < num_joints; ++ii)
00233   {
00234     if (!std::isfinite(tgt_jnt_vel_(ii)))
00235     {
00236       ROS_ERROR_THROTTLE(1.0, "Target joint velocity (%d) is not finite : %f", ii, tgt_jnt_vel_(ii));
00237       tgt_jnt_vel_(ii) = 1.0;
00238     }
00239   }
00240 
00241   // Limit accelerations while trying to keep same resulting direction
00242   // somewhere between previous and current value
00243   scale = 1.0;
00244   double accel_limit = 1.0;
00245   double vel_delta_limit = accel_limit * dt.toSec();
00246   for (unsigned ii = 0; ii < num_joints; ++ii)
00247   {
00248     double vel_delta = std::abs(tgt_jnt_vel_(ii) - last_tgt_jnt_vel_(ii));
00249     if (vel_delta > vel_delta_limit)
00250     {
00251       scale = std::min(scale, vel_delta_limit/vel_delta);
00252     }
00253   }
00254 
00255   if (scale <= 0.0)
00256   {
00257     ROS_ERROR_THROTTLE(1.0, "CartesianTwistController: acceleration limit produces non-positive scale %f", scale);
00258     scale = 0.0;
00259   }
00260 
00261   // Linear interpolate betwen previous velocity and new target velocity using scale.
00262   // scale = 1.0  final velocity = new target velocity
00263   // scale = 0.0  final velocity = previous velocity
00264   for (unsigned ii = 0; ii < num_joints; ++ii)
00265   {
00266     tgt_jnt_vel_(ii) = (tgt_jnt_vel_(ii) - last_tgt_jnt_vel_(ii))*scale + last_tgt_jnt_vel_(ii);
00267   }
00268 
00269   // Calculate new target position of joint.  Put target position a few timesteps into the future
00270   double dt_sec = dt.toSec();
00271   for (unsigned ii = 0; ii < num_joints; ++ii)
00272   {
00273     tgt_jnt_pos_(ii) += tgt_jnt_vel_(ii) * dt_sec;
00274   }
00275 
00276   // Limit target position of joint
00277   for (unsigned ii = 0; ii < num_joints; ++ii)
00278   {
00279     if (!joints_[ii]->isContinuous())
00280     {
00281       if (tgt_jnt_pos_(ii) > joints_[ii]->getPositionMax())
00282       {
00283         tgt_jnt_pos_(ii) = joints_[ii]->getPositionMax();
00284       }
00285       else if (tgt_jnt_pos_(ii) < joints_[ii]->getPositionMin())
00286       {
00287         tgt_jnt_pos_(ii) = joints_[ii]->getPositionMin();
00288       }  
00289     }
00290   }
00291 
00292 
00293   for (size_t ii = 0; ii < joints_.size(); ++ii)
00294   {
00295     joints_[ii]->setPosition(tgt_jnt_pos_(ii), tgt_jnt_vel_(ii), 0.0);
00296     last_tgt_jnt_vel_(ii) = tgt_jnt_vel_(ii);
00297   }
00298 }
00299 
00300 void CartesianTwistController::command(const geometry_msgs::TwistStamped::ConstPtr& goal)
00301 {
00302   // Need to initialize KDL structs
00303   if (!initialized_)
00304   {
00305     ROS_ERROR("CartesianTwistController: Cannot accept goal, controller is not initialized.");
00306     return;
00307   }
00308 
00309   if (goal->header.frame_id.empty())
00310   {
00311     manager_->requestStop(getName());
00312     return;
00313   }
00314 
00315   KDL::Twist twist;
00316   twist(0) = goal->twist.linear.x;
00317   twist(1) = goal->twist.linear.y;
00318   twist(2) = goal->twist.linear.z;
00319   twist(3) = goal->twist.angular.x;
00320   twist(4) = goal->twist.angular.y;
00321   twist(5) = goal->twist.angular.z;
00322 
00323   for (int ii=0; ii<6; ++ii)
00324   {
00325     if (!std::isfinite(twist(ii)))
00326     {
00327       ROS_ERROR_THROTTLE(1.0, "Twist command value (%d) is not finite : %f", ii, twist(ii));
00328       twist(ii) = 0.0;
00329     }
00330   }
00331 
00332   ros::Time now(ros::Time::now());
00333 
00334   {
00335     boost::mutex::scoped_lock lock(mutex_);
00336     twist_command_frame_ = goal->header.frame_id;
00337     twist_command_ = twist;
00338     last_command_time_ = now;
00339   }
00340   // Try to start up
00341   if (!is_active_ && manager_->requestStart(getName()) != 0)
00342   {
00343     ROS_ERROR("CartesianTwistController: Cannot start, blocked by another controller.");
00344     return;
00345   }
00346 }
00347 
00348 std::vector<std::string> CartesianTwistController::getCommandedNames()
00349 {
00350   std::vector<std::string> names;
00351   if (initialized_)
00352   {
00353     for (size_t i = 0; i < kdl_chain_.getNrOfSegments(); ++i)
00354       if (kdl_chain_.getSegment(i).getJoint().getType() != KDL::Joint::None)
00355         names.push_back(kdl_chain_.getSegment(i).getJoint().getName());
00356   }
00357   return names;
00358 }
00359 
00360 std::vector<std::string> CartesianTwistController::getClaimedNames()
00361 {
00362   return getCommandedNames();
00363 }
00364 
00365 }  // namespace robot_controllers


robot_controllers
Author(s): Michael Ferguson
autogenerated on Wed Jun 14 2017 04:09:10