Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

SegCam.cc

Go to the documentation of this file.
00001 #include "Shared/RobotInfo.h"
00002 #if defined(TGT_HAS_CAMERA) || defined(TGT_HAS_WEBCAM)
00003 
00004 #include "SegCam.h"
00005 #include "Wireless/Wireless.h"
00006 #include "Events/EventRouter.h"
00007 #include "Events/FilterBankEvent.h"
00008 #include "Behaviors/Controller.h"
00009 #include "Shared/ProjectInterface.h"
00010 #include "Vision/SegmentedColorGenerator.h"
00011 #include "Vision/RLEGenerator.h"
00012 #include "Shared/debuget.h"
00013 
00014 REGISTER_BEHAVIOR_MENU_OPT(SegCam,"TekkotsuMon",BEH_NONEXCLUSIVE);
00015 
00016 SegCam* SegCam::theOne=NULL;
00017 
00018 SegCam::SegCam()
00019   : CameraStreamBehavior("SegCam",visRLE), visRLE(NULL), packet(NULL), cur(NULL), avail(0), max_buf(0), lastProcessedTime(0)
00020 {
00021   ASSERT(theOne==NULL,"there was already a SegCam running!");
00022   theOne=this;
00023 }
00024 
00025 void
00026 SegCam::doStart() {
00027   BehaviorBase::doStart();
00028   setupServer();
00029   erouter->addListener(this,EventBase::visSegmentEGID,ProjectInterface::visSegmentSID,EventBase::deactivateETID);
00030   erouter->addListener(this,EventBase::visRLEEGID,ProjectInterface::visRLESID,EventBase::deactivateETID);
00031 }
00032 
00033 void
00034 SegCam::doStop() {
00035   erouter->removeListener(this);
00036   closeServer();
00037   BehaviorBase::doStop();
00038 }
00039 
00040 void
00041 SegCam::doEvent() {
00042   if(!wireless->isConnected(visRLE->sock))
00043     return;
00044   if( (config->vision.segcam.transport==0 && visRLE->getTransport()==Socket::SOCK_STREAM)
00045      || (config->vision.segcam.transport==1 && visRLE->getTransport()==Socket::SOCK_DGRAM) ) {
00046     closeServer();
00047     setupServer();
00048     return;
00049   }
00050   try {
00051     const FilterBankEvent* fbke=dynamic_cast<const FilterBankEvent*>(event);
00052     if(fbke==NULL) {
00053       CameraStreamBehavior::doEvent();
00054       return;
00055     }
00056     if ((get_time() - lastProcessedTime) < config->vision.segcam.interval) // not enough time has gone by
00057       return;
00058     if(config->vision.segcam.compression==Config::vision_config::SegCamConfig::COMPRESS_NONE && event->getGeneratorID()==EventBase::visSegmentEGID) {
00059       if(!writeSeg(*fbke)) {
00060         if(packet!=NULL) {
00061           cur=packet;
00062           closePacket();
00063         }
00064         //error message should already have been reported
00065         //ASSERTRET(succ,"serialization failed");
00066       }
00067     }
00068     if(config->vision.segcam.compression==Config::vision_config::SegCamConfig::COMPRESS_RLE && event->getGeneratorID()==EventBase::visRLEEGID) {
00069       if(!writeRLE(*fbke)) {
00070         if(packet!=NULL) {
00071           cur=packet;
00072           closePacket();
00073         }
00074         //error message should already have been reported
00075         //ASSERTRET(succ,"serialization failed");
00076       }
00077     }
00078   } catch(...) {
00079     if(packet!=NULL) {
00080       cur=packet;
00081       closePacket();
00082     }
00083     // typically this is a per-frame recurring error, so let's just stop now
00084     serr->printf("%s: exception generated during image serialization, stopping stream.\n",getName().c_str());
00085     stop();
00086     throw;
00087   }
00088 }
00089 
00090 void
00091 SegCam::closeServer() {
00092   if(wireless->isConnected(visRLE->sock))
00093     sendCloseConnectionPacket();
00094   Controller::closeGUI("SegVisionGUI");
00095   
00096   // this could be considered a bug in our wireless - if we don't setDaemon(...,false)
00097   // it will try to listen again even though we explicitly closed the server socket...
00098   wireless->setDaemon(visRLE,false);
00099   wireless->close(visRLE->sock);
00100 }
00101 
00102 void
00103 SegCam::setupServer() {
00104   std::vector<std::string> args;
00105   args.push_back("rle");
00106   char port[50];
00107   snprintf(port,50,"%d",*config->vision.segcam.port);
00108   args.push_back(port);
00109   if(config->vision.segcam.transport==0) {
00110     max_buf=UDP_WIRELESS_BUFFER_SIZE;
00111     visRLE=wireless->socket(Socket::SOCK_DGRAM, 1024, max_buf);
00112     args.push_back("udp");
00113   } else if(config->vision.segcam.transport==1) {
00114     max_buf=TCP_WIRELESS_BUFFER_SIZE;
00115     visRLE=wireless->socket(Socket::SOCK_STREAM, 1024, max_buf);
00116     args.push_back("tcp");
00117   } else {
00118     serr->printf("ERROR: Invalid Config::vision.segcam.transport: %d\n",*config->vision.segcam.transport);
00119     return;
00120   }
00121   wireless->setDaemon(visRLE,true);
00122   wireless->setReceiver(visRLE,networkCallback);
00123   wireless->listen(visRLE,config->vision.segcam.port);
00124   
00125   Controller::loadGUI("org.tekkotsu.mon.VisionGUI","SegVisionGUI",config->vision.segcam.port,args);
00126 }
00127 
00128 bool
00129 SegCam::openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer) {
00130   if(packet!=NULL)
00131     return false;
00132 
00133   avail=max_buf-1; //not sure why -1, but Alok had it, so i will too
00134   ASSERT(cur==NULL,"cur non-NULL");
00135   cur=NULL;
00136   char * buf=packet=(char*)visRLE->getWriteBuffer(avail);
00137   ASSERT(packet!=NULL,"dropped frame, network bandwidth is saturated (reduce frame rate or size)");
00138   if(packet==NULL)
00139     return false;
00140   
00141   if(!LoadSave::encodeInc("TekkotsuImage",buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00142   if(!LoadSave::encodeInc(Config::vision_config::ENCODE_SINGLE_CHANNEL,buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00143   if(!LoadSave::encodeInc(Config::vision_config::SegCamConfig::COMPRESS_RLE,buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00144 
00145   if(!LoadSave::encodeInc(fbkgen.getWidth(layer),buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00146   if(!LoadSave::encodeInc(fbkgen.getHeight(layer),buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00147   if(!LoadSave::encodeInc(time,buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00148   if(!LoadSave::encodeInc(fbkgen.getFrameNumber(),buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00149 
00150   cur=buf;
00151   return true;
00152 }
00153 
00154 bool
00155 SegCam::writeRLE(const FilterBankEvent& e) {
00156   FilterBankGenerator& fbkgen=*e.getSource();
00157 
00158   unsigned int layer=fbkgen.getNumLayers()-1-config->vision.segcam.skip;
00159   openPacket(fbkgen,e.getTimeStamp(),layer);
00160   if(cur==NULL) //error should have been displayed by openPacket
00161     return false;
00162   
00163   RLEGenerator * rle = dynamic_cast<RLEGenerator*>(&fbkgen);
00164   ASSERTRETVAL(rle!=NULL,"fbkgen isn't an RLEGenerator",false);
00165 
00166   rle->selectSaveImage(layer,config->vision.segcam.channel);
00167   if(!LoadSave::checkInc(rle->saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.segcam.transport to TCP and reopen seg cam")) return false;
00168   
00169   // send out the color map ourselves (since RLE compression doesn't have a concept of color)
00170   const SegmentedColorGenerator * seg = dynamic_cast<const SegmentedColorGenerator*>(rle->getSourceGenerator());
00171   ASSERTRETVAL(seg!=NULL,"RLE's source is not a SegmentedColorGenerator - how do i know what the colors are?",false);
00172   if(!seg->encodeColorsInc(cur,avail)) return false;
00173 
00174   closePacket();
00175 
00176   return true;
00177 }
00178 
00179 bool
00180 SegCam::writeSeg(const FilterBankEvent& e) {
00181   FilterBankGenerator& fbkgen=*e.getSource();
00182 
00183   unsigned int layer=fbkgen.getNumLayers()-1-config->vision.segcam.skip;
00184   openPacket(fbkgen,e.getTimeStamp(),layer);
00185   if(cur==NULL) //error should have been displayed by openPacket
00186     return false;
00187   
00188   fbkgen.selectSaveImage(layer,config->vision.segcam.channel);
00189   if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.segcam.transport to TCP and reopen seg cam")) return false;
00190   
00191   closePacket();
00192 
00193   return true;
00194 }
00195 
00196 void
00197 SegCam::closePacket() {
00198   if(packet==NULL)
00199     return;
00200   visRLE->write(cur-packet);
00201   packet=cur=NULL;
00202   avail=0;
00203   lastProcessedTime = get_time();
00204 }
00205 
00206 bool
00207 SegCam::sendCloseConnectionPacket() {
00208   char msg[]="CloseConnection";
00209   unsigned int len=strlen(msg)+LoadSave::stringpad;
00210   char * buf = (char*)visRLE->getWriteBuffer(len);
00211   if(buf==NULL) {
00212     std::cerr << "Could not get buffer for closing packet" << std::endl;
00213     return false;
00214   }
00215   unsigned int used=LoadSave::encode(msg,buf,len);
00216   if(used==0)
00217     std::cerr << "Could not write close packet" << std::endl;
00218   visRLE->write(used);
00219   return true;
00220 }
00221 
00222 #endif
00223 
00224 /*! @file
00225  * @brief Implements SegCam, which forwards segmented images from camera over wireless
00226  * @author ejt (Creator)
00227  */
00228 

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