interactive_world_parser.cpp
Go to the documentation of this file.
00001 #include <interactive_world_parser/interactive_world_parser.hpp>
00002 #include <geometry_msgs/Point.h>
00003 #include <fstream>
00004 #include <pwd.h>
00005 
00006 using namespace std;
00007 
00008 interactive_world_parser::interactive_world_parser() :
00009     private_("~")
00010 {
00011   // grab params
00012   private_.param("host", host_, string(RMS_DEFAULT_SERVER));
00013   private_.param("port", port_, RMS_DEFAULT_PORT);
00014   private_.param("user", user_, string(RMS_DEFAULT_USER));
00015   private_.param("password", password_, string(RMS_DEFAULT_PASSWORD));
00016   private_.param("database", database_, string(RMS_DEFAULT_DATABASE));
00017 
00018   // create the client
00019   client_ = new librms::rms(host_, (unsigned int) port_, user_, password_, database_);
00020 
00021   // attempt to connection
00022   if (!client_->connect())
00023   {
00024     ROS_ERROR("Fatal: could not connect to the RMS database.");
00025     exit(EXIT_FAILURE);
00026   }
00027 
00028   // setup servers
00029   parse_and_store_ = private_.advertiseService("parse_and_store", &interactive_world_parser::parse_and_store_cb, this);
00030   parse_and_save_ = private_.advertiseService("parse_and_save", &interactive_world_parser::parse_and_save_cb, this);
00031 
00032   // wait for external service
00033   learn_hypotheses_ = private_.serviceClient<interactive_world_msgs::LearnModels>("/interactive_world_learner/learn_hypotheses");
00034   ROS_INFO("Waiting for /interactive_world_learner/learn_hypotheses...");
00035   learn_hypotheses_.waitForExistence(ros::DURATION_MAX);
00036 
00037   ROS_INFO("Interactive World Parser Initialized");
00038 }
00039 
00040 
00041 interactive_world_parser::~interactive_world_parser()
00042 {
00043   delete client_;
00044 }
00045 
00046 static int __limit__ = 0;
00047 
00048 static bool cond(const interactive_world_msgs::PlacementSet &set)
00049 {
00050   return set.placements.size() < __limit__;
00051 }
00052 
00053 
00054 void interactive_world_parser::parse(int study_id)
00055 {
00056   ROS_INFO("=== BEGINING PARSE ===");
00057   data_.clear();
00058   librms::study study = client_->get_study(study_id);
00059   ROS_INFO("Running over study \"%s\"...", study.get_name().c_str());
00060 
00061   // grab the conditions
00062   vector<librms::condition> &conditions = study.get_conditions();
00063   ROS_INFO("+ Found %d conditions.", (int) conditions.size());
00064   for (uint i = 0; i < conditions.size(); i++)
00065   {
00066     librms::condition &condition = conditions[i];
00067     ROS_INFO("+ Parsing condition \"%s\"...", condition.get_name().c_str());
00068     int num_experiments = 0;
00069     int num_completed = 0;
00070     int num_placements = 0;
00071 
00072     vector<librms::slot> &slots = condition.get_slots();
00073     ROS_INFO("++ Parsing %d slots...",(int) slots.size());
00074     for (uint j = 0; j < slots.size(); j++)
00075     {
00076       librms::slot &slot = slots[j];
00077       if (slot.has_appointment())
00078       {
00079         // check for logs
00080         librms::appointment &appointment = slot.get_appointment();
00081         vector<librms::log> &logs = appointment.get_logs();
00082         if (logs.size() > 1)
00083         {
00084           bool completion = false;
00085           num_experiments++;
00086           interactive_world_msgs::Configuration config;
00087           for (uint k = 0; k < logs.size(); k++)
00088           {
00089             librms::log &log = logs[k];
00090 
00091             // parse the JSON
00092             Json::Value json;
00093             Json::Reader reader;
00094             reader.parse(log.get_entry(), json, false);
00095 
00096             // grab the initial configuration
00097             if (log.get_label().compare("config") == 0)
00098             {
00099               config = parse_json_config(json);
00100             } else if (log.get_label().compare("completion") == 0)
00101             {
00102               if (!completion)
00103               {
00104                 completion = true;
00105                 num_completed++;
00106               }
00107             } else
00108             {
00109               // parse the placements
00110               num_placements++;
00111               parse_json_placement(json, config, condition.get_id(), logs);
00112             }
00113           }
00114         }
00115       }
00116     }
00117     ROS_INFO("++ %d/%d completed sessions with %d placements.", num_completed, num_experiments, num_placements);
00118     __limit__ = (int) (num_placements * 0.05);
00119     ROS_INFO("++ Removing data sets with less than %d placements...", __limit__);
00120     vector<interactive_world_msgs::PlacementSet> &v = data_[condition.get_id()].data;
00121     v.erase(remove_if(v.begin(), v.end(), cond), v.end());
00122   }
00123 
00124   ROS_INFO("=== PARSE FINISHED ===");
00125 }
00126 
00127 void interactive_world_parser::save()
00128 {
00129   ROS_INFO("Writing data...");
00130   // save the data
00131   for (map<uint, interactive_world_msgs::TaskTrainingData>::iterator it = data_.begin(); it != data_.end(); ++it)
00132   {
00133     uint condition_id = it->first;
00134     interactive_world_msgs::TaskTrainingData &training = it->second;
00135     for (uint i = 0; i < training.data.size(); i++)
00136     {
00137       interactive_world_msgs::PlacementSet &placements = training.data[i];
00138       stringstream ss;
00139       ss << (getpwuid(getuid()))->pw_dir << "/" << condition_id << "-" << placements.item.name << "-in-" << placements.room.name << "-on-" << placements.surface.name << "-wrt-" << placements.reference_frame_id << ".csv";
00140       ofstream file;
00141       file.open(ss.str().c_str());
00142       for (uint j = 0; j < placements.placements.size(); j++)
00143       {
00144         interactive_world_msgs::Placement &placement = placements.placements[j];
00145         file << placement.position.x << "," << placement.position.y << "," << placement.position.z << "," << placement.rotation << endl;
00146       }
00147       file.close();
00148     }
00149   }
00150   ROS_INFO("Finished!");
00151 }
00152 
00153 void interactive_world_parser::learn()
00154 {
00155   ROS_INFO("=== BEGINING MODEL LEARNING ===");
00156   // save the data
00157   for (map<uint, interactive_world_msgs::TaskTrainingData>::iterator it = data_.begin(); it != data_.end(); ++it)
00158   {
00159     uint condition_id = it->first;
00160     interactive_world_msgs::TaskTrainingData &training = it->second;
00161     ROS_INFO("Sending condition %d data off to jinteractiveworld...", condition_id);
00162     // construct the message
00163     interactive_world_msgs::LearnModels srv;
00164     srv.request.host = host_;
00165     srv.request.port = port_;
00166     srv.request.user = user_;
00167     srv.request.password = password_;
00168     srv.request.database = database_;
00169     srv.request.condition_id = condition_id;
00170     srv.request.data = it->second;
00171     learn_hypotheses_.call(srv);
00172     ROS_INFO("Condition %d models learned.", condition_id);
00173   }
00174   ROS_INFO("=== MODEL LEARNING FINISHED ===");
00175 }
00176 
00177 bool interactive_world_parser::parse_and_store_cb(interactive_world_msgs::Parse::Request &req, interactive_world_msgs::Parse::Response &resp)
00178 {
00179   this->parse(req.study_id);
00180   this->learn();
00181   return true;
00182 }
00183 
00184 
00185 bool interactive_world_parser::parse_and_save_cb(interactive_world_msgs::Parse::Request &req, interactive_world_msgs::Parse::Response &resp)
00186 {
00187   this->parse(req.study_id);
00188   this->save();
00189   return true;
00190 }
00191 
00192 
00193 interactive_world_msgs::Configuration interactive_world_parser::parse_json_config(Json::Value &config)
00194 {
00195   interactive_world_msgs::Configuration configuration;
00196 
00197   // task description
00198   configuration.task = config["task"].asString();
00199   // objects
00200   Json::Value objects = config["objects"];
00201   for (uint i = 0; i < objects.size(); i++)
00202   {
00203     Json::Value cur_object = objects[i];
00204     interactive_world_msgs::Item item;
00205     item.name = cur_object["name"].asString();
00206     item.width = cur_object["width"].asDouble();
00207     item.height = cur_object["height"].asDouble();
00208     configuration.items.push_back(item);
00209   }
00210   // rooms
00211   Json::Value rooms = config["rooms"];
00212   for (uint i = 0; i < rooms.size(); i++)
00213   {
00214     Json::Value cur_room = rooms[i];
00215     interactive_world_msgs::Room room;
00216     room.name = cur_room["name"].asString();
00217     room.width = cur_room["width"].asDouble();
00218     room.height = cur_room["height"].asDouble();
00219     room.pose = parse_json_pose(cur_room["position"], cur_room["rotation"].asDouble());
00220     // surfaces
00221     Json::Value surfaces = cur_room["furniture"];
00222     for (uint j = 0; j < surfaces.size(); j++)
00223     {
00224       Json::Value cur_surface = surfaces[j];
00225       interactive_world_msgs::Surface surface;
00226       surface.name = cur_surface["name"].asString();
00227       surface.width = cur_surface["width"].asDouble();
00228       surface.height = cur_surface["height"].asDouble();
00229       surface.pose = parse_json_pose(cur_surface["position"], cur_surface["rotation"].asDouble());
00230       // POIs
00231       Json::Value pois = cur_surface["poi"];
00232       for (uint k = 0; k < pois.size(); k++)
00233       {
00234         Json::Value cur_poi = pois[k];
00235         interactive_world_msgs::PointOfInterest poi;
00236         poi.name = cur_poi["name"].asString();
00237         poi.width = cur_poi["width"].asDouble();
00238         poi.height = cur_poi["height"].asDouble();
00239         poi.pose = parse_json_pose(cur_poi["position"], cur_poi["rotation"].asDouble());
00240         surface.pois.push_back(poi);
00241       }
00242       room.surfaces.push_back(surface);
00243     }
00244     configuration.rooms.push_back(room);
00245   }
00246 
00247   return configuration;
00248 }
00249 
00250 void interactive_world_parser::parse_json_placement(Json::Value &placement, interactive_world_msgs::Configuration &config, unsigned int condition_id, vector<librms::log> logs)
00251 {
00252   // parse the JSON
00253   Json::Value json_furniture = placement["furniture"];
00254   Json::Value json_furniture_position = json_furniture["position"];
00255   Json::Value json_furniture_surface = json_furniture["surface"];
00256   Json::Value json_furniture_surface_position = json_furniture_surface["position"];
00257   Json::Value json_object = json_furniture_surface["object"];
00258   Json::Value json_object_position = json_object["position"];
00259 
00260   string room_name = placement["name"].asString();
00261   string surface_name = json_furniture["name"].asString();
00262   string object_name = json_object["name"].asString();
00263 
00264   interactive_world_msgs::Item item_msg;
00265   interactive_world_msgs::Room room_msg;
00266   interactive_world_msgs::Surface surface_msg;
00267 
00268   // get what we need from the config
00269   vector<interactive_world_msgs::PointOfInterest> pois;
00270   for (uint i = 0; i < config.rooms.size(); i++)
00271   {
00272     interactive_world_msgs::Room &room = config.rooms[i];
00273     if (room.name.compare(room_name) == 0)
00274     {
00275       room_msg = config.rooms[i];
00276       for (uint j = 0; j < room.surfaces.size(); j++)
00277       {
00278         interactive_world_msgs::Surface &surface = room.surfaces[j];
00279         if (surface.name.compare(surface_name) == 0)
00280         {
00281           surface_msg = room.surfaces[j];
00282           pois = surface.pois;
00283           break;
00284         }
00285       }
00286       break;
00287     }
00288   }
00289   for (uint i = 0; i < config.items.size(); i++)
00290   {
00291     interactive_world_msgs::Item &item = config.items[i];
00292     if (item.name.compare(object_name) == 0)
00293     {
00294       item_msg = config.items[i];
00295       break;
00296     }
00297   }
00298 
00299   // grab the surface info
00300   tf2::Transform t_room_surface = parse_json_tf(json_furniture_position, json_furniture["rotation"].asDouble());
00301 
00302   // placement surface
00303   tf2::Transform t_surface_psurface = parse_json_tf(json_furniture_surface_position, json_furniture_surface["rotation"].asDouble());
00304 
00305   // psurface to the object
00306   tf2::Transform t_psurface_object = parse_json_tf(json_object_position, json_object["rotation"].asDouble());
00307 
00308   // get the object in room and furniture coords
00309   tf2::Transform t_surface_object = t_surface_psurface * t_psurface_object;
00310   tf2::Transform t_room_object = t_room_surface * t_surface_psurface * t_psurface_object;
00311 
00312   // store the placement on the surface
00313   add_placement_to_data(condition_id, t_surface_object, item_msg, room_msg, surface_msg, surface_name);
00314 
00315   // check for POIs
00316   vector<string> used_names;
00317   for (uint i = 0; i < pois.size(); i++)
00318   {
00319     // check if this is a new POI type
00320     string cur_poi_name = pois[i].name;
00321     if (find(used_names.begin(), used_names.end(), cur_poi_name) == used_names.end())
00322     {
00323       used_names.push_back(cur_poi_name);
00324 
00325       // find the closest of this kind
00326       double closest_dist = numeric_limits<double>::infinity();
00327       tf2::Transform closest_t;
00328       for (uint j = 0; j < pois.size(); j++)
00329       {
00330         interactive_world_msgs::PointOfInterest cur_poi = pois[j];
00331         if (cur_poi_name.compare(cur_poi.name) == 0)
00332         {
00333           double distance = t_surface_object.getOrigin().distance(tf2::Vector3(cur_poi.pose.position.x, cur_poi.pose.position.y, cur_poi.pose.position.z));
00334           if (distance < closest_dist)
00335           {
00336             closest_dist = distance;
00337             closest_t = pose_to_tf(cur_poi.pose);
00338           }
00339         }
00340       }
00341       // convert to POI frame
00342       tf2::Transform t_poi_object = closest_t.inverseTimes(t_surface_object);
00343       // store the value
00344       add_placement_to_data(condition_id, t_poi_object, item_msg, room_msg, surface_msg, cur_poi_name);
00345     }
00346   }
00347 
00348   // place next to each closest item
00349   for (int i = 0; i < config.items.size(); i++)
00350   {
00351     interactive_world_msgs::Item &item = config.items[i];
00352     if (item.name.compare(object_name) != 0)
00353     {
00354       // search the logs again for the object
00355       double closest_dist = numeric_limits<double>::infinity();
00356       tf2::Transform closest_t;
00357       for (int j = 0; j < logs.size(); j++)
00358       {
00359         librms::log &log = logs[j];
00360         // grab the initial configuration
00361         if (log.get_label().compare("config") != 0 && log.get_label().compare("completion") != 0)
00362         {
00363           // parse the JSON
00364           Json::Value json;
00365           Json::Reader reader;
00366           reader.parse(log.get_entry(), json, false);
00367           // parse the JSON
00368           Json::Value json_furniture2 = json["furniture"];
00369           Json::Value json_furniture_position2 = json_furniture2["position"];
00370           Json::Value json_furniture_surface2 = json_furniture2["surface"];
00371           Json::Value json_furniture_surface_position2 = json_furniture_surface2["position"];
00372           Json::Value json_object2 = json_furniture_surface2["object"];
00373           Json::Value json_object_position2 = json_object2["position"];
00374           // only compare on the same furniture
00375           if (json["name"].asString().compare(room_name) == 0 && json_furniture2["name"].asString().compare(surface_name) == 0 && json_object2["name"].asString().compare(item.name) == 0)
00376           {
00377             // convert to the surface frame
00378             tf2::Transform t_surface_psurface2 = parse_json_tf(json_furniture_surface_position2, json_furniture_surface2["rotation"].asDouble());
00379             tf2::Transform t_psurface_object2 = parse_json_tf(json_object_position2, json_object2["rotation"].asDouble());
00380             tf2::Transform t_surface_object2 = t_surface_psurface2 * t_psurface_object2;
00381             // compute the distance
00382             double distance = t_surface_object.getOrigin().distance(t_surface_object2.getOrigin());
00383             if (distance < closest_dist)
00384             {
00385               closest_dist = distance;
00386               closest_t = t_surface_object2;
00387             }
00388           }
00389         }
00390       }
00391       // check if we found a closest match
00392       if (closest_dist < numeric_limits<double>::infinity())
00393       {
00394         // convert to object2 frame
00395         tf2::Transform t_object2_object = closest_t.inverseTimes(t_surface_object);
00396         // store the value (room/surface doesn't matter)
00397         interactive_world_msgs::Room tmp_room;
00398         interactive_world_msgs::Surface tmp_surface;
00399         add_placement_to_data(condition_id, t_object2_object, item_msg, tmp_room, tmp_surface, item.name);
00400       }
00401     }
00402   }
00403 }
00404 
00405 tf2::Transform interactive_world_parser::parse_json_tf(Json::Value &position, double rotation)
00406 {
00407   tf2::Quaternion q(Z_AXIS_TF2, rotation);
00408   tf2::Vector3 v(position["x"].asDouble(), position["y"].asDouble(), position["z"].asDouble());
00409   tf2::Transform tf(q, v);
00410   return tf;
00411 }
00412 
00413 tf2::Transform interactive_world_parser::pose_to_tf(geometry_msgs::Pose &pose)
00414 {
00415   tf2::Quaternion q(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);
00416   tf2::Vector3 v(pose.position.x, pose.position.y, pose.position.z);
00417   tf2::Transform tf(q, v);
00418   return tf;
00419 }
00420 
00421 geometry_msgs::Pose interactive_world_parser::parse_json_pose(Json::Value &position, double rotation)
00422 {
00423   geometry_msgs::Pose p;
00424   p.position.x = position["x"].asDouble();
00425   p.position.y = position["y"].asDouble();
00426   p.position.z = position["z"].asDouble();
00427 
00428   // create the rotation
00429   tf2::Quaternion q(Z_AXIS_TF2, rotation);
00430   p.orientation.x = q.x();
00431   p.orientation.y = q.y();
00432   p.orientation.z = q.z();
00433   p.orientation.w = q.w();
00434 
00435   return p;
00436 }
00437 
00438 void interactive_world_parser::add_placement_to_data(uint condition_id, tf2::Transform &tf, interactive_world_msgs::Item item, interactive_world_msgs::Room room, interactive_world_msgs::Surface surface, string reference_frame_id)
00439 {
00440   if (data_.find(condition_id) == data_.end())
00441   {
00442     data_[condition_id] = interactive_world_msgs::TaskTrainingData();
00443   }
00444   interactive_world_msgs::TaskTrainingData &training = data_[condition_id];
00445 
00446   // create the placement
00447   interactive_world_msgs::Placement placement;
00448   placement.item = item;
00449   placement.room = room;
00450   placement.surface = surface;
00451   placement.reference_frame_id = reference_frame_id;
00452   placement.rotation = tf.getRotation().getAngle();
00453   placement.position.x = tf.getOrigin().x();
00454   placement.position.y = tf.getOrigin().y();
00455   placement.position.z = tf.getOrigin().z();
00456 
00457   // search for the correct frame
00458   for (uint i = 0; i < training.data.size(); i++)
00459   {
00460     interactive_world_msgs::PlacementSet &placements = training.data[i];
00461     if (placements.item.name.compare(item.name) == 0 && placements.room.name.compare(room.name) == 0 && placements.surface.name.compare(surface.name) == 0 && placements.reference_frame_id.compare(reference_frame_id) == 0)
00462     {
00463       placements.placements.push_back(placement);
00464       return;
00465     }
00466   }
00467 
00468   // new entry
00469   interactive_world_msgs::PlacementSet set;
00470   set.reference_frame_id = reference_frame_id;
00471   set.item = item;
00472   set.room = room;
00473   set.surface = surface;
00474   set.placements.push_back(placement);
00475   training.data.push_back(set);
00476 }
00477 
00478 int main(int argc, char **argv)
00479 {
00480   // initialize ROS and the node
00481   ros::init(argc, argv, "interactive_world_parser");
00482 
00483   interactive_world_parser parser;
00484 
00485   ros::spin();
00486 }


interactive_world_parser
Author(s): Russell Toris
autogenerated on Thu Jun 6 2019 21:34:25