Revision: 7396
          http://playerstage.svn.sourceforge.net/playerstage/?rev=7396&view=rev
Author:   gerkey
Date:     2009-03-09 05:40:51 +0000 (Mon, 09 Mar 2009)

Log Message:
-----------
Got basic set and get working, with tolerance checking.

Modified Paths:
--------------
    code/branches/federation/gazebo/webgazebo/SConscript
    code/branches/federation/gazebo/webgazebo/WebGazebo.cc
    code/branches/federation/gazebo/webgazebo/WebGazebo.hh
    code/branches/federation/gazebo/webgazebo/main.cc

Modified: code/branches/federation/gazebo/webgazebo/SConscript
===================================================================
--- code/branches/federation/gazebo/webgazebo/SConscript        2009-03-09 
02:59:16 UTC (rev 7395)
+++ code/branches/federation/gazebo/webgazebo/SConscript        2009-03-09 
05:40:51 UTC (rev 7396)
@@ -21,11 +21,12 @@
   CPPPATH=Split('#.')
 )
 
-sources = Split('WebGazebo.cc')
+# We need Gazebo's quaternion functionality
+sources = Split('WebGazebo.cc #server/Quatern.os #server/Vector3.os 
#server/Angle.os')
 headers = Split('WebGazebo.hh')
 
 sharedLib = libEnv.SharedLibrary('webgazebo', sources)
-staticLib = libEnv.StaticLibrary('webgazebo', sources)
+#staticLib = libEnv.StaticLibrary('webgazebo', ssources)
 
 import os
 
@@ -50,5 +51,5 @@
 webgazebo = exeEnv.Program('webgazebo', 'main.cc')
 
 env.Install(install_prefix+'/lib', sharedLib)
-env.Install(install_prefix+'/lib', staticLib)
+#env.Install(install_prefix+'/lib', staticLib)
 env.Install(install_prefix+'/bin', webgazebo)

Modified: code/branches/federation/gazebo/webgazebo/WebGazebo.cc
===================================================================
--- code/branches/federation/gazebo/webgazebo/WebGazebo.cc      2009-03-09 
02:59:16 UTC (rev 7395)
+++ code/branches/federation/gazebo/webgazebo/WebGazebo.cc      2009-03-09 
05:40:51 UTC (rev 7396)
@@ -5,8 +5,12 @@
 #include <stdlib.h>
 #include <time.h>
 
-WebGazebo::WebGazebo(std::string _host, int _port) :
-        host(_host), port(_port)
+#include <boost/lexical_cast.hpp>
+
+#include "../server/Quatern.hh"
+
+WebGazebo::WebGazebo(std::string _host, int _port, double dtol, double atol) :
+        host(_host), port(_port), sq_dist_tol(dtol*dtol), sq_ang_tol(atol*atol)
 {
   // Set up the HTTP server
   // Not sure whether it's safe to do this more that once in one process
@@ -26,8 +30,11 @@
   this->client = new gazebo::Client();
   this->simIface = new gazebo::SimulationIface();
   this->client->ConnectWait(0, GZ_CLIENT_ID_USER_FIRST);
-  /// Open the Simulation Interface; let exceptions leak out
+  // Open the Simulation Interface; let exceptions leak out
   this->simIface->Open(this->client, "default");
+  // Get the list of models
+  if(!GetModelList())
+    throw("Failed to get list of models from Gazebo");
   puts("Done.");
 
   puts("[webgazebo] Ready");
@@ -42,8 +49,22 @@
 }
 
 bool
-WebGazebo::GetPose(gazebo::Pose* pose, std::string model)
+WebGazebo::GetModelList()
 {
+  // TODO
+  this->models["pioneer2dx_model1"] = 0;
+  return true;
+}
+
+bool WebGazebo::HasModel(const std::string& name)
+{
+  std::map<std::string,int>::const_iterator it = models.find(name);
+  return it != models.end();
+}
+
+bool
+WebGazebo::GetPose(std::string model, gazebo::Pose& pose)
+{
   // Discard any leftover responses;
   this->simIface->data->responseCount = 0;
 
@@ -56,24 +77,272 @@
     nanosleep(&sleeptime, NULL);
 
   assert(this->simIface->data->responseCount == 1);
-  *pose = this->simIface->data->responses[0].modelPose;
+  pose = this->simIface->data->responses[0].modelPose;
 
   return true;
 }
 
+bool
+WebGazebo::SetPose(std::string model, const gazebo::Pose& pose)
+{
+  // TODO: get pose, check for too-large jump, and complain about it
+
+  // Tell Gazebo the new pose
+  this->simIface->SetPose3d(model.c_str(), pose);
+
+  return true;
+}
+
+bool
+WebGazebo::ParseURI(std::string& model,
+                    std::string& prop,
+                    std::string& action,
+                    std::string uri,
+                    std::string& response)
+{
+  // Remove the query args
+  std::vector<std::string> uri_parts;
+  StringSplit(uri, uri_parts, "?");
+  assert(uri_parts.size() > 0);
+  std::string bare_uri = uri_parts[0];
+
+  // We require 3 path components: model/property/action
+  StringSplit(bare_uri, uri_parts, "/");
+  // There should be 4 parts, with the first one empty
+  if(uri_parts.size() != 4)
+  {
+    response = "Must be 3 slash-separated parts in the URI";
+    return false;
+  }
+
+  model = uri_parts[1];
+  prop = uri_parts[2];
+  action = uri_parts[3];
+
+  return true;
+}
+
+bool
+WebGazebo::CheckTolerances(gazebo::Pose p, gazebo::Pose q)
+{
+  // Check position
+  double sq_dd = ((p.pos.x - q.pos.x)*(p.pos.x - q.pos.x) +
+                  (p.pos.y - q.pos.y)*(p.pos.y - q.pos.y) +
+                  (p.pos.z - q.pos.z)*(p.pos.z - q.pos.z));
+  if((sq_dist_tol > 0) && (sq_dd > sq_dist_tol))
+    return false;
+
+  // Check orientation
+  gazebo::Quatern p_quat, q_quat;
+  gazebo::Vector3 pv(p.roll, p.pitch, p.yaw);
+  gazebo::Vector3 qv(q.roll, q.pitch, q.yaw);
+  p_quat.SetFromEuler(pv);
+  q_quat.SetFromEuler(qv);
+  gazebo::Quatern da = p_quat - q_quat;
+  //da.Normalize();
+
+  double sq_da = ((da.u*da.u) +
+                  (da.x*da.x) +
+                  (da.y*da.y) +
+                  (da.z*da.z));
+  if((sq_ang_tol > 0) && (sq_da > sq_ang_tol))
+    return false;
+
+  return true;
+}
+
+bool
+WebGazebo::HandleURI(const std::string& model,
+                     const std::string& prop,
+                     const std::string& action,
+                     struct evkeyvalq* kv,
+                     std::string& response)
+{
+  // The special simulation model
+  if(model == "sim")
+  {
+    // The special factory property
+    if(prop == "factory")
+    {
+      if(action == "create")
+      {
+        std::string name, type;
+        if(!GetValue(name, kv, "name") ||
+           !GetValue(type, kv, "type"))
+        {
+          response = "ERROR: Missing name and/or type argument for 
sim/factor/create";
+          return false;
+        }
+
+        printf("[webgazebo] Creating model %s of type %s\n",
+               name.c_str(), type.c_str());
+        response = "[webgazebo] Creating model " + name + " of type " + type;
+        return true;
+      }
+      else
+      {
+        response = "ERROR: Unknown action " + action + " for sim/factory";
+        return false;
+      }
+    }
+    else
+    {
+      response = "ERROR: Unknown property " + prop + " for sim";
+      return false;
+    }
+  }
+  // Everything else must be an existing model
+  else
+  {
+    printf("[webgazebo] got request for %s:%s:%s\n",
+           model.c_str(),
+           prop.c_str(),
+           action.c_str());
+    if(HasModel(model))
+    {
+      if(action == "get")
+      {
+        if(prop == "pose")
+        {
+          gazebo::Pose p;
+          if(GetPose(model, p))
+          {
+            char buf[1024];
+            snprintf(buf, sizeof(buf), 
+                     "Got %s's pose: (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f)",
+                      model.c_str(),
+                      p.pos.x, p.pos.y, p.pos.z,
+                      p.roll, p.pitch, p.yaw);
+            response = buf;
+            return true;
+          }
+          else
+          {
+            response = "ERROR: Failed to get pose for model " + model;
+            return false;
+          }
+        }
+        else
+        {
+          response = "ERROR: Unknown property " + prop + " for model " + model;
+          return false;
+        }
+      }
+      else if(action == "set")
+      {
+        if(prop == "pose")
+        {
+          std::string sx, sy, sz, sroll, spitch, syaw;
+
+          // Get pose first, fill in what the caller provided
+          gazebo::Pose p, q;
+          if(!GetPose(model, p))
+          {
+            response = "Failed to get pose before setting it";
+            return false;
+          }
+          try
+          {
+            q = p;
+            if(GetValue(sx, kv, "x"))
+              p.pos.x = boost::lexical_cast<float>(sx);
+            /*
+               if(GetValue(sy, kv, "y"))
+               p.pos.y = boost::lexical_cast<float>(sy);
+             */
+            if(GetValue(sz, kv, "z"))
+              p.pos.z = boost::lexical_cast<float>(sz);
+            if(GetValue(sroll, kv, "roll"))
+              p.roll = boost::lexical_cast<float>(sroll);
+            if(GetValue(spitch, kv, "pitch"))
+              p.pitch = boost::lexical_cast<float>(spitch);
+            if(GetValue(syaw, kv, "yaw"))
+              p.yaw = boost::lexical_cast<float>(syaw);
+          }
+          catch(boost::bad_lexical_cast e)
+          {
+            response = std::string("Failed to parse input value(s): ") + 
+                    e.what();
+            return false;
+          }
+
+          if(SetPose(model, p))
+          {
+            char buf[1024];
+            snprintf(buf, sizeof(buf), 
+                     "Set %s's pose: (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f)",
+                      model.c_str(),
+                      p.pos.x, p.pos.y, p.pos.z,
+                      p.roll, p.pitch, p.yaw);
+            response = buf;
+
+            // Check tolerances
+            if(!CheckTolerances(p,q))
+              response += "\nWARNING: Pose change exceeded tolerance";
+
+            return true;
+          }
+          else
+          {
+            response = "ERROR: Failed to get pose for model " + model;
+            return false;
+          }
+        }
+        else
+        {
+          response = "ERROR: Unknown property " + prop + " for model " + model;
+          return false;
+        }
+      }
+      else
+      {
+        response = "ERROR: Unknown action " + action;
+        return false;
+      }
+    }
+    else
+    {
+      response = "ERROR: No such model " + model;
+      return false;
+    }
+  }
+}
+
 void
 WebGazebo::EventCallback(evhttp_request* req, void* arg)
 {
   WebGazebo* obj = (WebGazebo*)arg;
 
   printf("[webgazebo] Got request:%s:\n", req->uri);
+  printf("[webgazebo] Decoded:%s:\n", evhttp_decode_uri(req->uri));
+
+  
+  // Pull out query args
+  struct evkeyvalq query_args;
+  evhttp_parse_query(req->uri, &query_args);
+
   struct evbuffer* eb = evbuffer_new();
   assert(eb);
 
+  std::string model, prop, action, response;
+  if(!obj->ParseURI(model, prop, action, req->uri, response))
+  {
+    evbuffer_add_printf(eb, "%s\n", response.c_str());
+    evhttp_send_reply(req, 400, "Invalid request", eb);
+    return;
+  }
+
+  if(!obj->HandleURI(model, prop, action, &query_args, response))
+  {
+    evbuffer_add_printf(eb, "%s\n", response.c_str());
+    evhttp_send_reply(req, 400, "Invalid request", eb);
+    return;
+  }
+
+  /*
   std::string model = "pioneer2dx_model1";
   gazebo::Pose p;
   assert(obj->GetPose(&p, model));
-
   evbuffer_add_printf(eb, "<html><head><title>WebGazebo</title></head><body>");
   evbuffer_add_printf(eb, "<h1>WebGazebo!</h1>");
   evbuffer_add_printf(eb, "%s's pose: (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f)",
@@ -81,7 +350,9 @@
                       p.pos.x, p.pos.y, p.pos.z,
                       p.roll, p.pitch, p.yaw);
   evbuffer_add_printf(eb, "</body></html>");
+  */
 
+  evbuffer_add_printf(eb, "%s\n", response.c_str());
   evhttp_send_reply(req, 200, "OK", eb);
   evbuffer_free(eb);
 }
@@ -91,3 +362,38 @@
 {
   event_dispatch();
 }
+
+void 
+WebGazebo::StringSplit(const std::string &s, 
+                       std::vector<std::string> &t, 
+                       const std::string &d)
+{
+  t.clear();
+  size_t start = 0, end;
+  while ((end = s.find_first_of(d, start)) != std::string::npos)
+  {
+    t.push_back(s.substr(start, end-start));
+    start = end + 1;
+  }
+  t.push_back(s.substr(start));
+}
+
+bool
+WebGazebo::GetValue(std::string& value,
+                    struct evkeyvalq* query_args, 
+                    const std::string& key)
+{
+  for(struct evkeyval* kv = ((struct evkeyval*)&query_args)->next.tqe_next;
+      kv;
+      kv = kv->next.tqe_next)
+  {
+    if(key == kv->key)
+    {
+      value = kv->value;
+      printf("setting %s to %s (%s)\n", 
+             key.c_str(), kv->value, value.c_str());
+      return true;
+    }
+  }
+  return false;
+}

Modified: code/branches/federation/gazebo/webgazebo/WebGazebo.hh
===================================================================
--- code/branches/federation/gazebo/webgazebo/WebGazebo.hh      2009-03-09 
02:59:16 UTC (rev 7395)
+++ code/branches/federation/gazebo/webgazebo/WebGazebo.hh      2009-03-09 
05:40:51 UTC (rev 7396)
@@ -1,4 +1,6 @@
 #include <string>
+#include <vector>
+#include <map>
 
 // These headers must be included prior to the libevent headers
 #include <sys/types.h>
@@ -15,7 +17,8 @@
 class WebGazebo
 {
   public:
-    WebGazebo(std::string _host, int _port);
+    WebGazebo(std::string _host, int _port,
+              double dtol, double atol);
     ~WebGazebo();
 
     void Spin();
@@ -23,14 +26,38 @@
   private:
     std::string host;
     int port;
+    double sq_dist_tol, sq_ang_tol;
 
     struct evhttp* eh;
 
     gazebo::Client *client;
     gazebo::SimulationIface *simIface;
 
+    // Available models
+    std::map<std::string,int> models;
+
     // Static, so that it can be passed as a callback to libevent
     static void EventCallback(evhttp_request* req, void* arg);
 
-    bool GetPose(gazebo::Pose* pose, std::string model);
+    bool CheckTolerances(gazebo::Pose p, gazebo::Pose q);
+    bool GetModelList();
+    bool HasModel(const std::string& name);
+    bool GetPose(std::string model, gazebo::Pose& pose);
+    bool SetPose(std::string model, const gazebo::Pose& pose);
+    void StringSplit(const std::string &s, 
+                     std::vector<std::string> &t, 
+                     const std::string &d);
+    bool GetValue(std::string& value,
+                  struct evkeyvalq* query_args, 
+                  const std::string& key);
+    bool HandleURI(const std::string& model,
+                   const std::string& prop,
+                   const std::string& action,
+                   struct evkeyvalq* kv,
+                   std::string& response);
+    bool ParseURI(std::string& model,
+                  std::string& prop,
+                  std::string& action,
+                  std::string uri,
+                  std::string& response);
 };

Modified: code/branches/federation/gazebo/webgazebo/main.cc
===================================================================
--- code/branches/federation/gazebo/webgazebo/main.cc   2009-03-09 02:59:16 UTC 
(rev 7395)
+++ code/branches/federation/gazebo/webgazebo/main.cc   2009-03-09 05:40:51 UTC 
(rev 7396)
@@ -9,6 +9,7 @@
 
 int g_port = DEFAULT_PORT;
 std::string g_host = DEFAULT_HOST;
+double g_dtol, g_atol;
 
 bool ParseArgs(int argc, char** argv);
 
@@ -23,7 +24,7 @@
 
   try
   {
-    WebGazebo wg(g_host, g_port);
+    WebGazebo wg(g_host, g_port, g_dtol, g_atol);
     wg.Spin();
   }
   catch(std::string e)
@@ -38,7 +39,7 @@
 bool
 ParseArgs(int argc, char** argv)
 {
-  char *flags = (char*)("p:h:");
+  char *flags = (char*)("p:h:d:a:");
   int ch;
 
   while ((ch = getopt(argc, argv, flags)) != -1)
@@ -57,6 +58,18 @@
           return false;
         g_host = optarg;
         break;
+      // distance tolerance
+      case 'd':
+        if(!optarg)
+          return false;
+        g_dtol = atof(optarg);
+        break;
+      // angular tolerance
+      case 'a':
+        if(!optarg)
+          return false;
+        g_atol = atof(optarg);
+        break;
       default:
         return false;
     }


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to