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)
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;
00066
00067 plist::Point initLocation;
00068 plist::Point initOrientation;
00069 plist::Primitive<bool> physicsWalk;
00070 plist::Primitive<bool> physicsWheels;
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());
00123 }
00124
00125 virtual void registerSource();
00126 virtual void deregisterSource();
00127
00128 plist::NamedEnumeration<Encoding> encoding;
00129 plist::Primitive<unsigned int> pngCompressionLevel;
00130 plist::Primitive<unsigned int> jpgQualityLevel;
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
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
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
00189
00190
00191
00192
00193 #endif