00001
00002 #ifndef INCLUDED_BatteryMonitorBehavior_h_
00003 #define INCLUDED_BatteryMonitorBehavior_h_
00004
00005 #include "Behaviors/BehaviorBase.h"
00006 #include "Shared/debuget.h"
00007 #include "Shared/WorldState.h"
00008 #include "Events/EventRouter.h"
00009 #include "IPC/SharedObject.h"
00010 #include "Motion/MotionManager.h"
00011 #include "Motion/PostureMC.h"
00012 #include "Shared/ERS210Info.h"
00013 #include "Shared/ERS220Info.h"
00014 #include "Shared/ERS7Info.h"
00015 #include "Motion/MMAccessor.h"
00016 #include "Sound/SoundManager.h"
00017 #include "Shared/RobotInfo.h"
00018 #ifdef TGT_HAS_LEDS
00019 # include "Motion/LedMC.h"
00020 #endif
00021
00022
00023
00024
00025
00026
00027 class BatteryMonitorBehavior : public BehaviorBase {
00028 public:
00029 static const unsigned int max_t=10000;
00030 static const unsigned int high_power_p=20;
00031 static const unsigned int no_power_p=14;
00032 static const double low_voltage_threshold;
00033
00034
00035 BatteryMonitorBehavior() : BehaviorBase("BatteryMonitorBehavior"), pose(NULL), pose_id(MotionManager::invalid_MC_ID), led_id(MotionManager::invalid_MC_ID) {}
00036
00037
00038 virtual ~BatteryMonitorBehavior() {}
00039
00040
00041 virtual void doStart() {
00042 #if defined(TGT_IS_BIOLOID)
00043 erouter->addTimer(this,0,20000);
00044 #else
00045 erouter->addListener(this,EventBase::powerEGID,PowerSrcID::LowPowerWarnSID);
00046 erouter->addListener(this,EventBase::powerEGID,PowerSrcID::ExternalPowerSID);
00047 erouter->addListener(this,EventBase::powerEGID,PowerSrcID::BatteryConnectSID);
00048 erouter->addListener(this,EventBase::powerEGID,PowerSrcID::UpdatedSID);
00049 #endif
00050
00051 if(shouldWarn())
00052 processEvent(EventBase(EventBase::powerEGID,PowerSrcID::UpdatedSID,EventBase::statusETID));
00053 }
00054
00055
00056 virtual void doStop() {
00057 if(pose!=NULL)
00058 stopWarning();
00059 }
00060
00061
00062 virtual void doEvent() {
00063 #if defined(TGT_HAS_POWER_STATUS)
00064 if(event->getGeneratorID()==EventBase::powerEGID) {
00065
00066 bool shouldwarn=shouldWarn();
00067 if(pose!=NULL && !shouldwarn)
00068 stopWarning();
00069 else if(pose==NULL && shouldwarn)
00070 startWarning();
00071 } else {
00072 ASSERTRET(event->getGeneratorID()==EventBase::timerEGID,"Unrequested event "<<event->getName());
00073 switch(event->getSourceID()) {
00074 case 0:{
00075
00076 bool shouldwarn=shouldWarn();
00077 if(pose!=NULL && !shouldwarn)
00078 stopWarning();
00079 else if(pose==NULL && shouldwarn)
00080 startWarning();
00081 break;
00082 }
00083 case 1: {
00084 std::cout<<"The switch is entering the wrong case"<<std::endl;
00085 ASSERTRET(pose!=NULL,"Extra timer 1");
00086 setFlipper(true);
00087 unsigned int flipdelay=calcFlipDelay();
00088
00089
00090 if(flipdelay<=NumFrames*FrameTime) {
00091 static bool on=false;
00092 on = !on;
00093 #if defined(TGT_HAS_LEDS)
00094 if(on) {
00095 motman->setPriority(led_id,MotionManager::kEmergencyPriority+1);
00096 MMAccessor<LedMC> led(led_id);
00097 led->displayPercent(state->sensors[PowerRemainOffset],LedEngine::major,LedEngine::major);
00098 } else
00099 motman->setPriority(led_id,MotionManager::kIgnoredPriority);
00100 #endif
00101 erouter->addTimer(this,1,128+flipdelay,false);
00102 } else {
00103 #if defined(TGT_HAS_LEDS)
00104 motman->setPriority(led_id,MotionManager::kEmergencyPriority+1);
00105 MMAccessor<LedMC> led(led_id);
00106 led->displayPercent(state->sensors[PowerRemainOffset],LedEngine::major,LedEngine::major);
00107 #endif
00108 erouter->addTimer(this,2,128,false);
00109 }
00110 } break;
00111 case 2: {
00112 ASSERTRET(pose!=NULL,"Extra timer 1");
00113 setFlipper(false);
00114 motman->setPriority(led_id,MotionManager::kIgnoredPriority);
00115
00116 erouter->addTimer(this,1,calcFlipDelay(),false);
00117 } break;
00118 default:
00119 ASSERTRET(false,"Unrequested timer " << event->getName());
00120 break;
00121 }
00122 }
00123 #endif
00124 }
00125
00126 static std::string getClassDescription() { return "Reports the current battery status, and has the robot indicate when the battery gets too low"; }
00127 virtual std::string getDescription() const { return getClassDescription(); }
00128
00129
00130
00131 static bool shouldWarn() {
00132 #if defined(TGT_IS_AIBO)
00133 return state!=NULL && state->powerFlags[PowerSrcID::BatteryConnectSID] && (state->sensors[PowerRemainOffset]*100<=high_power_p || state->powerFlags[PowerSrcID::LowPowerWarnSID]) && !state->powerFlags[PowerSrcID::ExternalPowerSID];
00134 #elif defined(TGT_HAS_POWER_STATUS)
00135 return state!=NULL && (state->sensors[PowerVoltageOffset] <= low_voltage_threshold) && (state->sensors[PowerVoltageOffset] > 0);
00136 #else
00137 return false;
00138 #endif
00139 }
00140
00141 protected:
00142
00143 void startWarning() {
00144 #if defined(TGT_IS_AIBO)
00145 serr->printf("LOW BATTERY\n");
00146 pose_id=motman->addPersistentMotion(SharedObject<PostureMC>(),MotionManager::kEmergencyPriority+1);
00147 pose=(PostureMC*)motman->peekMotion(pose_id);
00148 SharedObject<LedMC> led;
00149 led->displayPercent(state->sensors[PowerRemainOffset],LedEngine::major,LedEngine::major);
00150 led_id=motman->addPersistentMotion(led,MotionManager::kEmergencyPriority+1);
00151 setFlipper(true);
00152
00153 erouter->addTimer(this,2,128,false);
00154 #elif defined(TGT_HAS_POWER_STATUS)
00155 char batteryWarning[100];
00156 sprintf(batteryWarning,"Low battery: %4.1f volts",state->sensors[PowerVoltageOffset]);
00157 std::cout << "*** WARNING: " << batteryWarning << std::endl;
00158 sndman->speak(batteryWarning);
00159 #endif
00160 }
00161
00162
00163 void stopWarning() {
00164 serr->printf("BATTERY GOOD\n");
00165 motman->removeMotion(pose_id);
00166 motman->removeMotion(led_id);
00167 led_id=pose_id=MotionManager::invalid_MC_ID;
00168 pose=NULL;
00169 erouter->removeTimer(this,1);
00170 erouter->removeTimer(this,2);
00171 erouter->removeTimer(this,0);
00172 }
00173
00174
00175 unsigned int calcFlipDelay() {
00176 #if defined(TGT_HAS_POWER_STATUS)
00177 const float high_power=high_power_p/100.f;
00178 const float no_power=no_power_p/100.f;
00179 float cur_power=state->sensors[PowerRemainOffset];
00180 if(cur_power<no_power)
00181 return 0;
00182 return (unsigned int)(max_t*(cur_power-no_power)/(high_power-no_power));
00183 #else
00184 return 0;
00185 #endif
00186 }
00187
00188
00189 void setFlipper(bool set) {
00190 if(RobotName == ERS210Info::TargetName) {
00191 int ear=capabilities.getOutputOffset(ERS210Info::outputNames[ERS210Info::EarOffset]);
00192 for(unsigned int i=ear; i<ear+ERS210Info::NumEarJoints; i++)
00193 pose->setOutputCmd(i,set?!state->outputs[i]:OutputCmd());
00194 } else if(RobotName == ERS220Info::TargetName) {
00195 int light=capabilities.getOutputOffset(ERS220Info::outputNames[ERS220Info::RetractableHeadLEDOffset]);
00196 pose->setOutputCmd(light,set?(state->outputs[light]>.5?0:1):OutputCmd());
00197 } else if(RobotName == ERS7Info::TargetName) {
00198 int ear=capabilities.getOutputOffset(ERS7Info::outputNames[ERS7Info::EarOffset]);
00199 for(unsigned int i=ear; i<ear+ERS7Info::NumEarJoints; i++)
00200 pose->setOutputCmd(i,set?!state->outputs[i]:OutputCmd());
00201 }
00202 }
00203
00204 PostureMC* pose;
00205 MotionManager::MC_ID pose_id;
00206 MotionManager::MC_ID led_id;
00207
00208 private:
00209 BatteryMonitorBehavior(const BatteryMonitorBehavior&);
00210 BatteryMonitorBehavior operator=(const BatteryMonitorBehavior&);
00211 };
00212
00213
00214
00215
00216
00217
00218 #endif