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
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
00019 client_ = new librms::rms(host_, (unsigned int) port_, user_, password_, database_);
00020
00021
00022 if (!client_->connect())
00023 {
00024 ROS_ERROR("Fatal: could not connect to the RMS database.");
00025 exit(EXIT_FAILURE);
00026 }
00027
00028
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
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
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
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
00092 Json::Value json;
00093 Json::Reader reader;
00094 reader.parse(log.get_entry(), json, false);
00095
00096
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
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
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
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
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
00198 configuration.task = config["task"].asString();
00199
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
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
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
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
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
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
00300 tf2::Transform t_room_surface = parse_json_tf(json_furniture_position, json_furniture["rotation"].asDouble());
00301
00302
00303 tf2::Transform t_surface_psurface = parse_json_tf(json_furniture_surface_position, json_furniture_surface["rotation"].asDouble());
00304
00305
00306 tf2::Transform t_psurface_object = parse_json_tf(json_object_position, json_object["rotation"].asDouble());
00307
00308
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
00313 add_placement_to_data(condition_id, t_surface_object, item_msg, room_msg, surface_msg, surface_name);
00314
00315
00316 vector<string> used_names;
00317 for (uint i = 0; i < pois.size(); i++)
00318 {
00319
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
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
00342 tf2::Transform t_poi_object = closest_t.inverseTimes(t_surface_object);
00343
00344 add_placement_to_data(condition_id, t_poi_object, item_msg, room_msg, surface_msg, cur_poi_name);
00345 }
00346 }
00347
00348
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
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
00361 if (log.get_label().compare("config") != 0 && log.get_label().compare("completion") != 0)
00362 {
00363
00364 Json::Value json;
00365 Json::Reader reader;
00366 reader.parse(log.get_entry(), json, false);
00367
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
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
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
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
00392 if (closest_dist < numeric_limits<double>::infinity())
00393 {
00394
00395 tf2::Transform t_object2_object = closest_t.inverseTimes(t_surface_object);
00396
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
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
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
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
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
00481 ros::init(argc, argv, "interactive_world_parser");
00482
00483 interactive_world_parser parser;
00484
00485 ros::spin();
00486 }