00001
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
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 };
00022 static const char* encodingNames[];
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), depthsrc(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 sources["Depth"] = &depthsrc;
00055 }
00056
00057 virtual void motionStarting();
00058 virtual void updateAllOutputs();
00059 virtual bool isConnected();
00060 virtual void motionStopping();
00061 virtual void motionUpdated(const std::vector<size_t>& changedIndices, const float outputs[][NumOutputs]);
00062
00063 virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00064
00065 plist::Primitive<bool> persist;
00066
00067 plist::Primitive<bool> highres;
00068
00069 plist::Point initLocation;
00070 plist::Point initOrientation;
00071 plist::Primitive<bool> physicsWalk;
00072 plist::Primitive<bool> physicsWheels;
00073
00074 protected:
00075 Thread::Lock commLock;
00076 ionetstream comm;
00077 std::string bufferedMsg;
00078 CallbackThread opener;
00079 bool opening;
00080 plist::Primitive<float> positions[NumOutputs];
00081
00082 template<class T>
00083 class Subscription : public T, public NetworkCommPort {
00084 public:
00085 Subscription(const std::string& name) : DeviceDriver("MirageDriver::Subscription",name+"::Subscription"), T(name), NetworkCommPort(name) {
00086 host="localhost";
00087 port=DEFAULT_PORT;
00088 T::srcFrameRate = DEFAULT_FPS;
00089 }
00090 virtual const std::string& nextName() { return T::instanceName; }
00091 virtual void doFreeze();
00092 virtual void doUnfreeze();
00093 protected:
00094 virtual CommPort * getComm(const std::string& name) { return this; }
00095 virtual bool requestFrame(CommPort& comm);
00096 virtual void opened()=0;
00097 virtual void closing();
00098 virtual void plistValueChanged(const plist::PrimitiveBase& pl) {
00099 if(&pl==&host || &pl==&port)
00100 NetworkCommPort::plistValueChanged(pl);
00101 else
00102 T::plistValueChanged(pl);
00103 }
00104 };
00105
00106 class SensorSubscription : public Subscription<PListSensorDriver> {
00107 public:
00108 SensorSubscription(const std::string& name)
00109 : DeviceDriver("MirageDriver::ImageSubscription",name+"::SensorSubscription"), Subscription<PListSensorDriver>(name+"::SensorSubscription") {}
00110 protected:
00111 virtual void opened();
00112 } sensrc;
00113
00114 class ImageSubscription : public Subscription<ImageStreamDriver> {
00115 public:
00116 ImageSubscription(const std::string& name)
00117 : DeviceDriver("MirageDriver::ImageSubscription",name+"::ImageSubscription"), Subscription<ImageStreamDriver>(name+"::ImageSubscription"),
00118 encoding(ENCODE_PNG,encodingNames), pngCompressionLevel(1), jpgQualityLevel(85)
00119 {
00120 encoding.addNameForVal("jpeg",ENCODE_JPG);
00121 encoding.addPrimitiveListener(this);
00122 pngCompressionLevel.addPrimitiveListener(this);
00123 jpgQualityLevel.addPrimitiveListener(this);
00124 format.set(encoding.get());
00125 }
00126
00127 virtual void registerSource();
00128 virtual void deregisterSource();
00129
00130 plist::NamedEnumeration<Encoding> encoding;
00131 plist::Primitive<unsigned int> pngCompressionLevel;
00132 plist::Primitive<unsigned int> jpgQualityLevel;
00133 protected:
00134 virtual void opened();
00135 virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00136 } imgsrc;
00137
00138 class DepthSubscription : public Subscription<ImageStreamDriver> {
00139 public:
00140 DepthSubscription(const std::string& name)
00141 : DeviceDriver("MirageDriver::DepthSubscription", name + "::DepthSubscription"),
00142 Subscription<ImageStreamDriver> (name + "::DepthSubscription"),
00143 encoding(ENCODE_PNG, encodingNames), pngCompressionLevel(1), jpgQualityLevel(85)
00144 {
00145 encoding.addNameForVal("jpeg", ENCODE_JPG);
00146 encoding.addPrimitiveListener(this);
00147 pngCompressionLevel.addPrimitiveListener(this);
00148 jpgQualityLevel.addPrimitiveListener(this);
00149 format.set(encoding.get());
00150 setSID(ProjectInterface::visRawDepthSID);
00151 }
00152
00153 virtual void registerSource();
00154 virtual void deregisterSource();
00155
00156 plist::NamedEnumeration<Encoding> encoding;
00157 plist::Primitive<unsigned int> pngCompressionLevel;
00158 plist::Primitive<unsigned int> jpgQualityLevel;
00159 protected:
00160 virtual void opened();
00161 virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00162 } depthsrc;
00163
00164 void openConnection();
00165 void sendUpdate(plist::Dictionary& msg);
00166
00167 void processDriverMessage(const DriverMessaging::Message& dmsg);
00168
00169 private:
00170
00171 static const std::string autoRegisterDriver;
00172 };
00173
00174 template<class T>
00175 void MirageDriver::Subscription<T>::doUnfreeze() {
00176 T::doUnfreeze();
00177 if(!isWriteable())
00178 return;
00179 plist::Dictionary d;
00180 plist::Primitive<bool> singleFrame(false);
00181 d.addEntry("SingleFrame",singleFrame);
00182
00183 std::ostream os(&getWriteStreambuf());
00184 d.saveStream(os,true);
00185 os.flush();
00186 }
00187
00188 template<class T>
00189 void MirageDriver::Subscription<T>::doFreeze() {
00190 T::doFreeze();
00191 requestFrame(*this);
00192 }
00193
00194 template<class T>
00195 bool MirageDriver::Subscription<T>::requestFrame(CommPort& comm) {
00196 if(!isWriteable() || T::realtime)
00197 return false;
00198 plist::Dictionary d;
00199 plist::Primitive<bool> singleFrame(true);
00200 d.addEntry("SingleFrame",singleFrame);
00201 MarkScope autolock(*this);
00202 std::ostream os(&getWriteStreambuf());
00203 d.saveStream(os,true);
00204 os.flush();
00205
00206 return true;
00207 }
00208
00209 template<class T>
00210 void MirageDriver::Subscription<T>::closing() {
00211 MarkScope autolock(*this);
00212 std::ostream os(&getWriteStreambuf());
00213 os << "</subscription>" << std::flush;
00214 NetworkCommPort::closing();
00215 }
00216
00217
00218
00219
00220
00221
00222 #endif