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 markDirty();
00071 #endif
00072 }
00073
00074 void HeadPointerMC::setJoints(float tilt1, float pan, float tilt2) {
00075 #ifdef TGT_HAS_HEAD
00076 #ifdef TGT_IS_AIBO
00077 headTargets[TiltOffset]=clipAngularRange(HeadOffset+TiltOffset,tilt1);
00078 headTargets[PanOffset]=clipAngularRange(HeadOffset+PanOffset,pan);
00079 headTargets[NodOffset]=clipAngularRange(HeadOffset+NodOffset,tilt2);
00080 #else
00081 const char* n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::TiltOffset];
00082 unsigned int i = capabilities.findOutputOffset(n);
00083 if(i!=-1U)
00084 headTargets[i-HeadOffset]=clipAngularRange(i,tilt1);
00085 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::PanOffset];
00086 i = capabilities.findOutputOffset(n);
00087 if(i!=-1U)
00088 headTargets[i-HeadOffset]=clipAngularRange(i,pan);
00089 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::NodOffset];
00090 i = capabilities.findOutputOffset(n);
00091 if(i!=-1U)
00092 headTargets[i-HeadOffset]=clipAngularRange(i,tilt2);
00093 #endif
00094 markDirty();
00095 #endif
00096 }
00097
00098 void HeadPointerMC::setJoints(float pan, float shoulder, float elbow, float pitch) {
00099 setMaxSpeed(0, 0.2f);
00100 setMaxSpeed(1, 0.2f);
00101 setMaxSpeed(2, 0.2f);
00102 setMaxSpeed(3, 0.2f);
00103 setJointValue(0, pan);
00104 setJointValue(1, shoulder);
00105 setJointValue(2, elbow);
00106 setJointValue(3, pitch);
00107 }
00108
00109 #include <iostream>
00110 using namespace std;
00111
00112 bool HeadPointerMC::lookAtPoint(float x, float y, float z) {
00113 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00114 return false;
00115 #else
00116 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00117 if(kinEff==NULL) {
00118 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00119 return false;
00120 }
00121 KinematicJoint * effector = kinEff->cloneBranch();
00122 std::auto_ptr<KinematicJoint> root(effector->getRoot());
00123
00124
00125
00126
00127 effector->qmax = std::numeric_limits<float>::infinity();
00128
00129 bool conv = effector->getIK().solve(IKSolver::Point(),*effector,IKSolver::Point(x,y,z));
00130 do {
00131 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00132 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00133 effector = effector->getParent();
00134 } while(effector!=NULL);
00135 markDirty();
00136
00137 return conv;
00138 #endif
00139
00140 }
00141
00142 bool HeadPointerMC::lookAtPoint(const DualCoding::Point &p) {
00143 DualCoding::Point p2 = p;
00144 switch ( p2.getRefFrameType() ) {
00145 case DualCoding::camcentric:
00146
00147 cout << "Error: HeadPointerMC::lookAtPoint cannot accept point " << p2 << " in camera-centric coordinates\n";
00148 return false;
00149 case DualCoding::allocentric: {
00150 if ( DualCoding::VRmixin::mapBuilder == NULL ) {
00151 cout << "Error: HeadPointerMC:lookAtPoint can't convert allocentric point " << p2
00152 << " to egocentric because MapBuilder is not running\n";
00153 return false;
00154 }
00155 fmat::Column<3> q = DualCoding::VRmixin::mapBuilder->worldToLocalRotateMatrix
00156 * (DualCoding::VRmixin::mapBuilder->worldToLocalTranslateMatrix * p2.getCoords());
00157 p2.setCoords(q[0], q[1], q[2]);
00158 }
00159
00160 case DualCoding::egocentric:
00161 case DualCoding::unspecified:
00162 return lookAtPoint(p2.coordX(), p2.coordY(), p2.coordZ());
00163 }
00164 cerr << "Error: HeadPointerMC::lookAtPoint given DualCoding::Point with invalid reference frame " << p2.getRefFrameType() << endl;
00165 return false;
00166 }
00167
00168 bool HeadPointerMC::lookAtPoint(float x, float y, float z, float d) {
00169 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00170 return false;
00171 #else
00172 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00173 if(kinEff==NULL) {
00174 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00175 return false;
00176 }
00177 KinematicJoint * effector = kinEff->cloneBranch();
00178 std::auto_ptr<KinematicJoint> root(effector->getRoot());
00179
00180
00181
00182 bool conv = effector->getIK().solve(IKSolver::Point(0,0,d),*effector,IKSolver::Point(x,y,z));
00183 do {
00184 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00185 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00186 effector = effector->getParent();
00187 } while(effector!=NULL);
00188 markDirty();
00189
00190 return conv;
00191 #endif
00192 }
00193
00194 bool HeadPointerMC::lookInDirection(float x, float y, float z) {
00195 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00196 return false;
00197 #else
00198 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00199 if(kinEff==NULL) {
00200 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00201 return false;
00202 }
00203 KinematicJoint * effector = kinEff->cloneBranch();
00204 std::auto_ptr<KinematicJoint> root(effector->getRoot());
00205
00206
00207
00208 bool conv = effector->getIK().solve(IKSolver::Rotation(),*effector,IKSolver::Parallel(x,y,z));
00209 do {
00210 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00211 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00212 effector = effector->getParent();
00213 } while(effector!=NULL);
00214 markDirty();
00215
00216 return conv;
00217 #endif
00218 }
00219
00220
00221 int HeadPointerMC::updateOutputs() {
00222 int tmp=isDirty();
00223 if(tmp || hold) {
00224 dirty=false;
00225 #ifdef TGT_HAS_HEAD
00226 for(unsigned int i=0; i<NumHeadJoints; i++) {
00227 if(maxSpeed[i]<=0) {
00228 headCmds[i].value=headTargets[i];
00229 motman->setOutput(this,i+HeadOffset,headCmds[i]);
00230 } else {
00231 unsigned int f=0;
00232 while(headTargets[i]>headCmds[i].value+maxSpeed[i] && f<NumFrames) {
00233 headCmds[i].value+=maxSpeed[i];
00234 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00235 f++;
00236 }
00237 while(headTargets[i]<headCmds[i].value-maxSpeed[i] && f<NumFrames) {
00238 headCmds[i].value-=maxSpeed[i];
00239 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00240 f++;
00241 }
00242 if(f<NumFrames) {
00243 headCmds[i].value=headTargets[i];
00244 for(;f<NumFrames;f++)
00245 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00246 } else
00247 dirty=true;
00248 }
00249 }
00250 #endif
00251 if(!dirty && !targetReached) {
00252 postEvent(EventBase(EventBase::motmanEGID, getID(),EventBase::statusETID));
00253 targetReached=true;
00254 targetTimestamp=get_time();
00255 }
00256 }
00257 return tmp;
00258 }
00259
00260 int HeadPointerMC::isAlive() {
00261 #ifndef TGT_HAS_HEAD
00262 return false;
00263 #else
00264 if(dirty || !targetReached)
00265 return true;
00266 if(targetReached && (!hold || get_time()-targetTimestamp>timeout)) {
00267 if(get_time()-targetTimestamp>timeout && getAutoPrune())
00268 serr->printf("WARNING: HeadPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00269 return false;
00270 }
00271 float maxdiff=0;
00272 for(unsigned int i=0; i<NumHeadJoints; i++) {
00273 float diff=fabsf(state->outputs[HeadOffset+i]-headTargets[i]);
00274 if(diff>maxdiff)
00275 maxdiff=diff;
00276 }
00277 return (maxdiff>tolerance);
00278 #endif
00279 }
00280
00281 void HeadPointerMC::markDirty() {
00282 dirty=true;
00283 targetReached=false;
00284 #ifdef TGT_HAS_HEAD
00285 for(unsigned int i=0; i<NumHeadJoints; i++)
00286 headCmds[i].value=motman->getOutputCmd(HeadOffset+i).value;
00287 #endif
00288 }
00289
00290 bool HeadPointerMC::ensureValidJoint(unsigned int& i) {
00291 #ifndef TGT_HAS_HEAD
00292 serr->printf("ERROR: HeadPointerMC received a joint index of %d on headless target.\n",i);
00293 #else
00294 if(i<NumHeadJoints)
00295 return true;
00296 if(i>=HeadOffset && i<HeadOffset+NumHeadJoints) {
00297 i-=HeadOffset;
00298 serr->printf("WARNING: HeadPointerMC received a joint index of %d (HeadOffset+%d).\n",i+HeadOffset,i);
00299 serr->printf(" Since all parameters are assumed to be relative to HeadOffset,\n");
00300 serr->printf(" you should just pass %d directly.\n",i);
00301 serr->printf("WARNING: Assuming you meant %d...\n",i);
00302 return true;
00303 }
00304 serr->printf("ERROR: HeadPointerMC received a joint index of %d (HeadOffset%+d).\n",i,i-HeadOffset);
00305 serr->printf("ERROR: This does not appear to be a head joint. HeadPointerMC only controls\n");
00306 serr->printf(" head joints, and assumes its arguments are relative to HeadOffset\n");
00307 #endif
00308 return false;
00309 }
00310
00311
00312
00313
00314
00315