00001 #include <spatial_world_model/spatial_world_model_server.h>
00002
00003 #include <boost/algorithm/string.hpp>
00004
00005 using namespace std;
00006
00007 spatial_world_model_server::spatial_world_model_server() : private_("~")
00008 {
00009
00010 private_.param("host", host_, string(SWM_DEFAULT_SERVER));
00011 private_.param("port", port_, SWM_DEFAULT_PORT);
00012 private_.param("user", user_, string(SWM_DEFAULT_USER));
00013 private_.param("password", password_, string(SWM_DEFAULT_PASSWORD));
00014 private_.param("database", database_, string(SWM_DEFAULT_DATABASE));
00015
00016
00017 connected_ = false;
00018 conn_ = mysql_init(NULL);
00019 if (!mysql_real_connect(conn_, host_.c_str(), user_.c_str(), password_.c_str(), database_.c_str(), port_, NULL, 0))
00020 {
00021 ROS_ERROR("MySQL Error: %s", mysql_error(conn_));
00022 exit(EXIT_FAILURE);
00023 } else
00024 {
00025 connected_ = true;
00026 }
00027
00028
00029 MYSQL_RES *res = this->query(SWM_CREATE_TABLE);
00030 if (res)
00031 {
00032 mysql_free_result(res);
00033 }
00034
00035
00036 store_observation_ = private_.advertiseService("store_observation", &spatial_world_model_server::store_observation_cb,
00037 this);
00038 find_observations_ = private_.advertiseService("find_observations",
00039 &spatial_world_model_server::find_observations_cb, this);
00040 set_observations_removed_ = private_.advertiseService("set_observations_removed",
00041 &spatial_world_model_server::set_observations_removed_cb, this);
00042
00043 ROS_INFO("Spatial World Model Initialized");
00044 }
00045
00046 spatial_world_model_server::~spatial_world_model_server()
00047 {
00048 if (connected_)
00049 {
00050 mysql_close(conn_);
00051 }
00052 }
00053
00054
00055 bool spatial_world_model_server::set_observations_removed_cb(
00056 interactive_world_msgs::SetObservationsRemoved::Request & req,
00057 interactive_world_msgs::SetObservationsRemoved::Response & resp)
00058 {
00059
00060 stringstream ss;
00061 ss << "UPDATE `" << SWM_TABLE "` SET `removed`=NOW() WHERE `id` IN (";
00062 for (size_t i = 0; i < req.ids.size(); i++)
00063 {
00064 ss << req.ids[i];
00065 if (i == req.ids.size() - 1)
00066 {
00067 ss << ")";
00068 } else
00069 {
00070 ss << ", ";
00071 }
00072 }
00073 ss << ";";
00074
00075 string sql = ss.str();
00076 MYSQL_RES *res = this->query(sql);
00077 if (res)
00078 {
00079 mysql_free_result(res);
00080 }
00081
00082 return true;
00083 }
00084
00085 bool spatial_world_model_server::find_observations_cb(interactive_world_msgs::FindObservations::Request &req,
00086 interactive_world_msgs::FindObservations::Response &resp)
00087 {
00088
00089 stringstream ss;
00090 ss << "SELECT * FROM `" << SWM_TABLE << "` WHERE (";
00091 if (!req.item.empty())
00092 {
00093 ss << "(UPPER(item) =\"" << boost::to_upper_copy(req.item) << "\") AND ";
00094 }
00095 if (!req.surface.empty())
00096 {
00097 ss << "(UPPER(surface) =\"" << boost::to_upper_copy(req.surface) << "\") AND ";
00098 }
00099 if (!req.surface_frame_id.empty())
00100 {
00101 ss << "(UPPER(surface_frame_id) =\"" << boost::to_upper_copy(req.surface_frame_id) << "\") AND ";
00102 }
00103 if (!req.placement_surface_frame_id.empty())
00104 {
00105 ss << "(UPPER(placement_surface_frame_id) =\"" << boost::to_upper_copy(req.placement_surface_frame_id) <<
00106 "\") AND ";
00107 }
00108 if (req.removed)
00109 {
00110 ss << "(removed > '0000-00-00 00:00:00')) ";
00111 } else
00112 {
00113 ss << "(removed >= '0000-00-00 00:00:00')) ";
00114 }
00115 ss << "ORDER BY `time` DESC;";
00116 string query = ss.str();
00117
00118 MYSQL_RES *res = this->query(query);
00119 if (res)
00120 {
00121 MYSQL_ROW row;
00122 while ((row = mysql_fetch_row(res)) != NULL)
00123 {
00124 resp.ids.push_back(atoi(row[0]));
00125 resp.surfaces.push_back(string(row[1]));
00126 resp.surface_frame_ids.push_back(string(row[2]));
00127 resp.placement_surface_frame_ids.push_back(string(row[3]));
00128 resp.items.push_back(string(row[4]));
00129 resp.item_confs.push_back(atof(row[5]));
00130 resp.xs.push_back(atof(row[6]));
00131 resp.ys.push_back(atof(row[7]));
00132 resp.zs.push_back(atof(row[8]));
00133 resp.thetas.push_back(atof(row[9]));;
00134 resp.times.push_back(ros::Time(this->extract_time(row[10]), 0));
00135 resp.removals.push_back(ros::Time(this->extract_time(row[11]), 0));
00136 }
00137 mysql_free_result(res);
00138 }
00139
00140 if (resp.surfaces.empty())
00141 {
00142 ROS_WARN("No instances of %s found in the spatial world model.", req.item.c_str());
00143 }
00144
00145 return true;
00146 }
00147
00148 bool spatial_world_model_server::store_observation_cb(interactive_world_msgs::StoreObservation::Request &req,
00149 interactive_world_msgs::StoreObservation::Response &resp)
00150 {
00151
00152 stringstream ss;
00153 ss << "INSERT INTO `" << SWM_TABLE << "`"
00154 << "(`surface`, `surface_frame_id`, `placement_surface_frame_id`, `item`, `item_conf`, `x`, `y`, `z`, `theta`)"
00155 << "VALUES ("
00156 << "\"" << req.surface << "\", "
00157 << "\"" << req.surface_frame_id << "\", "
00158 << "\"" << req.placement_surface_frame_id << "\", "
00159 << "\"" << req.item << "\", "
00160 << "" << req.item_conf << ", "
00161 << "" << req.x << ", "
00162 << "" << req.y << ", "
00163 << "" << req.z << ", "
00164 << "" << req.theta
00165 << ");";
00166
00167 MYSQL_RES *res = this->query(ss.str());
00168 if (res)
00169 {
00170 mysql_free_result(res);
00171 }
00172
00173 return true;
00174 }
00175
00176 bool spatial_world_model_server::connected()
00177 {
00178 return connected_;
00179 }
00180
00181 MYSQL_RES *spatial_world_model_server::query(string query)
00182 {
00183 if (mysql_query(conn_, query.c_str()) == 0)
00184 {
00185
00186 return mysql_use_result(conn_);
00187 } else
00188 {
00189 ROS_ERROR("MySQL Error: %s", mysql_error(conn_));
00190 }
00191
00192
00193 return NULL;
00194 }
00195
00196 time_t spatial_world_model_server::extract_time(const string &str) const
00197 {
00198 if (str == "0000-00-00 00:00:00")
00199 {
00200 return 0;
00201 }
00202
00203 struct tm t;
00204 bzero(&t, sizeof(t));
00205 sscanf(str.c_str(), "%d-%d-%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec);
00206
00207 t.tm_year -= 1900;
00208 t.tm_mon -= 1;
00209
00210 t.tm_hour -= 1;
00211 return mktime(&t);
00212 }
00213
00214 int main(int argc, char **argv)
00215 {
00216
00217 ros::init(argc, argv, "spatial_world_model_server");
00218 spatial_world_model_server server;
00219 ros::spin();
00220 }