jinv_teleop_controller.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2008, 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 #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   // Ensure 128-bit alignment for Eigen
00068   // See also http://eigen.tuxfamily.org/dox/StructHavingEigenMembers.html
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   // All local variables of update.  Brought outside so they can be recorded
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   void commandCB(const simple_cartesian_controller::CartesianCommand::ConstPtr &command)
00141   {
00142     ROS_ERROR("COMMAND");
00143     // TODO: TF stuff
00144 
00145     tf::poseMsgToEigen(command->pose, x_desi_);
00146     tf::twistMsgToEigen(command->twist, xd_desi);
00147     xd_trans_limit_ = command->max_trans_vel;
00148     xd_rot_limit_ = command->max_rot_vel;
00149     mode_ = POSE;
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     //vel = transform.getBasis().inverse() * vel;
00188     //rot_vel = transform.getBasis().inverse() * rot_vel;
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     //ROS_INFO("Transformed twist: %.2f, %.2f, %.2f,  %.2f, %.2f, %.2f",
00200     //         xd_desi[0], xd_desi[1], xd_desi[2], xd_desi[3], xd_desi[4], xd_desi[5]);
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   // Initialized the chain
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   // TODO: check chain size again JOINTS
00281 
00282   // Creates the KDL solvers
00283   fk_solver_.reset(new KDL::ChainFkSolverVel_recursive(kdl_chain_));
00284   jac_solver_.reset(new KDL::ChainJntToJacSolver(kdl_chain_));
00285 
00286   // Cartesian gains
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   // Gets the joint gains
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   // Advertises state topics
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   // Subscribe to desired posture
00324   //sub_command_ = node_.subscribe("command", 1, &JinvTeleopController<JOINTS>::commandCB, this);
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   JointVector q, qd;
00350   Eigen::Affine3d x;
00351   Eigen::Matrix<double, 6, 1> xd;
00352   Eigen::Matrix<double, 6, 1> x_err;
00353   Eigen::Matrix<double, 6, 1> xd_ref;
00354   JointVector qd_pose;
00355   JointVector tau;
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   // Forward kinematics to get current x
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 //Eigen::Quaterniond eulerRot(const Eigen::MatrixBase<Derived>& e)
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   return
00402     Eigen::AngleAxis<double>(e[2], Eigen::Vector3d(0,0,1)) *
00403     Eigen::AngleAxis<double>(e[1], Eigen::Vector3d(0,1,0)) *
00404     Eigen::AngleAxis<double>(e[0], Eigen::Vector3d(1,0,0));
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   // Forward kinematics to get x and xd
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   // Integrates the desired twist to determine the next position.
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       // Clamp
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     // Filters the desired pose
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     //Eigen::Quaterniond q = q0.slerp(pose_command_filter_, q1);
00468     Eigen::Quaterniond q(tf_q.w(), tf_q.x(), tf_q.y(), tf_q.z());
00469     //x_desi_filtered_ = q * Eigen::Translation3d(p);
00470     x_desi_filtered_ = Eigen::Translation3d(p) * q;
00471   }
00472 
00473   //computePoseError(x, x_desi_, x_err);
00474   computePoseError(x, x_desi_filtered_, x_err);
00475 
00476   // Computes the reference twist from the pose error and the desired twist.
00477   xd_ref = xd_desi.array() - (Kp_x.array() / Kd_x.array()) * x_err.array();
00478 
00479   // Applies velocity limits
00480   // TODO
00481 
00482   // Computes pseudo-inverse of J
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   // Computes the nullspace of J
00496   Eigen::Matrix<double,JOINTS,JOINTS> I;
00497   I.setIdentity();
00498   Eigen::Matrix<double,JOINTS,JOINTS> N = I - J_pinv * J;
00499 
00500   // Computes the desired joint velocities for achieving the pose.
00501   qd_pose = J_pinv_damped * xd_ref;  // J-inverse
00502   //qd_pose = J.transpose() * xd_ref;  // J-transpose
00503   JointVector qd_desi = qd_pose;
00504 
00505   // Computes the desired joint velocities for achieving the posture
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   // Clamps the proxy
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   // Convertes the desired joint velocities into joint torques
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_;  // NOT RT SAFE
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_;  // NOT RT SAFE
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 } // namespace
00592 
00593 #include <pluginlib/class_list_macros.h>
00594 PLUGINLIB_DECLARE_CLASS(teleop_controllers, JinvTeleopController7,
00595                         pr2_teleop::JinvTeleopController<7>, pr2_controller_interface::Controller)


teleop_controllers
Author(s): Stuart Glaser
autogenerated on Sat Dec 28 2013 17:23:59