00001 #include "ros/ros.h"
00002 #include "nav_msgs/Odometry.h"
00003 #include "opencv2/highgui/highgui.hpp"
00004 #include "opencv2/imgproc/imgproc.hpp"
00005 #include "sensor_msgs/image_encodings.h"
00006 #include "tf/transform_broadcaster.h"
00007 #include "cirkit_waypoint_navigator/TeleportAbsolute.h"
00008
00009 #include <stdio.h>
00010
00011 const static std::string PARAM_NAME_RATIO_PARAM = "/ratio";
00012 const static std::string MAP_PATH = "/map/";
00013 const static std::string PARAM_NAME_MAP_NAME = "/image";
00014 const static std::string PARAM_NAME_MAP_RESOLUTION = "/resolution";
00015 const static std::string PARAM_NAME_MAP_ORIGIN = "/origin";
00016 const static std::string MAP_WINDOW_NAME = "Map Monitor";
00017 const static int ROS_SPIN_RATE = 100;
00018 const static int CV_WAIT_KEY_RATE = 50;
00019 const static cv::Scalar RED = cv::Scalar(0, 0, 255);
00020 const static cv::Scalar GREEN = cv::Scalar(0, 128, 0);
00021 const static cv::Scalar BLUE = cv::Scalar(255, 0, 0);
00022 const static int ARROW_LENGTH = 10;
00023
00024
00025 const static std::string DEFAULT_MAP_NAME = "201510240538.pgm";
00026 const static double DEFAULT_MAP_RESOLUTION = 0.1;
00027 const static double DEFAULT_RESIZE_RATIO = 0.2;
00028
00029 enum WAIT_KEY_MODE
00030 {
00031 CURR_POSITON,
00032 HISTORY_POSITION,
00033 QUIT
00034 };
00035
00036 enum RESULT
00037 {
00038 OK,
00039 NG
00040 };
00041
00042 enum MAP_COORD
00043 {
00044 INDEX_X,
00045 INDEX_Y,
00046 INDEX_Z
00047 };
00048
00049
00050 class RemoteMonitorServer
00051 {
00052 public:
00053 bool getRobotPose(cirkit_waypoint_navigator::TeleportAbsolute::Request &req,
00054 cirkit_waypoint_navigator::TeleportAbsolute::Response &res);
00055 bool getHumanPose(cirkit_waypoint_navigator::TeleportAbsolute::Request &req,
00056 cirkit_waypoint_navigator::TeleportAbsolute::Response &res);
00057
00058 RemoteMonitorServer(const std::string i_image_path, const std::string i_name_space)
00059 : rate_(ROS_SPIN_RATE), state_(CURR_POSITON)
00060 {
00061
00062
00063 map_origin_.clear();
00064 server_robot_pose_ = nh_.advertiseService<cirkit_waypoint_navigator::TeleportAbsolute::Request,
00065 cirkit_waypoint_navigator::TeleportAbsolute::Response>
00066 ("remote_monitor_robot_pose", boost::bind(&RemoteMonitorServer::getRobotPose, this, _1, _2));
00067 server_human_pose_ = nh_.advertiseService<cirkit_waypoint_navigator::TeleportAbsolute::Request,
00068 cirkit_waypoint_navigator::TeleportAbsolute::Response>
00069 ("remote_monitor_human_pose", boost::bind(&RemoteMonitorServer::getHumanPose, this, _1, _2));
00070
00071 this->loadRosParam(i_image_path, i_name_space);
00072 }
00073
00074 void drawRobotPoseOnMap(cirkit_waypoint_navigator::TeleportAbsolute::Request &req)
00075 {
00076
00077 drawArrow(map_img_pos_curr_, req);
00078
00079 drawArrow(map_img_pos_hist_, req);
00080 }
00081
00082 void drawArrow(cv::Mat &img, cirkit_waypoint_navigator::TeleportAbsolute::Request &req)
00083 {
00084
00085 map_img_ori_small_.copyTo(map_img_pos_curr_);
00086
00087 double x_map_center = (req.x - map_origin_[INDEX_X]) * resize_ratio_curr_ / map_resolution_;
00088 double y_map_center = map_img_pos_curr_.rows - (req.y - map_origin_[INDEX_Y]) / map_resolution_ * resize_ratio_curr_;
00089
00090 int w = 10;
00091 int h = 15;
00092 int lineType = 8;
00093
00095 cv::Point rook_points[1][4];
00096 double p1_x_ori = (x_map_center-w*0.5) + w*0.5;
00097 double p1_y_ori = (y_map_center-h*0.5) + 0.0;
00098 double p2_x_ori = (x_map_center-w*0.5) + 0;
00099 double p2_y_ori = (y_map_center-h*0.5) + h;
00100 double p3_x_ori = (x_map_center-w*0.5) + w*0.5;
00101 double p3_y_ori = (y_map_center-h*0.5) + h*0.7;
00102 double p4_x_ori = (x_map_center-w*0.5) + w;
00103 double p4_y_ori = (y_map_center-h*0.5) + h;
00104
00105 double cos_rot = cos(-req.theta + M_PI*0.5);
00106 double sin_rot = sin(-req.theta + M_PI*0.5);
00107
00108 double p1_x_rot = cos_rot*(p1_x_ori-x_map_center) - sin_rot*(p1_y_ori-y_map_center);
00109 double p1_y_rot = sin_rot*(p1_x_ori-x_map_center) + cos_rot*(p1_y_ori-y_map_center);
00110 double p2_x_rot = cos_rot*(p2_x_ori-x_map_center) - sin_rot*(p2_y_ori-y_map_center);
00111 double p2_y_rot = sin_rot*(p2_x_ori-x_map_center) + cos_rot*(p2_y_ori-y_map_center);
00112 double p3_x_rot = cos_rot*(p3_x_ori-x_map_center) - sin_rot*(p3_y_ori-y_map_center);
00113 double p3_y_rot = sin_rot*(p3_x_ori-x_map_center) + cos_rot*(p3_y_ori-y_map_center);
00114 double p4_x_rot = cos_rot*(p4_x_ori-x_map_center) - sin_rot*(p4_y_ori-y_map_center);
00115 double p4_y_rot = sin_rot*(p4_x_ori-x_map_center) + cos_rot*(p4_y_ori-y_map_center);
00116
00117 p1_x_rot += x_map_center;
00118 p1_y_rot += y_map_center;
00119 p2_x_rot += x_map_center;
00120 p2_y_rot += y_map_center;
00121 p3_x_rot += x_map_center;
00122 p3_y_rot += y_map_center;
00123 p4_x_rot += x_map_center;
00124 p4_y_rot += y_map_center;
00125
00126 rook_points[0][0] = cv::Point(p1_x_rot, p1_y_rot);
00127 rook_points[0][1] = cv::Point(p2_x_rot, p2_y_rot);
00128 rook_points[0][2] = cv::Point(p3_x_rot, p3_y_rot);
00129 rook_points[0][3] = cv::Point(p4_x_rot, p4_y_rot);
00130
00131 const cv::Point* ppt[1] = { rook_points[0] };
00132 int npt[] = { 4 };
00133
00134 cv::fillPoly( img, ppt, npt, 1, GREEN, lineType );
00135 }
00136
00137 void drawHumanPoseOnMap(cirkit_waypoint_navigator::TeleportAbsolute::Request &req)
00138 {
00139
00140 map_img_ori_small_.copyTo(map_img_pos_curr_);
00141
00142 double x_map_center = (req.x - map_origin_[INDEX_X]) * resize_ratio_curr_ / map_resolution_;
00143 double y_map_center = map_img_pos_curr_.rows - (req.y - map_origin_[INDEX_Y]) / map_resolution_ * resize_ratio_curr_;
00144 point_curr_ = cv::Point(x_map_center, y_map_center);
00145
00146
00147 drawHuman(map_img_pos_curr_, point_curr_);
00148
00149 drawHuman(map_img_pos_hist_, point_curr_);
00150 }
00151
00152 void drawHuman(cv::Mat &img, const cv::Point2f pos)
00153 {
00154 const double body_len = 18.0;
00155 const double arm_len = 12.0;
00156 const double leg_len = 14.0;
00157 cv::Point point_body = cv::Point(pos.x, pos.y + body_len);
00158 cv::Point point_chest = cv::Point(pos.x, pos.y + body_len * 0.7);
00159 cv::Point point_arm_r = cv::Point(pos.x + arm_len, pos.y + arm_len * 0.25);
00160 cv::Point point_arm_l = cv::Point(pos.x - arm_len, pos.y + arm_len * 0.25);
00161 cv::Point point_leg_r = cv::Point(pos.x + leg_len * 0.25, pos.y + body_len + leg_len);
00162 cv::Point point_leg_l = cv::Point(pos.x - leg_len * 0.25, pos.y + body_len + leg_len);
00163
00164
00165 cv::circle(img, point_curr_, 7, RED, -1, CV_AA);
00166 cv::line(img, point_curr_, point_body, RED, 2);
00167 cv::line(img, point_chest, point_arm_r, RED, 2);
00168 cv::line(img, point_chest, point_arm_l, RED, 2);
00169 cv::line(img, point_body, point_leg_r, RED, 2);
00170 cv::line(img, point_body, point_leg_l, RED, 2);
00171 }
00172
00173 int waitKeyJudge(const int i_key)
00174 {
00175 int ret = 0;
00176
00177
00178 if(i_key == 'c' || i_key == 'C')
00179 {
00180 ret = CURR_POSITON;
00181 }
00182
00183 else if(i_key == 'h' || i_key == 'H')
00184 {
00185 ret = HISTORY_POSITION;
00186 }
00187
00188 else if(i_key == 'r' || i_key == 'R')
00189 {
00190
00191 map_img_ori_small_.copyTo(map_img_pos_hist_);
00192
00193 drawArrow(map_img_pos_curr_, req_);
00194
00195
00196 ret = state_;
00197 }
00198
00199 else if(i_key == 'p' || i_key == 'P')
00200 {
00201 resize_ratio_prev_ = resize_ratio_curr_;
00202 resize_ratio_curr_ += 0.05;
00203 ret = state_;
00204
00205
00206
00207 cv::resize(map_img_ori_, map_img_ori_small_, cv::Size(), resize_ratio_curr_, resize_ratio_curr_, cv::INTER_LINEAR);
00208 map_img_pos_curr_ = map_img_ori_small_.clone();
00209 map_img_pos_hist_ = map_img_ori_small_.clone();
00210
00211 drawRobotPoseOnMap(req_);
00212 }
00213
00214 else if(i_key == 'm' || i_key == 'M')
00215 {
00216 resize_ratio_prev_ = resize_ratio_curr_;
00217 resize_ratio_curr_ -= 0.05;
00218 ret = state_;
00219
00220
00221 cv::resize(map_img_ori_, map_img_ori_small_, cv::Size(), resize_ratio_curr_, resize_ratio_curr_, cv::INTER_LINEAR);
00222 map_img_pos_curr_ = map_img_ori_small_.clone();
00223 map_img_pos_hist_ = map_img_ori_small_.clone();
00224
00225 drawRobotPoseOnMap(req_);
00226 }
00227
00228 else if(i_key == 27 || i_key == 'q' || i_key == 'Q')
00229 {
00230 ret = QUIT;
00231 }
00232 else
00233 {
00234
00235 ret = true;
00236 }
00237
00238 return ret;
00239 }
00240
00241 void showMap()
00242 {
00243
00244 if(state_ == CURR_POSITON)
00245 {
00246 cv::imshow(MAP_WINDOW_NAME, map_img_pos_curr_);
00247 }
00248
00249 else if(state_ == HISTORY_POSITION)
00250 {
00251 cv::imshow(MAP_WINDOW_NAME, map_img_pos_hist_);
00252 }
00253 else
00254 {
00255 cv::imshow(MAP_WINDOW_NAME, map_img_pos_curr_);
00256 }
00257 }
00258
00259 void runMainLoop()
00260 {
00261 while(nh_.ok())
00262 {
00263
00264 int key = cv::waitKey(CV_WAIT_KEY_RATE);
00265 if(key >= 0)
00266 state_ = waitKeyJudge(key);
00267
00268 if(state_ == QUIT)
00269 break;
00270 else
00271 showMap();
00272
00273 ros::spinOnce();
00274 rate_.sleep();
00275 }
00276 }
00277
00278 int loadMapImage()
00279 {
00280 map_img_ori_ = cv::imread(image_path_);
00281
00282 if(map_img_ori_.rows == 0 || map_img_ori_.cols == 0)
00283 {
00284 ROS_ERROR("image path is %s was not found.", image_path_.c_str());
00285 return NG;
00286 }
00287
00288 ROS_INFO("image %s was successfully loaded.", image_path_.c_str());
00289
00290 cv::resize(map_img_ori_, map_img_ori_small_, cv::Size(), resize_ratio_curr_, resize_ratio_curr_, cv::INTER_LINEAR);
00291 map_img_pos_curr_ = map_img_ori_small_.clone();
00292 map_img_pos_hist_ = map_img_ori_small_.clone();
00293 }
00294
00295 private:
00296 void loadRosParam(const std::string i_image_path, const std::string i_name_space)
00297 {
00298
00299 image_path_ = i_image_path + MAP_PATH;
00300 nh_.param<std::string>(i_name_space + PARAM_NAME_MAP_NAME, image_name_, DEFAULT_MAP_NAME);
00301 image_path_ += image_name_;
00302 ROS_INFO("image path is %s.", image_path_.c_str());
00303
00304
00305 nh_.param(i_name_space + PARAM_NAME_RATIO_PARAM, resize_ratio_curr_, DEFAULT_RESIZE_RATIO);
00306
00307 nh_.param(i_name_space + PARAM_NAME_MAP_RESOLUTION, map_resolution_, DEFAULT_MAP_RESOLUTION);
00308
00309 XmlRpc::XmlRpcValue origin_list;
00310 nh_.getParam(i_name_space + PARAM_NAME_MAP_ORIGIN, origin_list);
00311 ROS_ASSERT(origin_list.getType() == XmlRpc::XmlRpcValue::TypeArray);
00312
00313 for (int32_t i = 0; i < origin_list.size(); ++i)
00314 {
00315 ROS_ASSERT(origin_list[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00316 map_origin_.push_back(static_cast<double>(origin_list[i]));
00317 }
00318 }
00319
00320 private:
00321 ros::NodeHandle nh_;
00322 ros::Rate rate_;
00323 ros::ServiceServer server_robot_pose_;
00324 ros::ServiceServer server_human_pose_;
00325 std::string image_path_;
00326 std::string image_name_;
00327 double resize_ratio_curr_;
00328 double resize_ratio_prev_;
00329 double map_resolution_;
00330 std::vector<double> map_origin_;
00331 cv::Point point_curr_;
00332 cv::Point point_tip_;
00333
00334 cv::Mat map_img_ori_;
00335 cv::Mat map_img_ori_small_;
00336 cv::Mat map_img_pos_curr_;
00337 cv::Mat map_img_pos_hist_;
00338
00339 cirkit_waypoint_navigator::TeleportAbsolute::Request req_;
00340 int state_;
00341 };
00342
00343
00344 bool RemoteMonitorServer::getRobotPose(cirkit_waypoint_navigator::TeleportAbsolute::Request &req,
00345 cirkit_waypoint_navigator::TeleportAbsolute::Response &res)
00346 {
00347 ROS_INFO("RobotPose: [x] -> %6.2f, [y] -> %6.2f, [theta] -> %6.2f", req.x, req.y, req.theta);
00348
00349 req_ = req;
00350 drawRobotPoseOnMap(req);
00351
00352 return true;
00353 }
00354
00355 bool RemoteMonitorServer::getHumanPose(cirkit_waypoint_navigator::TeleportAbsolute::Request &req,
00356 cirkit_waypoint_navigator::TeleportAbsolute::Response &res)
00357 {
00358 ROS_INFO("HumanPose: [x] -> %6.2f, [y] -> %6.2f, [theta] -> %6.2f", req.x, req.y, req.theta);
00359
00360 req_ = req;
00361 drawHumanPoseOnMap(req);
00362
00363 return true;
00364 }
00365
00366 int fillPolygonAndShow()
00367 {
00368 int w = 20;
00369 cv::Mat img = cv::Mat::zeros( w, w, CV_8UC3 );
00370 int lineType = 8;
00371
00373 cv::Point rook_points[1][4];
00374 rook_points[0][0] = cv::Point(w*0.5, 0.0);
00375 rook_points[0][1] = cv::Point(0, w);
00376 rook_points[0][2] = cv::Point(w*0.5, w*0.7);
00377 rook_points[0][3] = cv::Point(w, w);
00378
00379 const cv::Point* ppt[1] = { rook_points[0] };
00380 int npt[] = { 4 };
00381
00382 cv::fillPoly( img, ppt, npt, 1, GREEN, lineType );
00383
00384 cv::Point2f center(img.cols*0.5, img.rows*0.5);
00385
00386
00387 cv::imshow("test", img);
00388 int key = cv::waitKey();
00389
00390 if(key == 27 || key == 'q' || key == 'Q')
00391 return -1;
00392 }
00393
00394 int humanDrawAndShow()
00395 {
00396
00397 int w = 20;
00398 cv::Mat img = cv::Mat::zeros( w, w, CV_8UC3 );
00399 int lineType = 8;
00400
00402 cv::Point rook_points[1][4];
00403 rook_points[0][0] = cv::Point(w*0.5, 0.0);
00404 rook_points[0][1] = cv::Point(0, w);
00405 rook_points[0][2] = cv::Point(w*0.5, w*0.7);
00406 rook_points[0][3] = cv::Point(w, w);
00407
00408 const cv::Point* ppt[1] = { rook_points[0] };
00409 int npt[] = { 4 };
00410
00411 cv::fillPoly( img, ppt, npt, 1, GREEN, lineType );
00412
00413 cv::Point2f center(img.cols*0.5, img.rows*0.5);
00414
00415
00416 cv::imshow("test", img);
00417 int key = cv::waitKey();
00418
00419 if(key == 27 || key == 'q' || key == 'Q')
00420 return -1;
00421 }
00422
00423 int main(int argc, char **argv)
00424 {
00425
00426
00427
00428
00429
00430 ros::init(argc, argv, "remote_monitor_server");
00431
00432 if(argc < 3)
00433 {
00434 ROS_ERROR("Short of arguments. map package path and namespace must be given.");
00435 ROS_ERROR("Aborting remote_monitor_server...");
00436 return -1;
00437 }
00438
00439 std::string map_package_path = argv[1];
00440 std::string ns = argv[2];
00441 RemoteMonitorServer monitor_server(map_package_path, ns);
00442
00443 if(monitor_server.loadMapImage() == NG)
00444 {
00445 ROS_ERROR("Aborting remote_monitor_server...");
00446 return -1;
00447 }
00448
00449 monitor_server.runMainLoop();
00450
00451 return 0;
00452 }