SingleChannelBeo.C

Go to the documentation of this file.
00001 /*!@file Neuro/SingleChannelBeo.C wrapper class to run a SingleChannel on a
00002   distant CPU */
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00006 // by the University of Southern California (USC) and the iLab at USC.  //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/SingleChannelBeo.C $
00036 // $Id: SingleChannelBeo.C 8195 2007-03-30 04:34:07Z rjpeters $
00037 //
00038 
00039 #include "Neuro/SingleChannelBeo.H"
00040 
00041 #include "Beowulf/Beowulf.H"
00042 #include "Beowulf/TCPmessage.H"
00043 #include "Component/ParamMap.H"
00044 #include "Util/Assert.H"
00045 
00046 #include <sstream>
00047 
00048 // ######################################################################
00049 SingleChannelBeo::SingleChannelBeo(const nub::ref<Beowulf>& beow) :
00050   itsBeo(beow), itsNode(-2), itsFrame(-1)
00051 { }
00052 
00053 // ######################################################################
00054 SingleChannelBeo::~SingleChannelBeo()
00055 {
00056   if (itsNode >= 0)
00057     itsBeo->releaseNode(itsNode);
00058 }
00059 
00060 // ######################################################################
00061 void SingleChannelBeo::handleInput(SingleChannel& chan,
00062                                    const Image<float>& bwimg,
00063                                    const SimTime& t,
00064                                    const Image<byte>& clipMask,
00065                                    const rutz::shared_ptr<PyramidCache<float> >& cache)
00066 {
00067   // if we haven't allocated a Beowulf node yet, then let's do so now:
00068   if (itsNode == -2)
00069     {
00070       if (itsBeo->getNodeNumber() != -1)
00071         LFATAL("I need to be Beowulf master");
00072 
00073       // ask the Beowulf for a node number:
00074       itsNode = itsBeo->requestNode();
00075       if (itsNode == -2)
00076         LFATAL("No more available nodes - You need a bigger Beowulf");
00077 
00078       LINFO("Delegating '%s' [%s] to Beowulf node %d",
00079             chan.descriptiveName().c_str(), chan.tagName().c_str(),
00080             itsNode);
00081     }
00082 
00083   // if this is the first time we are called, let's start by sending
00084   // off a configuration message to our processing node, so that it
00085   // can create a channel for us:
00086   if (itsFrame == -1) {
00087     // we have two types of config data: our ModelParam values, and our
00088     // map weights. We put each into a ParamMap:
00089     ParamMap param; chan.writeParamsTo(param);
00090     ParamMap weight; chan.writeTo(weight);
00091 
00092     // let's convert both ParamMaps to string:
00093     std::stringstream sparam, sweight;
00094     param.format(sparam); weight.format(sweight);
00095 
00096     // let's put our descriptive name, our tag name and both parameter
00097     // strings into a TCPmessage, and let's put our VisualFeature in
00098     // the 'frame' field, and let's send it off (NOTE: VisualFeature
00099     // also is in param, but having it here will make decoding of the
00100     // message easier).
00101     int32 vs = static_cast<int32>(chan.visualFeature());
00102     TCPmessage msg(vs, BEO_SCHANCONF);
00103     msg.addString(chan.descriptiveName().c_str());
00104     msg.addString(chan.tagName().c_str());
00105     msg.addString(sparam.str().c_str());
00106     msg.addString(sweight.str().c_str());
00107 
00108     itsBeo->send(itsNode, msg);
00109   }
00110 
00111   // increment our unofficial frame number; we have this counter just
00112   // because we have a frame field in TCPmessage, so we may as well
00113   // use it:
00114   itsFrame ++;
00115 
00116   // send t, bwimg and clipMask to processor node:
00117   TCPmessage msg(itsFrame, BEO_SCHANINPUT);
00118   msg.addDouble(t.secs()); msg.addImage(bwimg); msg.addImage(clipMask);
00119   itsBeo->send(itsNode, msg);
00120 
00121   // anybody needing our results will need to wait until they have
00122   // come back from the processor node:
00123   chan.killCaches();
00124 }
00125 
00126 // ######################################################################
00127 void SingleChannelBeo::waitForOutput(SingleChannel& chan)
00128 {
00129   // nothing to wait for if we haven't allocated a Beowulf node yet:
00130   if (itsNode == -2) return;
00131 
00132   // nothing to wait for if we have nothing in progress
00133   if (chan.hasOutputCache()) return;
00134 
00135   // See if we have a new message on our Beowulf:
00136   TCPmessage rmsg; bool gotnothing = true; int err = 0;
00137   int32 rframe, raction, rnode = itsNode;  // receive only from our server
00138   while(gotnothing) {
00139     err = 0;
00140     // wait up to 50ms
00141     if (itsBeo->receive(rnode, rmsg, rframe, raction, 50, &err)) {
00142       // message is supposed to contain: pyramid, submaps, possibly clipPyr:
00143       if (raction != BEO_SCHANOUTPUT && raction != BEO_SCHANALLOUT)
00144         LERROR("IGNORING message of wrong type from node %d", rnode);
00145       else {
00146         if (rframe != itsFrame)
00147           LERROR("Received results for frame %d while at frame %d??",
00148                  rframe, itsFrame);
00149         // the time:
00150         const double t = rmsg.getElementDouble();
00151 
00152         // the output map (always valid, but possibly blank):
00153         chan.storeOutputCache(rmsg.getElementFloatIma());
00154 
00155         // additional results?
00156         if (raction == BEO_SCHANALLOUT) {
00157           // the pyramid:
00158           ImageSet<float> pyr = rmsg.getElementFloatImaSet();
00159           // if the SingleChannel on the remote node had no output
00160           // available yet, we have an empty pyramid, which we don't
00161           // want to push into our pyramid queue; this way, we will also
00162           // have no pyramid available if the remote had none:
00163           if (pyr.size())
00164             chan.storePyramid(pyr, SimTime::SECS(t));
00165 
00166           // the submaps:
00167           pyr = rmsg.getElementFloatImaSet();
00168           if (pyr.size())
00169             chan.storeSubmapCache(pyr);
00170 
00171           // clip pyramid (if any):
00172           pyr = rmsg.getElementFloatImaSet();
00173           if (pyr.size())
00174             chan.storeClipPyramid(pyr);
00175         }
00176 
00177         // ok, we got our results, let's return:
00178         gotnothing = false;
00179       }
00180     }
00181 
00182     if (err != 0)
00183       LFATAL("error during Beowulf::receive()");
00184   }
00185 }
00186 
00187 // ######################################################################
00188 rutz::shared_ptr<InputHandler> SingleChannelBeo::makeClone() const
00189 {
00190   return rutz::make_shared(new SingleChannelBeo(itsBeo));
00191 }
00192 
00193 // ######################################################################
00194 /* So things look consistent in everyone's emacs... */
00195 /* Local Variables: */
00196 /* indent-tabs-mode: nil */
00197 /* End: */
Generated on Sun May 8 08:41:04 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3