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;
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
00219 try
00220 {
00221 poseFrame = referenceFrameMap.at(forceItr->first);
00222
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
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
00247 desiredPose = nodeFrames.at(i);
00248
00249
00250
00251
00252
00253 wrenchSensorFrame = forceItr->second.sensorForce;
00254
00255
00256
00257 wrenchDesired = forceItr->second.desiredForce;
00258
00259
00260
00261 KDL::Frame T_FP;
00262 T_FP = poseFrame.Inverse() * sensorFrame;
00263
00264
00265
00266
00267 wrenchPoseFrame = T_FP * wrenchSensorFrame;
00268
00269
00270
00271 forceError = wrenchDesired - wrenchPoseFrame;
00272
00273
00274
00275
00276
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
00281
00282
00283
00284 forceItr->second.integrator.force += fKi * forceError.force;
00285 forceItr->second.integrator.torque += tKi * forceError.torque;
00286
00287 limitVector(-forceIntegralWindupLimit, forceIntegralWindupLimit, forceItr->second.integrator.force);
00288 limitVector(-torqueIntegralWindupLimit, torqueIntegralWindupLimit, forceItr->second.integrator.torque);
00289
00290
00291
00292
00293 forceItr->second.error = forceError;
00294 forceItr->second.gain.force = fKp * forceError.force;
00295 forceItr->second.gain.torque = tKp * forceError.torque;
00296
00297
00298
00299 forcePID = forceItr->second.gain + forceItr->second.integrator + forceItr->second.derivative;
00300 printWrench("forcePID", forcePID);
00301
00303
00304
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
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
00353
00354
00355 desiredPose = poseFrame * desiredPose;
00356 forceItr->second.pose = poseFrame * forceItr->second.pose;
00357
00358
00359 limitPoseError(desiredPose, nodeFrames.at(i));
00360
00361
00362
00363 nodeFrames[i] = desiredPose;
00364
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
00374
00375
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
00389
00390
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
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
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 }