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
00048 }
00049
00050 } else if(stilldown) {
00051
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);
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
00072 if(curt-timeoflastfreeze>FrameTime*NumFrames*5) {
00073
00074 for(unsigned int i=0; i<NumPIDJoints; i++) {
00075
00076 piddutyavgs[i]=piddutyavgs[i]*.9f+state->pidduties[i]*.1f;
00077
00078 if(fabsf(state->outputs[PIDJointOffset+i]-cmds[PIDJointOffset+i].value)>.15f) {
00079
00080
00081 curPositions[PIDJointOffset+i]=cmds[PIDJointOffset+i].value=state->outputs[PIDJointOffset+i];
00082 dirty=true;
00083 targetReached=false;
00084 }
00085
00086 if(fabsf(piddutyavgs[i])>pidcutoff) {
00087 cmds[PIDJointOffset+i].value-=piddutyavgs[PIDJointOffset+i];
00088 dirty=true;
00089 targetReached=false;
00090 }
00091 }
00092 }
00093 }
00094 ledengine.updateLEDs(&cmds[LEDOffset]);
00095 if(state->robotDesign&WorldState::ERS7Mask) {
00096
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
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;
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();
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();
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
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224