Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EmergencyStopMC.cc

Go to the documentation of this file.
00001 #include "EmergencyStopMC.h"
00002 #include "Shared/WorldState.h"
00003 #include "Shared/get_time.h"
00004 #include "Motion/MotionManager.h"
00005 #include "Sound/SoundManager.h"
00006 #include "Shared/Config.h"
00007 #include "Events/EventRouter.h"
00008 #include "Shared/ERS210Info.h"
00009 #include "Shared/ERS220Info.h"
00010 #include "Shared/ERS7Info.h"
00011 #include "Wireless/Wireless.h"
00012 
00013 EmergencyStopMC::EmergencyStopMC()
00014   : PostureMC(), paused(false), stilldown(false), active(true), period(2000),
00015     timeoflastbtn(0), timeofthisbtn(0), timeoflastfreeze(0), timeoflastrelease(0), duration(600),
00016     pidcutoff(0.2), ledengine()
00017 {
00018   for(unsigned int i=0; i<NumPIDJoints; i++)
00019     piddutyavgs[i]=0;
00020   if(state->robotDesign&WorldState::ERS210Mask) {
00021     ledengine.cycle(ERS210Info::TlRedLEDMask,period,1,0,period/2);
00022     ledengine.cycle(ERS210Info::TlBluLEDMask,period,1);
00023   } else if(state->robotDesign&WorldState::ERS220Mask) {
00024     ledengine.cycle(ERS220Info::TailCenterLEDMask, period, 2.0f, -.5f, (int)(period * 0/5.5));
00025     ledengine.cycle(ERS220Info::TailLeftLEDMask|ERS220Info::TailRightLEDMask,   period, 2.0f, -.5f, (int)(period * 1/5.5));
00026     ledengine.cycle(ERS220Info::BackLeft3LEDMask|ERS220Info::BackRight1LEDMask, period, 2.0f, -.5f, (int)(period * 2/5.5));
00027     ledengine.cycle(ERS220Info::BackLeft2LEDMask|ERS220Info::BackRight2LEDMask, period, 2.0f, -.5f, (int)(period * 3/5.5));
00028     ledengine.cycle(ERS220Info::BackLeft1LEDMask|ERS220Info::BackRight3LEDMask, period, 2.0f, -.5f, (int)(period * 4/5.5));
00029   } else if(state->robotDesign&WorldState::ERS7Mask) {
00030     ledengine.cycle(1<<(ERS7Info::MdBackColorLEDOffset-LEDOffset),2*period/3,.15,.15/2-.5,0);
00031   } else {
00032     serr->printf("Emergency Stop: unknown model\n");
00033     ledengine.cycle(1<<(NumLEDs-1),period,1,0,period/2);
00034     ledengine.cycle(1<<(NumLEDs-2),period,1);
00035   }
00036   defaultMaxSpeed(.15);
00037   takeSnapshot();
00038 }
00039 
00040 
00041 int EmergencyStopMC::updateOutputs() {
00042   if(trigger()) {
00043     if(!stilldown) {
00044       stilldown=true;
00045       timeoflastbtn=timeofthisbtn;
00046       timeofthisbtn=get_time();
00047       //      cout << "Press " << timeofthisbtn << ' ' << timeoflastbtn << endl;
00048     }
00049     //    cout << "Down" << endl;
00050   } else if(stilldown) {
00051     //    cout << "Release " << get_time() << endl;
00052     stilldown=false;
00053     if((get_time()-timeoflastbtn)<duration)
00054       setStopped(!paused);
00055   }
00056   unsigned int curt=get_time();
00057   dirty=dirty || (curt<timeoflastrelease);
00058   if(!paused) {
00059     if(!dirty)
00060       return 0;
00061     if(curt>=timeoflastrelease) {
00062       for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00063         motman->setOutput(this,i,0.f); //blank out LEDs to avoid residual background display
00064       dirty=false;
00065       return 0;
00066     }
00067     float w = (curt>=timeoflastrelease) ? 0 : (static_cast<float>(timeoflastrelease-curt)/FADE_OUT_TIME);
00068     for(unsigned int i=0; i<NumOutputs; i++)
00069       cmds[i].weight=w;
00070   } else {
00071     //immediately following a pause, just hold current position at first to prevent twitching if we were in motion
00072     if(curt-timeoflastfreeze>FrameTime*NumFrames*5) { 
00073       //once joints have come to rest, respond to outside forces
00074       for(unsigned int i=0; i<NumPIDJoints; i++) {
00075         //exponential average of duty cycles to filter out noise
00076         piddutyavgs[i]=piddutyavgs[i]*.9f+state->pidduties[i]*.1f;
00077         //reset if there's something significantly out of place (perhaps we're being overridden)
00078         if(fabsf(state->outputs[PIDJointOffset+i]-cmds[PIDJointOffset+i].value)>.15f) {
00079           //if(PIDJointOffset+i==LFrLegOffset+RotatorOffset)
00080           //cout << "resetting from " << cmds[PIDJointOffset+i].value << " to " << state->outputs[PIDJointOffset+i] << endl;
00081           curPositions[PIDJointOffset+i]=cmds[PIDJointOffset+i].value=state->outputs[PIDJointOffset+i];
00082           dirty=true;
00083           targetReached=false;
00084         }
00085         //give if there's a force...
00086         if(fabsf(piddutyavgs[i])>pidcutoff) {
00087           cmds[PIDJointOffset+i].value-=piddutyavgs[PIDJointOffset+i]; //move in the direction of the force
00088           dirty=true;
00089           targetReached=false;
00090         }
00091       }
00092     }
00093   }
00094   ledengine.updateLEDs(&cmds[LEDOffset]);
00095   if(state->robotDesign&WorldState::ERS7Mask) {
00096     //a special Battlestar Galactica inspired effect for the ERS-7
00097     static float acts[5];
00098     static bool wasPaused=false;
00099     if(!wasPaused && paused) {
00100       for(int i=0; i<5; i++)
00101         acts[i]=0;
00102       wasPaused=paused;
00103     }
00104     float t=curt;
00105     t/=period;
00106     t=(((int)t)&1)?(int)t+1-t:(t-(int)t);
00107     t*=8;
00108     const float invsigma=-6;
00109     const float gamma=.83;
00110     const float amp=.5;
00111     float imp[5];
00112     // w is used to fade out LEDs when releasing estop
00113     float w = (paused || curt>=timeoflastrelease) ? 1 : (static_cast<float>(timeoflastrelease-curt)/FADE_OUT_TIME);
00114     for(int i=0; i<5; i++) {
00115       imp[i]=exp(invsigma*(t-i-2)*(t-i-2))*w;
00116       acts[i]+=amp*imp[i];
00117       acts[i]*=gamma*w;
00118     }
00119     cmds[ERS7Info::FaceLEDPanelOffset+ 6].value=acts[0]/2+imp[0];
00120     cmds[ERS7Info::FaceLEDPanelOffset+ 8].value=acts[1]/2+imp[1];
00121     cmds[ERS7Info::FaceLEDPanelOffset+10].value=acts[2]/2+imp[2];
00122     cmds[ERS7Info::FaceLEDPanelOffset+ 9].value=acts[3]/2+imp[3];
00123     cmds[ERS7Info::FaceLEDPanelOffset+ 7].value=acts[4]/2+imp[4];
00124   }
00125   int changed=PostureMC::updateOutputs();
00126   dirty=(curt<timeoflastrelease);
00127   return changed;
00128 }
00129 
00130 void EmergencyStopMC::setActive(bool a) {
00131   if(paused) {
00132     if(!a && active)
00133       releaseJoints();
00134     else if(a && !active)
00135       freezeJoints();
00136   }
00137   active=a;
00138 }
00139 
00140 
00141 void EmergencyStopMC::setStopped(bool p, bool sound) {
00142   if(p!=paused) {
00143     paused=p;
00144     if(active) {
00145       if(paused) {
00146         freezeJoints();
00147         if(sound)
00148           sndman->playFile(config->motion.estop_on_snd);
00149         cout << "*** PAUSED ***" << endl;
00150       } else {
00151         releaseJoints();
00152         if(sound)
00153           sndman->playFile(config->motion.estop_off_snd);
00154         cout << "*** UNPAUSED ***" << endl;
00155       }
00156     }
00157   }
00158 }
00159 
00160 void EmergencyStopMC::freezeJoints() {
00161   dirty=true;
00162   targetReached=false;
00163   for(unsigned int i=0; i<NumOutputs; i++) {
00164     OutputCmd c=motman->getOutputCmd(i);
00165     curPositions[i]=cmds[i].value = (c.weight==0) ? state->outputs[i] : c.value;
00166   }
00167   for(unsigned int i=0; i<NumPIDJoints; i++)
00168     piddutyavgs[i]=0; //or: state->pidduties[i];
00169   for(unsigned int i=0; i<LEDOffset; i++)
00170     cmds[i].weight=1;
00171   for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00172     cmds[i].unset(); // let other commands' LEDs "show through"
00173   for(unsigned int i=LEDOffset+NumLEDs; i<NumOutputs; i++)
00174     cmds[i].weight=1;
00175   if(state->robotDesign&WorldState::ERS210Mask) {
00176     cmds[ERS210Info::TlRedLEDOffset].set(0,.5);
00177     cmds[ERS210Info::TlBluLEDOffset].set(0,.5);
00178   } else if(state->robotDesign&WorldState::ERS220Mask) {
00179     for(unsigned int i = 0; i < NumLEDs; i++)
00180       if((ERS220Info::TailLEDMask|ERS220Info::BackLEDMask) & (1 << i))
00181         cmds[LEDOffset + i].set(0, .5);
00182   } else if(state->robotDesign&WorldState::ERS7Mask) {
00183     cmds[ERS7Info::MdBackColorLEDOffset].set(0,.5);
00184     for(int i=6; i<6+5; i++)
00185       cmds[ERS7Info::FaceLEDPanelOffset+i].set(0,0.5);
00186   } else {
00187     cmds[LEDOffset+NumLEDs-1].set(0,.5);
00188     cmds[LEDOffset+NumLEDs-2].set(0,.5);
00189   }
00190   postEvent(EventBase(EventBase::estopEGID,getID(),EventBase::activateETID,0));
00191   timeoflastfreeze=get_time();
00192 }
00193 
00194 void EmergencyStopMC::releaseJoints() {
00195   dirty=true;
00196   targetReached=false;
00197   unsigned int curt=get_time();
00198   timeoflastrelease=curt+FADE_OUT_TIME;
00199   postEvent(EventBase(EventBase::estopEGID,getID(),EventBase::deactivateETID,curt-timeoflastfreeze));
00200 }
00201 
00202 bool EmergencyStopMC::trigger() {
00203   WorldState * st=WorldState::getCurrent(); // this is need because trigger is a static, so it doesn't access the Motion
00204   if(st->robotDesign&WorldState::ERS210Mask)
00205     return st->button_times[ERS210Info::BackButOffset];
00206   if(st->robotDesign&WorldState::ERS220Mask)
00207     return st->button_times[ERS220Info::BackButOffset];
00208   if(st->robotDesign&WorldState::ERS7Mask)
00209     return st->button_times[ERS7Info::FrontBackButOffset]+st->button_times[ERS7Info::MiddleBackButOffset]+st->button_times[ERS7Info::RearBackButOffset];
00210   serr->printf("EmergencyStopMC: unsupported model!\n");
00211   return false;
00212 }
00213 
00214 /*! @file
00215  * @brief Implements EmergencyStopMC, overrides all joints, allows modelling, blinks tail
00216  * @author ejt (Creator)
00217  *
00218  * $Author: ejt $
00219  * $Name: tekkotsu-3_0 $
00220  * $Revision: 1.30 $
00221  * $State: Exp $
00222  * $Date: 2006/09/18 18:08:01 $
00223  */
00224 

Tekkotsu v3.0
Generated Wed Oct 4 00:03:43 2006 by Doxygen 1.4.7