00001 #include "kinton_arm_task_priority_control_alg_node.h"
00002
00003 using namespace KDL;
00004 using namespace Eigen;
00005 using namespace std;
00006
00007 KintonArmTaskPriorityControlAlgNode::KintonArmTaskPriorityControlAlgNode(void) :
00008 algorithm_base::IriBaseAlgorithm<KintonArmTaskPriorityControlAlgorithm>()
00009 {
00010
00011 this->loop_rate_ = 100;
00012
00013 this->init_ = true;
00014
00015
00016 this->time_ = ros::Time::now();
00017
00018 this->cam_vel_ = MatrixXd::Zero(6,1);
00019 this->v_rollpitch_ = MatrixXd::Zero(2,1);
00020
00021 this->num_joints_ = 0;
00022 this->cam_vel_ok_ = false;
00023 this->v_rollpitch_ = MatrixXd::Zero(2,1);
00024 this->q_rollpitch_ = MatrixXd::Zero(2,1);
00025 this->gain_sec_task_ = MatrixXd::Zero(3,1);
00026
00027 this->public_node_handle_.param<bool>("arm_unina", this->arm_unina_, "true" );
00028 this->public_node_handle_.param<bool>("arm_catec", this->arm_catec_, "false" );
00029 this->public_node_handle_.param<bool>("enable_sec_task", this->enable_sec_task_, "true" );
00030
00031 ros::NodeHandle nh;
00032
00033 string tip_name, root_name, optical_name;
00034 string xml_string;
00035 Tree tree;
00036 string urdf_xml,full_urdf_xml;
00037 nh.param("urdf_xml",urdf_xml,string("robot_description"));
00038 nh.searchParam(urdf_xml,full_urdf_xml);
00039 ROS_DEBUG("Reading xml file from parameter server\n");
00040 if (!nh.getParam(full_urdf_xml, xml_string)){
00041 ROS_ERROR("Could not load the xml from parameter server: %s\n", urdf_xml.c_str());
00042 }
00043 if (!nh.getParam("root_name", root_name)){
00044 ROS_ERROR("No root name found on parameter server");
00045 }
00046 if (!nh.getParam("tip_name", tip_name)){
00047 ROS_ERROR("No tip name found on parameter server");
00048 }
00049
00050
00051 if (!kdl_parser::treeFromString(xml_string, tree)){
00052 ROS_ERROR("Could not initialize tree object");
00053 }
00054 if (!tree.getChain(root_name, tip_name, this->kdl_chain_)){
00055 ROS_ERROR("Could not initialize kdl_chain object");
00056 }
00057
00058
00059 urdf::Model robot_model;
00060 if (!robot_model.initString(xml_string)) {
00061 ROS_ERROR("Could not initialize robot model");
00062 }
00063 if (!readJoints(robot_model,root_name,tip_name)) {
00064 ROS_ERROR("Could not read information about the joints");
00065 }
00066
00067 if (!nh.getParam("optical_frame_id", optical_name)){
00068 ROS_ERROR("No camera optical frame name found on parameter server");
00069 }
00070
00071
00072 this->Tcam_in_tip_ = get_HT_cam_in_tip(optical_name,tip_name);
00073
00074
00075 this->joints_pub_publisher_ = this->public_node_handle_.advertise<sensor_msgs::JointState>("arm_joints_states", 10);
00076 this->quad_vel_publisher_ = this->public_node_handle_.advertise<geometry_msgs::Twist>("cmd_vel", 10);
00077
00078
00079 this->cam_vel_subscriber_ = this->public_node_handle_.subscribe("cam_vel", 100, &KintonArmTaskPriorityControlAlgNode::cam_vel_callback, this);
00080 this->odom_subscriber_ = this->public_node_handle_.subscribe("odom", 100, &KintonArmTaskPriorityControlAlgNode::odom_callback, this);
00081 this->input_tag_subscriber_ = this->public_node_handle_.subscribe("input_tag", 10, &KintonArmTaskPriorityControlAlgNode::input_tag_callback, this);
00082
00083
00084
00085
00086
00087
00088
00089
00090 }
00091
00092 KintonArmTaskPriorityControlAlgNode::~KintonArmTaskPriorityControlAlgNode(void)
00093 {
00094
00095 }
00096
00097 void KintonArmTaskPriorityControlAlgNode::mainNodeThread(void)
00098 {
00099
00100
00101 if (this->init_)
00102 {
00103 this->time_last_=this->time_;
00104 init_arm();
00105
00106 this->vel_ = MatrixXd::Zero(6+this->num_joints_,1);
00107 this->init_=false;
00108 }
00109
00110 this->dt_=(this->time_-this->time_last_).toSec();
00111
00112
00113 if (this->cam_vel_ok_ && this->activate_){
00114
00115 this->alg_.lock();
00116 this->task_priority_ctrl_.task_priority_ctrl(this->cam_vel_,this->arm_unina_,
00117 this->arm_catec_,this->enable_sec_task_,
00118 this->Tcam_in_tip_,this->Ttag_in_cam_,
00119 this->lambda_robot_,this->gain_sec_task_,
00120 this->q_rollpitch_,this->v_rollpitch_,
00121 this->kdl_chain_,this->joint_info_,this->dt_,this->q_,this->vel_);
00122 this->alg_.unlock();
00123 }
00124 else
00125 {
00126 this->init_ = true;
00127 }
00128
00129
00130
00131
00132 for (int jj=0; jj<this->num_joints_; ++jj){
00133 this->JointState_msg_.position[jj]=this->q_(6+jj,0);
00134 this->JointState_msg_.velocity[jj]=this->vel_(6+jj);
00135 this->JointState_msg_.effort[jj]=1;
00136 }
00137
00138
00139 this->Twist_msg_.linear.x = this->vel_(0,0);
00140 this->Twist_msg_.linear.y = this->vel_(1,0);
00141 this->Twist_msg_.linear.z = this->vel_(2,0);
00142 this->Twist_msg_.angular.x = this->vel_(3,0);
00143 this->Twist_msg_.angular.y = this->vel_(4,0);
00144 this->Twist_msg_.angular.z = this->vel_(5,0);
00145
00146
00147 if (this->arm_unina_){
00148 this->Twist_msg_.linear.z= this->Twist_msg_.linear.z + 0.15;
00149 }
00150 else if (this->arm_catec_){
00151 this->Twist_msg_.linear.z= this->Twist_msg_.linear.z + 0;
00152 }
00153
00154
00155
00156
00157
00158
00159 this->quad_vel_publisher_.publish(this->Twist_msg_);
00160 this->joints_pub_publisher_.publish(this->JointState_msg_);
00161 }
00162
00163
00164 void KintonArmTaskPriorityControlAlgNode::cam_vel_callback(const geometry_msgs::TwistWithCovariance::ConstPtr& msg)
00165 {
00166
00167
00168
00169 this->cam_vel_mutex_.enter();
00170
00171 if (msg->covariance[0]<1000 && this->activate_)
00172 {
00173 this->cam_vel_(0,0) = msg->twist.linear.x;
00174 this->cam_vel_(1,0) = msg->twist.linear.y;
00175 this->cam_vel_(2,0) = msg->twist.linear.z;
00176 this->cam_vel_(3,0) = msg->twist.angular.x;
00177 this->cam_vel_(4,0) = msg->twist.angular.y;
00178 this->cam_vel_(5,0) = msg->twist.angular.z;
00179
00180 this->cam_vel_ok_ = true;
00181 }
00182 else
00183 {
00184 this->cam_vel_ = MatrixXd::Zero(6,1);
00185 this->cam_vel_ok_ = false;
00186 }
00187
00188
00189 this->cam_vel_mutex_.exit();
00190 }
00191
00192 void KintonArmTaskPriorityControlAlgNode::odom_callback(const nav_msgs::Odometry::ConstPtr& msg)
00193 {
00194
00195
00196
00197 this->odom_mutex_.enter();
00198
00199
00200
00201 this->v_rollpitch_ = MatrixXd::Zero(2,1);
00202 this->q_rollpitch_ = MatrixXd::Zero(2,1);
00203
00204 if (msg->twist.covariance[0]<100)
00205 {
00206
00207 if (!isnan(msg->twist.twist.angular.x) && !isnan(msg->twist.twist.angular.y)){
00208 this->v_rollpitch_(0,0) = msg->twist.twist.angular.x;
00209 this->v_rollpitch_(1,0) = msg->twist.twist.angular.y;
00210 }
00211
00212 if (!isnan(msg->pose.pose.orientation.x)){
00213
00214
00215 tf::Quaternion qt;
00216 double quad_roll, quad_pitch, quad_yaw;
00217 tf::quaternionMsgToTF(msg->pose.pose.orientation, qt);
00218 tf::Matrix3x3(qt).getRPY(quad_roll, quad_pitch, quad_yaw);
00219
00220 this->q_rollpitch_(0,0) = quad_roll;
00221 this->q_rollpitch_(1,0) = quad_pitch;
00222 }
00223
00224 }
00225
00226 this->v_rollpitch_ = MatrixXd::Zero(2,1);
00227
00228
00229 this->odom_mutex_.exit();
00230 }
00231
00232 void KintonArmTaskPriorityControlAlgNode::input_tag_callback(const ar_pose::ARMarkers::ConstPtr& msg)
00233 {
00234 this->input_tag_mutex_.enter();
00235
00236 this->time_last_ = this->time_;
00237
00238
00239 if (msg->markers.empty()){
00240 this->Ttag_in_cam_ = Matrix4d::Zero();
00241 this->Ttag_in_cam_.block(0,0,3,3) = Matrix3d::Identity();
00242 this->Ttag_in_cam_(3,3) = 1.0;
00243 this->time_ = ros::Time::now();
00244 this->init_ = true;
00245 ROS_INFO("No tag detected");
00246 }
00247
00248 if ((!msg->markers.empty()) && ((!std::isnan(msg->markers[0].pose.pose.orientation.x) && std::isfinite(msg->markers[0].pose.pose.orientation.x)) || (!std::isnan(msg->markers[1].pose.pose.orientation.x) && std::isfinite(msg->markers[1].pose.pose.orientation.x)))){
00249
00250 this->time_ = msg->markers.back().header.stamp;
00251 this->pose_ = msg->markers.back().pose.pose;
00252
00253 tf::Transform tf_pose;
00254
00255 double x,y,z,yaw,pitch,roll;
00256 tf::poseMsgToTF(this->pose_, tf_pose);
00257 tf_pose.getBasis().getRPY(roll,pitch,yaw);
00258
00259 Matrix3d Rot;
00260
00261 Rot = AngleAxisd(yaw, Vector3d::UnitZ()) \
00262 * AngleAxisd(pitch, Vector3d::UnitY()) \
00263 * AngleAxisd(roll, Vector3d::UnitX());
00264
00265 x = this->pose_.position.x;
00266 y = this->pose_.position.y;
00267 z = this->pose_.position.z;
00268
00269 this->Ttag_in_cam_=Matrix4d::Zero();
00270 if (!std::isnan(Rot(0,0))) this->Ttag_in_cam_.block(0,0,3,3)=Rot;
00271
00272 this->Ttag_in_cam_.block(0,3,3,1) << x, y, z;
00273 this->Ttag_in_cam_.row(3) << 0, 0, 0, 1;
00274 }
00275
00276 this->input_tag_mutex_.exit();
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 Matrix4d KintonArmTaskPriorityControlAlgNode::getTransform(const string& frame1, const string& frame2)
00286 {
00287
00288 tf::TransformListener listener;
00289 tf::StampedTransform transform;
00290
00291 try {
00292
00293 listener.lookupTransform(frame1,frame2, ros::Time(0), transform);
00294 }
00295 catch (tf::TransformException ex) {
00296
00297 }
00298
00299 double roll,pitch,yaw;
00300 tf::Quaternion q = transform.getRotation();
00301 tf::Matrix3x3(q).getRPY(roll,pitch,yaw);
00302
00303 Matrix3d Rot;
00304 Rot = AngleAxisd(yaw, Vector3d::UnitZ()) \
00305 * AngleAxisd(pitch, Vector3d::UnitY()) \
00306 * AngleAxisd(roll, Vector3d::UnitX());
00307 Matrix4d T = Matrix4d::Zero();
00308
00309 T.block(0,0,3,3) = Rot;
00310 T(0,3) = transform.getOrigin().x();
00311 T(1,3) = transform.getOrigin().y();
00312 T(2,3) = transform.getOrigin().z();
00313 T(3,3) = 1.0;
00314
00315
00316 return T;
00317 }
00318
00319 void KintonArmTaskPriorityControlAlgNode::init_arm()
00320 {
00321
00322 this->q_ = MatrixXd::Zero(6+this->num_joints_,1);
00323
00324
00325 if (this->arm_unina_ && !this->arm_catec_){
00326
00327
00328
00329
00330
00331
00332
00333
00334 this->q_ << 0, 0, 2.5, 0, 0, 0, 0, 0, 3.1415, 3.1415, 0;
00335 }
00336
00337 else if (this->arm_catec_ && !this->arm_unina_){
00338
00339
00340 this->q_ << 0, 0, 2.5, 0, 0, 0, 0, 2, -2, 0, 1.5707, 0;
00341 }
00342 else if ((this->arm_unina_ && this->arm_catec_) || (!this->arm_unina_ && !this->arm_catec_)){
00343 ROS_ERROR("Wrong arms configuration");
00344 }
00345
00346 this->JointState_msg_.header.stamp=ros::Time::now();
00347 this->JointState_msg_.header.frame_id="";
00348 this->JointState_msg_.name.resize(this->num_joints_);
00349 this->JointState_msg_.position.resize(this->num_joints_);
00350 this->JointState_msg_.velocity.resize(this->num_joints_);
00351 this->JointState_msg_.effort.resize(this->num_joints_);
00352 for (int ii = 0; ii < this->num_joints_; ++ii)
00353 {
00354 string quad_str="quadrotor::";
00355 stringstream joint_name;
00356 joint_name << quad_str << this->joint_info_.at(ii).link_child;
00357 this->JointState_msg_.name[ii]=joint_name.str();
00358 }
00359 }
00360
00361 void KintonArmTaskPriorityControlAlgNode::node_config_update(Config &config, uint32_t level)
00362 {
00363 this->alg_.lock();
00364 this->activate_=config.sim_activate;
00365 double lambda_quadrotor=config.lambda_quadrotor;
00366 double lambda_arm=config.lambda_arm;
00367 this->enable_sec_task_ = config.enable_sec_task;
00368
00369 this->gain_sec_task_(1,0) = config.gain_sec_task_CoG;
00370 this->gain_sec_task_(2,0) = config.gain_sec_task_jntlim;
00371
00372 this->lambda_robot_ = MatrixXd::Zero(4+this->num_joints_,1);
00373
00374 for (int i = 0; i < 4; ++i)
00375 {
00376 this->lambda_robot_(i,0)=lambda_quadrotor;
00377 }
00378 for (int i = 0; i < this->num_joints_; ++i)
00379 {
00380 this->lambda_robot_(4+i,0)=lambda_arm;
00381 }
00382
00383 this->alg_.unlock();
00384 }
00385
00386 void KintonArmTaskPriorityControlAlgNode::addNodeDiagnostics(void)
00387 {
00388 }
00389
00390
00391 int main(int argc,char *argv[])
00392 {
00393 return algorithm_base::main<KintonArmTaskPriorityControlAlgNode>(argc, argv, "kinton_arm_task_priority_control_alg_node");
00394 }
00395
00396 bool KintonArmTaskPriorityControlAlgNode::readJoints(urdf::Model &robot_model,const string& root_name,const string& tip_name) {
00397
00398 int num_joints = 0;
00399
00400 boost::shared_ptr<const urdf::Link> link = robot_model.getLink(tip_name);
00401 boost::shared_ptr<const urdf::Joint> joint;
00402
00403 while (link && link->name != root_name) {
00404 joint = robot_model.getJoint(link->parent_joint->name);
00405 if (!joint) {
00406 ROS_ERROR("Could not find joint: %s",link->parent_joint->name.c_str());
00407 return false;
00408 }
00409 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00410
00411 num_joints++;
00412 }
00413 link = robot_model.getLink(link->getParent()->name);
00414 }
00415
00416 this->num_joints_=num_joints;
00417 this->joint_info_.resize(num_joints);
00418
00419 link = robot_model.getLink(tip_name);
00420 int ii = 0;
00421 while (link && ii < num_joints) {
00422 joint = robot_model.getJoint(link->parent_joint->name);
00423 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00424
00425
00426 float lower, upper;
00427 if ( joint->type != urdf::Joint::CONTINUOUS ) {
00428 lower = joint->limits->lower;
00429 upper = joint->limits->upper;
00430 } else {
00431 lower = -M_PI;
00432 upper = M_PI;
00433 }
00434 int index = num_joints - ii -1;
00435 this->joint_info_.at(index).joint_min = lower;
00436 this->joint_info_.at(index).joint_max = upper;
00437 this->joint_info_.at(index).link_child = link->name;
00438 this->joint_info_.at(index).link_parent = link->getParent()->name;
00439 ii++;
00440 }
00441 link = robot_model.getLink(link->getParent()->name);
00442 }
00443 return true;
00444 }
00445
00446 Matrix4d KintonArmTaskPriorityControlAlgNode::get_HT_cam_in_tip(const string& cam_frame, const string& tip_frame)
00447 {
00448 Matrix4d Tcam_in_tip = Matrix4d::Zero();
00449
00450 tf::TransformListener listener;
00451 tf::StampedTransform transform;
00452 try{
00453 listener.waitForTransform(tip_frame, cam_frame, ros::Time(0), ros::Duration(1.0));
00454 listener.lookupTransform(tip_frame, cam_frame, ros::Time(0), transform);
00455 }
00456 catch (tf::TransformException ex){
00457 ROS_ERROR("%s",ex.what());
00458 }
00459
00460 double x,y,z,roll,pitch,yaw;
00461 transform.getBasis().getRPY(roll, pitch, yaw);
00462
00463 x=transform.getOrigin().x();
00464 y=transform.getOrigin().y();
00465 z=transform.getOrigin().z();
00466
00467 Matrix3d Rot;
00468
00469 Rot = AngleAxisd(yaw, Vector3d::UnitZ()) \
00470 * AngleAxisd(pitch, Vector3d::UnitY()) \
00471 * AngleAxisd(roll, Vector3d::UnitX());
00472
00473 Tcam_in_tip.block(0,0,3,3) = Rot;
00474 Tcam_in_tip(0,3) = x;
00475 Tcam_in_tip(1,3) = y;
00476 Tcam_in_tip(2,3) = z;
00477 Tcam_in_tip(3,3) = 1;
00478
00479 return Tcam_in_tip;
00480 }