00001 #include "MirageDriver.h"
00002 #include "local/CommPort.h"
00003 #include "Motion/KinematicJoint.h"
00004 #include "Shared/Config.h"
00005 #include "Shared/debuget.h"
00006 #include "Shared/get_time.h"
00007 #include <libxml/tree.h>
00008
00009
00010 using namespace std;
00011
00012 const std::string MirageDriver::autoRegisterDriver = DeviceDriver::getRegistry().registerType<MirageDriver>("Mirage");
00013
00014 const char* MirageDriver::encodingNames[] = { "YUV", "PNG", "JPG", NULL };
00015 INSTANTIATE_NAMEDENUMERATION_STATICS(MirageDriver::Encoding);
00016
00017
00018 void MirageDriver::ImageSubscription::registerSource() {
00019 DataStreamDriver::registerSource();
00020 #if defined(TGT_HAS_CAMERA)
00021 CameraName = "Mirage";
00022 #endif
00023 }
00024
00025 void MirageDriver::ImageSubscription::deregisterSource() {
00026 #if defined(TGT_HAS_CAMERA)
00027 CameraName = CameraModelName;
00028 #endif
00029 DataStreamDriver::deregisterSource();
00030 }
00031
00032 void MirageDriver::motionStarting() {
00033 MotionHook::motionStarting();
00034 opener.start();
00035 imgsrc.host.addPrimitiveListener(this);
00036 imgsrc.port.addPrimitiveListener(this);
00037 sensrc.host=imgsrc.host;
00038 sensrc.port=imgsrc.port;
00039 for(unsigned int i=0; i<NumOutputs; ++i)
00040 positions[i] = DataSource::getOutputValue(i);
00041 }
00042
00043 bool MirageDriver::isConnected() {
00044 return comm.is_open() || comm.is_connecting();
00045 }
00046
00047 void MirageDriver::motionStopping() {
00048 persist.removePrimitiveListener(this);
00049 imgsrc.host.removePrimitiveListener(this);
00050 imgsrc.port.removePrimitiveListener(this);
00051 if(opener.isStarted())
00052 opener.stop().join();
00053 MotionHook::motionStopping();
00054 }
00055
00056 void MirageDriver::motionUpdated(const std::vector<size_t>& changedIndices, const float outputs[][NumOutputs]) {
00057 MotionHook::motionUpdated(changedIndices,outputs);
00058 if(changedIndices.size()==0 || !comm.is_open() || !comm) {
00059
00060 for(std::vector<size_t>::const_iterator it=changedIndices.begin(); it!=changedIndices.end(); ++it)
00061 positions[*it]=outputs[NumFrames-1][*it];
00062 } else {
00063 plist::Dictionary d;
00064 plist::Dictionary pos;
00065 for(std::vector<size_t>::const_iterator it=changedIndices.begin(); it!=changedIndices.end(); ++it) {
00066 positions[*it]=outputs[NumFrames-1][*it];
00067 pos.addEntry(capabilities.getOutputName(*it),positions[*it]);
00068 }
00069 d.addEntry("Positions",pos);
00070 sendUpdate(d);
00071 }
00072 }
00073
00074
00075 void MirageDriver::plistValueChanged(const plist::PrimitiveBase& pl) {
00076 if(&pl==&imgsrc.host || &pl==&imgsrc.port) {
00077
00078
00079 if(opener.isStarted())
00080 opener.stop().join();
00081 sensrc.host=imgsrc.host;
00082 sensrc.port=imgsrc.port;
00083 opener.start();
00084 } else if(&pl==&persist) {
00085 plist::Dictionary d;
00086 d.addEntry("Persist",persist);
00087 sendUpdate(d);
00088 } else if(&pl==&highres) {
00089 if(highres && imgsrc.encoding==ENCODE_YUV) {
00090 std::cerr << "MirageDriver: YUV encoding does not support highres mode (try PNG)" << std::endl;
00091 highres=false;
00092 return;
00093 }
00094 if(!comm.is_open())
00095 return;
00096 #ifdef TGT_HAS_CAMERA
00097 plist::Dictionary cam;
00098 cam.addEntry("Width",new plist::Primitive<unsigned int>(highres ? CameraResolutionX*2 : CameraResolutionX));
00099 cam.addEntry("Height",new plist::Primitive<unsigned int>(highres ? CameraResolutionY*2 : CameraResolutionY));
00100 plist::Array cameras;
00101 cameras.addEntry(cam);
00102 plist::Dictionary d;
00103 d.addEntry("Cameras",cameras);
00104 sendUpdate(d);
00105 #endif
00106 } else if(&pl==&imgsrc.encoding) {
00107 if(highres && imgsrc.encoding==ENCODE_YUV) {
00108 std::cerr << "MirageDriver: YUV encoding does not support highres mode" << std::endl;
00109 highres=false;
00110 return;
00111 }
00112 } else if(&pl==&physicsWalk) {
00113 if(!physicsWalk) {
00114 DriverMessaging::addListener(this,DriverMessaging::FixedPoints::NAME);
00115 } else {
00116 std::cout << "removing fixed points" << std::endl;
00117 DriverMessaging::removeListener(this,DriverMessaging::FixedPoints::NAME);
00118
00119 plist::Array arr;
00120 plist::Dictionary msg;
00121 msg.addEntry("FixedPoints",arr);
00122 sendUpdate(msg);
00123 }
00124 } else if(&pl==&physicsWheels) {
00125 plist::Dictionary msg;
00126 msg.addEntry("PhysicsWheels",physicsWheels);
00127 sendUpdate(msg);
00128 } else {
00129 std::cerr << "Unhandled value change in " << getClassName() << ": " << pl.get() << std::endl;
00130 }
00131 }
00132
00133 void MirageDriver::openConnection() {
00134 IPaddr addr(imgsrc.host,imgsrc.port);
00135 if(!addr.is_valid()) {
00136 std::cerr << instanceName << " could not open connection to " << imgsrc.host << ":" << imgsrc.port << std::endl;
00137 return;
00138 }
00139
00140 try {
00141 if(!physicsWalk)
00142 DriverMessaging::addListener(this,DriverMessaging::FixedPoints::NAME);
00143 physicsWalk.addPrimitiveListener(this);
00144 physicsWheels.addPrimitiveListener(this);
00145 while(true) {
00146 {
00147 MarkScope autolock(commLock);
00148
00149 comm.clear();
00150 comm.seekp(0);
00151 while(!comm.open(addr)) {
00152 Thread::testCurrentCancel();
00153 usleep(1000*1000);
00154 Thread::testCurrentCancel();
00155
00156 }
00157 comm << "<messages>\n";
00158
00159 KinematicJoint kin;
00160 if(kin.loadFile(::config->makePath(::config->motion.kinematics).c_str())==0) {
00161 std::cerr << "MirageDriver unable to find/parse kinematics file '" << ::config->motion.kinematics << "'" << std::endl;
00162 return;
00163 }
00164
00165 plist::Dictionary d;
00166 d.addEntry("Persist",persist);
00167 if(!persist) {
00168 d.addEntry("Location",initLocation);
00169 d.addEntry("Orientation",initOrientation);
00170 }
00171 KinematicJointSaver kinSaver(kin);
00172 d.addEntry("Model",kinSaver);
00173 plist::Dictionary pos;
00174 for(unsigned int i=0; i<NumOutputs; ++i)
00175 pos.addEntry(outputNames[i],positions[i]);
00176 d.addEntry("Positions",pos);
00177 d.addEntry("PhysicsWheels",physicsWheels);
00178 #ifdef TGT_HAS_CAMERA
00179 plist::Dictionary cam;
00180 cam.addValue("FrameName",outputNames[CameraFrameOffset]);
00181 cam.addValue("Width",highres ? CameraResolutionX*2 : CameraResolutionX);
00182 cam.addValue("Height",highres ? CameraResolutionY*2 : CameraResolutionY);
00183
00184
00185
00186
00187
00188
00189
00190
00191 cam.addValue("FOV_Y",CameraVertFOV);
00192 plist::Array cameras;
00193 cameras.addEntry(cam);
00194 d.addEntry("Cameras",cameras);
00195 highres.addPrimitiveListener(this);
00196 #endif
00197
00198 sendUpdate(d);
00199
00200
00201 persist.addPrimitiveListener(this);
00202 }
00203
00204 comm.get();
00205 if(comm.is_open()) {
00206
00207 MarkScope autolock(commLock);
00208 comm.clear();
00209 comm << "</messages>" << std::endl;
00210 comm.close();
00211 }
00212 Thread::testCurrentCancel();
00213 ASSERT(!comm,"comm closed, but still active?");
00214 }
00215 } catch(...) {
00216 physicsWalk.removePrimitiveListener(this);
00217 physicsWheels.removePrimitiveListener(this);
00218 DriverMessaging::removeListener(this);
00219 if(comm.is_open()) {
00220
00221 MarkScope autolock(commLock);
00222 comm.clear();
00223 comm << "</messages>" << std::endl;
00224 comm.close();
00225 }
00226 throw;
00227 }
00228 }
00229
00230 void MirageDriver::sendUpdate(plist::Dictionary& msg) {
00231 std::stringstream ss;
00232 ss << "RobotID-" << ::config->wireless.id;
00233 plist::Primitive<std::string> wid(ss.str());
00234 msg.addEntry("ID",wid);
00235 MarkScope autolock(commLock);
00236 msg.saveStream(comm,true);
00237 if(bufferedMsg.size()>0) {
00238 comm << bufferedMsg;
00239 bufferedMsg.clear();
00240 }
00241 comm.flush();
00242 }
00243
00244 void MirageDriver::SensorSubscription::opened() {
00245 NetworkCommPort::opened();
00246
00247 plist::Dictionary msg;
00248
00249 std::stringstream ss;
00250 ss << "RobotID-" << ::config->wireless.id;
00251 plist::Primitive<std::string> wid(ss.str());
00252 msg.addEntry("ID",wid);
00253
00254 plist::Primitive<bool> sendSensors(true);
00255 msg.addEntry("SendSensors",sendSensors);
00256
00257 MarkScope autolock(*this);
00258 std::ostream os(&getWriteStreambuf());
00259 os << "<subscription>\n";
00260 msg.saveStream(os,true);
00261 os.flush();
00262 }
00263
00264 void MirageDriver::ImageSubscription::opened() {
00265 NetworkCommPort::opened();
00266
00267 plist::Dictionary msg;
00268
00269 std::stringstream ss;
00270 ss << "RobotID-" << ::config->wireless.id;
00271 plist::Primitive<std::string> wid(ss.str());
00272 msg.addEntry("ID",wid);
00273
00274 plist::Primitive<unsigned int> camIdx(0);
00275 msg.addEntry("CameraIndex",camIdx);
00276
00277 msg.addEntry("Encoding",encoding);
00278 msg.addEntry("PNGLevel",pngCompressionLevel);
00279 msg.addEntry("JPGQuality",jpgQualityLevel);
00280
00281 MarkScope autolock(*this);
00282 std::ostream os(&getWriteStreambuf());
00283 os << "<subscription>\n";
00284 msg.saveStream(os,true);
00285 os.flush();
00286 }
00287
00288 void MirageDriver::ImageSubscription::plistValueChanged(const plist::PrimitiveBase& pl) {
00289 if(&pl==&encoding) {
00290 format.set(encoding.get());
00291 } else if(&pl==&pngCompressionLevel || &pl==&jpgQualityLevel) {
00292 if(!isWriteable())
00293 return;
00294 plist::Dictionary d;
00295
00296 d.addEntry("PNGLevel",pngCompressionLevel);
00297 d.addEntry("JPGQuality",jpgQualityLevel);
00298 MarkScope autolock(*this);
00299 std::ostream os(&getWriteStreambuf());
00300 d.saveStream(os,true);
00301 os.flush();
00302 } else
00303 Subscription<ImageStreamDriver>::plistValueChanged(pl);
00304 }
00305
00306 void MirageDriver::processDriverMessage(const DriverMessaging::Message& dmsg) {
00307 if(!comm.is_open() || !comm)
00308 return;
00309 if(dmsg.CLASS_NAME==DriverMessaging::FixedPoints::NAME) {
00310 plist::Dictionary msg;
00311 const DriverMessaging::FixedPoints& fpmsg = dynamic_cast<const DriverMessaging::FixedPoints&>(dmsg);
00312 msg.addEntry("FixedPoints",const_cast<DriverMessaging::FixedPoints&>(fpmsg));
00313 if(!fpmsg.flushOnMotionUpdate)
00314 sendUpdate(msg);
00315 else {
00316 std::stringstream ss;
00317 ss << "RobotID-" << ::config->wireless.id;
00318 plist::Primitive<std::string> wid(ss.str());
00319 msg.addEntry("ID",wid);
00320 ss.str(std::string());
00321 msg.saveStream(ss,true);
00322 bufferedMsg = ss.str();
00323 }
00324 }
00325 }
00326
00327
00328
00329
00330