50 #include "rnr/rnrconfig.h" 52 #include "Dynamixel/Dynamixel.h" 53 #include "Dynamixel/DynaServo.h" 84 #define HEK_TRY_GET_SERVO(nServoId, pServo) \ 87 if( (pServo = m_robot.m_pDynaChain->GetServo(nServoId)) == NULL ) \ 89 LOGERROR("BUG: Servo %d: Cannot find in dynamixel chain.", nServoId); \ 90 return -HEK_ECODE_INTERNAL; \ 112 int HekCalibStretch::calibrate()
114 MapRobotJoints::iterator pos;
123 m_robot.m_pKin->resetServoOdometersForAllJoints();
128 for(i=0, rc=HEK_OK; (i<arraysize(CalibOrder)) && (rc >= 0); ++i)
133 if( (pJoint = m_robot.getArmJoint(strJointName)) == NULL )
139 if( pJoint->
m_eOpState == HekOpStateCalibrated )
144 LOGDIAG2(
"\n----------- Calibrating Joint %s...", strJointName.c_str());
150 if( eLimitTypes & HekLimitTypeElecTDC )
152 rc = calibrateJointTopDeadCenter(*pJoint);
156 else if( eLimitTypes & HekLimitTypeElec )
158 rc = calibrateJointByLimits(*pJoint);
162 else if( eLimitTypes & HekLimitTypePhys )
164 rc = calibrateJointByTorqueLimits(*pJoint);
168 else if( eLimitTypes & HekLimitTypeNone )
170 rc = calibrateJointByTrust(*pJoint);
173 else if( eLimitTypes & HekLimitTypeAbsEnc )
175 LOGWARN(
"Joint %s: Absolute encoders are not supported yet.",
176 strJointName.c_str());
182 LOGWARN(
"Joint %s: Do not know how to calibrate this joint.",
183 strJointName.c_str());
186 pJoint->
m_eOpState = rc == HEK_OK? HekOpStateCalibrated:
187 HekOpStateUncalibrated;
196 static double TuneCalVel =
degToRad(20.0);
199 static double TuneMinAngle =
degToRad(20.0);
207 double fJointGoalPos;
208 double fJointCalibPos;
224 LOGDIAG2(
"Joint %s (servo=%d): Calibrating by TDC optical limits.",
232 LOGERROR(
"Joint %s (servo=%d): Not a continuous joint.",
234 return -HEK_ECODE_NO_EXEC;
240 for(i=0, byOptMask=0x00; i<HekOptLimitMaxPerJoint; ++i)
248 if( byOptMask == 0x00 )
250 LOGERROR(
"Joint %s (servo=%d): No optical limit bits set, spec correct?",
251 strJointName.c_str(), nServoId);
252 return -HEK_ECODE_INTERNAL;
259 LOGDIAG2(
"Joint %s (servo=%d): " 260 "Determining joint top-dead-center by optical limit(s).",
261 strJointName.c_str(), nServoId);
263 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
265 LOGDIAG2(
"Joint %s (servo=%d): Starting at uncalibrated %.2lf degrees.",
266 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
278 if( byOptBits == 0x00 )
280 LOGDIAG2(
"Joint %s (servo=%d): " 281 "Determining joint optical limit light-to-dark edge.",
282 strJointName.c_str(), nServoId);
284 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
286 fJointGoalPos = fJointCurPos - TuneMinAngle;
289 LOGDIAG2(
"Joint %s (servo=%d): Move to the dark for <= %.2lf degrees.",
290 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
292 moveToDark(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
294 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
296 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
297 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
307 if( byOptBits == 0x00 )
309 LOGDIAG2(
"Joint %s (servo=%d): Did not find the dark. Reverse direction.",
310 strJointName.c_str(), nServoId);
312 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
314 fJointGoalPos = fJointCurPos +
M_TAU;
317 LOGDIAG2(
"Joint %s (servo=%d): " 318 "Move to the dark for <= %.2lf degrees in the maximum direction.",
319 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
321 moveToDark(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
323 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
325 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
326 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
335 if( byOptBits == 0x00 )
337 LOGERROR(
"Joint %s (servo=%d): Did not find any optical limits.",
338 strJointName.c_str(), nServoId);
339 return -HEK_ECODE_NO_EXEC;
345 for(i=0, byOptMask=0x00; i<HekOptLimitMaxPerJoint; ++i)
356 LOGERROR(
"Joint %s (servo=%d): Fine tuning failed.",
357 strJointName.c_str(), nServoId);
364 if( fJointCalibPos != 0.0 )
366 if( fJointCalibPos < M_PI )
368 fJointGoalPos = fJointCalibPos;
372 fJointGoalPos =
M_TAU - fJointCalibPos;
375 LOGDIAG2(
"Joint %s (servo=%d): " 376 "Move to the new zero point at %.2lf degrees.",
377 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
379 moveWait(strJointName, fJointGoalPos, TuneCalVel);
381 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
383 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
384 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
390 m_robot.m_pKin->resetServoOdometer(strJointName);
392 LOGDIAG2(
"Joint %s (servo=%d): Odometer reset.",
393 strJointName.c_str(), nServoId);
409 LOGDIAG2(
"Joint %s (servo=%d): Move to calibrated zero pt=%.2lf degrees.",
414 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
416 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
417 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
423 m_robot.m_pKin->getServoCurPosSpeed(strJointName,
424 nServoCurPos, nServoCurSpeed);
426 LOGDIAG2(
"Joint %s (servo=%d): Calibrated by TDC optical limits:\n" 427 " Top dead center: %.02lfdeg (od=%d).",
428 strJointName.c_str(), nServoId, 0.0, nServoCurPos);
436 static double TuneCalVel =
degToRad(20.0);
439 static double TuneMarginAngle =
degToRad(50.0);
447 double fJointGoalPos;
448 double fJointCalibPos;
474 pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
476 LOGDIAG2(
"Joint %s (servo=%d): Calibrating by optical limits.",
482 if( byOptMask == 0x00 )
484 LOGERROR(
"Joint %s (servo=%d): No optical limit bits set, spec correct?",
485 strJointName.c_str(), nServoId);
486 return -HEK_ECODE_INTERNAL;
492 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
494 LOGDIAG2(
"Joint %s (servo=%d): Starting at %.2lf uncalibrated degrees.",
495 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
507 if( byOptBits != 0x00 )
509 LOGDIAG2(
"Joint %s (servo=%d): " 510 "Determining joint optical limit dark-to-light edge.",
511 strJointName.c_str(), nServoId);
522 if( fAngle2 > fAngle1 )
527 fAngle1 += TuneMarginAngle;
529 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
531 fJointGoalPos = fJointCurPos + (double)nDir * fAngle1;
533 LOGDIAG2(
"Joint %s (servo=%d): Move to light for <= %.2lf degrees.",
534 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
537 multiMoveToLight(strJointName, nDir, fJointGoalPos, TuneCalVel, byOptMask);
539 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
541 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
542 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
545 byOptBits = m_robot.m_monitor.getJointLimitBits();
553 LOGDIAG2(
"Joint %s (servo=%d): " 554 "Did not find the light. Reverse direction.",
555 strJointName.c_str(), nServoId);
559 m_robot.m_pKin->getJointCurPosVel(strJointName,
560 fJointCurPos, fJointCurVel);
562 fJointGoalPos = fJointCurPos + (double)nDir * fAngle1;
564 LOGDIAG2(
"Joint %s (servo=%d): Move to light <= %.2lf degrees.",
565 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
567 multiMoveToLight(strJointName, nDir, fJointGoalPos, TuneCalVel,
570 m_robot.m_pKin->getJointCurPosVel(strJointName,
571 fJointCurPos, fJointCurVel);
573 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
574 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
578 byOptBits = m_robot.m_monitor.getJointLimitBits();
585 m_robot.m_pKin->getJointCurPosVel(strJointName,
586 fJointCurPos, fJointCurVel);
588 LOGDIAG2(
"Joint %s (servo=%d): Got a light edge at %.2lf degrees.",
589 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
591 return calibByLimitsFinal(joint, byOptMask, nDir);
599 LOGERROR(
"Joint %s (servo=%d): " 600 "Could not find optical limit switch light.",
601 strJointName.c_str(), nServoId);
602 return -HEK_ECODE_NO_EXEC;
614 nDir = nServoId == HekServoIdShoulderL? -1: 1;
620 fAngle1 += TuneMarginAngle;
622 LOGDIAG2(
"Joint %s (servo=%d): " 623 "Determining joint optical limit light-to-dark minimum edge.",
624 strJointName.c_str(), nServoId);
626 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
628 fJointGoalPos = fJointCurPos + (double)nDir * fAngle1;
630 LOGDIAG2(
"Joint %s (servo=%d): Move to dark for <= %.2lf degrees.",
631 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
634 multiMoveToDark(strJointName, nDir, fJointGoalPos, TuneCalVel, byOptMask);
636 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
638 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
639 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
642 byOptBits = m_robot.m_monitor.getJointLimitBits();
649 m_robot.m_pKin->getJointCurPosVel(strJointName,
650 fJointCurPos, fJointCurVel);
652 LOGDIAG2(
"Joint %s (servo=%d): Got a dark edge at %.2lf degrees.",
653 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
655 return calibByLimitsFinal(joint, byOptMask, nDir);
660 LOGERROR(
"Joint %s (servo=%d): " 661 "Could not find optical limit occlusion edge.",
662 strJointName.c_str(), nServoId);
664 return -HEK_ECODE_NO_EXEC;
668 LOGERROR(
"BUG: Joint %s (servo=%d): Should not be here.",
669 strJointName.c_str(), nServoId);
671 return -HEK_ECODE_INTERNAL;
679 static double TuneCalVel =
degToRad(20.0);
682 static double TuneMarginAngle =
degToRad(10.0);
692 double fJointGoalPos;
693 double fJointCalibPos;
704 pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
707 if( (rc = fineTuneLimit(joint, byOptMask, nDir, fJointCalibPos)) < 0 )
709 LOGERROR(
"Joint %s (servo=%d): Fine tuning failed.",
710 strJointName.c_str(), nServoId);
714 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
716 fJointGoalPos = fJointCurPos - fJointCalibPos;
724 if( strJointName ==
"shoulder" )
726 string strJointName2(
"elbow");
727 double fGearRatios = calcJointRatios(strJointName2, strJointName);
728 m_robot.m_pKin->move(strJointName2, 0.0, 0.75 * fGearRatios * TuneCalVel);
731 LOGDIAG2(
"Joint %s (servo=%d): Move to the new zero point at %.2lf degrees.",
732 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
734 moveWait(strJointName, fJointGoalPos, TuneCalVel);
736 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
738 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
739 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
741 m_robot.m_pKin->resetServoOdometer(strJointName);
743 LOGDIAG2(
"Joint %s (servo=%d): Odometer reset.",
744 strJointName.c_str(), nServoId);
759 LOGDIAG2(
"Joint %s (servo=%d): Calibrated by optical limits:\n" 760 " Physical limits: [%.2lfdeg (od=%d), %.2lfdeg (od=%d)]\n" 761 " Soft limits: [%.2lfdeg (od=%d), %.2lfdeg (od=%d)].",
762 strJointName.c_str(), nServoId,
774 static double TuneCalVel =
degToRad(20.0);
777 static double TuneBackoff =
degToRad(0.1);
788 double fJointStartPos;
791 double fJointGoalPos;
799 LOGDIAG2(
"Joint %s (servo=%d): Calibrating by torque limits.",
805 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointStartPos, fJointCurVel);
807 LOGDIAG2(
"Joint %s (servo=%d): Starting at %.2lf uncalibrated degrees.",
808 strJointName.c_str(), nServoId,
radToDeg(fJointStartPos));
814 LOGDIAG2(
"Joint %s (servo=%d): " 815 "Determining minimum joint angle by torque limit.",
818 fJointCurPos = fJointStartPos;
827 fJointGoalPos = -
M_TAU + -fabs(fJointCurPos);
836 if( (nServoPos = pServo->CalcOdometerAtEncMin()) > 0 )
838 nServoPos = pServo->CalcOdometerAtEncMax();
840 fJointGoalPos = m_robot.m_pKin->servoPosToJointPos(strJointName, nServoPos);
843 LOGDIAG2(
"Joint %s (servo=%d): Move to minimum >= %.2lf degrees.",
844 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
846 moveToTorqueLimit(strJointName, fJointGoalPos, TuneCalVel);
849 m_robot.m_pKin->getJointCurPosVel(strJointName, fMinLimit, fJointCurVel);
851 LOGDIAG2(
"Joint %s (servo=%d): Minimum reached at %.2lf degrees.",
852 strJointName.c_str(), nServoId,
radToDeg(fMinLimit));
857 LOGDIAG2(
"Joint %s (servo=%d): Move back to start at %.2lf degrees.",
858 strJointName.c_str(), nServoId,
radToDeg(fJointStartPos));
860 moveWait(strJointName, fJointStartPos, TuneCalVel);
862 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
864 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
865 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
871 LOGDIAG2(
"Joint %s (servo=%d): " 872 "Determining maximum joint angle by torque limit.",
876 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
885 fJointGoalPos =
M_TAU + fabs(fJointCurPos);
894 if( (nServoPos = pServo->CalcOdometerAtEncMin()) < 0 )
896 nServoPos = pServo->CalcOdometerAtEncMax();
898 fJointGoalPos = m_robot.m_pKin->servoPosToJointPos(strJointName, nServoPos);
901 LOGDIAG2(
"Joint %s (servo=%d): Move to maximum <= %.2lf degrees.",
902 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
904 moveToTorqueLimit(strJointName, fJointGoalPos, TuneCalVel);
907 m_robot.m_pKin->getJointCurPosVel(strJointName, fMaxLimit, fJointCurVel);
909 LOGDIAG2(
"Joint %s (servo=%d): Maximum reached at %.2lf degrees.",
910 strJointName.c_str(), nServoId,
radToDeg(fMaxLimit));
915 LOGDIAG2(
"Joint %s (servo=%d): Move back again to start at %.2lf degrees.",
916 strJointName.c_str(), nServoId,
radToDeg(fJointStartPos));
918 moveWait(strJointName, fJointStartPos, TuneCalVel);
920 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
922 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
923 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
932 fJointRange = fMaxLimit - fMinLimit;
937 fJointGoalPos = fMinLimit;
939 LOGDIAG2(
"Joint %s (servo=%d): Move to the new zero point at %.2lf degrees.",
940 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
942 moveToTorqueLimit(strJointName, fJointGoalPos, TuneCalVel);
944 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
946 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
947 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
952 m_robot.m_pKin->resetServoOdometer(strJointName);
954 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
956 LOGDIAG2(
"Joint %s (servo=%d): Odometer reset.",
957 strJointName.c_str(), nServoId);
976 if( nServoId == HekServoIdGraboid )
995 LOGDIAG2(
"Joint %s (servo=%d): Move to calibrated zero pt=%.2lf degrees.",
1000 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1002 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
1003 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
1009 LOGDIAG2(
"Joint %s (servo=%d): Calibrated by torque:\n" 1010 " Physical limits: [%.2lfdeg (od=%d), %.2lfdeg (od=%d)]\n" 1011 " Soft limits: [%.2lfdeg (od=%d), %.2lfdeg (od=%d)].",
1023 string strJointName;
1027 double fJointCurPos;
1028 double fJointCurVel;
1037 LOGDIAG2(
"Joint %s (servo=%d): Calibrating by trust.",
1043 m_robot.m_pKin->resetServoOdometer(strJointName);
1046 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1047 m_robot.m_pKin->getServoCurPosSpeed(strJointName,
1053 LOGDIAG2(
"Joint %s (servo=%d): Calibrated by trust:\n" 1054 " Top dead center: %.2lf deg (od=%d).",
1055 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos), nServoCurPos);
1059 LOGDIAG2(
"Joint %s (servo=%d): Calibrated by trust:\n" 1060 " Rotation [min, max] limits: [%.2lfdeg (od=%d), %.2lfdeg (od=%d)].",
1061 strJointName.c_str(), nServoId,
1075 static double TuneCalVel =
degToRad(10.0);
1078 static double TuneFudge =
degToRad(5.0);
1080 string strJointName;
1087 double fJointStartPos;
1088 double fJointCurPos;
1089 double fJointCurVel;
1090 double fJointGoalPos;
1092 double fLitEdgePos0;
1093 double fLitEdgePos1;
1099 pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
1101 LOGDIAG3(
"Joint %s (servo=%d): opt_mask=0x%02x, edge=%d.",
1102 strJointName.c_str(), nServoId, byOptMask, nEdge);
1104 LOGDIAG2(
"Joint %s (servo=%d): " 1105 "Occlusion band: max=%lfdeg, center=%lfdeg, min=%lfdeg.",
1106 strJointName.c_str(), nServoId,
1115 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointStartPos, fJointCurVel);
1120 fJointGoalPos = fJointStartPos + nEdge * fBandWidth;
1122 LOGDIAG2(
"Joint %s (servo=%d): " 1123 "Fine tune move for <= %.2lf degrees to find the first light edge.",
1124 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
1126 moveToLight(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1129 byOptBits = m_robot.m_monitor.getJointLimitBits();
1137 m_robot.m_pKin->getJointCurPosVel(strJointName, fLitEdgePos0, fJointCurVel);
1139 LOGDIAG2(
"Joint %s (servo=%d): Edge 0 at %.2lf degrees.",
1140 strJointName.c_str(), nServoId,
radToDeg(fLitEdgePos0));
1148 if( m_robot.m_pKin->hasOverTorqueCondition(strJointName) )
1150 LOGERROR(
"Joint %s (servo=%d): Cannot calibrate: Joint is obstucted.",
1152 rc = -HEK_ECODE_COLLISION;
1156 LOGERROR(
"Joint %s (servo=%d): Cannot calibrate: " 1157 "Did not find edge 0 of the occlusion band.",
1159 rc = -HEK_ECODE_NO_EXEC;
1172 LOGDIAG2(
"Joint %s (servo=%d): " 1173 "Move back into the occlusion band at %.2lf degrees.",
1174 strJointName.c_str(), nServoId,
radToDeg(fJointStartPos));
1176 moveToDark(strJointName, fJointStartPos, TuneCalVel, byOptMask);
1179 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1181 LOGDIAG2(
"Joint %s (servo=%d): Stopped at %.2lf degrees.",
1182 strJointName.c_str(), nServoId,
radToDeg(fJointCurPos));
1187 fJointGoalPos = fJointCurPos - nEdge * fBandWidth;
1189 LOGDIAG2(
"Joint %s (servo=%d): " 1190 "Fine tune move for %.2lf degrees to find the opposite light edge.",
1191 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
1194 moveToLight(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1197 byOptBits = m_robot.m_monitor.getJointLimitBits();
1205 m_robot.m_pKin->getJointCurPosVel(strJointName, fLitEdgePos1, fJointCurVel);
1207 LOGDIAG2(
"Joint %s (servo=%d): Edge 1 at %.2lf degrees.",
1208 strJointName.c_str(), nServoId,
radToDeg(fLitEdgePos1));
1216 if( m_robot.m_pKin->hasOverTorqueCondition(strJointName) )
1218 LOGERROR(
"Joint %s (servo=%d): Cannot calibrate: Joint is obstucted.",
1220 rc = (rc == HEK_OK)? -HEK_ECODE_COLLISION: rc;
1224 LOGERROR(
"Joint %s (servo=%d): Cannot calibrate: " 1225 "Did not find edge 1 of occlusion band.",
1227 rc = (rc == HEK_OK)? -HEK_ECODE_NO_EXEC: rc;
1236 fJointGoalPos = (fLitEdgePos1 + fLitEdgePos0) / 2.0;
1238 LOGDIAG2(
"Joint %s (servo=%d): Move to TDC at %.2lf degrees.",
1239 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
1241 moveWait(strJointName, fJointGoalPos, TuneCalVel);
1243 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1247 LOGDIAG2(
"Joint %s (servo=%d): Fine tune TDC diff = %.2lf degrees.",
1248 strJointName.c_str(), nServoId,
radToDeg(fPosition));
1260 static double TuneCalVel =
degToRad(5.0);
1263 static double TuneFudge =
degToRad(10.0);
1265 string strJointName;
1271 double fJointCurPos;
1272 double fJointCurVel;
1273 double fJointGoalPos;
1282 pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
1284 m_robot.m_pKin->stop(strJointName);
1287 byOptBits = m_robot.m_monitor.getJointLimitBits();
1295 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1297 fJointGoalPos = fJointCurPos + (double)nDir * TuneFudge;
1299 LOGDIAG2(
"Joint %s (servo=%d): " 1300 "Fine tune move for <= %.2lf degrees to find light edge.",
1301 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
1303 moveToLight(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1305 m_robot.m_pKin->getJointCurPosVel(strJointName, fLightPos, fJointCurVel);
1307 LOGDIAG2(
"Joint %s (servo=%d): Stopped at first light at %.2lf degrees.",
1308 strJointName.c_str(), nServoId,
radToDeg(fLightPos));
1312 byOptBits = m_robot.m_monitor.getJointLimitBits();
1317 LOGERROR(
"Joint %s (servo=%d): Cannot find occlusion band edge.",
1318 strJointName.c_str(), nServoId);
1319 return -HEK_ECODE_NO_EXEC;
1326 m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1328 fJointGoalPos = fJointCurPos + (double)nDir * TuneFudge;
1330 LOGDIAG2(
"Joint %s (servo=%d): " 1331 "Fine tune move for <= %.2lf degrees to find dark edge.",
1332 strJointName.c_str(), nServoId,
radToDeg(fJointGoalPos));
1334 moveToDark(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1336 m_robot.m_pKin->getJointCurPosVel(strJointName, fDarkPos, fJointCurVel);
1338 LOGDIAG2(
"Joint %s (servo=%d): Stopped at first dark at %.2lf degrees.",
1339 strJointName.c_str(), nServoId,
radToDeg(fDarkPos));
1342 byOptBits = m_robot.m_monitor.getJointLimitBits();
1349 if( m_robot.m_pKin->hasOverTorqueCondition(strJointName) )
1351 LOGERROR(
"Joint %s (servo=%d): Cannot calibrate: Joint is obstucted.",
1352 strJointName.c_str(), nServoId);
1353 rc = -HEK_ECODE_COLLISION;
1357 LOGERROR(
"Joint %s (servo=%d): Cannot calibrate: " 1358 "Did not find the dark edge of occlusion band.",
1359 strJointName.c_str(), nServoId);
1360 rc = -HEK_ECODE_NO_EXEC;
1367 fEdgePos = (fLightPos + fDarkPos) / 2.0;
1380 double HekCalibStretch::calcJointRatios(
const string &strJointName1,
1381 const string &strJointName2)
1386 if( (pJoint = m_robot.getArmJoint(strJointName1)) != NULL )
1389 if( (pJoint = m_robot.getArmJoint(strJointName2)) != NULL )
1406 int HekCalibStretch::multiMoveToLight(
const string &strJointName,
1408 double fJointGoalPos,
1409 double fJointGoalVel,
1412 string strJointName2;
1414 double fJointGoalPos2;
1415 double fJointGoalVel2;
1418 if( strJointName ==
"shoulder" )
1420 strJointName2 =
"elbow";
1421 fGearRatios = calcJointRatios(strJointName2, strJointName);
1424 fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMinSoftLimitRads;
1428 fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMaxSoftLimitRads;
1430 fJointGoalVel2 = fGearRatios * fJointGoalVel;
1431 m_robot.m_pKin->move(strJointName2, fJointGoalPos2, fJointGoalVel2);
1435 moveToLight(strJointName, fJointGoalPos, fJointGoalVel, byMask);
1438 if( strJointName2.size() > 0 )
1440 m_robot.m_pKin->stop(strJointName2);
1446 int HekCalibStretch::multiMoveToDark(
const string &strJointName,
1448 double fJointGoalPos,
1449 double fJointGoalVel,
1452 string strJointName2;
1454 double fJointGoalPos2;
1455 double fJointGoalVel2;
1458 if( strJointName ==
"shoulder" )
1460 strJointName2 =
"elbow";
1461 fGearRatios = calcJointRatios(strJointName2, strJointName);
1464 fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMinSoftLimitRads;
1468 fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMaxSoftLimitRads;
1470 fJointGoalVel2 = fGearRatios * fJointGoalVel;
1471 m_robot.m_pKin->move(strJointName2, fJointGoalPos2, fJointGoalVel2);
1475 moveToDark(strJointName, fJointGoalPos, fJointGoalVel, byMask);
1478 if( strJointName2.size() > 0 )
1480 m_robot.m_pKin->stop(strJointName2);
1488 switch( nChildServoId )
1490 case HekServoIdWristPitch:
1491 return &(m_robot.m_jointsArm[HekServoIdElbow]);
1492 case HekServoIdElbow:
1493 return &(m_robot.m_jointsArm[HekServoIdShoulderL]);
HekCalib - Hekateros calibration abstract base class interface.
int m_nMaxSoftLimitOd
joint max soft limit (odometer ticks)
HekOpState m_eOpState
current operational state
double m_fMinSoftLimitRads
joint min soft limit (radians)
int m_eLimitTypes
joint limit types
Operational robotic joint description class.
double m_fTicksPerJointRad
encoder/odom. ticks per joint radian
int m_eJointType
joint type
HekCalibStretch - Hekateros calibration by stretching class interface.
#define M_TAU
tau = 2 * pi
int m_nMinPhyLimitOd
joint min phys limit (odometer ticks)
double radToDeg(double r)
Convert radians to degrees.
int m_nMasterServoId
master servo id
double m_fMinBlackPos
minimum complete occlusion position
double m_fParkPosRads
joint parked position (radians)
double m_fCalibPosRads
joint calibrated position (radians)
double m_fMinPhyLimitRads
joint min physical limit (radians)
Hekateros Monitor Class interface.
double m_fMaxEdgePos
maxinum edge position of occlusion band
bool m_bIsServoContinuous
servo should [not] be continuous mode
int m_nMinSoftLimitOd
joint min soft limit (odometer ticks)
Hekateros joint classes interfaces.
int m_nMaxPhyLimitOd
joint max phys limit (odometer ticks)
double m_fMaxBlackPos
maximum complete occlusion position
double m_fMinEdgePos
mininum edge position of occlusion band
byte_t m_byOptLimitMask[HekOptLimitMaxPerJoint]
optical limit mask array
bool m_bStopAtOptLimits
do [not] stop at optical limits
static byte_t getDarkOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits have been triggered (occluded).
HekRobot - Hekateros Robot Class interface.
#define HEK_TRY_GET_SERVO(nServoId, pServo)
Convenience macro for trying to get a servo object from dynamixel chain.
std::string m_strName
joint name
Top-level package include file.
double degToRad(double d)
Convert degrees to radians.
double m_fMaxSoftLimitRads
joint max soft limit (radians)
static byte_t getLitOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits are lit (not occluded).
static const string CalibOrder[]
Calibration order by master servo id.
int m_nMasterServoDir
master servo normalized direction
double m_fGearRatio
joint gear ratio
double m_fMaxPhyLimitRads
joint max physical limit (radians)
double m_fCenterPos
center of operation position
The <b><i>Hekateros</i></b> namespace encapsulates all <b><i>Hekateros</i></b> related constructs...