Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

HeadPointerMC.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_HeadPointerMC_h
00003 #define INCLUDED_HeadPointerMC_h
00004 #include "MotionCommand.h"
00005 #include "OutputCmd.h"
00006 #include "Shared/RobotInfo.h"
00007 #include "Shared/mathutils.h"
00008 #include "roboop/robot.h"
00009 
00010 //! This class gives some quick and easy functions to point the head at things
00011 class HeadPointerMC : public MotionCommand {
00012 public:
00013   //! Constructor, defaults to all joints to current value in ::state (i.e. calls takeSnapshot() automatically)
00014   HeadPointerMC();
00015   
00016   //! Destructor
00017   virtual ~HeadPointerMC() {}
00018   
00019   //!Sets #hold - if this is set to false, it will allow a persistent motion to behave the same as a pruned motion, without being pruned
00020   virtual void setHold(bool h=true) { hold=h; }
00021   virtual bool getHold() { return hold; } //!< return #hold
00022 
00023   virtual void setTolerance(float t) { tolerance=t; } //!< sets #tolerance
00024   virtual float getTolerance() { return tolerance; } //!< returns #tolerance
00025   virtual void setTimeout(unsigned int delay) { timeout=delay; } //!< sets #timeout
00026   virtual unsigned int getTimeout() { return timeout; } //!< returns #timeout
00027   
00028   //! sets the target to last sent commands, and dirty to false; essentially freezes motion in place
00029   /*! This is very similar to takeSnapshot(), but will do the "right thing" (retain current position) when motion blending is involved.
00030    *  A status event will be generated if/when the joints reach the currently commanded position.
00031    *  Probably should use freezeMotion() if you want to stop a motion underway, but takeSnapshot() if you want to reset/intialize to the current joint positions. */
00032   virtual void freezeMotion();
00033   //! sets the target joint positions to current sensor values
00034   /*! Similar to freezeMotion() when a motion is underway, but only if no other MotionCommands are using neck joints.
00035     *  A status event will @e not be generated unless a motion was already underway.
00036     *  Probably should use freezeMotion() if you want to stop a motion underway, but takeSnapshot() if you want to reset/intialize to the current joint positions. */
00037   virtual void takeSnapshot();
00038 
00039   //!@name Speed Control
00040   
00041   //! Sets #maxSpeed to 0 (no maximum)
00042   void noMaxSpeed() { for(unsigned int i=0; i<NumHeadJoints; i++) maxSpeed[i]=0; }
00043   
00044   //! Restores #maxSpeed to default settings from Config::Motion_Config
00045   /*! @param x ratio of the max speed to use; so 0.5 would limit motion to half the recommended upper limit */
00046   void defaultMaxSpeed(float x=1);
00047   
00048   //! Sets #maxSpeed in rad/sec
00049   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00050    *  @param x maximum radians per second to move */
00051   void setMaxSpeed(unsigned int i, float x) { maxSpeed[i]=x*FrameTime/1000; }
00052   
00053   //! Returns #maxSpeed in rad/sec
00054   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00055    *  @return the maximum speed of joint @a i in radians per second */
00056   float getMaxSpeed(unsigned int i) { return maxSpeed[i]*1000/FrameTime; }
00057   
00058   //@}
00059   
00060   //!@name Joint Accessors
00061   
00062   //! Sets the weight values for all the neck joints
00063   void setWeight(float w);
00064   
00065   //! Directly sets the neck values (all values in radians)
00066   /*! @param j1 value for first neck joint (tilt on all ERS models)
00067    *  @param j2 value for second neck joint (pan on all ERS models)
00068    *  @param j3 value for third neck joint (nod on ERS-7, roll on ERS-2xx) */
00069   void setJoints(float j1, float j2, float j3);
00070   
00071   //! Directly set a single neck joint value
00072   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00073    *  @param value the value to be assigned to join @a i, in radians */
00074   void setJointValue(unsigned int i, float value) {
00075     if(!ensureValidJoint(i))
00076       return;
00077     headTargets[i]=clipAngularRange(HeadOffset+i,value);
00078     markDirty();
00079   }
00080   
00081   //! Returns the target value of joint @a i.  Use this if you want to know the current @b commanded joint value; To get the current joint @b position, look in WorldState::outputs
00082   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t) */
00083   float getJointValue(unsigned int i) const {
00084     if(ensureValidJoint(i))
00085       return headTargets[i];
00086     else
00087       return 0;
00088   }
00089   
00090   //! Centers the camera on a point in space, attempting to keep the camera as far away from the point as possible
00091   /*! Point should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00092    *  @param x location in millimeters
00093    *  @param y location in millimeters
00094    *  @param z location in millimeters
00095    *
00096    *  @todo this method is an approximation, could be more precise, and perhaps faster, although this is pretty good. */
00097   bool lookAtPoint(float x, float y, float z);
00098   
00099   //! Centers the camera on a point in space, attempting to move the camera @a d millimeters away from the point
00100   /*! Point should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00101    *  @param x location in millimeters
00102    *  @param y location in millimeters
00103    *  @param z location in millimeters
00104    *  @param d target distance from point in millimeters */
00105   bool lookAtPoint(float x, float y, float z, float d);
00106   
00107   //! Points the camera in a given direction
00108   /*! Vector should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00109    *  @param x component of the direction vector
00110    *  @param y component of the direction vector
00111    *  @param z component of the direction vector */
00112   bool lookInDirection(float x, float y, float z);
00113 
00114 
00115   
00116   //@}
00117   
00118 public: 
00119   //!@name Inherited:
00120   virtual int updateOutputs(); //!< Updates where the head is looking
00121   virtual int isDirty() { return (dirty || !targetReached)?3:0; } //!< true if a change has been made since the last updateJointCmds() and we're active
00122   virtual int isAlive(); //!< Alive while target is not reached
00123   virtual void DoStart() { MotionCommand::DoStart(); markDirty(); } //!< marks this as dirty each time it is added
00124   //@}
00125 
00126  protected:
00127          //! checks if target point or direction is actually reachable
00128         bool isReachable(const NEWMAT::ColumnVector& Pobj) {
00129     NEWMAT::ColumnVector poE=headkin.convertLink(0,headkin.get_dof())*Pobj;
00130     const float theta = mathutils::rad2deg(acos(poE(3)/sqrt(poE(1)*poE(1)+poE(2)*poE(2)+poE(3)*poE(3))));
00131     //    cout << "theta: " << theta << " degrees\n";
00132     return theta < 5.0;
00133   }
00134 
00135   //! puts x in the range (-pi,pi)
00136   static float normalizeAngle(float x) { return x-rint(x/(2*M_PI))*(2*M_PI); }
00137   
00138   //! if @a x is outside of the range of joint @a i, it is set to either the min or the max, whichever is closer
00139   static float clipAngularRange(unsigned int i, float x) {
00140     float min=outputRanges[i][MinRange];
00141     float max=outputRanges[i][MaxRange];
00142     if(x<min || x>max) {
00143       float mn_dist=fabs(normalizeAngle(min-x));
00144       float mx_dist=fabs(normalizeAngle(max-x));
00145       if(mn_dist<mx_dist)
00146         return min;
00147       else
00148         return max;
00149     } else
00150       return x;
00151   }
00152   //! if targetReached, reassigns headCmds from MotionManager::getOutputCmd(), then sets dirty to true and targetReached to false
00153   /*! should be called each time a joint value gets modified in case
00154    *  the head isn't where it's supposed to be, it won't jerk around
00155    * 
00156    *  MotionManager::getOutputCmd() is called instead of
00157    *  WorldState::outputs[] because if this is being called rapidly
00158    *  (i.e. after every sensor reading) using the sensor values will
00159    *  cause problems with very slow acceleration due to sensor lag
00160    *  continually resetting the current position.  Using the last
00161    *  value sent by the MotionManager fixes this.*/
00162   void markDirty();
00163 
00164   //! Makes sure @a i is in the range (0,NumHeadJoints).  If it is instead in the range (HeadOffset,HeadOffset+NumHeadJoints), output a warning and reset @a i to the obviously intended value.
00165   /*! @param[in] i joint offset relative to either HeadOffset (i.e. one of TPROffset_t) or 0
00166    *  @param[out] i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00167    *  @return true if the intended joint could be ascertained, false otherwise */
00168   static bool ensureValidJoint(unsigned int& i);
00169 
00170   bool dirty;                          //!< true if a change has been made since last call to updateJointCmds()
00171   bool  hold;                          //!< if set to true, the posture will be kept active; otherwise joints will be marked unused after each posture is achieved (as if the posture was pruned); set through setHold()
00172   float tolerance;                     //!< when autopruning, if the maxdiff() of this posture and the robot's current position is below this value, isAlive() will be false, defaults to 0.01 (5.7 degree error)
00173   bool targetReached;                  //!< false if the head is still moving towards its target
00174   unsigned int targetTimestamp;        //!< time at which the targetReached flag was set
00175   unsigned int timeout;                //!< number of milliseconds to wait before giving up on a target that should have already been reached, a value of -1U will try forever
00176   float headTargets[NumHeadJoints];    //!< stores the target value of each joint
00177   OutputCmd headCmds[NumHeadJoints];   //!< stores the last values we sent from updateOutputs
00178   float maxSpeed[NumHeadJoints];       //!< initialized from Config::motion_config, but can be overridden by setMaxSpeed(); rad per frame
00179   ROBOOP::Robot headkin;               //!< provides kinematics computations, there's a small leak and safety issue here because ROBOOP::Robot contains pointers, and those pointers typically aren't freed because MotionCommand destructor isn't called when detaching shared region
00180 };
00181 
00182 /*! @file
00183  * @brief Describes HeadPointerMC, a class for various ways to control where the head is looking
00184  * @author ejt (Creator)
00185  *
00186  * $Author: ejt $
00187  * $Name: tekkotsu-3_0 $
00188  * $Revision: 1.25 $
00189  * $State: Exp $
00190  * $Date: 2006/09/26 19:29:40 $
00191  */
00192 
00193 #endif
00194 

Tekkotsu v3.0
Generated Wed Oct 4 00:03:43 2006 by Doxygen 1.4.7