Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
LedEngine.hGo to the documentation of this file.00001 #ifndef INCLUDED_LedEngine_h 00002 #define INCLUDED_LedEngine_h 00003 00004 #include "Shared/RobotInfo.h" 00005 #include "Shared/get_time.h" 00006 #include "OutputCmd.h" 00007 #include <math.h> 00008 00009 class MotionCommand; 00010 00011 // LEDBitMask_t and associated constants are defined in RobotInfo.h 00012 00013 //! Provides basic LED effects via subclassing (e.g. LedMC) or embedding (e.g. EmergencyStopMC) 00014 /*! This implements a collection of LED special effects so that the code can be 00015 * reused various places as feedback to to the user. 00016 * 00017 * The basic effects provided are: 00018 * - static brightness (set(), cset(), invert(), clear()) 00019 * - temporary setting (flash(), cflash()) 00020 * - pulsing/blinking (cycle(), ccycle()) 00021 * - numeric display (displayNumber(), displayPercent()) 00022 * 00023 * The 'c' prefix on a function (cset(), cflash(), ccycle()) means it will call clear() before doing its own setting. This is 00024 * a quick way to replace whatever is currently displayed with whatever you are about to display. 00025 * 00026 * A flash() will invert and override the current setting, so that it 00027 * will "reset" after the flash. Flashes change mid-range values to 00028 * extremes to make the flash visible (ie not just (1-current)) Normal 00029 * invert() will do simple inverses (just (1-current)), and doesn't change back automatically. 00030 * 00031 * Cycling ("pulsing") and single-value setting are mutually exclusive; 00032 * one will cut off the other 00033 * 00034 * getSetting() returns value of last set(); 00035 * getValue() returns what's actually being returned to Motion at the moment 00036 * 00037 * There's some nice functions for using the LEDs to display numbers. 00038 * This is handy for when you want to be free of the terminal. 00039 * <img src="NumberLEDs.jpg"> 00040 * 00041 * The ERS-220 and ERS-7 have enough LEDs that they just use a "count 00042 * the lights" style of display instead of this pseudo-arabic display. 00043 * (look close to see that green bar LED at the top of the 210, which 00044 * doesn't show up well in the camera image for some reason. ) 00045 * <img src="NumberLEDs-ERS7.jpg"> 00046 * 00047 * The ERS-7 also has a "mode" which controls how certain face LEDs are 00048 * interpreted. By setting ERS7Info::LEDABModeOffset / 00049 * ERS7Info::LEDABModeMask, you can switch between the modes -- a value 00050 * of 0 is mode "A", and a value of 1 is mode "B". 00051 * <img src="ERS7-LED-Modes.png"> 00052 * 00053 * Things to note for the ERS-7: 00054 * - There are many fewer LEDs than there are holes in the "grill" (the holes you see on the face are not the positions of the LEDs. 00055 * - Each LED covers several holes. 00056 * - Not all holes have LEDs behind them -- some areas of the face panel are always dark. 00057 * - Some LEDs (12 and 13) control two symmetrical physical LEDs. 00058 * - Some LEDs change color based on mode (0-1), some don't change at all (2-11), and some change position and color (12-13) 00059 * - We don't have individual names for all of the LEDs on the panel. Instead you base off of FaceLEDPanelOffset or FaceLEDPanelMask to address the LEDs, e.g., to set the <i>n</i>th led to <i>x</i>: 00060 * @code 00061 * LedEngine::set(FaceLEDPanelMask << n, x) 00062 * @endcode 00063 * or (if using other classes, e.g. PostureEngine) 00064 * @code 00065 * PostureEngine::setOutputCmd(FaceLEDPanelOffset + n, x) 00066 * @endcode 00067 */ 00068 00069 class LedEngine { 00070 public: 00071 //!constructor - don't forget to call if you inherit 00072 LedEngine(); 00073 //!destructor 00074 virtual ~LedEngine() {} 00075 00076 //! call this from a MotionCommand's updateOutputs() - makes calls to MotionManager to update LED values 00077 /*! @param caller pass the "parent" motioncommand's address here (usually will pass 'this') 00078 * @param mask a bitmask of which leds to update (uses weight of 1) */ 00079 int updateLEDs(const MotionCommand* caller,LEDBitMask_t mask=AllLEDMask); 00080 00081 //! call this from a MotionCommand's updateOutputs() - performs the calculations to update LEDs' values 00082 /*! @param cmds on input, used for weight values - on return, holds the resulting OutputCmd's*/ 00083 int updateLEDs(OutputCmd cmds[NumLEDs]); 00084 00085 //! call this from a MotionCommand's updateOutputs() - performs the calculations to update LEDs' values 00086 /*! @param cmds on input, used for weight values - on return, holds the resulting OutputCmd's*/ 00087 int updateLEDFrames(OutputCmd cmds[NumLEDs][NumFrames]); 00088 00089 //! recalculates #nextFlashEnd so we can tell when a flash has completed 00090 void recalcFlashEnd(); 00091 00092 //! returns true if there are changes since the last updateLEDs() 00093 int isDirty(); 00094 00095 //!sets the leds specified by @a leds to the inverse of their current value 00096 void invert(LEDBitMask_t leds); 00097 //!sets the leds specified by @a leds to @a value, clears all the rest 00098 inline void cset(LEDBitMask_t leds, float value) { clear(); set(leds,value); } 00099 //!sets the leds specified by @a leds to @a value 00100 void set(LEDBitMask_t leds, float value); 00101 //!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back. Clears ~leds 00102 void cflash(LEDBitMask_t leds, float value, unsigned int ms); 00103 //!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back. 00104 void flash(LEDBitMask_t leds, float value, unsigned int ms); 00105 //!sets the leds specified by @a leds to either a much higher or much lower value for @a ms milliseconds, then sets back. 00106 void flash(LEDBitMask_t leds, unsigned int ms); 00107 //!causes the leds specified by @a leds to cycle between low and high, clears others. See cycle() for parameter documentation. 00108 inline void ccycle(LEDBitMask_t leds, unsigned int period, float amp, float offset=0, int phase=0) { clear(); cycle(leds,period,amp,offset,phase); } 00109 //!causes the leds specified by @a leds to cycle between low and high; values calculated for cycle will be clipped to [0,1] for more sensible blending of square wave approximations (high amplitude sine wave) 00110 void cycle(LEDBitMask_t leds, unsigned int period, float amp, float offset=0, int phase=0); 00111 //!sets all leds to 0. 00112 void clear(); 00113 00114 //!adds @a ms to all flash times (may resurrect previously completed flashes) 00115 void extendFlash(unsigned int ms); 00116 00117 //!returns the current setting of the LED specified by @a led_id (the value you passed in set()) 00118 float getSetting(LEDOffset_t led_id) { 00119 #ifndef TGT_HAS_LEDS 00120 (void)led_id; // avoid unused argument warning 00121 return 0; 00122 #else 00123 return infos[led_id-LEDOffset].value; 00124 #endif 00125 } 00126 //!returns the current value of the LED specified by @a led_id (the value being expressed - may change if cycling for instance) 00127 float getValue(LEDOffset_t led_id,unsigned int planahead=0) { 00128 #ifndef TGT_HAS_LEDS 00129 (void)led_id; (void)planahead; // avoid unused argument warnings 00130 return 0; 00131 #else 00132 return calcValue(led_id-LEDOffset,get_time()+planahead); 00133 #endif 00134 } 00135 00136 #ifdef TGT_HAS_LED_PANEL 00137 //!holds a series of bit masks for the onedigit style of numerical display (-9:9 and '.') 00138 /*!the hope is that these actually resemble the shapes of the numbers so people can 00139 * recognize them more easily - without counting or converting base 2 in their heads. */ 00140 static const LEDBitMask_t defaultMimicNumMasks[11]; 00141 static const LEDBitMask_t ERS220numMasks[11]; //!< bit masks for the ondigit style of numberical display - just count the LEDs on the head 00142 static const LEDBitMask_t ERS7numMasks[11]; //!< bit masks for the ondigit style of numberical display - just count the LEDs on the head 00143 #endif 00144 static const LEDBitMask_t defaultCountNumMasks[11]; //!< bit masks for the ondigit style of numberical display - just count the LEDs on the head 00145 //!Use these to specify a style for displaying numbers using displayNumber() 00146 enum numStyle_t { 00147 onedigit, //!< can display a number -9 thru 9, using the current robot model's numMask. For negative numbers, blinks the top bar - fast if it's supposed to be on, slow if it would otherwise be off 00148 twodigit //!< can display a number -99 thru 99, using setOneOfTwo(). For negative numbers, sets the top bar to 1 (off otherwise). 00149 }; 00150 //!Use these to specify a style for displaying a percentage value [0-1] using displayPercent() 00151 enum percentStyle_t { 00152 major, //!< shows overall value 00153 minor, //!< shows value within major tick 00154 none //!< if you want to leave blank 00155 }; 00156 00157 //!Allows convenient display of numerical information to the LEDs on the face. 00158 /*!If overflow occurs, the face LEDs are set to flash on and off 3 every 333 milliseconds*/ 00159 void displayNumber(int x, numStyle_t style); 00160 //!Allows convenient display of percentage information to the LEDs on the face. 00161 /*!Besides allowing a two-digit display, the 'edge' bar for each type is blinked to 00162 * denote how full it is. So you can get up to a two-digit, base 5 display, with an 00163 * extra digit of estimated value. 00164 * 00165 * If overflow (>1) occurs, sets everything to .75. <br> 00166 * If underflow (<0) occurs, sets everything to .25. 00167 * 00168 * The left and right columns are combined with an OR operation. (they overlap on the top bar) 00169 * Left and right designations are <em>dog centric!</em> */ 00170 void displayPercent(float x, percentStyle_t left_style, percentStyle_t right_style); 00171 00172 protected: 00173 //!Performs the 'invert' calculation based on current value (returns 1-value) 00174 static float calcInvert(float value) { 00175 return 1-value; 00176 } 00177 //!Performs the 'flash' calculation based on current value (uses calcInvert() if value upper or lower third, 0 or 1 otherwise) 00178 static float calcFlash(float value) { 00179 if(value>.33333 && value<.66666) 00180 return (value<.5 ? 1 : 0); 00181 else 00182 return calcInvert(value); 00183 } 00184 //!Performs the 'cycle' calculation based on desired period, amplituted, amplitude offset, and time since start. See cycle() 00185 static float calcCycle(unsigned int period, float amp, float offset, unsigned int t) { 00186 // cout << period << ',' << amp << ',' << offset << ',' << time << " -> " << x; 00187 float x=float(cos(t*2*M_PI/period))*(-amp/2)+.5f+offset; 00188 if(x<0) 00189 return 0; 00190 if(x>1) 00191 return 1; 00192 return x; 00193 } 00194 //!Calculates the current value of led @a i for current time t 00195 float calcValue(unsigned int i, unsigned int t) { 00196 if(t<infos[i].flashtime) 00197 return infos[i].flashvalue; 00198 else if(infos[i].isCycling) 00199 return calcCycle(infos[i].period,infos[i].amp,infos[i].offset,t-infos[i].starttime); 00200 else 00201 return infos[i].value; 00202 } 00203 //!used by displayNumber() to determine settings of LEDs when using numStyle_t::twodigit 00204 void setOneOfTwo(unsigned int x, unsigned int low, unsigned int mid, unsigned int high); 00205 //!used by displayPercent() to determine settings of LEDs 00206 void setColumn(float x, unsigned int low, unsigned int mid, unsigned int high, unsigned int top); 00207 00208 //!Holds all the information needed by each of the LEDs 00209 struct LEDInfo { 00210 float value; //!< the current value being expressed 00211 float amp; //!< the amplitude of the cycle (if cycling) 00212 unsigned int period; //!< the period of the cycle (if cycling) 00213 unsigned int starttime; //!< the start time of the cycle (if cycling) 00214 float offset; //!< the phase shift from normal of the cycle (if cycling) 00215 float flashvalue; //!< the value being 'flashed' (only valid if current time is less than flashtime 00216 unsigned int flashtime; //!< the time the 'flash' should retire 00217 bool isCycling; //!< true if in cycle mode 00218 }; 00219 00220 LEDInfo infos[NumLEDs]; //!< the information regarding each of the LEDs 00221 bool dirty; //!< true if changes since last updateLEDs: either at least one LED is cycling or a flash has begun/ended 00222 unsigned int numCycling;//!< the number of LEDs currently cycling (if non-zero, always dirty) 00223 unsigned int nextFlashEnd; //!< the soonest time a flash will end (and we'll become dirty) 00224 }; 00225 00226 /*! @file 00227 * @brief Describes LedEngine, which provides basic LED effects to anything that inherits or instantiates it 00228 * @author ejt (Creator) 00229 * 00230 * $Author: ejt $ 00231 * $Name: tekkotsu-4_0 $ 00232 * $Revision: 1.30 $ 00233 * $State: Exp $ 00234 * $Date: 2007/11/18 06:47:03 $ 00235 */ 00236 00237 #endif |
Tekkotsu v4.0 |
Generated Thu Nov 22 00:54:53 2007 by Doxygen 1.5.4 |