Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

PostureEditor.cc

Go to the documentation of this file.
00001 #include "PostureEditor.h"
00002 #include "Motion/MMAccessor.h"
00003 #include "Motion/EmergencyStopMC.h"
00004 #include "Motion/MotionSequenceMC.h"
00005 #include "Sound/SoundManager.h"
00006 #include "Events/EventRouter.h"
00007 #include "ValueEditControl.h"
00008 #include "NullControl.h"
00009 #include "StringInputControl.h"
00010 #include "FileInputControl.h"
00011 #include "Shared/ProjectInterface.h"
00012 #include "Motion/MotionPtr.h"
00013 #include "Shared/Config.h"
00014 
00015 #include "Shared/RobotInfo.h"
00016 #ifdef TGT_HAS_LEDS
00017 #  include "Motion/LedMC.h"
00018 #endif
00019 
00020 PostureEditor::PostureEditor()
00021   : ControlBase("Posture Editor","Allows you to load, save, and numerically edit the posture"), 
00022     pose(), reachID(invalid_MC_ID),
00023     loadPose(NULL), disabledLoadPose(NULL), savePose(NULL), pauseCalled(false)
00024 {
00025   // add load and save menus
00026   pushSlot(loadPose=new FileInputControl("Load Posture","Select a posture to open",config->portPath(config->motion.root)));
00027   loadPose->setFilter("*.pos");
00028   disabledLoadPose=new NullControl("[Load disabled by EStop]","Cannot load new postures while EStop is active");
00029   pushSlot(savePose=new StringInputControl("Save Posture","Please enter the filename to save to (in "+config->motion.root+")"));
00030 
00031   // add submenu for weight editors
00032   ControlBase * weights;
00033   pushSlot(weights=new ControlBase("Weights","Set the weights for outputs"));
00034   for(unsigned int i=0; i<NumOutputs; i++)
00035     weights->pushSlot(new ValueEditControl<float>(outputNames[i],&pose(i).weight));
00036 
00037   pushSlot(NULL); // a separator for clarity
00038 
00039   // add actual value editors
00040   for(unsigned int i=0; i<NumOutputs; i++)
00041     pushSlot(new ValueEditControl<float>(outputNames[i],&pose(i).value));
00042 }
00043 
00044 PostureEditor::~PostureEditor() {
00045   delete loadPose;
00046   delete disabledLoadPose;
00047   options[0]=NULL;
00048 }
00049 
00050 ControlBase *
00051 PostureEditor::activate(MC_ID disp_id, Socket * gui) {
00052   //cout << "activate" << endl;
00053   if(reachID!=invalid_MC_ID) // was already activated
00054     return ControlBase::activate(disp_id,gui); // happens when estop is turned on, causing "reactivation"
00055   // start off with current pose
00056   pose.takeSnapshot();
00057   pose.setWeights(1);
00058 #ifdef TGT_HAS_LEDS
00059   // clear the LEDs though
00060   for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00061     pose.setOutputCmd(i,0);
00062 #endif
00063   // add it the motion sequence we'll be using to move to changes
00064   SharedObject<SmallMotionSequenceMC> reach;
00065   reachID=motman->addPersistentMotion(reach);
00066   // we'll need to know when estop is turned on or off
00067   erouter->addListener(this,EventBase::estopEGID);
00068   // call super class
00069   return ControlBase::activate(disp_id,gui);
00070 }
00071 
00072 void
00073 PostureEditor::refresh() {
00074   //cout << "refresh" << endl;
00075   if(isEStopped()) {
00076     processEvent(EventBase(EventBase::timerEGID,1,EventBase::statusETID,0));
00077     erouter->addTimer(this,0,500);
00078     options[0]=disabledLoadPose;
00079   } else {
00080     for(unsigned int i=PIDJointOffset; i<PIDJointOffset+NumPIDJoints; ++i)
00081       if(state->pids[i][0]==0 && state->pids[i][1]==0 && state->pids[i][2]==0)
00082         pose(i).value=state->outputs[i];
00083     options[0]=loadPose;
00084   }
00085   if(loadPose->getLastInput().size()>0) {
00086     pose.loadFile(loadPose->getLastInput().c_str());
00087     updatePose(moveTime);
00088     loadPose->clearLastInput();
00089   } else if(savePose->getLastInput().size()>0) {
00090     // we just got back from the save menu
00091     std::string filename=savePose->getLastInput();
00092     if(filename.find(".")==std::string::npos)
00093       filename+=".pos";
00094     pose.saveFile(config->motion.makePath(filename).c_str());
00095     savePose->takeInput("");
00096   } else {
00097     updatePose(moveTime/2);
00098   }
00099   pauseCalled=false;
00100   ControlBase::refresh();
00101 }
00102 
00103 void
00104 PostureEditor::pause() {
00105   //cout << "pause" << endl;
00106   refresh(); //one last time, in case this pause is due to un-estop putting Controller into low-profile mode
00107   pauseCalled=true;
00108   erouter->removeTimer(this);
00109   ControlBase::pause();
00110 }
00111 
00112 void
00113 PostureEditor::deactivate() {
00114   //cout << "deactivate" << endl;
00115   //cout << "removeMotion(" << reachID << ")" << endl;
00116   motman->removeMotion(reachID);
00117   reachID=invalid_MC_ID;
00118   erouter->removeListener(this);
00119   erouter->removeTimer(this);
00120   ControlBase::deactivate();
00121 }
00122 
00123 void
00124 PostureEditor::processEvent(const EventBase& e) {
00125   //cout << "processEvent(" << e.getName() << ")" << endl;
00126   if(e.getGeneratorID()==EventBase::estopEGID) {
00127     if(e.getTypeID()==EventBase::deactivateETID) {
00128       MMAccessor<SmallMotionSequenceMC>(reachID)->play();
00129       erouter->removeTimer(this);
00130       if(!pauseCalled)
00131         refresh();
00132     } else {
00133       if(!pauseCalled) {
00134         erouter->addTimer(this,0,500); // timer to allow updates on joint positions
00135         processEvent(EventBase(EventBase::timerEGID,0,EventBase::statusETID)); // but also do one right now
00136       }
00137     }
00138   } else if(e.getGeneratorID()==EventBase::timerEGID) {
00139 #ifndef TGT_HAS_LEDS
00140     pose.takeSnapshot();
00141 #else
00142     //doing a manual copy instead of just takeSnapshot() so we don't disturb the LED settings
00143     for(unsigned int i=0; i<LEDOffset; i++)
00144       pose(i).value=state->outputs[i];
00145     for(unsigned int i=LEDOffset+NumLEDs; i<NumOutputs; i++)
00146       pose(i).value=state->outputs[i];
00147 #endif
00148     if(e.getSourceID()==0) // source==1 indicates it's a forged event sent from refresh -- don't inf. recurse
00149       refresh();
00150   } else {
00151     serr->printf("WARNING: PostureEditor unexpected event: %s\n",e.getName().c_str());
00152   }
00153 }
00154 
00155 bool
00156 PostureEditor::isEStopped() {
00157   return ProjectInterface::estop->getStopped();
00158 }
00159 
00160 void
00161 PostureEditor::updatePose(unsigned int delay) {
00162   //cout << "updatePose" << endl;
00163   bool paused=isEStopped();
00164   if ( reachID == MotionManager::invalid_MC_ID ) return;
00165   MMAccessor<SmallMotionSequenceMC> reach_acc(reachID);
00166   if(paused) {
00167     reach_acc->clear();
00168     return;
00169   }
00170   PostureEngine curpose;
00171   reach_acc->getPose(curpose);
00172   reach_acc->clear();
00173   //we want to keep the current pose to avoid any twitching
00174   reach_acc->setTime(1);
00175   for(unsigned int i=0; i<NumOutputs; i++) //only set weighted joints
00176     if(curpose(i).weight!=0)
00177       reach_acc->setOutputCmd(i,curpose(i));
00178   //now move to desired posture
00179   reach_acc->setTime(delay);
00180   reach_acc->setPose(pose);
00181   reach_acc->play();
00182 }
00183 
00184 
00185 /*! @file
00186  * @brief Describes PostureEditor, which allows numeric control of joints and LEDs
00187  * @author ejt (Creator)
00188  */

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:49 2016 by Doxygen 1.6.3