00001 #include "SensorObserverControl.h"
00002 #include "Events/EventRouter.h"
00003 #include "Motion/MMAccessor.h"
00004 #include "Shared/WorldState.h"
00005 #include "Sound/SoundManager.h"
00006 #include "Shared/Config.h"
00007
00008 #include "Shared/RobotInfo.h"
00009 #ifdef TGT_HAS_LEDS
00010 # include "Motion/LedMC.h"
00011 #endif
00012
00013 #include <sstream>
00014
00015 REGISTER_CONTROL(SensorObserverControl,"Status Reports");
00016
00017 SensorObserverControl::SensorObserverControl()
00018 : ControlBase("Sensor Observer","Allows you to see/log the sensor data"), logfilePath(), logfile(), helpCtl(NULL), sensorCtl(NULL), buttonCtl(NULL), outputCtl(NULL), dutyCtl(NULL), consoleCtl(NULL), fileCtl(NULL), rtCtl(NULL), rtFreqCtl(NULL), numListeners(0)
00019 {
00020 pushSlot(consoleCtl=new ToggleControl("Console Output","If selected, outputs events to the console"));
00021 pushSlot(fileCtl=new StringInputControl("[ ] File Output","Please enter the filename to log to (in /ms/...)"));
00022 pushSlot(rtCtl=new RTViewControl(this));
00023 pushSlot(rtFreqCtl=new StringInputControl("Real-time Update Period","Please enter the time between refreshes, in milliseconds; '0' to require manual refresh"));
00024 pushSlot(helpCtl=new ControlBase("Help"));
00025 pushSlot(NULL);
00026 helpCtl->pushSlot(new NullControl("The indexes listed here"));
00027 helpCtl->pushSlot(new NullControl("correspond to offsets"));
00028 helpCtl->pushSlot(new NullControl("given in the __Info.h"));
00029 helpCtl->pushSlot(new NullControl("file for the model"));
00030 helpCtl->pushSlot(new NullControl("robot which you are "));
00031 helpCtl->pushSlot(new NullControl("currently using."));
00032 pushSlot(sensorCtl=new ControlBase("Sensors:","Toggles logging of various sensors"));
00033 for(unsigned int i=0; i<NumSensors; i++)
00034 sensorCtl->pushSlot(new ToggleControl(sensorNames[i],"Turns logging of this sensor on/off"));
00035 pushSlot(buttonCtl=new ControlBase("Buttons:","Toggles logging of various buttons"));
00036 for(unsigned int i=0; i<NumButtons; i++)
00037 buttonCtl->pushSlot(new ToggleControl(buttonNames[i],"Turns logging of this button on/off"));
00038 pushSlot(outputCtl=new ControlBase("Outputs:","Toggles logging of various outputs' positions"));
00039 for(unsigned int i=0; i<NumOutputs; i++)
00040 outputCtl->pushSlot(new ToggleControl(outputNames[i],"Turns logging of this output's values on/off"));
00041 pushSlot(dutyCtl=new ControlBase("Duties:","Toggles logging of various PID joint's duty cycles"));
00042 for(unsigned int i=0; i<NumPIDJoints; i++)
00043 dutyCtl->pushSlot(new ToggleControl(outputNames[i+PIDJointOffset],"Turns logging of how hard this output is working on/off"));
00044 updateRT();
00045 }
00046
00047 ControlBase* SensorObserverControl::doSelect() {
00048 ControlBase* ans=this;
00049 bool wasListening=(numListeners>0);
00050 for(unsigned int i=0; i<hilights.size(); i++) {
00051 unsigned int cur=hilights[i];
00052 if(options[cur]==fileCtl) {
00053 if(options[cur]->getName()[1]!=' ') {
00054 logfile.close();
00055 options[cur]->setName("[ ] File Output");
00056 numListeners--;
00057 } else {
00058 ans=options[cur];
00059 numListeners++;
00060 }
00061 } else if(options[cur]==consoleCtl) {
00062 options[cur]->doSelect();
00063 if(consoleCtl->getStatus())
00064 numListeners--;
00065 else
00066 numListeners++;
00067 } else {
00068 ans=options[cur];
00069 }
00070 }
00071 sndman->playFile(config->controller.select_snd);
00072 if(wasListening!=(numListeners>0)) {
00073 if(numListeners>0)
00074 erouter->addListener(this,EventBase::sensorEGID,SensorSrcID::UpdatedSID);
00075 else
00076 erouter->removeListener(this);
00077 }
00078 if(ans==this)
00079 refresh();
00080 return ans;
00081 }
00082
00083 void SensorObserverControl::refresh() {
00084
00085 checkLogFile();
00086
00087 if(rtFreqCtl->getLastInput().size()>0) {
00088 unsigned int fr=atoi(rtFreqCtl->getLastInput().c_str());
00089 rtFreqCtl->clearLastInput();
00090 if(fr!=0 && rtCtl!=NULL)
00091 rtCtl->setPeriod(fr<100?100:fr);
00092 }
00093 ControlBase::refresh();
00094 }
00095
00096 void SensorObserverControl::processEvent(const EventBase& event) {
00097 if(event.getGeneratorID()==EventBase::sensorEGID) {
00098 std::ostringstream logdata;
00099 for(unsigned int i=0; i<NumSensors; i++)
00100 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(sensorCtl->getSlots()[i]))
00101 if(tgl->getStatus())
00102 logdata << state->lastSensorUpdateTime << "\tSENSOR:\t" << i << '\t' << state->sensors[i] << '\n';
00103 for(unsigned int i=0; i<NumButtons; i++)
00104 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(buttonCtl->getSlots()[i]))
00105 if(tgl->getStatus())
00106 logdata << state->lastSensorUpdateTime << "\tBUTTON:\t" << i << '\t' << state->buttons[i] << '\n';
00107 for(unsigned int i=0; i<NumOutputs; i++)
00108 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(outputCtl->getSlots()[i]))
00109 if(tgl->getStatus())
00110 logdata << state->lastSensorUpdateTime << "\tOUTPUT:\t" << i << '\t' << state->outputs[i] << '\n';
00111 for(unsigned int i=0; i<NumPIDJoints; i++)
00112 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(dutyCtl->getSlots()[i]))
00113 if(tgl->getStatus())
00114 logdata << state->lastSensorUpdateTime << "\tDUTY:\t" << i << '\t' << state->pidduties[i] << '\n';
00115 if(consoleCtl->getStatus())
00116 sout->printf("%s",logdata.str().c_str());
00117 checkLogFile();
00118 if(logfile)
00119 logfile << logdata.str() << std::flush;
00120 } else {
00121 serr->printf("WARNING: Unexpected event: %s\n",event.getName().c_str());
00122 }
00123 }
00124
00125 void SensorObserverControl::checkLogFile() {
00126 if(fileCtl->getLastInput()!=logfilePath) {
00127 logfile.close();
00128 logfilePath=fileCtl->getLastInput();
00129 logfile.clear();
00130 if(logfilePath.size()!=0) {
00131 sout->printf("Opening `%s'\n",config->portPath(logfilePath).c_str());
00132 logfile.open(config->portPath(logfilePath).c_str());
00133 if(!logfile.fail()) {
00134 std::string tmp=fileCtl->getName();
00135 tmp[1]='X';
00136 fileCtl->setName(tmp+": "+logfilePath);
00137 } else {
00138 serr->printf("Opening `%s' failed\n",config->portPath(logfilePath).c_str());
00139 }
00140 }
00141 }
00142 }
00143
00144 void SensorObserverControl::updateRT() {
00145 const unsigned int FTOS_LEN=50;
00146 char ftos[FTOS_LEN];
00147 rtCtl->clearSlots();
00148 bool first=true;
00149 for(unsigned int i=0; i<NumSensors; i++)
00150 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(sensorCtl->getSlots()[i]))
00151 if(tgl->getStatus()) {
00152 if(first)
00153 rtCtl->pushSlot(new NullControl("SENSORS:"));
00154 first=false;
00155 snprintf(ftos,FTOS_LEN,"%s: %g",sensorNames[i],state->sensors[i]);
00156 rtCtl->pushSlot(new NullControl(ftos));
00157 }
00158 first=true;
00159 for(unsigned int i=0; i<NumButtons; i++)
00160 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(buttonCtl->getSlots()[i]))
00161 if(tgl->getStatus()) {
00162 if(first)
00163 rtCtl->pushSlot(new NullControl("BUTTONS:"));
00164 first=false;
00165 snprintf(ftos,FTOS_LEN,"%s: %g",buttonNames[i],state->buttons[i]);
00166 rtCtl->pushSlot(new NullControl(ftos));
00167 }
00168 first=true;
00169 for(unsigned int i=0; i<NumOutputs; i++)
00170 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(outputCtl->getSlots()[i]))
00171 if(tgl->getStatus()) {
00172 if(first)
00173 rtCtl->pushSlot(new NullControl("OUTPUTS:"));
00174 first=false;
00175 snprintf(ftos,FTOS_LEN,"%s: %g",outputNames[i],state->outputs[i]);
00176 rtCtl->pushSlot(new NullControl(ftos));
00177 }
00178 first=true;
00179 for(unsigned int i=0; i<NumPIDJoints; i++)
00180 if(ToggleControl * tgl=dynamic_cast<ToggleControl*>(dutyCtl->getSlots()[i]))
00181 if(tgl->getStatus()) {
00182 if(first)
00183 rtCtl->pushSlot(new NullControl("DUTIES:"));
00184 first=false;
00185 snprintf(ftos,FTOS_LEN,"%s: %g",outputNames[i],state->pidduties[i]);
00186 rtCtl->pushSlot(new NullControl(ftos));
00187 }
00188 if(rtCtl->slotsSize()==0)
00189 rtCtl->pushSlot(new NullControl("No sensors selected","You need to select which sensors to view"));
00190 }
00191
00192 void SensorObserverControl::RTViewControl::refresh() {
00193 if(parent!=NULL)
00194 parent->updateRT();
00195 if(period!=0)
00196 erouter->addTimer(this,0,period);
00197 ControlBase::refresh();
00198 }
00199 void SensorObserverControl::RTViewControl::pause() {
00200 erouter->removeTimer(this);
00201 ControlBase::pause();
00202 }
00203 void SensorObserverControl::RTViewControl::deactivate() {
00204 erouter->removeTimer(this);
00205 ControlBase::deactivate();
00206 }
00207
00208 void SensorObserverControl::RTViewControl::setPeriod(unsigned int x) {
00209 period=x;
00210 }
00211
00212
00213
00214
00215
00216