loop_closure.h
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2008, Willow Garage, Inc.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Willow Garage nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *********************************************************************/
00036 
00037 #ifndef EXPLORE_LOOP_CLOSURE_H
00038 #define EXPLORE_LOOP_CLOSURE_H
00039 
00040 
00041 /*
00042  * Implement the loop-closure exploration algorithm, from Stachniss, et
00043  * al., IROS 2004.
00044  */
00045 
00046 #include <tf/transform_datatypes.h>
00047 #include <actionlib/client/simple_action_client.h>
00048 #include <move_base_msgs/MoveBaseAction.h>
00049 #include <costmap_2d/costmap_2d_ros.h>
00050 #include <std_msgs/Float64.h>
00051 #include <navfn/navfn_ros.h>
00052 
00053 #include <ros/node_handle.h>
00054 
00055 #include <boost/thread/mutex.hpp>
00056 #include <boost/function.hpp>
00057 
00058 #include <visualization_msgs/MarkerArray.h>
00059 
00060 namespace explore
00061 {
00062 
00063 class GraphNode
00064 {
00065   public:
00066     GraphNode(int id, const tf::Pose& pose) : 
00067             id_(id), pose_(pose), next_(NULL), dijkstra_d_(0.0), slam_entropy_(0.0), path_length_(DBL_MAX) {}
00068 
00069     // id of this node in the graph
00070     int id_;
00071     // Pose of this node, in map coords
00072     tf::Pose pose_;
00073     // The node to which the robot went after this one, last time it was
00074     // here.
00075     GraphNode* next_;
00076     // Dijkstra distance
00077     double dijkstra_d_;
00078     // SLAM entropy last time we were here
00079     double slam_entropy_;
00080     //the last path distance computed for the node
00081     double path_length_;
00082 };
00083 
00084 class LoopClosure
00085 {
00086   public:
00087     LoopClosure(double addition_dist_min, 
00088                 double loop_dist_min, 
00089                 double loop_dist_max, 
00090                 double slam_entropy_max_,
00091                 double graph_update_frequency,
00092                 actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>& move_base_client,
00093                 costmap_2d::Costmap2DROS& costmap,
00094                 boost::mutex& control_mutex,
00095                 boost::function<void (void) > continuation_callback);
00096     ~LoopClosure();
00097 
00098     // Call this periodically to let loop closure update its graph.  It may
00099     // take control of the robot, and not return until it's done.
00100     // @param pose : current robot pose
00101     void updateGraph(const tf::Pose& pose);
00102 
00103 
00104   private:
00105     // Consider adding a node (if distance and visibility constraints are
00106     // satisfied)
00107     void addNode(const tf::Pose& pose);
00108     bool checkLoopClosure(const tf::Pose& pose, std::vector<GraphNode*>& candidates);
00109     void dijkstra(int source);
00110     void entropyCallback(const std_msgs::Float64::ConstPtr& entropy);
00111 
00112     void visualizeNode(const tf::Pose& pose, visualization_msgs::MarkerArray& markers);
00113     void visualizeEdge(const tf::Pose& pose1, const tf::Pose& pose2, visualization_msgs::MarkerArray& markers);
00114     void visualizeGraph();
00115 
00116     inline double distance(const geometry_msgs::PoseStamped& p1, const geometry_msgs::PoseStamped& p2){
00117       double x1 = p1.pose.position.x;
00118       double x2 = p2.pose.position.x;
00119       double y1 = p1.pose.position.y;
00120       double y2 = p2.pose.position.y;
00121       return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
00122     }
00123 
00124     inline int sign(int x){
00125       return x > 0 ? 1.0 : -1.0;
00126     }
00127 
00137     template <class ActionType>
00138       inline void raytraceLine(ActionType at, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int size_x, unsigned int max_length = UINT_MAX){
00139         int dx = x1 - x0;
00140         int dy = y1 - y0;
00141 
00142         unsigned int abs_dx = abs(dx);
00143         unsigned int abs_dy = abs(dy);
00144 
00145         int offset_dx = sign(dx);
00146         int offset_dy = sign(dy) * size_x;
00147 
00148         unsigned int offset = y0 * size_x + x0;
00149 
00150         //we need to chose how much to scale our dominant dimension, based on the maximum length of the line
00151         double dist = sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
00152         double scale = std::min(1.0,  max_length / dist);
00153 
00154         //if x is dominant
00155         if(abs_dx >= abs_dy){
00156           int error_y = abs_dx / 2;
00157           bresenham2D(at, abs_dx, abs_dy, error_y, offset_dx, offset_dy, offset, (unsigned int)(scale * abs_dx));
00158           return;
00159         }
00160 
00161         //otherwise y is dominant
00162         int error_x = abs_dy / 2;
00163         bresenham2D(at, abs_dy, abs_dx, error_x, offset_dy, offset_dx, offset, (unsigned int)(scale * abs_dy));
00164 
00165       }
00166 
00170     template <class ActionType>
00171       inline void bresenham2D(ActionType at, unsigned int abs_da, unsigned int abs_db, int error_b, int offset_a, int offset_b, 
00172           unsigned int offset, unsigned int max_length){
00173         unsigned int end = std::min(max_length, abs_da);
00174         for(unsigned int i = 0; i < end; ++i){
00175           at(offset);
00176           offset += offset_a;
00177           error_b += abs_db;
00178           if((unsigned int)error_b >= abs_da){
00179             offset += offset_b;
00180             error_b -= abs_da;
00181           }
00182         }
00183         at(offset);
00184       }
00185 
00186     class VisibilityChecker {
00187       public:
00188         VisibilityChecker(const unsigned char* costmap, bool& is_visible) : costmap_(costmap), is_visible_(is_visible) {}
00189         inline void operator()(unsigned int offset){
00190           unsigned char cost = costmap_[offset];
00191           if(cost >= costmap_2d::INSCRIBED_INFLATED_OBSTACLE){
00192             is_visible_ = false;
00193           }
00194         }
00195 
00196       public:
00197         const unsigned char* costmap_;
00198         bool& is_visible_;
00199     };
00200     
00201     //The node we're currently associated with
00202     GraphNode* curr_node_;
00203     // Travel distance required to drop a new node.
00204     double addition_dist_min_;
00205     // Minimum distance in map space to try loop closure
00206     double loop_dist_min_;
00207     // Maximum distance in graph space to try loop closure
00208     double loop_dist_max_;
00209     // Maximum slam entropy we'll tolerate before trying loop closure
00210     double slam_entropy_max_;
00211 
00212     //Freqeuncy at which to update the graph when actively closing a loop
00213     double graph_update_frequency_;
00214 
00215     // Action client for commanding move base
00216     actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>& move_base_client_;
00217     ros::NodeHandle nh_;
00218     // List of nodes.
00219     std::vector<GraphNode*> nodes_;
00220     // Adjacency list representation of graph
00221     std::vector<std::vector<int> > graph_;
00222 
00223     ros::Subscriber entropy_subscriber_;
00224     ros::Publisher marker_publisher_;
00225     int marker_id_;
00226     costmap_2d::Costmap2DROS& costmap_;
00227     // Mutex to lock when commanding the robot
00228     boost::mutex& control_mutex_;
00229     boost::function<void(void)> continuation_callback_;
00230     navfn::NavfnROS* planner_;
00231     double slam_entropy_;
00232 };
00233 
00234 }
00235 
00236 #endif


explore_hrl
Author(s): Travis Deyle
autogenerated on Wed Nov 27 2013 11:48:01