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)