Cartesian_HybCntrl.cpp
Go to the documentation of this file.
00001 #include "robodyn_controllers/Cartesian_HybCntrl.h"
00002 
00003 Cartesian_HybCntrl::Cartesian_HybCntrl()
00004     : logCategory("gov.nasa.controllers.CartHybCntrl")
00005 {
00006     linearRateLimiter.reset(new RateLimiter);
00007     angularRateLimiter.reset(new RateLimiter);
00008 }
00009 
00010 Cartesian_HybCntrl::~Cartesian_HybCntrl()
00011 {
00012 }
00013 
00015 void Cartesian_HybCntrl::setGain(double forceP, double torqueP, double forceI, double torqueI, double forceD, double torqueD, double forceWindup, double torqueWindup, double positionErrorLimit_in, double rotationErrorLimit_in)
00016 {
00017     fKp = forceP;
00018     tKp = torqueP;
00019     fKi = forceI;
00020     tKi = torqueI;
00021     fKd = forceD;
00022     tKd = torqueD;
00023     forceIntegralWindupLimit = forceWindup;
00024     torqueIntegralWindupLimit = torqueWindup;
00025     positionErrorLimit = positionErrorLimit_in;
00026     rotationErrorLimit = rotationErrorLimit_in;
00027 
00028     edgeBuffer = 0.25; // percentage of the edge to buffer the gains
00029 
00030     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "set force and torque error gain";
00031 }
00032 
00034 void Cartesian_HybCntrl::setPoseSettings(double linVel, double angVel, double linAcc, double angAcc)
00035 {
00036     maxLinearVelocity = linVel;
00037     maxAngularVelocity = angVel;
00038 
00039     linearRateLimiter->setRateLimit(linAcc);
00040     angularRateLimiter->setRateLimit(angAcc);
00041 
00042     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "set pose settings for maxLinear, maxAngular Velocity and RateLimiter";
00043 }
00044 
00045 void Cartesian_HybCntrl::setFilter(double filterAlpha)
00046 {
00047     alpha = filterAlpha;
00048     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "set filter alpha";
00049 }
00050 
00052 void Cartesian_HybCntrl::setSensorNameMap(const std::map<std::string, std::string>& sensorNameMap)
00053 {
00054     this->sensorNameMap = sensorNameMap;
00055 }
00056 
00057 void Cartesian_HybCntrl::updateSensorForces(const std::map<std::string, KDL::Wrench>& sensorForces)
00058 {
00060     for (sensorForceItr = sensorForces.begin(); sensorForceItr != sensorForces.end(); ++sensorForceItr)
00061     {
00063         if (sensorForceMap.find(sensorForceItr->first) == sensorForceMap.end())
00064         {
00065             sensorForceMap[sensorForceItr->first] = KDL::Wrench::Zero();
00066         }
00067 
00068         sensorForceMap[sensorForceItr->first] = alpha * sensorForceMap[sensorForceItr->first] + (1 - alpha) * sensorForceItr->second;
00069     }
00070 }
00071 
00072 bool Cartesian_HybCntrl::setInitialPose(const std::string& frameName, const::KDL::Frame& pose)
00073 {
00074     if (forceCntrlMap.find(frameName) == forceCntrlMap.end())
00075     {
00076         NasaCommonLogging::Logger::getCategory("gov.nasa.controllers.core.CartHybCntrl") << log4cpp::Priority::ERROR << frameName << " not in force control";
00077         return false;
00078     }
00079     cout << "Cartetian_HybCntrl::reset for initial pose" <<endl;
00080     printFrame("Reset_Pose", pose);
00081     forceCntrlMap.at(frameName).pose = pose;
00082     return true;
00083 }
00084 
00087 void Cartesian_HybCntrl::createForceControlMap(std::map<std::string, std::pair<std::vector<int>, std::vector<double> > > forceNodes)
00088 {
00089     forceCntrlMap.clear();
00090 
00091     for (std::map<std::string, std::pair<std::vector<int>, std::vector<double> > >::iterator itr = forceNodes.begin(); itr != forceNodes.end(); ++itr)
00092     {
00093         if (itr->second.first.size() != itr->second.second.size())
00094         {
00095             NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::ERROR << "force axes and magnitudes do not match for node " << itr->first << "!";
00096             continue;
00097         }
00098 
00099         ForceControl newForceControl;
00100         newForceControl.sensorName = getSensorNameFromNode(itr->first);
00101 
00102         for (unsigned int i = 0; i < itr->second.first.size(); ++i)
00103         {
00104             switch (itr->second.first.at(i))
00105             {
00106                 case r2_msgs::ForceControlAxis::X:
00107                     newForceControl.x = true;
00108                     newForceControl.desiredForce.force.x(itr->second.second.at(i));
00109                     break;
00110 
00111                 case r2_msgs::ForceControlAxis::Y:
00112                     newForceControl.y = true;
00113                     newForceControl.desiredForce.force.y(itr->second.second.at(i));
00114                     break;
00115 
00116                 case r2_msgs::ForceControlAxis::Z:
00117                     newForceControl.z = true;
00118                     newForceControl.desiredForce.force.z(itr->second.second.at(i));
00119                     break;
00120 
00121                 case r2_msgs::ForceControlAxis::ROLL:
00122                     newForceControl.roll = true;
00123                     newForceControl.desiredForce.torque.x(itr->second.second.at(i));
00124                     break;
00125 
00126                 case r2_msgs::ForceControlAxis::PITCH:
00127                     newForceControl.pitch = true;
00128                     newForceControl.desiredForce.torque.y(itr->second.second.at(i));
00129                     break;
00130 
00131                 case r2_msgs::ForceControlAxis::YAW:
00132                     newForceControl.yaw = true;
00133                     newForceControl.desiredForce.torque.z(itr->second.second.at(i));
00134                     break;
00135 
00136                 default:
00137                     break;
00138             }
00139         }
00140 
00141         forceCntrlMap[itr->first] = newForceControl;
00142     }
00143 }
00144 
00145 void Cartesian_HybCntrl::printFrame(std::string name, KDL::Frame frame)
00146 {
00147     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << name << ": "
00148         << frame.p.x() << ", " << frame.p.y() << ", " << frame.p.z() << ", "
00149         << frame.M.GetRot().x() << ", " << frame.M.GetRot().y() << ", " << frame.M.GetRot().z();
00150 
00151     double alpha = 0;
00152     double beta = 0;
00153     double gamma = 0;
00154     frame.M.GetEulerZYX(alpha, beta, gamma);
00155 
00156     cout << "frame {" << name <<
00157         "} position = (" <<
00158         frame.p.x() << ", " <<
00159         frame.p.y() << ", " <<
00160         frame.p.z() << ") " <<
00161         "orientaion = (" <<
00162         gamma << ", " <<
00163         beta << ", " <<
00164         alpha << ")" << endl;
00165 }
00166 
00167 void Cartesian_HybCntrl::printWrench(std::string name, KDL::Wrench wrench)
00168 {
00169   cout <<
00170       "{" << name << "} " <<
00171       "Force = (" <<
00172       wrench.force.x() << ", " <<
00173       wrench.force.y() << ", " <<
00174       wrench.force.z() << ") " <<
00175       "Torque = (" <<
00176       wrench.torque.x() << ", " <<
00177       wrench.torque.y() << ", " <<
00178       wrench.torque.z() << ")" << endl;
00179 }
00180 
00181 
00182 void Cartesian_HybCntrl::updateFrames(std::vector<std::string> nodeNames, std::map<std::string, KDL::Frame> referenceFrameMap, std::vector<KDL::Frame>& nodeFrames, double dt)
00183 {
00184     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::DEBUG << "updating frames..";
00185 
00186     if (nodeNames.size() != nodeFrames.size())
00187     {
00188         std::stringstream err;
00189         err << "nodeNames and nodeFrames must be the same size! nodeNames: " << nodeNames.size() << ", nodeFrames: " << nodeFrames.size();
00190         NasaCommonLogging::Logger::log(logCategory, log4cpp::Priority::ERROR, err.str());
00191         throw std::runtime_error(err.str());
00192     }
00193 
00195     for (forceItr = forceCntrlMap.begin(); forceItr != forceCntrlMap.end(); ++forceItr)
00196     {
00197         sensorForceItr = sensorForceMap.find(forceItr->second.sensorName);
00198 
00199         if (sensorForceItr == sensorForceMap.end())
00200         {
00201             std::stringstream err;
00202             err << "Unable to find actual force for " << forceItr->second.sensorName;
00203             NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::ERROR << err.str();
00204             throw std::runtime_error(err.str());
00205         }
00206 
00207         forceItr->second.sensorForce = sensorForceItr->second;
00208     }
00209 
00210     for (unsigned int i = 0; i < nodeNames.size(); ++i)
00211     {
00212         std::stringstream ss;
00213 
00215         if ((forceItr = forceCntrlMap.find(nodeNames.at(i))) != forceCntrlMap.end())
00216         {
00218             //cout << "force gain = " << fKp <<endl;
00219             try
00220             {
00221                 poseFrame = referenceFrameMap.at(forceItr->first);
00222                 //printFrame("Pose_Frame", poseFrame);
00223             }
00224             catch (std::exception& e)
00225             {
00226                 std::stringstream err;
00227                 err << "Could not find pose frame " << forceItr->first << " in referenceFrameMap!";
00228                 NasaCommonLogging::Logger::log(logCategory, log4cpp::Priority::ERROR, err.str());
00229                 throw std::runtime_error(err.str());
00230             }
00231 
00233             try
00234             {
00235                 sensorFrame = referenceFrameMap.at(forceItr->second.sensorName);
00236                 //printFrame("sensor_frame", sensorFrame);
00237             }
00238             catch (std::exception& e)
00239             {
00240                 std::stringstream err;
00241                 err << "Could not find sensor frame " << forceItr->second.sensorName << " in referenceFrameMap!";
00242                 NasaCommonLogging::Logger::log(logCategory, log4cpp::Priority::ERROR, err.str());
00243                 throw std::runtime_error(err.str());
00244             }
00245 
00246             // rename the desired pose to do operations
00247             desiredPose = nodeFrames.at(i);
00248 
00249             //print the previous frame
00250             //printFrame("previous_frame", forceItr->second.pose);
00251 
00252             // Get the current sensor wrench
00253             wrenchSensorFrame = forceItr->second.sensorForce;
00254             //printWrench("wrenchSensorFrame", wrenchSensorFrame);
00255 
00256             //get the desired force
00257             wrenchDesired = forceItr->second.desiredForce;
00258             //printWrench("wrenchDesired", wrenchDesired);
00259 
00260             // convert the wrench from the sensor frame to the pose frame
00261             KDL::Frame T_FP;  // Transformation from Force to Pose
00262             T_FP = poseFrame.Inverse() * sensorFrame;
00263 
00264             // according the KDL docs, multiplying a Wrench by the transformation
00265             // from A to B will actually do the Force transformation, which is not just
00266             // a normal transformation matrix. See Craig book pg 158
00267             wrenchPoseFrame = T_FP * wrenchSensorFrame;
00268             //printWrench("wrenchPoseFrame", wrenchPoseFrame);
00269 
00270             // Calculate the force error
00271             forceError = wrenchDesired - wrenchPoseFrame; // do calcs in the pose frame
00272             //printWrench("forceError", forceError);
00273 
00274             // calculate the PID gains in the pose frame
00275 
00276             //Derivative Gain
00277             forceItr->second.derivative = (forceError - forceItr->second.error) / dt;
00278             forceItr->second.derivative.force = fKd * forceItr->second.derivative.force;
00279             forceItr->second.derivative.torque = tKd * forceItr->second.derivative.torque;
00280             //printWrench("derivatie_gain", forceItr->second.derivative);
00281 
00282             //Integral Gain
00283             //printWrench("pre_integrator_wrench", forceItr->second.integrator);
00284             forceItr->second.integrator.force += fKi * forceError.force;
00285             forceItr->second.integrator.torque += tKi * forceError.torque;
00286             //printWrench("integrator_gain_pre_limi", forceItr->second.integrator);
00287             limitVector(-forceIntegralWindupLimit, forceIntegralWindupLimit, forceItr->second.integrator.force);
00288             limitVector(-torqueIntegralWindupLimit, torqueIntegralWindupLimit, forceItr->second.integrator.torque);
00289             //printWrench("integrator_gain_post_limit", forceItr->second.integrator);
00290 
00291 
00292             //Proportional Gain
00293             forceItr->second.error = forceError; // this makes stores it for us
00294             forceItr->second.gain.force = fKp * forceError.force;
00295             forceItr->second.gain.torque = tKp * forceError.torque;
00296             //printWrench("proportional_gain", forceItr->second.gain);
00297 
00298             // forcePID in the pose_frame
00299             forcePID = forceItr->second.gain + forceItr->second.integrator + forceItr->second.derivative;
00300             printWrench("forcePID", forcePID);
00301 
00303 
00304             // Convert the desired pose into the pose frame and previous frame for calculations
00305             desiredPose = poseFrame.Inverse() * desiredPose;
00306             forceItr->second.pose = poseFrame.Inverse() * forceItr->second.pose;
00307             printFrame("converted_desiredPose", desiredPose);
00308 
00309             if (doFeedForward)
00310             {
00311                 velocity = KDL::Twist(forcePID.force, forcePID.torque) + forceItr->second.prevVelocity;
00312             }
00313             else
00314             {
00315                 velocity = KDL::Twist(forcePID.force, forcePID.torque);
00316             }
00317 
00318             limitVelocity(forceItr->second.prevVelocity, velocity);
00319 
00320             //TODO: This will only add position to the xyz, not roll,pitch,yaw right now
00321             KDL::Frame new_desiredPose = desiredPose;
00322             if (forceItr->second.x)
00323             {
00324                 new_desiredPose.p.x(forceItr->second.pose.p.x() + velocity.vel.x() * dt);
00325                 velocity.vel.x(edgeLimit(velocity.vel.x(), new_desiredPose.p.x(), desiredPose.p.x()));
00326                 desiredPose.p.x(forceItr->second.pose.p.x() + velocity.vel.x() * dt);
00327             }
00328             if (forceItr->second.y)
00329             {
00330                 new_desiredPose.p.y(forceItr->second.pose.p.y() + velocity.vel.y() * dt);
00331                 velocity.vel.y(edgeLimit(velocity.vel.y(), new_desiredPose.p.y(), desiredPose.p.y()));
00332                 desiredPose.p.y(forceItr->second.pose.p.y() + velocity.vel.y() * dt);
00333             }
00334             if (forceItr->second.z)
00335             {
00336                 new_desiredPose.p.z(forceItr->second.pose.p.z() + velocity.vel.z() * dt);
00337                 velocity.vel.z(edgeLimit(velocity.vel.z(), new_desiredPose.p.z(), desiredPose.p.z()));
00338                 desiredPose.p.z( forceItr->second.pose.p.z() + velocity.vel.z() * dt) ;
00339             }
00340             if (forceItr->second.roll)
00341             {
00342                 desiredPose.M.DoRotX( velocity.rot.x() * dt );
00343             }
00344             if (forceItr->second.pitch)
00345             {
00346                 desiredPose.M.DoRotY( velocity.rot.y() * dt );
00347             }
00348             if (forceItr->second.yaw)
00349             {
00350                 desiredPose.M.DoRotZ( velocity.rot.z() * dt );
00351             }
00352             //printFrame("New_desiredPose", desiredPose);
00353 
00354             //convert back to world frame
00355             desiredPose = poseFrame * desiredPose;
00356             forceItr->second.pose = poseFrame * forceItr->second.pose;
00357 
00358             // limit the pose error
00359             limitPoseError(desiredPose, nodeFrames.at(i));
00360             //printFrame("FINAL_desiredPose", desiredPose);
00361 
00362 
00363             nodeFrames[i] = desiredPose;
00364             //printFrame("Controller_Node_Frames_Out", nodeFrames[i]);
00365             forceItr->second.pose = desiredPose;
00366             forceItr->second.prevVelocity = velocity;
00367         }
00368     }
00369 }
00370 
00371 double Cartesian_HybCntrl::edgeLimit(double vel, double prev, double input)
00372 {
00373   // Take in the current velociy (aka, the forcePID value) and check to make sure
00374   // it is not with 25% of the error bound positionErrorLimit. If so, limit the PID
00375   // velocity value to less a the percentage and set that velocity.
00376   double comp = prev - input;
00377   if (comp > ((1-edgeBuffer) * positionErrorLimit) || comp <  -((1-edgeBuffer) * positionErrorLimit))
00378   {
00379       cout << "limiting vel from "<< vel << " to";
00380       vel = vel * (1 - (abs(comp) - (1-edgeBuffer) * positionErrorLimit) / (edgeBuffer * positionErrorLimit));
00381       cout << vel << endl;
00382   }
00383   return vel;
00384 }
00385 
00386 void Cartesian_HybCntrl::limitPoseError(KDL::Frame &output_pose, KDL::Frame input_pose)
00387 {
00388   // This function takes the current output pose and limits it based on the prescribed
00389   // maximum distance from the input pose
00390   //TODO: Make this work for rotations as well.
00391 
00392   if (output_pose.p.x() - input_pose.p.x() > positionErrorLimit)
00393   {
00394       output_pose.p.x(input_pose.p.x() + positionErrorLimit);
00395       cout<<"above x limit"<<endl;
00396   }
00397   else if (output_pose.p.x() - input_pose.p.x() < -positionErrorLimit)
00398   {
00399       output_pose.p.x(input_pose.p.x() - positionErrorLimit);
00400       cout<<"below x limit"<<endl;
00401   }
00402 
00403   // Y
00404   if (output_pose.p.y() - input_pose.p.y() > positionErrorLimit)
00405   {
00406       output_pose.p.y(input_pose.p.y() + positionErrorLimit);
00407       cout<<"above y limit"<<endl;
00408   }
00409   else if (output_pose.p.y() - input_pose.p.y() < -positionErrorLimit)
00410   {
00411       output_pose.p.y(input_pose.p.y() - positionErrorLimit);
00412       cout<<"below y limit"<<endl;
00413   }
00414 
00415   // Z
00416   if (output_pose.p.z() - input_pose.p.z() > positionErrorLimit)
00417   {
00418       output_pose.p.z(input_pose.p.z() + positionErrorLimit);
00419       cout<<"above z limit"<<endl;
00420   }
00421   else if (output_pose.p.z() - input_pose.p.z() < -positionErrorLimit)
00422   {
00423       output_pose.p.z(input_pose.p.z() - positionErrorLimit);
00424       cout<<"below z limit"<<endl;
00425   }
00426 }
00427 
00428 void Cartesian_HybCntrl::limitVector(double minVal, double maxVal, KDL::Vector& vector)
00429 {
00430     int i = 0;
00431 
00432     for (; i < 3; ++i)
00433     {
00434         Robodyn::limit(minVal, maxVal, vector[i]);
00435     }
00436 }
00437 
00438 void Cartesian_HybCntrl::limitVelocity(const KDL::Twist& pastVelocity, KDL::Twist& currVelocity)
00439 {
00440     for (int i = 0; i < 3; ++i)
00441     {
00442         currVelocity.vel(i) = linearRateLimiter->getLimitedValue(currVelocity.vel(i), pastVelocity.vel(i));
00443         currVelocity.rot(i) = angularRateLimiter->getLimitedValue(currVelocity.rot(i), pastVelocity.rot(i));
00444         limitVector(-maxLinearVelocity, maxLinearVelocity, currVelocity.vel);
00445         limitVector(-maxAngularVelocity, maxAngularVelocity, currVelocity.rot);
00446     }
00447 }
00448 
00449 std::string Cartesian_HybCntrl::getSensorNameFromNode(const std::string& nodeName)
00450 {
00451     for (std::map<std::string, std::string>::iterator itr = sensorNameMap.begin(); itr != sensorNameMap.end(); ++itr)
00452     {
00453         if (nodeName.find(itr->first) != std::string::npos)
00454         {
00456             return itr->second;
00457         }
00458     }
00459 
00461     NasaCommonLogging::Logger::getCategory(logCategory) << log4cpp::Priority::ERROR << "Could not find sensor for " << nodeName << "!!";
00462     return "";
00463 }


robodyn_controllers
Author(s):
autogenerated on Sat Jun 8 2019 20:20:53