Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

WorldStateSerializerBehavior.cc

Go to the documentation of this file.
00001 #include "WorldStateSerializerBehavior.h"
00002 #include "Shared/WorldState.h"
00003 #include "Wireless/Wireless.h"
00004 #include "Shared/Config.h"
00005 #include "Behaviors/Controller.h"
00006 #include "Events/EventRouter.h"
00007 #include "Shared/LoadSave.h"
00008 
00009 // not using REGISTER_BEHAVIOR macro so we can specify name for Aibo3D to access
00010 extern BehaviorSwitchControlBase * const autoRegisterWorldStateSerializer;
00011 BehaviorSwitchControlBase * const autoRegisterWorldStateSerializer = BehaviorBase::registerControllerEntry<WorldStateSerializerBehavior>("World State Serializer","TekkotsuMon",BEH_NONEXCLUSIVE);
00012 
00013 //! a little trick to get RobotName length under aperios, which has to use a string class instead of char*
00014 inline size_t strlen(const std::string& st) { return st.size(); }
00015 
00016 WorldStateSerializerBehavior::WorldStateSerializerBehavior()
00017 : BehaviorBase("WorldStateSerializerBehavior"), wsJoints(NULL), wsPIDs(NULL), lastProcessedTime(0)
00018 {
00019 }
00020 
00021 void WorldStateSerializerBehavior::doStart() {
00022   BehaviorBase::doStart(); // do this first
00023   
00024   const unsigned int transmitPIDSize=(NumPIDJoints*3)*LoadSave::getSerializedSize<float>()+2*LoadSave::getSerializedSize<unsigned int>();
00025   wsPIDs=wireless->socket(Socket::SOCK_STREAM, 1024, transmitPIDSize*4); // enough for 4 packets queued up
00026   wireless->setDaemon(wsPIDs);
00027   wireless->listen(wsPIDs, config->main.wspids_port);
00028 
00029   const size_t robotNameLen=strlen(RobotName)+1; //note the +1 to include '\0' at the end
00030   const size_t transmitJointsSize=(NumOutputs+NumSensors+NumButtons+NumPIDJoints)*LoadSave::getSerializedSize<float>()+6*LoadSave::getSerializedSize<unsigned int>()+robotNameLen;
00031   wsJoints=wireless->socket(Socket::SOCK_STREAM, 1024, transmitJointsSize*4); // enough for 4 packets queued up
00032   wireless->setDaemon(wsJoints);
00033   wireless->listen(wsJoints, config->main.wsjoints_port);
00034     
00035   Controller::loadGUI(getGUIType(),getGUIType(),getPort());
00036   
00037   erouter->addListener(this,EventBase::sensorEGID);
00038 }
00039 
00040 void WorldStateSerializerBehavior::doStop() {
00041   erouter->removeListener(this);
00042   
00043   Controller::closeGUI(getGUIType());
00044   
00045   wireless->setDaemon(wsJoints,false);
00046   wireless->close(wsJoints);
00047   wireless->setDaemon(wsPIDs,false);
00048   wireless->close(wsPIDs);
00049   
00050   BehaviorBase::doStop(); // do this last
00051 }
00052 
00053 void WorldStateSerializerBehavior::doEvent() {
00054   const size_t transmitPIDSize=(NumPIDJoints*3)*LoadSave::getSerializedSize<float>()+2*LoadSave::getSerializedSize<unsigned int>();
00055   if ((event->getTimeStamp() - lastProcessedTime) < config->main.worldState_interval) // not enough time has gone by
00056     return;
00057   lastProcessedTime = event->getTimeStamp();
00058   char *buf=(char*)wsPIDs->getWriteBuffer(transmitPIDSize);
00059   if(buf==NULL) {
00060     if(wireless->isConnected(wsPIDs->sock))
00061       std::cout << "WorldStateSerializer dropped pid at " << event->getTimeStamp() << std::endl;
00062   } else {
00063 #if LOADSAVE_SWAPBYTES
00064     // if we need to swap bytes, need to use this slightly slower method
00065     unsigned int remain=transmitPIDSize;
00066     LoadSave::encodeInc(state->lastSensorUpdateTime,buf,remain);
00067     LoadSave::encodeInc(NumPIDJoints,buf,remain);
00068     for(unsigned int i=0; i<NumPIDJoints; ++i)
00069       for(unsigned int j=0; j<3; ++j)
00070         LoadSave::encodeInc(state->pids[i][j],buf,remain);
00071     ASSERT(remain==0,"buffer remains");
00072     wsPIDs->write(transmitPIDSize-remain);
00073 #else
00074     // this is the original version, doesn't handle byte swapping, but faster
00075     copy(&buf,state->lastSensorUpdateTime);
00076     copy(&buf,NumPIDJoints);
00077     copy(&buf,state->pids,NumPIDJoints*3);
00078     wsPIDs->write(transmitPIDSize);
00079 #endif
00080   }
00081   
00082   const size_t robotNameLen=strlen(RobotName)+1; //note the +1 to include '\0' at the end
00083   const size_t transmitJointsSize=(NumOutputs+NumSensors+NumButtons+NumPIDJoints)*LoadSave::getSerializedSize<float>()+6*LoadSave::getSerializedSize<unsigned int>()+robotNameLen;
00084   //std::cout << "transmitting at " << event->getTimeStamp() << " with " << (wsJoints->getAvailableSendSize() / float(transmitJointsSize)) << std::endl;
00085   buf=(char*)wsJoints->getWriteBuffer(transmitJointsSize);
00086   if(buf==NULL) {
00087     if(wireless->isConnected(wsJoints->sock))
00088       std::cout << "WorldStateSerializer dropped state at " << event->getTimeStamp() << std::endl;
00089   } else {
00090 #if LOADSAVE_SWAPBYTES
00091     // if we need to swap bytes, need to use this slightly slower method
00092     unsigned int remain=transmitJointsSize;
00093     memcpy(buf,RobotName,robotNameLen);
00094     buf+=robotNameLen; remain-=robotNameLen;
00095     LoadSave::encodeInc(state->lastSensorUpdateTime,buf,remain);
00096     LoadSave::encodeInc(state->frameNumber,buf,remain);
00097     LoadSave::encodeInc(NumOutputs,buf,remain);
00098     for(unsigned int i=0; i<NumOutputs; ++i)
00099       LoadSave::encodeInc(state->outputs[i],buf,remain);
00100     LoadSave::encodeInc(NumSensors,buf,remain);
00101     for(unsigned int i=0; i<NumSensors; ++i)
00102       LoadSave::encodeInc(state->sensors[i],buf,remain);
00103     LoadSave::encodeInc(NumButtons,buf,remain);
00104     for(unsigned int i=0; i<NumButtons; ++i)
00105       LoadSave::encodeInc(state->buttons[i],buf,remain);
00106     LoadSave::encodeInc(NumPIDJoints,buf,remain);
00107     for(unsigned int i=0; i<NumPIDJoints; ++i)
00108       LoadSave::encodeInc(state->pidduties[i],buf,remain);
00109     ASSERT(remain==0,"buffer remains");
00110     wsJoints->write(transmitJointsSize-remain);
00111 #else
00112     // this is the original version, doesn't handle byte swapping, but faster
00113     copy(&buf,RobotName,robotNameLen);
00114     copy(&buf,state->lastSensorUpdateTime);
00115     copy(&buf,state->frameNumber);
00116     copy(&buf,NumOutputs);
00117     copy(&buf,state->outputs,NumOutputs);
00118     copy(&buf,NumSensors);
00119     copy(&buf,state->sensors,NumSensors);
00120     copy(&buf,NumButtons);
00121     copy(&buf,state->buttons,NumButtons);
00122     copy(&buf,NumPIDJoints);
00123     copy(&buf,state->pidduties,NumPIDJoints);
00124     wsJoints->write(transmitJointsSize);
00125 #endif
00126   }
00127 }
00128 
00129 
00130 /*! @file
00131 * @brief Implements WorldStateSerializer, which copies WorldState into a buffer for transmission over the network
00132 * @author alokl (Creator)
00133 */

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