cob_articulation.cpp
Go to the documentation of this file.
00001 
00028 #include <ros/ros.h>
00029 #include <math.h>
00030 #include <cob_path_broadcaster/cob_articulation.h>
00031 #include <tf/transform_broadcaster.h>
00032 #include <tinyxml.h>
00033 #include <std_msgs/Float64.h>
00034 #include <geometry_msgs/Pose.h>
00035 #include <visualization_msgs/Marker.h>
00036 #include <vector>
00037 #include <kdl_conversions/kdl_msg.h>
00038 #include <std_srvs/Empty.h>
00039 #include <cob_srvs/SetString.h>
00040 #include <algorithm>
00041 #include "ros/package.h"
00042 
00043 bool CobArticulation::initialize()
00044 {
00045         ros::NodeHandle nh_articulation("cob_articulation");
00046         
00047         bool success=true;
00049         if (nh_articulation.hasParam("update_rate"))
00050         {
00051                 nh_articulation.getParam("update_rate", update_rate_);
00052         }
00053         else{ update_rate_=68; }
00054         
00055         if (nh_articulation.hasParam("file_name"))
00056         {
00057                 nh_articulation.getParam("file_name", fileName_);
00058         }else{ success = false; }
00059         
00060         if (nh_articulation.hasParam("reference_frame"))
00061         {
00062                 nh_articulation.getParam("reference_frame", referenceFrame_);
00063         }else{ success = false; }
00064         
00065         if (nh_articulation.hasParam("target_frame"))
00066         {
00067                 nh_articulation.getParam("target_frame", targetFrame_);
00068         }else{ success = false; }
00069         
00070         if (nh_articulation.hasParam("endeffector_frame"))
00071         {
00072                 nh_articulation.getParam("endeffector_frame", endeffectorFrame_);
00073         }else{ success = false; }
00074         
00075         
00076         stringPath_ = ros::package::getPath("cob_path_broadcaster"); 
00077         stringPath_ = stringPath_+"/movement/"+fileName_;       
00078         charPath_ = stringPath_.c_str();
00079         
00080         marker1_=0;
00081         marker2_=0;
00082         
00083         vis_pub_ = nh_articulation.advertise<visualization_msgs::Marker>( "visualization_marker", 0 );
00084         speed_pub_ = nh_articulation.advertise<std_msgs::Float64> ("debug/linear_vel", 1);
00085         accl_pub_ = nh_articulation.advertise<std_msgs::Float64> ("debug/linear_accl", 1);
00086         path_pub_ = nh_articulation.advertise<std_msgs::Float64> ("debug/linear_path", 1);
00087         jerk_pub_ = nh_articulation.advertise<std_msgs::Float64> ("debug/linear_jerk", 1);
00088         
00089         ROS_WARN("Waiting for Services...");
00090         success = ros::service::waitForService("start_tracking");
00091         success = ros::service::waitForService("stop_tracking");
00092         startTracking_ = nh_.serviceClient<cob_srvs::SetString>("start_tracking");
00093         stopTracking_ = nh_.serviceClient<std_srvs::Empty>("stop_tracking");
00094         ROS_INFO("...done!");
00095         
00096         if(success){
00097                 return true;
00098         }else{
00099                 return false;
00100         }
00101 }
00102 
00103 
00104 
00105 void CobArticulation::load()
00106 {       
00107         stop_tracking();
00108         ROS_INFO("Stopping current tracking");
00109         
00110         std::vector <geometry_msgs::Pose> posVec;
00111         geometry_msgs::Pose pose,actualTcpPose,start,end;
00112         tf::Quaternion q;
00113         tf::Transform trans;
00114         double roll_actual,pitch_actual,yaw_actual,roll,pitch,yaw,quat_x,quat_y,quat_z,quat_w;
00115         double x,y,z,x_new,y_new,z_new,x_center,y_center,z_center;
00116         double r,holdTime,vel,accl,startAngle,endAngle;
00117         std::string profile,rotateOnly;
00118         bool justRotate;
00119         
00120         TiXmlDocument doc(charPath_);
00121         bool loadOkay = doc.LoadFile();
00122         if (loadOkay)
00123         {
00124                 ROS_INFO("load okay");
00125                 start_tracking();
00126 
00127                 TiXmlHandle docHandle( &doc );
00128                 TiXmlElement* child = docHandle.FirstChild( "Movement" ).FirstChild( "Move" ).ToElement();
00129                         
00130                 std::string movement;
00131                 
00132                 for( child; child; child=child->NextSiblingElement() )
00133                 {               
00134                         movement = child->Attribute( "move");
00135 
00136                         if ("move_lin" == movement){
00137                                 ROS_INFO("move_linear");
00138                                 
00139                                 // Read Attributes
00140                                 x_new = atof(child->Attribute( "x"));
00141                                 y_new = atof(child->Attribute( "y"));
00142                                 z_new = atof(child->Attribute( "z"));
00143                                 roll = atof(child->Attribute( "roll"));
00144                                 pitch = atof(child->Attribute( "pitch"));
00145                                 yaw = atof(child->Attribute( "yaw"));
00146                                 vel = atof(child->Attribute( "vel"));
00147                                 accl = atof(child->Attribute( "accl"));
00148                                 profile = child->Attribute( "profile");
00149                                 rotateOnly = child->Attribute( "RotateOnly");
00150                                 
00151                                 roll*=M_PI/180;
00152                                 pitch*=M_PI/180;
00153                                 yaw*=M_PI/180;
00154                                 
00155                                 if(rotateOnly == "Yes")
00156                                         justRotate=true;
00157                                 else
00158                                         justRotate=false;
00159 
00160                                 
00161                                 // Transform RPY to Quaternion
00162                                 q.setRPY(roll,pitch,yaw);
00163                                 trans.setRotation(q);
00164                                 
00165                                 // Define End Pose
00166                                 end.position.x = x_new;
00167                                 end.position.y = y_new;
00168                                 end.position.z = z_new;
00169                                 end.orientation.x = trans.getRotation()[0];
00170                                 end.orientation.y = trans.getRotation()[1];
00171                                 end.orientation.z = trans.getRotation()[2];
00172                                 end.orientation.w = trans.getRotation()[3];
00173                                 
00174                                 PoseToRPY(actualTcpPose,roll,pitch,yaw);
00175                                 ROS_INFO("..........................actualTcpPose roll: %f pitch: %f yaw: %f",roll,pitch,yaw);
00176                                 // Interpolate the path
00177                                 linear_interpolation(&posVec,actualTcpPose,end,vel,accl,profile,justRotate);
00178                                 
00179                                 // Broadcast the linearpath
00180                                 pose_path_broadcaster(&posVec);
00181                                 
00182                                 actualTcpPose=end;
00183                                 PoseToRPY(end,roll,pitch,yaw);
00184                                 ROS_INFO("..........................endpose roll: %f pitch: %f yaw: %f",roll,pitch,yaw);
00185 
00186                         }
00187                         
00188                         if("move_ptp" == movement){
00189                                 ROS_INFO("move_ptp");
00190                                 x_new = atof(child->Attribute( "x"));
00191                                 y_new = atof(child->Attribute( "y"));
00192                                 z_new = atof(child->Attribute( "z"));
00193                                 roll = atof(child->Attribute( "roll"));
00194                                 pitch = atof(child->Attribute( "pitch"));
00195                                 yaw = atof(child->Attribute( "yaw"));
00196                                 
00197                                 roll*=M_PI/180;
00198                                 pitch*=M_PI/180;
00199                                 yaw*=M_PI/180;
00200                                 
00201                                 // Transform RPY to Quaternion
00202                                 q.setRPY(roll,pitch,yaw);
00203                                 trans.setRotation(q);
00204                                 
00205                                 pose.position.x = x_new;
00206                                 pose.position.y = y_new;
00207                                 pose.position.z = z_new;
00208                                 pose.orientation.x = trans.getRotation()[0];
00209                                 pose.orientation.y = trans.getRotation()[1];
00210                                 pose.orientation.z = trans.getRotation()[2];
00211                                 pose.orientation.w = trans.getRotation()[3];
00212                                 
00213                                 move_ptp(pose,0.03);
00214                                 
00215                                 actualTcpPose = pose;
00216                                 PoseToRPY(actualTcpPose,roll,pitch,yaw);
00217                                 ROS_INFO("PTP End Orientation: %f %f %f",roll,pitch,yaw);
00218                         }
00219                         if("move_circ" == movement){
00220                                 ROS_INFO("move_circ");
00221                                 
00222                                 x_center        = atof(child->Attribute( "x_center"));
00223                                 y_center        = atof(child->Attribute( "y_center"));
00224                                 z_center        = atof(child->Attribute( "z_center"));
00225                                 roll            = atof(child->Attribute( "roll_center"));
00226                                 pitch           = atof(child->Attribute( "pitch_center"));
00227                                 yaw             = atof(child->Attribute( "yaw_center"));
00228                                 r                       = atof(child->Attribute( "r"));
00229                                 startAngle  = atof(child->Attribute( "startangle"));
00230                                 endAngle        = atof(child->Attribute( "endangle"));
00231                                 vel                     = atof(child->Attribute( "vel"));
00232                                 accl            = atof(child->Attribute( "accl"));
00233                                 profile         = child->Attribute( "profile");
00234 
00235 
00236                                 pose = getEndeffectorPose();
00237                                 quat_x = pose.orientation.x;
00238                                 quat_y = pose.orientation.y;
00239                                 quat_z = pose.orientation.z;
00240                                 quat_w = pose.orientation.w;
00241 
00242                                 int marker3=0;
00243                                 
00244                                 showDot(x_center,y_center,z_center,marker3,1.0,0,0,"Center_point");
00245                                 circular_interpolation(&posVec,x_center,y_center,z_center,roll,pitch,yaw,startAngle,endAngle,r,vel,accl,profile);
00246                                 
00247                                 move_ptp(posVec.at(0),0.03);
00248                                 pose_path_broadcaster(&posVec); 
00249                                 actualTcpPose=posVec.at(posVec.size()-1);
00250                         }
00251                 
00252                         
00253                         if("hold" == movement){         
00254                                 ROS_INFO("Hold position");
00255                                 holdTime = atof(child->Attribute( "time"));
00256                                 ros::Timer timer = nh_.createTimer(ros::Duration(holdTime), &CobArticulation::timerCallback, this);
00257                                 hold_=true;
00258                                 PoseToRPY(actualTcpPose,roll,pitch,yaw);
00259                                 ROS_INFO("Hold Orientation: %f %f %f",roll,pitch,yaw);
00260                                 hold_position(actualTcpPose);
00261                         }
00262                         posVec.clear();
00263                 }       
00264         }else{
00265                 ROS_WARN("Error loading File");
00266         }
00267         stop_tracking();
00268 }
00269 
00270 // Pseudo PTP
00271 void CobArticulation::move_ptp(geometry_msgs::Pose targetPose, double epsilon){
00272         reached_pos_=false;
00273         int reached_pos_counter=0;
00274         double ro,pi,ya;
00275         ros::Rate rate(update_rate_);
00276         ros::Time now;
00277         tf::StampedTransform stampedTransform;
00278         tf::Quaternion q;
00279         bool transformed=false;
00280         
00281         while(ros::ok()){
00282                 now = ros::Time::now();
00283 
00284                 // Linearkoordinaten
00285                 transform_.setOrigin( tf::Vector3(targetPose.position.x,targetPose.position.y,targetPose.position.z) );
00286         
00287                 q = tf::Quaternion(targetPose.orientation.x,targetPose.orientation.y,targetPose.orientation.z,targetPose.orientation.w);
00288                 transform_.setRotation(q);
00289 
00290                 // Send br Frame
00291                 br_.sendTransform(tf::StampedTransform(transform_, now, referenceFrame_, targetFrame_));
00292                 
00293                 // Get transformation
00294                 try{
00295                 listener_.waitForTransform(targetFrame_,endeffectorFrame_, now, ros::Duration(0.5));
00296                 listener_.lookupTransform(targetFrame_,endeffectorFrame_, now, stampedTransform);
00297                 }
00298                 catch (tf::TransformException &ex) {
00299                 ROS_ERROR("%s",ex.what());
00300                 }
00301                 
00302                 // Get current RPY out of quaternion
00303                 tf::Quaternion quatern = stampedTransform.getRotation();
00304                 tf::Matrix3x3(quatern).getRPY(ro,pi,ya);
00305                                 
00306                                 
00307                 // Wait for arm_7_link to be in position
00308                 if(epsilon_area(stampedTransform.getOrigin().x(), stampedTransform.getOrigin().y(), stampedTransform.getOrigin().z(),ro,pi,ya,epsilon)){
00309                         reached_pos_counter++;  // Count up if end effector position is in the epsilon area to avoid wrong values
00310                 }
00311                 
00312                 if(reached_pos_counter>=50){
00313                         reached_pos_=true;
00314                 }
00315                 
00316                 if(reached_pos_==true){ // Cancle while loop
00317                         break;
00318                 }
00319                 rate.sleep();
00320                 ros::spinOnce();
00321         }
00322 }
00323 
00324 
00325 
00326 void CobArticulation::pose_path_broadcaster(std::vector <geometry_msgs::Pose> *poseVector){
00327         ros::Rate rate(update_rate_);
00328         ros::Time now;
00329         tf::Quaternion q;
00330         
00331         double T_IPO=pow(update_rate_,-1);
00332 
00333         
00334         for(int i=0; i<poseVector->size()-1; i++){
00335                 now = ros::Time::now();
00336                 
00337         
00338                 // Linearkoordinaten
00339                 transform_.setOrigin(tf::Vector3(poseVector->at(i).position.x, poseVector->at(i).position.y, poseVector->at(i).position.z));
00340                 
00341                 q = tf::Quaternion(poseVector->at(i).orientation.x,poseVector->at(i).orientation.y,poseVector->at(i).orientation.z,poseVector->at(i).orientation.w);
00342                 
00343                 transform_.setRotation(q);   
00344                 
00345                 showMarker(tf::StampedTransform(transform_, ros::Time::now(), referenceFrame_, targetFrame_),marker1_, 0 , 1.0 , 0 ,"goalFrame");
00346                 //showMarker(stampedTransform_,marker2_, 1.0 , 0 , 0 , "TCP");                          
00347                 
00348                 br_.sendTransform(tf::StampedTransform(transform_, ros::Time::now(), referenceFrame_, targetFrame_));
00349                 
00350 
00351                 marker1_++;
00352                 //marker2_++;
00353                 
00354                 ros::spinOnce();
00355                 rate.sleep();
00356         }
00357         
00358 }
00359 
00360 
00361 void CobArticulation::hold_position(geometry_msgs::Pose holdPose)
00362 {       
00363         ros::Rate rate(update_rate_);
00364         ros::Time now;
00365         tf::Quaternion q;
00366         
00367         while(hold_){
00368                 now = ros::Time::now();
00369                 
00370                 // Linearcoordinates
00371                 transform_.setOrigin( tf::Vector3(holdPose.position.x,holdPose.position.y,holdPose.position.z) );
00372         
00373                 // RPY Angles
00374                 q = tf::Quaternion(holdPose.orientation.x,holdPose.orientation.y,holdPose.orientation.z,holdPose.orientation.w);
00375                 transform_.setRotation(q);
00376         
00377                 br_.sendTransform(tf::StampedTransform(transform_, ros::Time::now(), referenceFrame_, targetFrame_));
00378                 ros::spinOnce();
00379                 rate.sleep();
00380         }
00381 }
00382 
00383 
00384 // Helper Functions 
00385 //--------------------------------------------------------------------------------------------------------------
00386 void CobArticulation::linear_interpolation(     std::vector <geometry_msgs::Pose> *poseVector,
00387                                                                                         geometry_msgs::Pose start, geometry_msgs::Pose end,
00388                                                                                         double VelMax, double AcclMax, std::string profile,bool justRotate) 
00389 {     
00390         geometry_msgs::Pose pose;
00391         tf::Quaternion q;
00392         tf::Transform transform;
00393         std::vector<double> pathMatrix[4];
00394         std::vector<double> linearPath,rollPath,pitchPath,yawPath;
00395         double start_roll, start_pitch, start_yaw;
00396         double end_roll, end_pitch, end_yaw;
00397         double Se = sqrt(pow((end.position.x-start.position.x),2)+pow((end.position.y-start.position.y),2)+pow((end.position.z-start.position.z),2));
00398         
00399         // Convert Quaternions into RPY Angles for start and end pose
00400         q = tf::Quaternion(start.orientation.x, start.orientation.y, start.orientation.z, start.orientation.w);
00401         tf::Matrix3x3(q).getRPY(start_roll,start_pitch,start_yaw);      
00402         q = tf::Quaternion(end.orientation.x, end.orientation.y, end.orientation.z, end.orientation.w);
00403         tf::Matrix3x3(q).getRPY(end_roll,end_pitch,end_yaw);    
00404         
00405         // Calculate path length for the angular movement
00406         double Se_roll,Se_pitch,Se_yaw;
00407         Se_roll = end_roll - start_roll;
00408         Se_pitch = end_pitch - start_pitch;
00409         Se_yaw = end_yaw - start_yaw;
00410         
00411         // Calculate path for each Angle
00412         calculateProfileForAngularMovements(pathMatrix,Se,Se_roll,Se_pitch,Se_yaw,start_roll,start_pitch,start_yaw,VelMax,AcclMax,profile,justRotate);
00413         
00414         linearPath=pathMatrix[0];
00415         rollPath=pathMatrix[1];
00416         pitchPath=pathMatrix[2];
00417         yawPath=pathMatrix[3];
00418         
00419         /*
00420         for(int i=0;i<linearPath.size();i++){
00421                 ROS_INFO("linearPath[%i] = %f rollPath[%i] = %f  pitchPath[%i] = %f  yawPath[%i] = %f",i,linearPath.at(i),i,rollPath.at(i),i,pitchPath.at(i),i,yawPath.at(i));
00422         }
00423         */
00424         
00425         // Interpolate the linear path
00426         for(int i=0;i<pathMatrix[0].size();i++){
00427                 if(!justRotate){
00428                         pose.position.x = start.position.x + linearPath.at(i) * (end.position.x-start.position.x)/Se;
00429                         pose.position.y = start.position.y + linearPath.at(i) * (end.position.y-start.position.y)/Se;
00430                         pose.position.z = start.position.z + linearPath.at(i) * (end.position.z-start.position.z)/Se;
00431                 }
00432                 else{
00433                         pose.position.x = start.position.x;
00434                         pose.position.y = start.position.y;
00435                         pose.position.z = start.position.z;     
00436                 }
00437                 
00438                 // Transform RPY to Quaternion
00439                 q.setRPY(rollPath.at(i),pitchPath.at(i),yawPath.at(i));
00440                 transform.setRotation(q);
00441         
00442                 // Get Quaternion Values
00443                 pose.orientation.x = transform.getRotation()[0];
00444                 pose.orientation.y = transform.getRotation()[1];
00445                 pose.orientation.z = transform.getRotation()[2];
00446                 pose.orientation.w = transform.getRotation()[3];
00447                 poseVector->push_back(pose);
00448         }
00449 }
00450 
00451 
00452 
00453 
00454 void CobArticulation::circular_interpolation(   std::vector<geometry_msgs::Pose>* poseVector,
00455                                                                                                 double M_x,double M_y,double M_z,
00456                                                                                                 double M_roll,double M_pitch,double M_yaw,
00457                                                                                                 double startAngle, double endAngle,double r, double VelMax, double AcclMax,
00458                                                                                                 std::string profile)  
00459 {
00460         tf::Transform C,P,T;
00461         tf::Quaternion q;
00462         geometry_msgs::Pose pose,pos;
00463         std::vector<double> pathArray;
00464         
00465         
00466         // Convert RPY angles into [RAD]
00467         startAngle=startAngle*M_PI/180;
00468         endAngle=endAngle*M_PI/180;
00469         M_roll = M_roll*M_PI/180;
00470         M_pitch = M_pitch*M_PI/180;
00471         M_yaw = M_yaw*M_PI/180;
00472         
00473         double Se = endAngle-startAngle;
00474         bool forward;
00475         
00476         if(Se < 0)
00477                 forward=false;
00478         else
00479                 forward=true;
00480                 
00481         Se = std::fabs(Se);
00482         
00483         
00484         // Calculates the Path with Ramp - or Sinoidprofile
00485         calculateProfile(&pathArray,Se,VelMax,AcclMax,profile);
00486                 
00487         // Define Center Pose
00488         C.setOrigin( tf::Vector3(M_x,M_y,M_z) );
00489         q.setRPY(M_roll,M_pitch,M_yaw);
00490     C.setRotation(q);
00491 
00492         // Interpolate the circular path
00493         for(int i=0;i<pathArray.size();i++){
00494                 // Rotate T
00495                 T.setOrigin(tf::Vector3(cos(pathArray.at(i))*r,0,sin(pathArray.at(i))*r));
00496                 
00497                 if(endAngle<startAngle){
00498                                 T.setOrigin(tf::Vector3(cos(pathArray.at(i))*r,0,sin(pathArray.at(i))*r));
00499                                 q.setRPY(0,-pathArray.at(i),0);                 
00500                 }else{
00501                                 T.setOrigin(tf::Vector3(cos(startAngle-pathArray.at(i))*r,0,sin(startAngle-pathArray.at(i))*r));
00502                                 q.setRPY(0,pathArray.at(i),0);
00503                 }       
00504                 
00505                 T.setRotation(q);       
00506                         
00507                 // Calculate TCP Position
00508                 P = C * T;
00509                 
00510                 // Fill the Pose
00511                 pose.position.x = P.getOrigin().x();
00512                 pose.position.y = P.getOrigin().y();
00513                 pose.position.z = P.getOrigin().z();
00514                 
00515                 pose.orientation.x = P.getRotation()[0];
00516                 pose.orientation.y = P.getRotation()[1];
00517                 pose.orientation.z = P.getRotation()[2];
00518                 pose.orientation.w = P.getRotation()[3];
00519                 
00520                 // Put the pose into the pose Vector
00521                 poseVector->push_back(pose);
00522                 
00523         }
00524         
00525         // Visualize center point 
00526         int marker4=0;
00527         q.setRPY(M_roll+(M_PI/2),M_pitch,M_yaw);
00528     C.setRotation(q);
00529         showLevel(C,marker4,1.0,0,0,"level");
00530 }
00531 
00532 
00533 void CobArticulation::calculateProfile(std::vector<double> *pathArray,double Se, double VelMax, double AcclMax, std::string profile)
00534 {       
00535         int steps_te,steps_tv,steps_tb=0;
00536         double tv,tb,te=0;
00537         double T_IPO=pow(update_rate_,-1);
00538 
00539         if(profile == "ramp"){
00540                 // Calculate the Ramp Profile Parameters
00541                 if (VelMax > sqrt(Se*AcclMax)){
00542                         VelMax = sqrt(Se*AcclMax);
00543                 }
00544                 tb = VelMax/AcclMax;
00545                 te = (Se / VelMax) + tb;
00546                 tv = te - tb;
00547         }
00548         else{
00549                 // Calculate the Sinoide Profile Parameters
00550                 if (VelMax > sqrt(Se*AcclMax/2)){
00551                         VelMax = sqrt(Se*AcclMax/2);
00552                 }
00553                 tb = 2*VelMax/AcclMax;
00554                 te = (Se / VelMax) + tb;
00555                 tv = te - tb;           
00556         }
00557 
00558         // Interpolationsteps for every timesequence
00559         steps_tb = (double)tb / T_IPO;
00560         steps_tv = (double)(tv-tb) / T_IPO;
00561         steps_te = (double)(te-tv) / T_IPO;
00562 
00563 
00564         // Reconfigure timings wtih T_IPO
00565         tb=steps_tb*T_IPO;
00566         tv=(steps_tb+steps_tv)*T_IPO;
00567         te=(steps_tb+steps_tv+steps_te)*T_IPO;
00568         
00569                         
00570         ROS_INFO("Vm: %f m/s",VelMax);
00571         ROS_INFO("Bm: %f m/s²",AcclMax);
00572         ROS_INFO("Se: %f ",Se);
00573         ROS_INFO("tb: %f s",tb);
00574         ROS_INFO("tv: %f s",tv);
00575         ROS_INFO("te: %f s",te);
00576         
00577 
00578         if(profile == "ramp"){
00579                 ROS_INFO("Ramp Profile");
00580                 // Calculate the ramp profile path
00581                 // 0 <= t <= tb
00582                 for(int i=0;i<=steps_tb-1;i++){ 
00583                         pathArray->push_back(0.5*AcclMax*pow((T_IPO*i),2));
00584                 }
00585                 // tb <= t <= tv
00586                 for(int i=steps_tb;i<=(steps_tb+steps_tv-1);i++){       
00587                         pathArray->push_back(VelMax*(T_IPO*i)-0.5*pow(VelMax,2)/AcclMax);
00588                 }
00589                 // tv <= t <= te
00590                 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){    
00591                         //pathArray[i] = Se - 0.5*AcclMax* pow(((steps_tb+steps_tv+steps_te-i)*T_IPO),2);
00592                         pathArray->push_back(VelMax * (te-tb) - 0.5*AcclMax* pow(te-(i*T_IPO),2));
00593                 }
00594         }
00595         else{
00596                 ROS_INFO("Sinoide Profile");
00597                 // Calculate the sinoide profile path
00598                 // 0 <= t <= tb
00599                 for(int i=0;i<=steps_tb-1;i++){ 
00600                         pathArray->push_back(  AcclMax*(0.25*pow(i*T_IPO,2) + pow(tb,2)/(8*pow(M_PI,2)) *(cos(2*M_PI/tb * (i*T_IPO))-1))  );
00601                 }
00602                 // tb <= t <= tv
00603                 for(int i=steps_tb;i<=(steps_tb+steps_tv-1);i++){
00604                         pathArray->push_back(VelMax*(i*T_IPO-0.5*tb));
00605                 }
00606                 // tv <= t <= te
00607                 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){
00608                         pathArray->push_back(0.5*AcclMax*( te*(i*T_IPO + tb)  -  0.5*(pow(i*T_IPO,2)+pow(te,2)+2*pow(tb,2))  + (pow(tb,2)/(4*pow(M_PI,2))) * (1-cos( ((2*M_PI)/tb) * (i*T_IPO-tv)))));
00609                 }
00610         }       
00611 }
00612 
00613 
00614 void CobArticulation::calculateProfileForAngularMovements(std::vector<double> *pathMatrix,
00615                                                                                                                  double Se, double Se_roll, double Se_pitch, double Se_yaw,
00616                                                                                                                  double start_angle_roll, double start_angle_pitch, double start_angle_yaw,
00617                                                                                                                  double VelMax, double AcclMax,std::string profile, bool justRotate)
00618 {       
00619         std::vector<double> linearPath,rollPath,pitchPath,yawPath;
00620         int steps_te,steps_tv,steps_tb=0;
00621         double tv,tb,te=0;
00622         double T_IPO=pow(update_rate_,-1);
00623         double params[4][2];
00624         double Se_max,temp=0;
00625 
00626         double Se_array[4] = {Se,Se_roll,Se_pitch,Se_yaw};
00627         
00628         for(int i=0;i<sizeof(Se_array);i++){
00629                 if(temp<std::fabs(Se_array[i]))
00630                         temp=std::fabs(Se_array[i]);
00631         }
00632         
00633         // If justRoate == true, then set the largest angular difference as Se_max.
00634         if(justRotate){
00635                 Se_max=temp;
00636         }
00637         else{   // Otherwise set the linear-path as Se_max
00638                 Se_max = Se;
00639         }
00640         
00641         
00642         // Calculate the Profile Timings for the linear-path
00643         if(profile == "ramp"){
00644                 // Calculate the Ramp Profile Parameters
00645                 if (VelMax > sqrt(std::fabs(Se_max)*AcclMax)){
00646                         VelMax = sqrt(std::fabs(Se_max)*AcclMax);
00647                 }
00648                 tb = VelMax/AcclMax;
00649                 te = (std::fabs(Se_max) / VelMax) + tb;
00650                 tv = te - tb;
00651         }
00652         else{
00653                 // Calculate the Sinoide Profile Parameters
00654                 if (VelMax > sqrt(std::fabs(Se_max)*AcclMax/2)){
00655                         VelMax = sqrt(std::fabs(Se_max)*AcclMax/2);
00656                 }
00657                 tb = 2*VelMax/AcclMax;
00658                 te = (std::fabs(Se_max) / VelMax) + tb;
00659                 tv = te - tb;           
00660         }
00661         
00662         // Interpolationsteps for every timesequence
00663         steps_tb = (double)tb / T_IPO;
00664         steps_tv = (double)(tv-tb) / T_IPO;
00665         steps_te = (double)(te-tv) / T_IPO;
00666 
00667 
00668         // Reconfigure timings wtih T_IPO
00669         tb=steps_tb*T_IPO;
00670         tv=(steps_tb+steps_tv)*T_IPO;
00671         te=(steps_tb+steps_tv+steps_te)*T_IPO;
00672                 
00673         // Calculate the paths
00674         generatePath(&linearPath,       T_IPO,VelMax,AcclMax,Se_max,(steps_tb+steps_tv+steps_te),profile);
00675         generatePathWithTe(&rollPath, T_IPO, te, AcclMax, Se_roll, (steps_tb+steps_tv+steps_te),start_angle_roll,profile);
00676         generatePathWithTe(&pitchPath, T_IPO, te, AcclMax, Se_pitch, (steps_tb+steps_tv+steps_te),start_angle_pitch,profile);
00677         generatePathWithTe(&yawPath, T_IPO, te, AcclMax, Se_yaw, (steps_tb+steps_tv+steps_te),start_angle_yaw,profile);
00678         
00679 
00680         // Get the Vecotr sizes of each path-vector
00681         int MaxStepArray[4],maxSteps;
00682         MaxStepArray[0] = linearPath.size();
00683         MaxStepArray[1] = rollPath.size();
00684         MaxStepArray[2] = pitchPath.size();
00685         MaxStepArray[3] = yawPath.size();
00686         
00687         // Get the largest one
00688         maxSteps = 0;
00689         for(int i=0;i<4;i++){
00690                 if(maxSteps<MaxStepArray[i])
00691                         maxSteps=MaxStepArray[i];
00692         }
00693         
00694         
00695         bool linearOkay,rollOkay,pitchOkay,yawOkay=false;
00696         
00697         // Check if every vector has the same length than the largest one.
00698         while(true){
00699                 if(linearPath.size() < maxSteps){
00700                 linearPath.push_back(linearPath.at(linearPath.size()-1));       
00701                 }else{linearOkay=true;}
00702                 
00703                 if(rollPath.size() < maxSteps){
00704                         rollPath.push_back(rollPath.at(rollPath.size()-1));
00705                 }else{rollOkay=true;}
00706                 
00707                 if(pitchPath.size() < maxSteps){
00708                         pitchPath.push_back(pitchPath.at(pitchPath.size()-1));
00709                 }else{pitchOkay=true;}
00710                 
00711                 if(yawPath.size() < maxSteps){
00712                         yawPath.push_back(yawPath.at(yawPath.size()-1));
00713                 }else{yawOkay=true;}
00714                 
00715                 if(linearOkay && rollOkay && pitchOkay && yawOkay){
00716                         break;
00717                 }       
00718         }
00719 
00720         
00721         // Put the interpolated paths into the pathMatrix
00722         pathMatrix[0]=linearPath;
00723         pathMatrix[1]=rollPath;
00724         pathMatrix[2]=pitchPath;
00725         pathMatrix[3]=yawPath;
00726 }
00727 
00728 
00729 
00730 
00731 
00732 geometry_msgs::Pose CobArticulation::getEndeffectorPose()
00733 {       
00734         geometry_msgs::Pose pos;        
00735         tf::StampedTransform stampedTransform;
00736         bool transformed=false;
00737         do{
00738                 // Get transformation
00739                 try{
00740                         listener_.lookupTransform(referenceFrame_,endeffectorFrame_, ros::Time(0), stampedTransform);
00741                         transformed=true;
00742                 }
00743                 catch (tf::TransformException &ex) {
00744                         ROS_ERROR("%s",ex.what());
00745                         transformed = false;
00746                         ros::Duration(0.1).sleep();
00747                 }       
00748         }while(!transformed);
00749         
00750         currentEndeffectorStampedTransform_ = stampedTransform;
00751         
00752         pos.position.x=stampedTransform.getOrigin().x();
00753         pos.position.y=stampedTransform.getOrigin().y();
00754         pos.position.z=stampedTransform.getOrigin().z();
00755         pos.orientation.x = stampedTransform.getRotation()[0];
00756         pos.orientation.y = stampedTransform.getRotation()[1];
00757         pos.orientation.z = stampedTransform.getRotation()[2];
00758         pos.orientation.w = stampedTransform.getRotation()[3];
00759                         
00760         return pos;
00761 }
00762 
00763 
00764 
00765 // Checks if the endeffector is in the area of the 'br' frame
00766 bool CobArticulation::epsilon_area(double x,double y, double z, double roll, double pitch, double yaw,double epsilon)
00767 {
00768         bool x_okay=false, y_okay=false, z_okay=false;
00769         bool roll_okay=false, pitch_okay=false, yaw_okay=false;
00770         
00771         x=std::fabs(x);
00772         y=std::fabs(y);
00773         z=std::fabs(z);
00774         roll=std::fabs(roll);
00775         pitch=std::fabs(pitch);
00776         yaw=std::fabs(yaw);
00777         
00778         if(x < epsilon){ x_okay = true; };
00779         if(y < epsilon){ y_okay = true; };
00780         if(z < epsilon){ z_okay = true; };
00781         if(roll < epsilon){ roll_okay = true; };
00782         if(pitch < epsilon){ pitch_okay = true; };
00783         if(yaw < epsilon){ yaw_okay = true; };
00784         
00785         if(x_okay && y_okay && z_okay && roll_okay && pitch_okay && yaw_okay){
00786                 return true;
00787         }else{
00788                 return false;
00789         }
00790 }
00791 
00792 
00793 
00794 void CobArticulation::showMarker(tf::StampedTransform tf,int marker_id,double red, double green, double blue,std::string ns)
00795 {
00796         visualization_msgs::Marker marker;
00797         marker.header.frame_id = referenceFrame_;
00798         marker.header.stamp = ros::Time();
00799         marker.ns = ns;
00800         marker.id = marker_id;
00801         marker.type = visualization_msgs::Marker::SPHERE;
00802         marker.action = visualization_msgs::Marker::ADD;
00803                 
00804         marker.pose.position.x = tf.getOrigin().x();
00805         marker.pose.position.y = tf.getOrigin().y();
00806         marker.pose.position.z = tf.getOrigin().z();
00807         marker.pose.orientation.x = 0.0;
00808         marker.pose.orientation.y = 0.0;
00809         marker.pose.orientation.z = 0.0;
00810         marker.pose.orientation.w = 1.0;
00811         
00812         marker.scale.x = 0.01;
00813         marker.scale.y = 0.01;
00814         marker.scale.z = 0.01;
00815         marker.color.r = red;
00816         marker.color.g = green;
00817         marker.color.b = blue;
00818         
00819         marker.color.a = 1.0;
00820 
00821         vis_pub_.publish( marker );
00822         
00823 }
00824 
00825 void CobArticulation::showDot(double x,double y,double z,int marker_id,double red, double green, double blue,std::string ns)
00826 {
00827         visualization_msgs::Marker marker;
00828         marker.header.frame_id = referenceFrame_;
00829         marker.header.stamp = ros::Time();
00830         marker.ns = ns;
00831         marker.id = marker_id;
00832         marker.type = visualization_msgs::Marker::SPHERE;
00833         marker.action = visualization_msgs::Marker::ADD;
00834                 
00835         marker.pose.position.x = x;
00836         marker.pose.position.y = y;
00837         marker.pose.position.z = z;
00838         marker.pose.orientation.x = 0.0;
00839         marker.pose.orientation.y = 0.0;
00840         marker.pose.orientation.z = 0.0;
00841         marker.pose.orientation.w = 1.0;
00842         
00843         marker.scale.x = 0.05;
00844         marker.scale.y = 0.05;
00845         marker.scale.z = 0.05;
00846         marker.color.r = red;
00847         marker.color.g = green;
00848         marker.color.b = blue;
00849         
00850         marker.color.a = 1.0;
00851 
00852         vis_pub_.publish( marker );     
00853 }
00854 
00855 void CobArticulation::showLevel(tf::Transform pos,int marker_id,double red, double green, double blue,std::string ns)
00856 {
00857         visualization_msgs::Marker marker;
00858         marker.header.frame_id = referenceFrame_;
00859         marker.header.stamp = ros::Time();
00860         marker.ns = ns;
00861         marker.id = marker_id;
00862         marker.type = visualization_msgs::Marker::CUBE;
00863         marker.action = visualization_msgs::Marker::ADD;
00864                 
00865         marker.pose.position.x = pos.getOrigin().x();
00866         marker.pose.position.y = pos.getOrigin().y();
00867         marker.pose.position.z = pos.getOrigin().z();
00868         marker.pose.orientation.x = pos.getRotation()[0];
00869         marker.pose.orientation.y = pos.getRotation()[1];
00870         marker.pose.orientation.z = pos.getRotation()[2];
00871         marker.pose.orientation.w = pos.getRotation()[3];
00872         
00873         marker.scale.x = 1;
00874         marker.scale.y = 1;
00875         marker.scale.z = 0.01;
00876         marker.color.r = red;
00877         marker.color.g = green;
00878         marker.color.b = blue;
00879         
00880         marker.color.a = 0.2;
00881 
00882         vis_pub_.publish( marker );     
00883 }
00884 
00885 
00886 void CobArticulation::timerCallback(const ros::TimerEvent& event){
00887         hold_=false;
00888 }
00889 
00890 
00891 void CobArticulation::start_tracking()
00892 {       
00893     cob_srvs::SetString start;
00894     start.request.data = targetFrame_;
00895     startTracking_.call(start);
00896     
00897     if(start.response.success==true){
00898                 ROS_INFO("...service called!");
00899         }
00900         else{
00901                 ROS_INFO("...service failed");
00902         }
00903 }
00904 
00905 
00906 void CobArticulation::stop_tracking()
00907 {
00908     std_srvs::Empty srv_save_stop;
00909     srv_save_stop.request;
00910     if (stopTracking_.call(srv_save_stop)) {
00911                 ROS_INFO("... service stopped!");
00912                 }
00913         else {
00914                         ROS_ERROR("... service stop failed! FATAL!");
00915                 }
00916 }
00917 
00918 void CobArticulation::generatePath(std::vector<double> *pathArray,double T_IPO, double VelMax, double AcclMax,double Se_max, int steps_max, std::string profile){       
00919         double tv,tb,te=0;
00920         int steps_te,steps_tv,steps_tb=0;
00921         
00922         // Reconfigure the timings and parameters with T_IPO
00923         tb = (VelMax/(AcclMax*T_IPO)) * T_IPO;
00924         tv = (std::fabs(Se_max)/(VelMax*T_IPO)) * T_IPO;
00925         te=tv+tb;
00926         VelMax = std::fabs(Se_max) / tv;
00927         AcclMax = VelMax / tb;
00928         
00929         // Calculate the Profile Timings for the longest path
00930         if(profile == "ramp"){
00931                 tb = VelMax/AcclMax;
00932                 te = (std::fabs(Se_max) / VelMax) + tb;
00933                 tv = te - tb;
00934         }
00935         else{
00936                 tb = 2*VelMax/AcclMax;
00937                 te = (std::fabs(Se_max) / VelMax) + tb;
00938                 tv = te - tb;           
00939         }
00940 
00941         // Interpolationsteps for every timesequence
00942         steps_tb = (double)tb / T_IPO;
00943         steps_tv = (double)(tv-tb) / T_IPO;
00944         steps_te = (double)(te-tv) / T_IPO;
00945                 
00946         // Reconfigure timings wtih T_IPO
00947         tb=steps_tb*T_IPO;
00948         tv=(steps_tb+steps_tv)*T_IPO;
00949         te=(steps_tb+steps_tv+steps_te)*T_IPO;
00950         
00951         if(profile == "ramp"){
00952                 // Calculate the ramp profile path
00953                 // 0 <= t <= tb
00954                 for(int i=0;i<=steps_tb-1;i++){ 
00955                         pathArray->push_back( Se_max/std::fabs(Se_max)*(0.5*AcclMax*pow((T_IPO*i),2)));
00956                 }
00957                 // tb <= t <= tv
00958                 for(int i=steps_tb;i<=(steps_tb+steps_tv-1);i++){       
00959                         pathArray->push_back(Se_max/std::fabs(Se_max)*(VelMax*(T_IPO*i)-0.5*pow(VelMax,2)/AcclMax));
00960                 }
00961                 // tv <= t <= te
00962                 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){    
00963                         pathArray->push_back(Se_max/std::fabs(Se_max)*(VelMax * (te-tb) - 0.5*AcclMax* pow(te-(i*T_IPO),2)));
00964                 }
00965         }
00966         else{
00967                 // Calculate the sinoide profile path
00968                 // 0 <= t <= tb
00969                 for(int i=0;i<=steps_tb-1;i++){ 
00970                         pathArray->push_back( Se_max/std::fabs(Se_max)*( AcclMax*(0.25*pow(i*T_IPO,2) + pow(tb,2)/(8*pow(M_PI,2)) *(cos(2*M_PI/tb * (i*T_IPO))-1))  ));
00971                 }
00972                 // tb <= t <= tv
00973                 for(int i=steps_tb;i<=(steps_tb+steps_tv-1);i++){       
00974                         pathArray->push_back(Se_max/std::fabs(Se_max)*(VelMax*(i*T_IPO-0.5*tb)));
00975                 }
00976                 // tv <= t <= te
00977                 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){    
00978                         pathArray->push_back(Se_max/std::fabs(Se_max)*(0.5*AcclMax*( te*(i*T_IPO + tb)  -  0.5*(pow(i*T_IPO,2)+pow(te,2)+2*pow(tb,2))  + (pow(tb,2)/(4*pow(M_PI,2))) * (1-cos( ((2*M_PI)/tb) * (i*T_IPO-tv))))));
00979                 }
00980         }
00981 }
00982 
00983 
00984 void CobArticulation::generatePathWithTe(std::vector<double> *pathArray,double T_IPO, double te, double AcclMax,double Se_max, int steps_max,double start_angle,std::string profile){   
00985         double tv,tb=0;
00986         int steps_te,steps_tv,steps_tb=0;
00987         double VelMax;                                                          
00988 
00989         
00990         // Calculate the Profile Timings
00991         if(profile == "ramp"){
00992                 // Reconfigure AcclMax and Velmax
00993                 while(te< 2*sqrt(std::fabs(Se_max)/AcclMax)){
00994                         AcclMax+=0.001;
00995                 }
00996                 VelMax = AcclMax * te / 2 - sqrt((pow(AcclMax,2)*pow(te,2)/4) - std::fabs(Se_max) * AcclMax );
00997                 
00998                 // Calculate profile timings, te is known
00999                 tb = VelMax/AcclMax;
01000                 tv = te - tb;
01001         }
01002         else{   // Sinoide
01003                 // Reconfigure AcclMax and Velmax
01004                 while(te< sqrt(std::fabs(Se_max)*8/AcclMax)){
01005                         AcclMax+=0.001;
01006                 }
01007                 VelMax = AcclMax * te / 4 - sqrt((pow(AcclMax,2)*pow(te,2)/16) - std::fabs(Se_max) * AcclMax/2 );
01008                 
01009                 // Calculate profile timings, te is known
01010                 tb = 2*VelMax/AcclMax;
01011                 tv = te - tb;           
01012         }
01013 
01014         // Interpolationsteps for every timesequence
01015         steps_tb = (double)tb / T_IPO;
01016         steps_tv = (double)(tv-tb) / T_IPO;
01017         steps_te = (double)(te-tv) / T_IPO;
01018         
01019         
01020         // Reconfigure timings wtih T_IPO
01021         tb=steps_tb*T_IPO;
01022         tv=(steps_tb+steps_tv)*T_IPO;
01023         te=(steps_tb+steps_tv+steps_te)*T_IPO;
01024         
01025 
01026         if(profile == "ramp"){
01027                 // Calculate the ramp profile path
01028                 // 0 <= t <= tb
01029                 for(int i=0;i<=steps_tb-1;i++){ 
01030                         pathArray->push_back( start_angle + Se_max/std::fabs(Se_max)*(0.5*AcclMax*pow((T_IPO*i),2)));
01031                 }
01032                 // tb <= t <= tv
01033                 for(int i=steps_tb;i<=(steps_tb+steps_tv-1);i++){       
01034                         pathArray->push_back(start_angle + Se_max/std::fabs(Se_max)*(VelMax*(T_IPO*i)-0.5*pow(VelMax,2)/AcclMax));
01035                 }
01036                 // tv <= t <= te
01037                 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){    
01038                         pathArray->push_back(start_angle + Se_max/std::fabs(Se_max)*(VelMax * (te-tb) - 0.5*AcclMax* pow(te-(i*T_IPO),2)));
01039                 }
01040         }
01041         else{
01042                 // Calculate the sinoide profile path
01043                 // 0 <= t <= tb
01044                 for(int i=0;i<=steps_tb-1;i++){ 
01045                         pathArray->push_back(start_angle + Se_max/std::fabs(Se_max)*( AcclMax*(0.25*pow(i*T_IPO,2) + pow(tb,2)/(8*pow(M_PI,2)) *(cos(2*M_PI/tb * (i*T_IPO))-1))  ));
01046                 }
01047                 // tb <= t <= tv
01048                 for(int i=steps_tb;i<=(steps_tb+steps_tv-1);i++){       
01049                         pathArray->push_back(start_angle + Se_max/std::fabs(Se_max)*(VelMax*(i*T_IPO-0.5*tb)));
01050                 }
01051                 // tv <= t <= te
01052                 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){    
01053                         pathArray->push_back(start_angle + Se_max/std::fabs(Se_max)*(0.5*AcclMax*( te*(i*T_IPO + tb)  -  0.5*(pow(i*T_IPO,2)+pow(te,2)+2*pow(tb,2))  + (pow(tb,2)/(4*pow(M_PI,2))) * (1-cos( ((2*M_PI)/tb) * (i*T_IPO-tv))))));
01054                 }
01055         }
01056 }
01057 
01058 
01059 void CobArticulation::PoseToRPY(geometry_msgs::Pose pose,double &roll, double &pitch, double &yaw){
01060         tf::Quaternion q = tf::Quaternion(pose.orientation.x,pose.orientation.y,pose.orientation.z,pose.orientation.w);
01061         tf::Matrix3x3(q).getRPY(roll,pitch,yaw);
01062 }
01063 
01064 
01065 


cob_path_broadcaster
Author(s): Christoph Mark
autogenerated on Sun Mar 1 2015 13:56:50