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
00049
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
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
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
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
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
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
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
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
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);
00156 std::string extension = boost::filesystem::extension(filepath);
00157 std::ostringstream oss; oss << "$gdheBase.gdhe.ogl dumpPpm -color ";
00158
00159 if (host_is_local && extension == ".png")
00160 {
00161
00162
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
00170 boost::unique_lock<boost::mutex> convert_lock(convert_mutex);
00171
00172 if (convert_thread != NULL)
00173 while (!convert_done) convert_condition.wait(convert_lock);
00174
00175
00176 convert_data = ConvertData(tmpname, filebasepath+std::string("/")+filebasename+std::string(".png"));
00177 convert_done = false;
00178
00179 if (convert_thread == NULL)
00180 convert_thread = new boost::thread(boost::bind(&Client::convert,this));
00181
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
00215
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
00485
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
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