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/thread.hpp>
00036 #include <boost/shared_ptr.hpp>
00037 #include <boost/scoped_ptr.hpp>
00038 #include <boost/foreach.hpp>
00039
00040 #include <Eigen/Core>
00041 #include <Eigen/Geometry>
00042 #include <Eigen/LU>
00043
00044 #include <kdl/chainfksolver.hpp>
00045 #include <kdl/chainfksolverpos_recursive.hpp>
00046 #include <kdl/chain.hpp>
00047 #include <kdl/chainjnttojacsolver.hpp>
00048 #include <kdl/frames.hpp>
00049
00050 #include <ros/ros.h>
00051
00052 #include <std_msgs/Bool.h>
00053 #include <geometry_msgs/PoseStamped.h>
00054 #include <geometry_msgs/TwistStamped.h>
00055 #include <geometry_msgs/WrenchStamped.h>
00056 #include <pr2_manipulation_controllers/JTTaskControllerState.h>
00057
00058 #include <pluginlib/class_list_macros.h>
00059 #include <angles/angles.h>
00060 #include <control_toolbox/pid.h>
00061 #include <eigen_conversions/eigen_kdl.h>
00062 #include <eigen_conversions/eigen_msg.h>
00063 #include <pr2_controller_interface/controller.h>
00064 #include <pr2_mechanism_model/chain.h>
00065 #include <realtime_tools/realtime_publisher.h>
00066 #include <tf/transform_listener.h>
00067 #include <tf_conversions/tf_eigen.h>
00068
00069 #include <rosrt/rosrt.h>
00070
00071 #include <filters/filter_chain.h>
00072 #include <hrl_pr2_force_ctrl/HybridCartesianGains.h>
00073
00074 using namespace pr2_manipulation_controllers;
00075
00076 namespace hrl_pr2_force_ctrl {
00077
00078 template <int Joints>
00079 struct Kin
00080 {
00081 typedef Eigen::Matrix<double, Joints, 1> JointVec;
00082 typedef Eigen::Matrix<double, 6, Joints> Jacobian;
00083
00084 Kin(const KDL::Chain &kdl_chain) :
00085 fk_solver_(kdl_chain), jac_solver_(kdl_chain),
00086 kdl_q(Joints), kdl_J(Joints)
00087 {
00088 }
00089 ~Kin()
00090 {
00091 }
00092
00093 void fk(const JointVec &q, Eigen::Affine3d &x)
00094 {
00095 kdl_q.data = q;
00096 KDL::Frame kdl_x;
00097 fk_solver_.JntToCart(kdl_q, kdl_x);
00098 tf::transformKDLToEigen(kdl_x, x);
00099 }
00100 void jac(const JointVec &q, Jacobian &J)
00101 {
00102 kdl_q.data = q;
00103 jac_solver_.JntToJac(kdl_q, kdl_J);
00104 J = kdl_J.data;
00105 }
00106
00107 KDL::ChainFkSolverPos_recursive fk_solver_;
00108 KDL::ChainJntToJacSolver jac_solver_;
00109 KDL::JntArray kdl_q;
00110 KDL::Jacobian kdl_J;
00111 };
00112
00113 class HybridForceController : public pr2_controller_interface::Controller
00114 {
00115 public:
00116
00117
00118 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
00119 private:
00120 enum { Joints = 7 };
00121 typedef Eigen::Matrix<double, Joints, 1> JointVec;
00122 typedef Eigen::Matrix<double, 6, 1> CartVec;
00123 typedef Eigen::Matrix<double, 6, Joints> Jacobian;
00124 typedef pr2_manipulation_controllers::JTTaskControllerState StateMsg;
00125 public:
00126 HybridForceController();
00127 ~HybridForceController();
00128
00129 bool init(pr2_mechanism_model::RobotState *robot, ros::NodeHandle &n);
00130 void starting();
00131 void update();
00132
00133 Eigen::Affine3d x_desi_, x_desi_filtered_;
00134 CartVec wrench_desi_;
00135
00136 ros::NodeHandle node_;
00137 ros::Subscriber sub_gains_;
00138 ros::Subscriber sub_posture_;
00139 ros::Subscriber sub_pose_;
00140 ros::Subscriber sub_force_;
00141 ros::Subscriber sub_max_force_;
00142 ros::Subscriber sub_ft_zero_;
00143 ros::Subscriber sub_ft_params_;
00144 tf::TransformListener tf_;
00145
00146 rosrt::Publisher<StateMsg> pub_state_;
00147 rosrt::Publisher<geometry_msgs::PoseStamped> pub_x_, pub_x_desi_;
00148 rosrt::Publisher<geometry_msgs::Twist> pub_xd_, pub_xd_desi_;
00149 rosrt::Publisher<geometry_msgs::Twist> pub_x_err_, pub_wrench_;
00150 rosrt::Publisher<std_msgs::Float64MultiArray> pub_tau_;
00151 rosrt::Publisher<std_msgs::Float64MultiArray> pub_qdot_;
00152 rosrt::Publisher<geometry_msgs::WrenchStamped> pub_sensor_ft_;
00153 rosrt::Publisher<geometry_msgs::WrenchStamped> pub_sensor_raw_ft_;
00154 rosrt::Publisher<geometry_msgs::WrenchStamped> pub_f_cmd_, pub_f_err_;
00155 rosrt::Publisher<geometry_msgs::WrenchStamped> pub_k_effective_;
00156
00157 std::string root_name_, tip_name_;
00158 ros::Time last_time_;
00159 int loop_count_;
00160 pr2_mechanism_model::RobotState *robot_state_;
00161
00162 pr2_mechanism_model::Chain chain_;
00163 boost::scoped_ptr<Kin<Joints> > kin_;
00164 Eigen::Matrix<double,6,1> Kp, Kd;
00165 Eigen::Matrix<double,6,6> St;
00166 bool use_tip_frame_;
00167 Eigen::Matrix<double,6,1> Kfp, Kfi, Kfi_max, force_selector, motion_selector;
00168 double pose_command_filter_;
00169 double vel_saturation_trans_, vel_saturation_rot_;
00170 JointVec saturation_;
00171 JointVec joint_dd_ff_;
00172 double joint_vel_filter_;
00173 double jacobian_inverse_damping_;
00174 JointVec q_posture_;
00175 double k_posture_;
00176 bool use_posture_;
00177
00178
00179 double res_force_, res_position_;
00180 double res_torque_, res_orientation_;
00181
00182 Eigen::Affine3d last_pose_;
00183 CartVec last_wrench_;
00184 double last_stiffness_, last_compliance_;
00185 double last_Dx_, last_Df_;
00186
00187
00188 JointVec qdot_filtered_;
00189
00190
00191 pr2_hardware_interface::AnalogIn *analog_in_;
00192 std::string force_torque_frame_;
00193 CartVec F_sensor_zero_;
00194 double gripper_mass_;
00195 Eigen::Vector3d gripper_com_;
00196 Eigen::Affine3d ft_transform_;
00197 CartVec F_des_, F_max_, F_integ_, K_effective_, F_err_last_;
00198 bool zero_wrench_;
00199
00200
00201 std::vector<boost::shared_ptr<filters::FilterChain<double> > > force_filter_, qdot_filter_, xdot_filter_;
00202
00203 void setGains(const hrl_pr2_force_ctrl::HybridCartesianGains::ConstPtr &msg)
00204 {
00205
00206
00207 if (msg->p_gains.size() == 6)
00208 for (size_t i = 0; i < 6; ++i)
00209 Kp[i] = msg->p_gains[i];
00210 if (msg->d_gains.size() == 6)
00211 for (size_t i = 0; i < 6; ++i)
00212 Kd[i] = msg->d_gains[i];
00213
00214
00215 if (msg->fp_gains.size() == 6)
00216 for (size_t i = 0; i < 6; ++i)
00217 Kfp[i] = msg->fp_gains[i];
00218 if (msg->fi_gains.size() == 6)
00219 for (size_t i = 0; i < 6; ++i)
00220 Kfi[i] = msg->fi_gains[i];
00221 if (msg->fi_max_gains.size() == 6)
00222 for (size_t i = 0; i < 6; ++i)
00223 Kfi_max[i] = msg->fi_max_gains[i];
00224
00225
00226 if (msg->force_selector.size() == 6)
00227 for (size_t i = 0; i < msg->force_selector.size(); ++i)
00228 if(msg->force_selector[i]) {
00229 force_selector[i] = 1;
00230 motion_selector[i] = 0;
00231 } else {
00232 force_selector[i] = 0;
00233 motion_selector[i] = 1;
00234 }
00235
00236
00237 if(!msg->header.frame_id.compare(root_name_))
00238 {
00239 use_tip_frame_ = false;
00240 ROS_INFO("New gains in root frame [%s]: %.1lf, %.1lf, %.1lf %.1lf, %.1lf, %.1lf",
00241 root_name_.c_str(), Kp[0], Kp[1], Kp[2], Kp[3], Kp[4], Kp[5]);
00242 St.setIdentity();
00243 }
00244 else if(!msg->header.frame_id.compare(tip_name_))
00245 {
00246 use_tip_frame_ = true;
00247 ROS_INFO("New gains in tip frame [%s]: %.1lf, %.1lf, %.1lf %.1lf, %.1lf, %.1lf",
00248 tip_name_.c_str(), Kp[0], Kp[1], Kp[2], Kp[3], Kp[4], Kp[5]);
00249
00250 }
00251 else
00252 {
00253 use_tip_frame_ = false;
00254
00255 geometry_msgs::PoseStamped in_root;
00256 in_root.pose.orientation.w = 1.0;
00257 in_root.header.frame_id = msg->header.frame_id;
00258
00259 try {
00260 tf_.waitForTransform(root_name_, msg->header.frame_id, msg->header.stamp, ros::Duration(0.1));
00261 tf_.transformPose(root_name_, in_root, in_root);
00262 }
00263 catch (const tf::TransformException &ex)
00264 {
00265 ROS_ERROR("Failed to transform: %s", ex.what());
00266 return;
00267 }
00268
00269 Eigen::Affine3d t;
00270
00271 tf::poseMsgToEigen(in_root.pose, t);
00272
00273 St <<
00274 t(0,0),t(0,1),t(0,2),0,0,0,
00275 t(1,0),t(1,1),t(1,2),0,0,0,
00276 t(2,0),t(2,1),t(2,2),0,0,0,
00277 0,0,0,t(0,0),t(0,1),t(0,2),
00278 0,0,0,t(1,0),t(1,1),t(1,2),
00279 0,0,0,t(2,0),t(2,1),t(2,2);
00280
00281 St.transposeInPlace();
00282
00283 ROS_INFO("New gains in arbitrary frame [%s]: %.1lf, %.1lf, %.1lf %.1lf, %.1lf, %.1lf",
00284 msg->header.frame_id.c_str(), Kp[0], Kp[1], Kp[2], Kp[3], Kp[4], Kp[5]);
00285 }
00286 }
00287
00288 void zeroFTSensor(const std_msgs::Bool::ConstPtr &msg) {
00289 zero_wrench_ = true;
00290 ROS_INFO("Sensor Zeroed");
00291 }
00292
00293 void setFTSensorParams(const std_msgs::Float64MultiArray::ConstPtr &msg)
00294 {
00295 if ((int)msg->data.size() == 1) {
00296 gripper_mass_ = msg->data[0];
00297 }
00298 else if ((int)msg->data.size() == 4) {
00299 gripper_mass_ = msg->data[0];
00300 gripper_com_[0] = msg->data[1];
00301 gripper_com_[1] = msg->data[2];
00302 gripper_com_[2] = msg->data[3];
00303 }
00304 else
00305 {
00306 ROS_ERROR("ft_params message had the wrong size: %d", (int)msg->data.size());
00307 return;
00308 }
00309 }
00310
00311 void commandPosture(const std_msgs::Float64MultiArray::ConstPtr &msg)
00312 {
00313 if (msg->data.size() == 0) {
00314 use_posture_ = false;
00315 ROS_INFO("Posture turned off");
00316 }
00317 else if ((int)msg->data.size() != q_posture_.size()) {
00318 ROS_ERROR("Posture message had the wrong size: %d", (int)msg->data.size());
00319 return;
00320 }
00321 else
00322 {
00323 use_posture_ = true;
00324 for (int j = 0; j < Joints; ++j)
00325 q_posture_[j] = msg->data[j];
00326 }
00327 }
00328
00329 void commandPose(const geometry_msgs::PoseStamped::ConstPtr &command)
00330 {
00331 geometry_msgs::PoseStamped in_root;
00332 try {
00333 tf_.waitForTransform(root_name_, command->header.frame_id, command->header.stamp, ros::Duration(0.1));
00334 tf_.transformPose(root_name_, *command, in_root);
00335 }
00336 catch (const tf::TransformException &ex)
00337 {
00338 ROS_ERROR("Failed to transform: %s", ex.what());
00339 return;
00340 }
00341
00342 tf::poseMsgToEigen(in_root.pose, x_desi_);
00343 }
00344
00345 void commandForce(const geometry_msgs::WrenchStamped::ConstPtr &msg)
00346 {
00347 F_des_ << msg->wrench.force.x, msg->wrench.force.y, msg->wrench.force.z,
00348 msg->wrench.torque.x, msg->wrench.torque.y, msg->wrench.torque.z;
00349 if(msg->header.frame_id == root_name_)
00350 return;
00351
00352 geometry_msgs::PoseStamped in_root;
00353 in_root.pose.orientation.w = 1.0;
00354 in_root.header.frame_id = msg->header.frame_id;
00355
00356 try {
00357 tf_.waitForTransform(root_name_, msg->header.frame_id, msg->header.stamp, ros::Duration(0.1));
00358 tf_.transformPose(root_name_, in_root, in_root);
00359 }
00360 catch (const tf::TransformException &ex)
00361 {
00362 ROS_ERROR("Failed to transform: %s", ex.what());
00363 return;
00364 }
00365
00366 Eigen::Affine3d t;
00367
00368 tf::poseMsgToEigen(in_root.pose, t);
00369
00370 F_des_.head<3>() = t.linear() * F_des_.head<3>();
00371 F_des_.tail<3>() = t.linear() * F_des_.tail<3>();
00372 }
00373
00374 void commandMaxForce(const geometry_msgs::WrenchStamped::ConstPtr &msg)
00375 {
00376 F_max_ << msg->wrench.force.x, msg->wrench.force.y, msg->wrench.force.z,
00377 msg->wrench.torque.x, msg->wrench.torque.y, msg->wrench.torque.z;
00378 }
00379
00380 };
00381
00382
00383 HybridForceController::HybridForceController()
00384 : robot_state_(NULL), use_posture_(false)
00385 {}
00386
00387 HybridForceController::~HybridForceController()
00388 {
00389 sub_gains_.shutdown();
00390 sub_posture_.shutdown();
00391 sub_pose_.shutdown();
00392
00393
00394 sub_force_.shutdown();
00395 sub_max_force_.shutdown();
00396 sub_ft_zero_.shutdown();
00397 sub_ft_params_.shutdown();
00398 }
00399
00400
00401 bool HybridForceController::init(pr2_mechanism_model::RobotState *robot_state, ros::NodeHandle &n)
00402 {
00403 rosrt::init();
00404 node_ = n;
00405
00406 ROS_INFO_STREAM("JTTask controller compiled at " << __TIME__ );
00407
00408
00409 if (!node_.getParam("root_name", root_name_)){
00410 ROS_ERROR("HybridForceController: No root name found on parameter server (namespace: %s)",
00411 node_.getNamespace().c_str());
00412 return false;
00413 }
00414 if (!node_.getParam("tip_name", tip_name_)){
00415 ROS_ERROR("HybridForceController: No tip name found on parameter server (namespace: %s)",
00416 node_.getNamespace().c_str());
00417 return false;
00418 }
00419
00420
00421 assert(robot_state);
00422 robot_state_ = robot_state;
00423
00424
00425 if (!chain_.init(robot_state_, root_name_, tip_name_))
00426 return false;
00427 if (!chain_.allCalibrated())
00428 {
00429 ROS_ERROR("Not all joints in the chain are calibrated (namespace: %s)", node_.getNamespace().c_str());
00430 return false;
00431 }
00432
00433
00434
00435 KDL::Chain kdl_chain;
00436 chain_.toKDL(kdl_chain);
00437 kin_.reset(new Kin<Joints>(kdl_chain));
00438
00439
00440 double kp_trans, kd_trans, kp_rot, kd_rot;
00441 if (!node_.getParam("cart_gains/trans/p", kp_trans) ||
00442 !node_.getParam("cart_gains/trans/d", kd_trans))
00443 {
00444 ROS_ERROR("P and D translational gains not specified (namespace: %s)", node_.getNamespace().c_str());
00445 return false;
00446 }
00447 if (!node_.getParam("cart_gains/rot/p", kp_rot) ||
00448 !node_.getParam("cart_gains/rot/d", kd_rot))
00449 {
00450 ROS_ERROR("P and D rotational gains not specified (namespace: %s)", node_.getNamespace().c_str());
00451 return false;
00452 }
00453 Kp << kp_trans, kp_trans, kp_trans, kp_rot, kp_rot, kp_rot;
00454 Kd << kd_trans, kd_trans, kd_trans, kd_rot, kd_rot, kd_rot;
00455
00456
00457 use_tip_frame_ = false;
00458 if (!node_.getParam("use_tip_frame", use_tip_frame_)){
00459 ROS_WARN("HybridForceController: use_tip_frame was not specified, assuming 'false': %s)",
00460 node_.getNamespace().c_str());
00461 }
00462 St.setIdentity();
00463
00464
00465 F_des_.setZero();
00466 F_integ_.setZero();
00467 K_effective_.setZero();
00468
00469 double f_trans_max, f_rot_max;
00470 node_.param("force_trans_max", f_trans_max, 9999.0);
00471 node_.param("force_rot_max", f_rot_max, 9999.0);
00472 F_max_ << f_trans_max, f_trans_max, f_trans_max, f_rot_max, f_rot_max, f_rot_max;
00473
00474
00475 double kfp_trans, kfp_rot, kfi_trans, kfi_rot, kfi_max_trans, kfi_max_rot;
00476 if (!node_.getParam("force_gains/trans/p", kfp_trans) ||
00477 !node_.getParam("force_gains/trans/i", kfi_trans) ||
00478 !node_.getParam("force_gains/trans/i_max", kfi_max_trans))
00479 {
00480 ROS_ERROR("P and I translational force gains not specified (namespace: %s)", node_.getNamespace().c_str());
00481 return false;
00482 }
00483 if (!node_.getParam("force_gains/rot/p", kfp_rot) ||
00484 !node_.getParam("force_gains/rot/i", kfi_rot) ||
00485 !node_.getParam("force_gains/rot/i_max", kfi_max_rot))
00486 {
00487 ROS_ERROR("P and I rotational force gains not specified (namespace: %s)", node_.getNamespace().c_str());
00488 return false;
00489 }
00490 Kfp << kfp_trans, kfp_trans, kfp_trans, kfp_rot, kfp_rot, kfp_rot;
00491 Kfi << kfi_trans, kfi_trans, kfi_trans, kfi_rot, kfi_rot, kfi_rot;
00492 Kfi_max << kfi_max_trans, kfi_max_trans, kfi_max_trans, kfi_max_rot, kfi_max_rot, kfi_max_rot;
00493 motion_selector = CartVec::Ones();
00494 force_selector = CartVec::Zero();
00495 force_filter_.resize(6);
00496 for(int i=0;i<6;i++) {
00497 force_filter_[i].reset(new filters::FilterChain<double>("double"));
00498 force_filter_[i]->configure("force_filter", node_);
00499 ros::Duration(0.2).sleep();
00500 }
00501 qdot_filter_.resize(Joints);
00502 for(int i=0;i<Joints;i++) {
00503 ros::Duration(0.2).sleep();
00504 qdot_filter_[i].reset(new filters::FilterChain<double>("double"));
00505 qdot_filter_[i]->configure("qdot_filter", node_);
00506 }
00507 xdot_filter_.resize(6);
00508 for(int i=0;i<6;i++) {
00509 ros::Duration(0.2).sleep();
00510 xdot_filter_[i].reset(new filters::FilterChain<double>("double"));
00511 xdot_filter_[i]->configure("xdot_filter", node_);
00512 }
00513
00514 node_.param("pose_command_filter", pose_command_filter_, 1.0);
00515
00516
00517 node_.param("vel_saturation_trans", vel_saturation_trans_, 0.0);
00518 node_.param("vel_saturation_rot", vel_saturation_rot_, 0.0);
00519
00520 node_.param("jacobian_inverse_damping", jacobian_inverse_damping_, 0.0);
00521 node_.param("joint_vel_filter", joint_vel_filter_, 1.0);
00522
00523
00524 for (int i = 0; i < Joints; ++i)
00525 node_.param("joint_feedforward/" + chain_.getJoint(i)->joint_->name, joint_dd_ff_[i], 0.0);
00526 for (int i = 0; i < Joints; ++i)
00527 node_.param("saturation/" + chain_.getJoint(i)->joint_->name, saturation_[i], 0.0);
00528
00529
00530 node_.param("k_posture", k_posture_, 1.0);
00531
00532 node_.param("resolution/force", res_force_, 0.01);
00533 node_.param("resolution/position", res_position_, 0.001);
00534 node_.param("resolution/torque", res_torque_, 0.01);
00535 node_.param("resolution/orientation", res_orientation_, 0.001);
00536
00537
00538 zero_wrench_ = true;
00539 node_.param("gripper_params/mass", gripper_mass_, 1.02074);
00540 node_.param("gripper_params/com_pos_x", gripper_com_[0], -0.00126);
00541 node_.param("gripper_params/com_pos_y", gripper_com_[1], 0.001760);
00542 node_.param("gripper_params/com_pos_z", gripper_com_[2], -0.08532);
00543 std::string analog_in_name;
00544 if (!node_.getParam("force_torque_analog_in", analog_in_name))
00545 {
00546 ROS_ERROR("HybridForceController: No \"analog_in_name\" found on parameter namespace: %s",
00547 node_.getNamespace().c_str());
00548 return false;
00549 }
00550 pr2_hardware_interface::HardwareInterface* hw = robot_state_->model_->hw_;
00551 analog_in_ = hw->getAnalogIn(analog_in_name);
00552 if (analog_in_ == NULL)
00553 {
00554 ROS_ERROR("HybridForceController: Cannot find AnalogIn named \"%s\"",
00555 analog_in_name.c_str());
00556 BOOST_FOREACH(const pr2_hardware_interface::AnalogInMap::value_type &v, hw->analog_ins_)
00557 {
00558 ROS_INFO("AnalogIn : %s", v.first.c_str());
00559 }
00560 return false;
00561 }
00562 ROS_INFO("HybridForceController: Using AnalogIn named \"%s\"", analog_in_name.c_str());
00563 if (!node_.getParam("force_torque_frame", force_torque_frame_))
00564 {
00565 ROS_ERROR("HybridForceController: No \"force_torque_frame\" found on parameter namespace: %s",
00566 node_.getNamespace().c_str());
00567 return false;
00568 }
00569 try {
00570 tf::StampedTransform ft_stf;
00571 tf_.waitForTransform(tip_name_, force_torque_frame_, ros::Time(0), ros::Duration(1.0));
00572 tf_.lookupTransform(force_torque_frame_, tip_name_, ros::Time(0), ft_stf);
00573 tf::TransformTFToEigen(ft_stf, ft_transform_);
00574 }
00575 catch (const tf::TransformException &ex)
00576 {
00577 ROS_ERROR("Failed to transform: %s", ex.what());
00578 return false;
00579 }
00580
00581 sub_gains_ = node_.subscribe("gains", 5, &HybridForceController::setGains, this);
00582 sub_posture_ = node_.subscribe("command_posture", 5, &HybridForceController::commandPosture, this);
00583 sub_pose_ = node_.subscribe("command_pose", 1, &HybridForceController::commandPose, this);
00584
00585 sub_force_ = node_.subscribe("command_force", 1, &HybridForceController::commandForce, this);
00586 sub_max_force_ = node_.subscribe("command_max_force", 1, &HybridForceController::commandMaxForce, this);
00587 sub_ft_zero_ = node_.subscribe("ft_zero", 5, &HybridForceController::zeroFTSensor, this);
00588 sub_ft_params_ = node_.subscribe("ft_params", 5, &HybridForceController::setFTSensorParams, this);
00589
00590 StateMsg state_template;
00591 state_template.header.frame_id = root_name_;
00592 state_template.x.header.frame_id = root_name_;
00593 state_template.x_desi.header.frame_id = root_name_;
00594 state_template.x_desi_filtered.header.frame_id = root_name_;
00595 state_template.tau_pose.resize(Joints);
00596 state_template.tau_posture.resize(Joints);
00597 state_template.tau.resize(Joints);
00598 state_template.J.layout.dim.resize(2);
00599 state_template.J.data.resize(6*Joints);
00600 state_template.N.layout.dim.resize(2);
00601 state_template.N.data.resize(Joints*Joints);
00602 pub_state_.initialize(node_.advertise<StateMsg>("state", 10), 10, state_template);
00603
00604 geometry_msgs::PoseStamped pose_template;
00605 pose_template.header.frame_id = root_name_;
00606 pub_x_.initialize(node_.advertise<geometry_msgs::PoseStamped>("state/x", 10),
00607 10, pose_template);
00608 pub_x_desi_.initialize(node_.advertise<geometry_msgs::PoseStamped>("state/x_desi", 10),
00609 10, pose_template);
00610 pub_x_err_.initialize(node_.advertise<geometry_msgs::Twist>("x_err", 10),
00611 10, geometry_msgs::Twist());
00612 pub_xd_.initialize(node_.advertise<geometry_msgs::Twist>("state/xd", 10),
00613 10, geometry_msgs::Twist());
00614 pub_xd_desi_.initialize(node_.advertise<geometry_msgs::Twist>("state/xd_desi", 10),
00615 10, geometry_msgs::Twist());
00616 pub_wrench_.initialize(node_.advertise<geometry_msgs::Twist>("state/wrench", 10),
00617 10, geometry_msgs::Twist());
00618 pub_sensor_ft_.initialize(node_.advertise<geometry_msgs::WrenchStamped>("sensor_ft", 10),
00619 10, geometry_msgs::WrenchStamped());
00620 pub_sensor_raw_ft_.initialize(node_.advertise<geometry_msgs::WrenchStamped>("sensor_raw_ft", 10),
00621 10, geometry_msgs::WrenchStamped());
00622 pub_f_cmd_.initialize(node_.advertise<geometry_msgs::WrenchStamped>("f_cmd", 10),
00623 10, geometry_msgs::WrenchStamped());
00624 pub_f_err_.initialize(node_.advertise<geometry_msgs::WrenchStamped>("f_err", 10),
00625 10, geometry_msgs::WrenchStamped());
00626 pub_k_effective_.initialize(node_.advertise<geometry_msgs::WrenchStamped>("k_effective", 10),
00627 10, geometry_msgs::WrenchStamped());
00628
00629 std_msgs::Float64MultiArray joints_template;
00630 joints_template.layout.dim.resize(1);
00631 joints_template.layout.dim[0].size = Joints;
00632 joints_template.layout.dim[0].stride = 1;
00633 joints_template.data.resize(7);
00634 pub_tau_.initialize(node_.advertise<std_msgs::Float64MultiArray>("state/tau", 10),
00635 10, joints_template);
00636 pub_qdot_.initialize(node_.advertise<std_msgs::Float64MultiArray>("qd", 10),
00637 10, joints_template);
00638
00639 return true;
00640 }
00641
00642 void HybridForceController::starting()
00643 {
00644
00645
00646
00647 JointVec q;
00648 chain_.getPositions(q);
00649 kin_->fk(q, x_desi_);
00650 x_desi_filtered_ = x_desi_;
00651 last_pose_ = x_desi_;
00652 q_posture_ = q;
00653 qdot_filtered_.setZero();
00654 last_wrench_.setZero();
00655 F_err_last_.setZero();
00656
00657 last_stiffness_ = 0;
00658 last_compliance_ = 0;
00659 last_Dx_ = 0;
00660 last_Df_ = 0;
00661
00662 loop_count_ = 0;
00663
00664 F_integ_.setZero();
00665
00666 }
00667
00668
00669 static void computePoseError(const Eigen::Affine3d &xact, const Eigen::Affine3d &xdes, Eigen::Matrix<double,6,1> &err)
00670 {
00671 err.head<3>() = xact.translation() - xdes.translation();
00672 err.tail<3>() = 0.5 * (xdes.linear().col(0).cross(xact.linear().col(0)) +
00673 xdes.linear().col(1).cross(xact.linear().col(1)) +
00674 xdes.linear().col(2).cross(xact.linear().col(2)));
00675 }
00676
00677 void HybridForceController::update()
00678 {
00679
00680 ros::Time time = robot_state_->getTime();
00681 ros::Duration dt = time - last_time_;
00682 last_time_ = time;
00683 ++loop_count_;
00684
00685
00686
00687 JointVec q;
00688 chain_.getPositions(q);
00689
00690 Eigen::Affine3d x;
00691 kin_->fk(q, x);
00692
00693 Jacobian J;
00694 kin_->jac(q, J);
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 JointVec qdot;
00707 double in_qdot, out_qdot;
00708 for(int i=0;i<Joints;i++) {
00709 in_qdot = q[i];
00710 qdot_filter_[i]->update(in_qdot, out_qdot);
00711 qdot[i] = out_qdot;
00712 }
00713 qdot = qdot / dt.toSec();
00714 if(loop_count_ < 100)
00715 qdot.setZero();
00716
00717
00718 CartVec xdot = J * qdot;
00719 double in_xdot, out_xdot;
00720 for(int i=0;i<6;i++) {
00721 in_xdot = xdot[i];
00722 xdot_filter_[i]->update(in_xdot, out_xdot);
00723 xdot[i] = out_xdot;
00724 }
00725
00726
00727
00728 {
00729 Eigen::Vector3d p0(x_desi_filtered_.translation());
00730 Eigen::Vector3d p1(x_desi_.translation());
00731 Eigen::Quaterniond q0(x_desi_filtered_.linear());
00732 Eigen::Quaterniond q1(x_desi_.linear());
00733 q0.normalize();
00734 q1.normalize();
00735
00736 tf::Quaternion tf_q0(q0.x(), q0.y(), q0.z(), q0.w());
00737 tf::Quaternion tf_q1(q1.x(), q1.y(), q1.z(), q1.w());
00738 tf::Quaternion tf_q = tf_q0.slerp(tf_q1, pose_command_filter_);
00739
00740 Eigen::Vector3d p = p0 + pose_command_filter_ * (p1 - p0);
00741
00742 Eigen::Quaterniond q(tf_q.w(), tf_q.x(), tf_q.y(), tf_q.z());
00743
00744 x_desi_filtered_ = Eigen::Translation3d(p) * q;
00745 }
00746 CartVec x_err, x_err_ctrl_frame;
00747
00748 computePoseError(x, x_desi_filtered_, x_err);
00749
00750 if(use_tip_frame_)
00751 {
00752 St <<
00753 x(0,0),x(0,1),x(0,2),0,0,0,
00754 x(1,0),x(1,1),x(1,2),0,0,0,
00755 x(2,0),x(2,1),x(2,2),0,0,0,
00756 0,0,0,x(0,0),x(0,1),x(0,2),
00757 0,0,0,x(1,0),x(1,1),x(1,2),
00758 0,0,0,x(2,0),x(2,1),x(2,2);
00759 St.transposeInPlace();
00760 }
00761
00762
00763 x_err_ctrl_frame = St * x_err;
00764 CartVec xdot_desi = Kp.array() * x_err_ctrl_frame.array() * -1.0;
00765
00766
00767 if (vel_saturation_trans_ > 0.0)
00768 {
00769 if (fabs(xdot_desi.head<3>().norm()) > vel_saturation_trans_)
00770 xdot_desi.head<3>() *= (vel_saturation_trans_ / xdot_desi.head<3>().norm());
00771 }
00772 if (vel_saturation_rot_ > 0.0)
00773 {
00774 if (fabs(xdot_desi.tail<3>().norm()) > vel_saturation_rot_)
00775 xdot_desi.tail<3>() *= (vel_saturation_rot_ / xdot_desi.tail<3>().norm());
00776 }
00777
00778 CartVec xdot_ctrl_frame = St * xdot;
00779 CartVec F_damp = Kd.array() * xdot_ctrl_frame.array();
00780 CartVec F_cmd = motion_selector.array() * xdot_desi.array() +
00781 force_selector.array() * (St * F_des_).array() - F_damp.array();
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 for(int i=0;i<6;i++) {
00798 if(F_max_[i] >= 0.0) {
00799 if(F_cmd[i] > 0)
00800 F_cmd[i] = std::min(F_max_[i], F_cmd[i]);
00801 else
00802 F_cmd[i] = -std::min(F_max_[i], -F_cmd[i]);
00803 }
00804 }
00805
00806 CartVec F_motion = F_cmd;
00807
00809 CartVec F_sensor_raw, F_sensor_zeroed, F_grav;
00810 {
00811 for(int i=0;i<6;i++)
00812 F_sensor_raw[i] = analog_in_->state_.state_[i];
00813
00814
00815 Eigen::Vector4d z_grav(0, 0, -1, 0);
00816 z_grav = -1 * ft_transform_.matrix() * x.matrix().inverse() * z_grav;
00817 F_grav.head<3>() = gripper_mass_ * 9.81 * z_grav.head<3>();
00818 Eigen::Vector3d F_grav_vec(F_grav[0], F_grav[1], F_grav[2]);
00819 Eigen::Vector3d torque_vec = gripper_com_.cross(F_grav_vec);
00820 F_grav.tail<3>() = torque_vec;
00821 if(zero_wrench_) {
00822 F_sensor_zero_ = F_sensor_raw - F_grav;
00823 zero_wrench_ = false;
00824 }
00825 F_sensor_zeroed = (F_sensor_raw - F_grav - F_sensor_zero_);
00826
00827
00828 Eigen::Vector3d F_sensor_zeroed_force(F_sensor_zeroed[0], F_sensor_zeroed[1], F_sensor_zeroed[2]);
00829 Eigen::Vector3d F_sensor_zeroed_torque(F_sensor_zeroed[3], F_sensor_zeroed[4], F_sensor_zeroed[5]);
00830 F_sensor_zeroed_force = ft_transform_.linear().transpose() * F_sensor_zeroed_force;
00831 F_sensor_zeroed_torque = ft_transform_.linear().transpose() * F_sensor_zeroed_torque;
00832 Eigen::Vector3d torque_offset = ft_transform_.translation().cross(F_sensor_zeroed_torque);
00833 F_sensor_zeroed.head<3>() = F_sensor_zeroed_force;
00834 F_sensor_zeroed.tail<3>() = F_sensor_zeroed_torque + torque_offset;
00835
00836 if(!use_tip_frame_) {
00837
00838 F_sensor_zeroed.head<3>() = x.linear() * F_sensor_zeroed.head<3>();
00839 F_sensor_zeroed.tail<3>() = x.linear() * F_sensor_zeroed.tail<3>();
00840 F_sensor_zeroed = St * F_sensor_zeroed;
00841 }
00842
00843
00844 double in_F, out_F;
00845 for(int i=0;i<6;i++) {
00846 in_F = F_sensor_zeroed[i];
00847 force_filter_[i]->update(in_F, out_F);
00848 F_sensor_zeroed[i] = out_F;
00849 }
00850 if(loop_count_ < 100)
00851 F_sensor_zeroed.setZero();
00852 }
00854
00855
00856
00857 CartVec proportional_selector, integral_selector;
00858 proportional_selector.setZero();
00859 integral_selector.setZero();
00860 for(int i=0;i<6;i++)
00861 if(Kfi[i] != 0 || Kfi_max[i] != 0)
00862 integral_selector[i] = 1;
00863 else
00864 proportional_selector[i] = 1;
00865 CartVec F_control, F_control_p, F_control_i, F_err;
00866 F_err = F_cmd - F_sensor_zeroed;
00867
00868 F_control_p = F_cmd.array() + Kfp.array() * F_err.array();
00869
00870
00871 F_integ_ = integral_selector.array() * (F_integ_.array() + Kfi.array() * F_err.array());
00872 for(int i=0;i<6;i++)
00873 if(F_integ_[i] > Kfi_max[i])
00874 F_integ_[i] = Kfi_max[i];
00875 else if(F_integ_[i] < -Kfi_max[i])
00876 F_integ_[i] = -Kfi_max[i];
00877
00878 double velocity = std::sqrt(xdot(0) * xdot(0) + xdot(1) * xdot(1) + xdot(2) * xdot(2));
00879 for(int i=0;i<6;i++)
00880 if(((F_err[i] > 0) != (F_err_last_[i] > 0)) && velocity > 0.01)
00881 F_integ_[i] = 0;
00882 F_err_last_ = F_err;
00883
00884 F_control_i = F_integ_.array() + Kfp.array() * (F_cmd - F_sensor_zeroed).array();
00885
00886 F_control = proportional_selector.array() * F_control_p.array() +
00887 integral_selector.array() * F_control_i.array();
00888
00889
00890
00891
00892 JointVec tau_pose = J.transpose() * St.transpose() * F_control;
00893
00894
00895
00896
00897 Eigen::Matrix<double,6,6> I6; I6.setIdentity();
00898 Eigen::Matrix<double,6,6> JJt = J * J.transpose();
00899 Eigen::Matrix<double,6,6> JJt_inv;
00900 JJt_inv = JJt.inverse();
00901 Eigen::Matrix<double,6,6> JJt_damped = J * J.transpose() + jacobian_inverse_damping_ * I6;
00902 Eigen::Matrix<double,6,6> JJt_inv_damped;
00903 JJt_inv_damped = JJt_damped.inverse();
00904 Eigen::Matrix<double,Joints,6> J_pinv = J.transpose() * JJt_inv_damped;
00905
00906
00907 Eigen::Matrix<double,Joints,Joints> I;
00908 I.setIdentity();
00909 Eigen::Matrix<double,Joints,Joints> N = I - J_pinv * J;
00910
00911
00912
00913
00914 JointVec tau_posture;
00915 tau_posture.setZero();
00916 if (use_posture_)
00917 {
00918 JointVec posture_err = q_posture_ - q;
00919 for (size_t j = 0; j < Joints; ++j)
00920 {
00921 if (chain_.getJoint(j)->joint_->type == urdf::Joint::CONTINUOUS)
00922 posture_err[j] = angles::normalize_angle(posture_err[j]);
00923 }
00924
00925 for (size_t j = 0; j < Joints; ++j) {
00926 if (fabs(q_posture_[j] - 9999) < 1e-5)
00927 posture_err[j] = 0.0;
00928 }
00929
00930 JointVec qdd_posture = k_posture_ * posture_err;
00931 tau_posture = joint_dd_ff_.array() * (N * qdd_posture).array();
00932 }
00933
00934 JointVec tau = tau_pose + tau_posture;
00935
00936
00937 double sat_scaling = 1.0;
00938 for (int i = 0; i < Joints; ++i) {
00939 if (saturation_[i] > 0.0)
00940 sat_scaling = std::min(sat_scaling, fabs(saturation_[i] / tau[i]));
00941 }
00942 JointVec tau_sat = sat_scaling * tau;
00943
00944 chain_.addEfforts(tau_sat);
00945
00946
00947
00948
00949 CartVec df = F_motion - last_wrench_;
00950 CartVec dx;
00951 computePoseError(last_pose_, x, dx);
00952
00953
00954
00955 double Df, Dx;
00956 if (fabs(dx[2]) >= res_position_)
00957 Df = df[2] * res_position_ / fabs(dx[2]);
00958 else
00959 Df = (1. - fabs(dx[2])/res_position_) * last_Df_ + df[2];
00960 if (fabs(df[2]) >= res_force_)
00961 Dx = dx[2] * res_force_ / fabs(df[2]);
00962 else
00963 Dx = (1. - fabs(df[2])/res_force_) * last_Dx_ + dx[2];
00964 last_Df_ = Df;
00965 last_Dx_ = Dx;
00966
00967 double stiffness, compliance;
00968 if (fabs(dx[2]) >= res_position_)
00969 stiffness = fabs(df[2]) / fabs(dx[2]);
00970 else
00971 stiffness = (1 - fabs(dx[2])/res_position_) * last_stiffness_ + fabs(df[2]) / res_position_;
00972 if (fabs(df[2]) >= res_force_)
00973 compliance = fabs(dx[2]) / fabs(df[2]);
00974 else
00975 compliance = (1 - fabs(df[2])/res_force_) * last_compliance_ + fabs(dx[2]) / res_force_;
00976
00977 last_pose_ = x;
00978 last_wrench_ = F_motion;
00979 last_stiffness_ = stiffness;
00980 last_compliance_ = compliance;
00981
00982
00983 for(int i=0;i<6;i++)
00984 if(fabs(x_err_ctrl_frame[i]) > 0.001)
00985 K_effective_[i] = fabs(F_sensor_zeroed[i] / x_err_ctrl_frame[i]);
00986
00987 if (loop_count_ % 10 == 0)
00988 {
00989 geometry_msgs::PoseStamped::Ptr pose_msg;
00990 geometry_msgs::Twist::Ptr twist_msg;
00991 geometry_msgs::WrenchStamped::Ptr wrench_msg;
00992 std_msgs::Float64MultiArray::Ptr q_msg;
00993
00994 if (pose_msg = pub_x_.allocate()) {
00995 pose_msg->header.stamp = time;
00996 tf::poseEigenToMsg(x, pose_msg->pose);
00997 pub_x_.publish(pose_msg);
00998 }
00999
01000 if (pose_msg = pub_x_desi_.allocate()) {
01001 pose_msg->header.stamp = time;
01002 tf::poseEigenToMsg(x_desi_, pose_msg->pose);
01003 pub_x_desi_.publish(pose_msg);
01004 }
01005
01006 if (twist_msg = pub_x_err_.allocate()) {
01007 tf::twistEigenToMsg(x_err, *twist_msg);
01008 pub_x_err_.publish(twist_msg);
01009 }
01010
01011 if (twist_msg = pub_xd_.allocate()) {
01012 tf::twistEigenToMsg(xdot_ctrl_frame, *twist_msg);
01013 pub_xd_.publish(twist_msg);
01014 }
01015
01016 if (twist_msg = pub_xd_desi_.allocate()) {
01017 tf::twistEigenToMsg(xdot_desi, *twist_msg);
01018 pub_xd_desi_.publish(twist_msg);
01019 }
01020
01021 if (twist_msg = pub_wrench_.allocate()) {
01022 tf::twistEigenToMsg(F_motion, *twist_msg);
01023 pub_wrench_.publish(twist_msg);
01024 }
01025
01026 if (wrench_msg = pub_sensor_ft_.allocate()) {
01027 wrench_msg->header.stamp = time;
01028 wrench_msg->header.frame_id = tip_name_;
01029 tf::wrenchEigenToMsg(F_sensor_zeroed, wrench_msg->wrench);
01030 pub_sensor_ft_.publish(wrench_msg);
01031 }
01032
01033 if (wrench_msg = pub_sensor_raw_ft_.allocate()) {
01034 wrench_msg->header.stamp = time;
01035 wrench_msg->header.frame_id = force_torque_frame_;
01036 tf::wrenchEigenToMsg(F_sensor_raw, wrench_msg->wrench);
01037 pub_sensor_raw_ft_.publish(wrench_msg);
01038 }
01039
01040 if (wrench_msg = pub_f_cmd_.allocate()) {
01041 wrench_msg->header.stamp = time;
01042 wrench_msg->header.frame_id = tip_name_;
01043 tf::wrenchEigenToMsg(F_cmd, wrench_msg->wrench);
01044 pub_f_cmd_.publish(wrench_msg);
01045 }
01046
01047 if (wrench_msg = pub_f_err_.allocate()) {
01048 wrench_msg->header.stamp = time;
01049 wrench_msg->header.frame_id = tip_name_;
01050 tf::wrenchEigenToMsg(F_err, wrench_msg->wrench);
01051 pub_f_err_.publish(wrench_msg);
01052 }
01053
01054 if (wrench_msg = pub_k_effective_.allocate()) {
01055 wrench_msg->header.stamp = time;
01056 wrench_msg->header.frame_id = tip_name_;
01057 tf::wrenchEigenToMsg(K_effective_, wrench_msg->wrench);
01058 pub_k_effective_.publish(wrench_msg);
01059 }
01060
01061 if (q_msg = pub_tau_.allocate()) {
01062 for (size_t i = 0; i < Joints; ++i)
01063 q_msg->data[i] = tau[i];
01064 pub_tau_.publish(q_msg);
01065 }
01066
01067 if (q_msg = pub_qdot_.allocate()) {
01068 for (size_t i = 0; i < Joints; ++i)
01069 q_msg->data[i] = qdot[i];
01070 pub_qdot_.publish(q_msg);
01071 }
01072
01073 StateMsg::Ptr state_msg;
01074 if (state_msg = pub_state_.allocate()) {
01075 state_msg->header.stamp = time;
01076 state_msg->x.header.stamp = time;
01077 tf::poseEigenToMsg(x, state_msg->x.pose);
01078 state_msg->x_desi.header.stamp = time;
01079 tf::poseEigenToMsg(x_desi_, state_msg->x_desi.pose);
01080 state_msg->x_desi_filtered.header.stamp = time;
01081 tf::poseEigenToMsg(x_desi_filtered_, state_msg->x_desi_filtered.pose);
01082 tf::twistEigenToMsg(x_err, state_msg->x_err);
01083 tf::twistEigenToMsg(xdot, state_msg->xd);
01084 tf::twistEigenToMsg(xdot_desi, state_msg->xd_desi);
01085 tf::wrenchEigenToMsg(F_motion, state_msg->F);
01086 tf::matrixEigenToMsg(J, state_msg->J);
01087 tf::matrixEigenToMsg(N, state_msg->N);
01088 for (size_t j = 0; j < Joints; ++j) {
01089 state_msg->tau_pose[j] = tau_pose[j];
01090 state_msg->tau_posture[j] = tau_posture[j];
01091 state_msg->tau[j] = tau[j];
01092 }
01093 state_msg->stiffness = stiffness;
01094 state_msg->compliance = compliance;
01095 state_msg->Df = Df / res_position_;
01096 state_msg->Dx = Dx / res_force_;
01097 state_msg->df = df[2];
01098 state_msg->dx = dx[2];
01099 pub_state_.publish(state_msg);
01100 }
01101 }
01102
01103 }
01104
01105 }
01106
01107 PLUGINLIB_DECLARE_CLASS(hrl_pr2_force_ctrl, HybridForceController, hrl_pr2_force_ctrl::HybridForceController, pr2_controller_interface::Controller)
01108