Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
client.hpp
00001 #ifndef CLIENT_HPP
00002 #define CLIENT_HPP
00003 
00004 #include <cstdlib>
00005 #include <cstdio>
00006 #include <sstream>
00007 #include <fstream>
00008 
00009 #include <boost/bind.hpp>
00010 #include <boost/thread/thread.hpp>
00011 #include <boost/thread/mutex.hpp>
00012 #include <boost/thread/condition_variable.hpp>
00013 #include <boost/filesystem.hpp>
00014 
00015 
00016 #include <gdhe/GDHE_client_prot.h>
00017 
00018 #include "kernel/IdFactory.hpp"
00019 #include "jmath/misc.hpp"
00020 #include "jmath/jblas.hpp"
00021 
00022 #include "gdhe/gdheException.hpp"
00023 
00024 #define ENABLE_CHILDREN 0
00025 
00026 namespace jafar {
00027 namespace gdhe {
00028   
00039 
00040 
00041 
00043   struct ColorRGB
00044   {
00045     unsigned char R, G, B;
00046     ColorRGB(unsigned char R_, unsigned char G_, unsigned char B_): R(R_), G(G_), B(B_) {}
00047     ColorRGB(): R(0), G(0), B(0) {}
00048 //    std::ostream& operator<<(std::ostream& os)
00049 //      { os << (int)R << " " << (int)G << " " << (int)B; return os; }
00050   };
00051 
00052   std::ostream& operator<<(std::ostream& os, const ColorRGB & c)
00053     { os << (int)c.R << " " << (int)c.G << " " << (int)c.B; return os; }
00054   
00055   extern const ColorRGB colorRed;
00056   extern const ColorRGB colorGreen;
00057   extern const ColorRGB colorBlue;
00058 
00060 
00061 
00064   class Object;
00065   
00066   typedef kernel::IdFactorySet MyIdFactory;
00067   
00068   // FIXME maybe ask Matthieu to add const the parameters when included in c++ ? what's the best solution vs const_cast ?
00069   class Client
00070   {
00071     protected:
00072       MyIdFactory idFactory;
00073       std::string host;
00074       bool host_is_local;
00075       ColorRGB backgroundColor;
00076     protected:
00077       void init();
00078       typedef std::pair<std::string,std::string> ConvertData;
00079       //std::list<ConvertData> convert_queue;
00080       ConvertData convert_data;
00081       boost::mutex convert_mutex;
00082       boost::condition_variable convert_condition;
00083       std::string convert_tmppath;
00084       bool convert_done;
00085       bool convert_end;
00086       boost::thread *convert_thread;
00091       void convert()
00092       {
00093         std::cout << "starting conversion task !" << std::endl;
00094         convert_done = false;
00095         convert_end = false;
00096         while(true)
00097         {
00098           // wait for a task
00099           boost::unique_lock<boost::mutex> convert_lock(convert_mutex);
00100           while(convert_done && !convert_end) convert_condition.wait(convert_lock);
00101           if (convert_done && convert_end) break;
00102           convert_lock.unlock();
00103           
00104           // wait that the input file exists and is writable
00105           std::fstream f;
00106           while (!f.is_open())
00107           {
00108             f.open(convert_data.first.c_str(), std::fstream::out | std::fstream::app);
00109             usleep(100*1000);
00110           }
00111           f.close();
00112           
00113           // then convert
00114           std::ostringstream oss; oss << "convert " << convert_data.first << " " << convert_data.second << " ; rm -f " << convert_data.first;
00115           int r = system(oss.str().c_str());
00116           if (r == -1) std::cout << "conversion from " << convert_data.first << " to " << convert_data.second << " failed." << std::endl;
00117           
00118           // and notify that has finished
00119           convert_lock.lock();
00120           convert_done = true;
00121           convert_condition.notify_all();
00122         }
00123       }
00124     public:
00125       Client(): idFactory(), host("localhost"), host_is_local(true), backgroundColor(194,184,176), convert_thread(NULL) {}
00126       Client(std::string host_): idFactory(), host(host_), host_is_local(host_ == "localhost"), backgroundColor(194,184,176), convert_thread(NULL) {}
00127       ~Client()
00128       {
00129         // wait the convert thread
00130         if (convert_thread)
00131         {
00132           boost::unique_lock<boost::mutex> convert_lock(convert_mutex);
00133           convert_end = true;
00134           convert_thread->join();
00135           delete convert_thread;
00136         }
00137       }
00138       void setHost(std::string host_) { host = host_; }
00139       int connect(bool wait = true);
00140       int disconnect() { return ::disconnect(); }
00141       int eval(std::string exp) 
00142       {
00143         int r;
00144         r = ::eval_expression(const_cast<char*>(exp.c_str()));
00145         //JFR_DEBUG("evaluated [" << r << "] '" << exp << "'");
00146         return r;
00147       }
00148       int launch_server()
00149         { return system("gdhe&"); }
00150       int dump(std::string const& filename)
00151       {
00152         int r;
00153         boost::filesystem::path filepath(filename);
00154         std::string filebasepath = filepath.branch_path().string();
00155         std::string filebasename = boost::filesystem::basename(filepath); //filename.substr(0, filename.size()-4);
00156         std::string extension = boost::filesystem::extension(filepath); //filename.substr(filename.size()-3, 3);
00157         std::ostringstream oss; oss << "$gdheBase.gdhe.ogl dumpPpm -color ";
00158 //std::cout << "extension gdhe dump is '" << extension << "'"<< std::endl;
00159         if (host_is_local && extension == ".png")
00160         {
00161 //std::cout << "converting to png!" << std::endl;
00162           //-- dump
00163           std::string tmpname = 
00164             (convert_tmppath == "" ? filebasepath + std::string("/") : convert_tmppath + std::string("/gdhe.")) + 
00165             filebasename + std::string(".ppm");
00166           oss << tmpname;
00167           r = eval(oss.str());
00168           
00169           //-- ask conversion
00170           boost::unique_lock<boost::mutex> convert_lock(convert_mutex);
00171           // wait that the previous conversion has finished
00172           if (convert_thread != NULL)
00173             while (!convert_done) convert_condition.wait(convert_lock);
00174           // update data
00175 //std::cout << "DUMP: previous conversion has finished, changing data" << std::endl;
00176           convert_data = ConvertData(tmpname, filebasepath+std::string("/")+filebasename+std::string(".png"));
00177           convert_done = false;
00178           // start thread if first time
00179           if (convert_thread == NULL)
00180             convert_thread = new boost::thread(boost::bind(&Client::convert,this));
00181           // notify
00182           convert_lock.unlock();
00183           convert_condition.notify_all();
00184           
00185         } else
00186         {
00187           oss << filebasepath << "/" << filebasename << ".ppm"; 
00188           r = eval(oss.str());
00189         }
00190         return r;
00191       }
00192       void setConvertTempPath(std::string convert_tmppath_) { convert_tmppath = convert_tmppath_; }
00193       void redraw()
00194         { eval("redrawAllWindows"); }
00195       void clear() 
00196         { eval("set robots(test) {sphere 0 0 0 0};unset robots;set pos(test) {0 0 0 0 0 0};unset pos;"); }
00197       
00198       void setBackgroundColor(ColorRGB &_color) 
00199         { backgroundColor = _color; }
00200       void setBackgroundColor(unsigned char R_, unsigned char G_, unsigned char B_) 
00201         { backgroundColor.R = R_; backgroundColor.G = G_; backgroundColor.B = B_; }
00202       
00203       void addObject(Object *object, bool visible = true);
00204       void addSubObject(Object *object, Object *parent, std::string suffix, bool visible = true);
00205       void removeObject(Object *object);
00206       void setCameraTarget(double _x, double _y, double _z);
00207       void setCameraPos(double _yaw, double _pitch, double _dist);
00208       
00209     protected:
00210     public:
00211       struct SendToServer {};
00212       static SendToServer sendToServer;
00213       std::ostringstream oss;
00214 //      friend template<typename T> Client& operator<<(Client& oc, const T & element);
00215 //      friend template<> Client& operator<<(Client& oc, Client::SendToServer element);
00216   };
00217   
00218   template<typename T> Client& operator<<(Client& oc, const T & element)
00219     { oc.oss << element; return oc; }
00220   template<> Client& operator<<(Client& oc, const Client::SendToServer & element)
00221     { oc.eval(oc.oss.str()); oc.oss.str(""); return oc; }
00222   
00224 
00225 
00227   class Label;
00228   
00239   class Object
00240   {
00241     protected:
00242       double x, y, z;
00243       double yaw, pitch, roll;
00244       ColorRGB color;
00245       bool poseModified, attributesModified;
00246       
00247       Label *label;
00248       void createLabel();
00249       void updateLabelPose();
00250       
00251     protected:
00252       bool ownId;
00253       MyIdFactory::storage_t id; 
00254       std::string ids;
00255       Client *client;
00256       void registerClient(Client *client_);
00257       void setId(MyIdFactory::storage_t id_, std::string suffix = "", bool ownId_ = true) 
00258         { ownId = ownId_; id = id_; ids = jmath::toStr(id)+suffix; }
00259       void touch() { attributesModified = true; }
00260       #if ENABLE_CHILDREN
00261       std::list<Object*> children;
00262       #endif
00263     public:
00264       Object(): 
00265         x(0), y(0), z(0), yaw(0), pitch(0), roll(0), color(), poseModified(true), attributesModified(true), label(NULL), ownId(false), id(0), ids(""), client(NULL)
00266         { }
00267       Object(double _x, double _y, double _z, double _yaw, double _pitch, double _roll): 
00268         poseModified(true), attributesModified(true), label(NULL), ownId(false), id(0), ids(""), client(NULL) 
00269         { setPose(_x,_y,_z,_yaw,_pitch,_roll); }
00270       Object(double _x, double _y, double _z, double _yaw, double _pitch, double _roll, unsigned char R_, unsigned char G_, unsigned char B_): 
00271         poseModified(true), attributesModified(true), label(NULL), ownId(false), id(0), ids(""), client(NULL) 
00272         { setPose(_x,_y,_z,_yaw,_pitch,_roll); setColor(R_,G_,B_); }
00273       virtual ~Object();
00274 
00275       virtual const std::string construct_string() const = 0;
00276       virtual const std::string move_string() const
00277       {
00278         std::ostringstream oss;
00279         oss << "set pos(" << ids << ") {" << yaw << " " << pitch << " " << roll << " " << x << " " << y << " " << z << "};";
00280         return oss.str();
00281       }
00282       virtual const std::string remove_string() const
00283       {
00284         std::ostringstream oss;
00285         oss << "unset robots(" << ids << ");unset pos(" << ids << ");";
00286         return oss.str();
00287       }
00288       virtual void move_command(bool send = false) const
00289       {
00290         *client << "set pos(" << ids << ") {" << yaw << " " << pitch << " " << roll << " " << x << " " << y << " " << z << "};";
00291         if (send) *client << Client::sendToServer;
00292       }
00293       virtual void remove_command(bool send = false) const
00294       {
00295         *client << "unset robots(" << ids << ");unset pos(" << ids << ");";
00296         if (send) *client << Client::sendToServer;
00297       }
00298       
00302       void remove()
00303       {
00304         if (!client) JFR_ERROR(GdheException, GdheException::NOT_ADDED_TO_CLIENT, "This object was not added to a client");
00305         client->removeObject(this);
00306       }
00310       void hide()
00311       {
00312         if (!client) JFR_ERROR(GdheException, GdheException::NOT_ADDED_TO_CLIENT, "This object was not added to a client");
00313         std::ostringstream oss; oss << "unset pos(" << ids << ");"; client->eval(oss.str());
00314         poseModified = true;
00315       }
00319       void show()
00320       {
00321         if (!client) JFR_ERROR(GdheException, GdheException::NOT_ADDED_TO_CLIENT, "This object was not added to a client");
00322         client->eval(move_string());
00323         poseModified = false;
00324       }
00328       void refresh();
00329       
00330       void setPose(double _x, double _y, double _z, double _yaw, double _pitch, double _roll)
00331         { x = _x; y = _y; z = _z; yaw = _yaw; pitch = _pitch; roll = _roll; poseModified = true; updateLabelPose(); }
00332       void setPose(jblas::vec &pose) 
00333         { setPose(pose(0),pose(1),pose(2),pose(3),pose(4),pose(5)); }
00334       void setPose(jblas::vec &position, jblas::vec &euler)
00335         { setPose(position(0),position(1),position(2),euler(0),euler(1),euler(2)); }
00336       
00337       void setColor(ColorRGB &_color) 
00338         { color = _color; touch(); }
00339       void setColor(unsigned char R_, unsigned char G_, unsigned char B_) 
00340         { color.R = R_; color.G = G_; color.B = B_; touch(); }
00341       
00342       void setLabel(std::string text);
00343       void setLabelColor(ColorRGB &_color);
00344       void setLabelColor(unsigned char R_, unsigned char G_, unsigned char B_);
00345       void setLabelShift(double x_, double y_, double z_);
00346       
00347       friend class Client;
00348   };
00349   
00350   
00351   
00352 
00354 
00355 
00358   class Label: public Object
00359   {
00360     protected:
00361       std::string text;
00362       double shiftX, shiftY, shiftZ;
00363     public:
00364       Label(): text("") {}
00365       Label(std::string text_): text(text_) {}
00366       void setText(std::string text_) { text = text_; touch(); }
00367       void setShift(double x_, double y_, double z_) { shiftX = x_; shiftY = y_; shiftZ = z_; touch(); }
00368       virtual const std::string construct_string() const
00369       {
00370         std::ostringstream oss;
00371         oss << "set robots(" << ids << ") {";
00372         oss << "color " << color << ";";
00373         oss << "drawString " << shiftX << " " << shiftY << " " << shiftZ << " \"" << text << "\"};";
00374         return oss.str();
00375       }
00376   };
00377   
00378   class Robot: public Object
00379   {
00380     protected:
00381       std::string model;
00382     public:
00383       Robot(std::string model_):
00384         model(model_) {}
00385       Robot(std::string model_, double x_, double y_, double z_, double yaw_, double pitch_, double roll_):
00386         model(model_)
00387       {
00388         setPose(x_, y_, z_, yaw_, pitch_, roll_);
00389       }
00390       
00391       virtual const std::string construct_string() const
00392       {
00393         std::ostringstream oss;
00394         oss << "set robots(" << ids << ") {";
00395         if (model != "") oss << model; else oss << "color 255 255 255;sphere 0.001 12";
00396         oss << "};";
00397         return oss.str();
00398       }
00399       
00400   };
00401   
00402   
00403   class Sphere: public Object
00404   {
00405     protected:
00406       double radius;
00407       int facets;
00408       
00409     public:
00410       Sphere(double radius_, double facets_ = 12):
00411         Object(), radius(radius_), facets(facets_)
00412         { }
00413 
00414       void setRadius(double _radius) { radius = _radius; touch(); if (label) label->setShift(0,0,_radius*1.3); }
00415       void setFacets(double _facets) { facets = _facets; touch(); }
00416 
00417       const std::string construct_string() const
00418       {
00419         std::ostringstream oss;
00420         oss << "set robots(" << ids << ") {";
00421         oss << "color " << color << ";";
00422         oss << "sphere " << 0 << " " << 0 << " " << 0 << " " << radius << " " << facets << "};";
00423         return oss.str();
00424       }
00425   };
00426   
00427 
00428   class Ellipsoid: public Object
00429   {
00430     protected:
00431       double dx, dy, dz;
00432       int facets;
00433       
00434     public:
00435       Ellipsoid(double facets_ = 12):
00436         Object(), dx(0), dy(0), dz(0), facets(facets_)
00437         { }
00438       Ellipsoid(double _dx, double _dy, double _dz, double facets_ = 12):
00439         Object(), dx(_dx), dy(_dy), dz(_dz), facets(facets_)
00440         { }
00441       Ellipsoid(double x0_, double y0_, double z0_, double _dx, double _dy, double _dz, unsigned char R_, unsigned char G_, unsigned char B_, double facets_ = 12):
00442         Object(x0_, y0_, z0_, 0, 0, 0, R_, G_, B_), dx(_dx), dy(_dy), dz(_dz), facets(facets_)
00443         { }
00444       Ellipsoid(jblas::vec3 _x, jblas::sym_mat33 _xCov, double _scale = 1)
00445         { set(_x, _xCov, _scale); }
00446       void set(jblas::vec3 _x, jblas::sym_mat33 _xCov, double _scale = 1);
00447       void setCompressed(jblas::vec3 _x, jblas::sym_mat33 _xCov, double _scale = 1);
00448 
00449       void setRads(double _dx, double _dy, double _dz) { dx = _dx; dy = _dy; dz = _dz; touch(); if (label) label->setShift(0,0,_dz*1.3); }
00450       void setFacets(double _facets) { facets = _facets; touch(); }
00451 
00452       const std::string construct_string() const
00453       {
00454         std::ostringstream oss;
00455         oss << "set robots(" << ids << ") {";
00456         oss << "color " << color << ";";
00457         oss << "ellipsoid " << 0 << " " << 0 << " " << 0 << " " << dx << " " << dy << " " << dz << " " << facets << "};";
00458         return oss.str();
00459       }
00460   };
00461 
00462   class EllipsoidWire: public Ellipsoid
00463   {
00464     public:
00465       EllipsoidWire(double facets_ = 12): Ellipsoid(facets_) {}
00466       EllipsoidWire(double _dx, double _dy, double _dz, double facets_ = 12): Ellipsoid(_dx,_dy,_dz, facets_) {}
00467       EllipsoidWire(double x0_, double y0_, double z0_, double _dx, double _dy, double _dz, unsigned char R_, unsigned char G_, unsigned char B_, double facets_ = 12): Ellipsoid(x0_, y0_, z0_, _dx, _dy, _dz, R_, G_, B_, facets_) {}
00468       EllipsoidWire(jblas::vec3 _x, jblas::sym_mat33 _xCov, double _scale = 1): Ellipsoid(_x, _xCov, _scale) {}
00469       
00470       const std::string construct_string() const
00471       {
00472         std::ostringstream oss;
00473         oss << "set robots(" << ids << ") {";
00474         oss << "color " << color << ";";
00475         #if 0 // waiting approval of a commit in gdhe
00476         oss << "ellipse " << 0 << " " << 0 << " " << 0 << " z " << 2*dx << " " << 2*dy << " " << facets << ";";
00477         oss << "ellipse " << 0 << " " << 0 << " " << 0 << " y " << 2*dx << " " << 2*dz << " " << facets << ";";
00478         oss << "ellipse " << 0 << " " << 0 << " " << 0 << " x " << 2*dy << " " << 2*dz << " " << facets << ";";
00479         #endif
00480         oss << "polyline 2 " << -dx << " " <<  0  << " " <<  0  << " " << +dx << " " <<  0  << " " <<  0  << ";";
00481         oss << "polyline 2 " <<  0  << " " << -dy << " " <<  0  << " " <<  0  << " " << +dy << " " <<  0  << ";";
00482         oss << "polyline 2 " <<  0  << " " <<  0  << " " << -dz << " " <<  0  << " " <<  0  << " " << +dz << "};";
00483         return oss.str();
00484         // TODO also draw the angle uncertainty with an ellipsoidic cone (an ellipse which is the intersection
00485         // of an axis when the rotation around the two other axes vary, and 4 segments which are this axis at extrema)
00486       }
00487   };
00488 
00489   
00490   class Grid: public Object
00491   {
00492     protected:
00493       double extent;
00494       double size;
00495       
00496     public:
00497       Grid(double _extent, double _size):
00498         Object(), extent(_extent), size(_size)
00499         { }
00500 
00501       const std::string construct_string() const
00502       {
00503         std::ostringstream oss;
00504         oss << "set robots(" << ids << ") {";
00505         oss << "color " << color << ";";
00506         oss << "grille " << -extent << " " << -extent << " " << extent << " " << extent << " " << size << "};";
00507         return oss.str();
00508       }
00509   };
00510   
00511   struct Point3D
00512   {
00513     double x, y, z;
00514     Point3D(double x_, double y_, double z_): x(x_), y(y_), z(z_) {}
00515   };
00516   
00517   class Polyline: public Object
00518   {
00519     protected:
00520       std::vector<Point3D> line;
00521       
00522     public:
00523       Polyline(): Object() { }
00524       Polyline(double x0, double y0, double z0, double x1, double y1, double z1):
00525         Object()
00526       {
00527         line.push_back(Point3D(x0,y0,z0));
00528         line.push_back(Point3D(x1,y1,z1));
00529       }
00530 
00531       void addPoint(const Point3D &point) { line.push_back(point); touch(); }
00532       void addPoint(jblas::vec point) { addPoint(Point3D(point(0),point(1),point(2))); }
00533       void addPoint(double x, double y, double z) { addPoint(Point3D(x,y,z)); }
00534       void clear() { line.clear(); touch(); }
00535       Point3D const& back() { return line.back(); }
00536       int size() { return line.size(); }
00537 
00538       const std::string construct_string() const
00539       {
00540         std::ostringstream oss;
00541         oss << "set robots(" << ids << ") {";
00542         oss << "color " << color << ";";
00543         oss << "polyline " << line.size();
00544         for(std::vector<Point3D>::const_iterator it = line.begin(); it != line.end(); ++it)
00545           oss << " " << it->x << " " << it->y << " " << it->z;
00546         oss << "};";
00547         return oss.str();
00548       }
00549   };
00550   
00551   // TODO maybe compress a little bit, we'll lose detail but it's really big at 60Hz...
00552   class Trajectory: public Object
00553   {
00554     protected:
00555       std::vector<Polyline*> traj;
00556       int poly_size;
00557       Polyline *last_poly;
00558     public:
00559       Trajectory(): Object(), poly_size(20), last_poly(NULL) {}
00560       ~Trajectory()
00561       {
00562         for(std::vector<Polyline*>::iterator it = traj.begin(); it != traj.end(); ++it)
00563           delete *it;
00564       }
00565       void addPoint(const Point3D &point)
00566       {
00567         if (last_poly == NULL || last_poly->size() >= poly_size)
00568         {
00569           Polyline *prev_last_poly = last_poly;
00570           traj.push_back(new Polyline());
00571           last_poly = traj.back();
00572           last_poly->setColor(color);
00573           std::ostringstream oss; oss << "-" << traj.size();
00574           client->addSubObject(last_poly, this, oss.str(), false);
00575           poseModified = true;
00576           if (prev_last_poly)
00577             last_poly->addPoint(prev_last_poly->back());
00578         }
00579         last_poly->addPoint(point);
00580         touch();
00581       }
00582       void addPoint(jblas::vec point) { addPoint(Point3D(point(0),point(1),point(2))); }
00583       void addPoint(double x, double y, double z) { addPoint(Point3D(x,y,z)); }
00584       void clear() { traj.clear(); touch(); }
00585     
00586       const std::string move_string() const
00587         { if (last_poly) return last_poly->move_string(); else return ""; }
00588       const std::string remove_string() const
00589         { if (last_poly) return last_poly->remove_string(); else return ""; }
00590       const std::string construct_string() const
00591         { if (last_poly) return last_poly->construct_string(); else return ""; }
00592   };
00593   
00594   
00595   class Frame: public Object
00596   {
00597     protected:
00598       double length;
00599     public:
00600       Frame(): Object() { }
00601       Frame(double length_):
00602         Object(), length(length_) {}
00603       
00604       const std::string construct_string() const
00605       {
00606         std::ostringstream oss;
00607         oss << "set robots(" << ids << ") {";
00608         oss << "color " << color << ";";
00609         oss << "repere " << length << "};";
00610         return oss.str();
00611       }
00612   };
00613   
00614   
00615 }}
00616 
00617 #endif
00618 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:19 for Jafar by doxygen 1.7.6.1
LAAS-CNRS