Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ResetServos.cc

Go to the documentation of this file.
00001 #include "Shared/RobotInfo.h"
00002 #ifdef TGT_IS_BIOLOID
00003 
00004 #include "Behaviors/BehaviorBase.h"
00005 #include "Events/EventRouter.h"
00006 #include "Events/LocomotionEvent.h"
00007 #include "Motion/MMAccessor.h"
00008 #include "Motion/MotionManager.h"
00009 #include "Motion/MotionSequenceMC.h"
00010 #include "Motion/PIDMC.h"
00011 #include "Motion/PostureMC.h"
00012 #include "Shared/WorldState.h"
00013 #include "local/DeviceDrivers/DynamixelProtocol.h"
00014 #include "IPC/SharedObject.h"
00015 
00016 //! Listen for Dynamixel servo errors and power down the servo for a brief period to reset it.  Also twitch the legs if they're under load and the robot is just standing around.
00017 
00018 class ResetServos : public BehaviorBase {
00019 public:
00020   ResetServos() : BehaviorBase("ResetServos"), pidmc_id(MotionManager::invalid_MC_ID) {}
00021 
00022   virtual void doStart() {
00023     pidmc_id = motman->addPersistentMotion(SharedObject<PIDMC>(), MotionManager::kHighPriority);
00024     erouter->addListener(this, EventBase::servoEGID);
00025 #ifdef TGT_HAS_LEGS
00026     erouter->addListener(this, EventBase::locomotionEGID);
00027 #endif
00028   }
00029 
00030   virtual void doStop() {
00031     motman->removeMotion(pidmc_id);
00032   }
00033 
00034   static const unsigned int  loadErrorDownTime = 2500; //!< How long to keep the servo turned off (milliseconds) after a load error
00035   static const unsigned int  heatErrorDownTime = 5000; //!< How long to keep the servo turned off (milliseconds) after a heat error
00036   static const unsigned int  fidgetInterval = 10000; //!< How long between leg fidgets
00037 
00038   virtual void doEvent() {
00039     switch ( event->getGeneratorID() ) {
00040 
00041     case EventBase::servoEGID: {
00042       const unsigned int joint = event->getSourceID();
00043       if ( MMAccessor<PIDMC>(pidmc_id)->getPID(joint).weight > 0 )  // We're already cooling this servo, so punt
00044         return;
00045       unsigned char errorCode = (unsigned char)event->getMagnitude();
00046       if ( (errorCode & DynamixelProtocol::LOAD_ERROR) && std::abs(state->pidduties[joint]) > 0.05 )
00047         erouter->addTimer(this, joint, loadErrorDownTime, false);
00048       else if ( errorCode & DynamixelProtocol::HEAT_ERROR )
00049         erouter->addTimer(this, joint+1000, heatErrorDownTime, false);
00050       else return;
00051       std::cout << "Joint " << joint << " (" << outputNames[joint] << ") reported ";
00052       for(unsigned int i=0; i<sizeof(errorCode)*8; ++i)
00053         if( (errorCode>>i) & 1 )
00054         std::cout << DynamixelProtocol::ResponseErrorNames[i];
00055       std::cout << ",  pidduty=" << state->pidduties[joint] << std::endl;
00056       MMAccessor<PIDMC>(pidmc_id)->setJointPowerLevel(joint, 0, 1);    // Turn servo off: set power level to 0 with weight of 1
00057       break;
00058     }
00059 
00060 #ifdef TGT_HAS_LEGS
00061     case EventBase::locomotionEGID: {
00062       const LocomotionEvent& le = dynamic_cast<const LocomotionEvent&>(*event);
00063       if ( le.x == 0 && le.y == 0 && le.a == 0 )  // walking has stopped
00064         erouter->addTimer(this, 9999, fidgetInterval, true);
00065       else
00066         erouter->removeTimer(this, 9999);
00067     // std::cout << "ResetServos locomotion: "<< le.x <<" "<< le.y <<" "<<le.a<<std::endl;
00068       break;
00069     }
00070 #endif
00071 
00072     case EventBase::timerEGID: {
00073       unsigned int source = event->getSourceID();
00074 #ifdef TGT_HAS_LEGS
00075       if ( source == 9999 ) {
00076         twitchSomeLeg();
00077         return;
00078       }
00079 #endif
00080       bool loadError = source < 1000;
00081       unsigned int joint = loadError ? source : source-1000;
00082       MMAccessor<PIDMC>(pidmc_id)->setJointPowerLevel(joint, 0, 0);       // Reset weight to 0 so servo can power up again
00083 // std::cout << "Cured error in joint " << joint << std::endl;
00084       if ( loadError) {
00085       // For load errors, after cooldown, twitch the joint by briefly pulling it toward its zero degree position
00086         float curpos = state->outputs[joint];
00087         SharedObject<PostureMC> twitch_mc;
00088         twitch_mc->setOutputCmd(joint, curpos*state->pidduties[joint]);
00089         motman->addPrunableMotion(twitch_mc, MotionManager::kHighPriority);
00090       }
00091       break;
00092     }
00093 
00094     default:
00095       std::cout << "Unexpected event " << event->getDescription() << std::endl;
00096       break;
00097     }
00098   }
00099 
00100 #ifdef TGT_HAS_LEGS
00101   void twitchSomeLeg() {
00102     unsigned int joint = 0;
00103     for(unsigned int i = LegOffset; i < LegOffset+NumLegJoints; i++)
00104       if ( fabs(state->pidduties[i]) > fabs(state->pidduties[joint]) )
00105       joint=i;
00106     if( fabs(state->pidduties[joint]) < 0.2)
00107       return;
00108     unsigned int leg = (joint-LegOffset)/JointsPerLeg;  
00109     unsigned int elevator = LegOffset + leg*JointsPerLeg + ElevatorOffset;
00110     //const float midrange = (outputRanges[elevator][MaxRange]+outputRanges[elevator][MinRange])/2;
00111     // std::cout << "I found that the most presure being applied is at " << outputNames[joint] << "  " << state->pidduties[joint] << std::endl;
00112     float curpos = state->outputs[elevator];
00113     float newpos = 1.3f; // (curpos > midrange) ? curpos+0.4 : curpos-0.4;          
00114     // std::cout<<"curpos="<<curpos<<"   newpos="<<newpos<<"  tmidrange="<<midrange<<std::endl;
00115     SharedObject<TinyMotionSequenceMC> fidget_mc;
00116     fidget_mc->advanceTime(700);
00117     fidget_mc->setOutputCmd(joint,newpos);
00118     fidget_mc->advanceTime(300);
00119     fidget_mc->setOutputCmd(joint,curpos);
00120     motman->addPrunableMotion(fidget_mc,MotionManager::kHighPriority);
00121   }
00122 #endif
00123 
00124 private:
00125   MotionManager::MC_ID pidmc_id;
00126 
00127 };
00128 
00129 REGISTER_BEHAVIOR_MENU_OPT(ResetServos,"Background Behaviors/System Daemons",BEH_NONEXCLUSIVE|BEH_START);
00130 
00131 #endif

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