00001 #include "HeadPointerMC.h"
00002 #include "Kinematics.h"
00003 #include "Shared/debuget.h"
00004 #include "Shared/WorldState.h"
00005 #include "MotionManager.h"
00006 #include "Shared/Config.h"
00007 #include "Wireless/Socket.h"
00008 #include "Shared/ERS7Info.h"
00009 #include "Shared/ERS210Info.h"
00010 #include "Motion/IKSolver.h"
00011 #include "Shared/get_time.h"
00012 #include "Events/EventBase.h"
00013 #include "DualCoding/VRmixin.h"
00014 #include "Crew/MapBuilder.h"
00015 #include "DualCoding/Point.h"
00016
00017 #include <memory>
00018 #include <cmath>
00019
00020 HeadPointerMC::HeadPointerMC()
00021 : MotionCommand(), dirty(true), hold(true), tolerance(.05f),
00022 targetReached(true), targetTimestamp(0), timeout(2000)
00023 {
00024 setWeight(1);
00025 defaultMaxSpeed();
00026 takeSnapshot();
00027 }
00028
00029 void HeadPointerMC::freezeMotion() {
00030 #ifdef TGT_HAS_HEAD
00031 for(unsigned int i=0; i<NumHeadJoints; i++)
00032 headTargets[i]=headCmds[i].value;
00033 dirty=false;
00034 #endif
00035 }
00036
00037 void HeadPointerMC::takeSnapshot() {
00038 #ifdef TGT_HAS_HEAD
00039 for(unsigned int i=0; i<NumHeadJoints; i++)
00040 headTargets[i]=headCmds[i].value=state->outputs[HeadOffset+i];
00041 dirty=true;
00042 #endif
00043 }
00044
00045 void HeadPointerMC::defaultMaxSpeed(float x) {
00046 #ifdef TGT_HAS_HEAD
00047 const char* n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::TiltOffset];
00048 unsigned int i = capabilities.findOutputOffset(n);
00049 if(i!=-1U)
00050 maxSpeed[i-HeadOffset]=config->motion.max_head_tilt_speed*FrameTime*x/1000;
00051 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::PanOffset];
00052 i = capabilities.findOutputOffset(n);
00053 if(i!=-1U)
00054 maxSpeed[i-HeadOffset]=config->motion.max_head_pan_speed*FrameTime*x/1000;
00055 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::NodOffset];
00056 i = capabilities.findOutputOffset(n);
00057 if(i!=-1U)
00058 maxSpeed[i-HeadOffset]=config->motion.max_head_roll_speed*FrameTime*x/1000;
00059 n = ERS210Info::outputNames[ERS210Info::HeadOffset+ERS210Info::RollOffset];
00060 i = capabilities.findOutputOffset(n);
00061 if(i!=-1U)
00062 maxSpeed[i-HeadOffset]=config->motion.max_head_roll_speed*FrameTime*x/1000;
00063 #endif
00064 }
00065
00066 void HeadPointerMC::setWeight(float w) {
00067 #ifdef TGT_HAS_HEAD
00068 for(unsigned int x=0; x<NumHeadJoints; x++)
00069 headCmds[x].weight=w;
00070 setDirty();
00071 #endif
00072 }
00073
00074 void HeadPointerMC::setJoints(float pan, float tilt) {
00075 headTargets[PanOffset]=clipAngularRange(HeadOffset+PanOffset,pan);
00076 headTargets[TiltOffset]=clipAngularRange(HeadOffset+TiltOffset,tilt);
00077 }
00078
00079 void HeadPointerMC::setJoints(float tilt1, float pan, float tilt2) {
00080 #ifdef TGT_HAS_HEAD
00081 #ifdef TGT_IS_AIBO
00082 headTargets[TiltOffset]=clipAngularRange(HeadOffset+TiltOffset,tilt1);
00083 headTargets[PanOffset]=clipAngularRange(HeadOffset+PanOffset,pan);
00084 headTargets[NodOffset]=clipAngularRange(HeadOffset+NodOffset,tilt2);
00085 #else
00086 const char* n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::TiltOffset];
00087 unsigned int i = capabilities.findOutputOffset(n);
00088 if(i!=-1U)
00089 headTargets[i-HeadOffset]=clipAngularRange(i,tilt1);
00090 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::PanOffset];
00091 i = capabilities.findOutputOffset(n);
00092 if(i!=-1U)
00093 headTargets[i-HeadOffset]=clipAngularRange(i,pan);
00094 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::NodOffset];
00095 i = capabilities.findOutputOffset(n);
00096 if(i!=-1U)
00097 headTargets[i-HeadOffset]=clipAngularRange(i,tilt2);
00098 #endif
00099 setDirty();
00100 #endif
00101 }
00102
00103 void HeadPointerMC::setJoints(float pan, float shoulder, float elbow, float pitch) {
00104 setMaxSpeed(0, 0.2f);
00105 setMaxSpeed(1, 0.2f);
00106 setMaxSpeed(2, 0.2f);
00107 setMaxSpeed(3, 0.2f);
00108 setJointValue(0, pan);
00109 setJointValue(1, shoulder);
00110 setJointValue(2, elbow);
00111 setJointValue(3, pitch);
00112 }
00113
00114 #include <iostream>
00115 using namespace std;
00116
00117 bool HeadPointerMC::lookAtPoint(float x, float y, float z) {
00118 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00119 return false;
00120 #else
00121 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00122 if(kinEff==NULL) {
00123 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00124 return false;
00125 }
00126 KinematicJoint * effector = kinEff->cloneBranch();
00127 std::unique_ptr<KinematicJoint> root(effector->getRoot());
00128
00129
00130
00131
00132 effector->qmax = std::numeric_limits<float>::infinity();
00133
00134 bool conv = effector->getIK().solve(IKSolver::Point(),*effector,IKSolver::Point(x,y,z));
00135 do {
00136 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00137 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00138 effector = effector->getParent();
00139 } while(effector!=NULL);
00140 setDirty();
00141
00142 return conv;
00143 #endif
00144
00145 }
00146
00147 bool HeadPointerMC::lookAtPoint(const DualCoding::Point &p) {
00148 DualCoding::Point p2 = p;
00149 switch ( p2.getRefFrameType() ) {
00150 case DualCoding::camcentric:
00151
00152 cout << "Error: HeadPointerMC::lookAtPoint cannot accept point " << p2 << " in camera-centric coordinates\n";
00153 return false;
00154 case DualCoding::allocentric: {
00155 if ( DualCoding::VRmixin::mapBuilder == NULL ) {
00156 cout << "Error: HeadPointerMC:lookAtPoint can't convert allocentric point " << p2
00157 << " to egocentric because MapBuilder is not running\n";
00158 return false;
00159 }
00160 fmat::Column<3> q = DualCoding::VRmixin::mapBuilder->worldToLocalMatrix * p2.getCoords();
00161 p2.setCoords(q[0], q[1], q[2]);
00162 }
00163
00164 case DualCoding::egocentric:
00165 case DualCoding::unspecified:
00166 return lookAtPoint(p2.coordX(), p2.coordY(), p2.coordZ());
00167 }
00168 cerr << "Error: HeadPointerMC::lookAtPoint given DualCoding::Point with invalid reference frame " << p2.getRefFrameType() << endl;
00169 return false;
00170 }
00171
00172 bool HeadPointerMC::lookAtPoint(const fmat::Column<3> &p) {
00173 return lookAtPoint(p[0], p[1], p[2]);
00174 }
00175
00176 bool HeadPointerMC::lookAtPoint(float x, float y, float z, float d) {
00177 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00178 return false;
00179 #else
00180 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00181 if(kinEff==NULL) {
00182 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00183 return false;
00184 }
00185 KinematicJoint * effector = kinEff->cloneBranch();
00186 std::unique_ptr<KinematicJoint> root(effector->getRoot());
00187
00188
00189
00190 bool conv = effector->getIK().solve(IKSolver::Point(0,0,d),*effector,IKSolver::Point(x,y,z));
00191 do {
00192 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00193 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00194 effector = effector->getParent();
00195 } while(effector!=NULL);
00196 setDirty();
00197
00198 return conv;
00199 #endif
00200 }
00201
00202 bool HeadPointerMC::lookInDirection(float x, float y, float z) {
00203 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00204 return false;
00205 #else
00206 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00207 if(kinEff==NULL) {
00208 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00209 return false;
00210 }
00211 KinematicJoint * effector = kinEff->cloneBranch();
00212 std::unique_ptr<KinematicJoint> root(effector->getRoot());
00213
00214
00215
00216 bool conv = effector->getIK().solve(IKSolver::Rotation(),*effector,IKSolver::Parallel(x,y,z));
00217 do {
00218 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00219 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00220 effector = effector->getParent();
00221 } while(effector!=NULL);
00222 setDirty();
00223
00224 return conv;
00225 #endif
00226 }
00227
00228 bool HeadPointerMC::lookAtJoint(unsigned int j) {
00229 const fmat::Column<3> jointPos = kine->linkToBase(j).translation();
00230 return lookAtPoint(jointPos);
00231 }
00232
00233 int HeadPointerMC::updateOutputs() {
00234 int tmp=isDirty();
00235 if(tmp || hold) {
00236 dirty=false;
00237 #ifdef TGT_HAS_HEAD
00238 for(unsigned int i=0; i<NumHeadJoints; i++) {
00239 if(maxSpeed[i]<=0) {
00240 headCmds[i].value=headTargets[i];
00241 motman->setOutput(this,i+HeadOffset,headCmds[i]);
00242 } else {
00243 unsigned int f=0;
00244 while(headTargets[i]>headCmds[i].value+maxSpeed[i] && f<NumFrames) {
00245 headCmds[i].value+=maxSpeed[i];
00246 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00247 f++;
00248 }
00249 while(headTargets[i]<headCmds[i].value-maxSpeed[i] && f<NumFrames) {
00250 headCmds[i].value-=maxSpeed[i];
00251 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00252 f++;
00253 }
00254 if(f<NumFrames) {
00255 headCmds[i].value=headTargets[i];
00256 for(;f<NumFrames;f++)
00257 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00258 } else
00259 dirty=true;
00260 }
00261 }
00262 #endif
00263 if(!dirty && !targetReached) {
00264 postEvent(EventBase(EventBase::motmanEGID, getID(),EventBase::statusETID));
00265 targetReached=true;
00266 targetTimestamp=get_time();
00267 }
00268 }
00269 return tmp;
00270 }
00271
00272 int HeadPointerMC::isAlive() {
00273 #ifndef TGT_HAS_HEAD
00274 return false;
00275 #else
00276 if(dirty || !targetReached)
00277 return true;
00278 if(targetReached && (!hold || get_time()-targetTimestamp>timeout)) {
00279 if(get_time()-targetTimestamp>timeout && getAutoPrune())
00280 serr->printf("WARNING: HeadPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00281 return false;
00282 }
00283 float maxdiff=0;
00284 for(unsigned int i=0; i<NumHeadJoints; i++) {
00285 float diff=fabsf(state->outputs[HeadOffset+i]-headTargets[i]);
00286 if(diff>maxdiff)
00287 maxdiff=diff;
00288 }
00289 return (maxdiff>tolerance);
00290 #endif
00291 }
00292
00293 void HeadPointerMC::setDirty() {
00294 dirty=true;
00295 targetReached=false;
00296 #ifdef TGT_HAS_HEAD
00297 for(unsigned int i=0; i<NumHeadJoints; i++)
00298 headCmds[i].value=motman->getOutputCmd(HeadOffset+i).value;
00299 #endif
00300 }
00301
00302 bool HeadPointerMC::ensureValidJoint(unsigned int& i) {
00303 #ifndef TGT_HAS_HEAD
00304 serr->printf("ERROR: HeadPointerMC received a joint index of %d on headless target.\n",i);
00305 #else
00306 if(i<NumHeadJoints)
00307 return true;
00308 if(i>=HeadOffset && i<HeadOffset+NumHeadJoints) {
00309 i-=HeadOffset;
00310 serr->printf("WARNING: HeadPointerMC received a joint index of %d (HeadOffset+%d).\n",i+HeadOffset,i);
00311 serr->printf(" Since all parameters are assumed to be relative to HeadOffset,\n");
00312 serr->printf(" you should just pass %d directly.\n",i);
00313 serr->printf("WARNING: Assuming you meant %d...\n",i);
00314 return true;
00315 }
00316 serr->printf("ERROR: HeadPointerMC received a joint index of %d (HeadOffset%+d).\n",i,i-HeadOffset);
00317 serr->printf("ERROR: This does not appear to be a head joint. HeadPointerMC only controls\n");
00318 serr->printf(" head joints, and assumes its arguments are relative to HeadOffset\n");
00319 #endif
00320 return false;
00321 }
00322
00323
00324
00325
00326
00327