Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

MirageDriver.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_MirageDriver_h_
00003 #define INCLUDED_MirageDriver_h_
00004 
00005 #include "local/DeviceDriver.h"
00006 #include "local/MotionHook.h"
00007 #include "local/DeviceDrivers/ImageStreamDriver.h"
00008 #include "local/DeviceDrivers/PListSensorDriver.h"
00009 #include "local/CommPorts/NetworkCommPort.h"
00010 #include "Wireless/netstream.h"
00011 #include "IPC/CallbackThread.h"
00012 #include "Shared/MarkScope.h"
00013 #include "IPC/DriverMessaging.h"
00014 
00015 //! description of MirageDriver
00016 class MirageDriver : public virtual DeviceDriver, public MotionHook, public virtual plist::PrimitiveListener, public virtual DriverMessaging::Listener {
00017 public:
00018   static const unsigned int DEFAULT_PORT = 19785;
00019   static const unsigned int DEFAULT_FPS = 25;
00020   
00021   enum Encoding { ENCODE_YUV, ENCODE_PNG, ENCODE_JPG }; //!< must be kept in sync with tools/mirage/CommThread.h
00022   static const char* encodingNames[]; //!< must be kept in sync with tools/mirage/CommThread.h
00023 
00024   explicit MirageDriver(const std::string& name)
00025     : DeviceDriver(autoRegisterDriver,name), MotionHook(), persist(false), highres(false), initLocation(), initOrientation(), physicsWalk(false), physicsWheels(true),
00026     commLock(), comm(), bufferedMsg(), opener(&MirageDriver::openConnection,*this), opening(false), positions(), sensrc(name), imgsrc(name)
00027   {
00028     addEntry("Host",imgsrc.host,"Specifies the hostname running the Mirage client");
00029     addEntry("Port",imgsrc.port,"Specifies the port number of the Mirage client");
00030     addEntry("Persist",persist,"If true, the robot model will not be removed when the Tekkotsu executable disconnects.");
00031     addEntry("Encoding",imgsrc.encoding,"Indicates whether to request JPG or PNG images from the simulated camera input");
00032     addEntry("PNGLevel",imgsrc.pngCompressionLevel,"The compression level to pass to libpng, and thus zlib.  0 for no compression (fastest), 9 for maximum (slowest).  Image quality is constant as this is lossless.");
00033     addEntry("JPGQuality",imgsrc.jpgQualityLevel,"The compression level to pass to libjpeg, 0 for very poor quality and small file size, 100 for best quality but larger files.");
00034     addEntry("HighRes",highres,"If true, will render simulated camera input at 'double' resolution instead of 'full'");
00035     addEntry("InitialLocation",initLocation,"The x, y, and z coordinates the robot will start out at if Persist is false.");
00036     addEntry("InitialOrientation",initOrientation,"The axis component of a quaternion representing robot orientation to use if Persist is false.");
00037     addEntry("PhysicsWalk",physicsWalk,"If true (and the kinematics configuration specifies mass for the robot), Mirage will use friction and physics to model the effects of walking; if false, Mirage will use a \"perfect\" model based on hints from the WalkMC itself.");
00038     addEntry("PhysicsWheels",physicsWheels,"If true (and the kinematics configuration specifies mass for the robot), then Mirage wheel use friction and physics to model robot motion; if false, Mirage will try to directly compute and move the robot.");
00039     highres.addPrimitiveListener(this);
00040     imgsrc.encoding.addPrimitiveListener(this);
00041     setLoadSavePolicy(FIXED,SYNC);
00042   }
00043 
00044   virtual std::string getClassName() const { return autoRegisterDriver; }
00045   
00046   virtual MotionHook* getMotionSink() { return dynamic_cast<MotionHook*>(this); }
00047   virtual void getSensorSources(std::map<std::string,DataSource*>& sources) {
00048     sources.clear();
00049     sources["Sensors"]=&sensrc;
00050   }
00051   virtual void getImageSources(std::map<std::string,DataSource*>& sources) {
00052     sources.clear();
00053     sources["Camera"]=&imgsrc;
00054   }
00055   
00056   virtual void motionStarting();
00057   virtual bool isConnected();
00058   virtual void motionStopping();
00059   virtual void motionUpdated(const std::vector<size_t>& changedIndices, const float outputs[][NumOutputs]);
00060   
00061   virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00062   
00063   plist::Primitive<bool> persist;
00064   
00065   plist::Primitive<bool> highres; //!< If true, will render simulated camera input at "double" resolution instead of "full"
00066   
00067   plist::Point initLocation;
00068   plist::Point initOrientation;
00069   plist::Primitive<bool> physicsWalk; //!< If true (and the kinematics configuration specifies mass for the robot), Mirage will use friction and physics to model the effects of walking; if false, Mirage will use a "perfect" model based on hints from the WalkMC itself.
00070   plist::Primitive<bool> physicsWheels; //!< If true (and the kinematics configuration specifies mass for the robot), then Mirage wheel use friction and physics to model robot motion; if false, Mirage will try to directly compute and move the robot.
00071   
00072 protected:
00073   Thread::Lock commLock;
00074   ionetstream comm;
00075   std::string bufferedMsg;
00076   CallbackThread opener;
00077   bool opening;
00078   plist::Primitive<float> positions[NumOutputs];
00079   
00080   template<class T>
00081   class Subscription : public T, public NetworkCommPort {
00082   public:
00083     Subscription(const std::string& name) : DeviceDriver("MirageDriver::Subscription",name+"::Subscription"), T(name), NetworkCommPort(name) {
00084       host="localhost";
00085       port=DEFAULT_PORT;
00086       T::srcFrameRate = DEFAULT_FPS;
00087     }
00088     virtual const std::string& nextName() { return T::instanceName; }
00089     virtual void doFreeze();
00090     virtual void doUnfreeze();
00091   protected:
00092     virtual CommPort * getComm(const std::string& name) { return this; }
00093     virtual bool requestFrame(CommPort& comm);
00094     virtual void opened()=0;
00095     virtual void closing();
00096     virtual void plistValueChanged(const plist::PrimitiveBase& pl) {
00097       if(&pl==&host || &pl==&port)
00098         NetworkCommPort::plistValueChanged(pl);
00099       else
00100         T::plistValueChanged(pl);
00101     }
00102   };
00103   
00104   class SensorSubscription : public Subscription<PListSensorDriver> {
00105   public:
00106     SensorSubscription(const std::string& name)
00107     : DeviceDriver("MirageDriver::ImageSubscription",name+"::SensorSubscription"), Subscription<PListSensorDriver>(name+"::SensorSubscription") {}
00108   protected:
00109     virtual void opened();
00110   } sensrc;
00111   
00112   class ImageSubscription : public Subscription<ImageStreamDriver> {
00113   public:
00114     ImageSubscription(const std::string& name)
00115       : DeviceDriver("MirageDriver::ImageSubscription",name+"::ImageSubscription"), Subscription<ImageStreamDriver>(name+"::ImageSubscription"),
00116       encoding(ENCODE_PNG,encodingNames), pngCompressionLevel(1), jpgQualityLevel(85)
00117     {
00118       encoding.addNameForVal("jpeg",ENCODE_JPG);
00119       encoding.addPrimitiveListener(this);
00120       pngCompressionLevel.addPrimitiveListener(this);
00121       jpgQualityLevel.addPrimitiveListener(this);
00122       format.set(encoding.get()); // pass as string to select appropriate enum
00123     }
00124     
00125     virtual void registerSource();
00126     virtual void deregisterSource();
00127     
00128     plist::NamedEnumeration<Encoding> encoding; //!< indicates whether to stream JPG or PNG images as simulated camera input
00129     plist::Primitive<unsigned int> pngCompressionLevel; //!< the compression level to pass to libpng, and thus zlib.  0 for no compression (fastest), 9 for maximum compression (slowest), image quality is constant as this is lossless
00130     plist::Primitive<unsigned int> jpgQualityLevel; //!< the compression level to pass to libjpeg, 0 for very poor quality and small file size, 100 for best quality but larger files
00131   protected:
00132     virtual void opened();
00133     virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00134   } imgsrc;
00135     
00136   void openConnection();
00137   void sendUpdate(plist::Dictionary& msg);
00138   
00139   void processDriverMessage(const DriverMessaging::Message& dmsg);
00140 
00141 private:
00142   //! holds the class name, set via registration with the DeviceDriver registry
00143   static const std::string autoRegisterDriver;
00144 };
00145 
00146 template<class T>
00147 void MirageDriver::Subscription<T>::doUnfreeze() {
00148   T::doUnfreeze();
00149   if(!isWriteable())
00150     return;
00151   plist::Dictionary d;
00152   plist::Primitive<bool> singleFrame(false);
00153   d.addEntry("SingleFrame",singleFrame);
00154   //MarkScope autolock(*this); // not a query-response, don't need lock
00155   std::ostream os(&getWriteStreambuf());
00156   d.saveStream(os,true);
00157   os.flush();
00158 }
00159 
00160 template<class T>
00161 void MirageDriver::Subscription<T>::doFreeze() {
00162   T::doFreeze();
00163   requestFrame(*this);
00164 }
00165 
00166 template<class T>
00167 bool MirageDriver::Subscription<T>::requestFrame(CommPort& comm) {
00168   if(!isWriteable() || T::realtime)
00169     return false;
00170   plist::Dictionary d;
00171   plist::Primitive<bool> singleFrame(true);
00172   d.addEntry("SingleFrame",singleFrame);
00173   MarkScope autolock(*this);
00174   std::ostream os(&getWriteStreambuf());
00175   d.saveStream(os,true);
00176   os.flush();
00177   return true;
00178 }
00179 
00180 template<class T>
00181 void MirageDriver::Subscription<T>::closing() {
00182   MarkScope autolock(*this);
00183   std::ostream os(&getWriteStreambuf());
00184   os << "</subscription>" << std::flush;
00185   NetworkCommPort::closing();
00186 }
00187 
00188 /*! @file
00189  * @brief 
00190  * @author Ethan Tira-Thompson (ejt) (Creator)
00191  */
00192 
00193 #endif

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Fri Mar 16 05:30:35 2012 by Doxygen 1.6.3