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