Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

DepthCam.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 "DepthCam.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(DepthCam,"TekkotsuMon",BEH_NONEXCLUSIVE);
00015 
00016 DepthCam* DepthCam::theOne=NULL;
00017 
00018 DepthCam::DepthCam()
00019   : CameraStreamBehavior("DepthCam",visDepth), visDepth(NULL), packet(NULL), cur(NULL), avail(0), max_buf(0), lastProcessedTime(0)
00020 {
00021   ASSERT(theOne==NULL,"there was already a DepthCam running!");
00022   theOne=this;
00023 }
00024 
00025 void
00026 DepthCam::doStart() {
00027   BehaviorBase::doStart();
00028   setupServer();
00029   erouter->addListener(this,EventBase::visRawDepthEGID, ProjectInterface::visRawDepthSID, EventBase::deactivateETID);
00030   // *** does this stuff below work for depth?  or is it hard-coded to the rgb image?
00031   erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visColorJPEGSID,EventBase::deactivateETID);
00032   erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visGrayscaleJPEGSID,EventBase::deactivateETID);
00033 }
00034 
00035 void
00036 DepthCam::doStop() {
00037   erouter->removeListener(this);
00038   closeServer();
00039   BehaviorBase::doStop();
00040 }
00041 
00042 void
00043 DepthCam::doEvent() {
00044   if(!wireless->isConnected(visDepth->sock))
00045     return;
00046   if((config->vision.depthcam.transport==0 && visDepth->getTransport()==Socket::SOCK_STREAM)
00047      || (config->vision.depthcam.transport==1 && visDepth->getTransport()==Socket::SOCK_DGRAM)) {
00048     //reset the socket
00049     closeServer();
00050     setupServer();
00051     return;
00052   }
00053   try {
00054     const FilterBankEvent* fbke=dynamic_cast<const FilterBankEvent*>(event);
00055     if(fbke==NULL) {
00056       CameraStreamBehavior::doEvent();
00057       return;
00058     }
00059     if((get_time() - lastProcessedTime) < config->vision.depthcam.interval) {// not enough time has gone by
00060       return;
00061     }
00062     /* // turning these off enables individual channel compression
00063       if(config->vision.depthcam.compression==Config::vision_config::COMPRESS_NONE && event->getGeneratorID()!=EventBase::visRawCameraEGID)
00064       return;
00065       if(config->vision.depthcam.compression==Config::vision_config::COMPRESS_JPEG && event->getGeneratorID()!=EventBase::visJPEGEGID)
00066       return; */
00067   
00068     if(!writeDepth(*fbke)) {
00069             if(packet) {
00070                     cur=packet;
00071                     closePacket();
00072       }
00073     }
00074   } catch(...) {
00075     if(packet) { //packet was opened, need to close it
00076       cur=packet; // don't send anything
00077       closePacket();
00078     }
00079     // typically this is a per-frame recurring error, so let's just stop now
00080     serr->printf("%s: exception generated during image serialization, stopping stream.\n",getName().c_str());
00081     stop();
00082     throw;
00083   }
00084 }
00085 
00086 void
00087 DepthCam::closeServer() {
00088   if(wireless->isConnected(visDepth->sock))
00089     sendCloseConnectionPacket();
00090   Controller::closeGUI("DepthVisionGUI");
00091   
00092   // this could be considered a bug in our wireless - if we don't setDaemon(...,false)
00093   // it will try to listen again even though we explicitly closed the server socket...
00094   wireless->setDaemon(visDepth,false);
00095   wireless->close(visDepth->sock);
00096 }
00097 
00098 void
00099 DepthCam::setupServer() {
00100   std::vector<std::string> args;
00101   args.push_back("depth");
00102   char port[50];
00103   snprintf(port,50,"%d",*config->vision.depthcam.port);
00104   args.push_back(port);
00105   if(config->vision.depthcam.transport==0) {
00106     max_buf=UDP_WIRELESS_BUFFER_SIZE;
00107     visDepth=wireless->socket(Socket::SOCK_DGRAM, 1024, max_buf);
00108     args.push_back("udp");
00109   } else if(config->vision.depthcam.transport==1) {
00110     max_buf=TCP_WIRELESS_BUFFER_SIZE;
00111     visDepth=wireless->socket(Socket::SOCK_STREAM, 1024, max_buf);
00112     args.push_back("tcp");
00113   } else {
00114     serr->printf("ERROR: Invalid Config::vision.depthcam.transport: %d\n",*config->vision.depthcam.transport);
00115     return;
00116   }
00117   wireless->setDaemon(visDepth,true);
00118   wireless->setReceiver(visDepth,networkCallback);
00119   wireless->listen(visDepth,config->vision.depthcam.port);
00120   Controller::loadGUI("org.tekkotsu.mon.VisionGUI","DepthVisionGUI",*config->vision.depthcam.port,args);
00121 }
00122 bool
00123 DepthCam::openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer) {
00124   if(packet!=NULL)
00125     return false;
00126 
00127   avail=max_buf-1; //not sure why -1, but Alok had it, so i will too
00128   ASSERT(cur==NULL,"cur non-NULL");
00129   cur=NULL;
00130   char * buf=packet=(char*)visDepth->getWriteBuffer(avail);
00131   ASSERT(packet!=NULL,"dropped frame, network bandwidth is saturated (reduce frame rate or size)");
00132   if(packet==NULL)
00133     return false;
00134   
00135   if(!LoadSave::encodeInc("TekkotsuImage",buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00136   if(!LoadSave::encodeInc(Config::vision_config::ENCODE_DEPTH,buf,avail,"ran out of space %s:%u\n",__FILE__,__LINE__)) return false;;
00137   if(!LoadSave::encodeInc(*config->vision.depthcam.compression,buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00138   if(!LoadSave::encodeInc(fbkgen.getWidth(layer),buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00139   if(!LoadSave::encodeInc(fbkgen.getHeight(layer),buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00140   if(!LoadSave::encodeInc(time,buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00141   if(!LoadSave::encodeInc(fbkgen.getFrameNumber(),buf,avail,"ran out of space %s:%un",__FILE__,__LINE__)) return false;;
00142 
00143   cur=buf;
00144   return true;
00145 }
00146 bool
00147 DepthCam::writeDepth(const FilterBankEvent& e) {
00148   FilterBankGenerator& fbkgen=*e.getSource();
00149 
00150   unsigned int y0_layer=fbkgen.getNumLayers()-1-config->vision.depthcam.y0_skip;
00151   unsigned int y1_layer=fbkgen.getNumLayers()-1-config->vision.depthcam.y1_skip;
00152   unsigned int big_layer=y0_layer;
00153   unsigned int small_layer=y1_layer;
00154   if(y0_layer<y1_layer) { 
00155     big_layer=y1_layer;
00156     small_layer=y0_layer;
00157   }
00158   if(const JPEGGenerator* jgen=dynamic_cast<const JPEGGenerator*>(&fbkgen)) {
00159     if(config->vision.depthcam.compression!=Config::vision_config::DepthCamConfig::COMPRESS_JPEG)
00160       return true;
00161     if(jgen->getCurrentSourceFormat()==JPEGGenerator::SRC_COLOR && big_layer-small_layer<2) {
00162       openPacket(fbkgen,e.getTimeStamp(),big_layer);
00163       if(cur==NULL) //error should have been displayed by openPacket
00164         return false;
00165       
00166       fbkgen.selectSaveImage(big_layer,0);
00167       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.depthcam.transport to TCP and reopen depth cam")) return false;
00168       
00169       closePacket();
00170     } else if(jgen->getCurrentSourceFormat()==JPEGGenerator::SRC_GRAYSCALE && big_layer-small_layer>=2) {
00171       bool opened=openPacket(fbkgen,e.getTimeStamp(),big_layer);
00172       if(cur==NULL) //error should have been displayed by openPacket
00173         return false;
00174       
00175       if(big_layer==y0_layer) {
00176         fbkgen.selectSaveImage(y0_layer,RawCameraGenerator::CHAN_Y);
00177         if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.depthcam.transport to TCP and reopen depth cam")) return false;
00178       } else {
00179         fbkgen.selectSaveImage(y1_layer,RawCameraGenerator::CHAN_U);
00180         if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.depthcam.transport to TCP and reopen depth cam")) return false;
00181       }
00182       
00183       if(!opened)
00184         closePacket();
00185     }
00186   } else { // not a JPEG generator
00187     bool opened=false;
00188     
00189     if(config->vision.depthcam.compression==Config::vision_config::DepthCamConfig::COMPRESS_NONE || (big_layer-small_layer>=2 && big_layer==y1_layer)) {
00190       opened=openPacket(fbkgen,e.getTimeStamp(),big_layer);
00191       if(cur==NULL) //error should have been displayed by openPacket
00192         return false;
00193       fbkgen.selectSaveImage(y0_layer,RawCameraGenerator::CHAN_Y);
00194       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.depthcam.transport to TCP and reopen depth cam")) return false;
00195     }
00196     
00197     if(config->vision.depthcam.compression==Config::vision_config::DepthCamConfig::COMPRESS_NONE || (big_layer-small_layer>=2 && big_layer==y0_layer)) {
00198       opened=openPacket(fbkgen,e.getTimeStamp(),big_layer);
00199       if(cur==NULL) //error should have been displayed by openPacket
00200         return false;
00201       fbkgen.selectSaveImage(y1_layer,RawCameraGenerator::CHAN_U);
00202       if(!LoadSave::checkInc(fbkgen.saveBuffer(cur,avail),cur,avail,"image size too large -- may need to set Config::vision.depthcam.transport to TCP and reopen depth cam")) return false;
00203     }
00204     
00205     if(config->vision.depthcam.compression==Config::vision_config::DepthCamConfig::COMPRESS_NONE || !opened)
00206       closePacket();
00207   }
00208   
00209   return true;
00210 }
00211 
00212 void DepthCam::closePacket() {
00213   if(packet==NULL)
00214     return;
00215   visDepth->write(cur-packet);
00216   packet=cur=NULL;
00217   avail=0;
00218   lastProcessedTime = get_time();
00219 }
00220 
00221 bool DepthCam::sendCloseConnectionPacket() {
00222   char msg[]="CloseConnection";
00223   unsigned int len=strlen(msg)+LoadSave::stringpad;
00224   char * buf = (char*)visDepth->getWriteBuffer(len);
00225   if(buf==NULL) {
00226     std::cerr << "Could not get buffer for closing packet" << std::endl;
00227     return false;
00228   }
00229   unsigned int used=LoadSave::encode(msg,buf,len);
00230   if(used==0)
00231     std::cerr << "Could not write close packet" << std::endl;
00232   visDepth->write(used);
00233   return true;
00234 }
00235 
00236 #endif
00237 
00238 /*! @file
00239  * @brief Implements DepthCam, which forwards images from camera over wireless
00240  * @author ejt (Creator)
00241  */

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