cleaning_plan_alg_node.cpp
Go to the documentation of this file.
00001 #include "cleaning_plan_alg_node.h"
00002 
00003 using namespace std;
00004 using namespace cv;
00005 
00006 CleaningPlanAlgNode::CleaningPlanAlgNode(void) :
00007   algorithm_base::IriBaseAlgorithm<CleaningPlanAlgorithm>()
00008 {
00009         //init class attributes if necessary
00010         //this->loop_rate_ = 2;//in [Hz]
00011 
00012         // [init publishers]
00013         this->image_plan_out_publisher_ = this->public_node_handle_.advertise<sensor_msgs::Image>("image_plan_out", 1);
00014         this->visualization_markers_publisher_ = this->public_node_handle_.advertise<visualization_msgs::MarkerArray>("visualization_markers", 1);
00015         
00016         // [init subscribers]
00017         
00018         // [init services]
00019         this->representation_to_string_server_ = this->public_node_handle_.advertiseService("representation_to_string", &CleaningPlanAlgNode::representation_to_stringCallback, this);
00020         this->get_dirty_areas_state_representation_server_ = this->public_node_handle_.advertiseService("get_dirty_areas_state_representation", &CleaningPlanAlgNode::get_dirty_areas_state_representationCallback, this);
00021         this->get_trajectories_from_plan_server_ = this->public_node_handle_.advertiseService("get_trajectories_from_plan", &CleaningPlanAlgNode::get_trajectories_from_planCallback, this);
00022         
00023         // [init clients]
00024         
00025         // [init action servers]
00026         
00027         // [init action clients]
00028         
00029         // Other
00030         
00031 }
00032 
00033 CleaningPlanAlgNode::~CleaningPlanAlgNode(void)
00034 {
00035         // [free dynamic memory]
00036 }
00037 
00038 void CleaningPlanAlgNode::mainNodeThread(void)
00039 {
00040         // [fill msg structures]
00041         
00042         // [fill srv structure and make request to the server]
00043         
00044         // [fill action structure and make request to the action server]
00045 
00046         // [publish messages]
00047         
00048 }
00049 
00050 /*  [subscriber callbacks] */
00051 
00052 /*  [service callbacks] */
00053 bool CleaningPlanAlgNode::representation_to_stringCallback(estirabot_msgs::RepresentationToString::Request &req, estirabot_msgs::RepresentationToString::Response &res) 
00054 { 
00055         ROS_DEBUG("CleaningPlanAlgNode::representation_to_stringCallback: New Request Received!"); 
00056 
00057         //use appropiate mutex to shared variables if necessary 
00058         //this->alg_.lock(); 
00059         //this->representation_to_string_mutex_.enter(); 
00060 
00061     // TODO remove traversed_ellipses from request
00062         res.state_string = this->ellipses_representation.getStateString(req.dirty_areas);
00063         
00064         //unlock previously blocked shared variables 
00065         //this->alg_.unlock(); 
00066         //this->representation_to_string_mutex_.exit(); 
00067 
00068         return true; 
00069 }
00070 
00071 bool CleaningPlanAlgNode::get_dirty_areas_state_representationCallback(iri_clean_board::StateRepresentation::Request &req, iri_clean_board::StateRepresentation::Response &res) 
00072 { 
00073         ROS_INFO("CleaningPlanAlgNode::get_dirty_areas_state_representationCallback: New Request Received!"); 
00074         
00075         cv_bridge::CvImagePtr cv_ptr;
00076         
00077         try
00078         {
00079                 cv_ptr = cv_bridge::toCvCopy(req.image, sensor_msgs::image_encodings::TYPE_8UC1);
00080         }
00081         catch (cv_bridge::Exception& e)
00082         {
00083                 ROS_ERROR("cv_bridge exception: %s", e.what());
00084                 return false;
00085         }
00086         
00087         //use appropiate mutex to shared variables if necessary 
00088         this->alg_.lock(); 
00089         this->get_dirty_areas_state_representation_mutex_.enter(); 
00090         
00091         this->ellipses_representation.createNewState(cv_ptr->image);
00092         
00093         for( size_t i = 0; i < ellipses_representation.getEllipsesNumber(); i++ ) { // Debugging info
00094                 ROS_DEBUG_STREAM("ELIPSES: DATA");
00095                 ROS_DEBUG_STREAM("Center: " << ellipses_representation.getCurrentEllipses()[i].center << 
00096                                  " Size: " << ellipses_representation.getCurrentEllipses()[i].size.width << "," << ellipses_representation.getCurrentEllipses()[i].size.height);
00097                 ROS_DEBUG_STREAM("Angle: " << (ellipses_representation.getCurrentEllipses()[i].angle/180)*M_PI);
00098         }
00099         
00100         if (ellipses_representation.getEllipsesNumber() > 0) { // if there's something to clean
00101                 res.dirty_areas  = this->ellipses_representation.getRosDirtyAreas();
00102                 res.distances    = this->ellipses_representation.distancesBetweenEllipses(res.dirty_areas);
00103                 res.traversed_ellipses = this->ellipses_representation.getTraversedEllipses(res.dirty_areas);
00104                 res.state_string = this->ellipses_representation.getStateString(res.dirty_areas);
00105                 res.arm_position = this->ellipses_representation.getNearestEllipse();
00106                 res.is_clean     = false;
00107         }
00108         else {
00109                 res.state_string = "";
00110                 res.is_clean = true; // nothing to clean
00111         }
00112         
00113         this->ellipses_representation.writeStateToFile(this->file_planner_state, res.dirty_areas);
00114         
00115         //unlock previously blocked shared variables 
00116         this->alg_.unlock(); 
00117         this->get_dirty_areas_state_representation_mutex_.exit(); 
00118 
00119         return true; 
00120 }
00121 
00122 
00123 bool CleaningPlanAlgNode::get_trajectories_from_planCallback(iri_clean_board::PlanToTrajectories::Request &req, iri_clean_board::PlanToTrajectories::Response &res) 
00124 { 
00125         ROS_DEBUG("CleaningPlanAlgNode::get_trajectories_from_planCallback: New Request Received!"); 
00126         
00127         //use appropiate mutex to shared variables if necessary 
00128         //this->alg_.lock(); 
00129         //this->get_trajectories_from_plan_mutex_.enter(); 
00130         
00131         savePlanningResponse(req, res);
00132         
00133         if ( (res.poses.size()>0) && (this->image_plan_out_publisher_.getNumSubscribers()>0) ){ // Publish plan image
00134                 cv_bridge::CvImage cvbridge_aux;
00135                 cv::Mat image_bgr;
00136                 cvbridge_aux.encoding     = sensor_msgs::image_encodings::BGR8;
00137                 cvbridge_aux.image        = this->ellipses_representation.show_image;
00138                 cvbridge_aux.header.stamp = ros::Time::now();
00139                 
00140                 this->Image_msg_ = *cvbridge_aux.toImageMsg();
00141                 this->image_plan_out_publisher_.publish(this->Image_msg_);
00142         }
00143         
00144         //unlock previously blocked shared variables 
00145         //this->alg_.unlock(); 
00146         //this->get_trajectories_from_plan_mutex_.exit(); 
00147         
00148         return true; 
00149 }
00150 
00151 
00152 void CleaningPlanAlgNode::savePlanningResponse(iri_clean_board::PlanToTrajectories::Request req, 
00153                                                  iri_clean_board::PlanToTrajectories::Response &res)
00154 {
00155         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00156         bool is_real_movement;
00157         
00158         size_t i = 0; // max_actions = this->max_number_actions || max_actions = num_actions
00159         uint j = 0; // max movements = #ellipses  // movements don't include move(X)
00160         
00161         if (this->no_planning) {
00162                 getNearestCleanPlan(req, res);
00163                 return;
00164         }
00165         else if (this->no_perception) {
00166                 getNoPerceptionCleanPlan(req, res);
00167                 return;
00168         }
00169         
00170         pcl::fromROSMsg (req.pointcloud_in, *cloud);
00171     // debugging info
00172         show_dirty_areas_information(req.pointcloud_in, req.dirty_areas);
00173         
00174         ROS_INFO_STREAM("Got number of actions: " << req.actions.size());
00175         
00176         while ( (i < req.actions.size()) && 
00177                 (j < this->max_number_actions) && (j < req.dirty_areas.size() ) ) 
00178         {
00179                 // print executed action
00180                 std::stringstream ss;
00181                 for (size_t k = 0; k< req.target_ellipses[i].indexes.size(); ++k) { ss << req.target_ellipses[i].indexes[k] << ","; }
00182                 ROS_INFO_STREAM("Adding movement " << req.actions[i] << "(" << ss.str() << ")");
00183                 
00184                 is_real_movement= this->alg_.getMovementFromAction(req.dirty_areas, req.actions[i], 
00185                                                                    req.target_ellipses[i],
00186                                                                    this->ellipses_representation,
00187                                                                    cloud, req.plane_coefficients, 
00188                                                                    res.poses, res.poses_2d_coordinates, res.secondary_arm );
00189                 if (is_real_movement)
00190                         j++;
00191                 i++;
00192         }
00193         
00194         if (j == 0) { // something to clean but planner didn't return any movement
00195                 res.movement = false;
00196         }
00197         else { // something to clean and planner returned a plan
00198                 res.movement = true;
00199         }
00200 }
00201 
00202 
00203 void CleaningPlanAlgNode::show_dirty_areas_information(sensor_msgs::PointCloud2 pointcloud, std::vector< estirabot_msgs::DirtyArea > dirty_areas)
00204 {
00205     pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_cloud (new pcl::PointCloud<pcl::PointXYZ>);
00206     visualization_msgs::MarkerArray markers_msg;
00207     
00208     if(this->visualization_markers_publisher_.getNumSubscribers())
00209     {
00210         pcl::fromROSMsg (pointcloud, *pcl_cloud);
00211         
00212         for (size_t i = 0; i < dirty_areas.size(); i++) {
00213                 // marker
00214                 visualization_msgs::Marker marker;
00215                 marker.header.frame_id = pointcloud.header.frame_id; //"/camera_rgb_optical_frame";
00216                 marker.ns = "Dirty areas";
00217                 marker.id = i;
00218                 marker.header.stamp = ros::Time();
00219                 marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00220                 marker.action = visualization_msgs::Marker::ADD;
00221                 
00222                 pcl::PointXYZ point = pcl_cloud->at(dirty_areas[i].ellipse.center.x,dirty_areas[i].ellipse.center.y);
00223                 marker.pose.position.x = point.x;
00224                 marker.pose.position.y = point.y;
00225                 marker.pose.position.z = point.z - 0.05;
00226                 marker.pose.orientation.x = 0.0;
00227                 marker.pose.orientation.y = 0.0;
00228                 marker.pose.orientation.z = 0.0;
00229                 marker.pose.orientation.w = 1.0;
00230                 
00231                 // scale
00232                 marker.scale.x = 0.1;
00233                 marker.scale.y = 0.1;
00234                 marker.scale.z = 0.1;
00235                 // visible
00236                 marker.color.a = 1.0;
00237                 marker.color.r = 1.0;
00238                 marker.color.g = 0.0;
00239                 marker.color.b = 0.0;
00240                 
00241                 std::stringstream ss;
00242                 ss << 60 + dirty_areas[i].id;
00243                 marker.text=ss.str();
00244                 
00245                 // add to array
00246                 markers_msg.markers.push_back(marker);
00247         }
00248         
00249         // remove posible remaining markers
00250         for (size_t i = markers_msg.markers.size(); i < 10; i++) {
00251                 // marker
00252                 visualization_msgs::Marker marker;
00253                 marker.header.frame_id = pointcloud.header.frame_id; //"/camera_rgb_optical_frame";
00254                 marker.ns = "Dirty areas";
00255                 marker.id = i;
00256                 marker.header.stamp = ros::Time();
00257                 marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00258                 marker.action = visualization_msgs::Marker::ADD;
00259                 
00260                 marker.pose.position.x = 0.0;
00261                 marker.pose.position.y = 0.0;
00262                 marker.pose.position.z = (0.1 * i);
00263                 marker.pose.orientation.x = 0.0;
00264                 marker.pose.orientation.y = 0.0;
00265                 marker.pose.orientation.z = 0.0;
00266                 marker.pose.orientation.w = 1.0;
00267                 
00268                 // scale
00269                 marker.scale.x = 0.1;
00270                 marker.scale.y = 0.1;
00271                 marker.scale.z = 0.1;
00272                 // visible
00273                 marker.color.a = 0.0;
00274                 marker.color.r = 1.0;
00275                 marker.color.g = 0.0;
00276                 marker.color.b = 0.0;
00277                 
00278                 marker.text="as";
00279                 
00280                 markers_msg.markers.push_back(marker);
00281         }
00282         
00283         this->MarkerArray_msg_ = markers_msg;
00284     
00285     
00286         this->visualization_markers_publisher_.publish(this->MarkerArray_msg_);
00287     }
00288 }
00289 
00290 
00291 void CleaningPlanAlgNode::getNearestCleanPlan(iri_clean_board::PlanToTrajectories::Request req, 
00292                                                 iri_clean_board::PlanToTrajectories::Response &res)
00293 {
00294         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00295         
00296         pcl::fromROSMsg (req.pointcloud_in, *cloud);
00297         
00298 //      std::vector< size_t > plan = ellipses_representation.getGoodPathThroughAllEllipses(ellipses_representation.getNearestEllipse());
00299     std::vector< size_t > plan = ellipses_representation.getGoodPathThroughAllDirtyAreas(req.dirty_areas);
00300         std::vector< size_t >::iterator plan_it;
00301 
00302         for ( plan_it = plan.begin() ; plan_it < plan.end(); plan_it++ ) {
00303                 estirabot_msgs::ArrayIndexes target_ellipses;
00304                 std::string movement_type;
00305                 target_ellipses.indexes.push_back(*plan_it);
00306                 
00307                 if (this->board_plan) {
00308                         cv::RotatedRect ellipse = this->ellipses_representation.getCurrentEllipses()[*plan_it];
00309                         
00310                         movement_type = "smallClean";
00311                         if (1) { // use actions also
00312                                 if (ellipse.size.width > 50)
00313                                         movement_type = "circularClean";
00314                                 else if (ellipse.size.height > 50)
00315                                         movement_type = "straightClean";
00316                         }
00317                 }
00318                 else
00319                         movement_type = "pickUp";
00320                 
00321                 alg_.getMovementFromAction(req.dirty_areas, "pickUp", target_ellipses, 
00322                                         this->ellipses_representation,
00323                                         cloud, req.plane_coefficients, 
00324                                         res.poses, res.poses_2d_coordinates, res.secondary_arm );
00325         }
00326         
00327         res.movement = true;
00328 }
00329 
00330 void CleaningPlanAlgNode::getNoPerceptionCleanPlan(iri_clean_board::PlanToTrajectories::Request req, iri_clean_board::PlanToTrajectories::Response &res)
00331 {
00332         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00333         pcl::fromROSMsg (req.pointcloud_in, *cloud);
00334         
00335         ROS_INFO_STREAM("Creating trajectories without ellipses perception.");
00336         req.actions.clear();
00337         req.actions.push_back("NoPerception");
00338         this->alg_.getMovementFromAction(req.dirty_areas, req.actions[0], 
00339                                                                    req.target_ellipses[0],
00340                                                                    this->ellipses_representation,
00341                                                                    cloud, req.plane_coefficients, 
00342                                                                    res.poses, res.poses_2d_coordinates, res.secondary_arm );
00343         
00344         res.movement = true;
00345 }
00346 
00347 
00348 /*  [action callbacks] */
00349 
00350 /*  [action requests] */
00351 
00352 void CleaningPlanAlgNode::node_config_update(Config &config, uint32_t level)
00353 {
00354         this->alg_.lock();
00355         
00356         this->max_number_actions = config.max_number_actions;
00357         this->no_planning = config.no_planning;
00358         this->no_perception = config.no_perceptions;
00359         this->board_plan = config.board_plan;
00360         this->file_planner_state = config.file_planner_state;
00361         
00362         // update ellipses_representation config
00363         this->ellipses_representation.config_update(config, level);
00364         
00365         this->alg_.unlock();
00366 }
00367 
00368 void CleaningPlanAlgNode::addNodeDiagnostics(void)
00369 {
00370 }
00371 
00372 /* main function */
00373 int main(int argc,char *argv[])
00374 {
00375         return algorithm_base::main<CleaningPlanAlgNode>(argc, argv, "cleaning_plan_alg_node");
00376 }
00377 


iri_clean_board
Author(s): David Martinez
autogenerated on Fri Dec 6 2013 23:52:37