Homepage Demos Overview Downloads Tutorials Reference
Credits

Controller.cc

Go to the documentation of this file.
00001 #include "Controller.h"
00002 #include "Motion/EmergencyStopMC.h"
00003 #include "Motion/LedMC.h"
00004 #include "Motion/MMAccessor.h"
00005 #include "Shared/SharedObject.h"
00006 #include "Shared/WorldState.h"
00007 #include "Shared/get_time.h"
00008 #include "SoundPlay/SoundManager.h"
00009 #include "Events/TextMsgEvent.h"
00010 #include "Shared/ERS210Info.h"
00011 #include "Shared/ERS220Info.h"
00012 #include "Shared/DynamicConfig.h"
00013 #include "Shared/string_util.h"
00014 #include <sstream>
00015 
00016 Controller * Controller::theOneController=NULL;
00017 
00018 //these are given appropriate values in init once we know which model we're running on
00019 EventBase Controller::nextItem;
00020 EventBase Controller::prevItem;
00021 EventBase Controller::nextItemFast;
00022 EventBase Controller::prevItemFast;
00023 EventBase Controller::selectItem;
00024 EventBase Controller::cancel;
00025 
00026 using namespace string_util;
00027 
00028 
00029 void Controller::DoStart() {
00030   BehaviorBase::DoStart();
00031   sndman->LoadFile(config->controller.select_snd);
00032   sndman->LoadFile(config->controller.next_snd);
00033   sndman->LoadFile(config->controller.prev_snd);
00034   sndman->LoadFile(config->controller.read_snd);
00035   sndman->LoadFile(config->controller.cancel_snd);
00036   erouter->addListener(this,EventBase::estopEGID);
00037   // Turn on wireless
00038   wireless->setReceiver(gui_comm->sock, gui_comm_callback);
00039   wireless->listen(gui_comm->sock, config->controller.gui_port);
00040   theOneController=this;
00041   reset();
00042 }
00043 
00044 void Controller::DoStop() {
00045   sndman->ReleaseFile(config->controller.select_snd);
00046   sndman->ReleaseFile(config->controller.next_snd);
00047   sndman->ReleaseFile(config->controller.prev_snd);
00048   sndman->ReleaseFile(config->controller.read_snd);
00049   sndman->ReleaseFile(config->controller.cancel_snd);
00050   erouter->forgetListener(this);
00051   reset();
00052   wireless->close(gui_comm);
00053   theOneController=NULL;
00054   BehaviorBase::DoStop();
00055 }
00056 
00057 bool Controller::trapEvent(const EventBase& e) {
00058   if(!chkCmdStack())
00059     return false;
00060   last_time=cur_time;
00061   cur_time=get_time();
00062   if(nextItem.sameGenSource(e)) {
00063     nextEv_val=e.getMagnitude();
00064     nextEv_dur=e.getDuration();
00065     if(nextEv_val==0 && prevEv_val==0)
00066       alreadyGotBoth=false;
00067     if(nextEv_val>.75 && prevEv_val>.75 && nextEv_dur<666 && prevEv_dur<666)
00068       if(alreadyGotBoth)
00069         return true;
00070       else {
00071         alreadyGotBoth=true;
00072         return setNext(cmdstack.top()->doReadStdIn());
00073       }
00074     if(e.getTypeID()==nextItem.getTypeID() && e.getDuration()<666)
00075       return setNext(cmdstack.top()->doNextItem());
00076     if(e.getTypeID()==nextItemFast.getTypeID() && e.getDuration()>666 && calcPulse(cur_time,last_time,static_cast<unsigned int>(50/e.getMagnitude())))
00077       return setNext(cmdstack.top()->doNextItem());
00078   }
00079   if(prevItem.sameGenSource(e)) {
00080     prevEv_val=e.getMagnitude();
00081     prevEv_dur=e.getDuration();
00082     if(nextEv_val==0 && prevEv_val==0)
00083       alreadyGotBoth=false;
00084     if(nextEv_val>.75 && prevEv_val>.75 && nextEv_dur<666 && prevEv_dur<666)
00085       if(alreadyGotBoth)
00086         return true;
00087       else {
00088         alreadyGotBoth=true;
00089         return setNext(cmdstack.top()->doReadStdIn());
00090       }
00091     if(e.getTypeID()==prevItem.getTypeID() && e.getDuration()<666)
00092       return setNext(cmdstack.top()->doPrevItem());
00093     if(e.getTypeID()==prevItemFast.getTypeID() && e.getDuration()>666 && calcPulse(cur_time,last_time,static_cast<unsigned int>(50/e.getMagnitude())))
00094       return setNext(cmdstack.top()->doPrevItem());
00095   }
00096   if(e.getDuration()>250) {
00097     if(e==selectItem)
00098       return setNext(cmdstack.top()->doSelect());
00099     if(e==cancel)
00100       return setNext(cmdstack.top()->doCancel());
00101   }
00102   return true;
00103 }
00104 
00105 void Controller::processEvent(const EventBase& event) {
00106   if(event.getTypeID()==EventBase::activateETID) { //estop just turned on
00107     if(display==MotionManager::invalid_MC_ID)
00108       activate();
00109   } else { //estop just turned off
00110     if(display!=MotionManager::invalid_MC_ID)
00111       deactivate();
00112   }
00113 }
00114 
00115 void Controller::reset() {
00116   while(cmdstack.size()>1)
00117     pop();
00118   if(!cmdstack.empty()) {
00119     cmdstack.top()->deactivate();
00120     cmdstack.pop();
00121   }
00122   refresh();
00123 }
00124 
00125 void Controller::refresh() {
00126   if(!chkCmdStack())
00127     return;
00128   cmdstack.top()->refresh();
00129 }
00130 
00131 void Controller::push(ControlBase* c) {
00132   if(!chkCmdStack())
00133     return;
00134   cmdstack.top()->pause();
00135   cmdstack.push(c);
00136   theOneController->gui_comm->printf("push\n");
00137   setNext(cmdstack.top()->activate(display,gui_comm));
00138 }
00139 
00140 void Controller::pop() {
00141   cmdstack.top()->deactivate();
00142   cmdstack.pop();
00143   theOneController->gui_comm->printf("pop\n");
00144   refresh();
00145 }
00146 
00147 Controller& Controller::setRoot(ControlBase* r) {
00148   reset();
00149   root=r;
00150   refresh();
00151   return *this;
00152 }
00153 
00154 Controller& Controller::setEStopID(MotionManager::MC_ID estopid) {
00155   estop_id=estopid;
00156   if(static_cast<EmergencyStopMC*>(motman->peekMotion(estopid))->getStopped()) {
00157     if(display==MotionManager::invalid_MC_ID)
00158       activate();
00159   } else {
00160     if(display!=MotionManager::invalid_MC_ID)
00161       deactivate();
00162   }   
00163   return *this;
00164 }
00165 
00166 void Controller::loadGUI(const std::string& type, const std::string& name, unsigned int port, const std::vector<std::string>& args) {
00167   std::stringstream ss;
00168   ss << "load\n" << type << '\n' << name << '\n' << port << '\n';
00169   for(unsigned int i=0; i<args.size(); i++) {
00170     ss << '"';
00171     for(unsigned int j=0; j<args[i].size(); j++) {
00172       if(args[i][j]=='\\' || args[i][j]=='"' || args[i][j]=='\n')
00173         ss << '\\';
00174       ss << args[i][j];
00175     }
00176     ss << "\" ";
00177   }
00178   ss << '\n';
00179   theOneController->gui_comm->write((const byte*)ss.str().c_str(),ss.str().size());
00180 }
00181 
00182 void Controller::closeGUI(const std::string& name) {
00183   ASSERTRET(theOneController!=NULL,"null controller");
00184   ASSERTRET(theOneController->gui_comm!=NULL,"null gui_comm");
00185 
00186   theOneController->gui_comm->printf("close\n%s\n",name.c_str());
00187 }
00188 
00189 int Controller::gui_comm_callback(char *buf, int bytes) {
00190   std::string s(buf,bytes);
00191   //  cout << "Controller Received: " << s << endl;
00192   if(theOneController==NULL)
00193     return 0;
00194 
00195   static std::string incomplete;
00196 
00197   //pass a line at a time to the controller
00198   while(s.size()>0) {
00199     unsigned int endline=s.find('\n');
00200     if(endline==std::string::npos) {
00201       incomplete+=s;
00202       return 0;
00203     }
00204     incomplete+=s.substr(0,endline);
00205     theOneController->takeLine(incomplete); //is now complete
00206     incomplete.erase();
00207     s=s.substr(endline+1);
00208   }
00209   
00210   return 0;
00211 }
00212 
00213 int Controller::console_callback(char *buf, int bytes) {
00214   std::string s(buf,bytes);
00215   //  cout << "Console Received: " << s << endl;
00216   if(theOneController==NULL)
00217     return 0;
00218 
00219   static std::string incomplete;
00220 
00221   //pass a line at a time to the controller
00222   while(s.size()>0) {
00223     unsigned int endline=s.find('\n');
00224     if(endline==std::string::npos) {
00225       incomplete+=s;
00226       return 0;
00227     }
00228     incomplete+=s.substr(0,endline);
00229     //is now complete:
00230     if(wireless->isConnected(theOneController->gui_comm->sock))
00231       erouter->postEvent(new TextMsgEvent(incomplete));
00232     else
00233       theOneController->takeLine(incomplete); 
00234     incomplete.erase();
00235     s=s.substr(endline+1);
00236   }
00237   
00238   return 0;
00239 }
00240 
00241 void Controller::init() {
00242   wireless->setDaemon(gui_comm);
00243   if(state->robotDesign & WorldState::ERS210Mask) {
00244     nextItem=EventBase(EventBase::buttonEGID,ERS210Info::HeadFrButOffset,EventBase::deactivateETID,0);
00245     prevItem=EventBase(EventBase::buttonEGID,ERS210Info::HeadBkButOffset,EventBase::deactivateETID,0);
00246     nextItemFast=EventBase(EventBase::buttonEGID,ERS210Info::HeadFrButOffset,EventBase::statusETID,666);
00247     prevItemFast=EventBase(EventBase::buttonEGID,ERS210Info::HeadBkButOffset,EventBase::statusETID,666);
00248     selectItem=EventBase(EventBase::buttonEGID,ERS210Info::ChinButOffset,EventBase::deactivateETID,250);
00249     cancel=EventBase(EventBase::buttonEGID,ERS210Info::BackButOffset,EventBase::deactivateETID,250);
00250   } else if(state->robotDesign & WorldState::ERS220Mask) {
00251     nextItem=EventBase(EventBase::buttonEGID,ERS220Info::TailLeftButOffset,EventBase::deactivateETID,0);
00252     prevItem=EventBase(EventBase::buttonEGID,ERS220Info::TailRightButOffset,EventBase::deactivateETID,0);
00253     //the 220 doesn't really support the next two because it's using boolean buttons
00254     //i'm using a "hack" on the 210 because the pressure sensitivity causes status
00255     //events to continually be sent but since this is just on/off, it only gets the
00256     //activate/deactivate.  To fix this, make these timers and do timer management
00257     //in processEvents()
00258     nextItemFast=EventBase(EventBase::buttonEGID,ERS220Info::TailLeftButOffset,EventBase::statusETID,666);
00259     prevItemFast=EventBase(EventBase::buttonEGID,ERS220Info::TailRightButOffset,EventBase::statusETID,666);
00260     selectItem=EventBase(EventBase::buttonEGID,ERS220Info::TailCenterButOffset,EventBase::deactivateETID,50);
00261     cancel=EventBase(EventBase::buttonEGID,ERS220Info::BackButOffset,EventBase::deactivateETID,50);
00262   }
00263 }
00264 
00265 void Controller::takeLine(const std::string& s) {
00266   //  cout << "RECEIVED: " << s << endl;
00267   if(s.size()==0)
00268     return;
00269   // break s into a vector of arguments
00270   std::vector<std::string> args;
00271   std::vector<unsigned int> offsets;
00272   if(!string_util::parseArgs(s,args,offsets)) {
00273     serr->printf("Controller::takeLine(\"%s\") was malformed.\n",s.c_str());
00274     return;
00275   }
00276   // now look through for a ';' (separates multiple commands)
00277   unsigned int last=offsets[0];
00278   for(unsigned int i=0; i<args.size(); i++) {
00279     if(args[i]==";") { // if we found a ';', recurse with substring
00280       takeLine(s.substr(last,offsets[i]-last));
00281       if(i+1==args.size()) // last arg is a ';'
00282         return;
00283       last=offsets[i+1];
00284     }
00285     if(args[i]=="\\;") // if we found a '\;', replace it with base ';'
00286       args[i]=";";
00287   }
00288   if(!chkCmdStack())
00289     return;
00290   if(args[0][0]!='!') {
00291     setNext(cmdstack.top()->takeInput(s));
00292   } else {
00293     if(last!=offsets[0]) { // only changes if we found a ';' - in that case, need to do last segment
00294       takeLine(s.substr(last));
00295     } else if(args[0]=="!refresh") {
00296       refresh();
00297     } else if(args[0]=="!reset") {
00298       reset();
00299     } else if(args[0]=="!cancel") {
00300       setNext(cmdstack.top()->doCancel());
00301     } else if(args[0]=="!select") {
00302       setNext(cmdstack.top()->doSelect());
00303     } else if(args[0]=="!next") {
00304       setNext(cmdstack.top()->doNextItem());
00305     } else if(args[0]=="!prev") {
00306       setNext(cmdstack.top()->doPrevItem());
00307     } else if(args[0]=="!msg") {
00308       erouter->postEvent(new TextMsgEvent(s.substr(offsets[1])));
00309     } else if(args[0]=="!hello") {
00310       static unsigned int count=0;
00311       count++;
00312       theOneController->gui_comm->printf("hello\n%d\n",count);
00313     } else if(args[0]=="!root") {
00314       ControlBase * ret=root->takeInput(s.substr(offsets[1]));
00315       if(ret!=NULL)
00316         setNext(ret);
00317     } else if(args[0]=="!hilight") {
00318       std::vector<unsigned int> hilights;
00319       for(unsigned int i=1; i<args.size(); i++)
00320         hilights.push_back(atoi(args[i].c_str()));
00321       cmdstack.top()->setHilights(hilights);
00322     } else if(args[0]=="!input") {
00323       const std::vector<unsigned int>& hilights=cmdstack.top()->getHilights();
00324       const std::vector<ControlBase*>& slots=cmdstack.top()->getSlots();
00325       std::string in=s.substr(offsets[1]);
00326       for(unsigned int i=0; i<hilights.size(); i++)
00327         if(hilights[i]<slots.size() && slots[hilights[i]]!=NULL) {
00328           ControlBase * ret=slots[hilights[i]]->takeInput(in);
00329           if(ret!=NULL)
00330             setNext(ret);
00331         }
00332       refresh();
00333     } else if(args[0]=="!set") {
00334       DynamicConfig::assignVarFromController(s.substr(offsets[1]).c_str());
00335     } else
00336       setNext(cmdstack.top()->takeInput(s));
00337   }
00338 }
00339 
00340 bool Controller::setNext(ControlBase* next) {
00341   if(next==NULL)
00342     pop();
00343   else if(next!=cmdstack.top())
00344     push(next);
00345   return true;
00346 }
00347 
00348 void Controller::activate() {
00349   SharedObject<LedMC> leds;
00350   leds->setWeights(~FaceLEDMask,0);
00351   leds->setWeights(FaceLEDMask,.75);
00352   display=motman->addMotion(leds,MotionManager::kEmergencyPriority);
00353   erouter->addTrapper(this,EventBase::buttonEGID);
00354   if(!cmdstack.empty())
00355     cmdstack.top()->activate(display,gui_comm);
00356   else
00357     chkCmdStack();
00358 }
00359 
00360 void Controller::deactivate() {
00361   motman->removeMotion(display);
00362   //these two lines help prevent residual display in case that was the only MotionCommand using LEDs
00363   for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00364     motman->setOutput(NULL,i,0.f);
00365   display=MotionManager::invalid_MC_ID;
00366   erouter->removeTrapper(this);
00367   cmdstack.top()->pause();
00368 }
00369 
00370 bool Controller::chkCmdStack() {
00371   if(cmdstack.empty()) {
00372     if(root==NULL)
00373       return false;
00374     cmdstack.push(root);
00375     ControlBase * next = cmdstack.top()->activate(display,gui_comm);
00376     if(next==NULL)
00377       cout << "*** WARNING Controller root returned NULL on activate!" << endl;
00378     else if(next!=root)
00379       push(next);
00380   }
00381   return true;
00382 }
00383 
00384 
00385 /*! @file
00386  * @brief Implements Controller class, a behavior that should be started whenever the emergency stop goes on to provide menus for robot control
00387  * @author ejt (Creator)
00388  *
00389  * $Author: ejt $
00390  * $Name: tekkotsu-1_5 $
00391  * $Revision: 1.28 $
00392  * $State: Rel $
00393  * $Date: 2003/10/10 00:44:50 $
00394  */

Tekkotsu v1.5
Generated Fri Oct 10 15:51:58 2003 by Doxygen 1.3.4