Hekateros  3.4.3
RoadNarrows Robotics Robot Arm Project
hekateros::HekCalibStretch Class Reference

Hekateros robotic manipulator calibration by stretching class. More...

#include <hekCalibStretch.h>

Inheritance diagram for hekateros::HekCalibStretch:
hekateros::HekCalib

Public Member Functions

 HekCalibStretch (HekRobot &robot)
 
virtual ~HekCalibStretch ()
 
virtual int calibrate ()
 Calibrate the Hekateros's robotic arm. More...
 
- Public Member Functions inherited from hekateros::HekCalib
 HekCalib (HekRobot &robot)
 
virtual ~HekCalib ()
 
virtual double moveWait (const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
 Move joint to position. More...
 
virtual double moveToTorqueLimit (const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
 Move joint until torque limit is reached. More...
 
virtual double moveToLight (const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
 Move joint until unoccluded optical limit position is detected. More...
 
virtual double moveToDark (const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
 Move joint until occluded optical limit position is detected. More...
 

Protected Member Functions

virtual int calibrateJointTopDeadCenter (HekRobotJoint &joint)
 Calibrate a continuously rotating joint by top-dead-center electronic limits. More...
 
virtual int calibrateJointByLimits (HekRobotJoint &joint)
 Calibrate a rovolute joint by electronic limits. More...
 
virtual int calibByLimitsFinal (HekRobotJoint &joint, byte_t byOptMask, int nEdge)
 Perform final calibration by limits calculations and movements. More...
 
virtual int calibrateJointByTorqueLimits (HekRobotJoint &joint)
 Calibrate joint by torque limits. More...
 
virtual int calibrateJointByTrust (HekRobotJoint &joint)
 Calibrate joint by trust. More...
 
virtual int fineTuneTDC (HekRobotJoint &joint, byte_t byOptMask, int nEdge, double &fPosition)
 Fine tune joint to top dead center of optical limit. More...
 
virtual int fineTuneLimit (HekRobotJoint &joint, byte_t byOptMask, int nEdge, double &fDeltaPos)
 Fine tune joint to optical limit edge. More...
 
double calcJointRatios (const std::string &strJointName1, const std::string &strJointName2)
 Calculate two joints' gear ratios. More...
 
virtual int multiMoveToLight (const std::string &strJointName, int nDir, double fJointGoalPos, double fJointGoalVel, byte_t byMask)
 Move joint until unoccluded optical limit position is detected. More...
 
virtual int multiMoveToDark (const std::string &strJointName, int nDir, double fJointGoalPos, double fJointGoalVel, byte_t byMask)
 Move joint until occluded optical limit position is detected. More...
 
virtual HekRobotJointgetHelpfulParentJoint (int nChildServoId)
 Get the parent joint (and link) that could aid in calibration. More...
 

Additional Inherited Members

- Protected Attributes inherited from hekateros::HekCalib
HekRobotm_robot
 robot instance
 

Detailed Description

Hekateros robotic manipulator calibration by stretching class.

The hekateros will do a choreographed sequence of moves to find the limits or top-dead-centers for all joints.

Note
It is best if the user places the arm in the upright position and with not obstructions in the workspace prior to executing sequence.
Move Sequence:
  • End effector open and close limits. (torque determines this range).
  • Wrist rotation top dead center.
  • Wrist pitch clockwise and counter-clockwise limits.
  • Elbow clockwise and counter-clockwise limits.
  • Shoulder clockwise and counter-clockwise limits.
  • Base rotation top dead center.

Definition at line 83 of file hekCalibStretch.h.

Constructor & Destructor Documentation

hekateros::HekCalibStretch::HekCalibStretch ( HekRobot robot)
inline

Default initialization constructor.

Parameters
robotInstance of Hekateros robot.

Definition at line 92 of file hekCalibStretch.h.

92  : HekCalib(robot)
93  {
94  }
HekCalib(HekRobot &robot)
Definition: hekCalib.h:82

Member Function Documentation

double HekCalibStretch::calcJointRatios ( const std::string &  strJointName1,
const std::string &  strJointName2 
)
protected

Calculate two joints' gear ratios.

Parameters
strJointName1First joint. strJointName2 Second joint.
Returns
joint1 gear ratio to joint 2 gear ratio.

Definition at line 1380 of file hekCalibStretch.cxx.

References hekateros::HekRobotJoint::m_fGearRatio.

Referenced by ~HekCalibStretch().

1382 {
1383  HekRobotJoint *pJoint; // working joint description
1384  double fGearRatios; // gear ratio 1 to gear ratio 2
1385 
1386  if( (pJoint = m_robot.getArmJoint(strJointName1)) != NULL )
1387  {
1388  fGearRatios = pJoint->m_fGearRatio;
1389  if( (pJoint = m_robot.getArmJoint(strJointName2)) != NULL )
1390  {
1391  fGearRatios /= pJoint->m_fGearRatio;
1392  }
1393  else
1394  {
1395  fGearRatios = 0.0;
1396  }
1397  }
1398  else
1399  {
1400  fGearRatios = 0.0;
1401  }
1402 
1403  return fGearRatios;
1404 }
HekRobotJoint * getArmJoint(const std::string &strName)
Get robotic joint in arm+ee kinematic chain.
Definition: hekRobot.h:610
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
Operational robotic joint description class.
Definition: hekJoint.h:80
double m_fGearRatio
joint gear ratio
Definition: hekJoint.h:155
int HekCalibStretch::calibByLimitsFinal ( HekRobotJoint joint,
byte_t  byOptMask,
int  nEdge 
)
protectedvirtual

Perform final calibration by limits calculations and movements.

Parameters
jointRobotic joint.
byOptMaskJoint optical limit bit mask;
nEdgeWhich edge triggered limit switch. The minimum, unknown, or maximum leading edge is specified as < 0, 0, or > 0, respectively.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 674 of file hekCalibStretch.cxx.

References hekateros::degToRad(), hekateros::HekRobotJoint::m_bStopAtOptLimits, hekateros::HekOpticalLimit_T::m_fMaxEdgePos, hekateros::HekRobotJoint::m_fMaxPhyLimitRads, hekateros::HekRobotJoint::m_fMaxSoftLimitRads, hekateros::HekOpticalLimit_T::m_fMinEdgePos, hekateros::HekRobotJoint::m_fMinPhyLimitRads, hekateros::HekRobotJoint::m_fMinSoftLimitRads, hekateros::HekRobotJoint::m_fTicksPerJointRad, hekateros::HekRobotJoint::m_nMasterServoDir, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_nMaxPhyLimitOd, hekateros::HekRobotJoint::m_nMaxSoftLimitOd, hekateros::HekRobotJoint::m_nMinPhyLimitOd, hekateros::HekRobotJoint::m_nMinSoftLimitOd, hekateros::HekRobotJoint::m_strName, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

677 {
678  // joint calibrating velocity (radians/second)
679  static double TuneCalVel = degToRad(20.0);
680 
681  // additional angle margin (radians)
682  static double TuneMarginAngle = degToRad(10.0);
683 
684  string strJointName; // joint name
685  int nServoId; // servo id
686  bool bIsReverse; // odometer is [not] reversed
687 
688  HekOpticalLimit_T *pLimit; // limit info associated with mask
689 
690  double fJointCurPos; // user's starting/current position (radians)
691  double fJointCurVel; // joint current velocity (radians/second)
692  double fJointGoalPos; // joint working goal position (radians)
693  double fJointCalibPos; // joint calibrated position (radians)
694 
695  int nServoCurPos; // servo current position (odometer ticks)
696  int nServoCurSpeed; // servo current speed (raw unitless)
697 
698  int i; // working index
699  int rc; // return code
700 
701  strJointName = joint.m_strName;
702  nServoId = joint.m_nMasterServoId;
703  bIsReverse = joint.m_nMasterServoDir == DYNA_DIR_CCW? false: true;
704  pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
705 
706  // fine tune edge
707  if( (rc = fineTuneLimit(joint, byOptMask, nDir, fJointCalibPos)) < 0 )
708  {
709  LOGERROR("Joint %s (servo=%d): Fine tuning failed.",
710  strJointName.c_str(), nServoId);
711  return rc;
712  }
713 
714  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
715 
716  fJointGoalPos = fJointCurPos - fJointCalibPos;
717 
718  //
719  // Special joint movements.
720  //
721  // Note: Slow down the elbow a tad to reduce hard stop at new zero point.
722  // Looks cleaner.
723  //
724  if( strJointName == "shoulder" )
725  {
726  string strJointName2("elbow");
727  double fGearRatios = calcJointRatios(strJointName2, strJointName);
728  m_robot.m_pKin->move(strJointName2, 0.0, 0.75 * fGearRatios * TuneCalVel);
729  }
730 
731  LOGDIAG2("Joint %s (servo=%d): Move to the new zero point at %.2lf degrees.",
732  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
733 
734  moveWait(strJointName, fJointGoalPos, TuneCalVel);
735 
736  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
737 
738  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
739  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
740 
741  m_robot.m_pKin->resetServoOdometer(strJointName);
742 
743  LOGDIAG2("Joint %s (servo=%d): Odometer reset.",
744  strJointName.c_str(), nServoId);
745 
746  //
747  // Adjust limits and positions.
748  //
749  joint.m_fMinSoftLimitRads = pLimit->m_fMinEdgePos;
750  joint.m_fMaxSoftLimitRads = pLimit->m_fMaxEdgePos;
751  joint.m_nMinSoftLimitOd = (int)(joint.m_fMinSoftLimitRads *
752  joint.m_fTicksPerJointRad);
753  joint.m_nMaxSoftLimitOd = (int)(joint.m_fMaxSoftLimitRads *
754  joint.m_fTicksPerJointRad);
755 
756  // Enable optical limit stopping for joint during normal operation.
757  joint.m_bStopAtOptLimits = true;
758 
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,
767 
768  return HEK_OK;
769 }
HekOpticalLimit_T * getJointLimitInfo(byte_t byMask)
Get joint limits information.
Definition: hekMonitor.h:403
int m_nMaxSoftLimitOd
joint max soft limit (odometer ticks)
Definition: hekJoint.h:169
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
double m_fMinSoftLimitRads
joint min soft limit (radians)
Definition: hekJoint.h:166
double calcJointRatios(const std::string &strJointName1, const std::string &strJointName2)
Calculate two joints&#39; gear ratios.
Optical limit switch.
Definition: hekOptical.h:148
double m_fTicksPerJointRad
encoder/odom. ticks per joint radian
Definition: hekJoint.h:157
virtual double moveWait(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
Move joint to position.
Definition: hekCalib.cxx:65
int m_nMinPhyLimitOd
joint min phys limit (odometer ticks)
Definition: hekJoint.h:164
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
virtual int fineTuneLimit(HekRobotJoint &joint, byte_t byOptMask, int nEdge, double &fDeltaPos)
Fine tune joint to optical limit edge.
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
double m_fMinPhyLimitRads
joint min physical limit (radians)
Definition: hekJoint.h:162
double m_fMaxEdgePos
maxinum edge position of occlusion band
Definition: hekOptical.h:182
int m_nMinSoftLimitOd
joint min soft limit (odometer ticks)
Definition: hekJoint.h:168
int m_nMaxPhyLimitOd
joint max phys limit (odometer ticks)
Definition: hekJoint.h:165
double m_fMinEdgePos
mininum edge position of occlusion band
Definition: hekOptical.h:178
virtual int resetServoOdometer(const std::string &strJointName)
Reset joint&#39;s master servo odometer to the current encoder position.
Definition: hekKin.cxx:336
bool m_bStopAtOptLimits
do [not] stop at optical limits
Definition: hekJoint.h:180
std::string m_strName
joint name
Definition: hekJoint.h:149
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
double m_fMaxSoftLimitRads
joint max soft limit (radians)
Definition: hekJoint.h:167
HekMonitor m_monitor
power, health, and safety monitor
Definition: hekRobot.h:709
int m_nMasterServoDir
master servo normalized direction
Definition: hekJoint.h:153
double m_fMaxPhyLimitRads
joint max physical limit (radians)
Definition: hekJoint.h:163
virtual int move(HekJointTrajectoryPoint &trajectoryPoint)
Move kinematic chain through a trajectory point.
Definition: hekKin.cxx:500
int HekCalibStretch::calibrate ( )
virtual

Calibrate the Hekateros's robotic arm.

Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Implements hekateros::HekCalib.

Definition at line 112 of file hekCalibStretch.cxx.

References CalibOrder, hekateros::HekRobotJoint::m_eLimitTypes, and hekateros::HekRobotJoint::m_eOpState.

Referenced by hekateros::HekRobot::calibrate(), and ~HekCalibStretch().

113 {
114  MapRobotJoints::iterator pos;
115 
116  string strJointName;
117  HekRobotJoint *pJoint;
118  int eLimitTypes;
119  size_t i;
120  int rc;
121 
122  // reset odometer to current arm pose
124 
125  //
126  // Calibrate Hekateros joints in the specified calibration order.
127  //
128  for(i=0, rc=HEK_OK; (i<arraysize(CalibOrder)) && (rc >= 0); ++i)
129  {
130  strJointName = CalibOrder[i];
131 
132  // no joint in this product version with associated joint name
133  if( (pJoint = m_robot.getArmJoint(strJointName)) == NULL )
134  {
135  continue;
136  }
137 
138  // already calibrated
139  if( pJoint->m_eOpState == HekOpStateCalibrated )
140  {
141  continue;
142  }
143 
144  LOGDIAG2("\n----------- Calibrating Joint %s...", strJointName.c_str());
145 
146  eLimitTypes = pJoint->m_eLimitTypes;
148 
149  // one or more top dead center electronic switch limits
150  if( eLimitTypes & HekLimitTypeElecTDC )
151  {
152  rc = calibrateJointTopDeadCenter(*pJoint);
153  }
154 
155  // one or more electronic switch limiters
156  else if( eLimitTypes & HekLimitTypeElec )
157  {
158  rc = calibrateJointByLimits(*pJoint);
159  }
160 
161  // physical limits
162  else if( eLimitTypes & HekLimitTypePhys )
163  {
164  rc = calibrateJointByTorqueLimits(*pJoint);
165  }
166 
167  // no detectable limits - assume current position is the good position
168  else if( eLimitTypes & HekLimitTypeNone )
169  {
170  rc = calibrateJointByTrust(*pJoint);
171  }
172 
173  else if( eLimitTypes & HekLimitTypeAbsEnc )
174  {
175  LOGWARN("Joint %s: Absolute encoders are not supported yet.",
176  strJointName.c_str());
177  }
178 
179  // warning
180  else
181  {
182  LOGWARN("Joint %s: Do not know how to calibrate this joint.",
183  strJointName.c_str());
184  }
185 
186  pJoint->m_eOpState = rc == HEK_OK? HekOpStateCalibrated:
188  }
189 
190  return rc;
191 }
HekRobotJoint * getArmJoint(const std::string &strName)
Get robotic joint in arm+ee kinematic chain.
Definition: hekRobot.h:610
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
HekOpState m_eOpState
current operational state
Definition: hekJoint.h:179
int m_eLimitTypes
joint limit types
Definition: hekJoint.h:173
absolute encoder
Definition: hekSpec.h:96
Operational robotic joint description class.
Definition: hekJoint.h:80
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
virtual int resetServoOdometersForAllJoints()
Reset all joints&#39; master servos odometers to the current respective encoder positions.
Definition: hekKin.cxx:220
virtual int calibrateJointByLimits(HekRobotJoint &joint)
Calibrate a rovolute joint by electronic limits.
electronic top dead center
Definition: hekSpec.h:95
virtual int calibrateJointTopDeadCenter(HekRobotJoint &joint)
Calibrate a continuously rotating joint by top-dead-center electronic limits.
static const string CalibOrder[]
Calibration order by master servo id.
virtual int calibrateJointByTrust(HekRobotJoint &joint)
Calibrate joint by trust.
virtual int calibrateJointByTorqueLimits(HekRobotJoint &joint)
Calibrate joint by torque limits.
no limit detection
Definition: hekSpec.h:92
int HekCalibStretch::calibrateJointByLimits ( HekRobotJoint joint)
protectedvirtual

Calibrate a rovolute joint by electronic limits.

The joint has an electronic limit switch and a occlusion band that marks the minimum and maximum rotation limits.

The joint is rotated until the electronic limit are triggered to find these min,max limits.

When the joint calibration moves are finished, the joint is repositioned at its new home position.

Heuristic:
light = optical switch unoccluded (closed)
dark = optical switch occluded (open)
  1. If starting in the dark.
    1. Get the park position from spec to determine best guess direction.
    2. Try to rotate X degrees to find the light, stopping either when first light is detected, torqued limit is reached, or have rotated X °.
    3. If in the light, goto 4.
    4. Else if over torqued (probably at physical limit).
      1. Reverse rotate X degrees to find the light, stopping either when first light is detected, torqued limit is reached, or have rotated X °.
      2. If in the light, goto 4.
    5. Else cannot get out of the dark, return with failure.
  2. Else starting in the light.
    1. Rotate in minimum direction Y degrees to find the dark, stopping either when first dark is detected, torqued limit is reached, or have rotated Y °.
    2. If in the dark, goto 4.
    3. Else probably obstructed.
      1. While less than MAX tries.
        1. Rotate in maximum direction Y degrees to find the dark, stopping either when first dark is detected, torqued limit is reached, or have rotated Y °.
        2. If in the dark, goto 4.
        3. Else if have helpful parent joint (e.g. shoulder for elbow).
          1. Rotate parent joint position Z degrees.
          2. If no movement return with failure.
        4. Else break loop.
  3. Return with failure.
  4. Final Stage.
    1. Fine tune to find edge precisely.
    2. While less than MAX tries.
      1. Rotate to 0 °.
      2. If reached 0 °.
        1. Reset odometer.
        2. Return with success.
      3. Else if have helpful parent joint.
        1. Rotate parent joint position Z degrees.
        2. If no movement return with failure.
      4. Else break loop.
    3. Return with failure
Parameters
jointRobotic joint to calibrate.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 433 of file hekCalibStretch.cxx.

References hekateros::degToRad(), hekateros::getDarkOpticalLimits(), hekateros::getLitOpticalLimits(), hekateros::HekRobotJoint::m_bStopAtOptLimits, hekateros::HekRobotJoint::m_byOptLimitMask, hekateros::HekOpticalLimit_T::m_fMaxBlackPos, hekateros::HekRobotJoint::m_fMaxPhyLimitRads, hekateros::HekOpticalLimit_T::m_fMinBlackPos, hekateros::HekRobotJoint::m_fMinPhyLimitRads, hekateros::HekRobotJoint::m_fParkPosRads, hekateros::HekRobotJoint::m_nMasterServoDir, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_strName, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

434 {
435  // joint calibrating velocity (radians/second)
436  static double TuneCalVel = degToRad(20.0);
437 
438  // additional angle margin (radians)
439  static double TuneMarginAngle = degToRad(50.0);
440 
441  string strJointName; // joint name
442  int nServoId; // servo id
443  bool bIsReverse; // odometer is [not] reversed
444 
445  double fJointCurPos; // user's starting/current position (radians)
446  double fJointCurVel; // joint current velocity (radians/second)
447  double fJointGoalPos; // joint working goal position (radians)
448  double fJointCalibPos; // joint calibrated position (radians)
449 
450  int nServoCurPos; // servo current position (odometer ticks)
451  int nServoCurSpeed; // servo current speed (raw unitless)
452 
453  byte_t byOptMask; // optical limits mask
454  byte_t byOptBits; // optical limits bits
455  HekOpticalLimit_T *pLimit; // limit info associated with mask
456 
457  int nDir; // working direction
458  double fAngle1; // working angle 1
459  double fAngle2; // working angle 2
460 
461  int i; // working index
462  int rc = HEK_OK; // return code
463 
464  //
465  // Initialize fixed working data.
466  //
467  // Note: Only work with one optical limit per joint for now. Can extend if
468  // needed.
469  //
470  strJointName = joint.m_strName;
471  nServoId = joint.m_nMasterServoId;
472  bIsReverse = joint.m_nMasterServoDir == DYNA_DIR_CCW? false: true;
473  byOptMask = joint.m_byOptLimitMask[0];
474  pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
475 
476  LOGDIAG2("Joint %s (servo=%d): Calibrating by optical limits.",
477  strJointName.c_str(), joint.m_nMasterServoId);
478 
479  //
480  // Sanity check.
481  //
482  if( byOptMask == 0x00 )
483  {
484  LOGERROR("Joint %s (servo=%d): No optical limit bits set, spec correct?",
485  strJointName.c_str(), nServoId);
486  return -HEK_ECODE_INTERNAL;
487  }
488 
489  // Disable optical limit auto-stopping for the joint during calibration.
490  joint.m_bStopAtOptLimits = false;
491 
492  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
493 
494  LOGDIAG2("Joint %s (servo=%d): Starting at %.2lf uncalibrated degrees.",
495  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
496 
497  //
498  // Get current optical limit values.
499  //
501  byOptMask);
502 
503  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
504  // Starting in the dark.
505  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
506 
507  if( byOptBits != 0x00 )
508  {
509  LOGDIAG2("Joint %s (servo=%d): "
510  "Determining joint optical limit dark-to-light edge.",
511  strJointName.c_str(), nServoId);
512 
513  // best guess direction based on configured parked position for this joint.
514  nDir = joint.m_fParkPosRads < 0? 1: -1;
515 
516  //
517  // Calculate the maximum of the minimum travel angles to reach an edge.
518  //
519  fAngle1 = pLimit->m_fMinBlackPos - joint.m_fMinPhyLimitRads;
520  fAngle2 = joint.m_fMaxPhyLimitRads - pLimit->m_fMaxBlackPos;
521 
522  if( fAngle2 > fAngle1 )
523  {
524  fAngle1 = fAngle2;
525  }
526 
527  fAngle1 += TuneMarginAngle;
528 
529  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
530 
531  fJointGoalPos = fJointCurPos + (double)nDir * fAngle1;
532 
533  LOGDIAG2("Joint %s (servo=%d): Move to light for <= %.2lf degrees.",
534  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
535 
536  // Move to occlusion band edge.
537  multiMoveToLight(strJointName, nDir, fJointGoalPos, TuneCalVel, byOptMask);
538 
539  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
540 
541  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
542  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
543 
544  // optical bits
545  byOptBits = m_robot.m_monitor.getJointLimitBits();
546 
547  //
548  // Did't find the light, probably guessed wrong direction and joint is at
549  // a physical limit. Reverse direction.
550  //
551  if( !getLitOpticalLimits(byOptBits, byOptMask) )
552  {
553  LOGDIAG2("Joint %s (servo=%d): "
554  "Did not find the light. Reverse direction.",
555  strJointName.c_str(), nServoId);
556 
557  nDir = -nDir;
558 
559  m_robot.m_pKin->getJointCurPosVel(strJointName,
560  fJointCurPos, fJointCurVel);
561 
562  fJointGoalPos = fJointCurPos + (double)nDir * fAngle1;
563 
564  LOGDIAG2("Joint %s (servo=%d): Move to light <= %.2lf degrees.",
565  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
566 
567  multiMoveToLight(strJointName, nDir, fJointGoalPos, TuneCalVel,
568  byOptMask);
569 
570  m_robot.m_pKin->getJointCurPosVel(strJointName,
571  fJointCurPos, fJointCurVel);
572 
573  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
574  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
575  }
576 
577  // optical bits
578  byOptBits = m_robot.m_monitor.getJointLimitBits();
579 
580  //
581  // Got an edge, perform final calibration fine tuning.
582  //
583  if( getLitOpticalLimits(byOptBits, byOptMask) )
584  {
585  m_robot.m_pKin->getJointCurPosVel(strJointName,
586  fJointCurPos, fJointCurVel);
587 
588  LOGDIAG2("Joint %s (servo=%d): Got a light edge at %.2lf degrees.",
589  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
590 
591  return calibByLimitsFinal(joint, byOptMask, nDir);
592  }
593 
594  //
595  // Still no light. Give up.
596  //
597  else
598  {
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;
603  }
604  }
605 
606 
607  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
608  // Starting in the light.
609  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
610 
611  else
612  {
613  // best guess direction
614  nDir = nServoId == HekServoIdShoulderL? -1: 1;
615 
616  //
617  // Calculate the maximum angle to reach an edge.
618  //
619  fAngle1 = pLimit->m_fMaxBlackPos - pLimit->m_fMinBlackPos;
620  fAngle1 += TuneMarginAngle;
621 
622  LOGDIAG2("Joint %s (servo=%d): "
623  "Determining joint optical limit light-to-dark minimum edge.",
624  strJointName.c_str(), nServoId);
625 
626  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
627 
628  fJointGoalPos = fJointCurPos + (double)nDir * fAngle1;
629 
630  LOGDIAG2("Joint %s (servo=%d): Move to dark for <= %.2lf degrees.",
631  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
632 
633  // Move to occlusion band edge.
634  multiMoveToDark(strJointName, nDir, fJointGoalPos, TuneCalVel, byOptMask);
635 
636  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
637 
638  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
639  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
640 
641  // optical bits
642  byOptBits = m_robot.m_monitor.getJointLimitBits();
643 
644  //
645  // Got an edge, perform final calibration fine tuning.
646  //
647  if( getDarkOpticalLimits(byOptBits, byOptMask) )
648  {
649  m_robot.m_pKin->getJointCurPosVel(strJointName,
650  fJointCurPos, fJointCurVel);
651 
652  LOGDIAG2("Joint %s (servo=%d): Got a dark edge at %.2lf degrees.",
653  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
654 
655  return calibByLimitsFinal(joint, byOptMask, nDir);
656  }
657 
658  else
659  {
660  LOGERROR("Joint %s (servo=%d): "
661  "Could not find optical limit occlusion edge.",
662  strJointName.c_str(), nServoId);
663 
664  return -HEK_ECODE_NO_EXEC;
665  }
666  }
667 
668  LOGERROR("BUG: Joint %s (servo=%d): Should not be here.",
669  strJointName.c_str(), nServoId);
670 
671  return -HEK_ECODE_INTERNAL;
672 }
byte_t getJointLimitBits()
Get current limit switch bit values.
Definition: hekMonitor.h:413
HekOpticalLimit_T * getJointLimitInfo(byte_t byMask)
Get joint limits information.
Definition: hekMonitor.h:403
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
Optical limit switch.
Definition: hekOptical.h:148
static const int HEK_ECODE_NO_EXEC
cannot execute error
Definition: hekateros.h:84
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
double m_fMinBlackPos
minimum complete occlusion position
Definition: hekOptical.h:179
double m_fParkPosRads
joint parked position (radians)
Definition: hekJoint.h:172
double m_fMinPhyLimitRads
joint min physical limit (radians)
Definition: hekJoint.h:162
double m_fMaxBlackPos
maximum complete occlusion position
Definition: hekOptical.h:181
virtual int multiMoveToDark(const std::string &strJointName, int nDir, double fJointGoalPos, double fJointGoalVel, byte_t byMask)
Move joint until occluded optical limit position is detected.
byte_t m_byOptLimitMask[HekOptLimitMaxPerJoint]
optical limit mask array
Definition: hekJoint.h:175
bool m_bStopAtOptLimits
do [not] stop at optical limits
Definition: hekJoint.h:180
static const int HEK_ECODE_INTERNAL
internal error (bug)
Definition: hekateros.h:74
static byte_t getDarkOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits have been triggered (occluded).
Definition: hekOptical.h:194
std::string m_strName
joint name
Definition: hekJoint.h:149
static const int HekServoIdShoulderL
left shoulder
Definition: hekateros.h:261
virtual int multiMoveToLight(const std::string &strJointName, int nDir, double fJointGoalPos, double fJointGoalVel, byte_t byMask)
Move joint until unoccluded optical limit position is detected.
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
static byte_t getLitOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits are lit (not occluded).
Definition: hekOptical.h:209
HekMonitor m_monitor
power, health, and safety monitor
Definition: hekRobot.h:709
int m_nMasterServoDir
master servo normalized direction
Definition: hekJoint.h:153
virtual int calibByLimitsFinal(HekRobotJoint &joint, byte_t byOptMask, int nEdge)
Perform final calibration by limits calculations and movements.
double m_fMaxPhyLimitRads
joint max physical limit (radians)
Definition: hekJoint.h:163
int HekCalibStretch::calibrateJointByTorqueLimits ( HekRobotJoint joint)
protectedvirtual

Calibrate joint by torque limits.

The joint is rotated to its minimum and maximum physical end points. When the torque reaches a software defined limit, an endpoint is considered reached.

From the joint specification and detected limits, the home position at 0 ° is fine tuned.

When the joint calibration moves are finished, the joint is repositioned at its new home position.

Heuristic:
  1. Rotate in minimum direction until torque limit reached.
  2. Mark position.
  3. Rotate in maximum direction until torque limit reached.
  4. Mark position.
  5. Calculate 0 ° based on expected min,max positions and detected min,max positions.
  6. Rotate to 0 °.
  7. Reset odomter.
Parameters
jointRobotic joint to calibrate.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 771 of file hekCalibStretch.cxx.

References hekateros::degToRad(), HEK_TRY_GET_SERVO, hekateros::HekRobotJoint::m_bIsServoContinuous, hekateros::HekRobotJoint::m_fCalibPosRads, hekateros::HekRobotJoint::m_fMaxPhyLimitRads, hekateros::HekRobotJoint::m_fMaxSoftLimitRads, hekateros::HekRobotJoint::m_fMinPhyLimitRads, hekateros::HekRobotJoint::m_fMinSoftLimitRads, hekateros::HekRobotJoint::m_nMasterServoDir, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_nMaxPhyLimitOd, hekateros::HekRobotJoint::m_nMaxSoftLimitOd, hekateros::HekRobotJoint::m_nMinPhyLimitOd, hekateros::HekRobotJoint::m_nMinSoftLimitOd, hekateros::HekRobotJoint::m_strName, M_TAU, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

772 {
773  // joint calibrating velocity (radians/second)
774  static double TuneCalVel = degToRad(20.0);
775 
776  // backoff angle margin (radians)
777  static double TuneBackoff = degToRad(0.1);
778 
779  string strJointName; // joint name
780  int nServoId; // servo id
781  bool bIsReverse; // odometer is [not] reversed
782  DynaServo *pServo; // servo control
783 
784  double fMinLimit; // joint minimum position
785  double fMaxLimit; // joint maximum position
786  double fJointRange; // joint range of motion
787 
788  double fJointStartPos; // user's starting position (radians)
789  double fJointCurPos; // joint current position (radians)
790  double fJointCurVel; // joint current velocity (radians/second)
791  double fJointGoalPos; // joint working goal position (radians)
792 
793  int nServoPos; // working servo position (odometer ticks);
794 
795  strJointName = joint.m_strName;
796  nServoId = joint.m_nMasterServoId;
797  bIsReverse = joint.m_nMasterServoDir == DYNA_DIR_CCW? false: true;
798 
799  LOGDIAG2("Joint %s (servo=%d): Calibrating by torque limits.",
800  strJointName.c_str(), joint.m_nMasterServoId);
801 
802  HEK_TRY_GET_SERVO(nServoId, pServo);
803 
804  // starting position
805  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointStartPos, fJointCurVel);
806 
807  LOGDIAG2("Joint %s (servo=%d): Starting at %.2lf uncalibrated degrees.",
808  strJointName.c_str(), nServoId, radToDeg(fJointStartPos));
809 
810  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
811  // Find minimum joint limit.
812  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
813 
814  LOGDIAG2("Joint %s (servo=%d): "
815  "Determining minimum joint angle by torque limit.",
816  joint.m_strName.c_str(), nServoId);
817 
818  fJointCurPos = fJointStartPos;
819 
820  //
821  // A continuous mode servo must have its joint minimum limit within 360
822  // degreees of joint rotation from the current position. Go to this endpoint
823  // until the torque limit is found.
824  //
825  if( joint.m_bIsServoContinuous )
826  {
827  fJointGoalPos = -M_TAU + -fabs(fJointCurPos);
828  }
829 
830  //
831  // A servo mode servo has encoder endpoints that are known and finite. Go to
832  // the appropriate endpoint until the torque limit is found.
833  //
834  else
835  {
836  if( (nServoPos = pServo->CalcOdometerAtEncMin()) > 0 )
837  {
838  nServoPos = pServo->CalcOdometerAtEncMax();
839  }
840  fJointGoalPos = m_robot.m_pKin->servoPosToJointPos(strJointName, nServoPos);
841  }
842 
843  LOGDIAG2("Joint %s (servo=%d): Move to minimum >= %.2lf degrees.",
844  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
845 
846  moveToTorqueLimit(strJointName, fJointGoalPos, TuneCalVel);
847 
848  // save minimum limit position
849  m_robot.m_pKin->getJointCurPosVel(strJointName, fMinLimit, fJointCurVel);
850 
851  LOGDIAG2("Joint %s (servo=%d): Minimum reached at %.2lf degrees.",
852  strJointName.c_str(), nServoId, radToDeg(fMinLimit));
853 
854  //
855  // Off load servo by moving back to starting calibration position.
856  //
857  LOGDIAG2("Joint %s (servo=%d): Move back to start at %.2lf degrees.",
858  strJointName.c_str(), nServoId, radToDeg(fJointStartPos));
859 
860  moveWait(strJointName, fJointStartPos, TuneCalVel);
861 
862  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
863 
864  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
865  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
866 
867  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
868  // Find maximum limit.
869  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
870 
871  LOGDIAG2("Joint %s (servo=%d): "
872  "Determining maximum joint angle by torque limit.",
873  joint.m_strName.c_str(), nServoId);
874 
875  // current position
876  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
877 
878  //
879  // A continuous mode servo must have its joint minimum limit within 360
880  // degreees of joint rotation from the current position. Go to this endpoint
881  // until the torque limit is found.
882  //
883  if( joint.m_bIsServoContinuous )
884  {
885  fJointGoalPos = M_TAU + fabs(fJointCurPos);
886  }
887 
888  //
889  // A servo mode servo has encoder endpoints that are known and finite. Go to
890  // the appropriate endpoint until the torque limit is found.
891  //
892  else
893  {
894  if( (nServoPos = pServo->CalcOdometerAtEncMin()) < 0 )
895  {
896  nServoPos = pServo->CalcOdometerAtEncMax();
897  }
898  fJointGoalPos = m_robot.m_pKin->servoPosToJointPos(strJointName, nServoPos);
899  }
900 
901  LOGDIAG2("Joint %s (servo=%d): Move to maximum <= %.2lf degrees.",
902  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
903 
904  moveToTorqueLimit(strJointName, fJointGoalPos, TuneCalVel);
905 
906  // save maximum limit position
907  m_robot.m_pKin->getJointCurPosVel(strJointName, fMaxLimit, fJointCurVel);
908 
909  LOGDIAG2("Joint %s (servo=%d): Maximum reached at %.2lf degrees.",
910  strJointName.c_str(), nServoId, radToDeg(fMaxLimit));
911 
912  //
913  // Off load servo by moving back to starting calibration position
914  //
915  LOGDIAG2("Joint %s (servo=%d): Move back again to start at %.2lf degrees.",
916  strJointName.c_str(), nServoId, radToDeg(fJointStartPos));
917 
918  moveWait(strJointName, fJointStartPos, TuneCalVel);
919 
920  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
921 
922  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
923  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
924 
925  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
926  // Set zero point and limits.
927  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
928 
929  //
930  // Joint range of motion.
931  //
932  fJointRange = fMaxLimit - fMinLimit;
933 
934  //
935  // Move to new zero point position.
936  //
937  fJointGoalPos = fMinLimit;
938 
939  LOGDIAG2("Joint %s (servo=%d): Move to the new zero point at %.2lf degrees.",
940  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
941 
942  moveToTorqueLimit(strJointName, fJointGoalPos, TuneCalVel);
943 
944  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
945 
946  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
947  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
948 
949  //
950  // Reset odometer to new zero degree position.
951  //
952  m_robot.m_pKin->resetServoOdometer(strJointName);
953 
954  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
955 
956  LOGDIAG2("Joint %s (servo=%d): Odometer reset.",
957  strJointName.c_str(), nServoId);
958 
959  //
960  // Adjust limits and positions to adjusted zero degree point.
961  //
962  joint.m_fMinPhyLimitRads = fJointCurPos;
963  joint.m_fMaxPhyLimitRads = fJointCurPos + fJointRange;
964 
966  strJointName,
967  joint.m_fMinPhyLimitRads);
969  strJointName,
970  joint.m_fMaxPhyLimitRads);
971 
972  joint.m_fMinSoftLimitRads = joint.m_fMinPhyLimitRads + TuneBackoff;
973  joint.m_fMaxSoftLimitRads = joint.m_fMaxPhyLimitRads - TuneBackoff;
974 
975  // hack - should be in spec
976  if( nServoId == HekServoIdGraboid )
977  {
978  joint.m_fMaxSoftLimitRads = joint.m_fMaxPhyLimitRads - degToRad(1.0);
979  }
980 
981 
983  strJointName,
984  joint.m_fMinSoftLimitRads);
986  strJointName,
987  joint.m_fMaxSoftLimitRads);
988 
989 
990  //
991  // Finally move to pre-defined calibration zero point position.
992  //
993  if( joint.m_fCalibPosRads != 0.0 )
994  {
995  LOGDIAG2("Joint %s (servo=%d): Move to calibrated zero pt=%.2lf degrees.",
996  strJointName.c_str(), nServoId, radToDeg(joint.m_fCalibPosRads));
997 
998  moveWait(strJointName, joint.m_fCalibPosRads, TuneCalVel);
999 
1000  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1001 
1002  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
1003  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
1004  }
1005 
1006  //
1007  // Calibrated.
1008  //
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)].",
1012  joint.m_strName.c_str(), nServoId,
1017 
1018  return HEK_OK;
1019 }
virtual double moveToTorqueLimit(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
Move joint until torque limit is reached.
Definition: hekCalib.cxx:110
int m_nMaxSoftLimitOd
joint max soft limit (odometer ticks)
Definition: hekJoint.h:169
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
double m_fMinSoftLimitRads
joint min soft limit (radians)
Definition: hekJoint.h:166
virtual double moveWait(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
Move joint to position.
Definition: hekCalib.cxx:65
#define M_TAU
tau = 2 * pi
Definition: hekUtils.h:67
int m_nMinPhyLimitOd
joint min phys limit (odometer ticks)
Definition: hekJoint.h:164
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
double m_fCalibPosRads
joint calibrated position (radians)
Definition: hekJoint.h:170
double m_fMinPhyLimitRads
joint min physical limit (radians)
Definition: hekJoint.h:162
bool m_bIsServoContinuous
servo should [not] be continuous mode
Definition: hekJoint.h:152
int m_nMinSoftLimitOd
joint min soft limit (odometer ticks)
Definition: hekJoint.h:168
int m_nMaxPhyLimitOd
joint max phys limit (odometer ticks)
Definition: hekJoint.h:165
virtual int resetServoOdometer(const std::string &strJointName)
Reset joint&#39;s master servo odometer to the current encoder position.
Definition: hekKin.cxx:336
#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
Definition: hekJoint.h:149
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
double m_fMaxSoftLimitRads
joint max soft limit (radians)
Definition: hekJoint.h:167
int jointPosToServoPos(const std::string &strJointName, const double fPos)
Convert joint position to the equivalent servo position.
Definition: hekKin.cxx:278
int m_nMasterServoDir
master servo normalized direction
Definition: hekJoint.h:153
double m_fMaxPhyLimitRads
joint max physical limit (radians)
Definition: hekJoint.h:163
static const int HekServoIdGraboid
graboid
Definition: hekateros.h:272
double servoPosToJointPos(const std::string &strJointName, const int nOdPos)
Convert servo position to the equivalent joint position.
Definition: hekKin.cxx:293
int HekCalibStretch::calibrateJointByTrust ( HekRobotJoint joint)
protectedvirtual

Calibrate joint by trust.

The joint is assumed to be already position at zero degrees by the user.

Parameters
jointRobotic joint to calibrate.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 1021 of file hekCalibStretch.cxx.

References hekateros::HekRobotJoint::m_eJointType, hekateros::HekRobotJoint::m_fMaxPhyLimitRads, hekateros::HekRobotJoint::m_fMinPhyLimitRads, hekateros::HekRobotJoint::m_nMasterServoDir, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_nMaxPhyLimitOd, hekateros::HekRobotJoint::m_nMinPhyLimitOd, hekateros::HekRobotJoint::m_strName, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

1022 {
1023  string strJointName; // joint name
1024  int nServoId; // servo id
1025  bool bIsReverse; // odometer is [not] reversed
1026 
1027  double fJointCurPos; // joint current position (radians)
1028  double fJointCurVel; // joint current velocity (radians/second)
1029 
1030  int nServoCurPos; // servo current position (odometer ticks)
1031  int nServoCurSpeed; // servo current speed (raw unitless)
1032 
1033  strJointName = joint.m_strName;
1034  nServoId = joint.m_nMasterServoId;
1035  bIsReverse = joint.m_nMasterServoDir == DYNA_DIR_CCW? false: true;
1036 
1037  LOGDIAG2("Joint %s (servo=%d): Calibrating by trust.",
1038  strJointName.c_str(), joint.m_nMasterServoId);
1039 
1040  //
1041  // Reset odometer to the current position
1042  //
1043  m_robot.m_pKin->resetServoOdometer(strJointName);
1044 
1045  // starting position
1046  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1047  m_robot.m_pKin->getServoCurPosSpeed(strJointName,
1048  nServoCurPos,
1049  nServoCurSpeed);
1050 
1051  if( joint.m_eJointType == HekJointTypeContinuous )
1052  {
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);
1056  }
1057  else
1058  {
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,
1064  }
1065 
1066  return HEK_OK;
1067 }
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
int m_eJointType
joint type
Definition: hekJoint.h:154
int m_nMinPhyLimitOd
joint min phys limit (odometer ticks)
Definition: hekJoint.h:164
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
continuous rotation
Definition: hekSpec.h:78
double m_fMinPhyLimitRads
joint min physical limit (radians)
Definition: hekJoint.h:162
int m_nMaxPhyLimitOd
joint max phys limit (odometer ticks)
Definition: hekJoint.h:165
virtual int resetServoOdometer(const std::string &strJointName)
Reset joint&#39;s master servo odometer to the current encoder position.
Definition: hekKin.cxx:336
std::string m_strName
joint name
Definition: hekJoint.h:149
int m_nMasterServoDir
master servo normalized direction
Definition: hekJoint.h:153
double m_fMaxPhyLimitRads
joint max physical limit (radians)
Definition: hekJoint.h:163
void getServoCurPosSpeed(const std::string &strJointName, int &nServoCurPos, int &nServoCurSpeed)
Get the current servo position and speed.
Definition: hekKin.cxx:266
int HekCalibStretch::calibrateJointTopDeadCenter ( HekRobotJoint joint)
protectedvirtual

Calibrate a continuously rotating joint by top-dead-center electronic limits.

The joint has optical limit switch(es) at defined location, typically at 0 ° and/or, at 180 °. A small occlusion band triggers the (occludes) the switch(es).

The joint is rotated until the electronic limits are triggered to find top-dead-center.

When the joint calibration moves are finished, the joint is repositioned at its new home position.

Heuristic:
light = optical switch unoccluded (closed)
dark = optical switch occluded (open)
  1. If starting in the light
    1. Rotate a small number of degrees in minimum direction.
    2. If light, rotate joint in the oposite direction 360 °.
    3. If light, return with failure.
  2. Started in or moved to the dark.
    1. Now find an edge of occlusion band (dark to light).
    2. Move back to find opposite edge.
    3. Calculated center of band from both edge positions and rotate there.
    4. Rotate to 0 °.
    5. Reset odometer.
    6. Return with success.
Parameters
jointRobotic joint to calibrate.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 193 of file hekCalibStretch.cxx.

References hekateros::degToRad(), hekateros::getDarkOpticalLimits(), hekateros::HekRobotJoint::m_bStopAtOptLimits, hekateros::HekRobotJoint::m_byOptLimitMask, hekateros::HekRobotJoint::m_eJointType, hekateros::HekRobotJoint::m_fCalibPosRads, hekateros::HekRobotJoint::m_fMaxSoftLimitRads, hekateros::HekRobotJoint::m_fMinSoftLimitRads, hekateros::HekRobotJoint::m_fTicksPerJointRad, hekateros::HekRobotJoint::m_nMasterServoDir, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_nMaxSoftLimitOd, hekateros::HekRobotJoint::m_nMinSoftLimitOd, hekateros::HekRobotJoint::m_strName, M_TAU, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

194 {
195  // joint calibrating velocity (radians/second)
196  static double TuneCalVel = degToRad(20.0);
197 
198  // quick try in the minimum direction (radians)
199  static double TuneMinAngle = degToRad(20.0);
200 
201  string strJointName; // joint name
202  int nServoId; // servo id
203  bool bIsReverse; // odometer is [not] reversed
204 
205  double fJointCurPos; // user's starting/current position (radians)
206  double fJointCurVel; // joint current velocity (radians/second)
207  double fJointGoalPos; // joint working goal position (radians)
208  double fJointCalibPos; // joint calibrated position (radians)
209 
210  int nServoCurPos; // servo current position (odometer ticks)
211  int nServoCurSpeed; // servo current speed (raw unitless)
212 
213  byte_t byOptMask; // optical limits mask
214  byte_t byOptBits; // optical limits bits
215  int nEdge; // which edge triggered
216 
217  int i; // working index
218  int rc = HEK_OK; // return code
219 
220  strJointName = joint.m_strName;
221  nServoId = joint.m_nMasterServoId;
222  bIsReverse = joint.m_nMasterServoDir == DYNA_DIR_CCW? false: true;
223 
224  LOGDIAG2("Joint %s (servo=%d): Calibrating by TDC optical limits.",
225  strJointName.c_str(), joint.m_nMasterServoId);
226 
227  //
228  // Only continuous joints support tdc limits
229  //
230  if( joint.m_eJointType != HekJointTypeContinuous )
231  {
232  LOGERROR("Joint %s (servo=%d): Not a continuous joint.",
233  strJointName.c_str(), joint.m_nMasterServoId);
234  return -HEK_ECODE_NO_EXEC;
235  }
236 
237  //
238  // Build optical limits bit mask.
239  //
240  for(i=0, byOptMask=0x00; i<HekOptLimitMaxPerJoint; ++i)
241  {
242  byOptMask |= joint.m_byOptLimitMask[i];
243  }
244 
245  //
246  // Sanity check
247  //
248  if( byOptMask == 0x00 )
249  {
250  LOGERROR("Joint %s (servo=%d): No optical limit bits set, spec correct?",
251  strJointName.c_str(), nServoId);
252  return -HEK_ECODE_INTERNAL;
253  }
254 
255  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
256  // Find joint top-dead-center position.
257  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
258 
259  LOGDIAG2("Joint %s (servo=%d): "
260  "Determining joint top-dead-center by optical limit(s).",
261  strJointName.c_str(), nServoId);
262 
263  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
264 
265  LOGDIAG2("Joint %s (servo=%d): Starting at uncalibrated %.2lf degrees.",
266  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
267 
268  // Never auto-stop at TDC limits.
269  joint.m_bStopAtOptLimits = false;
270 
272  byOptMask);
273 
274  //
275  // Starting in the light. First try a small degree of rotation in the
276  // minimum direction to find an optical limit dark edge.
277  //
278  if( byOptBits == 0x00 )
279  {
280  LOGDIAG2("Joint %s (servo=%d): "
281  "Determining joint optical limit light-to-dark edge.",
282  strJointName.c_str(), nServoId);
283 
284  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
285 
286  fJointGoalPos = fJointCurPos - TuneMinAngle;
287  nEdge = 1; // move will detect edge on maximum side
288 
289  LOGDIAG2("Joint %s (servo=%d): Move to the dark for <= %.2lf degrees.",
290  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
291 
292  moveToDark(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
293 
294  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
295 
296  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
297  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
298  }
299 
301  byOptMask);
302 
303  //
304  // Did not find the optical limit. Do a complete spin in the opposite
305  // direction to find a limit.
306  //
307  if( byOptBits == 0x00 )
308  {
309  LOGDIAG2("Joint %s (servo=%d): Did not find the dark. Reverse direction.",
310  strJointName.c_str(), nServoId);
311 
312  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
313 
314  fJointGoalPos = fJointCurPos + M_TAU;
315  nEdge = -1; // move will detect edge on minimum side
316 
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));
320 
321  moveToDark(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
322 
323  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
324 
325  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
326  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
327  }
328 
330  byOptMask);
331 
332  //
333  // Make sure that an optical limits has been found.
334  //
335  if( byOptBits == 0x00 )
336  {
337  LOGERROR("Joint %s (servo=%d): Did not find any optical limits.",
338  strJointName.c_str(), nServoId);
339  return -HEK_ECODE_NO_EXEC;
340  }
341 
342  //
343  // Fine tune center of optical limit.
344  //
345  for(i=0, byOptMask=0x00; i<HekOptLimitMaxPerJoint; ++i)
346  {
347  if( byOptBits & joint.m_byOptLimitMask[i] )
348  {
349  rc = fineTuneTDC(joint, joint.m_byOptLimitMask[i], nEdge, fJointCalibPos);
350  break;
351  }
352  }
353 
354  if( rc < 0 )
355  {
356  LOGERROR("Joint %s (servo=%d): Fine tuning failed.",
357  strJointName.c_str(), nServoId);
358  return rc;
359  }
360 
361  //
362  // Move to 0 degrees the shortest way.
363  //
364  if( fJointCalibPos != 0.0 )
365  {
366  if( fJointCalibPos < M_PI )
367  {
368  fJointGoalPos = fJointCalibPos;
369  }
370  else
371  {
372  fJointGoalPos = M_TAU - fJointCalibPos;
373  }
374 
375  LOGDIAG2("Joint %s (servo=%d): "
376  "Move to the new zero point at %.2lf degrees.",
377  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
378 
379  moveWait(strJointName, fJointGoalPos, TuneCalVel);
380 
381  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
382 
383  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
384  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
385  }
386 
387  //
388  // Reset odometer to new zero degree position.
389  //
390  m_robot.m_pKin->resetServoOdometer(strJointName);
391 
392  LOGDIAG2("Joint %s (servo=%d): Odometer reset.",
393  strJointName.c_str(), nServoId);
394 
395  //
396  // Adjust limits and positions to adjusted zero degree point.
397  //
398  joint.m_fMinSoftLimitRads = 0.0;
399  joint.m_fMaxSoftLimitRads = M_TAU;
400  joint.m_nMinSoftLimitOd = 0;
401  joint.m_nMaxSoftLimitOd = (int)(joint.m_fMaxSoftLimitRads *
402  joint.m_fTicksPerJointRad);
403 
404  //
405  // Finally move to the pre-defined calibration zero point position.
406  //
407  if( joint.m_fCalibPosRads != 0.0 )
408  {
409  LOGDIAG2("Joint %s (servo=%d): Move to calibrated zero pt=%.2lf degrees.",
410  strJointName.c_str(), nServoId, radToDeg(joint.m_fCalibPosRads));
411 
412  moveWait(strJointName, joint.m_fCalibPosRads, TuneCalVel);
413 
414  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
415 
416  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
417  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
418  }
419 
420  //
421  // Calibrated.
422  //
423  m_robot.m_pKin->getServoCurPosSpeed(strJointName,
424  nServoCurPos, nServoCurSpeed);
425 
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);
429 
430  return HEK_OK;
431 }
byte_t getJointLimitBits()
Get current limit switch bit values.
Definition: hekMonitor.h:413
int m_nMaxSoftLimitOd
joint max soft limit (odometer ticks)
Definition: hekJoint.h:169
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
double m_fMinSoftLimitRads
joint min soft limit (radians)
Definition: hekJoint.h:166
double m_fTicksPerJointRad
encoder/odom. ticks per joint radian
Definition: hekJoint.h:157
int m_eJointType
joint type
Definition: hekJoint.h:154
static const int HEK_ECODE_NO_EXEC
cannot execute error
Definition: hekateros.h:84
virtual double moveWait(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
Move joint to position.
Definition: hekCalib.cxx:65
#define M_TAU
tau = 2 * pi
Definition: hekUtils.h:67
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
virtual double moveToDark(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until occluded optical limit position is detected.
Definition: hekCalib.cxx:241
continuous rotation
Definition: hekSpec.h:78
double m_fCalibPosRads
joint calibrated position (radians)
Definition: hekJoint.h:170
int m_nMinSoftLimitOd
joint min soft limit (odometer ticks)
Definition: hekJoint.h:168
byte_t m_byOptLimitMask[HekOptLimitMaxPerJoint]
optical limit mask array
Definition: hekJoint.h:175
virtual int resetServoOdometer(const std::string &strJointName)
Reset joint&#39;s master servo odometer to the current encoder position.
Definition: hekKin.cxx:336
bool m_bStopAtOptLimits
do [not] stop at optical limits
Definition: hekJoint.h:180
static const int HEK_ECODE_INTERNAL
internal error (bug)
Definition: hekateros.h:74
static byte_t getDarkOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits have been triggered (occluded).
Definition: hekOptical.h:194
std::string m_strName
joint name
Definition: hekJoint.h:149
static const int HekOptLimitMaxPerJoint
max limits/joint
Definition: hekOptical.h:120
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
double m_fMaxSoftLimitRads
joint max soft limit (radians)
Definition: hekJoint.h:167
HekMonitor m_monitor
power, health, and safety monitor
Definition: hekRobot.h:709
int m_nMasterServoDir
master servo normalized direction
Definition: hekJoint.h:153
virtual int fineTuneTDC(HekRobotJoint &joint, byte_t byOptMask, int nEdge, double &fPosition)
Fine tune joint to top dead center of optical limit.
void getServoCurPosSpeed(const std::string &strJointName, int &nServoCurPos, int &nServoCurSpeed)
Get the current servo position and speed.
Definition: hekKin.cxx:266
int HekCalibStretch::fineTuneLimit ( HekRobotJoint joint,
byte_t  byOptMask,
int  nEdge,
double &  fDeltaPos 
)
protectedvirtual

Fine tune joint to optical limit edge.

Limit Fine Tuning:
*  fine tune step           occlusion band
*                       _____________________
*   0 (start)           |     *             |
*                       |     *             |
*   1 lit_edge      * <------ *             |
*                   *   |                   |
*   2 dark_edge     * ----> *               |
*                       |___________________|
*
* Or:
*
*  fine tune step           occlusion band
*                       _____________________
*   0 start         *   |                   |
*                   *   |                   |
*   2 dark_edge     * ----> *               |
*                       |___________________|
* 
Parameters
jointRobotic joint.
byOptMaskJoint optical limit bit mask;
nEdgeWhich edge triggered limit switch. The minimum, unknown, or maximum leading edge is specified as < 0, 0, or > 0, respectively.
[out]fDeltaPosDelta position (radians) from current to zero point as determined by the optical limit.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 1254 of file hekCalibStretch.cxx.

References hekateros::degToRad(), hekateros::getDarkOpticalLimits(), hekateros::getLitOpticalLimits(), hekateros::HekOpticalLimit_T::m_fMaxEdgePos, hekateros::HekOpticalLimit_T::m_fMinEdgePos, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_strName, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

1258 {
1259  // joint calibrating velocity (radians/second)
1260  static double TuneCalVel = degToRad(5.0);
1261 
1262  // tuning slop (radians)
1263  static double TuneFudge = degToRad(10.0);
1264 
1265  string strJointName; // joint name
1266  int nServoId; // servo id
1267 
1268  HekOpticalLimit_T *pLimit; // limit info associated with mask
1269  byte_t byOptBits; // optical limits bits
1270 
1271  double fJointCurPos; // joint current position (radians)
1272  double fJointCurVel; // joint current velocity (radians/second)
1273  double fJointGoalPos; // joint working goal position (radians)
1274  double fLightPos; // occlusion band light position (radian)
1275  double fDarkPos; // occlusion band dark position (radian)
1276  double fEdgePos; // occlusion band edge position (radians)
1277 
1278  int rc = HEK_OK; // return code
1279 
1280  strJointName = joint.m_strName;
1281  nServoId = joint.m_nMasterServoId;
1282  pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
1283 
1284  m_robot.m_pKin->stop(strJointName);
1285 
1286  // optical bits
1287  byOptBits = m_robot.m_monitor.getJointLimitBits();
1288 
1289  // need to start in the light
1290  if( !getLitOpticalLimits(byOptBits, byOptMask) )
1291  {
1292  nDir = -nDir;
1293 
1294  // current position
1295  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1296 
1297  fJointGoalPos = fJointCurPos + (double)nDir * TuneFudge;
1298 
1299  LOGDIAG2("Joint %s (servo=%d): "
1300  "Fine tune move for <= %.2lf degrees to find light edge.",
1301  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
1302 
1303  moveToLight(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1304 
1305  m_robot.m_pKin->getJointCurPosVel(strJointName, fLightPos, fJointCurVel);
1306 
1307  LOGDIAG2("Joint %s (servo=%d): Stopped at first light at %.2lf degrees.",
1308  strJointName.c_str(), nServoId, radToDeg(fLightPos));
1309  }
1310 
1311  // optical bits
1312  byOptBits = m_robot.m_monitor.getJointLimitBits();
1313 
1314  // sanity check
1315  if( getLitOpticalLimits(byOptBits, byOptMask) == 0x00 )
1316  {
1317  LOGERROR("Joint %s (servo=%d): Cannot find occlusion band edge.",
1318  strJointName.c_str(), nServoId);
1319  return -HEK_ECODE_NO_EXEC;
1320  }
1321 
1322  // move to dark
1323  nDir = -nDir;
1324 
1325  // current position
1326  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1327 
1328  fJointGoalPos = fJointCurPos + (double)nDir * TuneFudge;
1329 
1330  LOGDIAG2("Joint %s (servo=%d): "
1331  "Fine tune move for <= %.2lf degrees to find dark edge.",
1332  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
1333 
1334  moveToDark(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1335 
1336  m_robot.m_pKin->getJointCurPosVel(strJointName, fDarkPos, fJointCurVel);
1337 
1338  LOGDIAG2("Joint %s (servo=%d): Stopped at first dark at %.2lf degrees.",
1339  strJointName.c_str(), nServoId, radToDeg(fDarkPos));
1340 
1341  // optical bits
1342  byOptBits = m_robot.m_monitor.getJointLimitBits();
1343 
1344  //
1345  // Didn't find the dark past the edge.
1346  //
1347  if( getDarkOpticalLimits(byOptBits, byOptMask) == 0x00 )
1348  {
1349  if( m_robot.m_pKin->hasOverTorqueCondition(strJointName) )
1350  {
1351  LOGERROR("Joint %s (servo=%d): Cannot calibrate: Joint is obstucted.",
1352  strJointName.c_str(), nServoId);
1353  rc = -HEK_ECODE_COLLISION;
1354  }
1355  else
1356  {
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;
1361  }
1362  }
1363 
1364  //
1365  // Set delta joint position as specified in spec.
1366  //
1367  fEdgePos = (fLightPos + fDarkPos) / 2.0;
1368  if( nDir > 0 )
1369  {
1370  fDeltaPos = pLimit->m_fMaxEdgePos + fDarkPos - fEdgePos;
1371  }
1372  else
1373  {
1374  fDeltaPos = pLimit->m_fMinEdgePos + fEdgePos - fDarkPos;
1375  }
1376 
1377  return rc;
1378 }
virtual int stop()
Stop kinematics chain at the current position.
Definition: hekKin.cxx:399
byte_t getJointLimitBits()
Get current limit switch bit values.
Definition: hekMonitor.h:413
HekOpticalLimit_T * getJointLimitInfo(byte_t byMask)
Get joint limits information.
Definition: hekMonitor.h:403
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
virtual double moveToLight(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until unoccluded optical limit position is detected.
Definition: hekCalib.cxx:164
Optical limit switch.
Definition: hekOptical.h:148
static const int HEK_ECODE_NO_EXEC
cannot execute error
Definition: hekateros.h:84
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
virtual double moveToDark(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until occluded optical limit position is detected.
Definition: hekCalib.cxx:241
double m_fMaxEdgePos
maxinum edge position of occlusion band
Definition: hekOptical.h:182
double m_fMinEdgePos
mininum edge position of occlusion band
Definition: hekOptical.h:178
static byte_t getDarkOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits have been triggered (occluded).
Definition: hekOptical.h:194
std::string m_strName
joint name
Definition: hekJoint.h:149
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
static const int HEK_ECODE_COLLISION
robot link(s) in collision
Definition: hekateros.h:94
static byte_t getLitOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits are lit (not occluded).
Definition: hekOptical.h:209
virtual bool hasOverTorqueCondition(const std::string &strJointName)
Test if joint is in an over torque condition.
Definition: hekKin.cxx:322
HekMonitor m_monitor
power, health, and safety monitor
Definition: hekRobot.h:709
int HekCalibStretch::fineTuneTDC ( HekRobotJoint joint,
byte_t  byOptMask,
int  nEdge,
double &  fPosition 
)
protectedvirtual

Fine tune joint to top dead center of optical limit.

The position of the joint must be in the dark, occluded region of a band prior to calling this function.

TDC Fine Tuning:
*  fine tune step           occlusion band
*                       _____________________
*   0 (start)           |     *             |
*                       |     *             |
*   1 lit_edge_0    * <------ *             |
*                   *   |                   |
*   2 dark_edge_0   * ----> *               |
*                       |   *               |
*   3 lit_edge_1        |   * ----------------> *
*                       |                   |   *
*   4 center            |         * <---------- *
*                       |___________________|
*
* 
Parameters
jointRobotic joint.
byOptMaskJoint optical limit bit mask;
nEdgeWhich edge triggered limit switch. The minimum, unknown, or maximum leading edge is specified as < 0, 0, or > 0, respectively. Not used
[out]fPositionDifference of determined uncalibrated joint position at TDC and the designed TDC (radians).
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 1069 of file hekCalibStretch.cxx.

References hekateros::degToRad(), hekateros::getLitOpticalLimits(), hekateros::HekOpticalLimit_T::m_fCenterPos, hekateros::HekOpticalLimit_T::m_fMaxEdgePos, hekateros::HekOpticalLimit_T::m_fMinEdgePos, hekateros::HekRobotJoint::m_nMasterServoId, hekateros::HekRobotJoint::m_strName, and hekateros::radToDeg().

Referenced by ~HekCalibStretch().

1073 {
1074  // joint calibrating velocity (radians/second)
1075  static double TuneCalVel = degToRad(10.0);
1076 
1077  // tuning slop (radians)
1078  static double TuneFudge = degToRad(5.0);
1079 
1080  string strJointName; // joint name
1081  int nServoId; // servo id
1082 
1083  byte_t byOptBits; // optical limits bits
1084  HekOpticalLimit_T *pLimit; // limit info associated with mask
1085  double fBandWidth; // occlusion band width (radians)
1086 
1087  double fJointStartPos; // user's starting position (radians)
1088  double fJointCurPos; // joint current position (radians)
1089  double fJointCurVel; // joint current velocity (radians/second)
1090  double fJointGoalPos; // joint working goal position (radians)
1091 
1092  double fLitEdgePos0; // joint lit edge position 0 (radians)
1093  double fLitEdgePos1; // joint lit edge position 1 (radians)
1094 
1095  int rc = HEK_OK; // return code
1096 
1097  strJointName = joint.m_strName;
1098  nServoId = joint.m_nMasterServoId;
1099  pLimit = m_robot.m_monitor.getJointLimitInfo(byOptMask);
1100 
1101  LOGDIAG3("Joint %s (servo=%d): opt_mask=0x%02x, edge=%d.",
1102  strJointName.c_str(), nServoId, byOptMask, nEdge);
1103 
1104  LOGDIAG2("Joint %s (servo=%d): "
1105  "Occlusion band: max=%lfdeg, center=%lfdeg, min=%lfdeg.",
1106  strJointName.c_str(), nServoId,
1107  radToDeg(pLimit->m_fMaxEdgePos),
1108  radToDeg(pLimit->m_fCenterPos),
1109  radToDeg(pLimit->m_fMinEdgePos));
1110 
1111  // width of occlusion band + some
1112  fBandWidth = pLimit->m_fMaxEdgePos - pLimit->m_fMinEdgePos + TuneFudge;
1113 
1114  // starting position
1115  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointStartPos, fJointCurVel);
1116 
1117  //
1118  // Move to the light side of one of the occlusion band edges.
1119  //
1120  fJointGoalPos = fJointStartPos + nEdge * fBandWidth;
1121 
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));
1125 
1126  moveToLight(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1127 
1128  // optical bits
1129  byOptBits = m_robot.m_monitor.getJointLimitBits();
1130 
1131  //
1132  // Found edge 0.
1133  //
1134  if( getLitOpticalLimits(byOptBits, byOptMask) != 0x00 )
1135  {
1136  // mark edge 0
1137  m_robot.m_pKin->getJointCurPosVel(strJointName, fLitEdgePos0, fJointCurVel);
1138 
1139  LOGDIAG2("Joint %s (servo=%d): Edge 0 at %.2lf degrees.",
1140  strJointName.c_str(), nServoId, radToDeg(fLitEdgePos0));
1141  }
1142 
1143  //
1144  // Didn't find the light.
1145  //
1146  else
1147  {
1148  if( m_robot.m_pKin->hasOverTorqueCondition(strJointName) )
1149  {
1150  LOGERROR("Joint %s (servo=%d): Cannot calibrate: Joint is obstucted.",
1151  joint.m_strName.c_str(), nServoId);
1152  rc = -HEK_ECODE_COLLISION;
1153  }
1154  else
1155  {
1156  LOGERROR("Joint %s (servo=%d): Cannot calibrate: "
1157  "Did not find edge 0 of the occlusion band.",
1158  joint.m_strName.c_str(), nServoId);
1159  rc = -HEK_ECODE_NO_EXEC;
1160  }
1161  }
1162 
1163  //
1164  // Move in opposite direction to the light side of the other occlusion band
1165  // edge.
1166  //
1167  // Note: Even on any failures above, try to move back to a probably more
1168  // reasonable position.
1169  //
1170 
1171  // first back into the dark
1172  LOGDIAG2("Joint %s (servo=%d): "
1173  "Move back into the occlusion band at %.2lf degrees.",
1174  strJointName.c_str(), nServoId, radToDeg(fJointStartPos));
1175 
1176  moveToDark(strJointName, fJointStartPos, TuneCalVel, byOptMask);
1177 
1178  // current position in dark band
1179  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1180 
1181  LOGDIAG2("Joint %s (servo=%d): Stopped at %.2lf degrees.",
1182  strJointName.c_str(), nServoId, radToDeg(fJointCurPos));
1183 
1184  //
1185  // Move to the opposite light side of one of the occlusion band edges.
1186  //
1187  fJointGoalPos = fJointCurPos - nEdge * fBandWidth;
1188 
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));
1192 
1193  // then move to the opposite light
1194  moveToLight(strJointName, fJointGoalPos, TuneCalVel, byOptMask);
1195 
1196  // optical bits
1197  byOptBits = m_robot.m_monitor.getJointLimitBits();
1198 
1199  //
1200  // Found edge 1.
1201  //
1202  if( getLitOpticalLimits(byOptBits, byOptMask) != 0x00 )
1203  {
1204  // mark edge 1
1205  m_robot.m_pKin->getJointCurPosVel(strJointName, fLitEdgePos1, fJointCurVel);
1206 
1207  LOGDIAG2("Joint %s (servo=%d): Edge 1 at %.2lf degrees.",
1208  strJointName.c_str(), nServoId, radToDeg(fLitEdgePos1));
1209  }
1210 
1211  //
1212  // Didn't find the light edge.
1213  //
1214  else
1215  {
1216  if( m_robot.m_pKin->hasOverTorqueCondition(strJointName) )
1217  {
1218  LOGERROR("Joint %s (servo=%d): Cannot calibrate: Joint is obstucted.",
1219  joint.m_strName.c_str(), nServoId);
1220  rc = (rc == HEK_OK)? -HEK_ECODE_COLLISION: rc;
1221  }
1222  else
1223  {
1224  LOGERROR("Joint %s (servo=%d): Cannot calibrate: "
1225  "Did not find edge 1 of occlusion band.",
1226  joint.m_strName.c_str(), nServoId);
1227  rc = (rc == HEK_OK)? -HEK_ECODE_NO_EXEC: rc;
1228  }
1229  }
1230 
1231  //
1232  // Move to center of occlusion band.
1233  //
1234  if( rc == HEK_OK )
1235  {
1236  fJointGoalPos = (fLitEdgePos1 + fLitEdgePos0) / 2.0;
1237 
1238  LOGDIAG2("Joint %s (servo=%d): Move to TDC at %.2lf degrees.",
1239  strJointName.c_str(), nServoId, radToDeg(fJointGoalPos));
1240 
1241  moveWait(strJointName, fJointGoalPos, TuneCalVel);
1242 
1243  m_robot.m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
1244 
1245  fPosition = pLimit->m_fCenterPos;
1246 
1247  LOGDIAG2("Joint %s (servo=%d): Fine tune TDC diff = %.2lf degrees.",
1248  strJointName.c_str(), nServoId, radToDeg(fPosition));
1249  }
1250 
1251  return rc;
1252 }
byte_t getJointLimitBits()
Get current limit switch bit values.
Definition: hekMonitor.h:413
HekOpticalLimit_T * getJointLimitInfo(byte_t byMask)
Get joint limits information.
Definition: hekMonitor.h:403
virtual void getJointCurPosVel(const std::string &strJointName, double &fJointCurPos, double &fJointCurVel)
Get the current instantaneous joint position and velocity.
Definition: hekKin.cxx:242
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
virtual double moveToLight(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until unoccluded optical limit position is detected.
Definition: hekCalib.cxx:164
Optical limit switch.
Definition: hekOptical.h:148
static const int HEK_ECODE_NO_EXEC
cannot execute error
Definition: hekateros.h:84
virtual double moveWait(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel)
Move joint to position.
Definition: hekCalib.cxx:65
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double radToDeg(double r)
Convert radians to degrees.
Definition: hekUtils.h:137
int m_nMasterServoId
master servo id
Definition: hekJoint.h:150
virtual double moveToDark(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until occluded optical limit position is detected.
Definition: hekCalib.cxx:241
double m_fMaxEdgePos
maxinum edge position of occlusion band
Definition: hekOptical.h:182
double m_fMinEdgePos
mininum edge position of occlusion band
Definition: hekOptical.h:178
std::string m_strName
joint name
Definition: hekJoint.h:149
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
static const int HEK_ECODE_COLLISION
robot link(s) in collision
Definition: hekateros.h:94
static byte_t getLitOpticalLimits(byte_t byBits, byte_t byMask)
Test if any of the optical limits are lit (not occluded).
Definition: hekOptical.h:209
virtual bool hasOverTorqueCondition(const std::string &strJointName)
Test if joint is in an over torque condition.
Definition: hekKin.cxx:322
HekMonitor m_monitor
power, health, and safety monitor
Definition: hekRobot.h:709
double m_fCenterPos
center of operation position
Definition: hekOptical.h:180
HekRobotJoint * HekCalibStretch::getHelpfulParentJoint ( int  nChildServoId)
protectedvirtual

Get the parent joint (and link) that could aid in calibration.

Only a few joints serve this function.

Parameters
nChildServoIdChild joint's master servo id.
Returns
If parenet exists, returns pointer to parent joint. Otherwise returns NULL.

Definition at line 1486 of file hekCalibStretch.cxx.

Referenced by ~HekCalibStretch().

1487 {
1488  switch( nChildServoId )
1489  {
1490  case HekServoIdWristPitch:
1491  return &(m_robot.m_jointsArm[HekServoIdElbow]);
1492  case HekServoIdElbow:
1494  default:
1495  return NULL;
1496  }
1497 }
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HekServoIdWristPitch
wrist pitch
Definition: hekateros.h:264
static const int HekServoIdElbow
elbow
Definition: hekateros.h:263
MapRobotJoints m_jointsArm
robot arm + end effector joints
Definition: hekRobot.h:697
static const int HekServoIdShoulderL
left shoulder
Definition: hekateros.h:261
int HekCalibStretch::multiMoveToDark ( const std::string &  strJointName,
int  nDir,
double  fJointGoalPos,
double  fJointGoalVel,
byte_t  byMask 
)
protectedvirtual

Move joint until occluded optical limit position is detected.

Since moving a given joint during calibration may result in large trajectory arcs, other joints may be reposition to minimize this effects.

This call blocks until move is complete.

Parameters
strJointNameName of joint.
nDirDirection indicator.
fJointGoalPosJoint goal position (radians).
fJointGoalVelJoint goal velocity (radians/second).
byMaskMask of limits to check.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 1446 of file hekCalibStretch.cxx.

Referenced by ~HekCalibStretch().

1451 {
1452  string strJointName2; // helper joint name
1453  double fGearRatios; // joint 2 gear ratio to joint 1 gear ratio
1454  double fJointGoalPos2; // helper joint goal position (radians)
1455  double fJointGoalVel2; // helper joint goal velocity (radians/second)
1456 
1457  // start helper joint moving is good direction
1458  if( strJointName == "shoulder" )
1459  {
1460  strJointName2 = "elbow";
1461  fGearRatios = calcJointRatios(strJointName2, strJointName);
1462  if( nDir > 0 )
1463  {
1464  fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMinSoftLimitRads;
1465  }
1466  else
1467  {
1468  fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMaxSoftLimitRads;
1469  }
1470  fJointGoalVel2 = fGearRatios * fJointGoalVel;
1471  m_robot.m_pKin->move(strJointName2, fJointGoalPos2, fJointGoalVel2);
1472  }
1473 
1474  // block while joint moves to light
1475  moveToDark(strJointName, fJointGoalPos, fJointGoalVel, byMask);
1476 
1477  // stop helper joint
1478  if( strJointName2.size() > 0 )
1479  {
1480  m_robot.m_pKin->stop(strJointName2);
1481  }
1482 
1483  return HEK_OK;
1484 }
HekRobotJoint * getArmJoint(const std::string &strName)
Get robotic joint in arm+ee kinematic chain.
Definition: hekRobot.h:610
virtual int stop()
Stop kinematics chain at the current position.
Definition: hekKin.cxx:399
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
double m_fMinSoftLimitRads
joint min soft limit (radians)
Definition: hekJoint.h:166
double calcJointRatios(const std::string &strJointName1, const std::string &strJointName2)
Calculate two joints&#39; gear ratios.
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
virtual double moveToDark(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until occluded optical limit position is detected.
Definition: hekCalib.cxx:241
double m_fMaxSoftLimitRads
joint max soft limit (radians)
Definition: hekJoint.h:167
virtual int move(HekJointTrajectoryPoint &trajectoryPoint)
Move kinematic chain through a trajectory point.
Definition: hekKin.cxx:500
int HekCalibStretch::multiMoveToLight ( const std::string &  strJointName,
int  nDir,
double  fJointGoalPos,
double  fJointGoalVel,
byte_t  byMask 
)
protectedvirtual

Move joint until unoccluded optical limit position is detected.

Since moving a given joint during calibration may result in large trajectory arcs, other joints may be reposition to minimize this effects.

This call blocks until move is complete.

Parameters
strJointNameName of joint.
nDirDirection indicator.
fJointGoalPosJoint goal position (radians).
fJointGoalVelJoint goal velocity (radians/second).
byMaskMask of limits to check.
Returns
On success, HEK_OK is returned.
On error, the appropriate < 0 negated Hekateros Error Code is returned.

Definition at line 1406 of file hekCalibStretch.cxx.

Referenced by ~HekCalibStretch().

1411 {
1412  string strJointName2; // helper joint name
1413  double fGearRatios; // joint 2 gear ratio to joint 1 gear ratio
1414  double fJointGoalPos2; // helper joint goal position (radians)
1415  double fJointGoalVel2; // helper joint goal velocity (radians/second)
1416 
1417  // start helper joint moving is good direction
1418  if( strJointName == "shoulder" )
1419  {
1420  strJointName2 = "elbow";
1421  fGearRatios = calcJointRatios(strJointName2, strJointName);
1422  if( nDir > 0 )
1423  {
1424  fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMinSoftLimitRads;
1425  }
1426  else
1427  {
1428  fJointGoalPos2 = m_robot.getArmJoint(strJointName2)->m_fMaxSoftLimitRads;
1429  }
1430  fJointGoalVel2 = fGearRatios * fJointGoalVel;
1431  m_robot.m_pKin->move(strJointName2, fJointGoalPos2, fJointGoalVel2);
1432  }
1433 
1434  // block while joint moves to light
1435  moveToLight(strJointName, fJointGoalPos, fJointGoalVel, byMask);
1436 
1437  // stop helper joint
1438  if( strJointName2.size() > 0 )
1439  {
1440  m_robot.m_pKin->stop(strJointName2);
1441  }
1442 
1443  return HEK_OK;
1444 }
HekRobotJoint * getArmJoint(const std::string &strName)
Get robotic joint in arm+ee kinematic chain.
Definition: hekRobot.h:610
virtual int stop()
Stop kinematics chain at the current position.
Definition: hekKin.cxx:399
HekRobot & m_robot
robot instance
Definition: hekCalib.h:165
static const int HEK_OK
not an error, success
Definition: hekateros.h:70
double m_fMinSoftLimitRads
joint min soft limit (radians)
Definition: hekJoint.h:166
double calcJointRatios(const std::string &strJointName1, const std::string &strJointName2)
Calculate two joints&#39; gear ratios.
virtual double moveToLight(const std::string &strJointName, const double fJointGoalPos, const double fJointGoalVel, byte_t byMask)
Move joint until unoccluded optical limit position is detected.
Definition: hekCalib.cxx:164
HekKinematics * m_pKin
dynamics and kinematics
Definition: hekRobot.h:703
double m_fMaxSoftLimitRads
joint max soft limit (radians)
Definition: hekJoint.h:167
virtual int move(HekJointTrajectoryPoint &trajectoryPoint)
Move kinematic chain through a trajectory point.
Definition: hekKin.cxx:500

The documentation for this class was generated from the following files: