00001 #include "ArmMC.h"
00002 #include "Kinematics.h"
00003 #include "IKSolver.h"
00004 #include "Shared/debuget.h"
00005 #include "Shared/WorldState.h"
00006 #include "MotionManager.h"
00007 #include "Shared/Config.h"
00008 #include "Wireless/Socket.h"
00009 #include "Shared/get_time.h"
00010 #include "Events/EventBase.h"
00011
00012 #include <memory>
00013 #include <cmath>
00014 using namespace std;
00015
00016 ArmMC::ArmMC()
00017 : MotionCommand(), dirty(true), hold(true), tolerance(.05f),
00018 completionReported(true), targetTimestamp(0), timeout(2000),
00019 pulseOnPeriod(0), pulseOffPeriod(0), pulseStartTime(0),
00020 desiredLoad(0), angleIncrement(0.05), idleCycles(8)
00021 {
00022
00023
00024
00025
00026 takeSnapshot();
00027 setWeight(0);
00028 defaultMaxSpeed();
00029 }
00030
00031 void ArmMC::freezeMotion() {
00032 #ifdef TGT_HAS_ARMS
00033 for(unsigned int i=0; i<NumArmJoints; i++)
00034 armTargets[i]=armCmds[i].value;
00035 dirty=false;
00036 #endif
00037 }
00038
00039 void ArmMC::takeSnapshot() {
00040 #ifdef TGT_HAS_ARMS
00041 for(unsigned int i=0; i<NumArmJoints; i++)
00042 armTargets[i]=armCmds[i].value=state->outputs[ArmOffset+i];
00043 dirty=true;
00044 #endif
00045 }
00046
00047 float ArmMC::armJointValue(unsigned int i) {
00048 #ifdef TGT_HAS_ARMS
00049 return armTargets[i];
00050 #else
00051 serr->printf("WARNING: No Arm");
00052 return -1000.0f;
00053 #endif
00054 }
00055
00056 void ArmMC::defaultMaxSpeed(float x) {
00057 #ifdef TGT_HAS_ARMS
00058 for(unsigned int i = 0; i<NumArmJoints; i++)
00059 maxSpeed[i] = 0.3f;
00060 #endif
00061 }
00062
00063 void ArmMC::setWeight(float w) {
00064 #ifdef TGT_HAS_ARMS
00065 for(unsigned int i=0; i<NumArmJoints; i++)
00066 armCmds[i].weight=w;
00067 setDirty();
00068 #endif
00069 }
00070
00071 void ArmMC::setWeight(int i, float w) {
00072 #ifdef TGT_HAS_ARMS
00073 armCmds[i].weight=w;
00074 setDirty();
00075 #endif
00076 }
00077
00078 void ArmMC::setJoints(float shoulder, float elbow, float wrist){
00079 #ifdef TGT_HAS_ARMS
00080 setMaxSpeed(0, 0.4f);
00081 setMaxSpeed(1, 0.4f);
00082 setMaxSpeed(2, 0.4f);
00083 setJointValue(0, shoulder);
00084 setJointValue(1, elbow);
00085 setJointValue(2, wrist);
00086 #endif
00087 }
00088
00089 void ArmMC::setJoints(float shoulder, float elbow, float yaw, float pitch, float roll, float gripper) {
00090 #ifdef TGT_HAS_ARMS
00091 setMaxSpeed(0, 0.4f);
00092 setMaxSpeed(1, 0.4f);
00093 setMaxSpeed(2, 0.4f);
00094 setMaxSpeed(3, 0.4f);
00095 setMaxSpeed(4, 0.4f);
00096 setMaxSpeed(5, 0.4f);
00097 setJointValue(0, shoulder);
00098 setJointValue(1, elbow);
00099 setJointValue(2, yaw);
00100 setJointValue(3, pitch);
00101 setJointValue(4, roll);
00102 setJointValue(5, gripper);
00103 #endif
00104 }
00105
00106 void ArmMC::setWrist(float pitch, float roll, float gripper) {
00107 #ifdef TGT_HAS_ARMS
00108 setMaxSpeed(3, 0.4f);
00109 setMaxSpeed(4, 0.4f);
00110 setMaxSpeed(5, 0.4f);
00111 setJointValue(3, pitch);
00112 setJointValue(4, roll);
00113 setJointValue(5, gripper);
00114 #endif
00115 }
00116
00117 void ArmMC::setGripperSpeed(float x) {
00118 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00119 setMaxSpeed(GripperOffset-ArmOffset, x);
00120
00121 setGraspSpeed(x/10.0);
00122 #elif defined(TGT_IS_CALLIOPE5)
00123 setMaxSpeed(LeftFingerOffset-ArmOffset, x);
00124 setMaxSpeed(RightFingerOffset-ArmOffset, x);
00125 #else
00126 std::cerr << "ArmMC::setGripperSpeed doesn't know about this robot type." << std::endl;
00127 #endif
00128 }
00129
00130 void ArmMC::setGripperPulse(unsigned int onPeriod, unsigned int offPeriod) {
00131 pulseOnPeriod = onPeriod;
00132 pulseOffPeriod = offPeriod;
00133 pulseStartTime = get_time();
00134 setDirty();
00135 }
00136
00137
00138 void ArmMC::requestGripperLoad(int newLoad = -280){
00139 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00140 desiredLoad = newLoad;
00141 setDirty();
00142 #else
00143 cout << "Method \"requestGripperLoad\" is only applicable for CALLIOPE robots" << endl;
00144 #endif
00145 }
00146
00147 int ArmMC::getGripperLoad(){
00148 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00149 return int(state->pidduties[GripperOffset]*1023);
00150 #else
00151 cout << "Method \"requestGripperLoad\" is only applicable for CALLIOPE robots" << endl;
00152 return 0;
00153 #endif
00154 }
00155
00156 void ArmMC::setGraspSpeed( float speed){
00157 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00158 angleIncrement = speed;
00159 #else
00160 cout << "Method \"setGraspSpeed\" is only applicable for CALLIOPE robots" << endl;
00161 #endif
00162 }
00163
00164 void ArmMC::setGraspWait(unsigned int cycles){
00165 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00166 idleCycles = cycles;
00167 #else
00168 cout << "Method \"setGraspWait\" is only applicable for CALLIOPE robots" << endl;
00169 #endif
00170 }
00171
00172 void ArmMC::incrementGrasp(){
00173 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00174
00175
00176 static float progressiveIncrement = 0.0;
00177 static int previousLoad = 0;
00178 static unsigned int idlePeriods = 0;
00179
00180 int currentLoad = getGripperLoad();
00181
00182 if(currentLoad < desiredLoad){
00183 return;
00184 }
00185 else{
00186
00187 float currentGripperAngle = state->outputs[GripperOffset];
00188
00189 if(state->sensors[GPSXOffset] != 0.0 && currentGripperAngle <= 0.45){
00190
00191
00192 return;
00193 }
00194 else if(currentGripperAngle <= 0.15){
00195
00196 return;
00197 }
00198
00199
00200 if(previousLoad == currentLoad && currentLoad != 0){
00201 if(idlePeriods == idleCycles){
00202 progressiveIncrement += angleIncrement;
00203 idlePeriods = 0;
00204 }
00205 else {
00206 idlePeriods++;
00207 }
00208 } else {
00209 previousLoad = currentLoad;
00210 progressiveIncrement = 0;
00211 idlePeriods = 0;
00212 }
00213
00214 setJointValue(GripperOffset-ArmOffset, currentGripperAngle - angleIncrement - progressiveIncrement);
00215 }
00216 #endif
00217 }
00218
00219
00220 void ArmMC::clearGripperPulse() {
00221 pulseOnPeriod = pulseOffPeriod = 0;
00222 #if defined(TGT_HAS_FINGERS)
00223 motman->setOutput(this, LeftFingerOffset, OutputPID(DefaultPIDs[LeftFingerOffset-PIDJointOffset],1));
00224 motman->setOutput(this, RightFingerOffset, OutputPID(DefaultPIDs[RightFingerOffset-PIDJointOffset],1));
00225 #elif defined(TGT_IS_MANTIS)
00226 ;
00227 #elif defined(TGT_HAS_GRIPPER)
00228 motman->setOutput(this, GripperOffset, OutputPID(DefaultPIDs[GripperOffset-PIDJointOffset],1));
00229 #endif
00230 }
00231
00232 bool ArmMC::moveOffsetToPoint(const fmat::Column<3>& offset, const fmat::Column<3>& tgt) {
00233 #ifndef TGT_HAS_ARMS
00234 return false;
00235 #else
00236 const KinematicJoint * kinEff=NULL;
00237 unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00238 if(effIdx!=-1U)
00239 kinEff = kine->getKinematicJoint(effIdx);
00240 if(kinEff==NULL)
00241 kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00242 if(kinEff==NULL)
00243 return false;
00244 KinematicJoint * effector = kinEff->cloneBranch();
00245
00246
00247 bool conv = effector->getIK().solve(offset,*effector,IKSolver::Point(tgt));
00248
00249
00250 while(effector!=NULL) {
00251 if(effector->outputOffset<NumOutputs)
00252 setOutputCmd(effector->outputOffset, effector->getQ());
00253 effector = effector->getParent();
00254 }
00255 return conv;
00256 #endif
00257 }
00258
00259 bool ArmMC::moveOffsetToPointWithOrientation(const fmat::Column<3>& offset, const fmat::Column<3>& tgt, const fmat::Quaternion& ori) {
00260 #ifndef TGT_HAS_ARMS
00261 return false;
00262 #else
00263 const KinematicJoint * kinEff=NULL;
00264 unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00265 if(effIdx!=-1U)
00266 kinEff = kine->getKinematicJoint(effIdx);
00267 if(kinEff==NULL)
00268 kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00269 if(kinEff==NULL)
00270 return false;
00271 KinematicJoint * effector = kinEff->cloneBranch();
00272
00273
00274 bool conv = effector->getIK().solve(offset, IKSolver::Rotation(fmat::Quaternion()), *effector, IKSolver::Point(tgt), 1, IKSolver::Rotation(ori), 0);
00275
00276
00277 while(effector!=NULL) {
00278 if(effector->outputOffset<NumOutputs)
00279 setOutputCmd(effector->outputOffset, effector->getQ());
00280 effector = effector->getParent();
00281 }
00282 return conv;
00283 #endif
00284 }
00285
00286 bool ArmMC::setFingerGap(float dist) {
00287 #ifdef TGT_CALLIOPE5KP
00288 PostureEngine mypos;
00289 mypos.setOutputCmd(LeftFingerOffset, 0);
00290 mypos.setOutputCmd(RightFingerOffset, 0);
00291 fmat::Column<3> lf = mypos.getPosition(LeftFingerOffset);
00292 fmat::Column<3> rf = mypos.getPosition(RightFingerOffset);
00293 float c = (lf-rf).norm();
00294 fmat::Transform trans = mypos.linkToLink(LeftFingerFrameOffset, LeftFingerOffset);
00295 AngSignPi alpha = asin(trans(0,0));
00296 float r = sqrt ( trans(0,3)*trans(0,3) + trans(1,3)*trans(1,3) );
00297 if ( dist < 0 || dist > 2*r+c )
00298 return false;
00299 AngSignPi q = asin((dist/2-c/2)/r) - alpha;
00300 setJointValue(LeftFingerOffset, -q);
00301 setJointValue(RightFingerOffset, q);
00302 #endif
00303 return true;
00304 }
00305
00306 bool ArmMC::openGripper(float percentage) {
00307 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00308 float gripperAngle = outputRanges[GripperOffset][MinRange] +
00309 percentage * (outputRanges[GripperOffset][MaxRange] - outputRanges[GripperOffset][MinRange]);
00310 setJointValue(GripperOffset-ArmOffset, gripperAngle);
00311
00312 requestGripperLoad(0);
00313 #elif defined(TGT_IS_CALLIOPE5)
00314 float gripperAngleL = outputRanges[LeftFingerOffset][MaxRange] +
00315 percentage * (outputRanges[LeftFingerOffset][MinRange] - outputRanges[LeftFingerOffset][MaxRange]);
00316 float gripperAngleR = outputRanges[RightFingerOffset][MinRange] +
00317 percentage * (outputRanges[RightFingerOffset][MaxRange] - outputRanges[RightFingerOffset][MinRange]);
00318 setJointValue(LeftFingerOffset-ArmOffset, gripperAngleL);
00319 setJointValue(RightFingerOffset-ArmOffset, gripperAngleR);
00320 #endif
00321 return true;
00322 }
00323
00324 int ArmMC::updateOutputs() {
00325 int prevDirty = isDirty();
00326 if (prevDirty || hold) {
00327 dirty = false;
00328 #ifdef TGT_HAS_ARMS
00329 for(unsigned int i=0; i < NumArmJoints; i++) {
00330 if(maxSpeed[i]<=0) {
00331 armCmds[i].value=armTargets[i];
00332 motman->setOutput(this,i+ArmOffset,armCmds[i]);
00333 } else {
00334 unsigned int f=0;
00335 while(armTargets[i]>armCmds[i].value+maxSpeed[i] && f<NumFrames) {
00336 armCmds[i].value+=maxSpeed[i];
00337 motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00338 f++;
00339 }
00340 while(armTargets[i]<armCmds[i].value-maxSpeed[i] && f<NumFrames) {
00341 armCmds[i].value-=maxSpeed[i];
00342 motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00343 f++;
00344 }
00345 if(f<NumFrames) {
00346 armCmds[i].value=armTargets[i];
00347 for(;f<NumFrames;f++)
00348 motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00349 } else
00350 dirty=true;
00351 }
00352 }
00353 #if defined(TGT_IS_CALLIOPE2)
00354 if(desiredLoad != 0) incrementGrasp();
00355 #endif
00356 #endif
00357 if(!dirty && !completionReported) {
00358 postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
00359 completionReported=true;
00360 targetTimestamp=get_time();
00361 }
00362 }
00363
00364
00365 #if false
00366
00367 if ( pulseOnPeriod > 0 ) {
00368 dirty = true;
00369 unsigned int t = get_time();
00370 if ( t >= pulseStartTime + pulseOnPeriod + pulseOffPeriod ) {
00371 pulseStartTime = t;
00372 }
00373
00374 #if defined(TGT_HAS_FINGERS) || defined(TGT_HAS_GRIPPER)
00375 if (t >= pulseStartTime + pulseOnPeriod) {
00376
00377 #ifdef TGT_HAS_FINGERS
00378 motman->setOutput(this, LeftFingerOffset, OutputPID(0,0,0,1));
00379 motman->setOutput(this, RightFingerOffset, OutputPID(0,0,0,1));
00380 #else
00381 motman->setOutput(this, GripperOffset, OutputPID(0,0,0,1));
00382 #endif
00383 } else {
00384 #ifdef TGT_HAS_FINGERS
00385 motman->setOutput(this, LeftFingerOffset, OutputPID(DefaultPIDs[LeftFingerOffset-PIDJointOffset],1));
00386 motman->setOutput(this, RightFingerOffset, OutputPID(DefaultPIDs[RightFingerOffset-PIDJointOffset],1));
00387 #else
00388 motman->setOutput(this, GripperOffset, OutputPID(DefaultPIDs[GripperOffset-PIDJointOffset],1));
00389 #endif
00390 }
00391 #endif
00392 }
00393 #endif
00394
00395 return prevDirty;
00396 }
00397
00398 int ArmMC::isAlive() {
00399 #ifdef TGT_HAS_ARMS
00400 if(dirty || !completionReported)
00401 return true;
00402
00403 if(completionReported && (!hold || get_time()-targetTimestamp>timeout)) {
00404 if(get_time()-targetTimestamp>timeout && getAutoPrune())
00405 serr->printf("WARNING: ArmPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00406 return false;
00407 }
00408 float maxdiff=0;
00409 for(unsigned int i=0; i<NumArmJoints; i++) {
00410 float diff=fabsf(state->outputs[ArmOffset+i]-armTargets[i]);
00411 if(diff>maxdiff)
00412 maxdiff=diff;
00413 }
00414 return (maxdiff>tolerance);
00415 #else
00416 return false;
00417 #endif
00418 }
00419
00420 void ArmMC::setDirty() {
00421 dirty=true;
00422 completionReported=false;
00423 #ifdef TGT_HAS_ARMS
00424 for(unsigned int i=0; i<NumArmJoints; i++)
00425 armCmds[i].value=motman->getOutputCmd(ArmOffset+i).value;
00426 #endif
00427 }
00428
00429 bool ArmMC::ensureValidJoint(unsigned int& i) {
00430 #ifdef TGT_HAS_ARMS
00431 if(i<NumArmJoints)
00432 return true;
00433 if(i>=ArmOffset && i<ArmOffset+NumArmJoints) {
00434 i-=ArmOffset;
00435 serr->printf("WARNING: ArmMC received a joint index of %d (ArmOffset+%d).\n",i+ArmOffset,i);
00436 serr->printf(" Since all parameters are assumed to be relative to ArmOffset,\n");
00437 serr->printf(" you should just pass %d directly.\n",i);
00438 serr->printf("WARNING: Assuming you meant %d...\n",i);
00439 return true;
00440 }
00441 serr->printf("ERROR: ArmMC received a joint index of %d (ArmOffset%+d).\n",i,i-ArmOffset);
00442 serr->printf("ERROR: This does not appear to be a arm joint. ArmPointerMC only controls\n");
00443 serr->printf(" arm joints, and assumes its arguments are relative to ArmOffset\n");
00444 #endif
00445 return false;
00446 }