Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ArmMC.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_ArmMC_h
00003 #define INCLUDED_ArmMC_h
00004 
00005 #include "MotionCommand.h"
00006 #include "OutputCmd.h"
00007 #include "PostureEngine.h"
00008 #include "PostureMC.h"
00009 #include "Shared/RobotInfo.h"
00010 #include "Shared/mathutils.h"
00011 
00012 class ArmMC : public MotionCommand {
00013 public:
00014   //! Constructor, defaults to all joints to current value in ::state (i.e. calls takeSnapshot() automatically)
00015   ArmMC();
00016   virtual ~ArmMC() {}
00017 
00018   //! Constructor
00019   
00020   //!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
00021   virtual void setHold(bool h=true) { hold=h; }
00022   virtual bool getHold() { return hold; } //!< return #hold
00023 
00024   virtual void setTolerance(float t) { tolerance=t; } //!< sets #tolerance
00025   virtual float getTolerance() { return tolerance; } //!< returns #tolerance
00026   virtual void setTimeout(unsigned int delay) { timeout=delay; } //!< sets #timeout
00027   virtual unsigned int getTimeout() { return timeout; } //!< returns #timeout
00028 
00029   //! sets the target to last sent commands, and dirty to false; essentially freezes motion in place
00030   /*! This is very similar to takeSnapshot(), but will do the "right thing" (retain current position) when motion blending is involved.
00031    *  A status event will be generated if/when the joints reach the currently commanded position.
00032    *  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. */
00033   virtual void freezeMotion();
00034 
00035   //! sets the target joint positions to current sensor values
00036   /*! Similar to freezeMotion() when a motion is underway, but only if no other MotionCommands are using neck joints.
00037     *  A status event will @e not be generated unless a motion was already underway.
00038     *  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. */
00039   virtual void takeSnapshot();
00040 
00041   //!@name Speed Control
00042   
00043   //! Sets #maxSpeed to 0 (no maximum)
00044   void noMaxSpeed() { for(unsigned int i=0; i<NumArmJoints; i++) maxSpeed[i]=0; }
00045 
00046   //! Restores #maxSpeed to default settings from Config::Motion_Config
00047   /*! @param x ratio of the max speed to use; so 0.5 would limit motion to half the recommended upper limit */
00048   void defaultMaxSpeed(float x=1);
00049 
00050   //! Sets #maxSpeed for all joints in rad/sec
00051   void setMaxSpeed(float x) { for(unsigned int i=0; i<NumArmJoints; i++) setMaxSpeed(i,x); }
00052 
00053   //! Sets #maxSpeed for join @a i in rad/sec
00054   /*! @param i joint offset relative to ArmOffset (i.e. one of TPROffset_t)
00055    *  @param x maximum radians per second to move */
00056   void setMaxSpeed(unsigned int i, float x) { maxSpeed[i]=x*FrameTime/1000; }
00057 
00058   //! Returns #maxSpeed in rad/sec
00059   /*! @param i joint offset relative to ArmOffset (i.e. one of TPROffset_t)
00060    *  @return the maximum speed of joint @a i in radians per second */
00061   float getMaxSpeed(unsigned int i) { return maxSpeed[i]*1000/FrameTime; }
00062 
00063   //@}
00064   
00065   //!@name Joint Accessors
00066   
00067   //! Sets the weight values for all the arm joints
00068   void setWeight(float w);  
00069   void setWeight(int x, float w);
00070   float armJointValue(unsigned int i);
00071 
00072 
00073   void setJointValue(unsigned int i, float value) {
00074 #ifdef TGT_HAS_ARMS
00075     if(!ensureValidJoint(i)) return;
00076     setWeight(i, 1);
00077     armTargets[i]=clipAngularRange(ArmOffset+i,value);
00078     markDirty();
00079 #endif
00080   }
00081 
00082   //! 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
00083   /*! @param i joint offset relative to ArmOffset (i.e. one of TPROffset_t) */
00084   float getJointValue(unsigned int i) const {
00085     if(ensureValidJoint(i))
00086       return armTargets[i];
00087     else
00088       return 0;
00089   }
00090 
00091   void setJoints(float shoulder, float elbow, float wrist);  //!< Set joint values for a three-link arm
00092   void setJoints(float shoulder, float elbow, float yaw, float pitch, float roll, float gripper); //!< Set joint values for a Chiara-style arm
00093   void setWrist(float pitch, float roll, float gripper);
00094 
00095   //! Move arm to specified point in base frame coordinates; return false if unreachable
00096   bool moveToPoint(float x, float y, float z) { return moveOffsetToPoint(fmat::Column<3>(), fmat::pack(x,y,z)); }
00097   bool moveToPoint(const fmat::Column<3>& tgt) { return moveOffsetToPoint(fmat::Column<3>(), tgt); }
00098   bool moveOffsetToPoint(const fmat::Column<3>& offset, const fmat::Column<3>& tgt);
00099   bool moveOffsetToPointWithOrientation(const fmat::Column<3>& offset, const fmat::Column<3>& tgt, const fmat::Quaternion& ori);
00100   
00101   void setOutputCmd(unsigned int i, const OutputCmd& c) { 
00102 #ifdef TGT_HAS_ARMS
00103     dirty=true; 
00104     completionReported=false; 
00105     armTargets[i-ArmOffset]=c.value;
00106     if(armCmds[i-ArmOffset].weight==0)
00107       armCmds[i-ArmOffset].value = state->outputs[i];
00108     armCmds[i-ArmOffset].weight = c.weight;
00109 #endif
00110   }
00111   
00112 public:
00113   //!@name Inherited:
00114   virtual int updateOutputs(); //!< Updates where the arm is looking
00115   virtual int isDirty() { return (dirty || !completionReported)?3:0; } //!< true if a change has been made since the last updateJointCmds() and we're active
00116   virtual int isAlive(); //!< Alive while target is not reached
00117   virtual void doStart() { MotionCommand::doStart(); markDirty(); } //!< marks this as dirty each time it is added
00118   //@}
00119 
00120 protected:
00121          /*//! checks if target point or direction is actually reachable
00122         bool isReachable(const NEWMAT::ColumnVector& Pobj) {
00123     NEWMAT::ColumnVector poE=armkin.convertLink(0,armkin.get_dof())*Pobj;
00124     const float theta = mathutils::rad2deg(acos(poE(3)/sqrt(poE(1)*poE(1)+poE(2)*poE(2)+poE(3)*poE(3))));
00125     //    cout << "theta: " << theta << " degrees\n";
00126     return theta < 5.0;
00127   }*/
00128 
00129   //! puts x in the range (-pi,pi)
00130   static float normalizeAngle(float x) { return x - static_cast<float>( rint(x/(2*M_PI)) * (2*M_PI) ); }
00131   
00132   //! 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
00133   static float clipAngularRange(unsigned int i, float x) {
00134     float min=outputRanges[i][MinRange];
00135     float max=outputRanges[i][MaxRange];
00136     if(x<min || x>max) {
00137       float mn_dist=std::abs(normalizeAngle(min-x));
00138       float mx_dist=std::abs(normalizeAngle(max-x));
00139       if(mn_dist<mx_dist)
00140         return min;
00141       else
00142         return max;
00143     } else
00144       return x;
00145   }
00146 
00147   //! if completionReported, copies armCmds from MotionManager::getOutputCmd(), then sets dirty to true and completionReported to false
00148   /*! should be called each time a joint value gets modified in case
00149    *  the arm isn't where it's supposed to be, it won't jerk around
00150    * 
00151    *  MotionManager::getOutputCmd() is called instead of
00152    *  WorldState::outputs[] because if this is being called rapidly
00153    *  (i.e. after every sensor reading) using the sensor values will
00154    *  cause problems with very slow acceleration due to sensor lag
00155    *  continually resetting the current position.  Using the last
00156    *  value sent by the MotionManager fixes this.*/
00157   void markDirty();
00158 
00159   //! Makes sure @a i is in the range (0,NumArmJoints).  If it is instead in the range (ArmOffset,ArmOffset+NumArmJoints), output a warning and reset @a i to the obviously intended value.
00160   /*! @param[in] i joint offset relative to either ArmOffset (i.e. one of TPROffset_t) or 0
00161    *  @param[out] i joint offset relative to ArmOffset (i.e. one of TPROffset_t)
00162    *  @return true if the intended joint could be ascertained, false otherwise */
00163   static bool ensureValidJoint(unsigned int& i);
00164 
00165   bool dirty;                          //!< true if a change has been made since last call to updateJointCmds()
00166   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()
00167   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)
00168   bool completionReported;                  //!< true if the most recent movement request has completed
00169   unsigned int targetTimestamp;        //!< time at which the completionReported flag was set
00170   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
00171   float armTargets[NumArmJoints];    //!< stores the target value of each joint
00172   OutputCmd armCmds[NumArmJoints];   //!< stores the last values we sent from updateOutputs
00173   float maxSpeed[NumArmJoints];       //!< initialized from Config::motion_config, but can be overridden by setMaxSpeed(); rad per frame
00174 };
00175 
00176 #endif

Tekkotsu v5.1CVS
Generated Tue Jan 31 04:31:47 2012 by Doxygen 1.6.3