Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
PIDMC.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_PIDMC_h_ 00003 #define INCLUDED_PIDMC_h_ 00004 00005 #include "MotionCommand.h" 00006 #include "MotionManager.h" 00007 #include "OutputPID.h" 00008 #include "Events/EventBase.h" 00009 00010 //! A nice little MotionCommand for manually manipulating the PID values 00011 /*! This will, by default, autoprune after its PID values have been set. 00012 * 00013 * Although this doesn't handle directly sending PID commands to the 00014 * system (the MotionManager::updatePIDs() does that) a little 00015 * documentation on how Tekkotsu ad OPEN-R handle the PIDs might be 00016 * nice. 00017 * 00018 * In Tekkotsu, each of P,I, and D are a single floating point 00019 * number. However, OPEN-R has, in essence, a limited precision 00020 * floating point number. Each value is broken into a gain 00021 * (mantissa) and shift (exponent). The shifts appear to be 4 bit 00022 * values, and are inverted. In other words, x = g/(1<<(0x10-s)), or 00023 * @f$ x = \frac{g}{2^{16-s}} @f$ The gain is probably 6-8 bits of 00024 * resolution. 00025 * 00026 * On the ERS-2xx series, each joint is completely independent. One 00027 * caveat is that the shift value 0x0A gives a warning 00028 * (AGRMSDriver::SetGain() : 0x0A IS USED FOR GAIN SHIFT VALUE.) for 00029 * some unknown reason. 00030 * 00031 * On the ERS-7, all the joints share the last set shift values, so 00032 * a global set of shifts must be enforced. This of course, pretty 00033 * much kills the whole point of having the shifts. 00034 * 00035 * To understand the conversion from Tekkotsu format to the 00036 * OPEN-R format, see MotionManager::updatePIDs(). 00037 * 00038 * A final note: the OPENR::SetJointGain function seems to be 00039 * a rather costly function call. You should probably try to avoid 00040 * setting PIDs at too high a frequency. 00041 */ 00042 class PIDMC : public MotionCommand { 00043 public: 00044 //!Constructor, uses default PIDs and 0 weight for all 00045 PIDMC() : MotionCommand(), dirty(false), completionReported(false) { 00046 setDefaults(0); 00047 dirty=false; 00048 } 00049 //!Constructor, sets general power level of all 00050 PIDMC(float powerlevel, float w=1) : MotionCommand(), dirty(false), completionReported(false) { 00051 setAllPowerLevel(powerlevel,w); 00052 } 00053 //!Constructor, sets general power level of a range of joints, uses default and 0 weight for others, see setRangePowerLevel() 00054 /*! @param low the first joint to apply @a powerlevel to 00055 * @param high one-past last joint to apply @a powerlevel to (i.e. exclusive upper limit) 00056 * @param powerlevel scaling factor for all of the default PID parameters 00057 * @param w MotionManager weight for averaging conflicting commands 00058 * 00059 * Note that if you want to set a single joint @e i, then @a low = @e i, and @a high = @e i + 1 because high is an exclusive upper limit*/ 00060 PIDMC(unsigned int low, unsigned int high, float powerlevel, float w=1) : 00061 MotionCommand(), dirty(false), completionReported(false) { 00062 setRangePowerLevel(PIDJointOffset,low,1.f,0.f); 00063 setRangePowerLevel(low,high,powerlevel,w); 00064 setRangePowerLevel(high,PIDJointOffset+NumPIDJoints,1.f,0.f); 00065 } 00066 00067 //!Destructor 00068 virtual ~PIDMC() {} 00069 00070 //!Inherited 00071 //@{ 00072 virtual int updateOutputs() { 00073 for(unsigned int i=0; i<NumPIDJoints; i++) 00074 motman->setOutput(this,i+PIDJointOffset,PIDs[i]); 00075 int wasDirty=dirty; 00076 dirty=false; 00077 if ( ! completionReported ) { 00078 postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID)); 00079 completionReported = true; 00080 } 00081 return wasDirty; 00082 } 00083 virtual int isDirty() { return dirty; } 00084 virtual int isAlive() { return dirty; } 00085 00086 void setDirty() { dirty = true; } 00087 00088 //! marks this as dirty each time it is added 00089 virtual void doStart() { 00090 MotionCommand::doStart(); 00091 completionReported = false; 00092 dirty=true; 00093 } 00094 //@} 00095 00096 //!Sets the PIDs to the defaults specified in RobotInfo 00097 void setDefaults(float weight=1) { 00098 setAllPowerLevel(1.f,weight); 00099 } 00100 00101 //!Sets the PIDs to a percentage of default for a given joint, and sets weight 00102 void setJointPowerLevel(unsigned int i, float p, float w=1) { 00103 i-=PIDJointOffset; 00104 for(unsigned int j=0;j<3;j++) 00105 PIDs[i].pid[j]=DefaultPIDs[i][j]*p; 00106 PIDs[i].weight=w; 00107 dirty=true; 00108 } 00109 00110 //!Sets the PIDs to a percentage of default for all joints 00111 void setAllPowerLevel(float p, float w=1) { 00112 for(unsigned int i=0; i<NumPIDJoints; i++) { 00113 for(unsigned int j=0;j<3;j++) 00114 PIDs[i].pid[j]=DefaultPIDs[i][j]*p; 00115 PIDs[i].weight=w; 00116 } 00117 dirty=true; 00118 } 00119 00120 //!Sets a range of joints' PIDs to a given power level and weight 00121 /*! @param low the first joint to apply power level @a p to 00122 * @param high one-past last joint to apply power level @a p to (i.e. exclusive upper limit) 00123 * @param p scaling factor for all of the default PID parameters 00124 * @param w MotionManager weight for averaging conflicting commands 00125 * 00126 * Note that if you want to set a single joint @e i with this function (as opposed to setJointPowerLevel() which is designed for that...) 00127 * then you would need to pass @a low = @e i, and @a high = @e i + 1 because high is an exclusive upper limit*/ 00128 void setRangePowerLevel(unsigned int low, unsigned int high, float p, float w=1) { 00129 low-=PIDJointOffset; 00130 high-=PIDJointOffset; 00131 for(unsigned int i=low; i<high; i++) { 00132 for(unsigned int j=0;j<3;j++) 00133 PIDs[i].pid[j]=DefaultPIDs[i][j]*p; 00134 PIDs[i].weight=w; 00135 } 00136 dirty=true; 00137 } 00138 00139 00140 //!Use this to set the PID value and weight 00141 void setPID(unsigned int i, const OutputPID& pid) { 00142 i-=PIDJointOffset; 00143 PIDs[i]=pid; 00144 dirty=true; 00145 } 00146 00147 //!Use this if you want to double check the PID you set 00148 OutputPID& getPID(unsigned int i) { 00149 return PIDs[i-PIDJointOffset]; 00150 } 00151 00152 //!Use this if you want to double check the PID you set 00153 const OutputPID& getPID(unsigned int i) const { 00154 return PIDs[i-PIDJointOffset]; 00155 } 00156 00157 protected: 00158 //! returns true if the output i is a PID joint 00159 static inline bool isPID(unsigned int i) { 00160 return ((int)i>=(int)PIDJointOffset && i<PIDJointOffset+NumPIDJoints); //casting to int just to get rid of compiler warning.. sigh 00161 } 00162 00163 bool dirty; //!< true if there are changes that have not been picked up by Motion 00164 bool completionReported; //!< true if we've reported completion of this motion command 00165 OutputPID PIDs[NumPIDJoints]; //!< the PIDs being requested 00166 }; 00167 00168 /*! @file 00169 * @brief Defines PIDMC, a nice little MotionCommand for manually manipulating the PID values 00170 * @author ejt (Creator) 00171 */ 00172 00173 #endif |
Tekkotsu v5.1CVS |
Generated Mon May 9 04:58:46 2016 by Doxygen 1.6.3 |