Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
MotionCommand.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_MotionCommand_h 00003 #define INCLUDED_MotionCommand_h 00004 00005 #include "Shared/RobotInfo.h" 00006 #include "MotionManagerMsg.h" 00007 #include "OutputCmd.h" 00008 #include <stddef.h> 00009 00010 class EventTranslator; 00011 class EventBase; 00012 00013 //! The abstract base class for motions, provides common interface. All motions should inherit from this 00014 /*! For instructions on how to create: 00015 * - <b>a new subclass</b> of MotionCommand, read on. Also see the step-by-step 00016 * <a href="../FirstMotionCommand.html">guide</a> 00017 * - <b>an instantiation</b> of a MotionCommand subclass, see MotionManager 00018 * 00019 * To create a new type of motion, you'll want to subclass this. You 00020 * don't need to do anything fancy, but just be sure to override the 3 00021 * abstract functions. 00022 * 00023 * When an output is set to a value, that output is held at that value 00024 * until it is set to a new value, even if the MotionCommand that set 00025 * it is pruned or stops using the output. Outputs never "reset" to 0 00026 * or some other relatively arbitrary base value if all the 00027 * MotionCommands are removed. 00028 * 00029 * However, PID values will reset to the default values if pruned or 00030 * not set since these values <i>do</i> have a base value which you 00031 * will want to use 99% of the time. 00032 * 00033 * Be aware that there is a delay between when you set a joint to a 00034 * value and that actually is taken into account by the system - it's 00035 * on the order of FrameTime*NumFrames (currently 8*4 = 32 ms, so 00036 * worse case 2*8*4 = 64 ms) This is because the commands are double 00037 * buffered. PIDs, on the other hand, seem to take effect more 00038 * quickly. This un-synchronization can sometimes cause a bit of 00039 * jerkiness (mainly on startup, where there's a large difference 00040 * between desired and target values.) 00041 * 00042 * Here is the cycle of calls made by MotionManager to your command: 00043 * -# shouldPrune() (by default, this will return !isAlive() iff #autoprune==true) 00044 * -# updateJointCmds() (assuming the MC wasn't pruned after the previous step) 00045 * 00046 * So, if you want to hold a joint at a value, each time your 00047 * updateJointCmds() function is called, you should tell the 00048 * MotionManager to keep the joint there (using one of 00049 * MotionManager::setOutput()'s). If you do not set a joint after a 00050 * call to updateJointCmds, the MotionManager will assume you are no 00051 * longer using that joint and a lower priority MotionCommand may 00052 * inherit it. 00053 * 00054 * MotionCommands which generate events should use the inherited 00055 * postEvent() instead of trying to access a global ::erouter - the 00056 * inherited version will properly handle sending the events 00057 * regardless of the current context, but trying to access a 00058 * non-shared global like ::erouter could cause problems. 00059 * 00060 * @warning <b>Be careful what you call in MotionManager</b> \n 00061 * Some functions are marked MotionCommand-safe - this is another 00062 * issue due to our "fake" fork. In short, when a function is called 00063 * on a MotionCommand, it uses the context of whatever process created 00064 * it, not the process that actually made the function call. Thus, 00065 * when Motion calls updateOutputs(), calls that the MotionCommand 00066 * makes are indistinguishable from concurrent calls from Main. This 00067 * can cause deadlock if a function is called which locks the 00068 * MotionManager. To get around this, we need to pass the 'this' 00069 * parameter on functions that require a lock, namely 00070 * MotionManager::setOutputs(). This allows the MotionManager to 00071 * figure out that it's the same MotionCommand it previously called 00072 * updateOutputs() on, and thus avoid trying to lock itself again. 00073 * 00074 * @warning <b>Don't store pointers in motion commands!</b> \n 00075 * Since motion commands are in shared memory, and these shared memory 00076 * regions can have different base pointers in each process, pointers 00077 * will only be valid in the process from which they were assigned. 00078 * In other processes, that address may point to something else, 00079 * especially if it was pointing outside of the shared memory 00080 * regions.\n 00081 * There are convoluted ways of getting around this. If needed, 00082 * MotionManager could be modified to hand out shared memory regions 00083 * upon request. Let's try to avoid this for now. Keep 00084 * MotionCommands simple, without dynamic memory. Do more complicated 00085 * stuff with behaviors, which only have to worry about running in Main. 00086 */ 00087 class MotionCommand : public MotionManagerMsg { 00088 //!@nosubgrouping 00089 public: 00090 00091 // ***************** 00092 //! @name *** ABSTRACT: *** (must be defined by subclasses) 00093 // ***************** 00094 00095 //! is called once per update cycle, can do any processing you need to change your priorities or set output commands on the MotionManager 00096 /*! @return zero if no changes were made, non-zero otherwise 00097 * @see RobotInfo::NumFrames @see RobotInfo::FrameTime */ 00098 virtual int updateOutputs()=0; 00099 00100 //! not used by MotionManager at the moment, but could be used to reduce recomputation, and you may find it useful 00101 /*! @return zero if none of the commands have changed since last 00102 * getJointCmd(), else non-zero */ 00103 virtual int isDirty()=0; 00104 00105 //! used to prune "dead" motions from the MotionManager 00106 /*! note that a motion could be "paused" or inactive and therefore 00107 * not dirty, but still alive, biding its time to "strike" ;) 00108 * @return zero if the motion is still processing, non-zero otherwise */ 00109 virtual int isAlive()=0; 00110 00111 //@} 00112 00113 00114 // ****************** 00115 //! @name *** INHERITED: *** 00116 // ****************** 00117 00118 //! Constructor: Defaults to kStdPriority and autoprune==true 00119 MotionCommand() : MotionManagerMsg(), queue(NULL), autoprune(true), started(false) {} 00120 //! Destructor 00121 virtual ~MotionCommand() {} 00122 00123 //! called after this is added to MotionManager 00124 virtual void DoStart() { started=true; } 00125 00126 //! called after this is removed from MotionManager 00127 virtual void DoStop() { started=false; clearID(); } 00128 00129 //! returns true if the MotionCommand is currently running (although it may be overridden by a higher priority MotionCommand) 00130 virtual bool isActive() const { return started; } 00131 00132 /*! @return current setting of autopruning - used to remove motion from groups when !isAlive() */ 00133 virtual bool getAutoPrune() { return autoprune; } 00134 00135 /*! @param ap bool representing requested autopruning setting */ 00136 virtual void setAutoPrune(bool ap) { autoprune=ap; } 00137 00138 //! whether this motion should be removed from its motion group automatically ( MotionCommand::autoprune && !isAlive()) 00139 /*! @return (MotionCommand::autoprune && !isAlive())*/ 00140 virtual bool shouldPrune() { return (autoprune && !isAlive()); } 00141 00142 //! only called from MMCombo during process setup, allows MotionCommands to send events 00143 void setTranslator(EventTranslator * q) { queue=q; } 00144 00145 protected: 00146 //! this utility function will probably be of use to a lot of MotionCommand's 00147 /*! Does a weighted average of a and b, favoring b by x percent (so x==0 results in a, x==1 results in b) 00148 * @param a first value 00149 * @param b second value 00150 * @param x weight of second value as opposed to first 00151 * @return @f$a*(1.0-x)+b*x@f$ 00152 * @todo - replace with a more fancy spline based thing? */ 00153 static inline double interpolate(double a, double b, double x) { 00154 return a*(1.0-x)+b*x; 00155 } 00156 //! this utility function will probably be of use to a lot of MotionCommand's 00157 /*! Does a weighted average of a and b, favoring b by x percent (so x==0 results in a, x==1 results in b) 00158 * @param a first value 00159 * @param b second value 00160 * @param x weight of second value as opposed to first 00161 * @return @f$a*(1.0-x)+b*x@f$ 00162 * @todo - replace with a more fancy spline based thing? */ 00163 static inline float interpolate(float a, float b, float x) { 00164 return a*(1.0-x)+b*x; 00165 } 00166 //! this utility function will probably be of use to a lot of MotionCommand's, see interpolate(double a,double b,double r) 00167 /*! interpolates both value and weights of JointCmd's 00168 * @param a first joint cmd 00169 * @param b second joint cmd 00170 * @param x weight to favor b's value and weight 00171 * @param r joint cmd to store the result */ 00172 static inline void interpolate(const OutputCmd& a, const OutputCmd& b, float x, OutputCmd& r) { 00173 r.set(interpolate(a.value,b.value,x),interpolate(a.weight,b.weight,x)); 00174 } 00175 //@} 00176 00177 //! calls EventTranslator::trapEvent() directly (avoids needing erouter, which is a non-shared global, causes problems with context, grr, silly OS) 00178 void postEvent(const EventBase& event); 00179 00180 EventTranslator * queue; //!< send events using this, instead of posting to the erouter 00181 00182 int autoprune; //!< default true, autoprune setting, if this is true and isAlive() returns false, MotionManager will attempt to remove the MC automatically 00183 bool started; //!< true if the MotionCommand is currently running (although it may be overridden by a higher priority MotionCommand) 00184 00185 private: 00186 MotionCommand(const MotionCommand&); //!< don't call 00187 MotionCommand& operator=(const MotionCommand&); //!< don't call 00188 }; 00189 00190 /*! @file 00191 * @brief Defines the MotionCommand class, used for creating motions of arbitrary complexity 00192 * @author ejt (Creator) 00193 * 00194 * $Author: ejt $ 00195 * $Name: tekkotsu-2_4_1 $ 00196 * $Revision: 1.19 $ 00197 * $State: Exp $ 00198 * $Date: 2005/08/07 04:11:03 $ 00199 */ 00200 00201 #endif 00202 |
Tekkotsu v2.4.1 |
Generated Tue Aug 16 16:32:47 2005 by Doxygen 1.4.4 |