Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CameraBehavior.cc

Go to the documentation of this file.
00001 #include "CameraBehavior.h"
00002 #include "Events/EventRouter.h"
00003 #include "Events/TextMsgEvent.h"
00004 #include "Shared/RobotInfo.h"
00005 #include "Wireless/Socket.h"
00006 #include "Shared/WorldState.h"
00007 #include "Sound/SoundManager.h"
00008 #include "Shared/Config.h"
00009 #include "Shared/ProjectInterface.h"
00010 #include "Motion/MMAccessor.h"
00011 #include "IPC/SharedObject.h"
00012 
00013 #include "Vision/FilterBankGenerator.h"
00014 #include "Vision/RawCameraGenerator.h"
00015 #include "Vision/InterleavedYUVGenerator.h"
00016 #include "Vision/JPEGGenerator.h"
00017 #include "Vision/PNGGenerator.h"
00018 
00019 #include "Shared/RobotInfo.h"
00020 #ifdef TGT_HAS_LEDS
00021 #  include "Motion/LedMC.h"
00022 #endif
00023 
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <unistd.h>
00027 #include <dirent.h>
00028 
00029 REGISTER_BEHAVIOR_MENU_OPT(CameraBehavior,"Background Behaviors",BEH_NONEXCLUSIVE);
00030 
00031 void
00032 CameraBehavior::doStart() {
00033   BehaviorBase::doStart();
00034   if(capabilities.findButtonOffset("HeadBut")!=-1U) // if there is a head button, use it for the trigger
00035     camera_click.setSourceID(capabilities.getButtonOffset("HeadBut"));
00036   // (otherwise, just stick with the default button 0 as set in camera_click constructor)
00037   initIndex();
00038   sndman->loadFile("camera.wav");
00039 #ifdef TGT_HAS_LEDS
00040   ledID=motman->addPersistentMotion(SharedObject<LedMC>());
00041 #endif
00042   erouter->addListener(this,camera_click);
00043   erouter->addListener(this,EventBase::textmsgEGID);
00044 }
00045 
00046 void CameraBehavior::doStop() {
00047   erouter->removeListener(this);
00048   sndman->releaseFile("camera.wav");
00049   motman->removeMotion(ledID);
00050   BehaviorBase::doStop();
00051 }
00052 
00053   
00054 /*! The format used depends on the current config settings.  If JPEG
00055  *  is the current choice, then a JPEG file will be written.
00056  *  Otherwise, RawCameraGenerator::saveFile() will be called.
00057  */
00058 void
00059 CameraBehavior::doEvent() {
00060   if(event->getGeneratorID()==EventBase::textmsgEGID) {
00061     const TextMsgEvent * txt=dynamic_cast<const TextMsgEvent*>(event);
00062     if(txt==NULL || txt->getText()!="camera")
00063       return;
00064   } else if(event->shorterThan(camera_click))
00065     return;
00066 
00067   {
00068 #if defined(TGT_ERS7) || defined(TGT_ERS210) || defined(TGT_ERS220) || defined(TGT_ERS2xx)
00069     MMAccessor<LedMC> leds(ledID);
00070     leds->cset(FaceLEDMask,2.0f/3.0f);
00071     leds->set(TopBrLEDMask,1);
00072 #elif defined(TGT_HAS_LEDS)
00073     MMAccessor<LedMC> leds(ledID);
00074     leds->set(AllLEDMask,1);
00075 #endif
00076   }
00077 
00078   if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_NONE) {
00079     //this is our own odd little format, would be nice to save a TIFF or something instead
00080 
00081     // open file
00082     FILE * f=openNextFile(".raw");
00083     if(f==NULL) //error message already displayed in openNextFile()
00084       return;
00085 
00086     //! write actual image data
00087     if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_COLOR) {
00088       FilterBankGenerator * gen=ProjectInterface::defInterleavedYUVGenerator; // just an alias for readability
00089       gen->selectSaveImage(ProjectInterface::doubleLayer,InterleavedYUVGenerator::CHAN_YUV);
00090       unsigned int len=gen->saveFileStream(f);
00091       if(len==0) {
00092         serr->printf("Error saving file\n");
00093         sndman->playFile(config->controller.error_snd);
00094         return;
00095       }
00096     } else if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
00097       FilterBankGenerator * gen=ProjectInterface::defRawCameraGenerator; // just an alias for readability
00098       gen->selectSaveImage(ProjectInterface::doubleLayer,config->vision.rawcam.channel);
00099       unsigned int len=gen->saveFileStream(f);
00100       if(len==0) {
00101         serr->printf("Error saving file\n");
00102         sndman->playFile(config->controller.error_snd);
00103         return;
00104       }
00105     }
00106     
00107     // close file
00108     fclose(f);
00109 
00110   } else if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_JPEG) {
00111     //save a JPEG image
00112     JPEGGenerator * jpeg=NULL; // we'll set this to pick between the color jpeg or a single channel grayscale jpeg
00113     unsigned int chan=0; // and this will hold the channel to use out of that jpeg generator
00114     if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_COLOR)
00115       jpeg=dynamic_cast<JPEGGenerator*>(ProjectInterface::defColorJPEGGenerator);
00116     else if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
00117       jpeg=dynamic_cast<JPEGGenerator*>(ProjectInterface::defGrayscaleJPEGGenerator);
00118       chan=config->vision.rawcam.channel;
00119     }
00120     if(jpeg!=NULL) {
00121       unsigned int tmp_q=jpeg->getQuality(); //temporary storage so we can reset the default
00122       jpeg->setQuality(92);
00123       
00124       // open file
00125       FILE * f=openNextFile(".jpg");
00126       if(f==NULL) //error message already displayed in openNextFile()
00127         return;
00128 
00129       //! write actual image data
00130       unsigned char * imgbuf=jpeg->getImage(ProjectInterface::doubleLayer,chan);
00131       unsigned int writ=fwrite(imgbuf,jpeg->getImageSize(ProjectInterface::doubleLayer,chan),1,f);
00132       if(writ==0) {
00133         serr->printf("Error saving file\n");
00134         sndman->playFile(config->controller.error_snd);
00135         return;
00136       }
00137 
00138       // close file
00139       fclose(f);
00140       
00141       jpeg->setQuality(tmp_q);
00142     }
00143 
00144   } else if(config->vision.rawcam.compression==Config::vision_config::RawCamConfig::COMPRESS_PNG) {
00145     //save a PNG image
00146     PNGGenerator * png=NULL; // we'll set this to pick between the color png or a single channel grayscale png
00147     unsigned int chan=0; // and this will hold the channel to use out of that png generator
00148     if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_COLOR)
00149       png=dynamic_cast<PNGGenerator*>(ProjectInterface::defColorPNGGenerator);
00150     else if(config->vision.rawcam.encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
00151       png=dynamic_cast<PNGGenerator*>(ProjectInterface::defGrayscalePNGGenerator);
00152       chan=config->vision.rawcam.channel;
00153     }
00154     if(png!=NULL) {
00155       // open file
00156       FILE * f=openNextFile(".png");
00157       if(f==NULL) //error message already displayed in openNextFile()
00158         return;
00159       
00160       //! write actual image data
00161       unsigned char * imgbuf=png->getImage(ProjectInterface::doubleLayer,chan);
00162       unsigned int writ=fwrite(imgbuf,png->getImageSize(ProjectInterface::doubleLayer,chan),1,f);
00163       if(writ==0) {
00164         serr->printf("Error saving file\n");
00165         sndman->playFile(config->controller.error_snd);
00166         return;
00167       }
00168       
00169       // close file
00170       fclose(f);
00171     }
00172   }
00173   
00174   {
00175 #if defined(TGT_ERS7) || defined(TGT_ERS210) || defined(TGT_ERS220) || defined(TGT_ERS2xx)
00176     MMAccessor<LedMC> leds(ledID);
00177     leds->clear();
00178     leds->flash(TopBrLEDMask,700);
00179     leds->flash(TopLLEDMask|TopRLEDMask,500);
00180     leds->flash(MidLLEDMask|MidRLEDMask,300);
00181     leds->flash(BotLLEDMask|BotRLEDMask,100);
00182 #elif defined(TGT_HAS_LEDS)
00183     MMAccessor<LedMC> leds(ledID);
00184     leds->clear();
00185     if(NumLEDs>3)
00186       leds->flash(1<<3,700);
00187     if(NumLEDs>2)
00188       leds->flash(1<<2,500);
00189     if(NumLEDs>1)
00190       leds->flash(1<<1,300);
00191     if(NumLEDs>0)
00192       leds->flash(1<<0,100);
00193 #endif
00194   }
00195 
00196   sout->printf("done\n");
00197 }
00198 
00199 FILE *
00200 CameraBehavior::openNextFile(const std::string& ext) {
00201   FILE * f=fopen(getNextName(ext).c_str(),"w+");
00202   if(f==NULL) {
00203     serr->printf("Error opening file\n");
00204     sndman->playFile(config->controller.error_snd);
00205     return NULL;
00206   }
00207   sndman->playFile("camera.wav");
00208   return f;
00209 }
00210 
00211 
00212 std::string
00213 CameraBehavior::getNextName(const std::string& ext) {
00214   char tmp[100];
00215   snprintf(tmp,100,"data/img%05d%s",index++,ext.c_str());
00216   std::string ans=config->portPath(tmp);
00217   sout->printf("Saving `%s'...",ans.c_str());
00218   return ans;
00219 }
00220 
00221 void
00222 CameraBehavior::initIndex() {
00223   std::string path=config->portPath("data/");
00224   DIR* dir=opendir(path.c_str());
00225   if(dir==NULL) {
00226     serr->printf("bad path: `%s'\n",path.c_str());
00227     return;
00228   }
00229   struct dirent * ent=readdir(dir);
00230   while(ent!=NULL) {
00231     struct stat s;
00232     std::string fullpath=path+ent->d_name;
00233     int err=stat(fullpath.c_str(),&s);
00234     if(err!=0) {
00235       serr->printf("File disappeared: %s\n",fullpath.c_str());
00236       return;
00237     }
00238     if((s.st_mode&S_IFDIR)==0 && strncasecmp(ent->d_name,"IMG",3)==0) {
00239       unsigned int cur=atoi(&ent->d_name[3]);
00240       if(cur>index)
00241         index=cur;
00242     }
00243     ent=readdir(dir);
00244   }
00245   closedir(dir);
00246   index++; //set index to next unused
00247   sout->printf("The next saved image will go to %simg%05d\n",path.c_str(),index);
00248 }
00249 
00250 /*! @file
00251  * @brief Implements CameraBehavior, for taking pictures
00252  * @author ejt (Creator)
00253  */
00254 

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