Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

RawCam.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 "RawCam.h"
00005 #include "Wireless/Wireless.h"
00006 #include "Events/EventRouter.h"
00007 #include "Vision/RawCameraGenerator.h"
00008 #include "Vision/JPEGGenerator.h"
00009 #include "Events/FilterBankEvent.h"
00010 #include "Behaviors/Controller.h"
00011 #include "Shared/ProjectInterface.h"
00012 #include "Shared/debuget.h"
00013 
00014 REGISTER_BEHAVIOR_MENU_OPT(RawCam,"TekkotsuMon",BEH_NONEXCLUSIVE);
00015 
00016 RawCam* RawCam::theOne=NULL;
00017 
00018 RawCam::RawCam()
00019   : CameraStreamBehavior("RawCam",visRaw), visRaw(NULL), packet(NULL), cur(NULL), avail(0), max_buf(0), lastProcessedTime(0)
00020 {
00021   ASSERT(theOne==NULL,"there was already a RawCam running!");
00022   theOne=this;
00023 }
00024 
00025 void
00026 RawCam::doStart() {
00027   BehaviorBase::doStart();
00028   setupServer();
00029   erouter->addListener(this,EventBase::visRawCameraEGID, ProjectInterface::visRawCameraSID,EventBase::deactivateETID);
00030   erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visColorJPEGSID,EventBase::deactivateETID);
00031   erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visGrayscaleJPEGSID,EventBase::deactivateETID);
00032 }
00033 
00034 void
00035 RawCam::doStop() {
00036   erouter->removeListener(this);
00037   closeServer();
00038   BehaviorBase::doStop();
00039 }
00040 
00041 void
00042 RawCam::doEvent() {
00043   if(!wireless->isConnected(visRaw->sock))
00044     return;
00045   if((config->vision.rawcam.transport==0 && visRaw->getTransport()==Socket::SOCK_STREAM)
00046      || (config->vision.rawcam.transport==1 && visRaw->getTransport()==Socket::SOCK_DGRAM)) {
00047     //reset the socket
00048     closeServer();
00049     setupServer();
00050     return;
00051   }
00052   try {
00053     const FilterBankEvent* fbke=dynamic_cast<const FilterBankEvent*>(event);
00054     if(fbke==NULL) {
00055       CameraStreamBehavior::doEvent();
00056       return;
00057     }
00058     if((get_time() - lastProcessedTime) < config->vision.rawcam.interval) {// not enough time has gone by
00059       return;
00060     }
00061     /* // turning these off enables individual channel compression
00062       if(config->vision.rawcam.compression==Config::vision_config::COMPRESS_NONE && event->getGeneratorID()!=EventBase::visRawCameraEGID)
00063       return;
00064       if(config->vision.rawcam.compression==Config::vision_config::COMPRESS_JPEG && event->getGeneratorID()!=EventBase::visJPEGEGID)
00065       return; */
00066     if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_COLOR) {
00067       //std::cout << "Encode_Color called" << std::endl;
00068       if(!writeColor(*fbke)) {
00069         if(packet) { //packet was opened, need to close it
00070           cur=packet; // don't send anything
00071           closePacket();
00072         }
00073         //error message should already be printed in writeColor
00074         //ASSERTRET(false,"serialization failed");
00075       }
00076     } else if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
00077       //std::cout << "Encode_Single_channel called " << std::endl;
00078       if(!writeSingleChannel(*fbke)) {
00079         if(packet) { //packet was opened, need to close it
00080           cur=packet; // don't send anything
00081           closePacket();
00082         }
00083         //error message should already be printed in writeSingleChannel
00084         //ASSERTRET(false,"serialization failed");
00085       }
00086     } 
00087           else {
00088       serr->printf("%s: Bad rawcam.encoding setting\n",getName().c_str());
00089     }
00090   } catch(...) {
00091     if(packet) { //packet was opened, need to close it
00092       cur=packet; // don't send anything
00093       closePacket();
00094     }
00095     // typically this is a per-frame recurring error, so let's just stop now
00096     serr->printf("%s: exception generated during image serialization, stopping stream.\n",getName().c_str());
00097     stop();
00098     throw;
00099   }
00100 }
00101 
00102 unsigned int RawCam::getSourceLayer(unsigned int chan, unsigned int numLayers) {
00103   if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
00104     if(config->vision.rawcam.channel!=(int)chan)
00105       return -1U;
00106     return numLayers-1-config->vision.rawcam.y_skip;
00107   }
00108   // must be full-color
00109   switch(chan) {
00110   case RawCameraGenerator::CHAN_Y:
00111     if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_JPEG) {
00112       if(config->vision.rawcam.y_skip-config->vision.rawcam.uv_skip == 1)
00113         return numLayers-1-config->vision.rawcam.uv_skip;
00114     }
00115     return numLayers-1-config->vision.rawcam.y_skip;
00116   case RawCameraGenerator::CHAN_U:
00117   case RawCameraGenerator::CHAN_V:
00118     if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_JPEG) {
00119       if(config->vision.rawcam.uv_skip-config->vision.rawcam.y_skip == 1)
00120         return numLayers-1-config->vision.rawcam.y_skip;
00121     }
00122     return numLayers-1-config->vision.rawcam.uv_skip;
00123   default: // other channels, i.e. Y-derivatives
00124     return -1U;
00125   }
00126 }
00127 unsigned int RawCam::getSourceYLayer(unsigned int numLayers) {
00128   return getSourceLayer(RawCameraGenerator::CHAN_Y,numLayers);
00129 }
00130 unsigned int RawCam::getSourceULayer(unsigned int numLayers) {
00131   return getSourceLayer(RawCameraGenerator::CHAN_U,numLayers);
00132 }
00133 unsigned int RawCam::getSourceVLayer(unsigned int numLayers) {
00134   return getSourceLayer(RawCameraGenerator::CHAN_V,numLayers);
00135 }
00136 
00137 void
00138 RawCam::closeServer() {
00139   if(wireless->isConnected(visRaw->sock))
00140     sendCloseConnectionPacket();
00141   Controller::closeGUI("RawVisionGUI");
00142   
00143   // this could be considered a bug in our wireless - if we don't setDaemon(...,false)
00144   // it will try to listen again even though we explicitly closed the server socket...
00145   wireless->setDaemon(visRaw,false);
00146   wireless->close(visRaw->sock);
00147 }
00148 
00149 void
00150 RawCam::setupServer() {
00151   std::vector<std::string> args;
00152   args.push_back("raw");
00153   char port[50];
00154   snprintf(port,50,"%d",*config->vision.rawcam.port);
00155   args.push_back(port);
00156   if(config->vision.rawcam.transport==0) {
00157     max_buf=UDP_WIRELESS_BUFFER_SIZE;
00158     visRaw=wireless->socket(Socket::SOCK_DGRAM, 1024, max_buf);
00159     args.push_back("udp");
00160   } else if(config->vision.rawcam.transport==1) {
00161     max_buf=TCP_WIRELESS_BUFFER_SIZE;
00162     visRaw=wireless->socket(Socket::SOCK_STREAM, 1024, max_buf);
00163     args.push_back("tcp");
00164   } else {
00165     serr->printf("ERROR: Invalid Config::vision.rawcam.transport: %d\n",*config->vision.rawcam.transport);
00166     return;
00167   }
00168   wireless->setDaemon(visRaw,true);
00169   wireless->setReceiver(visRaw,networkCallback);
00170   wireless->listen(visRaw,config->vision.rawcam.port);
00171   
00172   Controller::loadGUI("org.tekkotsu.mon.VisionGUI","RawVisionGUI",*config->vision.rawcam.port,args);
00173 }
00174 
00175 bool
00176 RawCam::openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer) {
00177   if(packet!=NULL)
00178     return false;
00179 
00180   avail=max_buf-1; //not sure why -1, but Alok had it, so i will too
00181   ASSERT(cur==NULL,"cur non-NULL");
00182   cur=NULL;
00183   char * buf=packet=(char*)visRaw->getWriteBuffer(avail);
00184   ASSERT(packet!=NULL,"dropped frame, network bandwidth is saturated (reduce frame rate or size)");
00185   if(packet==NULL)
00186     return false;
00187   
00188   if(!LoadSave::encodeInc("TekkotsuImage",buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00189   if(!LoadSave::encodeInc(*config->vision.rawcam.encoding,buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00190   if(!LoadSave::encodeInc(*config->vision.rawcam.compression,buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00191   if(!LoadSave::encodeInc(fbkgen.getWidth(layer),buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00192   if(!LoadSave::encodeInc(fbkgen.getHeight(layer),buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00193   if(!LoadSave::encodeInc(time,buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00194   if(!LoadSave::encodeInc(fbkgen.getFrameNumber(),buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00195 
00196   cur=buf;
00197   return true;
00198 }
00199 
00200 bool
00201 RawCam::writeColor(const FilterBankEvent& e) {
00202   FilterBankGenerator& fbkgen=*e.getSource();
00203 
00204   unsigned int y_layer=fbkgen.getNumLayers()-1-config->vision.rawcam.y_skip;
00205   unsigned int uv_layer=fbkgen.getNumLayers()-1-config->vision.rawcam.uv_skip;
00206 
00207   if(config->vision.rawcam.channel==-1) {
00208     if((e.getGeneratorID()==EventBase::visRawCameraEGID && config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_NONE)
00209        || (e.getGeneratorID()==EventBase::visJPEGEGID && config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_JPEG)) {
00210       if(const JPEGGenerator* jgen=dynamic_cast<const JPEGGenerator*>(&fbkgen))
00211         if(jgen->getCurrentSourceFormat()==JPEGGenerator::SRC_COLOR)
00212           return true;
00213       openPacket(fbkgen,e.getTimeStamp(),uv_layer);
00214       if(cur==NULL) //error should have been displayed by openPacket
00215         return false;
00216       
00217       if(!LoadSave::encodeInc("FbkImage",cur,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00218       if(!LoadSave::encodeInc(0,cur,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00219       if(!LoadSave::encodeInc(0,cur,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00220       if(!LoadSave::encodeInc(-1,cur,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00221       if(!LoadSave::encodeInc(RawCameraGenerator::CHAN_Y,cur,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00222       if(!LoadSave::encodeInc("blank",cur,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00223 
00224       fbkgen.selectSaveImage(uv_layer,RawCameraGenerator::CHAN_U);
00225       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00226       
00227       fbkgen.selectSaveImage(uv_layer,RawCameraGenerator::CHAN_V);
00228       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00229 
00230       closePacket();
00231     }
00232     return true;
00233   }
00234 
00235   unsigned int big_layer=y_layer;
00236   unsigned int small_layer=uv_layer;
00237   if(y_layer<uv_layer) { 
00238     big_layer=uv_layer;
00239     small_layer=y_layer;
00240   }
00241   if(const JPEGGenerator* jgen=dynamic_cast<const JPEGGenerator*>(&fbkgen)) {
00242     if(config->vision.rawcam.compression!=Config::vision_config::RawCamConfig::COMPRESS_JPEG)
00243       return true;
00244     if(jgen->getCurrentSourceFormat()==JPEGGenerator::SRC_COLOR && big_layer-small_layer<2) {
00245       openPacket(fbkgen,e.getTimeStamp(),big_layer);
00246       if(cur==NULL) //error should have been displayed by openPacket
00247         return false;
00248       
00249       fbkgen.selectSaveImage(big_layer,0);
00250       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00251       
00252       closePacket();
00253     } else if(jgen->getCurrentSourceFormat()==JPEGGenerator::SRC_GRAYSCALE && big_layer-small_layer>=2) {
00254       bool opened=openPacket(fbkgen,e.getTimeStamp(),big_layer);
00255       if(cur==NULL) //error should have been displayed by openPacket
00256         return false;
00257       
00258       if(big_layer==y_layer) {
00259         fbkgen.selectSaveImage(y_layer,RawCameraGenerator::CHAN_Y);
00260         if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00261       } else {
00262         fbkgen.selectSaveImage(uv_layer,RawCameraGenerator::CHAN_U);
00263         if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00264         fbkgen.selectSaveImage(uv_layer,RawCameraGenerator::CHAN_V);
00265         if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00266       }
00267       
00268       if(!opened)
00269         closePacket();
00270     }
00271   } else {
00272     bool opened=false;
00273     
00274     if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_NONE || (big_layer-small_layer>=2 && big_layer==uv_layer)) {
00275       opened=openPacket(fbkgen,e.getTimeStamp(),big_layer);
00276       if(cur==NULL) //error should have been displayed by openPacket
00277         return false;
00278       fbkgen.selectSaveImage(y_layer,RawCameraGenerator::CHAN_Y);
00279       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00280     }
00281     
00282     if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_NONE || (big_layer-small_layer>=2 && big_layer==y_layer)) {
00283       opened=openPacket(fbkgen,e.getTimeStamp(),big_layer);
00284       if(cur==NULL) //error should have been displayed by openPacket
00285         return false;
00286       fbkgen.selectSaveImage(uv_layer,RawCameraGenerator::CHAN_U);
00287       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00288       fbkgen.selectSaveImage(uv_layer,RawCameraGenerator::CHAN_V);
00289       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00290     }
00291     
00292     if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_NONE || !opened)
00293       closePacket();
00294   }
00295   
00296   return true;
00297 }
00298 
00299 bool
00300 RawCam::writeSingleChannel(const FilterBankEvent& e) {
00301   FilterBankGenerator& fbkgen=*e.getSource();
00302   if( (config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_NONE && e.getGeneratorID()==EventBase::visRawCameraEGID)
00303       || (config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_JPEG && e.getGeneratorID()==EventBase::visJPEGEGID) )
00304     {
00305       if(const JPEGGenerator * jgen=dynamic_cast<const JPEGGenerator*>(&fbkgen))
00306         if(jgen->getCurrentSourceFormat()!=JPEGGenerator::SRC_GRAYSCALE)
00307           return true;
00308       unsigned int layer=fbkgen.getNumLayers()-1-config->vision.rawcam.y_skip;
00309       
00310       openPacket(fbkgen,e.getTimeStamp(),layer);
00311       if(cur==NULL) //error should have been displayed by openPacket
00312         return false;
00313       
00314       fbkgen.selectSaveImage(layer,config->vision.rawcam.channel);
00315       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.rawcam.transport to TCP and reopen raw cam")) return false;
00316       
00317       closePacket();
00318     }
00319   return true;
00320 }
00321 
00322 void
00323 RawCam::closePacket() {
00324   if(packet==NULL)
00325     return;
00326   visRaw->write(cur-packet);
00327   packet=cur=NULL;
00328   avail=0;
00329   lastProcessedTime = get_time();
00330 }
00331 
00332 bool
00333 RawCam::sendCloseConnectionPacket() {
00334   char msg[]="CloseConnection";
00335   unsigned int len=strlen(msg)+LoadSave::stringpad;
00336   char * buf = (char*)visRaw->getWriteBuffer(len);
00337   if(buf==NULL) {
00338     std::cerr << "Could not get buffer for closing packet" << std::endl;
00339     return false;
00340   }
00341   unsigned int used=LoadSave::encode(msg,buf,len);
00342   if(used==0)
00343     std::cerr << "Could not write close packet" << std::endl;
00344   visRaw->write(used);
00345   return true;
00346 }
00347 
00348 #endif
00349 
00350 /*! @file
00351  * @brief Implements RawCam, which forwards images from camera over wireless
00352  * @author ejt (Creator)
00353  */
00354 

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:50 2012 by Doxygen 1.6.3