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
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) {
00059 return;
00060 }
00061
00062
00063
00064
00065
00066 if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_COLOR) {
00067
00068 if(!writeColor(*fbke)) {
00069 if(packet) {
00070 cur=packet;
00071 closePacket();
00072 }
00073
00074
00075 }
00076 } else if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
00077
00078 if(!writeSingleChannel(*fbke)) {
00079 if(packet) {
00080 cur=packet;
00081 closePacket();
00082 }
00083
00084
00085 }
00086 }
00087 else {
00088 serr->printf("%s: Bad rawcam.encoding setting\n",getName().c_str());
00089 }
00090 } catch(...) {
00091 if(packet) {
00092 cur=packet;
00093 closePacket();
00094 }
00095
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
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:
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
00144
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;
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)
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)
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)
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)
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)
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)
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
00351
00352
00353
00354