JointCommandFinger.h
Go to the documentation of this file.
00001 
00008 #ifndef JOINTCOMMANDFINGER_H
00009 #define JOINTCOMMANDFINGER_H
00010 
00011 #include "robodyn_mechanisms/JointCommandInterface.h"
00012 #include "robot_instance/StringUtilities.h"
00013 #include "diagnostic_msgs/DiagnosticArray.h"
00014 #include "robodyn_mechanisms/FingerController.h"
00015 #include "EmbeddedSmoother.h"
00016 #include <boost/ptr_container/ptr_array.hpp>
00017 #include "robodyn_utilities/GeneralUtilities.h"
00018 #include <boost/lexical_cast.hpp>
00019 
00020 /***************************************************************************/
00026 template <unsigned int N, unsigned int NHall = N>
00027 class JointCommandFinger : public JointCommandInterface
00028 {
00029 public:
00030     JointCommandFinger(const std::string& mechanism, IoFunctions ioFunctions);
00031     ~JointCommandFinger();
00032 
00033     sensor_msgs::JointState           getSimpleMeasuredState();
00034     sensor_msgs::JointState           getCompleteMeasuredState();
00035     r2_msgs::JointCommand getCommandedState();
00036     void setCommand(r2_msgs::JointCommand msg, r2_msgs::JointControlData control);
00037     void updateMeasuredState(r2_msgs::JointControlData msg);
00038     void setFaultState();
00039 
00040     r2_msgs::JointCapability getCapability();
00041     void loadCoeffs();
00042 
00043 private:
00044     FingerController<N, NHall> controller;
00045     boost::array<std::string, NHall>        hallStateElements;
00046     boost::array < std::string, N + 1 >     encoderStateElements;
00047     boost::array < std::string, N + 1 >     tensionAStateElements;
00048     boost::array < std::string, N + 1 >     tensionBStateElements;
00049     boost::array < std::string, N + 1 >     motComCommandElements;
00050 
00051 
00052     typename FingerController<N, NHall>::JointVectorType    jointVec;
00053     typename FingerController<N, NHall>::HallVectorType     hallVecRaw, hallVec;
00054     typename FingerController<N, NHall>::SliderVectorType   encoderVec, encoderOffset, sliderVec, desiredSliders, desiredSliderVels;
00055     typename FingerController<N, NHall>::SliderVectorType   tensionAVec, tensionBVec, tensionVec, kTendon, fingerBoostMotCom;
00056     typename FingerController<N, NHall>::SliderVectorType   sliderMotComs, sliderVel;
00057 
00058     bool tubeTared;
00059     double kTendonDefault;
00060     bool activeStiffnessOn;
00061     bool useCartesian;
00062     bool isLeft;
00063     double tensionMin;
00064     double fingerBoostTime;
00065     ros::Duration fingerBoostCurrentDuration;
00066     ros::Time fingerBoostTimerStart;
00067 
00068     std::vector<double> positionVals;
00069     std::vector<double> velocityVals;
00070     std::vector<double> effortVals;
00071 
00072     // util
00073     std::vector<std::string>::iterator strVecIt;
00074     boost::ptr_array<EmbeddedSmoother, N> smoother;
00075     typename FingerController<N, NHall>::JointVectorType smoothedPos;
00076     typename FingerController<N, NHall>::JointVectorType prevSmoothedPos;
00077 
00078     // filter values
00079     typename FingerController<N, NHall>::SliderVectorType filteredSliderVec;
00080     typename FingerController<N, NHall>::HallVectorType   filteredHallVec;
00081     std::vector<double> prevPositionVals;
00082     double timestep;
00083     double positionAlpha;
00084     bool filterInitialized;
00085 
00086     // live coeff names
00087     std::string nameIsCalibrated;
00088     std::string nameCoeffState;
00089     boost::array < std::string, N + 1 >          encoderOffsetElements;
00090     boost::array < std::string, N + 1 >          sliderOffsetElements;
00091     boost::array < std::string, N + 1 >          sliderTarePosElements;
00092     boost::array < std::string, N + 1 >          tensionOffsetElements;
00093 
00094     // param names
00095     std::string nameActiveStiffnessOn;
00096     std::string nameUseCartesian;
00097     std::string nameFingerBoostTime;
00098     boost::array < std::string, N + 1 >          nameKTendon;
00099     boost::array < std::string, N + 1 >          nameFingerBoost;
00100 };
00101 
00102 template <unsigned int N, unsigned int NHall>
00103 JointCommandFinger<N, NHall>::JointCommandFinger(const std::string& mechanism, IoFunctions ioFunctions)
00104     : JointCommandInterface(mechanism, ioFunctions)
00105     , desiredSliders(FingerController<N, NHall>::SliderVectorType::Zero())
00106     , tubeTared(false), kTendonDefault(0.0) , activeStiffnessOn(false), useCartesian(false), isLeft(false), tensionMin(0.0), filterInitialized(false)
00107 {
00108     if (mechanism == "")
00109     {
00110         std::stringstream err;
00111         err << "Constructor requires mechanism be non-empty.";
00112         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00113         throw std::invalid_argument(err.str());
00114     }
00115 
00116     if (io.getUInt16.empty())
00117     {
00118         std::stringstream err;
00119         err << "Constructor requires 'io.getUInt16' be non-empty.";
00120         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00121         throw std::invalid_argument(err.str());
00122     }
00123 
00124     if (io.getInt16.empty())
00125     {
00126         std::stringstream err;
00127         err << "Constructor requires 'io.getInt16' be non-empty.";
00128         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00129         throw std::invalid_argument(err.str());
00130     }
00131 
00132     if (io.setInt16.empty())
00133     {
00134         std::stringstream err;
00135         err << "Constructor requires 'io.setInt16' be non-empty.";
00136         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00137         throw std::invalid_argument(err.str());
00138     }
00139 
00140     if (io.getBrainstemCoeff.empty())
00141     {
00142         std::stringstream err;
00143         err << "Constructor requires 'io.getBrainstemCoeff' be non-empty.";
00144         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00145         throw std::invalid_argument(err.str());
00146     }
00147 
00148     if (io.getMotorCoeff.empty())
00149     {
00150         std::stringstream err;
00151         err << "Constructor requires 'io.getMotorCoeff' be non-empty.";
00152         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00153         throw std::invalid_argument(err.str());
00154     }
00155 
00156     if (io.hasLiveCoeff.empty())
00157     {
00158         std::stringstream err;
00159         err << "Constructor requires 'io.hasLiveCoeff' be non-empty.";
00160         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00161         throw std::invalid_argument(err.str());
00162     }
00163 
00164     if (io.getLiveCoeff.empty())
00165     {
00166         std::stringstream err;
00167         err << "Constructor requires 'io.getLiveCoeff' be non-empty.";
00168         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00169         throw std::invalid_argument(err.str());
00170     }
00171 
00172     if (io.setLiveCoeff.empty())
00173     {
00174         std::stringstream err;
00175         err << "Constructor requires 'io.setLiveCoeff' be non-empty.";
00176         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00177         throw std::invalid_argument(err.str());
00178     }
00179 
00180     if (io.hasParam.empty())
00181     {
00182         std::stringstream err;
00183         err << "Constructor requires 'io.hasParam' be non-empty.";
00184         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00185         throw std::invalid_argument(err.str());
00186     }
00187 
00188     if (io.getDoubleParam.empty())
00189     {
00190         std::stringstream err;
00191         err << "Constructor requires 'io.getDoubleParam' be non-empty.";
00192         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00193         throw std::invalid_argument(err.str());
00194     }
00195 
00196     if (io.setDoubleParam.empty())
00197     {
00198         std::stringstream err;
00199         err << "Constructor requires 'io.setDoubleParam' be non-empty.";
00200         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00201         throw std::invalid_argument(err.str());
00202     }
00203 
00204     if (io.getBoolParam.empty())
00205     {
00206         std::stringstream err;
00207         err << "Constructor requires 'io.getBoolParam' be non-empty.";
00208         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00209         throw std::invalid_argument(err.str());
00210     }
00211 
00212     if (io.setBoolParam.empty())
00213     {
00214         std::stringstream err;
00215         err << "Constructor requires 'io.setBoolParam' be non-empty.";
00216         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00217         throw std::invalid_argument(err.str());
00218     }
00219 
00220 
00221     if (io.getJointNames.empty())
00222     {
00223         std::stringstream err;
00224         err << "Constructor requires 'io.getJointNames' be non-empty.";
00225         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00226         throw std::invalid_argument(err.str());
00227     }
00228 
00229     if (io.getAllJointNames.empty())
00230     {
00231         std::stringstream err;
00232         err << "Constructor requires 'io.getAllJointNames' be non-empty.";
00233         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00234         throw std::invalid_argument(err.str());
00235     }
00236 
00237     if (io.getActuatorNames.empty())
00238     {
00239         std::stringstream err;
00240         err << "Constructor requires 'io.getActuatorNames' be non-empty.";
00241         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00242         throw std::invalid_argument(err.str());
00243     }
00244 
00245     if (io.getCommandFile.empty())
00246     {
00247         std::stringstream err;
00248         err << "Constructor requires 'io.getCommandFile' be non-empty.";
00249         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00250         throw std::invalid_argument(err.str());
00251     }
00252 
00253     roboDynJoints    = io.getJointNames(mechanism);
00254     roboDynAllJoints = io.getAllJointNames(mechanism);
00255     roboDynActuators = io.getActuatorNames(mechanism);
00256 
00257     if (roboDynJoints.size() != N or roboDynAllJoints.size() != NHall or roboDynActuators.size() != N + 1)
00258     {
00259         std::stringstream err;
00260         err << "Constructor requires roboDynJoints to have N, roboDynAllJoints to have NHall, and roboDynActuators have N+1 values, where N = " << N << " and NHall = " << NHall << " for this instance\n";
00261 
00262         err << "The current size of roboDynJoints: " << roboDynJoints.size() << " [";
00263 
00264         for (size_t i = 0; i < roboDynJoints.size(); ++i)
00265         {
00266             err << " " << roboDynJoints[i];
00267         }
00268 
00269         err << " ]\n";
00270 
00271         err << "The current size of roboDynAllJoints: " << roboDynAllJoints.size() << " [";
00272 
00273         for (size_t i = 0; i < roboDynAllJoints.size(); ++i)
00274         {
00275             err << " " << roboDynAllJoints[i];
00276         }
00277 
00278         err << " ]\n";
00279 
00280         err << "The current size of roboDynActuators: " << roboDynActuators.size() << " [";
00281 
00282         for (size_t i = 0; i < roboDynActuators.size(); ++i)
00283         {
00284             err << " " << roboDynActuators[i];
00285         }
00286 
00287         err << " ]\n";
00288 
00289         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00290         throw std::invalid_argument(err.str());
00291 
00292     }
00293 
00294     loadCoeffs();
00295 }
00296 
00297 template <unsigned int N, unsigned int NHall>
00298 JointCommandFinger<N, NHall>::~JointCommandFinger()
00299 {}
00300 
00301 template <unsigned int N, unsigned int NHall>
00302 void JointCommandFinger<N, NHall>::loadCoeffs()
00303 {
00304     tubeTared = false;
00305     kTendonDefault = 0.0;
00306     activeStiffnessOn = false;
00307     useCartesian = false;
00308     isLeft = false;
00309     tensionMin = 0.0;
00310     filterInitialized = false;
00311 
00312     std::string parameterFile = io.getCommandFile(mechanism);
00313 
00315     unsigned int numSimpleStates = NHall; // n joints, n+1 sliders (with tension/effort)
00316     simpleMeasuredStateMsg.name.resize(numSimpleStates);
00317     simpleMeasuredStateMsg.position.resize(numSimpleStates, 0.);
00318     simpleMeasuredStateMsg.velocity.resize(numSimpleStates, 0.);
00319     simpleMeasuredStateMsg.effort.resize(numSimpleStates, 0.);
00320 
00321     // NHall hall sensors, N joint embedded commands, and (N + 1) slider embedded commands
00322     unsigned int numCompleteStates = (N) + (NHall) + (N) + 2 * (N + 1);
00323     completeMeasuredStateMsg.name.resize(numCompleteStates);
00324     completeMeasuredStateMsg.position.resize(numCompleteStates, 0.);
00325     completeMeasuredStateMsg.velocity.resize(numCompleteStates, 0.);
00326     completeMeasuredStateMsg.effort.resize(numCompleteStates, 0.);
00327 
00328     commandedStateMsg.name = roboDynJoints;
00329     commandedStateMsg.desiredPosition.resize(N, 0.);
00330     commandedStateMsg.desiredPositionVelocityLimit.resize(N, 0.);
00331     commandedStateMsg.feedForwardTorque.resize(N, 0.);
00332     commandedStateMsg.proportionalGain.resize(N, 0.);
00333     commandedStateMsg.derivativeGain.resize(N, 0.);
00334     commandedStateMsg.integralGain.resize(N, 0.);
00335     commandedStateMsg.positionLoopTorqueLimit.resize(N, 0.);
00336     commandedStateMsg.positionLoopWindupLimit.resize(N, 0.);
00337     commandedStateMsg.torqueLoopVelocityLimit.resize(N, 0.);
00338 
00339     jointCapabilityMsg.name = roboDynJoints;
00340     jointCapabilityMsg.positionLimitMax.resize(N, 0.);
00341     jointCapabilityMsg.positionLimitMin.resize(N, 0.);
00342     jointCapabilityMsg.velocityLimit.resize(N, 30.);  
00343     jointCapabilityMsg.torqueLimit.resize(N, 0.);
00344 
00345     for (unsigned int i = 0; i < numSimpleStates; ++i)
00346     {
00347         simpleMeasuredStateMsg.name[i] = roboDynAllJoints[i];
00348     }
00349 
00350 //    for (unsigned int i = 0; i < N + 1; ++i)
00351 //    {
00352 //        simpleMeasuredStateMsg.name[N + i] = roboDynActuators[i];
00353 //    }
00354 
00355     for (unsigned int i = 0; i < N; ++i)
00356     {
00357         completeMeasuredStateMsg.name[i] = roboDynJoints[i];
00358         completeMeasuredStateMsg.name[2 * N + 1 + i] = roboDynJoints[i] + "/embeddedCommand";
00359     }
00360 
00361     for (unsigned int i = 0; i < N + 1; ++i)
00362     {
00363         completeMeasuredStateMsg.name[N + i] = roboDynActuators[i];
00364         completeMeasuredStateMsg.name[3 * N + 1 + i] = roboDynActuators[i] + "/embeddedCommand";
00365     }
00366 
00367     for (unsigned int i = 0; i < NHall; ++i)
00368     {
00369         completeMeasuredStateMsg.name[4 * N + 2 + i] = roboDynAllJoints[i] + "/halls";
00370     }
00371 
00372     for (unsigned int i = 0; i < (N + 1); ++i)
00373     {
00374         kTendon[i] = kTendonDefault;
00375         fingerBoostMotCom[i] = 0.0;
00376     }
00377 
00378     fingerBoostTime = 0.0;
00379     fingerBoostCurrentDuration = ros::Duration(0.0);
00380     unsigned int numStates = 2 * N + 1;
00381     positionVals.resize(numStates, 0.);
00382     velocityVals.resize(numStates, 0.);
00383     effortVals.resize(numStates, 0.);
00384     prevPositionVals = positionVals;
00385     smoothedPos.setZero();
00386     prevSmoothedPos.setZero();
00387 
00389     TiXmlDocument file(parameterFile.c_str());
00390     bool loadOkay = file.LoadFile();
00391 
00392     if (!loadOkay)
00393     {
00394         std::stringstream err;
00395         err << "Failed to load file [" << parameterFile << "]";
00396         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::FATAL, err.str());
00397         throw std::runtime_error(err.str());
00398     }
00399 
00400     TiXmlHandle doc(&file);
00401     NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::INFO, "CommandFile [" + parameterFile + "] successfully loaded.");
00402 
00403     // Check for ApiMap
00404     TiXmlHandle parametersElement(doc.FirstChildElement("ApiMap"));
00405 
00406     if (parametersElement.ToElement())
00407     {
00409         std::stringstream str;
00410 
00411         for (unsigned int i = 0; i < N + 1; ++i)
00412         {
00413             str.str("");
00414             str << "Actuator" << i << "EncoderState";
00415             encoderStateElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], ApiMap::getXmlElementValue(parametersElement, str.str()));
00416             str.str("");
00417             str << "Actuator" << i << "TensionAState";
00418             tensionAStateElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], ApiMap::getXmlElementValue(parametersElement, str.str()));
00419             str.str("");
00420             str << "Actuator" << i << "TensionBState";
00421             tensionBStateElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], ApiMap::getXmlElementValue(parametersElement, str.str()));
00422             str.str("");
00423             str << "Actuator" << i << "MotComCommand";
00424             motComCommandElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], ApiMap::getXmlElementValue(parametersElement, str.str()));
00425         }
00426 
00427         for (unsigned int i = 0; i < NHall; ++i)
00428         {
00429             str.str("");
00430             str << "Joint" << i << "HallState";
00431             hallStateElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynAllJoints[i], ApiMap::getXmlElementValue(parametersElement, str.str()));
00432         }
00433 
00435         // finger controller coeffs
00436         float tempVal;
00437         tempVal = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MillimetersPerCount")));
00438         controller.setMillimetersPerCount(static_cast<double>(tempVal));
00439 
00440         double hallScale;
00441         hallScale = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "HallScaleFactor")));
00442 
00443         typename FingerController<N, NHall>::HallVectorType hallCoeffs0, hallCoeffs1, hallCoeffs2, hallCoeffs3;
00444 
00445         for (unsigned int i = 0; i < hallCoeffs0.rows(); ++i)
00446         {
00447             str.str("");
00448             str << "Joint" << i << "HallCoeff0";
00449             hallCoeffs0[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00450             str.str("");
00451             str << "Joint" << i << "HallCoeff1";
00452             hallCoeffs1[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00453             str.str("");
00454             str << "Joint" << i << "HallCoeff2";
00455             hallCoeffs2[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00456             str.str("");
00457             str << "Joint" << i << "HallCoeff3";
00458             hallCoeffs3[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00459         }
00460 
00461         controller.setHallAngleParameters(hallScale, hallCoeffs0, hallCoeffs1, hallCoeffs2, hallCoeffs3);
00462 
00463         typename FingerController<N, NHall>::SliderVectorType tensionParam1, tensionParam2, tensionParam3, tensionParam4;
00464 
00465         for (unsigned int i = 0; i < tensionParam1.rows(); ++i)
00466         {
00467             str.str("");
00468             str << "Actuator" << i << "TensionAGain";
00469             tensionParam1[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00470             str.str("");
00471             str << "Actuator" << i << "TensionBGain";
00472             tensionParam2[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00473             str.str("");
00474             str << "Actuator" << i << "TensionSensorCalOffset";
00475             tensionParam3[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00476             str.str("");
00477             str << "Actuator" << i << "CalibratedStrain";
00478             tensionParam4[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00479         }
00480 
00481         controller.setTensionParameters(tensionParam1, tensionParam2, tensionParam3, tensionParam4);
00482 
00483         nameActiveStiffnessOn = StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "ActiveStiffnessOn"));
00484         nameUseCartesian      = StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "UseCartesian"));
00485 
00486         activeStiffnessOn = boost::lexical_cast<bool>(io.getMotorCoeff(nameActiveStiffnessOn));
00487         io.setBoolParam(nameActiveStiffnessOn, activeStiffnessOn);
00488 
00489         useCartesian = boost::lexical_cast<bool>(io.getMotorCoeff(nameUseCartesian));
00490         io.setBoolParam(nameUseCartesian, useCartesian);
00491 
00492         isLeft = !(mechanism.find("left") > 10);
00493 
00494         double kd, tensionMax, tensionKp, tFreq, deadband;
00495         typename FingerController<N, NHall>::JointVectorType stiffnessK, jointKp;
00496         kd = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "KdGain")));
00497         tensionMin = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MinTension")));
00498         tensionMax = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MaxTension")));
00499         tensionKp = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "tensionKpGain")));
00500         tFreq = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "tensionFilterCutoffFreq")));
00501         deadband = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "DeadbandSize")));
00502 
00503         for (unsigned int i = 0; i < stiffnessK.rows(); ++i)
00504         {
00505             str.str("");
00506             str << "Joint" << i << "stiffnessKGain";
00507             stiffnessK[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00508             str.str("");
00509             str << "Joint" << i << "torqueKpGain";
00510             jointKp[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00511         }
00512 
00513         controller.setStiffnessGains(stiffnessK, kd, tensionMin, tensionMax, jointKp, tensionKp, tFreq, deadband);
00514 
00515         tempVal = io.getBrainstemCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "BusVoltage")));
00516         controller.setBusVoltage(static_cast<double>(tempVal));
00517 
00518         // filter
00519         positionAlpha = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "PositionAlpha")));
00520 
00521         // "embedded" smoothing
00522         EmbeddedSmoother::Settings smoothSettings;
00523         timestep = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "Timestep")));
00524 
00525         if (timestep <= 0.)
00526         {
00527             throw std::runtime_error("invalid timestep");
00528         }
00529 
00530         smoothSettings.timestep = timestep;
00531 
00532         for (unsigned int i = 0; i < N; ++i)
00533         {
00534             str.str("");
00535             str << "Joint" << i << "MinimumVelocity";
00536             smoothSettings.minVel = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00537             str.str("");
00538             str << "Joint" << i << "MaximumAcceleration";
00539             smoothSettings.maxAcc = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00540             str.str("");
00541             str << "Joint" << i << "AccelerationGain";
00542             smoothSettings.accGain = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00543             smoother.replace(i, new EmbeddedSmoother(smoothSettings));
00544         }
00545 
00547         MultiLoopController tempController;
00548         tempController.setLoopRate(1. / timestep);
00549 
00550         double bypass =             io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "PositionLoopBypass")));
00551         double sliderMinPosition =  io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMinPositionCommand")));
00552         double sliderMaxPosition =  io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMaxPositionCommand")));
00553         double pKp               =  io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderKpGainCommand")));
00554 
00555         tempController.setPositionLoopParameters(sliderMinPosition, sliderMaxPosition, pKp, !(bypass <= 0));
00556 
00557         bypass =               io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "TorqueLoopBypass")));
00558         double minTension =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMinTensionCommand")));
00559         double maxTension =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMaxTensionCommand")));
00560         double tKp        =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderTensionKpGainCommand")));
00561         double offset     =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderTensionOffsetCommand")));
00562 
00563         tempController.setTorqueLoopParameters(minTension, maxTension, tKp, offset, !(bypass <= 0));
00564 
00565         bypass =                io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "VelocityLoopBypass")));
00566         double minVelocity =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMinVelocityCommand" )));
00567         double maxVelocity =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMaxVelocityCommand" )));
00568         double vKp =            io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderVelocityKpGainCommand" )));
00569         double vKi =            io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderVelocityKiGainCommand" )));
00570         double windup =         io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderIntegratorWindupLimit" )));
00571 
00572         tempController.setVelocityLoopParameters(minVelocity, maxVelocity, vKp, vKi, windup, !(bypass <= 0));
00573 
00574         bypass =                io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "CurrentLoopBypass")));
00575         double minCurrent =     io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMinCurrentCommand" )));
00576         double maxCurrent =     io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMaxCurrentCommand" )));
00577         double maxDutyCycle =   io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "SliderMaxDutyCycleCommand" )));
00578 
00579         tempController.setCurrentLoopParameters(minCurrent, maxCurrent, maxDutyCycle, !(bypass <= 0));
00580 
00581         double motorViscousDampingComp =    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotorViscousDampingCompensation" )));
00582         double motorInertia =               io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotorInertia" )));
00583         double motorTorqueConst =           io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotorTorqueConstant" )));
00584         double motorPhaseRes =              io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotorPhaseResistance" )));
00585         double motorBackEMF =               io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotorBackEMFConstant" )));
00586         double motorImductance =            io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotorInductance" )));
00587         double motionRatio =                io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "MotionRatio" )));
00588         double PWMFreq =                    io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "PWMFrequency" )));
00589         double bridgeDeadTime =             io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "BridgeDeadTime" )));
00590         double bridgeSwitchTime =           io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, "BridgeSwitchTime" )));
00591 
00592         tempController.setHardwareParameters(motorViscousDampingComp, motorInertia, motorTorqueConst, motorPhaseRes, motorBackEMF, motorImductance, motionRatio, PWMFreq, bridgeDeadTime, bridgeSwitchTime);
00593 
00594         for (unsigned int i = 0; i < N + 1; ++i)
00595         {
00596             controller.setMultiLoopController(tempController, i);
00597         }
00598 
00599         for (unsigned int i = 0; i < N; ++i)
00600         {
00601             str.str("");
00602             str << "Joint" << i << "PositionMin";
00603             jointCapabilityMsg.positionLimitMin[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00604             str.str("");
00605             str << "Joint" << i << "PositionMax";
00606             jointCapabilityMsg.positionLimitMax[i] = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00607         }
00608 
00610         typename FingerController<N, NHall>::ReferenceMatrixType refMatrix;
00611 
00612         for (unsigned int i = 0; i < refMatrix.rows(); ++i)
00613         {
00614             for (unsigned int j = 0; j < refMatrix.cols(); ++j)
00615             {
00616                 str.str("");
00617                 str << "ReferenceMatrix" << i << j;
00618                 refMatrix(i, j) = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism,  ApiMap::getXmlElementValue(parametersElement, str.str())));
00619             }
00620         }
00621 
00622         controller.setReferenceMatrix(refMatrix);
00623 
00625         nameIsCalibrated          = StringUtilities::makeFullyQualifiedRoboDynElement(mechanism, "CalibrationMode");
00626         nameCoeffState            = StringUtilities::makeFullyQualifiedRoboDynElement(mechanism, "CoeffState");
00627 
00628 
00629 
00630         for (unsigned int i = 0; i < N + 1; ++i)
00631         {
00632             nameKTendon[i]           = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], "KTendon");
00633             io.setDoubleParam(nameKTendon[i], kTendon[i]);
00634 
00635             nameFingerBoost[i]       = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], "FingerBoostMotCom");
00636             io.setDoubleParam(nameFingerBoost[i], fingerBoostMotCom[i]);
00637 
00638             encoderOffsetElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], "EncoderOffset");
00639             sliderOffsetElements[i]  = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], "SliderOffset");
00640             sliderTarePosElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], "SliderTarePosition");
00641             tensionOffsetElements[i] = StringUtilities::makeFullyQualifiedRoboDynElement(roboDynActuators[i], "TensionOffset");
00642         }
00643 
00644         nameFingerBoostTime          = StringUtilities::makeFullyQualifiedRoboDynElement(mechanism, "FingerBoostTime");
00645         io.setDoubleParam(nameFingerBoostTime, fingerBoostTime);
00646 
00647         io.setLiveCoeff(nameIsCalibrated,   r2_msgs::JointControlCalibrationMode::UNCALIBRATED);
00648         io.setLiveCoeff(nameCoeffState,     r2_msgs::JointControlCoeffState::LOADED);
00649     }
00650     else
00651     {
00652         std::stringstream err;
00653         err << "The file " << parameterFile << " has no element named [ApiMap]";
00654         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::ERROR, err.str());
00655         throw std::runtime_error(err.str());
00656     }
00657 }
00658 
00659 template <unsigned int N, unsigned int NHall>
00660 void JointCommandFinger<N, NHall>::updateMeasuredState(r2_msgs::JointControlData msg)
00661 {
00662     unsigned int i;
00663 
00664     // get params
00665 
00666     if (!io.getBoolParam(nameActiveStiffnessOn, activeStiffnessOn))
00667     {
00668         std::stringstream err;
00669         err << "rosparam [" << nameActiveStiffnessOn << "] does not exist.";
00670         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::ERROR, err.str());
00671         throw std::runtime_error(err.str());
00672     }
00673 
00674     if (!io.getBoolParam(nameUseCartesian, useCartesian))
00675     {
00676         std::stringstream err;
00677         err << "rosparam [" << nameUseCartesian << "] does not exist.";
00678         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::ERROR, err.str());
00679         throw std::runtime_error(err.str());
00680     }
00681 
00682     // If coeffs are not loaded, override with zeros RDEV-1075
00683     if (msg.coeffState.state != r2_msgs::JointControlCoeffState::LOADED)
00684     {
00685         unsigned int numStates = 2 * N + 1; // n joints, n+1 sliders (with tension/effort)
00686         positionVals.assign(numStates, 0.0);
00687         velocityVals.assign(numStates, 0.0);
00688         effortVals.assign(numStates, 0.0);
00689         return;
00690     }
00691 
00692     for (i = 0; i < encoderStateElements.size(); ++i)
00693     {
00694         encoderVec[i] = io.getInt16(encoderStateElements[i]);
00695     }
00696 
00697     for (i = 0; i < hallStateElements.size(); ++i)
00698     {
00699         hallVecRaw[i] = io.getUInt16(hallStateElements[i]);
00700     }
00701 
00702     for (i = 0; i < tensionAStateElements.size(); ++i)
00703     {
00704         tensionAVec[i] = io.getUInt16(tensionAStateElements[i]);
00705     }
00706 
00707     for (i = 0; i < tensionBStateElements.size(); ++i)
00708     {
00709         tensionBVec[i] = io.getUInt16(tensionBStateElements[i]);
00710     }
00711 
00712     // get hall positions
00713     controller.getHallAngles(hallVecRaw, hallVec);
00714 
00715     if (io.getLiveCoeff(nameIsCalibrated) == r2_msgs::JointControlCalibrationMode::DISABLE)
00716     {
00717         // calibrated
00718         if (!tubeTared)
00719         {
00720             typename FingerController<N, NHall>::SliderVectorType sliderOffset, sliderTarePos, tensionOffset;
00721 
00722             for (i = 0; i < encoderOffset.rows(); ++i)
00723             {
00724                 encoderOffset[i] = io.getLiveCoeff(encoderOffsetElements[i]);
00725                 sliderOffset[i]  = io.getLiveCoeff(sliderOffsetElements[i]);
00726                 sliderTarePos[i] = io.getLiveCoeff(sliderTarePosElements[i]);
00727                 tensionOffset[i] = io.getLiveCoeff(tensionOffsetElements[i]);
00728             }
00729 
00730             sliderOffset -= encoderOffset;
00731             controller.reset();
00732 
00733             //check that tensions are above the minimum tension, or adjust tensionOffset
00734             controller.getCalibratedTensions(tensionAVec, tensionBVec, 0.0, tensionVec);
00735 
00736             for (i = 0; i < encoderOffset.rows(); ++i)
00737             {
00738                 if (tensionVec[i] < tensionMin)
00739                 {
00740                     tensionOffset[i] += tensionVec[i] - tensionMin;    //tensionVec.sum()/tensionVec.rows();
00741                 }
00742             }
00743 
00744             controller.setTubeTareParameters(sliderOffset, sliderTarePos, tensionOffset);
00745             filterInitialized = false;
00746             tubeTared = true;
00747         }
00748 
00749         // get positions
00750         encoderVec -= encoderOffset;
00751         controller.getSlidersFromEncoders(encoderVec, sliderVec);
00752 
00753         // filter sliders and halls
00754         if (!filterInitialized)
00755         {
00756             filteredSliderVec = sliderVec;
00757             filteredHallVec = hallVec;
00758         }
00759 
00760         filteredSliderVec = filteredSliderVec * positionAlpha + sliderVec * (1 - positionAlpha);
00761         filteredHallVec = filteredHallVec * positionAlpha + hallVec * (1 - positionAlpha);
00762 
00763         controller.getJointsFromSliders(filteredSliderVec, jointVec);
00764 
00765         //use hall sensor data
00766         // TODO: Check functionality of activeStiffness given passive hall additions
00767         if (activeStiffnessOn)
00768         {
00769             if (sliderVec.rows() >= 4)                 //limits operation to thumb, rows == 5, and primaries, rows == 4 (secondaries only have 3 actuators)
00770             {
00771                 jointVec.tail(3) = hallVec.tail(3);    //don't use roll joint hall on thumb
00772             }
00773         }
00774 
00775 
00776         //don't use secondary finger halls (doesn't use combined proximal/medial joint angles)
00777 
00778         // get tensions
00779         controller.getCalibratedTensions(tensionAVec, tensionBVec, timestep, tensionVec);
00780         typename FingerController<N, NHall>::JointVectorType xyPos, desTorques;
00781 
00782         for (i = 0; i < N; ++i)
00783         {
00784             Robodyn::limit(jointCapabilityMsg.positionLimitMin[i], jointCapabilityMsg.positionLimitMax[i], jointVec[i]);
00785         }
00786 
00787         if (useCartesian)
00788         {
00789             controller.getXYPos(jointVec, isLeft, xyPos, desTorques);
00790         }
00791         else
00792         {
00793             xyPos = jointVec;
00794             desTorques = FingerController<N, NHall>::JointVectorType::Zero();
00795         }
00796 
00797         for (i = 0; i < N; ++i)
00798         {
00799             positionVals[i] = xyPos[i];
00800             effortVals[i] = desTorques[i];
00801         }
00802 
00803         for (i = 0; i < N + 1; ++i)
00804         {
00805             positionVals[N + i] = filteredSliderVec[i];
00806             effortVals[N + i]   = tensionVec[i];
00807         }
00808     }
00809     else
00810     {
00811         // not calibrated
00812         tubeTared = false;
00813 
00814         for (i = 0; i < N; ++i)
00815         {
00816             positionVals[i] = 0.;
00817         }
00818 
00819         for (i = 0; i < N + 1; ++i)
00820         {
00821             positionVals[N + i] = 0.;
00822             effortVals[N + i]   = 0.;
00823         }
00824     }
00825 
00826     // get velocities
00827     if (!filterInitialized)
00828     {
00829         velocityVals.assign(velocityVals.size(), 0.);
00830         filterInitialized = true;
00831     }
00832     else
00833     {
00834         for (unsigned int i = 0; i < velocityVals.size(); ++i)
00835         {
00836             velocityVals[i] = (positionVals[i] - prevPositionVals[i]) / timestep;
00837         }
00838     }
00839 
00840     prevPositionVals = positionVals;
00841 }
00842 
00843 template <unsigned int N, unsigned int NHall>
00844 sensor_msgs::JointState JointCommandFinger<N, NHall>::getSimpleMeasuredState()
00845 {
00846     for (unsigned int i = 0; i < N; ++i)
00847     {
00848         // joint vals
00849         simpleMeasuredStateMsg.velocity[i] = velocityVals[i];
00850         simpleMeasuredStateMsg.effort[i] = effortVals[i];
00851     }
00852 
00853     for (unsigned int i = 0; i < NHall; ++i)
00854     {
00855         simpleMeasuredStateMsg.position[i] = hallVec[i];
00856     }
00857 
00858     simpleMeasuredStateMsg.header.stamp = ros::Time::now();
00859     return simpleMeasuredStateMsg;
00860 }
00861 
00862 template <unsigned int N, unsigned int NHall>
00863 sensor_msgs::JointState JointCommandFinger<N, NHall>::getCompleteMeasuredState()
00864 {
00865     prevSmoothedPos = (smoothedPos - prevSmoothedPos) / timestep;
00866     unsigned int index = 0;
00867 
00868     for (unsigned int i = 0; i < N; ++i)
00869     {
00870         // joint vals
00871         completeMeasuredStateMsg.position[i] = positionVals[i];
00872         completeMeasuredStateMsg.velocity[i] = velocityVals[i];
00873         completeMeasuredStateMsg.effort[i] = effortVals[i];
00874 
00875         // joint embeddedCommands
00876         index = 2 * N + 1 + i;
00877         completeMeasuredStateMsg.position[index] = smoothedPos[i];
00878         completeMeasuredStateMsg.velocity[index] = prevSmoothedPos[i];
00879     }
00880 
00881     // halls
00882     for (unsigned int i = 0; i < NHall; ++i)
00883     {
00884         index = 4 * N + 2 + i;
00885         completeMeasuredStateMsg.position[index] = hallVec[i];
00886     }
00887 
00888     for (unsigned int i = 0; i < N + 1; ++i)
00889     {
00890         // slider vals
00891         index = N + i;
00892         completeMeasuredStateMsg.position[index] = positionVals[index];
00893         completeMeasuredStateMsg.velocity[index] = velocityVals[index];
00894         completeMeasuredStateMsg.effort[index] = effortVals[index];
00895 
00896         // slider embeddedCommands
00897         index = 3 * N + 1 + i;
00898         completeMeasuredStateMsg.position[index] = desiredSliders[i];
00899         completeMeasuredStateMsg.velocity[index] = desiredSliderVels[i];
00900         completeMeasuredStateMsg.effort[index] = sliderMotComs[i];
00901     }
00902 
00903     completeMeasuredStateMsg.header.stamp = ros::Time::now();
00904     prevSmoothedPos = smoothedPos;
00905     return completeMeasuredStateMsg;
00906 }
00907 
00908 template <unsigned int N, unsigned int NHall>
00909 r2_msgs::JointCommand JointCommandFinger<N, NHall>::getCommandedState()
00910 {
00911     commandedStateMsg.header.stamp = ros::Time::now();
00912     return commandedStateMsg;
00913 }
00914 
00915 template <unsigned int N, unsigned int NHall>
00916 void JointCommandFinger<N, NHall>::setFaultState()
00917 {
00918 }
00919 
00920 template <unsigned int N, unsigned int NHall>
00921 void JointCommandFinger<N, NHall>::setCommand(r2_msgs::JointCommand msg, r2_msgs::JointControlData control)
00922 {
00923 
00924     // get KTendon parameter
00925     for (unsigned int i = 0; i < (N + 1); ++i)
00926     {
00927         if (!io.getDoubleParam(nameKTendon[i], kTendon[i]))
00928         {
00929             std::stringstream err;
00930             err << "param [" << nameKTendon[i] << "] does not exist.";
00931             NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::ERROR, err.str());
00932             throw std::runtime_error(err.str());
00933         }
00934     }
00935 
00936     // get fingerBoost parameters if appropriate
00937     double prevFingerBoostTime = fingerBoostTime;
00938 
00939     if (!io.getDoubleParam(nameFingerBoostTime, fingerBoostTime))
00940     {
00941         std::stringstream err;
00942         err << "param [" << nameFingerBoostTime << "] does not exist.";
00943         NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::ERROR, err.str());
00944         throw std::runtime_error(err.str());
00945     }
00946 
00947     if (fingerBoostTime > 0 && fingerBoostTime != prevFingerBoostTime)
00948     {
00949         fingerBoostTimerStart = ros::Time::now();
00950 
00951         for (unsigned int i = 0; i < (N + 1); ++i)
00952         {
00953             if (!io.getDoubleParam(nameFingerBoost[i], fingerBoostMotCom[i]))
00954             {
00955                 std::stringstream err;
00956                 err << "param [" << nameFingerBoost[i] << "] does not exist.";
00957                 NasaCommonLogging::Logger::log("gov.nasa.robonet.JointCommandFinger", log4cpp::Priority::ERROR, err.str());
00958                 throw std::runtime_error(err.str());
00959             }
00960         }
00961     }
00962     else if (fingerBoostTime > 0)
00963     {
00964         fingerBoostCurrentDuration = ros::Time::now() - fingerBoostTimerStart;
00965     }
00966     else
00967     {
00968         for (unsigned int i = 0; i < N + 1; ++i)
00969         {
00970             io.setDoubleParam(nameFingerBoost[i], 0.0);
00971             io.getDoubleParam(nameFingerBoost[i], fingerBoostMotCom[i]);
00972         }
00973     }
00974 
00975     if (fingerBoostCurrentDuration > ros::Duration(fingerBoostTime))
00976     {
00977         io.setDoubleParam(nameFingerBoostTime, 0.0);
00978         io.getDoubleParam(nameFingerBoostTime, fingerBoostTime);
00979 
00980         for (unsigned int i = 0; i < N + 1; ++i)
00981         {
00982             io.setDoubleParam(nameFingerBoost[i], 0.0);
00983             io.getDoubleParam(nameFingerBoost[i], fingerBoostMotCom[i]);
00984         }
00985 
00986         fingerBoostCurrentDuration = ros::Duration(0.0);
00987     }
00988 
00989     // end of fingerBoost parameter setting
00990 
00991 
00992     if (!msg.name.empty() && !msg.desiredPosition.empty())
00993     {
00994         if (msg.desiredPositionVelocityLimit.empty())
00995         {
00996             msg.desiredPositionVelocityLimit.resize(msg.name.size(), 0.);
00997         }
00998 
00999         for (unsigned int i = 0; i < msg.name.size(); ++i)
01000         {
01001             strVecIt = std::find(commandedStateMsg.name.begin(), commandedStateMsg.name.end(), msg.name[i]);
01002 
01003             if (strVecIt != commandedStateMsg.name.end())
01004             {
01005                 unsigned int index = strVecIt - commandedStateMsg.name.begin();
01006 
01007                 Robodyn::limit(jointCapabilityMsg.positionLimitMin[index], jointCapabilityMsg.positionLimitMax[index], msg.desiredPosition[i]);
01008 
01009                 // smooth if in drive and not in actuator
01010                 if (control.controlMode.state == r2_msgs::JointControlMode::DRIVE
01011                         && control.commandMode.state != r2_msgs::JointControlCommandMode::ACTUATOR)
01012                 {
01013                     smoothedPos[index] = smoother[index].update(msg.desiredPosition[i], msg.desiredPositionVelocityLimit[i]);
01014                 }
01015                 else
01016                 {
01017                     smoothedPos[index] = msg.desiredPosition[i];
01018                     smoother[index].reset(smoothedPos[index], 0.);
01019                 }
01020 
01021 
01022                 commandedStateMsg.desiredPosition[index] = msg.desiredPosition[i];
01023                 commandedStateMsg.desiredPositionVelocityLimit[index] = msg.desiredPositionVelocityLimit[i];
01024             }
01025         }
01026     }
01027 
01028     if (control.calibrationMode.state == r2_msgs::JointControlCalibrationMode::ENABLE)
01029     {
01030         // do nothing if calibrating (tubetare controls when in this mode)
01031         return;
01032     }
01033 
01034     if (control.commandMode.state == r2_msgs::JointControlCommandMode::MOTCOM)
01035     {
01036         for (unsigned int i = 0; i < msg.name.size(); ++i)
01037         {
01038             strVecIt = std::find(roboDynActuators.begin(), roboDynActuators.end(), msg.name[i]);
01039 
01040             if (strVecIt != roboDynActuators.end())
01041             {
01042                 sliderMotComs[strVecIt - roboDynActuators.begin()] = msg.desiredPosition[i];
01043             }
01044         }
01045     }
01046     else if (control.commandMode.state == r2_msgs::JointControlCommandMode::ACTUATOR)
01047     {
01048         for (unsigned int i = 0; i < msg.name.size(); ++i)
01049         {
01050             strVecIt = std::find(roboDynActuators.begin(), roboDynActuators.end(), msg.name[i]);
01051 
01052             if (strVecIt != roboDynActuators.end())
01053             {
01054                 desiredSliders[strVecIt - roboDynActuators.begin()] = msg.desiredPosition[i];
01055             }
01056         }
01057 
01058         // get equivalent joint command
01059         controller.getJointsFromSliders(desiredSliders, smoothedPos);
01060 
01061         for (unsigned int i = 0; i < smoothedPos.size(); ++i)
01062         {
01063             commandedStateMsg.desiredPosition[i] = smoothedPos[i];
01064             smoother[i].reset(smoothedPos[i], 0.);
01065         }
01066 
01067         // get motcoms
01068         sliderVel = FingerController<N, NHall>::SliderVectorType::Map(&(velocityVals[N]));
01069         controller.getMotComs(desiredSliders, kTendon, filteredSliderVec, tensionVec, sliderVel, sliderMotComs, desiredSliderVels, fingerBoostMotCom);
01070 
01071     }
01072     else
01073     {
01074         // get motcoms
01075         sliderVel = FingerController<N, NHall>::SliderVectorType::Map(&(velocityVals[N]));
01076 
01077         if (activeStiffnessOn)
01078         {
01079 //            typename FingerController<N, NHall>::SliderVectorType sliderVel1;
01081 //            sliderVel1 = FingerController<N, NHall>::SliderVectorType::Map(&(velocityVals[N]));
01082             controller.getDesiredSlidersStiffness(smoothedPos, jointVec, filteredSliderVec, tensionVec, sliderVel, useCartesian, isLeft, desiredSliders);
01083         }
01084         else
01085         {
01086             controller.getDesiredSliders(smoothedPos, filteredSliderVec, desiredSliders);
01087         }
01088 
01089         controller.getMotComs(desiredSliders, kTendon, filteredSliderVec, tensionVec, sliderVel, sliderMotComs, desiredSliderVels, fingerBoostMotCom);
01090     }
01091 
01092 
01093     if (control.controlMode.state == r2_msgs::JointControlMode::DRIVE)
01094     {
01095         for (unsigned int i = 0; i < sliderMotComs.rows(); ++i)
01096         {
01097             io.setInt16(motComCommandElements[i], static_cast<int16_t>(sliderMotComs[i]));
01098         }
01099     }
01100     else
01101     {
01102         desiredSliderVels.setZero();
01103 
01105         for (unsigned int i = 0; i < motComCommandElements.size(); ++i)
01106         {
01107             io.setInt16(motComCommandElements[i], 0);
01108         }
01109     }
01110 }
01111 
01112 template <unsigned int N, unsigned int NHall>
01113 r2_msgs::JointCapability JointCommandFinger<N, NHall>::getCapability()
01114 {
01115     return jointCapabilityMsg;
01116 }
01117 
01118 
01119 #endif


robodyn_mechanisms
Author(s):
autogenerated on Thu Jun 6 2019 21:22:48