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
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
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
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
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;
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
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
00351
00352
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
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
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
00519 positionAlpha = io.getMotorCoeff(StringUtilities::makeFullyQualifiedRoboDynElement( mechanism, ApiMap::getXmlElementValue(parametersElement, "PositionAlpha")));
00520
00521
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
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
00683 if (msg.coeffState.state != r2_msgs::JointControlCoeffState::LOADED)
00684 {
00685 unsigned int numStates = 2 * N + 1;
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
00713 controller.getHallAngles(hallVecRaw, hallVec);
00714
00715 if (io.getLiveCoeff(nameIsCalibrated) == r2_msgs::JointControlCalibrationMode::DISABLE)
00716 {
00717
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
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;
00741 }
00742 }
00743
00744 controller.setTubeTareParameters(sliderOffset, sliderTarePos, tensionOffset);
00745 filterInitialized = false;
00746 tubeTared = true;
00747 }
00748
00749
00750 encoderVec -= encoderOffset;
00751 controller.getSlidersFromEncoders(encoderVec, sliderVec);
00752
00753
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
00766
00767 if (activeStiffnessOn)
00768 {
00769 if (sliderVec.rows() >= 4)
00770 {
00771 jointVec.tail(3) = hallVec.tail(3);
00772 }
00773 }
00774
00775
00776
00777
00778
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
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
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
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
00871 completeMeasuredStateMsg.position[i] = positionVals[i];
00872 completeMeasuredStateMsg.velocity[i] = velocityVals[i];
00873 completeMeasuredStateMsg.effort[i] = effortVals[i];
00874
00875
00876 index = 2 * N + 1 + i;
00877 completeMeasuredStateMsg.position[index] = smoothedPos[i];
00878 completeMeasuredStateMsg.velocity[index] = prevSmoothedPos[i];
00879 }
00880
00881
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
00891 index = N + i;
00892 completeMeasuredStateMsg.position[index] = positionVals[index];
00893 completeMeasuredStateMsg.velocity[index] = velocityVals[index];
00894 completeMeasuredStateMsg.effort[index] = effortVals[index];
00895
00896
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
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
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
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
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
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
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
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
01075 sliderVel = FingerController<N, NHall>::SliderVectorType::Map(&(velocityVals[N]));
01076
01077 if (activeStiffnessOn)
01078 {
01079
01081
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