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 #include <boost/shared_ptr.hpp>
00036 #include <boost/scoped_ptr.hpp>
00037 
00038 #include <ros/ros.h>
00039 #include <rosrt/rosrt.h>
00040 #include <angles/angles.h>
00041 #include <control_toolbox/pid.h>
00042 #include <eigen_conversions/eigen_kdl.h>
00043 #include <eigen_conversions/eigen_msg.h>
00044 #include <pr2_controller_interface/controller.h>
00045 #include <pr2_mechanism_model/chain.h>
00046 #include <realtime_tools/realtime_publisher.h>
00047 #include <tf/transform_listener.h>
00048 
00049 #include <kdl/chain.hpp>
00050 #include <kdl/chainfksolver.hpp>
00051 #include <kdl/chainjnttojacsolver.hpp>
00052 #include <kdl/chainfksolvervel_recursive.hpp>
00053 
00054 #include <Eigen/Geometry>
00055 #include <Eigen/LU>
00056 #include <Eigen/Core>
00057 
00058 #include <geometry_msgs/TwistStamped.h>
00059 #include <teleop_controllers/JinvTeleopControllerState.h>
00060 
00061 namespace pr2_teleop {
00062 
00063 template <int JOINTS>
00064 class JinvTeleopController : public pr2_controller_interface::Controller
00065 {
00066 public:
00067   
00068   
00069   EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00070 private:
00071   typedef Eigen::Matrix<double, JOINTS, 1> JointVector;
00072   typedef Eigen::Matrix<double, 6, 1> CartVector;
00073   typedef teleop_controllers::JinvTeleopControllerState StateMsg;
00074 public:
00075 
00076   JinvTeleopController();
00077 
00078   ~JinvTeleopController();
00079 
00080   bool init(pr2_mechanism_model::RobotState *r, ros::NodeHandle &n);
00081 
00082   void starting();
00083 
00084   void update();
00085 
00086 private:
00087 
00088   pr2_mechanism_model::RobotState *robot_;
00089 
00090   enum {POSE, TWIST} mode_;
00091 
00092   ros::NodeHandle node_;
00093   ros::Subscriber sub_command_;
00094   ros::Subscriber sub_command_pose_;
00095   ros::Subscriber sub_twist_;
00096   ros::Subscriber sub_posture_;
00097   realtime_tools::RealtimePublisher<geometry_msgs::PoseStamped> pub_x_;
00098   realtime_tools::RealtimePublisher<geometry_msgs::PoseStamped> pub_x_desi_;
00099   realtime_tools::RealtimePublisher<geometry_msgs::TwistStamped> pub_x_err_;
00100   rosrt::Publisher<StateMsg> pub_state_;
00101   ros::Publisher pub_transformed_twist_;
00102   ros::Publisher pub_transformed_rot_vel_;
00103   tf::TransformListener tf_;
00104 
00105   CartVector Kp_x, Kd_x;
00106   JointVector Kp_j, Kd_j, pclamp_j;
00107   double jacobian_inverse_damping_;
00108   double pose_command_filter_;
00109 
00110   ros::Time last_command_time_;
00111   Eigen::Affine3d x_desi_, x_desi_filtered_;
00112   CartVector xd_desi;
00113   double xd_trans_limit_;
00114   double xd_rot_limit_;
00115   JointVector q_proxy_;
00116 
00117   double k_posture_;
00118   bool use_posture_;
00119   JointVector q_posture_;
00120 
00121   ros::Time last_time_;
00122   int loop_count_;
00123 
00124   std::string root_name_;
00125   pr2_mechanism_model::Chain chain_;
00126   KDL::Chain kdl_chain_;
00127   boost::scoped_ptr<KDL::ChainFkSolverVel> fk_solver_;
00128   boost::scoped_ptr<KDL::ChainJntToJacSolver> jac_solver_;
00129 
00130   
00131   JointVector q, qd;
00132   Eigen::Affine3d x;
00133   CartVector xd;
00134   CartVector x_err;
00135   CartVector xd_ref;
00136   JointVector qd_pose;
00137   JointVector tau;
00138 
00139   
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153   void commandPoseCB(const geometry_msgs::PoseStamped::ConstPtr &command)
00154   {
00155     geometry_msgs::PoseStamped in_root;
00156     try {
00157       tf_.waitForTransform(root_name_, command->header.frame_id, command->header.stamp, ros::Duration(0.1));
00158       tf_.transformPose(root_name_, *command, in_root);
00159     }
00160     catch (const tf::TransformException &ex)
00161     {
00162       ROS_ERROR("Failed to transform: %s", ex.what());
00163       return;
00164     }
00165 
00166     tf::poseMsgToEigen(in_root.pose, x_desi_);
00167     xd_desi.setZero();
00168   }
00169 
00170   void commandTwistCB(const geometry_msgs::TwistStamped::ConstPtr &command)
00171   {
00172     tf::StampedTransform transform;
00173     try {
00174       tf_.waitForTransform(root_name_, command->header.frame_id, command->header.stamp,
00175                            ros::Duration(0.1));
00176       tf_.lookupTransform(root_name_, command->header.frame_id, command->header.stamp, transform);
00177     }
00178     catch (const tf::TransformException &ex)
00179     {
00180       ROS_ERROR("Failed to transform: %s", ex.what());
00181       return;
00182     }
00183 
00184     tf::Vector3 vel(command->twist.linear.x, command->twist.linear.y, command->twist.linear.z);
00185     tf::Vector3 rot_vel(command->twist.angular.x, command->twist.angular.y, command->twist.angular.z);
00186 
00187     
00188     
00189     vel = transform.getBasis() * vel;
00190     rot_vel = transform.getBasis() * rot_vel;
00191 
00192     xd_desi[0] = vel[0];
00193     xd_desi[1] = vel[1];
00194     xd_desi[2] = vel[2];
00195     xd_desi[3] = rot_vel[0];
00196     xd_desi[4] = rot_vel[1];
00197     xd_desi[5] = rot_vel[2];
00198 
00199     
00200     
00201 
00202     xd_trans_limit_ = 0.0;
00203     xd_rot_limit_ = 0.0;
00204 
00205     geometry_msgs::TwistStamped msg;
00206     msg.header.stamp = ros::Time::now();
00207     msg.header.frame_id = root_name_;
00208     tf::twistEigenToMsg(xd_desi, msg.twist);
00209     pub_transformed_twist_.publish(msg);
00210     geometry_msgs::Vector3Stamped vm;
00211     vm.header.stamp = ros::Time::now();
00212     vm.header.frame_id = root_name_;
00213     vm.vector.x = rot_vel[0];
00214     vm.vector.y = rot_vel[1];
00215     vm.vector.z = rot_vel[2];
00216     pub_transformed_rot_vel_.publish(vm);
00217 
00218     last_command_time_ = ros::Time::now();
00219     mode_ = TWIST;
00220   }
00221 
00222   void commandPostureCB(const std_msgs::Float64MultiArray::ConstPtr &msg)
00223   {
00224     if (msg->data.size() == 0) {
00225       use_posture_ = false;
00226       ROS_INFO("Posture turned off");
00227     }
00228     else if ((int)msg->data.size() != JOINTS) {
00229       ROS_ERROR("Posture message had the wrong size: %d", (int)msg->data.size());
00230       return;
00231     }
00232     else
00233     {
00234       use_posture_ = true;
00235       for (int j = 0; j < JOINTS; ++j)
00236         q_posture_[j] = msg->data[j];
00237     }
00238   }
00239 };
00240 
00241 
00242 template <int JOINTS>
00243 JinvTeleopController<JOINTS>::JinvTeleopController()
00244 {
00245   loop_count_ = 0;
00246 }
00247 
00248 template <int JOINTS>
00249 JinvTeleopController<JOINTS>::~JinvTeleopController()
00250 {
00251   sub_command_.shutdown();
00252   sub_command_pose_.shutdown();
00253   sub_twist_.shutdown();
00254   sub_posture_.shutdown();
00255 }
00256 
00257 template <int JOINTS>
00258 bool JinvTeleopController<JOINTS>::init(pr2_mechanism_model::RobotState *r, ros::NodeHandle &n)
00259 {
00260   rosrt::init();
00261   node_ = n;
00262   robot_ = r;
00263 
00264   
00265   std::string tip_name;
00266   if (!node_.getParam("root_name", root_name_))
00267   {
00268     ROS_ERROR("No \"root_name\" found on parameter server");
00269     return false;
00270   }
00271   if (!node_.getParam("tip_name", tip_name))
00272   {
00273     ROS_ERROR("No \"tip_name\" found on parameter server");
00274     return false;
00275   }
00276   if (!chain_.init(robot_, root_name_, tip_name))
00277     return false;
00278   chain_.toKDL(kdl_chain_);
00279 
00280   
00281 
00282   
00283   fk_solver_.reset(new KDL::ChainFkSolverVel_recursive(kdl_chain_));
00284   jac_solver_.reset(new KDL::ChainJntToJacSolver(kdl_chain_));
00285 
00286   
00287   double kp_trans, kd_trans, kp_rot, kd_rot;
00288   if (!node_.getParam("cart_gains/trans/p", kp_trans) ||
00289       !node_.getParam("cart_gains/trans/d", kd_trans))
00290   {
00291     ROS_ERROR("P and D translational gains not specified (namespace: %s)", node_.getNamespace().c_str());
00292     return false;
00293   }
00294   if (!node_.getParam("cart_gains/rot/p", kp_rot) ||
00295       !node_.getParam("cart_gains/rot/d", kd_rot))
00296   {
00297     ROS_ERROR("P and D rotational gains not specified (namespace: %s)", node_.getNamespace().c_str());
00298     return false;
00299   }
00300   Kp_x << kp_trans, kp_trans, kp_trans,  kp_rot, kp_rot, kp_rot;
00301   Kd_x << kd_trans, kd_trans, kd_trans,  kd_rot, kd_rot, kd_rot;
00302 
00303   
00304   for (size_t j = 0; j < JOINTS; ++j)
00305   {
00306     const std::string prefix = std::string("joints/" + chain_.getJoint(j)->joint_->name);
00307     node_.param(prefix + "/p", Kp_j[j], 0.0);
00308     node_.param(prefix + "/d", Kd_j[j], 0.0);
00309     node_.param(prefix + "/p_clamp", pclamp_j[j], 0.0);
00310   }
00311 
00312   node_.param("k_posture", k_posture_, 0.0);
00313   node_.param("jacobian_inverse_damping", jacobian_inverse_damping_, 0.0);
00314   node_.param("pose_command_filter", pose_command_filter_, 1.0);
00315 
00316   
00317   pub_x_.init(node_, "state/x", 3);
00318   pub_x_desi_.init(node_, "state/x_desi", 3);
00319   pub_x_err_.init(node_, "state/x_error", 3);
00320   pub_transformed_twist_ = node_.advertise<geometry_msgs::TwistStamped>("state/transformed_twist", 3);
00321   pub_transformed_rot_vel_ = node_.advertise<geometry_msgs::Vector3Stamped>("state/transformed_rot_vel", 3);
00322 
00323   
00324   
00325   sub_command_pose_ = node_.subscribe("command_pose", 20, &JinvTeleopController<JOINTS>::commandPoseCB, this);
00326   sub_twist_ = node_.subscribe("command_twist", 1,
00327                                &JinvTeleopController<JOINTS>::commandTwistCB, this);
00328   sub_posture_ = node_.subscribe("command_posture", 3,
00329                                  &JinvTeleopController<JOINTS>::commandPostureCB, this);
00330 
00331   StateMsg state_template;
00332   state_template.header.frame_id = root_name_;
00333   state_template.x.header.frame_id = root_name_;
00334   state_template.x_desi.header.frame_id = root_name_;
00335   state_template.x_desi_filtered.header.frame_id = root_name_;
00336   state_template.q_proxy.resize(JOINTS);
00337   state_template.qd_pose.resize(JOINTS);
00338   state_template.qd_posture.resize(JOINTS);
00339   state_template.qd_posture_raw.resize(JOINTS);
00340   state_template.qd_desi.resize(JOINTS);
00341   state_template.tau.resize(JOINTS);
00342   state_template.J.layout.dim.resize(2);
00343   state_template.J.data.resize(6*JOINTS);
00344   state_template.N.layout.dim.resize(2);
00345   state_template.N.data.resize(JOINTS*JOINTS);
00346   pub_state_.initialize(node_.advertise<StateMsg>("state", 20), 20, state_template);
00347 
00348   
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357   return true;
00358 }
00359 
00360 
00361 static void computePoseError(const Eigen::Affine3d &xact, const Eigen::Affine3d &xdes, Eigen::Matrix<double,6,1> &err)
00362 {
00363   err.head<3>() = xact.translation() - xdes.translation();
00364   err.tail<3>()   = 0.5 * (xdes.linear().col(0).cross(xact.linear().col(0)) +
00365                           xdes.linear().col(1).cross(xact.linear().col(1)) +
00366                           xdes.linear().col(2).cross(xact.linear().col(2)));
00367 }
00368 
00369 template <int JOINTS>
00370 void JinvTeleopController<JOINTS>::starting()
00371 {
00372   last_time_ = robot_->getTime();
00373 
00374   KDL::JntArrayVel q_qd(JOINTS);
00375   chain_.getVelocities(q_qd);
00376   JointVector q(q_qd.q.data), qd(q_qd.qdot.data);
00377 
00378   
00379   Eigen::Affine3d x;
00380   KDL::FrameVel x_framevel;
00381   fk_solver_->JntToCart(q_qd, x_framevel);
00382   tf::transformKDLToEigen(x_framevel.GetFrame(), x);
00383   q_proxy_ = q;
00384 
00385   x_desi_ = x;
00386   x_desi_filtered_ = x;
00387   xd_desi.setZero();
00388   use_posture_ = false;
00389   mode_ = POSE;
00390 }
00391 
00392 template <class Derived>
00393 
00394 Eigen::Matrix<double,3,3> eulerRot(double dt, const Eigen::MatrixBase<Derived>& e)
00395 {
00396   double n = e.norm();
00397   if (fabs(n) < 1e-8)
00398     return Eigen::Matrix<double,3,3>::Identity();
00399   return Eigen::AngleAxis<double>(n * dt, e.normalized()).toRotationMatrix();
00400   
00401 
00402 
00403 
00404 
00405 
00406 }
00407 
00408 template <int JOINTS>
00409 void JinvTeleopController<JOINTS>::update()
00410 {
00411   ros::Time time = robot_->getTime();
00412   ros::Duration dt = time - last_time_;
00413 
00414   KDL::JntArrayVel q_qd(JOINTS);
00415   chain_.getVelocities(q_qd);
00416   q = q_qd.q.data;
00417   qd = q_qd.qdot.data;
00418 
00419   KDL::Jacobian kdl_jacobian(JOINTS);
00420   jac_solver_->JntToJac(q_qd.q, kdl_jacobian);
00421   Eigen::Matrix<double, 6, JOINTS> J(kdl_jacobian.data);
00422 
00423   
00424   KDL::FrameVel x_framevel;
00425   fk_solver_->JntToCart(q_qd, x_framevel);
00426   tf::transformKDLToEigen(x_framevel.GetFrame(), x);
00427   tf::twistKDLToEigen(x_framevel.GetTwist(), xd);
00428 
00429   
00430   if (mode_ == TWIST)
00431   {
00432     if (time < last_command_time_ + ros::Duration(2.0))
00433     {
00434       x_desi_.translation() += xd_desi.head<3>() * dt.toSec();
00435       x_desi_.linear() = eulerRot(dt.toSec(), xd_desi.tail<3>()) * x_desi_.linear();
00436 
00437       
00438       Eigen::Vector3d err = x_desi_.translation() - x.translation();
00439       if (err.norm() > 0.1)
00440       {
00441         x_desi_.translation() = x.translation() + err.normalized() * 0.1;
00442       }
00443     }
00444     else
00445     {
00446       x_desi_ = x;
00447       mode_ = POSE;
00448     }
00449     x_desi_filtered_ = x_desi_;
00450   }
00451   else
00452   {
00453     
00454 
00455     Eigen::Vector3d p0(x_desi_filtered_.translation());
00456     Eigen::Vector3d p1(x_desi_.translation());
00457     Eigen::Quaterniond q0(x_desi_filtered_.linear());
00458     Eigen::Quaterniond q1(x_desi_.linear());
00459     q0.normalize();
00460     q1.normalize();
00461 
00462     tf::Quaternion tf_q0(q0.x(), q0.y(), q0.z(), q0.w());
00463     tf::Quaternion tf_q1(q1.x(), q1.y(), q1.z(), q1.w());
00464     tf::Quaternion tf_q = tf_q0.slerp(tf_q1, pose_command_filter_);
00465 
00466     Eigen::Vector3d p = p0 + pose_command_filter_ * (p1 - p0);
00467     
00468     Eigen::Quaterniond q(tf_q.w(), tf_q.x(), tf_q.y(), tf_q.z());
00469     
00470     x_desi_filtered_ = Eigen::Translation3d(p) * q;
00471   }
00472 
00473   
00474   computePoseError(x, x_desi_filtered_, x_err);
00475 
00476   
00477   xd_ref = xd_desi.array() - (Kp_x.array() / Kd_x.array()) * x_err.array();
00478 
00479   
00480   
00481 
00482   
00483 
00484   Eigen::Matrix<double,6,6> JJt = J * J.transpose();
00485   Eigen::Matrix<double,6,6> JJt_inv;
00486   JJt_inv = JJt.inverse();
00487   Eigen::Matrix<double,JOINTS,6> J_pinv = J.transpose() * JJt_inv;
00488 
00489   Eigen::Matrix<double,6,6> I6; I6.setIdentity();
00490   Eigen::Matrix<double,6,6> JJt_damped = J * J.transpose() + jacobian_inverse_damping_ * I6;
00491   Eigen::Matrix<double,6,6> JJt_inv_damped;
00492   JJt_inv_damped = JJt_damped.inverse();
00493   Eigen::Matrix<double,JOINTS,6> J_pinv_damped = J.transpose() * JJt_inv_damped;
00494 
00495   
00496   Eigen::Matrix<double,JOINTS,JOINTS> I;
00497   I.setIdentity();
00498   Eigen::Matrix<double,JOINTS,JOINTS> N = I - J_pinv * J;
00499 
00500   
00501   qd_pose = J_pinv_damped * xd_ref;  
00502   
00503   JointVector qd_desi = qd_pose;
00504 
00505   
00506   JointVector qd_posture;
00507   JointVector qd_posture_raw;
00508   if (use_posture_)
00509   {
00510     JointVector posture_err = q_posture_ - q;
00511     for (size_t j = 0; j < JOINTS; ++j)
00512     {
00513       if (chain_.getJoint(j)->joint_->type == urdf::Joint::CONTINUOUS)
00514         posture_err[j] = angles::normalize_angle(posture_err[j]);
00515     }
00516 
00517     for (size_t j = 0; j < JOINTS; ++j) {
00518       if (fabs(q_posture_[j] - 9999) < 1e-5)
00519         posture_err[j] = 0.0;
00520     }
00521 
00522     qd_posture_raw = k_posture_ * posture_err;
00523     qd_posture = N * qd_posture_raw;
00524     qd_desi += qd_posture;
00525   }
00526 
00527   
00528   for (int j = 0; j < JOINTS; ++j)
00529     q_proxy_[j] = std::max(q[j] - pclamp_j[j], std::min(q_proxy_[j], q[j] + pclamp_j[j]));
00530 
00531   
00532   tau = Kp_j.array() * (q_proxy_ - q).array() + Kd_j.array() * (qd_desi - qd).array();
00533   q_proxy_ += qd * dt.toSec();
00534 
00535   chain_.addEfforts(tau);
00536 
00537   if (loop_count_ % 10 == 0)
00538   {
00539     if (pub_x_.trylock())
00540     {
00541       pub_x_.msg_.header.stamp = time;
00542       pub_x_.msg_.header.frame_id = root_name_;  
00543       tf::poseEigenToMsg(x, pub_x_.msg_.pose);
00544       pub_x_.unlockAndPublish();
00545     }
00546 
00547     if (pub_x_desi_.trylock())
00548     {
00549       pub_x_desi_.msg_.header.stamp = time;
00550       pub_x_desi_.msg_.header.frame_id = root_name_;  
00551       tf::poseEigenToMsg(x_desi_, pub_x_desi_.msg_.pose);
00552       pub_x_desi_.unlockAndPublish();
00553     }
00554     if (pub_x_err_.trylock())
00555     {
00556       pub_x_err_.msg_.header.stamp = time;
00557       tf::twistEigenToMsg(x_err, pub_x_err_.msg_.twist);
00558       pub_x_err_.unlockAndPublish();
00559     }
00560 
00561     StateMsg::Ptr state_msg;
00562     if (state_msg = pub_state_.allocate()) {
00563       state_msg->header.stamp = time;
00564       state_msg->x.header.stamp = time;
00565       tf::poseEigenToMsg(x, state_msg->x.pose);
00566       state_msg->x_desi.header.stamp = time;
00567       tf::poseEigenToMsg(x_desi_, state_msg->x_desi.pose);
00568       state_msg->x_desi_filtered.header.stamp = time;
00569       tf::poseEigenToMsg(x_desi_filtered_, state_msg->x_desi_filtered.pose);
00570       tf::twistEigenToMsg(x_err, state_msg->x_err);
00571       tf::twistEigenToMsg(xd, state_msg->xd);
00572       tf::twistEigenToMsg(xd_desi, state_msg->xd_desi);
00573       tf::matrixEigenToMsg(J, state_msg->J);
00574       tf::matrixEigenToMsg(N, state_msg->N);
00575       for (size_t j = 0; j < JOINTS; ++j) {
00576         state_msg->q_proxy[j] = q_proxy_[j];
00577         state_msg->qd_pose[j] = qd_pose[j];
00578         state_msg->qd_posture[j] = qd_posture[j];
00579         state_msg->qd_posture_raw[j] = qd_posture_raw[j];
00580         state_msg->qd_desi[j] = qd_desi[j];
00581         state_msg->tau[j] = tau[j];
00582       }
00583       pub_state_.publish(state_msg);
00584     }
00585   }
00586 
00587   last_time_ = time;
00588   ++loop_count_;
00589 }
00590 
00591 } 
00592 
00593 #include <pluginlib/class_list_macros.h>
00594 PLUGINLIB_DECLARE_CLASS(teleop_controllers, JinvTeleopController7,
00595                         pr2_teleop::JinvTeleopController<7>, pr2_controller_interface::Controller)