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/RobotInfo.h"
00009 #include "Shared/ERS210Info.h"
00010 #include "Shared/ERS220Info.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.2f)
00017 #ifdef TGT_HAS_LEDS
00018 , ledengine()
00019 #endif
00020 {
00021 for(unsigned int i=0; i<NumPIDJoints; i++)
00022 piddutyavgs[i]=0;
00023 #if defined(TGT_ERS2xx) || defined(TGT_ERS210) || defined(TGT_ERS220)
00024
00025
00026 if(RobotName == ERS210Info::TargetName) {
00027 int red=capabilities.getOutputOffset(ERS210Info::outputNames[ERS210Info::TlRedLEDOffset]) - LEDOffset;
00028 int blue=capabilities.getOutputOffset(ERS210Info::outputNames[ERS210Info::TlBluLEDOffset]) - LEDOffset;
00029 ledengine.cycle((1<<red),period,1,0,period/2);
00030 ledengine.cycle((1<<blue),period,1);
00031 } else if(RobotName == ERS220Info::TargetName) {
00032 int tl=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::TailLeftLEDOffset]) - LEDOffset;
00033 int tc=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::TailCenterLEDOffset]) - LEDOffset;
00034 int tr=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::TailRightLEDOffset]) - LEDOffset;
00035 int bl1=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackLeft1LEDOffset]) - LEDOffset;
00036 int bl2=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackLeft2LEDOffset]) - LEDOffset;
00037 int bl3=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackLeft3LEDOffset]) - LEDOffset;
00038 int br1=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackRight1LEDOffset]) - LEDOffset;
00039 int br2=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackRight2LEDOffset]) - LEDOffset;
00040 int br3=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackRight3LEDOffset]) - LEDOffset;
00041 ledengine.cycle((1<<tc), period, 2.0f, -.5f, (int)(period * 0/5.5));
00042 ledengine.cycle((1<<tl)|(1<<tr), period, 2.0f, -.5f, (int)(period * 1/5.5));
00043 ledengine.cycle((1<<bl3)|(1<<br1), period, 2.0f, -.5f, (int)(period * 2/5.5));
00044 ledengine.cycle((1<<bl2)|(1<<br2), period, 2.0f, -.5f, (int)(period * 3/5.5));
00045 ledengine.cycle((1<<bl1)|(1<<br3), period, 2.0f, -.5f, (int)(period * 4/5.5));
00046 }
00047 #elif defined(TGT_ERS7)
00048 ledengine.cycle(MdBackColorLEDMask,2*period/3,.15f,.15f/2-.5f,0);
00049 #elif defined(TGT_IS_QWERK)
00050 ledengine.cycle(1<<8,period,1,0,period/2);
00051 ledengine.cycle(1<<9,period,1);
00052 #elif defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00053 int red = RobotInfo::PowerRedLEDOffset - LEDOffset;
00054 int green = RobotInfo::PowerGreenLEDOffset - LEDOffset;
00055 ledengine.cycle(1<<red,period/2,1);
00056 ledengine.cycle(1<<green,period/2,1,0,period/4);
00057 #elif defined(TGT_CHIARA)
00058 ledengine.cycle(ChiaraInfo::RedLEDOffset, 2*period/3, 5.0f);
00059 #elif defined(TGT_CHIARA2)
00060 ledengine.cycle(Chiara2Info::AllLEDMask, 2*period/3, 5.0f);
00061 #elif defined(TGT_HANDEYE) || defined(TGT_HANDEYEZ)
00062 #elif defined(TGT_HAS_LEDS)
00063 # warning EmergencyStop using generic LED special effects (last two LEDs will alternate)
00064 ledengine.cycle(1<<(NumLEDs-1),period,1,0,period/2);
00065 # if TGT_HAS_LEDS>1
00066 ledengine.cycle(1<<(NumLEDs-2),period,1);
00067 # endif
00068 #endif
00069 defaultMaxSpeed(.15f);
00070 takeSnapshot();
00071 }
00072
00073
00074 int EmergencyStopMC::updateOutputs() {
00075 #if defined(TGT_IS_CREATE) || defined(TGT_IS_KOBUKI) || defined(TGT_IS_CREATE2)
00076 if(trigger()) {
00077 setStopped(true);
00078 }
00079 #else
00080 if(trigger()) {
00081 if(!stilldown) {
00082 stilldown=true;
00083 timeoflastbtn=timeofthisbtn;
00084 timeofthisbtn=get_time();
00085
00086 }
00087
00088 } else if(stilldown) {
00089
00090 stilldown=false;
00091 if((get_time()-timeoflastbtn)<duration)
00092 setStopped(!paused);
00093 }
00094 #endif
00095 unsigned int curt=get_time();
00096 dirty=dirty || (curt<timeoflastrelease);
00097 if(!paused) {
00098 if(!dirty)
00099 return 0;
00100 if(curt>=timeoflastrelease) {
00101 #ifdef TGT_HAS_LEDS
00102 for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00103 motman->setOutput(this,i,0.f);
00104 #endif
00105 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00106 motman->setOutput(this,RobotInfo::PowerRedLEDOffset,OutputCmd(0.0f, 0.5f));
00107 motman->setOutput(this,RobotInfo::PowerGreenLEDOffset,OutputCmd(0.5f, 0.5f));
00108 #endif
00109 dirty=false;
00110 return 0;
00111 }
00112 float w = (curt>=timeoflastrelease) ? 0 : (static_cast<float>(timeoflastrelease-curt)/FADE_OUT_TIME);
00113 for(unsigned int i=0; i<NumOutputs; i++)
00114 cmds[i].weight=w;
00115 } else {
00116
00117 if(curt-timeoflastfreeze>FrameTime*NumFrames*5) {
00118
00119 for(unsigned int i=0; i<NumPIDJoints; i++) {
00120
00121 piddutyavgs[i]=piddutyavgs[i]*.9f+state->pidduties[i]*.1f;
00122
00123 if(fabsf(state->outputs[PIDJointOffset+i]-cmds[PIDJointOffset+i].value)>.15f) {
00124
00125
00126 curPositions[PIDJointOffset+i]=cmds[PIDJointOffset+i].value=state->outputs[PIDJointOffset+i];
00127 dirty=true;
00128 targetReached=false;
00129 }
00130
00131 if(fabsf(piddutyavgs[i])>pidcutoff) {
00132 cmds[PIDJointOffset+i].value-=piddutyavgs[PIDJointOffset+i];
00133 dirty=true;
00134 targetReached=false;
00135 }
00136 }
00137 }
00138 }
00139 #ifdef TGT_HAS_LEDS
00140 ledengine.updateLEDs(&cmds[LEDOffset]);
00141 #endif
00142 #if defined(TGT_ERS7)
00143
00144 static float acts[5];
00145 static bool wasPaused=false;
00146 if(!wasPaused && paused) {
00147 for(int i=0; i<5; i++)
00148 acts[i]=0;
00149 wasPaused=paused;
00150 }
00151 float t=curt;
00152 t/=period;
00153 t=(((int)t)&1)?(int)t+1-t:(t-(int)t);
00154 t*=8;
00155 const float invsigma=-6;
00156 const float gamma=.83f;
00157 const float amp=.5f;
00158 float imp[5];
00159
00160 float w = (paused || curt>=timeoflastrelease) ? 1 : (static_cast<float>(timeoflastrelease-curt)/FADE_OUT_TIME);
00161 for(int i=0; i<5; i++) {
00162 float p=invsigma*(t-i-2)*(t-i-2);
00163 if(p>-10) {
00164
00165 imp[i]=expf(p)*w;
00166 acts[i]+=amp*imp[i];
00167 } else {
00168 imp[i]=0;
00169 }
00170 acts[i]*=gamma*w;
00171 }
00172 cmds[ERS7Info::FaceLEDPanelOffset+ 6]=acts[0]/2+imp[0];
00173 cmds[ERS7Info::FaceLEDPanelOffset+ 8]=acts[1]/2+imp[1];
00174 cmds[ERS7Info::FaceLEDPanelOffset+10]=acts[2]/2+imp[2];
00175 cmds[ERS7Info::FaceLEDPanelOffset+ 9]=acts[3]/2+imp[3];
00176 cmds[ERS7Info::FaceLEDPanelOffset+ 7]=acts[4]/2+imp[4];
00177 #elif defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00178 if (!paused) {
00179 cmds[RobotInfo::PowerRedLEDOffset].set(0.2f,1);
00180 cmds[RobotInfo::PowerGreenLEDOffset].set(1,1);
00181 }
00182 #endif
00183 int changed=PostureMC::updateOutputs();
00184 dirty=(curt<timeoflastrelease);
00185 return changed;
00186 }
00187
00188 void EmergencyStopMC::setActive(bool a) {
00189 if(paused) {
00190 if(!a && active)
00191 releaseJoints();
00192 else if(a && !active)
00193 freezeJoints();
00194 }
00195 active=a;
00196 }
00197
00198
00199 void EmergencyStopMC::setStopped(bool p, bool sound) {
00200 if(p!=paused) {
00201 paused=p;
00202 if(active) {
00203 if(paused) {
00204 freezeJoints();
00205 if(sound)
00206 sndman->playFile(config->motion.estop_on_snd);
00207 std::cout << "*** PAUSED ***" << std::endl;
00208 } else {
00209 releaseJoints();
00210 if(sound)
00211 sndman->playFile(config->motion.estop_off_snd);
00212 std::cout << "*** UNPAUSED ***" << std::endl;
00213 }
00214 }
00215 }
00216 }
00217
00218 void EmergencyStopMC::freezeJoints() {
00219 dirty=true;
00220 targetReached=false;
00221 for(unsigned int i=0; i<NumOutputs; i++) {
00222 OutputCmd c=motman->getOutputCmd(i);
00223 curPositions[i]=cmds[i].value = (c.weight==0) ? state->outputs[i] : c.value;
00224 }
00225 for(unsigned int i=0; i<NumPIDJoints; i++)
00226 piddutyavgs[i]=0;
00227 #ifdef TGT_HAS_WHEELS
00228
00229 for(unsigned int i=WheelOffset; i<WheelOffset+NumWheels; i++) {
00230 cmds[i].value = 0;
00231 curPositions[i] = 0;
00232 }
00233 #endif
00234 #ifndef TGT_HAS_LEDS
00235
00236 for(unsigned int i=0; i<NumOutputs; i++)
00237 cmds[i].weight=1;
00238 #else
00239 for(unsigned int i=0; i<LEDOffset; i++)
00240 cmds[i].weight=1;
00241 for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00242 cmds[i].unset();
00243 for(unsigned int i=LEDOffset+NumLEDs; i<NumOutputs; i++)
00244 cmds[i].weight=1;
00245 #endif
00246 #if defined(TGT_ERS2xx) || defined(TGT_ERS210) || defined(TGT_ERS220)
00247
00248
00249 if(RobotName == ERS210Info::TargetName) {
00250 int red=capabilities.getOutputOffset(ERS210Info::outputNames[ERS210Info::TlRedLEDOffset]);
00251 int blue=capabilities.getOutputOffset(ERS210Info::outputNames[ERS210Info::TlBluLEDOffset]);
00252 cmds[red].set(0,.5f);
00253 cmds[blue].set(0,.5f);
00254 } else if(RobotName == ERS220Info::TargetName) {
00255 int tl=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::TailLeftLEDOffset]);
00256 int tc=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::TailCenterLEDOffset]);
00257 int tr=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::TailRightLEDOffset]);
00258 int bl1=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackLeft1LEDOffset]);
00259 int bl2=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackLeft2LEDOffset]);
00260 int bl3=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackLeft3LEDOffset]);
00261 int br1=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackRight1LEDOffset]);
00262 int br2=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackRight2LEDOffset]);
00263 int br3=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::BackRight3LEDOffset]);
00264 cmds[tl].set(0, .5f); cmds[tc].set(0, .5f); cmds[tr].set(0, .5f);
00265 cmds[bl1].set(0, .5f); cmds[bl2].set(0, .5f); cmds[bl3].set(0, .5f);
00266 cmds[br1].set(0, .5f); cmds[br2].set(0, .5f); cmds[br3].set(0, .5f);
00267 }
00268 #elif defined(TGT_ERS7)
00269 cmds[MdBackColorLEDOffset].set(0,.5f);
00270 for(int i=6; i<6+5; i++)
00271 cmds[FaceLEDPanelOffset+i].set(0,0.5f);
00272 #elif defined(TGT_CHIARA)
00273 cmds[ChiaraInfo::RedLEDOffset].set(0,.5f);
00274 #elif defined(TGT_CHIARA2)
00275 cmds[Chiara2Info::AllLEDMask].set(0,.5f);
00276 #elif defined(TGT_IS_QWERK)
00277 cmds[LEDOffset+8].set(0,.5f);
00278 cmds[LEDOffset+9].set(0,.5f);
00279 # if defined(TGT_QBOTPLUS)
00280 cmds[LEDOffset+10].set(1,1);
00281 # endif
00282 #elif defined(TGT_IS_CREATE) | defined(TGT_IS_CREATE2)
00283 cmds[RobotInfo::PowerRedLEDOffset].set(0,.5f);
00284 cmds[RobotInfo::PowerGreenLEDOffset].set(0,.5f);
00285 #elif defined(TGT_HAS_LEDS)
00286 cmds[LEDOffset+NumLEDs-1].set(0,.5f);
00287 # if TGT_HAS_LEDS>1
00288 cmds[LEDOffset+NumLEDs-2].set(0,.5f);
00289 # endif
00290 #endif
00291 postEvent(EventBase(EventBase::estopEGID,getID(),EventBase::activateETID,0));
00292 timeoflastfreeze=get_time();
00293 }
00294
00295 void EmergencyStopMC::releaseJoints() {
00296 dirty=true;
00297 targetReached=false;
00298 unsigned int curt=get_time();
00299 timeoflastrelease=curt+FADE_OUT_TIME;
00300 postEvent(EventBase(EventBase::estopEGID,getID(),EventBase::deactivateETID,curt-timeoflastfreeze));
00301 }
00302
00303 bool EmergencyStopMC::trigger() {
00304 const WorldState * st=WorldState::getCurrent();
00305 #if defined(TGT_ERS2xx) || defined(TGT_ERS210) || defined(TGT_ERS220)
00306 if(RobotName == ERS210Info::TargetName)
00307 return st->button_times[capabilities.getButtonOffset(ERS210Info::buttonNames[ERS210Info::BackButOffset])];
00308 if(RobotName == ERS220Info::TargetName)
00309 return st->button_times[capabilities.getButtonOffset(ERS220Info::buttonNames[ERS220Info::BackButOffset])];
00310 #elif defined(TGT_ERS7)
00311 return st->button_times[ERS7Info::FrontBackButOffset]+st->button_times[ERS7Info::MiddleBackButOffset]+st->button_times[ERS7Info::RearBackButOffset];
00312 #elif defined(TGT_IS_QWERK)
00313 return st->button_times[0];
00314 #elif defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00315 return (st->sensors[RobotInfo::ModeStateOffset] == RobotInfo::MODE_PASSIVE);
00316 #elif defined(TGT_IS_KOBUKI)
00317 return(st->buttons[RobotInfo::DropLeftWheelButOffset] > 0 || st->buttons[RobotInfo::DropRightWheelButOffset] > 0);
00318 #elif defined(TGT_IS_CHIARA)
00319 return st->button_times[RedButOffset];
00320 #else
00321 # if defined(TGT_HAS_BUTTONS)
00322 # warning Target model has buttons, but EmergencyStop does not know which to use for the trigger
00323 # endif
00324 (void)st;
00325 #endif
00326 return false;
00327 }
00328
00329
00330
00331
00332
00333