$search
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 <pr2_manipulation_controllers/JinvTeleopControllerState.h> 00060 00061 namespace pr2_manipulation_controllers { 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 pr2_manipulation_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(pr2_manipulation_controllers, JinvTeleopController7, 00595 pr2_manipulation_controllers::JinvTeleopController<7>, pr2_controller_interface::Controller)