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
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
00162 q.setRPY(roll,pitch,yaw);
00163 trans.setRotation(q);
00164
00165
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
00177 linear_interpolation(&posVec,actualTcpPose,end,vel,accl,profile,justRotate);
00178
00179
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
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
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
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
00291 br_.sendTransform(tf::StampedTransform(transform_, now, referenceFrame_, targetFrame_));
00292
00293
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
00303 tf::Quaternion quatern = stampedTransform.getRotation();
00304 tf::Matrix3x3(quatern).getRPY(ro,pi,ya);
00305
00306
00307
00308 if(epsilon_area(stampedTransform.getOrigin().x(), stampedTransform.getOrigin().y(), stampedTransform.getOrigin().z(),ro,pi,ya,epsilon)){
00309 reached_pos_counter++;
00310 }
00311
00312 if(reached_pos_counter>=50){
00313 reached_pos_=true;
00314 }
00315
00316 if(reached_pos_==true){
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
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
00347
00348 br_.sendTransform(tf::StampedTransform(transform_, ros::Time::now(), referenceFrame_, targetFrame_));
00349
00350
00351 marker1_++;
00352
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
00371 transform_.setOrigin( tf::Vector3(holdPose.position.x,holdPose.position.y,holdPose.position.z) );
00372
00373
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
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
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
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
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
00421
00422
00423
00424
00425
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
00439 q.setRPY(rollPath.at(i),pitchPath.at(i),yawPath.at(i));
00440 transform.setRotation(q);
00441
00442
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
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
00485 calculateProfile(&pathArray,Se,VelMax,AcclMax,profile);
00486
00487
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
00493 for(int i=0;i<pathArray.size();i++){
00494
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
00508 P = C * T;
00509
00510
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
00521 poseVector->push_back(pose);
00522
00523 }
00524
00525
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
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
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
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
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
00581
00582 for(int i=0;i<=steps_tb-1;i++){
00583 pathArray->push_back(0.5*AcclMax*pow((T_IPO*i),2));
00584 }
00585
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
00590 for(int i=(steps_tb+steps_tv);i<(steps_tv+steps_tb+steps_te-1);i++){
00591
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
00598
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
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
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
00634 if(justRotate){
00635 Se_max=temp;
00636 }
00637 else{
00638 Se_max = Se;
00639 }
00640
00641
00642
00643 if(profile == "ramp"){
00644
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00953
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
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
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
00968
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
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
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
00991 if(profile == "ramp"){
00992
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
00999 tb = VelMax/AcclMax;
01000 tv = te - tb;
01001 }
01002 else{
01003
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
01010 tb = 2*VelMax/AcclMax;
01011 tv = te - tb;
01012 }
01013
01014
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
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
01028
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
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
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
01043
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
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
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