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